diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3486,6 +3486,24 @@ /// parameters. bool isDependentType() const { return isDependentContext(); } + /// Whether this declaration was a definition in some module but was forced + /// to be a declaration. + /// + /// Useful for clients checking if a module has a definition of a specific + /// symbol and not interested in the final AST with deduplicated definitions. + bool isThisDeclarationADemotedDefinition() const { + return TagDeclBits.IsThisDeclarationADemotedDefinition; + } + + /// Mark a definition as a declaration and maintain information it _was_ + /// a definition. + void demoteThisDefinitionToDeclaration() { + assert(isCompleteDefinition() && + "Should demote definitions only, not forward declarations"); + setCompleteDefinition(false); + TagDeclBits.IsThisDeclarationADemotedDefinition = true; + } + /// Starts the definition of this tag declaration. /// /// This method should be invoked at the beginning of the definition diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -1443,10 +1443,14 @@ /// Has the full definition of this type been required by a use somewhere in /// the TU. uint64_t IsCompleteDefinitionRequired : 1; + + /// Whether this tag is a definition which was demoted due to + /// a module merge. + uint64_t IsThisDeclarationADemotedDefinition : 1; }; /// Number of non-inherited bits in TagDeclBitfields. - enum { NumTagDeclBits = 9 }; + enum { NumTagDeclBits = 10 }; /// Stores the bits used by EnumDecl. /// If modified NumEnumDeclBit and the accessor diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4301,6 +4301,7 @@ setEmbeddedInDeclarator(false); setFreeStanding(false); setCompleteDefinitionRequired(false); + TagDeclBits.IsThisDeclarationADemotedDefinition = false; } SourceLocation TagDecl::getOuterLocStart() const { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -773,7 +773,7 @@ } if (OldDef) { Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef)); - ED->setCompleteDefinition(false); + ED->demoteThisDefinitionToDeclaration(); Reader.mergeDefinitionVisibility(OldDef, ED); if (OldDef->getODRHash() != ED->getODRHash()) Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED); @@ -828,7 +828,7 @@ } if (OldDef) { Reader.MergedDeclContexts.insert(std::make_pair(RD, OldDef)); - RD->setCompleteDefinition(false); + RD->demoteThisDefinitionToDeclaration(); Reader.mergeDefinitionVisibility(OldDef, RD); } else { OldDef = RD;