Introduce a new kind of RAII class, ASTOwningVector, which is an
llvm::SmallVector that owns all of the AST nodes inside of it. This
RAII class is used to ensure proper destruction of AST nodes when
template instantiation fails.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72186 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplateInstantiateStmt.cpp b/lib/Sema/SemaTemplateInstantiateStmt.cpp
index c136d25..e83718e 100644
--- a/lib/Sema/SemaTemplateInstantiateStmt.cpp
+++ b/lib/Sema/SemaTemplateInstantiateStmt.cpp
@@ -136,29 +136,22 @@
 
 Sema::OwningStmtResult 
 TemplateStmtInstantiator::VisitCompoundStmt(CompoundStmt *S) {
-  // FIXME: We need an *easy* RAII way to delete these statements if something
-  // goes wrong.
-  llvm::SmallVector<Stmt *, 16> Statements;
+  ASTOwningVector<&ActionBase::DeleteStmt> Statements(SemaRef);
   
   for (CompoundStmt::body_iterator B = S->body_begin(), BEnd = S->body_end();
        B != BEnd; ++B) {
     OwningStmtResult Result = Visit(*B);
-    if (Result.isInvalid()) {
-      // FIXME: This should be handled by an RAII destructor.
-      for (unsigned I = 0, N = Statements.size(); I != N; ++I)
-        Statements[I]->Destroy(SemaRef.Context);
+    if (Result.isInvalid())
       return SemaRef.StmtError();
-    }
 
     Statements.push_back(Result.takeAs<Stmt>());
   }
 
-  return SemaRef.Owned(
-           new (SemaRef.Context) CompoundStmt(SemaRef.Context,
-                                              &Statements[0], 
-                                              Statements.size(),
-                                              S->getLBracLoc(),
-                                              S->getRBracLoc()));
+  return SemaRef.ActOnCompoundStmt(S->getLBracLoc(), S->getRBracLoc(),
+                                   Sema::MultiStmtArg(SemaRef,
+                                                      Statements.take(),
+                                                      Statements.size()),
+                                   /*isStmtExpr=*/false);
 }
 
 Sema::OwningStmtResult 
@@ -326,22 +319,18 @@
     return SemaRef.StmtError();
 
   // Instantiate the handlers.
-  llvm::SmallVector<Stmt *, 4> Handlers;
+  ASTOwningVector<&ActionBase::DeleteStmt> Handlers(SemaRef);
   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);
+    if (Handler.isInvalid())
       return SemaRef.StmtError();
-    }
 
     Handlers.push_back(Handler.takeAs<Stmt>());
   }
 
   return SemaRef.ActOnCXXTryBlock(S->getTryLoc(), move(TryBlock),
                                   Sema::MultiStmtArg(SemaRef,
-                                                     (void**)&Handlers.front(),
+                                                     Handlers.take(),
                                                      Handlers.size()));
 }