Use RAII objects to ensure proper destruction of expression and statement AST nodes in the parser in most cases, even on error.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60057 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 7006241..86e18bf 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/Parser.h"
#include "ExtensionRAIIObject.h"
+#include "AstGuard.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Parse/DeclSpec.h"
@@ -229,6 +230,7 @@
SkipUntil(tok::colon);
return true;
}
+ ExprGuard LHSGuard(Actions, LHS);
// GNU case range extension.
SourceLocation DotDotDotLoc;
@@ -244,6 +246,7 @@
}
RHSVal = RHS.Val;
}
+ ExprGuard RHSGuard(Actions, RHSVal);
if (Tok.isNot(tok::colon)) {
Diag(Tok, diag::err_expected_colon_after) << "'case'";
@@ -265,8 +268,8 @@
if (SubStmt.isInvalid)
SubStmt = Actions.ActOnNullStmt(ColonLoc);
- return Actions.ActOnCaseStmt(CaseLoc, LHS.Val, DotDotDotLoc, RHSVal, ColonLoc,
- SubStmt.Val);
+ return Actions.ActOnCaseStmt(CaseLoc, LHSGuard.take(), DotDotDotLoc,
+ RHSGuard.take(), ColonLoc, SubStmt.Val);
}
/// ParseDefaultStatement
@@ -351,8 +354,9 @@
// TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are
// only allowed at the start of a compound stmt regardless of the language.
-
- llvm::SmallVector<StmtTy*, 32> Stmts;
+
+ typedef StmtVector StmtsTy;
+ StmtsTy Stmts(Actions);
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
StmtResult R;
if (Tok.isNot(tok::kw___extension__)) {
@@ -410,7 +414,7 @@
SourceLocation RBraceLoc = ConsumeBrace();
return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc,
- &Stmts[0], Stmts.size(), isStmtExpr);
+ Stmts.take(), Stmts.size(), isStmtExpr);
}
/// ParseIfStatement
@@ -456,6 +460,7 @@
} else {
CondExp = ParseSimpleParenExpression();
}
+ ExprGuard CondGuard(Actions, CondExp);
if (CondExp.isInvalid) {
SkipUntil(tok::semi);
@@ -528,9 +533,7 @@
if ((ThenStmt.isInvalid && ElseStmt.isInvalid) ||
(ThenStmt.isInvalid && ElseStmt.Val == 0) ||
(ThenStmt.Val == 0 && ElseStmt.isInvalid)) {
- // Both invalid, or one is invalid and other is non-present: delete cond and
- // return error.
- Actions.DeleteExpr(CondExp.Val);
+ // Both invalid, or one is invalid and other is non-present: return error.
return true;
}
@@ -540,7 +543,7 @@
if (ElseStmt.isInvalid)
ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
- return Actions.ActOnIfStmt(IfLoc, CondExp.Val, ThenStmt.Val,
+ return Actions.ActOnIfStmt(IfLoc, CondGuard.take(), ThenStmt.Val,
ElseLoc, ElseStmt.Val);
}
@@ -668,6 +671,7 @@
} else {
Cond = ParseSimpleParenExpression();
}
+ ExprGuard CondGuard(Actions, Cond);
// C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
// there is no compound stmt. C90 does not have this clause. We only do this
@@ -685,6 +689,7 @@
// Read the body statement.
StmtResult Body = ParseStatement();
+ StmtGuard BodyGuard(Actions, Body);
// Pop the body scope if needed.
if (NeedsInnerScope) ExitScope();
@@ -693,7 +698,7 @@
if (Cond.isInvalid || Body.isInvalid) return true;
- return Actions.ActOnWhileStmt(WhileLoc, Cond.Val, Body.Val);
+ return Actions.ActOnWhileStmt(WhileLoc, CondGuard.take(), BodyGuard.take());
}
/// ParseDoStatement
@@ -725,6 +730,7 @@
// Read the body statement.
StmtResult Body = ParseStatement();
+ StmtGuard BodyGuard(Actions, Body);
// Pop the body scope if needed.
if (NeedsInnerScope) ExitScope();
@@ -749,12 +755,14 @@
// Parse the condition.
ExprResult Cond = ParseSimpleParenExpression();
+ ExprGuard CondGuard(Actions, Cond);
ExitScope();
if (Cond.isInvalid || Body.isInvalid) return true;
- return Actions.ActOnDoStmt(DoLoc, Body.Val, WhileLoc, Cond.Val);
+ return Actions.ActOnDoStmt(DoLoc, BodyGuard.take(),
+ WhileLoc, CondGuard.take());
}
/// ParseForStatement
@@ -810,6 +818,8 @@
ExprTy *SecondPart = 0;
StmtTy *ThirdPart = 0;
bool ForEach = false;
+ StmtGuard FirstGuard(Actions), ThirdGuard(Actions);
+ ExprGuard SecondGuard(Actions);
// Parse the first part of the for specifier.
if (Tok.is(tok::semi)) { // for (;
@@ -856,7 +866,10 @@
SkipUntil(tok::semi);
}
}
+ FirstGuard.reset(FirstPart);
+ SecondGuard.reset(SecondPart);
if (!ForEach) {
+ assert(!SecondGuard.get() && "Shouldn't have a second expression yet.");
// Parse the second part of the for specifier.
if (Tok.is(tok::semi)) { // for (...;;
// no second part.
@@ -888,6 +901,8 @@
ThirdPart = R.Val;
}
}
+ SecondGuard.reset(SecondPart);
+ ThirdGuard.reset(ThirdPart);
}
// Match the ')'.
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
@@ -918,6 +933,10 @@
if (Body.isInvalid)
return Body;
+ // Release all the guards.
+ FirstGuard.take();
+ SecondGuard.take();
+ ThirdGuard.take();
if (!ForEach)
return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart,
SecondPart, ThirdPart, RParenLoc, Body.Val);
@@ -1082,11 +1101,12 @@
ExprResult AsmString = ParseAsmStringLiteral();
if (AsmString.isInvalid)
return true;
+ ExprGuard AsmGuard(Actions, AsmString);
llvm::SmallVector<std::string, 4> Names;
- llvm::SmallVector<ExprTy*, 4> Constraints;
- llvm::SmallVector<ExprTy*, 4> Exprs;
- llvm::SmallVector<ExprTy*, 4> Clobbers;
+ ExprVector Constraints(Actions);
+ ExprVector Exprs(Actions);
+ ExprVector Clobbers(Actions);
unsigned NumInputs = 0, NumOutputs = 0;
@@ -1097,7 +1117,7 @@
RParenLoc = ConsumeParen();
} else {
- // Parse Outputs, if present.
+ // Parse Outputs, if present.
if (ParseAsmOperandsOpt(Names, Constraints, Exprs))
return true;
@@ -1136,9 +1156,9 @@
return Actions.ActOnAsmStmt(AsmLoc, isSimple, isVolatile,
NumOutputs, NumInputs,
- &Names[0], &Constraints[0], &Exprs[0],
- AsmString.Val,
- Clobbers.size(), &Clobbers[0],
+ &Names[0], Constraints.take(),
+ Exprs.take(), AsmGuard.take(),
+ Clobbers.size(), Clobbers.take(),
RParenLoc);
}