[cfe-commits] r72035 - in /cfe/trunk: include/clang/AST/StmtCXX.h lib/AST/Stmt.cpp lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp lib/Sema/SemaTemplateInstantiateStmt.cpp test/SemaTemplate/instantiate-function-1.cpp
Douglas Gregor
dgregor at apple.com
Mon May 18 13:52:32 PDT 2009
Author: dgregor
Date: Mon May 18 15:51:54 2009
New Revision: 72035
URL: http://llvm.org/viewvc/llvm-project?rev=72035&view=rev
Log:
Template instantiation for C++ try/catch statements.
Modified:
cfe/trunk/include/clang/AST/StmtCXX.h
cfe/trunk/lib/AST/Stmt.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp
cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp
Modified: cfe/trunk/include/clang/AST/StmtCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtCXX.h?rev=72035&r1=72034&r2=72035&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/StmtCXX.h (original)
+++ cfe/trunk/include/clang/AST/StmtCXX.h Mon May 18 15:51:54 2009
@@ -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 @@
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 @@
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]);
Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=72035&r1=72034&r2=72035&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Mon May 18 15:51:54 2009
@@ -564,7 +564,7 @@
QualType CXXCatchStmt::getCaughtType() {
if (ExceptionDecl)
- return llvm::cast<VarDecl>(ExceptionDecl)->getType();
+ return ExceptionDecl->getType();
return QualType();
}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=72035&r1=72034&r2=72035&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon May 18 15:51:54 2009
@@ -1244,7 +1244,12 @@
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);
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=72035&r1=72034&r2=72035&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon May 18 15:51:54 2009
@@ -2534,13 +2534,14 @@
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 @@
// 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 @@
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 @@
}
}
- 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);
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=72035&r1=72034&r2=72035&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon May 18 15:51:54 2009
@@ -130,6 +130,8 @@
else
SemaRef.AddInitializerToDecl(Sema::DeclPtrTy::make(Var), move(Init),
D->hasCXXDirectInitializer());
+ } else {
+ // FIXME: Call ActOnUninitializedDecl? (Not always)
}
return Var;
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp?rev=72035&r1=72034&r2=72035&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateStmt.cpp Mon May 18 15:51:54 2009
@@ -320,16 +320,69 @@
//===----------------------------------------------------------------------===/
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>()));
}
//===----------------------------------------------------------------------===/
Modified: cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp?rev=72035&r1=72034&r2=72035&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp (original)
+++ cfe/trunk/test/SemaTemplate/instantiate-function-1.cpp Mon May 18 15:51:54 2009
@@ -50,7 +50,7 @@
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 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}}
More information about the cfe-commits
mailing list