diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2008-11-25 22:21:31 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2008-11-25 22:21:31 +0000 |
commit | a55e52c0802cae3b7c366a05c461d3d15074c1a3 (patch) | |
tree | fca8cd5d7a9b355502c69fea49e50e69a7ddd379 | |
parent | 71fcec9abf2ce66d5e17a24bd021680e94e42f0d (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.h | 5 | ||||
-rw-r--r-- | lib/Parse/AstGuard.h | 106 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 18 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 13 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 80 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 13 | ||||
-rw-r--r-- | lib/Parse/ParseInit.cpp | 16 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 43 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.cpp | 7 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 56 |
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, + |