[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