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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156289 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/RAIIObjectsForParser.h b/lib/Parse/RAIIObjectsForParser.h
index ef17aee..f5a6f8f 100644
--- a/lib/Parse/RAIIObjectsForParser.h
+++ b/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