From f06a2893bc9778857295c64ee32b4a899a338480 Mon Sep 17 00:00:00 2001 From: Richard Smith <richard-llvm@metafoo.co.uk> Date: Wed, 23 Oct 2013 02:17:46 +0000 Subject: [PATCH] Make UsingShadowDecls redeclarable. This fixes some visibility problems with modules. With this fixed, I no longer see any test regressions in the libc++ test suite when enabling a single-module module.map for libc++ (other than issues with my system headers). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@193219 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclCXX.h | 28 +++++++++++++-- include/clang/Sema/Sema.h | 6 ++-- lib/Sema/SemaDeclCXX.cpp | 44 ++++++++++++++---------- lib/Sema/SemaTemplateInstantiateDecl.cpp | 21 ++++++----- lib/Serialization/ASTCommon.cpp | 2 +- lib/Serialization/ASTReaderDecl.cpp | 16 ++++++++- lib/Serialization/ASTWriterDecl.cpp | 1 + test/Modules/Inputs/module.map | 5 +++ test/Modules/Inputs/using-decl-a.h | 10 ++++++ test/Modules/Inputs/using-decl-b.h | 11 ++++++ test/Modules/using-decl.cpp | 8 +++++ 11 files changed, 118 insertions(+), 34 deletions(-) create mode 100644 test/Modules/Inputs/using-decl-a.h create mode 100644 test/Modules/Inputs/using-decl-b.h create mode 100644 test/Modules/using-decl.cpp diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index bbf35604402..bb97b55f123 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -2676,7 +2676,7 @@ public: /// // Also creates a UsingShadowDecl for A::foo() in B /// } /// \endcode -class UsingShadowDecl : public NamedDecl { +class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> { virtual void anchor(); /// The referenced declaration. @@ -2699,6 +2699,17 @@ class UsingShadowDecl : public NamedDecl { setImplicit(); } + typedef Redeclarable<UsingShadowDecl> redeclarable_base; + virtual UsingShadowDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } + virtual UsingShadowDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual UsingShadowDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } + public: static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, UsingDecl *Using, @@ -2707,7 +2718,20 @@ public: } static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); - + + typedef redeclarable_base::redecl_iterator redecl_iterator; + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; + + virtual UsingShadowDecl *getCanonicalDecl() { + return getFirstDecl(); + } + virtual const UsingShadowDecl *getCanonicalDecl() const { + return getFirstDecl(); + } + /// \brief Gets the underlying declaration which has been brought into the /// local scope. NamedDecl *getTargetDecl() const { return Underlying; } diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 0c68e5c37a0..abbf512f3c1 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -3640,9 +3640,11 @@ public: void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow); bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target, - const LookupResult &PreviousDecls); + const LookupResult &PreviousDecls, + UsingShadowDecl *&PrevShadow); UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD, - NamedDecl *Target); + NamedDecl *Target, + UsingShadowDecl *PrevDecl); bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc, bool HasTypenameKeyword, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index f5bb3511f22..221c53f03f6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -7073,20 +7073,15 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, /// \brief Determine whether a using declaration considers the given /// declarations as "equivalent", e.g., if they are redeclarations of /// the same entity or are both typedefs of the same type. -static bool -IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2, - bool &SuppressRedeclaration) { - if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) { - SuppressRedeclaration = false; +static bool +IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) { + if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) return true; - } if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1)) - if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) { - SuppressRedeclaration = true; + if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) return Context.hasSameType(TD1->getUnderlyingType(), TD2->getUnderlyingType()); - } return false; } @@ -7095,7 +7090,8 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2, /// Determines whether to create a using shadow decl for a particular /// decl, given the set of decls existing prior to this using lookup. bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, - const LookupResult &Previous) { + const LookupResult &Previous, + UsingShadowDecl *&PrevShadow) { // Diagnose finding a decl which is not from a base class of the // current class. We do this now because there are cases where this // function will silently decide not to build a shadow decl, which @@ -7155,16 +7151,22 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // FIXME: but we might be increasing its access, in which case we // should redeclare it. NamedDecl *NonTag = 0, *Tag = 0; + bool FoundEquivalentDecl = false; for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); I != E; ++I) { NamedDecl *D = (*I)->getUnderlyingDecl(); - bool Result; - if (IsEquivalentForUsingDecl(Context, D, Target, Result)) - return Result; + if (IsEquivalentForUsingDecl(Context, D, Target)) { + if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I)) + PrevShadow = Shadow; + FoundEquivalentDecl = true; + } (isa<TagDecl>(D) ? Tag : NonTag) = D; } + if (FoundEquivalentDecl) + return false; + if (Target->isFunctionOrFunctionTemplate()) { FunctionDecl *FD; if (isa<FunctionTemplateDecl>(Target)) @@ -7223,7 +7225,8 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, /// Builds a shadow declaration corresponding to a 'using' declaration. UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, UsingDecl *UD, - NamedDecl *Orig) { + NamedDecl *Orig, + UsingShadowDecl *PrevDecl) { // If we resolved to another shadow declaration, just coalesce them. NamedDecl *Target = Orig; @@ -7231,16 +7234,18 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, Target = cast<UsingShadowDecl>(Target)->getTargetDecl(); assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration"); } - + UsingShadowDecl *Shadow = UsingShadowDecl::Create(Context, CurContext, UD->getLocation(), UD, Target); UD->addShadowDecl(Shadow); - + Shadow->setAccess(UD->getAccess()); if (Orig->isInvalidDecl() || UD->isInvalidDecl()) Shadow->setInvalidDecl(); - + + Shadow->setPreviousDecl(PrevDecl); + if (S) PushOnScopeChains(Shadow, S); else @@ -7504,8 +7509,9 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, } for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { - if (!CheckUsingShadowDecl(UD, *I, Previous)) - BuildUsingShadowDecl(S, UD, *I); + UsingShadowDecl *PrevDecl = 0; + if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl)) + BuildUsingShadowDecl(S, UD, *I, PrevDecl); } return UD; diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index b5171640009..d0c3ac69144 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2152,19 +2152,22 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) { I != E; ++I) { UsingShadowDecl *Shadow = *I; NamedDecl *InstTarget = - cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl( - Shadow->getLocation(), - Shadow->getTargetDecl(), - TemplateArgs)); + cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl( + Shadow->getLocation(), Shadow->getTargetDecl(), TemplateArgs)); if (!InstTarget) return 0; - if (CheckRedeclaration && - SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev)) - continue; + UsingShadowDecl *PrevDecl = 0; + if (CheckRedeclaration) { + if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl)) + continue; + } else if (UsingShadowDecl *OldPrev = Shadow->getPreviousDecl()) { + PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl( + Shadow->getLocation(), OldPrev, TemplateArgs)); + } - UsingShadowDecl *InstShadow - = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget); + UsingShadowDecl *InstShadow = + SemaRef.BuildUsingShadowDecl(/*Scope*/0, NewUD, InstTarget, PrevDecl); SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow); if (isFunctionScope) diff --git a/lib/Serialization/ASTCommon.cpp b/lib/Serialization/ASTCommon.cpp index 79bba0cb94f..a8176878dc4 100644 --- a/lib/Serialization/ASTCommon.cpp +++ b/lib/Serialization/ASTCommon.cpp @@ -165,6 +165,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::CXXConstructor: case Decl::CXXDestructor: case Decl::CXXConversion: + case Decl::UsingShadow: case Decl::Var: case Decl::FunctionTemplate: case Decl::ClassTemplate: @@ -192,7 +193,6 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::NonTypeTemplateParm: case Decl::TemplateTemplateParm: case Decl::Using: - case Decl::UsingShadow: case Decl::ObjCMethod: case Decl::ObjCCategory: case Decl::ObjCCategoryImpl: diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index e68c7fc6f9f..463af777986 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1134,12 +1134,14 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { } void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) { + RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); D->setTargetDecl(ReadDeclAs<NamedDecl>(Record, Idx)); D->UsingOrNextShadow = ReadDeclAs<NamedDecl>(Record, Idx); UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>(Record, Idx); if (Pattern) Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern); + mergeRedeclarable(D, Redecl); } void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { @@ -2151,6 +2153,12 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { // FIXME: Also check the value is odr-equivalent. return true; + // Using shadow declarations with the same target match. + if (UsingShadowDecl *USX = dyn_cast<UsingShadowDecl>(X)) { + UsingShadowDecl *USY = cast<UsingShadowDecl>(Y); + return USX->getTargetDecl() == USY->getTargetDecl(); + } + // FIXME: Many other cases to implement. return false; } @@ -2258,6 +2266,8 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) { VD->RedeclLink.setNext(cast<VarDecl>(previous)); } else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { TD->RedeclLink.setNext(cast<TypedefNameDecl>(previous)); + } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) { + USD->RedeclLink.setNext(cast<UsingShadowDecl>(previous)); } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { ID->RedeclLink.setNext(cast<ObjCInterfaceDecl>(previous)); } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { @@ -2285,7 +2295,7 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { TD->RedeclLink = Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest)); } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - FD->RedeclLink + FD->RedeclLink = Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest)); } else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { VD->RedeclLink @@ -2294,6 +2304,10 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) { TD->RedeclLink = Redeclarable<TypedefNameDecl>::LatestDeclLink( cast<TypedefNameDecl>(Latest)); + } else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) { + USD->RedeclLink + = Redeclarable<UsingShadowDecl>::LatestDeclLink( + cast<UsingShadowDecl>(Latest)); } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { ID->RedeclLink = Redeclarable<ObjCInterfaceDecl>::LatestDeclLink( diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 2d5ab7bb3a0..bee1786a0ac 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -938,6 +938,7 @@ void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) { } void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) { + VisitRedeclarable(D); VisitNamedDecl(D); Writer.AddDeclRef(D->getTargetDecl(), Record); Writer.AddDeclRef(D->UsingOrNextShadow, Record); diff --git a/test/Modules/Inputs/module.map b/test/Modules/Inputs/module.map index 12da7a649ad..cb4d339f7e4 100644 --- a/test/Modules/Inputs/module.map +++ b/test/Modules/Inputs/module.map @@ -258,3 +258,8 @@ module warning { module initializer_list { header "initializer_list" } + +module using_decl { + module a { header "using-decl-a.h" export * } + module b { header "using-decl-b.h" export * } +} diff --git a/test/Modules/Inputs/using-decl-a.h b/test/Modules/Inputs/using-decl-a.h new file mode 100644 index 00000000000..85a4788e764 --- /dev/null +++ b/test/Modules/Inputs/using-decl-a.h @@ -0,0 +1,10 @@ +typedef int using_decl_type; +int using_decl_var; + +namespace UsingDecl { + using ::using_decl_type; + using ::using_decl_var; + + namespace A { typedef int inner; } + using A::inner; +} diff --git a/test/Modules/Inputs/using-decl-b.h b/test/Modules/Inputs/using-decl-b.h new file mode 100644 index 00000000000..b82526f39ff --- /dev/null +++ b/test/Modules/Inputs/using-decl-b.h @@ -0,0 +1,11 @@ +namespace UsingDecl { + namespace B { typedef int inner; } + using B::inner; +} + +#include "using-decl-a.h" + +namespace UsingDecl { + using ::using_decl_type; + using ::using_decl_var; +} diff --git a/test/Modules/using-decl.cpp b/test/Modules/using-decl.cpp new file mode 100644 index 00000000000..4432738f060 --- /dev/null +++ b/test/Modules/using-decl.cpp @@ -0,0 +1,8 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -verify + +@import using_decl.a; + +// expected-no-diagnostics +UsingDecl::using_decl_type x = UsingDecl::using_decl_var; +UsingDecl::inner y = x; -- GitLab