diff options
| author | Douglas Gregor <dgregor@apple.com> | 2009-05-18 20:51:54 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2009-05-18 20:51:54 +0000 |
| commit | 5e16fbe5621804a06a60b886b6f95e018751e92d (patch) | |
| tree | 597c619d11e98bdce21d930caa9e2b1ba35ba53d /clang/lib/Sema | |
| parent | 9b0276092336641907aebf4f8b7874314695632b (diff) | |
| download | bcm5719-llvm-5e16fbe5621804a06a60b886b6f95e018751e92d.tar.gz bcm5719-llvm-5e16fbe5621804a06a60b886b6f95e018751e92d.zip | |
Template instantiation for C++ try/catch statements.
llvm-svn: 72035
Diffstat (limited to 'clang/lib/Sema')
| -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 |
4 files changed, 108 insertions, 24 deletions
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>())); } //===----------------------------------------------------------------------===/ |

