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()));
}