forked from OSchip/llvm-project
Template instantiation for C++ try/catch statements.
llvm-svn: 72035
This commit is contained in:
parent
9b02760923
commit
5e16fbe562
|
@ -18,17 +18,19 @@
|
|||
|
||||
namespace clang {
|
||||
|
||||
class VarDecl;
|
||||
|
||||
/// CXXCatchStmt - This represents a C++ catch block.
|
||||
///
|
||||
class CXXCatchStmt : public Stmt {
|
||||
SourceLocation CatchLoc;
|
||||
/// The exception-declaration of the type.
|
||||
Decl *ExceptionDecl;
|
||||
VarDecl *ExceptionDecl;
|
||||
/// The handler block.
|
||||
Stmt *HandlerBlock;
|
||||
|
||||
public:
|
||||
CXXCatchStmt(SourceLocation catchLoc, Decl *exDecl, Stmt *handlerBlock)
|
||||
CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock)
|
||||
: Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
|
||||
HandlerBlock(handlerBlock) {}
|
||||
|
||||
|
@ -38,7 +40,8 @@ public:
|
|||
return SourceRange(CatchLoc, HandlerBlock->getLocEnd());
|
||||
}
|
||||
|
||||
Decl *getExceptionDecl() { return ExceptionDecl; }
|
||||
SourceLocation getCatchLoc() const { return CatchLoc; }
|
||||
VarDecl *getExceptionDecl() { return ExceptionDecl; }
|
||||
QualType getCaughtType();
|
||||
Stmt *getHandlerBlock() { return HandlerBlock; }
|
||||
|
||||
|
@ -67,6 +70,8 @@ public:
|
|||
return SourceRange(TryLoc, Stmts.back()->getLocEnd());
|
||||
}
|
||||
|
||||
SourceLocation getTryLoc() const { return TryLoc; }
|
||||
|
||||
CompoundStmt *getTryBlock() { return llvm::cast<CompoundStmt>(Stmts[0]); }
|
||||
const CompoundStmt *getTryBlock() const {
|
||||
return llvm::cast<CompoundStmt>(Stmts[0]);
|
||||
|
|
|
@ -564,7 +564,7 @@ Stmt::child_iterator CXXCatchStmt::child_end() {
|
|||
|
||||
QualType CXXCatchStmt::getCaughtType() {
|
||||
if (ExceptionDecl)
|
||||
return llvm::cast<VarDecl>(ExceptionDecl)->getType();
|
||||
return ExceptionDecl->getType();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
|
|
|
@ -1244,7 +1244,12 @@ public:
|
|||
ExprArg SynchExpr,
|
||||
StmtArg SynchBody);
|
||||
|
||||
VarDecl *BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
|
||||
IdentifierInfo *Name,
|
||||
SourceLocation Loc,
|
||||
SourceRange Range);
|
||||
virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D);
|
||||
|
||||
virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
|
||||
DeclPtrTy ExDecl,
|
||||
StmtArg HandlerBlock);
|
||||
|
|
|
@ -2534,13 +2534,14 @@ Sema::DeclPtrTy Sema::ActOnFinishLinkageSpecification(Scope *S,
|
|||
return LinkageSpec;
|
||||
}
|
||||
|
||||
/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
|
||||
/// handler.
|
||||
Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
|
||||
QualType ExDeclType = GetTypeForDeclarator(D, S);
|
||||
SourceLocation Begin = D.getDeclSpec().getSourceRange().getBegin();
|
||||
|
||||
bool Invalid = D.isInvalidType();
|
||||
/// \brief Perform semantic analysis for the variable declaration that
|
||||
/// occurs within a C++ catch clause, returning the newly-created
|
||||
/// variable.
|
||||
VarDecl *Sema::BuildExceptionDeclaration(Scope *S, QualType ExDeclType,
|
||||
IdentifierInfo *Name,
|
||||
SourceLocation Loc,
|
||||
SourceRange Range) {
|
||||
bool Invalid = false;
|
||||
|
||||
// Arrays and functions decay.
|
||||
if (ExDeclType->isArrayType())
|
||||
|
@ -2553,9 +2554,10 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
|
|||
// incomplete type, other than [cv] void*.
|
||||
// N2844 forbids rvalue references.
|
||||
if(ExDeclType->isRValueReferenceType()) {
|
||||
Diag(Begin, diag::err_catch_rvalue_ref) << D.getSourceRange();
|
||||
Diag(Loc, diag::err_catch_rvalue_ref) << Range;
|
||||
Invalid = true;
|
||||
}
|
||||
|
||||
QualType BaseType = ExDeclType;
|
||||
int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference
|
||||
unsigned DK = diag::err_catch_incomplete;
|
||||
|
@ -2570,18 +2572,36 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
|
|||
DK = diag::err_catch_incomplete_ref;
|
||||
}
|
||||
if (!Invalid && (Mode == 0 || !BaseType->isVoidType()) &&
|
||||
RequireCompleteType(Begin, BaseType, DK))
|
||||
!BaseType->isDependentType() && RequireCompleteType(Loc, BaseType, DK))
|
||||
Invalid = true;
|
||||
|
||||
if (!Invalid && RequireNonAbstractType(Begin, ExDeclType,
|
||||
diag::err_abstract_type_in_decl,
|
||||
AbstractVariableType))
|
||||
if (!Invalid && !ExDeclType->isDependentType() &&
|
||||
RequireNonAbstractType(Loc, ExDeclType,
|
||||
diag::err_abstract_type_in_decl,
|
||||
AbstractVariableType))
|
||||
Invalid = true;
|
||||
|
||||
// FIXME: Need to test for ability to copy-construct and destroy the exception
|
||||
// variable.
|
||||
// FIXME: Need to test for ability to copy-construct and destroy the
|
||||
// exception variable.
|
||||
|
||||
// FIXME: Need to check for abstract classes.
|
||||
|
||||
VarDecl *ExDecl = VarDecl::Create(Context, CurContext, Loc,
|
||||
Name, ExDeclType, VarDecl::None,
|
||||
Range.getBegin());
|
||||
|
||||
if (Invalid)
|
||||
ExDecl->setInvalidDecl();
|
||||
|
||||
return ExDecl;
|
||||
}
|
||||
|
||||
/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
|
||||
/// handler.
|
||||
Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
|
||||
QualType ExDeclType = GetTypeForDeclarator(D, S);
|
||||
|
||||
bool Invalid = D.isInvalidType();
|
||||
IdentifierInfo *II = D.getIdentifier();
|
||||
if (NamedDecl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) {
|
||||
// The scope should be freshly made just for us. There is just no way
|
||||
|
@ -2593,21 +2613,25 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) {
|
|||
}
|
||||
}
|
||||
|
||||
VarDecl *ExDecl = VarDecl::Create(Context, CurContext, D.getIdentifierLoc(),
|
||||
II, ExDeclType, VarDecl::None, Begin);
|
||||
if (D.getCXXScopeSpec().isSet() && !Invalid) {
|
||||
Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator)
|
||||
<< D.getCXXScopeSpec().getRange();
|
||||
Invalid = true;
|
||||
}
|
||||
|
||||
VarDecl *ExDecl = BuildExceptionDeclaration(S, ExDeclType,
|
||||
D.getIdentifier(),
|
||||
D.getIdentifierLoc(),
|
||||
D.getDeclSpec().getSourceRange());
|
||||
|
||||
if (Invalid)
|
||||
ExDecl->setInvalidDecl();
|
||||
|
||||
// Add the exception declaration into this scope.
|
||||
S->AddDecl(DeclPtrTy::make(ExDecl));
|
||||
if (II)
|
||||
IdResolver.AddDecl(ExDecl);
|
||||
PushOnScopeChains(ExDecl, S);
|
||||
else
|
||||
CurContext->addDecl(Context, ExDecl);
|
||||
|
||||
ProcessDeclAttributes(ExDecl, D);
|
||||
return DeclPtrTy::make(ExDecl);
|
||||
|
|
|
@ -130,6 +130,8 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
|
|||
else
|
||||
SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), move(Init),
|
||||
D->hasCXXDirectInitializer());
|
||||
} else {
|
||||
// FIXME: Call ActOnUninitializedDecl? (Not always)
|
||||
}
|
||||
|
||||
return Var;
|
||||
|
|
|
@ -320,16 +320,69 @@ TemplateStmtInstantiator::VisitAsmStmt(AsmStmt *S) {
|
|||
//===----------------------------------------------------------------------===/
|
||||
Sema::OwningStmtResult
|
||||
TemplateStmtInstantiator::VisitCXXTryStmt(CXXTryStmt *S) {
|
||||
// FIXME: Implement this
|
||||
assert(false && "Cannot instantiate a C++ try statement");
|
||||
return SemaRef.StmtError();
|
||||
// Instantiate the try block itself.
|
||||
OwningStmtResult TryBlock = VisitCompoundStmt(S->getTryBlock());
|
||||
if (TryBlock.isInvalid())
|
||||
return SemaRef.StmtError();
|
||||
|
||||
// Instantiate the handlers.
|
||||
llvm::SmallVector<Stmt *, 4> Handlers;
|
||||
for (unsigned I = 0, N = S->getNumHandlers(); I != N; ++I) {
|
||||
OwningStmtResult Handler = VisitCXXCatchStmt(S->getHandler(I));
|
||||
if (Handler.isInvalid()) {
|
||||
// Destroy all of the previous handlers.
|
||||
for (unsigned Victim = 0; Victim != I; ++Victim)
|
||||
Handlers[Victim]->Destroy(SemaRef.Context);
|
||||
return SemaRef.StmtError();
|
||||
}
|
||||
|
||||
Handlers.push_back(Handler.takeAs<Stmt>());
|
||||
}
|
||||
|
||||
return SemaRef.ActOnCXXTryBlock(S->getTryLoc(), move(TryBlock),
|
||||
Sema::MultiStmtArg(SemaRef,
|
||||
(void**)&Handlers.front(),
|
||||
Handlers.size()));
|
||||
}
|
||||
|
||||
Sema::OwningStmtResult
|
||||
TemplateStmtInstantiator::VisitCXXCatchStmt(CXXCatchStmt *S) {
|
||||
// FIXME: Implement this
|
||||
assert(false && "Cannot instantiate a C++ catch statement");
|
||||
return SemaRef.StmtError();
|
||||
// Instantiate the exception declaration, if any.
|
||||
VarDecl *Var = 0;
|
||||
if (S->getExceptionDecl()) {
|
||||
VarDecl *ExceptionDecl = S->getExceptionDecl();
|
||||
QualType T = SemaRef.InstantiateType(ExceptionDecl->getType(),
|
||||
TemplateArgs,
|
||||
ExceptionDecl->getLocation(),
|
||||
ExceptionDecl->getDeclName());
|
||||
if (T.isNull())
|
||||
return SemaRef.StmtError();
|
||||
|
||||
Var = SemaRef.BuildExceptionDeclaration(0, T,
|
||||
ExceptionDecl->getIdentifier(),
|
||||
ExceptionDecl->getLocation(),
|
||||
/*FIXME: Inaccurate*/
|
||||
SourceRange(ExceptionDecl->getLocation()));
|
||||
if (Var->isInvalidDecl()) {
|
||||
Var->Destroy(SemaRef.Context);
|
||||
return SemaRef.StmtError();
|
||||
}
|
||||
|
||||
// Introduce the exception declaration into scope.
|
||||
SemaRef.CurrentInstantiationScope->InstantiatedLocal(ExceptionDecl, Var);
|
||||
}
|
||||
|
||||
// Instantiate the actual exception handler.
|
||||
OwningStmtResult Handler = Visit(S->getHandlerBlock());
|
||||
if (Handler.isInvalid()) {
|
||||
if (Var)
|
||||
Var->Destroy(SemaRef.Context);
|
||||
return SemaRef.StmtError();
|
||||
}
|
||||
|
||||
return SemaRef.Owned(new (SemaRef.Context) CXXCatchStmt(S->getCatchLoc(),
|
||||
Var,
|
||||
Handler.takeAs<Stmt>()));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===/
|
||||
|
|
|
@ -50,7 +50,7 @@ template <typename T> struct X4 {
|
|||
template struct X4<void>; // expected-note{{in instantiation of}}
|
||||
template struct X4<int>; // expected-note{{in instantiation of}}
|
||||
|
||||
struct Incomplete; // expected-note{{forward declaration}}
|
||||
struct Incomplete; // expected-note 2{{forward declaration}}
|
||||
|
||||
template<typename T> struct X5 {
|
||||
T f() { } // expected-error{{incomplete result type}}
|
||||
|
@ -180,3 +180,21 @@ template<typename T> struct IndirectGoto0 {
|
|||
|
||||
template struct IndirectGoto0<void*>;
|
||||
template struct IndirectGoto0<int>; // expected-note{{instantiation}}
|
||||
|
||||
template<typename T> struct TryCatch0 {
|
||||
void f() {
|
||||
try {
|
||||
} catch (T t) { // expected-error{{incomplete type}} \
|
||||
// expected-error{{abstract class}}
|
||||
} catch (...) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct Abstract {
|
||||
virtual void foo() = 0; // expected-note{{pure virtual}}
|
||||
};
|
||||
|
||||
template struct TryCatch0<int>; // okay
|
||||
template struct TryCatch0<Incomplete*>; // expected-note{{instantiation}}
|
||||
template struct TryCatch0<Abstract>; // expected-note{{instantiation}}
|
||||
|
|
Loading…
Reference in New Issue