]> granicus.if.org Git - clang/commitdiff
Start fleshing out ASTMutationListener; notify when a tag definition is completed.
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 24 Oct 2010 17:26:50 +0000 (17:26 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sun, 24 Oct 2010 17:26:50 +0000 (17:26 +0000)
In that case a chained PCH will record the updates to the DefinitionData pointer of forward references.
If a forward reference mutated into a definition re-write it into the chained PCH, this is too big of a change.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117239 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ASTMutationListener.h
include/clang/Serialization/ASTWriter.h
lib/AST/Decl.cpp
lib/Serialization/ASTCommon.h
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriter.cpp
test/PCH/chain-cxx.cpp

index ea09b0c202ab05a287728e0561623ed006db2b2b..72e4571cc8164dc6ab4b3872eaaa4a1ed4495df6 100644 (file)
@@ -14,6 +14,7 @@
 #define LLVM_CLANG_AST_ASTMUTATIONLISTENER_H
 
 namespace clang {
+  class TagDecl;
   class CXXRecordDecl;
   class CXXMethodDecl;
 
@@ -23,6 +24,9 @@ namespace clang {
 class ASTMutationListener {
 public:
   virtual ~ASTMutationListener();
+
+  /// \brief A new TagDecl definition was completed.
+  virtual void CompletedTagDefinition(const TagDecl *D) { }
 };
 
 } // end namespace clang
index d6b146757695c73037689ef7cc90b9ef3a14ae03..7b6b00155d66caf84d9956356b3afa2fb9f69afe 100644 (file)
@@ -511,6 +511,9 @@ public:
   void DeclRead(serialization::DeclID ID, const Decl *D);
   void SelectorRead(serialization::SelectorID ID, Selector Sel);
   void MacroDefinitionRead(serialization::MacroID ID, MacroDefinition *MD);
+
+  // ASTMutationListener implementation.
+  virtual void CompletedTagDefinition(const TagDecl *D);
 };
 
 /// \brief AST and semantic-analysis consumer that generates a
index fc5b57f1485b9850e327263dbff5959917e16f6a..42e762d56ab676fc5eb4b0ad7dfd445cf2bef10c 100644 (file)
@@ -21,6 +21,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/ASTMutationListener.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/Specifiers.h"
@@ -1713,6 +1714,9 @@ void TagDecl::completeDefinition() {
 
   IsDefinition = true;
   IsBeingDefined = false;
+
+  if (ASTMutationListener *L = getASTMutationListener())
+    L->CompletedTagDefinition(this);
 }
 
 TagDecl* TagDecl::getDefinition() const {
index a0e2ecd8aa1bb91e3c682c4dcde4c1321f65d926..36958c75009826b2b088996210e27f9b5aee27ad 100644 (file)
@@ -20,6 +20,10 @@ namespace clang {
 
 namespace serialization {
 
+enum DeclUpdateKind {
+  UPD_CXX_SET_DEFINITIONDATA
+};
+
 TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT);
 
 template <typename IdxForTypeTy>
index 45d729a2fc72c78236b76792e7b7394ee0bf24c5..f4568a7e70e531b9343d448c4d869e94217e5412 100644 (file)
@@ -1588,5 +1588,17 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) {
 }
 
 void ASTDeclReader::UpdateDecl(Decl *D, const RecordData &Record) {
-  // No update is tracked yet.
+  unsigned Idx = 0;
+  while (Idx < Record.size()) {
+    switch ((DeclUpdateKind)Record[Idx++]) {
+    case UPD_CXX_SET_DEFINITIONDATA: {
+      CXXRecordDecl *RD = cast<CXXRecordDecl>(D);
+      CXXRecordDecl *
+          DefinitionDecl = cast<CXXRecordDecl>(Reader.GetDecl(Record[Idx++]));
+      assert(!RD->DefinitionData && "DefinitionData is already set!");
+      InitializeCXXDefinitionData(RD, DefinitionDecl, Record, Idx);
+      break;
+    }
+    }
+  }
 }
index c6df2dd95d33a785eb0699ab6bc45b66ede22d92..436525f1999ea4333222fe6ceca1bf31895d1b80 100644 (file)
@@ -3297,3 +3297,32 @@ void ASTWriter::MacroDefinitionRead(serialization::MacroID ID,
                                     MacroDefinition *MD) {
   MacroDefinitions[MD] = ID;
 }
+
+void ASTWriter::CompletedTagDefinition(const TagDecl *D) {
+  assert(D->isDefinition());
+  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
+    // We are interested when a PCH decl is modified.
+    if (RD->getPCHLevel() > 0) {
+      // A forward reference was mutated into a definition. Rewrite it.
+      // FIXME: This happens during template instantiation, should we
+      // have created a new definition decl instead ?
+      DeclsToRewrite.insert(RD);
+    }
+
+    for (CXXRecordDecl::redecl_iterator
+           I = RD->redecls_begin(), E = RD->redecls_end(); I != E; ++I) {
+      CXXRecordDecl *Redecl = cast<CXXRecordDecl>(*I);
+      if (Redecl == RD)
+        continue;
+
+      // We are interested when a PCH decl is modified.
+      if (Redecl->getPCHLevel() > 0) {
+        UpdateRecord &Record = DeclUpdates[Redecl];
+        Record.push_back(UPD_CXX_SET_DEFINITIONDATA);
+        assert(Redecl->DefinitionData);
+        assert(Redecl->DefinitionData->Definition == D);
+        AddDeclRef(D, Record); // the DefinitionDecl
+      }
+    }
+  }
+}
index 8c17fee41b99d22e975cf43ace5b8f7e3eeb62fa..d269de529fba3a4d6ff1a85af2c1bee5e95c9b96 100644 (file)
@@ -7,7 +7,6 @@
 // RUN: %clang_cc1 -x c++-header -emit-pch -o %t1 %s
 // RUN: %clang_cc1 -x c++-header -emit-pch -o %t2 %s -include-pch %t1 -chained-pch
 // RUN: %clang_cc1 -fsyntax-only -verify -include-pch %t2 %s
-// XFAIL: *
 
 #ifndef HEADER1
 #define HEADER1