Refactor DelayedDiagnostics so that it keeps diagnostics in
separate pools owned by the RAII objects that keep pushing
decl state.  This gives us quite a bit more flexibility.

llvm-svn: 156289
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp
index c7b29d9..2a64be5 100644
--- a/clang/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp
@@ -16,6 +16,7 @@
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/Scope.h"
 #include "clang/AST/DeclTemplate.h"
+#include "RAIIObjectsForParser.h"
 using namespace clang;
 
 /// ParseCXXInlineMethodDef - We parsed and verified that the specified
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 12941b0..dbf35b1 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -2560,7 +2560,7 @@
   bool FirstDeclarator = true;
   SourceLocation CommaLoc;
   while (1) {
-    ParsingDeclRAIIObject PD(*this);
+    ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
     FieldDeclarator DeclaratorInfo(DS);
     DeclaratorInfo.D.setCommaLoc(CommaLoc);
 
@@ -3067,7 +3067,7 @@
 
     SourceLocation EqualLoc;
     ExprResult AssignedVal;
-    ParsingDeclRAIIObject PD(*this);
+    ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
     
     if (Tok.is(tok::equal)) {
       EqualLoc = ConsumeToken();
diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp
index dd82599..1baebd5 100644
--- a/clang/lib/Parse/ParseObjc.cpp
+++ b/clang/lib/Parse/ParseObjc.cpp
@@ -965,7 +965,7 @@
                                   tok::TokenKind mType,
                                   tok::ObjCKeywordKind MethodImplKind,
                                   bool MethodDefinition) {
-  ParsingDeclRAIIObject PD(*this);
+  ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
 
   if (Tok.is(tok::code_completion)) {
     Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, 
diff --git a/clang/lib/Parse/ParseTemplate.cpp b/clang/lib/Parse/ParseTemplate.cpp
index d906782..664ba8b 100644
--- a/clang/lib/Parse/ParseTemplate.cpp
+++ b/clang/lib/Parse/ParseTemplate.cpp
@@ -90,7 +90,8 @@
 
   // Tell the action that names should be checked in the context of
   // the declaration to come.
-  ParsingDeclRAIIObject ParsingTemplateParams(*this);
+  ParsingDeclRAIIObject
+    ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);
 
   // Parse multiple levels of template headers within this template
   // parameter scope, e.g.,
@@ -213,10 +214,11 @@
     return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd,
                                             prefixAttrs);
 
-  // Parse the declaration specifiers, stealing the accumulated
-  // diagnostics from the template parameters.
+  // Parse the declaration specifiers, stealing any diagnostics from
+  // the template parameters.
   ParsingDeclSpec DS(*this, &DiagsFromTParams);
 
+  // Move the attributes from the prefix into the DS.
   DS.takeAttributesFrom(prefixAttrs);
 
   ParseDeclarationSpecifiers(DS, TemplateInfo, AS,
@@ -1132,7 +1134,8 @@
                                          SourceLocation &DeclEnd,
                                          AccessSpecifier AS) {
   // This isn't really required here.
-  ParsingDeclRAIIObject ParsingTemplateParams(*this);
+  ParsingDeclRAIIObject
+    ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent);
 
   return ParseSingleDeclarationAfterTemplate(Context,
                                              ParsedTemplateInfo(ExternLoc,
diff --git a/clang/lib/Parse/RAIIObjectsForParser.h b/clang/lib/Parse/RAIIObjectsForParser.h
index ef17aee..f5a6f8f 100644
--- a/clang/lib/Parse/RAIIObjectsForParser.h
+++ b/clang/lib/Parse/RAIIObjectsForParser.h
@@ -16,13 +16,156 @@
 #define LLVM_CLANG_PARSE_RAII_OBJECTS_FOR_PARSER_H
 
 #include "clang/Parse/ParseDiagnostic.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Sema/DelayedDiagnostic.h"
+#include "clang/Sema/Sema.h"
 
 namespace clang {
-  // TODO: move ParsingDeclRAIIObject here.
   // TODO: move ParsingClassDefinition here.
   // TODO: move TentativeParsingAction here.
-  
-  
+
+  /// \brief RAII object used to inform the actions that we're
+  /// currently parsing a declaration.  This is active when parsing a
+  /// variable's initializer, but not when parsing the body of a
+  /// class or function definition.
+  class ParsingDeclRAIIObject {
+    Sema &Actions;
+    sema::DelayedDiagnosticPool DiagnosticPool;
+    Sema::ParsingDeclState State;
+    bool Popped;
+
+    // Do not implement.
+    ParsingDeclRAIIObject(const ParsingDeclRAIIObject &other);
+    ParsingDeclRAIIObject &operator=(const ParsingDeclRAIIObject &other);
+
+  public:
+    enum NoParent_t { NoParent };
+    ParsingDeclRAIIObject(Parser &P, NoParent_t _)
+        : Actions(P.getActions()), DiagnosticPool(NULL) {
+      push();
+    }
+
+    /// Creates a RAII object whose pool is optionally parented by another.
+    ParsingDeclRAIIObject(Parser &P,
+                          const sema::DelayedDiagnosticPool *parentPool)
+        : Actions(P.getActions()), DiagnosticPool(parentPool) {
+      push();
+    }
+
+    /// Creates a RAII object and, optionally, initialize its
+    /// diagnostics pool by stealing the diagnostics from another
+    /// RAII object (which is assumed to be the current top pool).
+    ParsingDeclRAIIObject(Parser &P, ParsingDeclRAIIObject *other)
+        : Actions(P.getActions()),
+          DiagnosticPool(other ? other->DiagnosticPool.getParent() : NULL) {
+      if (other) {
+        DiagnosticPool.steal(other->DiagnosticPool);
+        other->abort();
+      }
+      push();
+    }
+
+    ~ParsingDeclRAIIObject() {
+      abort();
+    }
+
+    sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() {
+      return DiagnosticPool;
+    }
+    const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
+      return DiagnosticPool;
+    }
+
+    /// Resets the RAII object for a new declaration.
+    void reset() {
+      abort();
+      push();
+    }
+
+    /// Signals that the context was completed without an appropriate
+    /// declaration being parsed.
+    void abort() {
+      pop(0);
+    }
+
+    void complete(Decl *D) {
+      assert(!Popped && "ParsingDeclaration has already been popped!");
+      pop(D);
+    }
+
+  private:
+    void steal(ParsingDeclRAIIObject &Other) {
+      DiagnosticPool.steal(Other.DiagnosticPool);
+      State = Other.State;
+      Popped = Other.Popped;
+      Other.Popped = true;
+    }
+
+    void push() {
+      State = Actions.PushParsingDeclaration(DiagnosticPool);
+      Popped = false;
+    }
+
+    void pop(Decl *D) {
+      if (!Popped) {
+        Actions.PopParsingDeclaration(State, D);
+        Popped = true;
+      }
+    }
+  };
+
+  /// A class for parsing a DeclSpec.
+  class ParsingDeclSpec : public DeclSpec {
+    ParsingDeclRAIIObject ParsingRAII;
+
+  public:
+    ParsingDeclSpec(Parser &P)
+      : DeclSpec(P.getAttrFactory()),
+        ParsingRAII(P, ParsingDeclRAIIObject::NoParent) {}
+    ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII)
+      : DeclSpec(P.getAttrFactory()),
+        ParsingRAII(P, RAII) {}
+
+    const sema::DelayedDiagnosticPool &getDelayedDiagnosticPool() const {
+      return ParsingRAII.getDelayedDiagnosticPool();
+    }
+
+    void complete(Decl *D) {
+      ParsingRAII.complete(D);
+    }
+
+    void abort() {
+      ParsingRAII.abort();
+    }
+  };
+
+  /// A class for parsing a declarator.
+  class ParsingDeclarator : public Declarator {
+    ParsingDeclRAIIObject ParsingRAII;
+
+  public:
+    ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C)
+      : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) {
+    }
+
+    const ParsingDeclSpec &getDeclSpec() const {
+      return static_cast<const ParsingDeclSpec&>(Declarator::getDeclSpec());
+    }
+
+    ParsingDeclSpec &getMutableDeclSpec() const {
+      return const_cast<ParsingDeclSpec&>(getDeclSpec());
+    }
+
+    void clear() {
+      Declarator::clear();
+      ParsingRAII.reset();
+    }
+
+    void complete(Decl *D) {
+      ParsingRAII.complete(D);
+    }
+  };
+
   /// ExtensionRAIIObject - This saves the state of extension warnings when
   /// constructed and disables them.  When destructed, it restores them back to
   /// the way they used to be.  This is used to handle __extension__ in the