Use RAII objects to ensure proper destruction of expression and statement AST nodes in the parser in most cases, even on error.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60057 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index a379eec..17b14bd 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 @@
   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 @@
     
     // 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 @@
         // 'logical-OR-expression' as we might expect.
         TernaryMiddle = ParseExpression();
         if (TernaryMiddle.isInvalid) {
-          Actions.DeleteExpr(LHS.Val);
           return TernaryMiddle;
         }
       } else {
@@ -268,12 +272,11 @@
         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 @@
     // 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 @@
       // 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 @@
 ///         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 @@
     }
       
     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 @@
       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 @@
         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 @@
   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 @@
       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 @@
     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 @@
   }
   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 @@
       return ExprResult(true);
     
     ExprResult Expr1 = ParseAssignmentExpression();
+    ExprGuard Guard1(Actions, Expr1);
     if (Expr1.isInvalid) {
       SkipUntil(tok::r_paren);
       return Expr1;
@@ -937,6 +954,7 @@
       return ExprResult(true);
     
     ExprResult Expr2 = ParseAssignmentExpression();
+    ExprGuard Guard2(Actions, Expr2);
     if (Expr2.isInvalid) {
       SkipUntil(tok::r_paren);
       return Expr2;
@@ -945,12 +963,12 @@
       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 @@
       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;
   }