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).

llvm-svn: 193219
This commit is contained in:
Richard Smith 2013-10-23 02:17:46 +00:00
parent c89e4ca3c1
commit fd8634a09d
11 changed files with 118 additions and 34 deletions

View File

@ -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; }

View File

@ -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,

View File

@ -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;

View File

@ -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)

View File

@ -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:

View File

@ -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(

View File

@ -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);

View File

@ -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 * }
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;