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);
--- /dev/null
+//===--- 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
#include "clang/Basic/Diagnostic.h"
#include "clang/Parse/Scope.h"
#include "ExtensionRAIIObject.h"
+#include "AstGuard.h"
#include "llvm/ADT/SmallSet.h"
using namespace clang;
} 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
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
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
// 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);
}
}
} 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;
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 {
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);
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);
#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
// 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
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);
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
#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;
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;
// 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:
// 'logical-OR-expression' as we might expect.
TernaryMiddle = ParseExpression();
if (TernaryMiddle.isInvalid) {
- Actions.DeleteExpr(LHS.Val);
return TernaryMiddle;
}
} else {
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);
}
// 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.
// 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
}
}
/// 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 ']'.
}
case tok::l_paren: { // p-e: p-e '(' argument-expression-list[opt] ')'
- ExprListTy ArgExprs;
+ ExprVector ArgExprs(Actions);
CommaLocsTy CommaLocs;
Loc = ConsumeParen();
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);
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;
}
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);
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: {
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
}
case tok::kw___builtin_choose_expr: {
ExprResult Cond = ParseAssignmentExpression();
+ ExprGuard CondGuard(Actions, Cond);
if (Cond.isInvalid) {
SkipUntil(tok::r_paren);
return Cond;
return ExprResult(true);
ExprResult Expr1 = ParseAssignmentExpression();
+ ExprGuard Guard1(Actions, Expr1);
if (Expr1.isInvalid) {
SkipUntil(tok::r_paren);
return Expr1;
return ExprResult(true);
ExprResult Expr2 = ParseAssignmentExpression();
+ ExprGuard Guard2(Actions, Expr2);
if (Expr2.isInvalid) {
SkipUntil(tok::r_paren);
return Expr2;
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
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;
}
#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.
assert(Tok.is(tok::l_paren) && "Expected '('!");
SourceLocation LParenLoc = ConsumeParen();
- ExprListTy Exprs;
+ ExprVector Exprs(Actions);
CommaLocsTy CommaLocs;
if (Tok.isNot(tok::r_paren)) {
"Unexpected number of commas!");
return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
LParenLoc,
- &Exprs[0], Exprs.size(),
+ Exprs.take(), Exprs.size(),
&CommaLocs[0], RParenLoc);
}
// 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;
ParenTypeId = false;
}
- ExprListTy ConstructorArgs;
+ ExprVector ConstructorArgs(Actions);
SourceLocation ConstructorLParen, ConstructorRParen;
if (Tok.is(tok::l_paren)) {
}
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);
}
#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;
///
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);
// 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;
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.
#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;
}
ConsumeParen(); // '('
ExprResult Res = ParseExpression();
+ ExprGuard ResGuard(Actions, Res);
if (Res.isInvalid) {
SkipUntil(tok::semi);
return true;
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:
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
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)
FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
FinallyBody.Val);
+ FinallyGuard.reset(FinallyStmt);
catch_or_finally_seen = true;
ExitScope();
break;
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 '}'
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) {
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) {
// 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());
}
/// objc-protocol-expression
/// @protocol ( protocol-name )
-
Parser::ExprResult Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
SourceLocation ProtoLoc = ConsumeToken();
//===----------------------------------------------------------------------===//
#include "ParsePragma.h"
+#include "AstGuard.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/Action.h"
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)) {
Alignment = Actions.ActOnNumericConstant(Tok);
if (Alignment.isInvalid)
return;
+ AlignmentGuard.reset(Alignment);
PP.Lex(Tok);
} else if (Tok.is(tok::identifier)) {
Alignment = Actions.ActOnNumericConstant(Tok);
if (Alignment.isInvalid)
return;
+ AlignmentGuard.reset(Alignment);
PP.Lex(Tok);
}
}
SourceLocation RParenLoc = Tok.getLocation();
- Actions.ActOnPragmaPack(Kind, Name, Alignment.Val, PackLoc,
+ Actions.ActOnPragmaPack(Kind, Name, AlignmentGuard.take(), PackLoc,
LParenLoc, RParenLoc);
}
#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"
SkipUntil(tok::colon);
return true;
}
+ ExprGuard LHSGuard(Actions, LHS);
// GNU case range extension.
SourceLocation DotDotDotLoc;
}
RHSVal = RHS.Val;
}
+ ExprGuard RHSGuard(Actions, RHSVal);
if (Tok.isNot(tok::colon)) {
Diag(Tok, diag::err_expected_colon_after) << "'case'";
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
// 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__)) {
SourceLocation RBraceLoc = ConsumeBrace();
return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc,
- &Stmts[0], Stmts.size(), isStmtExpr);
+ Stmts.take(), Stmts.size(), isStmtExpr);
}
/// ParseIfStatement
} else {
CondExp = ParseSimpleParenExpression();
}
+ ExprGuard CondGuard(Actions, CondExp);
if (CondExp.isInvalid) {
SkipUntil(tok::semi);
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;
}
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);
}
} 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
// Read the body statement.
StmtResult Body = ParseStatement();
+ StmtGuard BodyGuard(Actions, Body);
// Pop the body scope if needed.
if (NeedsInnerScope) ExitScope();
if (Cond.isInvalid || Body.isInvalid) return true;
- return Actions.ActOnWhileStmt(WhileLoc, Cond.Val, Body.Val);
+ return Actions.ActOnWhileStmt(WhileLoc, CondGuard.take(), BodyGuard.take());
}
/// ParseDoStatement
// Read the body statement.
StmtResult Body = ParseStatement();
+ StmtGuard BodyGuard(Actions, Body);
// Pop the body scope if needed.
if (NeedsInnerScope) ExitScope();
// 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
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 (;
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.
ThirdPart = R.Val;
}
}
+ SecondGuard.reset(SecondPart);
+ ThirdGuard.reset(ThirdPart);
}
// Match the ')'.
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
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);
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;
RParenLoc = ConsumeParen();
} else {
- // Parse Outputs, if present.
+ // Parse Outputs, if present.
if (ParseAsmOperandsOpt(Names, Constraints, Exprs))
return true;
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);
}