forked from OSchip/llvm-project
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:
parent
c89e4ca3c1
commit
fd8634a09d
clang
include/clang
lib
Sema
Serialization
test/Modules
|
@ -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; }
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 * }
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
Loading…
Reference in New Issue