diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e9c40aa2e5d..9bbfeaf19ef 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1836,11 +1836,18 @@ static void filterNonConflictingPreviousTypedefDecls(ASTContext &Context, // 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 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { 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 @@ void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { 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 |