[modules] Add a flag for TagDecl if it was a definition demoted to a declaration.

For redeclaration chains we maintain an invariant of having only a
single definition in the chain. In a single translation unit we make
sure not to create duplicates. But modules are separate translation
units and they can contain definitions for the same symbol
independently. When we load such modules together, we need to demote
duplicate definitions to keep the AST invariants.

Some AST clients are interested in distinguishing
declaration-that-was-demoted-from-definition and
declaration-that-was-never-a-definition. For that purpose introducing
`IsThisDeclarationADemotedDefinition`. No functional change intended.

rdar://84677782

Differential Revision: https://reviews.llvm.org/D118855
This commit is contained in:
Volodymyr Sapsai 2022-02-01 15:03:59 -08:00
parent bca13174bc
commit fa4a0f1d31
4 changed files with 26 additions and 3 deletions

View File

@ -3486,6 +3486,24 @@ public:
/// 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

View File

@ -1443,10 +1443,14 @@ class DeclContext {
/// 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

View File

@ -4301,6 +4301,7 @@ TagDecl::TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
setEmbeddedInDeclarator(false);
setFreeStanding(false);
setCompleteDefinitionRequired(false);
TagDeclBits.IsThisDeclarationADemotedDefinition = false;
}
SourceLocation TagDecl::getOuterLocStart() const {

View File

@ -773,7 +773,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
}
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 @@ void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) {
}
if (OldDef) {
Reader.MergedDeclContexts.insert(std::make_pair(RD, OldDef));
RD->setCompleteDefinition(false);
RD->demoteThisDefinitionToDeclaration();
Reader.mergeDefinitionVisibility(OldDef, RD);
} else {
OldDef = RD;