Index: lib/Parse/ParseInit.cpp
===================================================================
--- lib/Parse/ParseInit.cpp	(revision 59970)
+++ lib/Parse/ParseInit.cpp	(working copy)
@@ -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;
@@ -242,6 +243,7 @@
   /// InitExprs - This is the actual list of expressions contained in the
   /// initializer.
   llvm::SmallVector<ExprTy*, 8> InitExprs;
+  AstArrayGuard InitGuard(Actions, InitExprs, AstArrayGuard::Expr);
   
   /// ExprDesignators - For each initializer, keep track of the designator that
   /// was specified for it, if any.
@@ -289,6 +291,9 @@
       // 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 +310,9 @@
     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, InitGuard.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: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 59970)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -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;
 
@@ -123,6 +124,7 @@
             ConsumeToken();
             // __attribute__(( format(printf, 1, 2) ))
             llvm::SmallVector<ExprTy*, 8> ArgExprs;
+            AstArrayGuard ArgGuard(Actions, ArgExprs, AstArrayGuard::Expr);
             bool ArgExprsOk = true;
             
             // now parse the non-empty comma separated list of expressions
@@ -142,7 +144,7 @@
             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, ArgGuard.take(), ArgExprs.size(), CurrAttr);
             }
           }
         } else { // not an identifier
@@ -155,6 +157,7 @@
           } else { 
             // __attribute__(( aligned(16) ))
             llvm::SmallVector<ExprTy*, 8> ArgExprs;
+            AstArrayGuard ArgGuard(Actions, ArgExprs, AstArrayGuard::Expr);
             bool ArgExprsOk = true;
             
             // now parse the list of expressions
@@ -174,8 +177,8 @@
             // 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(), ArgGuard.take(), ArgExprs.size(),
                            CurrAttr);
             }
           }
@@ -296,6 +299,7 @@
       // Parse C++ direct initializer: '(' expression-list ')'
       SourceLocation LParenLoc = ConsumeParen();
       ExprListTy Exprs;
+      AstArrayGuard ExprGuard(Actions, Exprs, AstArrayGuard::Expr);
       CommaLocsTy CommaLocs;
 
       bool InvalidExpr = false;
@@ -310,7 +314,7 @@
         assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() &&
                "Unexpected number of commas!");
         Actions.AddCXXDirectInitializerToDecl(LastDeclInGroup, LParenLoc,
-                                              &Exprs[0], Exprs.size(),
+                                              ExprGuard.take(), Exprs.size(),
                                               &CommaLocs[0], RParenLoc);
       }
     } else {
@@ -1982,6 +1986,7 @@
       Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
   } else { // we have an expression.
     ExprResult Result = ParseExpression();
+    AstGuard ResultGuard(Actions, Result);
     
     if (Result.isInvalid || Tok.isNot(tok::r_paren)) {
       MatchRHSPunctuation(tok::r_paren, LParenLoc);
@@ -1991,7 +1996,7 @@
     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: lib/Parse/ParsePragma.cpp
===================================================================
--- lib/Parse/ParsePragma.cpp	(revision 59970)
+++ lib/Parse/ParsePragma.cpp	(working copy)
@@ -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 @@
   Action::PragmaPackKind Kind = Action::PPK_Default;
   IdentifierInfo *Name = 0;
   Action::ExprResult Alignment;
+  AstGuard 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 @@
           Alignment = Actions.ActOnNumericConstant(Tok);
           if (Alignment.isInvalid)
             return;
+          AlignmentGuard.reset(Alignment);
 
           PP.Lex(Tok);
         } else if (Tok.is(tok::identifier)) {
@@ -83,6 +87,7 @@
             Alignment = Actions.ActOnNumericConstant(Tok);
             if (Alignment.isInvalid)
               return;
+            AlignmentGuard.reset(Alignment);
 
             PP.Lex(Tok);
           }
@@ -100,7 +105,7 @@
   }
 
   SourceLocation RParenLoc = Tok.getLocation();
-  Actions.ActOnPragmaPack(Kind, Name, Alignment.Val, PackLoc, 
+  Actions.ActOnPragmaPack(Kind, Name, AlignmentGuard.take(), PackLoc, 
                           LParenLoc, RParenLoc);
 }
 
Index: lib/Parse/ParseObjc.cpp
===================================================================
--- lib/Parse/ParseObjc.cpp	(revision 59970)
+++ lib/Parse/ParseObjc.cpp	(working copy)
@@ -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 @@
   }
   ConsumeParen();  // '('
   ExprResult Res = ParseExpression();
+  AstGuard ResGuard(Actions, Res);
   if (Res.isInvalid) {
     SkipUntil(tok::semi);
     return true;
@@ -1216,7 +1218,8 @@
   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 @@
   ExitScope();
   if (TryBody.isInvalid)
     TryBody = Actions.ActOnNullStmt(Tok.getLocation());
-  
+  AstGuard TryGuard(Actions, TryBody);
+  AstGuard 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 @@
         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 @@
         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 @@
     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 '}'
@@ -1469,6 +1476,7 @@
 
   llvm::SmallVector<IdentifierInfo *, 12> KeyIdents;
   llvm::SmallVector<Action::ExprTy *, 12> KeyExprs;
+  AstArrayGuard KeyGuard(Actions, KeyExprs, AstArrayGuard::Expr);
 
   if (Tok.is(tok::colon)) {
     while (1) {
@@ -1551,9 +1559,9 @@
     return Actions.ActOnClassMessage(CurScope,
                                      ReceiverName, Sel, 
                                      LBracLoc, NameLoc, RBracLoc,
-                                     &KeyExprs[0], KeyExprs.size());
+                                     KeyGuard.take(), KeyExprs.size());
   return Actions.ActOnInstanceMessage(ReceiverExpr, Sel, LBracLoc, RBracLoc,
-                                      &KeyExprs[0], KeyExprs.size());
+                                      KeyGuard.take(), KeyExprs.size());
 }
 
 Parser::ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
@@ -1565,30 +1573,26 @@
   // with '@' is an @"".
   llvm::SmallVector<SourceLocation, 4> AtLocs;
   llvm::SmallVector<ExprTy*, 4> AtStrings;
+  AstArrayGuard AtGuard(Actions, AtStrings, AstArrayGuard::Expr);
   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], AtGuard.take(),
                                         AtStrings.size());
 }
 
@@ -1614,7 +1618,6 @@
 
 ///     objc-protocol-expression
 ///       @protocol ( protocol-name )
-
 Parser::ExprResult Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
   SourceLocation ProtoLoc = ConsumeToken();
   
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp	(revision 59970)
+++ lib/Parse/ParseExpr.cpp	(working copy)
@@ -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;
 
+  AstGuard 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);
+    AstGuard 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;
     }
+    AstGuard 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) {
-  
+  AstGuard 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();
-      
+      AstGuard 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 ']'.
@@ -703,6 +710,7 @@
       
     case tok::l_paren: {   // p-e: p-e '(' argument-expression-list[opt] ')'
       ExprListTy ArgExprs;
+      AstArrayGuard ArgGuard(Actions, ArgExprs, AstArrayGuard::Expr);
       CommaLocsTy CommaLocs;
       
       Loc = ConsumeParen();
@@ -718,8 +726,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, ArgGuard.take(),
+                                    ArgExprs.size(), &CommaLocs[0],
+                                    Tok.getLocation());
+        LHSGuard.reset(LHS);
       }
       
       MatchRHSPunctuation(tok::r_paren, Loc);
@@ -735,18 +745,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 +854,7 @@
   default: assert(0 && "Not a builtin primary expression!");
   case tok::kw___builtin_va_arg: {
     ExprResult Expr = ParseAssignmentExpression();
+    AstGuard ExprGuard(Actions, Expr);
     if (Expr.isInvalid) {
       SkipUntil(tok::r_paren);
       return ExprResult(true);
@@ -854,7 +869,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 +894,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 +937,7 @@
   }
   case tok::kw___builtin_choose_expr: {
     ExprResult Cond = ParseAssignmentExpression();
+    AstGuard CondGuard(Actions, Cond);
     if (Cond.isInvalid) {
       SkipUntil(tok::r_paren);
       return Cond;
@@ -929,6 +946,7 @@
       return ExprResult(true);
     
     ExprResult Expr1 = ParseAssignmentExpression();
+    AstGuard Guard1(Actions, Expr1);
     if (Expr1.isInvalid) {
       SkipUntil(tok::r_paren);
       return Expr1;
@@ -937,6 +955,7 @@
       return ExprResult(true);
     
     ExprResult Expr2 = ParseAssignmentExpression();
+    AstGuard Guard2(Actions, Expr2);
     if (Expr2.isInvalid) {
       SkipUntil(tok::r_paren);
       return Expr2;
@@ -945,12 +964,13 @@
       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;
+    AstArrayGuard ArgGuard(Actions, ArgExprs, AstArrayGuard::Expr);
     llvm::SmallVector<SourceLocation, 8> CommaLocs;
 
     // For each iteration through the loop look for assign-expr followed by a
@@ -977,7 +997,7 @@
       SkipUntil(tok::r_paren);
       return ExprResult(true);
     }
-    Res = Actions.ActOnOverloadExpr(&ArgExprs[0], ArgExprs.size(), 
+    Res = Actions.ActOnOverloadExpr(ArgGuard.take(), ArgExprs.size(), 
                                     &CommaLocs[0], StartLoc, ConsumeParen());
     break;
   }
Index: lib/Parse/AstGuard.h
===================================================================
--- lib/Parse/AstGuard.h	(revision 0)
+++ lib/Parse/AstGuard.h	(revision 0)
@@ -0,0 +1,129 @@
+//===--- AstGuard.h - C Language Parser -------------------------*- 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 AstGuard, an RAII guard for the Action elements.
+//
+//===----------------------------------------------------------------------===//
+
+#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.
+  class AstGuard {
+  public:
+    enum AstType {
+      Stmt,
+      Expr
+    };
+
+  private:
+    Action &Actions;
+    void *AstElement;
+    AstType Type;
+
+    void destroy() {
+      if (AstElement) {
+        if (Type == Stmt)
+          Actions.DeleteStmt(AstElement);
+        else
+          Actions.DeleteExpr(AstElement);
+      }
+    }
+
+    AstGuard(const AstGuard&); // DO NOT IMPLEMENT
+    // Reference member prevents copy assignment.
+
+  public:
+    explicit AstGuard(Action &actions) : Actions(actions), AstElement(0) {}
+    AstGuard(Action &actions, void *element, AstType type)
+      : Actions(actions), AstElement(element), Type(type) {}
+    AstGuard(Action &actions, const Action::ExprResult &res)
+      : Actions(actions), AstElement(res.Val), Type(Expr) {}
+    AstGuard(Action &actions, const Action::StmtResult &res)
+      : Actions(actions), AstElement(res.Val), Type(Stmt) {}
+    ~AstGuard() { destroy(); }
+
+    void reset(void *element, AstType type) {
+      destroy();
+      AstElement = element;
+      Type = type;
+    }
+    void reset(const Action::ExprResult &res) {
+      reset(res.Val, Expr);
+    }
+    void reset(const Action::StmtResult &res) {
+      reset(res.Val, Stmt);
+    }
+    void *take() {
+      void *Temp = AstElement;
+      AstElement = 0;
+      return Temp;
+    }
+    void *get() const { return AstElement; }
+  };
+
+  // RAII guard for freeing SmallVectors of Stmts and Exprs on early exit
+  // in the parser.
+  class AstArrayGuard {
+  public:
+    enum AstType {
+      Stmt,
+      Expr
+    };
+
+  private:
+    Action &Actions;
+    typedef llvm::SmallVectorImpl<void*> ArrayT;
+    ArrayT *Array;
+    AstType Type;
+
+    void destroy() {
+      if (Array) {
+        while (!Array->empty()) {
+          if (Type == Stmt)
+            Actions.DeleteStmt(Array->back());
+          else
+            Actions.DeleteExpr(Array->back());
+          Array->pop_back();
+        }
+      }
+    }
+
+    AstArrayGuard(const AstArrayGuard&); // DO NOT IMPLEMENT
+    // Reference member prevents copy assignment.
+
+  public:
+    AstArrayGuard(Action &actions) : Actions(actions), Array(0) {}
+    AstArrayGuard(Action &actions, ArrayT &array, AstType type)
+      : Actions(actions), Array(&array), Type(type) {}
+
+    ~AstArrayGuard() { destroy(); }
+
+    void reset(ArrayT &array, AstType type) {
+      destroy();
+      Array = &array;
+      Type = type;
+    }
+
+    void **take() {
+      if (!Array)
+        return 0;
+      void **Temp = &(*Array)[0];
+      Array = 0;
+      return Temp;
+    }
+  };
+}
+
+#endif
Index: lib/Parse/ParseStmt.cpp
===================================================================
--- lib/Parse/ParseStmt.cpp	(revision 59970)
+++ lib/Parse/ParseStmt.cpp	(working copy)
@@ -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 @@
     SkipUntil(tok::colon);
     return true;
   }
+  AstGuard LHSGuard(Actions, LHS);
   
   // GNU case range extension.
   SourceLocation DotDotDotLoc;
@@ -244,6 +246,7 @@
     }
     RHSVal = RHS.Val;
   }
+  AstGuard RHSGuard(Actions, RHSVal, AstGuard::Expr);
   
   if (Tok.isNot(tok::colon)) {
     Diag(Tok, diag::err_expected_colon_after) << "'case'";
@@ -265,8 +268,8 @@
   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,10 @@
 
   // 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 llvm::SmallVector<StmtTy*, 32> StmtsTy;
+  StmtsTy Stmts;
+  AstArrayGuard StmtGuard(Actions, Stmts, AstArrayGuard::Stmt);
   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
     StmtResult R;
     if (Tok.isNot(tok::kw___extension__)) {
@@ -410,7 +415,7 @@
   
   SourceLocation RBraceLoc = ConsumeBrace();
   return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc,
-                                   &Stmts[0], Stmts.size(), isStmtExpr);
+                                   StmtGuard.take(), Stmts.size(), isStmtExpr);
 }
 
 /// ParseIfStatement
@@ -456,6 +461,7 @@
   } else {
     CondExp = ParseSimpleParenExpression();
   }
+  AstGuard CondGuard(Actions, CondExp);
 
   if (CondExp.isInvalid) {
     SkipUntil(tok::semi);
@@ -528,9 +534,7 @@
   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 +544,7 @@
   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 +672,7 @@
   } else {
     Cond = ParseSimpleParenExpression();
   }
+  AstGuard 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 +690,7 @@
   
   // Read the body statement.
   StmtResult Body = ParseStatement();
+  AstGuard BodyGuard(Actions, Body);
 
   // Pop the body scope if needed.
   if (NeedsInnerScope) ExitScope();
@@ -693,7 +699,7 @@
   
   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 +731,7 @@
   
   // Read the body statement.
   StmtResult Body = ParseStatement();
+  AstGuard BodyGuard(Actions, Body);
 
   // Pop the body scope if needed.
   if (NeedsInnerScope) ExitScope();
@@ -749,12 +756,14 @@
   
   // Parse the condition.
   ExprResult Cond = ParseSimpleParenExpression();
+  AstGuard 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 +819,7 @@
   ExprTy *SecondPart = 0;
   StmtTy *ThirdPart = 0;
   bool ForEach = false;
+  AstGuard FirstGuard(Actions), SecondGuard(Actions), ThirdGuard(Actions);
   
   // Parse the first part of the for specifier.
   if (Tok.is(tok::semi)) {  // for (;
@@ -856,7 +866,10 @@
       SkipUntil(tok::semi);
     }
   }
+  FirstGuard.reset(FirstPart, AstGuard::Stmt);
+  SecondGuard.reset(SecondPart, AstGuard::Expr);
   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 @@
           ThirdPart = R.Val;
       }
     }
+    SecondGuard.reset(SecondPart, AstGuard::Expr);
+    ThirdGuard.reset(ThirdPart, AstGuard::Stmt);
   }
   // Match the ')'.
   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
@@ -918,6 +933,10 @@
   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,10 +1101,13 @@
   ExprResult AsmString = ParseAsmStringLiteral();
   if (AsmString.isInvalid)
     return true;
+  AstGuard AsmGuard(Actions, AsmString);
   
   llvm::SmallVector<std::string, 4> Names;
   llvm::SmallVector<ExprTy*, 4> Constraints;
+  AstArrayGuard ConstraintGuard(Actions, Constraints, AstArrayGuard::Expr);
   llvm::SmallVector<ExprTy*, 4> Exprs;
+  AstArrayGuard ExprGuard(Actions, Exprs, AstArrayGuard::Expr);
   llvm::SmallVector<ExprTy*, 4> Clobbers;
 
   unsigned NumInputs = 0, NumOutputs = 0;
@@ -1097,7 +1119,7 @@
     
     RParenLoc = ConsumeParen();
   } else {
-    // Parse Outputs, if present. 
+    // Parse Outputs, if present.
     if (ParseAsmOperandsOpt(Names, Constraints, Exprs))
         return true;
   
@@ -1136,8 +1158,8 @@
   
   return Actions.ActOnAsmStmt(AsmLoc, isSimple, isVolatile,
                               NumOutputs, NumInputs,
-                              &Names[0], &Constraints[0], &Exprs[0],
-                              AsmString.Val,
+                              &Names[0], ConstraintGuard.take(),
+                              ExprGuard.take(), AsmGuard.take(),
                               Clobbers.size(), &Clobbers[0],
                               RParenLoc);
 }
Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp	(revision 59970)
+++ lib/Parse/ParseDeclCXX.cpp	(working copy)
@@ -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 @@
   
   // 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
@@ -748,6 +749,7 @@
 
   // Parse the optional expression-list.
   ExprListTy ArgExprs;
+  AstArrayGuard ArgGuard(Actions, ArgExprs, AstArrayGuard::Expr);
   CommaLocsTy CommaLocs;
   if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
     SkipUntil(tok::r_paren);
@@ -756,7 +758,7 @@
 
   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, ArgGuard.take(),
+                                     ArgExprs.size(), &CommaLocs[0], RParenLoc);
 }
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp	(revision 59970)
+++ lib/Parse/ParseExprCXX.cpp	(working copy)
@@ -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.
@@ -329,6 +330,7 @@
   SourceLocation LParenLoc = ConsumeParen();
 
   ExprListTy Exprs;
+  AstArrayGuard ExprGuard(Actions, Exprs, AstArrayGuard::Expr);
   CommaLocsTy CommaLocs;
 
   if (Tok.isNot(tok::r_paren)) {
@@ -345,7 +347,7 @@
          "Unexpected number of commas!");
   return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
                                            LParenLoc,
-                                           &Exprs[0], Exprs.size(),
+                                           ExprGuard.take(), Exprs.size(),
                                            &CommaLocs[0], RParenLoc);
 }
 
@@ -660,6 +662,7 @@
   // second form of new-expression. It can't be a new-type-id.
 
   ExprListTy PlacementArgs;
+  AstArrayGuard PlaceGuard(Actions, PlacementArgs, AstArrayGuard::Expr);
   SourceLocation PlacementLParen, PlacementRParen;
 
   TypeTy *Ty = 0;
@@ -707,6 +710,7 @@
   }
 
   ExprListTy ConstructorArgs;
+  AstArrayGuard ConsGuard(Actions, ConstructorArgs, AstArrayGuard::Expr);
   SourceLocation ConstructorLParen, ConstructorRParen;
 
   if (Tok.is(tok::l_paren)) {
@@ -722,9 +726,9 @@
   }
 
   return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
-                             &PlacementArgs[0], PlacementArgs.size(),
+                             PlaceGuard.take(), PlacementArgs.size(),
                              PlacementRParen, ParenTypeId, TyStart, Ty, TyEnd,
-                             ConstructorLParen, &ConstructorArgs[0],
+                             ConstructorLParen, ConsGuard.take(),
                              ConstructorArgs.size(), ConstructorRParen);
 }
 
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp	(revision 59970)
+++ lib/Parse/Parser.cpp	(working copy)
@@ -497,12 +497,9 @@
   if (!FTI.hasPrototype && FTI.NumArgs != 0)
     ParseKNRParamDeclarations(D);
 
-  if (getLang().CPlusPlus && Tok.is(tok::colon)) {
-    
-  }
-
   // We should have either an opening brace or, in a C++ constructor,
   // we may have a colon.
+  // FIXME: In C++, we might also find the 'try' keyword.
   if (Tok.isNot(tok::l_brace) && Tok.isNot(tok::colon)) {
     Diag(Tok, diag::err_expected_fn_body);
 
