[modules] Handle defining a tag with a typedef name for linkage purposes on top of an existing imported-but-not-visible definition.
llvm-svn: 233345
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e9c40aa..9bbfeaf 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1836,11 +1836,18 @@
// Declarations of the same entity are not ignored, even if they have
// different linkages.
- if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old))
+ if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old)) {
if (Context.hasSameType(OldTD->getUnderlyingType(),
Decl->getUnderlyingType()))
continue;
+ // If both declarations give a tag declaration a typedef name for linkage
+ // purposes, then they declare the same entity.
+ if (OldTD->getAnonDeclWithTypedefName() &&
+ Decl->getAnonDeclWithTypedefName())
+ continue;
+ }
+
if (!Old->isExternallyVisible())
Filter.erase();
}
@@ -1950,6 +1957,29 @@
if (Old->isInvalidDecl())
return New->setInvalidDecl();
+ if (auto *OldTD = dyn_cast<TypedefNameDecl>(Old)) {
+ auto *OldTag = OldTD->getAnonDeclWithTypedefName();
+ auto *NewTag = New->getAnonDeclWithTypedefName();
+ NamedDecl *Hidden = nullptr;
+ if (getLangOpts().CPlusPlus && OldTag && NewTag &&
+ OldTag->getCanonicalDecl() != NewTag->getCanonicalDecl() &&
+ !hasVisibleDefinition(OldTag, &Hidden)) {
+ // There is a definition of this tag, but it is not visible. Use it
+ // instead of our tag.
+ New->setTypeForDecl(OldTD->getTypeForDecl());
+ if (OldTD->isModed())
+ New->setModedTypeSourceInfo(OldTD->getTypeSourceInfo(),
+ OldTD->getUnderlyingType());
+ else
+ New->setTypeSourceInfo(OldTD->getTypeSourceInfo());
+
+ // Make the old tag definition visible.
+ if (auto *Listener = getASTMutationListener())
+ Listener->RedefinedHiddenDefinition(Hidden, NewTag->getLocation());
+ Hidden->setHidden(false);
+ }
+ }
+
// If the typedef types are not identical, reject them in all languages and
// with any extensions enabled.
if (isIncompatibleTypedef(Old, New))
@@ -2019,7 +2049,6 @@
Diag(New->getLocation(), diag::ext_redefinition_of_typedef)
<< New->getDeclName();
Diag(Old->getLocation(), diag::note_previous_definition);
- return;
}
/// DeclhasAttr - returns true if decl Declaration already has the target