diff options
| -rw-r--r-- | clang/include/clang/AST/StmtCXX.h | 11 | ||||
| -rw-r--r-- | clang/lib/AST/Stmt.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 5 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 60 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateStmt.cpp | 65 | ||||
| -rw-r--r-- | clang/test/SemaTemplate/instantiate-function-1.cpp | 20 | 
7 files changed, 136 insertions, 29 deletions
| diff --git a/clang/include/clang/AST/StmtCXX.h b/clang/include/clang/AST/StmtCXX.h index ce1cf6622cd..2338f1457a8 100644 --- a/clang/include/clang/AST/StmtCXX.h +++ b/clang/include/clang/AST/StmtCXX.h @@ -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]); diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 71103b83e3c..b2fadb1834f 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -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();  } diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index de3944a75b6..9b953a80024 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -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); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 9a74b53da95..d968bc6b75a 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -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); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index c08841abaa0..385112b7d77 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -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; diff --git a/clang/lib/Sema/SemaTemplateInstantiateStmt.cpp b/clang/lib/Sema/SemaTemplateInstantiateStmt.cpp index a8dd6c194c5..c136d254478 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateStmt.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateStmt.cpp @@ -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>()));  }  //===----------------------------------------------------------------------===/ diff --git a/clang/test/SemaTemplate/instantiate-function-1.cpp b/clang/test/SemaTemplate/instantiate-function-1.cpp index d30055c9a1e..caae97e60bb 100644 --- a/clang/test/SemaTemplate/instantiate-function-1.cpp +++ b/clang/test/SemaTemplate/instantiate-function-1.cpp @@ -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}} | 

