]> granicus.if.org Git - clang/commitdiff
Use RAII objects to ensure proper destruction of expression and statement AST nodes...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 25 Nov 2008 22:21:31 +0000 (22:21 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 25 Nov 2008 22:21:31 +0000 (22:21 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60057 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Parse/Parser.h
lib/Parse/AstGuard.h [new file with mode: 0644]
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Parse/ParseInit.cpp
lib/Parse/ParseObjc.cpp
lib/Parse/ParsePragma.cpp
lib/Parse/ParseStmt.cpp

index 47b1191818219c4cd476c29cf8d26dc483ce9c35..bfb198eea15353081294e7f067f195dfbd9e3675 100644 (file)
@@ -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 (file)
index 0000000..434c72c
--- /dev/null
@@ -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
index eaf9f8b0f98a91bced3bf188de2e69b7ad804ce7..d8894c66fa9d5427d16eb205c4d8407ad7fed8da 100644 (file)
@@ -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);
index 9e380c903694a01e140b60e119fb6bae94dc8792..a80e06002a3ce1608795cdfa84c374529485f6c7 100644 (file)
@@ -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
index a379eeca2ee2f99c72e346fb1730db40f09eff67..17b14bd2a1b953e915527631381c3f038830b0be 100644 (file)
@@ -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;
   }
index 527aba2020801ad0b238ed0ea13b0f54df08219a..b4b6fb533024ea67318ff44a070c441c0eacb154 100644 (file)
@@ -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);
 }
 
index c3d2cd2c4ccc5daa4111feb035f3ba49c91b4386..61c9b9c286d8727ba1aaaf790172863f29c2417d 100644 (file)
@@ -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.
index cabfe7c593dd1b25550713c87409de773322d086..9fe4c1ec12e24d477c8e71e3fef99bf2329b8f46 100644 (file)
@@ -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();
   
index 17eba03c2604ed331bb88322e50271998e9b6122..a6e2328d177e0c5eff86cafd4e1f0771fa707e60 100644 (file)
@@ -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);
 }
 
index 70062416fb31414e6aeb942971da62bbdf15f45b..86e18bfca8513f1a35dec0ab2159b0fafb855597 100644 (file)
@@ -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,
+                               RHSGuard.take(), ColonLoc, SubStmt.Val);
 }
 
 /// ParseDefaultStatement
@@ -351,8 +354,9 @@ Parser::StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
 
   // 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 @@ Parser::StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
   
   SourceLocation RBraceLoc = ConsumeBrace();
   return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc,
-                                   &Stmts[0], Stmts.size(), isStmtExpr);
+                                   Stmts.take(), Stmts.size(), isStmtExpr);
 }
 
 /// ParseIfStatement
@@ -456,6 +460,7 @@ Parser::StmtResult Parser::ParseIfStatement() {
   } else {
     CondExp = ParseSimpleParenExpression();
   }
+  ExprGuard CondGuard(Actions, CondExp);
 
   if (CondExp.isInvalid) {
     SkipUntil(tok::semi);
@@ -528,9 +533,7 @@ Parser::StmtResult Parser::ParseIfStatement() {
   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 @@ Parser::StmtResult Parser::ParseIfStatement() {
   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 @@ Parser::StmtResult Parser::ParseWhileStatement() {
   } 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 @@ Parser::StmtResult Parser::ParseWhileStatement() {
   
   // Read the body statement.
   StmtResult Body = ParseStatement();
+  StmtGuard BodyGuard(Actions, Body);
 
   // Pop the body scope if needed.
   if (NeedsInnerScope) ExitScope();
@@ -693,7 +698,7 @@ Parser::StmtResult Parser::ParseWhileStatement() {
   
   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 @@ Parser::StmtResult Parser::ParseDoStatement() {
   
   // Read the body statement.
   StmtResult Body = ParseStatement();
+  StmtGuard BodyGuard(Actions, Body);
 
   // Pop the body scope if needed.
   if (NeedsInnerScope) ExitScope();
@@ -749,12 +755,14 @@ Parser::StmtResult Parser::ParseDoStatement() {
   
   // 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 @@ Parser::StmtResult Parser::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 (;
@@ -856,7 +866,10 @@ Parser::StmtResult Parser::ParseForStatement() {
       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 @@ Parser::StmtResult Parser::ParseForStatement() {
           ThirdPart = R.Val;
       }
     }
+    SecondGuard.reset(SecondPart);
+    ThirdGuard.reset(ThirdPart);
   }
   // Match the ')'.
   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
@@ -918,6 +933,10 @@ Parser::StmtResult Parser::ParseForStatement() {
   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 @@ Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) {
   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 @@ Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) {
     
     RParenLoc = ConsumeParen();
   } else {
-    // Parse Outputs, if present. 
+    // Parse Outputs, if present.
     if (ParseAsmOperandsOpt(Names, Constraints, Exprs))
         return true;
   
@@ -1136,9 +1156,9 @@ Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) {
   
   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);
 }