aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2008-11-25 22:21:31 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2008-11-25 22:21:31 +0000
commita55e52c0802cae3b7c366a05c461d3d15074c1a3 (patch)
treefca8cd5d7a9b355502c69fea49e50e69a7ddd379
parent71fcec9abf2ce66d5e17a24bd021680e94e42f0d (diff)
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
-rw-r--r--include/clang/Parse/Parser.h5
-rw-r--r--lib/Parse/AstGuard.h106
-rw-r--r--lib/Parse/ParseDecl.cpp18
-rw-r--r--lib/Parse/ParseDeclCXX.cpp13
-rw-r--r--lib/Parse/ParseExpr.cpp80
-rw-r--r--lib/Parse/ParseExprCXX.cpp13
-rw-r--r--lib/Parse/ParseInit.cpp16
-rw-r--r--lib/Parse/ParseObjc.cpp43
-rw-r--r--lib/Parse/ParsePragma.cpp7
-rw-r--r--lib/Parse/ParseStmt.cpp56
10 files changed, 256 insertions, 101 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 47b1191818..bfb198eea1 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -445,8 +445,9 @@ private:
ExprResult ParseSizeofAlignofExpression();
ExprResult ParseBuiltinPrimaryExpression();
- typedef llvm::SmallVector<ExprTy*, 8> ExprListTy;
- typedef llvm::SmallVector<SourceLocation, 8> CommaLocsTy;
+ static const unsigned ExprListSize = 12;
+ typedef llvm::SmallVector<ExprTy*, ExprListSize> ExprListTy;
+ typedef llvm::SmallVector<SourceLocation, ExprListSize> CommaLocsTy;
/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
bool ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs);
diff --git a/lib/Parse/AstGuard.h b/lib/Parse/AstGuard.h
new file mode 100644
index 0000000000..434c72c554
--- /dev/null
+++ b/lib/Parse/AstGuard.h
@@ -0,0 +1,106 @@
+//===--- AstGuard.h - Parser Ownership Tracking Utilities -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines RAII objects for managing ExprTy* and StmtTy*.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_PARSE_ASTGUARD_H
+#define LLVM_CLANG_PARSE_ASTGUARD_H
+
+#include "clang/Parse/Action.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace clang
+{
+ /// RAII guard for freeing StmtTys and ExprTys on early exit in the parser.
+ /// Instantiated for statements and expressions (Action::DeleteStmt and
+ /// Action::DeleteExpr).
+ template <void (Action::*Destroyer)(void*)>
+ class ASTGuard {
+ Action &Actions;
+ void *Node;
+
+ void destroy() {
+ if (Node)
+ (Actions.*Destroyer)(Node);
+ }
+
+ ASTGuard(const ASTGuard&); // DO NOT IMPLEMENT
+ // Reference member prevents copy assignment.
+
+ public:
+ explicit ASTGuard(Action &actions) : Actions(actions), Node(0) {}
+ ASTGuard(Action &actions, void *node)
+ : Actions(actions), Node(node) {}
+ template <unsigned N>
+ ASTGuard(Action &actions, const Action::ActionResult<N> &res)
+ : Actions(actions), Node(res.Val) {}
+ ~ASTGuard() { destroy(); }
+
+ void reset(void *element) {
+ destroy();
+ Node = element;
+ }
+ template <unsigned N>
+ void reset(const Action::ActionResult<N> &res) {
+ reset(res.Val);
+ }
+ void *take() {
+ void *Temp = Node;
+ Node = 0;
+ return Temp;
+ }
+ void *get() const { return Node; }
+ };
+
+ typedef ASTGuard<&Action::DeleteStmt> StmtGuard;
+ typedef ASTGuard<&Action::DeleteExpr> ExprGuard;
+
+ /// RAII SmallVector wrapper that holds Action::ExprTy* and similar,
+ /// automatically freeing them on destruction unless it's been disowned.
+ /// Instantiated for statements and expressions (Action::DeleteStmt and
+ /// Action::DeleteExpr).
+ template <void (Action::*Destroyer)(void*), unsigned N>
+ class ASTVector : public llvm::SmallVector<void*, N> {
+ private:
+ Action &Actions;
+ bool Owns;
+
+ void destroy() {
+ if (Owns) {
+ while (!this->empty()) {
+ (Actions.*Destroyer)(this->back());
+ this->pop_back();
+ }
+ }
+ }
+
+ ASTVector(const ASTVector&); // DO NOT IMPLEMENT
+ // Reference member prevents copy assignment.
+
+ public:
+ ASTVector(Action &actions) : Actions(actions), Owns(true) {}
+
+ ~ASTVector() { destroy(); }
+
+ void **take() {
+ Owns = false;
+ return &(*this)[0];
+ }
+ };
+
+ /// A SmallVector of statements, with stack size 32 (as that is the only one
+ /// used.)
+ typedef ASTVector<&Action::DeleteStmt, 32> StmtVector;
+ /// A SmallVector of expressions, with stack size 12 (the maximum used.)
+ typedef ASTVector<&Action::DeleteExpr, 12> ExprVector;
+}
+
+#endif
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index eaf9f8b0f9..d8894c66fa 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -15,6 +15,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Parse/Scope.h"
#include "ExtensionRAIIObject.h"
+#include "AstGuard.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
@@ -122,7 +123,7 @@ AttributeList *Parser::ParseAttributes() {
} else if (Tok.is(tok::comma)) {
ConsumeToken();
// __attribute__(( format(printf, 1, 2) ))
- llvm::SmallVector<ExprTy*, 8> ArgExprs;
+ ExprVector ArgExprs(Actions);
bool ArgExprsOk = true;
// now parse the non-empty comma separated list of expressions
@@ -142,7 +143,7 @@ AttributeList *Parser::ParseAttributes() {
if (ArgExprsOk && Tok.is(tok::r_paren)) {
ConsumeParen(); // ignore the right paren loc for now
CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName,
- ParmLoc, &ArgExprs[0], ArgExprs.size(), CurrAttr);
+ ParmLoc, ArgExprs.take(), ArgExprs.size(), CurrAttr);
}
}
} else { // not an identifier
@@ -154,7 +155,7 @@ AttributeList *Parser::ParseAttributes() {
0, SourceLocation(), 0, 0, CurrAttr);
} else {
// __attribute__(( aligned(16) ))
- llvm::SmallVector<ExprTy*, 8> ArgExprs;
+ ExprVector ArgExprs(Actions);
bool ArgExprsOk = true;
// now parse the list of expressions
@@ -174,8 +175,8 @@ AttributeList *Parser::ParseAttributes() {
// Match the ')'.
if (ArgExprsOk && Tok.is(tok::r_paren)) {
ConsumeParen(); // ignore the right paren loc for now
- CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
- SourceLocation(), &ArgExprs[0], ArgExprs.size(),
+ CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0,
+ SourceLocation(), ArgExprs.take(), ArgExprs.size(),
CurrAttr);
}
}
@@ -295,7 +296,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
} else if (Tok.is(tok::l_paren)) {
// Parse C++ direct initializer: '(' expression-list ')'
SourceLocation LParenLoc = ConsumeParen();
- ExprListTy Exprs;
+ ExprVector Exprs(Actions);
CommaLocsTy CommaLocs;
bool InvalidExpr = false;
@@ -310,7 +311,7 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) {
assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
"Unexpected number of commas!");
Actions.AddCXXDirectInitializerToDecl(LastDeclInGroup, LParenLoc,
- &Exprs[0], Exprs.size(),
+ Exprs.take(), Exprs.size(),
&CommaLocs[0], RParenLoc);
}
} else {
@@ -1988,6 +1989,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
} else { // we have an expression.
ExprResult Result = ParseExpression();
+ ExprGuard ResultGuard(Actions, Result);
if (Result.isInvalid || Tok.isNot(tok::r_paren)) {
MatchRHSPunctuation(tok::r_paren, LParenLoc);
@@ -1997,7 +1999,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
const char *PrevSpec = 0;
// Check for duplicate type specifiers (e.g. "int typeof(int)").
if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec,
- Result.Val))
+ ResultGuard.take()))
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
}
DS.SetRangeEnd(RParenLoc);
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 9e380c9036..a80e06002a 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -15,6 +15,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
+#include "AstGuard.h"
using namespace clang;
/// ParseNamespace - We know that the current token is a namespace keyword. This
@@ -377,8 +378,8 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclTy *ClassDecl)
// Notify semantic analysis that we have parsed a complete
// base-specifier.
- return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access, BaseType,
- BaseLoc);
+ return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
+ BaseType, BaseLoc);
}
/// getAccessSpecifierIfPresent - Determine whether the next token is
@@ -747,7 +748,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclTy *ConstructorDecl) {
SourceLocation LParenLoc = ConsumeParen();
// Parse the optional expression-list.
- ExprListTy ArgExprs;
+ ExprVector ArgExprs(Actions);
CommaLocsTy CommaLocs;
if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
SkipUntil(tok::r_paren);
@@ -756,9 +757,9 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclTy *ConstructorDecl) {
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
- return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, II, IdLoc,
- LParenLoc, &ArgExprs[0], ArgExprs.size(),
- &CommaLocs[0], RParenLoc);
+ return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, II, IdLoc,
+ LParenLoc, ArgExprs.take(),
+ ArgExprs.size(), &CommaLocs[0], RParenLoc);
}
/// ParseExceptionSpecification - Parse a C++ exception-specification
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index a379eeca2e..17b14bd2a1 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -23,6 +23,7 @@
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
#include "ExtensionRAIIObject.h"
+#include "AstGuard.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;
@@ -238,12 +239,15 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind());
SourceLocation ColonLoc;
+ ExprGuard LHSGuard(Actions, LHS);
while (1) {
// If this token has a lower precedence than we are allowed to parse (e.g.
// because we are called recursively, or because the token is not a binop),
// then we are done!
- if (NextTokPrec < MinPrec)
+ if (NextTokPrec < MinPrec) {
+ LHSGuard.take();
return LHS;
+ }
// Consume the operator, saving the operator token for error reporting.
Token OpToken = Tok;
@@ -251,6 +255,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
// Special case handling for the ternary operator.
ExprResult TernaryMiddle(true);
+ ExprGuard MiddleGuard(Actions);
if (NextTokPrec == prec::Conditional) {
if (Tok.isNot(tok::colon)) {
// Handle this production specially:
@@ -259,7 +264,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
// 'logical-OR-expression' as we might expect.
TernaryMiddle = ParseExpression();
if (TernaryMiddle.isInvalid) {
- Actions.DeleteExpr(LHS.Val);
return TernaryMiddle;
}
} else {
@@ -268,12 +272,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
TernaryMiddle = ExprResult(false);
Diag(Tok, diag::ext_gnu_conditional_expr);
}
+ MiddleGuard.reset(TernaryMiddle);
if (Tok.isNot(tok::colon)) {
Diag(Tok, diag::err_expected_colon);
Diag(OpToken, diag::note_matching) << "?";
- Actions.DeleteExpr(LHS.Val);
- Actions.DeleteExpr(TernaryMiddle.Val);
return ExprResult(true);
}
@@ -284,10 +287,9 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
// Parse another leaf here for the RHS of the operator.
ExprResult RHS = ParseCastExpression(false);
if (RHS.isInvalid) {
- Actions.DeleteExpr(LHS.Val);
- Actions.DeleteExpr(TernaryMiddle.Val);
return RHS;
}
+ ExprGuard RHSGuard(Actions, RHS);
// Remember the precedence of this operator and get the precedence of the
// operator immediately to the right of the RHS.
@@ -306,30 +308,32 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, unsigned MinPrec) {
// more tightly than the current operator. If it is left-associative, it
// is okay, to bind exactly as tightly. For example, compile A=B=C=D as
// A=(B=(C=D)), where each paren is a level of recursion here.
+ // The function takes ownership of the RHS.
+ RHSGuard.take();
RHS = ParseRHSOfBinaryExpression(RHS, ThisPrec + !isRightAssoc);
if (RHS.isInvalid) {
- Actions.DeleteExpr(LHS.Val);
- Actions.DeleteExpr(TernaryMiddle.Val);
return RHS;
}
+ RHSGuard.reset(RHS);
NextTokPrec = getBinOpPrecedence(Tok.getKind());
}
assert(NextTokPrec <= ThisPrec && "Recursion didn't work!");
-
+
if (!LHS.isInvalid) {
// Combine the LHS and RHS into the LHS (e.g. build AST).
+ LHSGuard.take();
+ MiddleGuard.take();
+ RHSGuard.take();
if (TernaryMiddle.isInvalid)
LHS = Actions.ActOnBinOp(CurScope, OpToken.getLocation(),
OpToken.getKind(), LHS.Val, RHS.Val);
else
LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
LHS.Val, TernaryMiddle.Val, RHS.Val);
- } else {
- // We had a semantic error on the LHS. Just free the RHS and continue.
- Actions.DeleteExpr(TernaryMiddle.Val);
- Actions.DeleteExpr(RHS.Val);
+ LHSGuard.reset(LHS);
}
+ // If we had an invalid LHS, Middle and RHS will be freed by the guards here
}
}
@@ -676,24 +680,27 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
/// argument-expression-list ',' assignment-expression
///
Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
-
+ ExprGuard LHSGuard(Actions, LHS);
// Now that the primary-expression piece of the postfix-expression has been
// parsed, see if there are any postfix-expression pieces here.
SourceLocation Loc;
while (1) {
switch (Tok.getKind()) {
default: // Not a postfix-expression suffix.
+ LHSGuard.take();
return LHS;
case tok::l_square: { // postfix-expression: p-e '[' expression ']'
Loc = ConsumeBracket();
ExprResult Idx = ParseExpression();
-
+ ExprGuard IdxGuard(Actions, Idx);
+
SourceLocation RLoc = Tok.getLocation();
- if (!LHS.isInvalid && !Idx.isInvalid && Tok.is(tok::r_square))
- LHS = Actions.ActOnArraySubscriptExpr(CurScope, LHS.Val, Loc,
- Idx.Val, RLoc);
- else
+ if (!LHS.isInvalid && !Idx.isInvalid && Tok.is(tok::r_square)) {
+ LHS = Actions.ActOnArraySubscriptExpr(CurScope, LHSGuard.take(), Loc,
+ IdxGuard.take(), RLoc);
+ LHSGuard.reset(LHS);
+ } else
LHS = ExprResult(true);
// Match the ']'.
@@ -702,7 +709,7 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
}
case tok::l_paren: { // p-e: p-e '(' argument-expression-list[opt] ')'
- ExprListTy ArgExprs;
+ ExprVector ArgExprs(Actions);
CommaLocsTy CommaLocs;
Loc = ConsumeParen();
@@ -718,8 +725,10 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
if (!LHS.isInvalid && Tok.is(tok::r_paren)) {
assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&&
"Unexpected number of commas!");
- LHS = Actions.ActOnCallExpr(LHS.Val, Loc, &ArgExprs[0], ArgExprs.size(),
- &CommaLocs[0], Tok.getLocation());
+ LHS = Actions.ActOnCallExpr(LHSGuard.take(), Loc, ArgExprs.take(),
+ ArgExprs.size(), &CommaLocs[0],
+ Tok.getLocation());
+ LHSGuard.reset(LHS);
}
MatchRHSPunctuation(tok::r_paren, Loc);
@@ -735,18 +744,22 @@ Parser::ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
return ExprResult(true);
}
- if (!LHS.isInvalid)
- LHS = Actions.ActOnMemberReferenceExpr(LHS.Val, OpLoc, OpKind,
+ if (!LHS.isInvalid) {
+ LHS = Actions.ActOnMemberReferenceExpr(LHSGuard.take(), OpLoc, OpKind,
Tok.getLocation(),
*Tok.getIdentifierInfo());
+ LHSGuard.reset(LHS);
+ }
ConsumeToken();
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
case tok::minusminus: // postfix-expression: postfix-expression '--'
- if (!LHS.isInvalid)
+ if (!LHS.isInvalid) {
LHS = Actions.ActOnPostfixUnaryOp(CurScope, Tok.getLocation(),
- Tok.getKind(), LHS.Val);
+ Tok.getKind(), LHSGuard.take());
+ LHSGuard.reset(LHS);
+ }
ConsumeToken();
break;
}
@@ -840,6 +853,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
default: assert(0 && "Not a builtin primary expression!");
case tok::kw___builtin_va_arg: {
ExprResult Expr = ParseAssignmentExpression();
+ ExprGuard ExprGuard(Actions, Expr);
if (Expr.isInvalid) {
SkipUntil(tok::r_paren);
return ExprResult(true);
@@ -854,7 +868,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
Diag(Tok, diag::err_expected_rparen);
return ExprResult(true);
}
- Res = Actions.ActOnVAArg(StartLoc, Expr.Val, Ty, ConsumeParen());
+ Res = Actions.ActOnVAArg(StartLoc, ExprGuard.take(), Ty, ConsumeParen());
break;
}
case tok::kw___builtin_offsetof: {
@@ -879,6 +893,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
+ // FIXME: This loop leaks the index expressions on error.
while (1) {
if (Tok.is(tok::period)) {
// offsetof-member-designator: offsetof-member-designator '.' identifier
@@ -921,6 +936,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
}
case tok::kw___builtin_choose_expr: {
ExprResult Cond = ParseAssignmentExpression();
+ ExprGuard CondGuard(Actions, Cond);
if (Cond.isInvalid) {
SkipUntil(tok::r_paren);
return Cond;
@@ -929,6 +945,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
return ExprResult(true);
ExprResult Expr1 = ParseAssignmentExpression();
+ ExprGuard Guard1(Actions, Expr1);
if (Expr1.isInvalid) {
SkipUntil(tok::r_paren);
return Expr1;
@@ -937,6 +954,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
return ExprResult(true);
ExprResult Expr2 = ParseAssignmentExpression();
+ ExprGuard Guard2(Actions, Expr2);
if (Expr2.isInvalid) {
SkipUntil(tok::r_paren);
return Expr2;
@@ -945,12 +963,12 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
Diag(Tok, diag::err_expected_rparen);
return ExprResult(true);
}
- Res = Actions.ActOnChooseExpr(StartLoc, Cond.Val, Expr1.Val, Expr2.Val,
- ConsumeParen());
+ Res = Actions.ActOnChooseExpr(StartLoc, CondGuard.take(), Guard1.take(),
+ Guard2.take(), ConsumeParen());
break;
}
case tok::kw___builtin_overload: {
- llvm::SmallVector<ExprTy*, 8> ArgExprs;
+ ExprVector ArgExprs(Actions);
llvm::SmallVector<SourceLocation, 8> CommaLocs;
// For each iteration through the loop look for assign-expr followed by a
@@ -977,7 +995,7 @@ Parser::ExprResult Parser::ParseBuiltinPrimaryExpression() {
SkipUntil(tok::r_paren);
return ExprResult(true);
}
- Res = Actions.ActOnOverloadExpr(&ArgExprs[0], ArgExprs.size(),
+ Res = Actions.ActOnOverloadExpr(ArgExprs.take(), ArgExprs.size(),
&CommaLocs[0], StartLoc, ConsumeParen());
break;
}
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 527aba2020..b4b6fb5330 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -14,6 +14,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
+#include "AstGuard.h"
using namespace clang;
/// ParseCXXScopeSpecifier - Parse global scope or nested-name-specifier.
@@ -328,7 +329,7 @@ Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
assert(Tok.is(tok::l_paren) && "Expected '('!");
SourceLocation LParenLoc = ConsumeParen();
- ExprListTy Exprs;
+ ExprVector Exprs(Actions);
CommaLocsTy CommaLocs;
if (Tok.isNot(tok::r_paren)) {
@@ -345,7 +346,7 @@ Parser::ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
"Unexpected number of commas!");
return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
LParenLoc,
- &Exprs[0], Exprs.size(),
+ Exprs.take(), Exprs.size(),
&CommaLocs[0], RParenLoc);
}
@@ -659,7 +660,7 @@ Parser::ExprResult Parser::ParseCXXNewExpression()
// A '(' now can be a new-placement or the '(' wrapping the type-id in the
// second form of new-expression. It can't be a new-type-id.
- ExprListTy PlacementArgs;
+ ExprVector PlacementArgs(Actions);
SourceLocation PlacementLParen, PlacementRParen;
TypeTy *Ty = 0;
@@ -706,7 +707,7 @@ Parser::ExprResult Parser::ParseCXXNewExpression()
ParenTypeId = false;
}
- ExprListTy ConstructorArgs;
+ ExprVector ConstructorArgs(Actions);
SourceLocation ConstructorLParen, ConstructorRParen;
if (Tok.is(tok::l_paren)) {
@@ -722,9 +723,9 @@ Parser::ExprResult Parser::ParseCXXNewExpression()
}
return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
- &PlacementArgs[0], PlacementArgs.size(),
+ PlacementArgs.take(), PlacementArgs.size(),
PlacementRParen, ParenTypeId, TyStart, Ty, TyEnd,
- ConstructorLParen, &ConstructorArgs[0],
+ ConstructorLParen, ConstructorArgs.take(),
ConstructorArgs.size(), ConstructorRParen);
}
diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp
index c3d2cd2c4c..61c9b9c286 100644
--- a/lib/Parse/ParseInit.cpp
+++ b/lib/Parse/ParseInit.cpp
@@ -13,6 +13,7 @@
#include "clang/Parse/Designator.h"
#include "clang/Parse/Parser.h"
+#include "AstGuard.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallString.h"
using namespace clang;
@@ -238,11 +239,11 @@ ParseInitializerWithPotentialDesignator(InitListDesignations &Designations,
///
Parser::ExprResult Parser::ParseBraceInitializer() {
SourceLocation LBraceLoc = ConsumeBrace();
-
+
/// InitExprs - This is the actual list of expressions contained in the
/// initializer.
- llvm::SmallVector<ExprTy*, 8> InitExprs;
-
+ ExprVector InitExprs(Actions);
+
/// ExprDesignators - For each initializer, keep track of the designator that
/// was specified for it, if any.
InitListDesignations InitExprDesignations(Actions);
@@ -289,6 +290,9 @@ Parser::ExprResult Parser::ParseBraceInitializer() {
// parsing the rest of the initializer. This allows us to emit
// diagnostics for later elements that we find. If we don't see a comma,
// assume there is a parse error, and just skip to recover.
+ // FIXME: This comment doesn't sound right. If there is a r_brace
+ // immediately, it can't be an error, since there is no other way of
+ // leaving this loop except through this if.
if (Tok.isNot(tok::comma)) {
SkipUntil(tok::r_brace, false, true);
break;
@@ -305,13 +309,9 @@ Parser::ExprResult Parser::ParseBraceInitializer() {
if (Tok.is(tok::r_brace)) break;
}
if (InitExprsOk && Tok.is(tok::r_brace))
- return Actions.ActOnInitList(LBraceLoc, &InitExprs[0], InitExprs.size(),
+ return Actions.ActOnInitList(LBraceLoc, InitExprs.take(), InitExprs.size(),
InitExprDesignations, ConsumeBrace());
- // On error, delete any parsed subexpressions.
- for (unsigned i = 0, e = InitExprs.size(); i != e; ++i)
- Actions.DeleteExpr(InitExprs[i]);
-
// Match the '}'.
MatchRHSPunctuation(tok::r_brace, LBraceLoc);
return ExprResult(true); // an error occurred.
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index cabfe7c593..9fe4c1ec12 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -14,6 +14,7 @@
#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
+#include "AstGuard.h"
#include "clang/Basic/Diagnostic.h"
#include "llvm/ADT/SmallVector.h"
using namespace clang;
@@ -1194,6 +1195,7 @@ Parser::StmtResult Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
}
ConsumeParen(); // '('
ExprResult Res = ParseExpression();
+ ExprGuard ResGuard(Actions, Res);
if (Res.isInvalid) {
SkipUntil(tok::semi);
return true;
@@ -1216,7 +1218,8 @@ Parser::StmtResult Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
ExitScope();
if (SynchBody.isInvalid)
SynchBody = Actions.ActOnNullStmt(Tok.getLocation());
- return Actions.ActOnObjCAtSynchronizedStmt(atLoc, Res.Val, SynchBody.Val);
+ return Actions.ActOnObjCAtSynchronizedStmt(atLoc, ResGuard.take(),
+ SynchBody.Val);
}
/// objc-try-catch-statement:
@@ -1245,7 +1248,9 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
ExitScope();
if (TryBody.isInvalid)
TryBody = Actions.ActOnNullStmt(Tok.getLocation());
-
+ ExprGuard TryGuard(Actions, TryBody);
+ ExprGuard CatchGuard(Actions), FinallyGuard(Actions);
+
while (Tok.is(tok::at)) {
// At this point, we need to lookahead to determine if this @ is the start
// of an @catch or @finally. We don't want to consume the @ token if this
@@ -1290,7 +1295,8 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
if (CatchBody.isInvalid)
CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc, RParenLoc,
- FirstPart, CatchBody.Val, CatchStmts.Val);
+ FirstPart, CatchBody.Val, CatchGuard.take());
+ CatchGuard.reset(CatchStmts);
ExitScope();
} else {
Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
@@ -1313,6 +1319,7 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
FinallyBody.Val);
+ FinallyGuard.reset(FinallyStmt);
catch_or_finally_seen = true;
ExitScope();
break;
@@ -1322,8 +1329,8 @@ Parser::StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
Diag(atLoc, diag::err_missing_catch_finally);
return true;
}
- return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.Val, CatchStmts.Val,
- FinallyStmt.Val);
+ return Actions.ActOnObjCAtTryStmt(atLoc, TryGuard.take(), CatchGuard.take(),
+ FinallyGuard.take());
}
/// objc-method-def: objc-method-proto ';'[opt] '{' body '}'
@@ -1468,7 +1475,7 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
IdentifierInfo *selIdent = ParseObjCSelector(Loc);
llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
- llvm::SmallVector<Action::ExprTy *, 12> KeyExprs;
+ ExprVector KeyExprs(Actions);
if (Tok.is(tok::colon)) {
while (1) {
@@ -1551,9 +1558,9 @@ Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
return Actions.ActOnClassMessage(CurScope,
ReceiverName, Sel,
LBracLoc, NameLoc, RBracLoc,
- &KeyExprs[0], KeyExprs.size());
+ KeyExprs.take(), KeyExprs.size());
return Actions.ActOnInstanceMessage(ReceiverExpr, Sel, LBracLoc, RBracLoc,
- &KeyExprs[0], KeyExprs.size());
+ KeyExprs.take(), KeyExprs.size());
}
Parser::ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
@@ -1564,31 +1571,26 @@ Parser::ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
// expressions. At this point, we know that the only valid thing that starts
// with '@' is an @"".
llvm::SmallVector<SourceLocation, 4> AtLocs;
- llvm::SmallVector<ExprTy*, 4> AtStrings;
+ ExprVector AtStrings(Actions);
AtLocs.push_back(AtLoc);
AtStrings.push_back(Res.Val);
while (Tok.is(tok::at)) {
AtLocs.push_back(ConsumeToken()); // eat the @.
- ExprResult Res(true); // Invalid unless there is a string literal.
+ ExprResult Lit(true); // Invalid unless there is a string literal.
if (isTokenStringLiteral())
- Res = ParseStringLiteralExpression();
+ Lit = ParseStringLiteralExpression();
else
Diag(Tok, diag::err_objc_concat_string);
- if (Res.isInvalid) {
- while (!AtStrings.empty()) {
- Actions.DeleteExpr(AtStrings.back());
- AtStrings.pop_back();
- }
- return Res;
- }
+ if (Lit.isInvalid)
+ return Lit;
- AtStrings.push_back(Res.Val);
+ AtStrings.push_back(Lit.Val);
}
- return Actions.ParseObjCStringLiteral(&AtLocs[0], &AtStrings[0],
+ return Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.take(),
AtStrings.size());
}
@@ -1614,7 +1616,6 @@ Parser::ExprResult Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
/// objc-protocol-expression
/// @protocol ( protocol-name )
-
Parser::ExprResult Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
SourceLocation ProtoLoc = ConsumeToken();
diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp
index 17eba03c26..a6e2328d17 100644
--- a/lib/Parse/ParsePragma.cpp
+++ b/lib/Parse/ParsePragma.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "ParsePragma.h"
+#include "AstGuard.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/Action.h"
@@ -35,12 +36,14 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
Action::PragmaPackKind Kind = Action::PPK_Default;
IdentifierInfo *Name = 0;
Action::ExprResult Alignment;
+ ExprGuard AlignmentGuard(Actions);
SourceLocation LParenLoc = Tok.getLocation();
PP.Lex(Tok);
if (Tok.is(tok::numeric_constant)) {
Alignment = Actions.ActOnNumericConstant(Tok);
if (Alignment.isInvalid)
return;
+ AlignmentGuard.reset(Alignment);
PP.Lex(Tok);
} else if (Tok.is(tok::identifier)) {
@@ -66,6 +69,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
Alignment = Actions.ActOnNumericConstant(Tok);
if (Alignment.isInvalid)
return;
+ AlignmentGuard.reset(Alignment);
PP.Lex(Tok);
} else if (Tok.is(tok::identifier)) {
@@ -83,6 +87,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
Alignment = Actions.ActOnNumericConstant(Tok);
if (Alignment.isInvalid)
return;
+ AlignmentGuard.reset(Alignment);
PP.Lex(Tok);
}
@@ -100,7 +105,7 @@ void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
}
SourceLocation RParenLoc = Tok.getLocation();
- Actions.ActOnPragmaPack(Kind, Name, Alignment.Val, PackLoc,
+ Actions.ActOnPragmaPack(Kind, Name, AlignmentGuard.take(), PackLoc,
LParenLoc, RParenLoc);
}
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 70062416fb..86e18bfca8 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 @@ Parser::StmtResult Parser::ParseCaseStatement() {
SkipUntil(tok::colon);
return true;
}
+ ExprGuard LHSGuard(Actions, LHS);
// GNU case range extension.
SourceLocation DotDotDotLoc;
@@ -244,6 +246,7 @@ Parser::StmtResult Parser::ParseCaseStatement() {
}
RHSVal = RHS.Val;
}
+ ExprGuard RHSGuard(Actions, RHSVal);
if (Tok.isNot(tok::colon)) {
Diag(Tok, diag::err_expected_colon_after) << "'case'";
@@ -265,8 +268,8 @@ Parser::StmtResult Parser::ParseCaseStatement() {
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,
+