Template instantiation for C++ try/catch statements.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72035 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateStmt.cpp b/lib/Sema/SemaTemplateInstantiateStmt.cpp
index a8dd6c1..c136d25 100644
--- a/lib/Sema/SemaTemplateInstantiateStmt.cpp
+++ b/lib/Sema/SemaTemplateInstantiateStmt.cpp
@@ -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>()));
}
//===----------------------------------------------------------------------===/