From 565bf30bf5607b9740d288d8d9c45cf38ea75298 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Sun, 24 Oct 2010 17:26:50 +0000 Subject: [PATCH] Start fleshing out ASTMutationListener; notify when a tag definition is completed. 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 | 4 ++++ include/clang/Serialization/ASTWriter.h | 3 +++ lib/AST/Decl.cpp | 4 ++++ lib/Serialization/ASTCommon.h | 4 ++++ lib/Serialization/ASTReaderDecl.cpp | 14 +++++++++++- lib/Serialization/ASTWriter.cpp | 29 +++++++++++++++++++++++++ test/PCH/chain-cxx.cpp | 1 - 7 files changed, 57 insertions(+), 2 deletions(-) diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index ea09b0c202..72e4571cc8 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -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 diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index d6b1467576..7b6b00155d 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -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 diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index fc5b57f148..42e762d56a 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -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 { diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h index a0e2ecd8aa..36958c7500 100644 --- a/lib/Serialization/ASTCommon.h +++ b/lib/Serialization/ASTCommon.h @@ -20,6 +20,10 @@ namespace clang { namespace serialization { +enum DeclUpdateKind { + UPD_CXX_SET_DEFINITIONDATA +}; + TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); template diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 45d729a2fc..f4568a7e70 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -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(D); + CXXRecordDecl * + DefinitionDecl = cast(Reader.GetDecl(Record[Idx++])); + assert(!RD->DefinitionData && "DefinitionData is already set!"); + InitializeCXXDefinitionData(RD, DefinitionDecl, Record, Idx); + break; + } + } + } } diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index c6df2dd95d..436525f199 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -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(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(*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 + } + } + } +} diff --git a/test/PCH/chain-cxx.cpp b/test/PCH/chain-cxx.cpp index 8c17fee41b..d269de529f 100644 --- a/test/PCH/chain-cxx.cpp +++ b/test/PCH/chain-cxx.cpp @@ -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 -- 2.40.0