Skip to content

Commit fd8634a

Browse files
committed
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
1 parent c89e4ca commit fd8634a

File tree

11 files changed

+118
-34
lines changed

11 files changed

+118
-34
lines changed

clang/include/clang/AST/DeclCXX.h

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2676,7 +2676,7 @@ class NamespaceAliasDecl : public NamedDecl {
26762676
/// // Also creates a UsingShadowDecl for A::foo() in B
26772677
/// }
26782678
/// \endcode
2679-
class UsingShadowDecl : public NamedDecl {
2679+
class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
26802680
virtual void anchor();
26812681

26822682
/// The referenced declaration.
@@ -2699,6 +2699,17 @@ class UsingShadowDecl : public NamedDecl {
26992699
setImplicit();
27002700
}
27012701

2702+
typedef Redeclarable<UsingShadowDecl> redeclarable_base;
2703+
virtual UsingShadowDecl *getNextRedeclaration() {
2704+
return RedeclLink.getNext();
2705+
}
2706+
virtual UsingShadowDecl *getPreviousDeclImpl() {
2707+
return getPreviousDecl();
2708+
}
2709+
virtual UsingShadowDecl *getMostRecentDeclImpl() {
2710+
return getMostRecentDecl();
2711+
}
2712+
27022713
public:
27032714
static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC,
27042715
SourceLocation Loc, UsingDecl *Using,
@@ -2707,7 +2718,20 @@ class UsingShadowDecl : public NamedDecl {
27072718
}
27082719

27092720
static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID);
2710-
2721+
2722+
typedef redeclarable_base::redecl_iterator redecl_iterator;
2723+
using redeclarable_base::redecls_begin;
2724+
using redeclarable_base::redecls_end;
2725+
using redeclarable_base::getPreviousDecl;
2726+
using redeclarable_base::getMostRecentDecl;
2727+
2728+
virtual UsingShadowDecl *getCanonicalDecl() {
2729+
return getFirstDecl();
2730+
}
2731+
virtual const UsingShadowDecl *getCanonicalDecl() const {
2732+
return getFirstDecl();
2733+
}
2734+
27112735
/// \brief Gets the underlying declaration which has been brought into the
27122736
/// local scope.
27132737
NamedDecl *getTargetDecl() const { return Underlying; }

clang/include/clang/Sema/Sema.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3640,9 +3640,11 @@ class Sema {
36403640

36413641
void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
36423642
bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target,
3643-
const LookupResult &PreviousDecls);
3643+
const LookupResult &PreviousDecls,
3644+
UsingShadowDecl *&PrevShadow);
36443645
UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD,
3645-
NamedDecl *Target);
3646+
NamedDecl *Target,
3647+
UsingShadowDecl *PrevDecl);
36463648

36473649
bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
36483650
bool HasTypenameKeyword,

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7073,20 +7073,15 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S,
70737073
/// \brief Determine whether a using declaration considers the given
70747074
/// declarations as "equivalent", e.g., if they are redeclarations of
70757075
/// the same entity or are both typedefs of the same type.
7076-
static bool
7077-
IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
7078-
bool &SuppressRedeclaration) {
7079-
if (D1->getCanonicalDecl() == D2->getCanonicalDecl()) {
7080-
SuppressRedeclaration = false;
7076+
static bool
7077+
IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) {
7078+
if (D1->getCanonicalDecl() == D2->getCanonicalDecl())
70817079
return true;
7082-
}
70837080

70847081
if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1))
7085-
if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2)) {
7086-
SuppressRedeclaration = true;
7082+
if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(D2))
70877083
return Context.hasSameType(TD1->getUnderlyingType(),
70887084
TD2->getUnderlyingType());
7089-
}
70907085

70917086
return false;
70927087
}
@@ -7095,7 +7090,8 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2,
70957090
/// Determines whether to create a using shadow decl for a particular
70967091
/// decl, given the set of decls existing prior to this using lookup.
70977092
bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
7098-
const LookupResult &Previous) {
7093+
const LookupResult &Previous,
7094+
UsingShadowDecl *&PrevShadow) {
70997095
// Diagnose finding a decl which is not from a base class of the
71007096
// current class. We do this now because there are cases where this
71017097
// function will silently decide not to build a shadow decl, which
@@ -7155,16 +7151,22 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
71557151
// FIXME: but we might be increasing its access, in which case we
71567152
// should redeclare it.
71577153
NamedDecl *NonTag = 0, *Tag = 0;
7154+
bool FoundEquivalentDecl = false;
71587155
for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
71597156
I != E; ++I) {
71607157
NamedDecl *D = (*I)->getUnderlyingDecl();
7161-
bool Result;
7162-
if (IsEquivalentForUsingDecl(Context, D, Target, Result))
7163-
return Result;
7158+
if (IsEquivalentForUsingDecl(Context, D, Target)) {
7159+
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(*I))
7160+
PrevShadow = Shadow;
7161+
FoundEquivalentDecl = true;
7162+
}
71647163

71657164
(isa<TagDecl>(D) ? Tag : NonTag) = D;
71667165
}
71677166

7167+
if (FoundEquivalentDecl)
7168+
return false;
7169+
71687170
if (Target->isFunctionOrFunctionTemplate()) {
71697171
FunctionDecl *FD;
71707172
if (isa<FunctionTemplateDecl>(Target))
@@ -7223,24 +7225,27 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
72237225
/// Builds a shadow declaration corresponding to a 'using' declaration.
72247226
UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
72257227
UsingDecl *UD,
7226-
NamedDecl *Orig) {
7228+
NamedDecl *Orig,
7229+
UsingShadowDecl *PrevDecl) {
72277230

72287231
// If we resolved to another shadow declaration, just coalesce them.
72297232
NamedDecl *Target = Orig;
72307233
if (isa<UsingShadowDecl>(Target)) {
72317234
Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
72327235
assert(!isa<UsingShadowDecl>(Target) && "nested shadow declaration");
72337236
}
7234-
7237+
72357238
UsingShadowDecl *Shadow
72367239
= UsingShadowDecl::Create(Context, CurContext,
72377240
UD->getLocation(), UD, Target);
72387241
UD->addShadowDecl(Shadow);
7239-
7242+
72407243
Shadow->setAccess(UD->getAccess());
72417244
if (Orig->isInvalidDecl() || UD->isInvalidDecl())
72427245
Shadow->setInvalidDecl();
7243-
7246+
7247+
Shadow->setPreviousDecl(PrevDecl);
7248+
72447249
if (S)
72457250
PushOnScopeChains(Shadow, S);
72467251
else
@@ -7504,8 +7509,9 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
75047509
}
75057510

75067511
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
7507-
if (!CheckUsingShadowDecl(UD, *I, Previous))
7508-
BuildUsingShadowDecl(S, UD, *I);
7512+
UsingShadowDecl *PrevDecl = 0;
7513+
if (!CheckUsingShadowDecl(UD, *I, Previous, PrevDecl))
7514+
BuildUsingShadowDecl(S, UD, *I, PrevDecl);
75097515
}
75107516

75117517
return UD;

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2152,19 +2152,22 @@ Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
21522152
I != E; ++I) {
21532153
UsingShadowDecl *Shadow = *I;
21542154
NamedDecl *InstTarget =
2155-
cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
2156-
Shadow->getLocation(),
2157-
Shadow->getTargetDecl(),
2158-
TemplateArgs));
2155+
cast_or_null<NamedDecl>(SemaRef.FindInstantiatedDecl(
2156+
Shadow->getLocation(), Shadow->getTargetDecl(), TemplateArgs));
21592157
if (!InstTarget)
21602158
return 0;
21612159

2162-
if (CheckRedeclaration &&
2163-
SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev))
2164-
continue;
2160+
UsingShadowDecl *PrevDecl = 0;
2161+
if (CheckRedeclaration) {
2162+
if (SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev, PrevDecl))
2163+
continue;
2164+
} else if (UsingShadowDecl *OldPrev = Shadow->getPreviousDecl()) {
2165+
PrevDecl = cast_or_null<UsingShadowDecl>(SemaRef.FindInstantiatedDecl(
2166+
Shadow->getLocation(), OldPrev, TemplateArgs));
2167+
}
21652168

2166-
UsingShadowDecl *InstShadow
2167-
= SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget);
2169+
UsingShadowDecl *InstShadow =
2170+
SemaRef.BuildUsingShadowDecl(/*Scope*/0, NewUD, InstTarget, PrevDecl);
21682171
SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
21692172

21702173
if (isFunctionScope)

clang/lib/Serialization/ASTCommon.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
165165
case Decl::CXXConstructor:
166166
case Decl::CXXDestructor:
167167
case Decl::CXXConversion:
168+
case Decl::UsingShadow:
168169
case Decl::Var:
169170
case Decl::FunctionTemplate:
170171
case Decl::ClassTemplate:
@@ -192,7 +193,6 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
192193
case Decl::NonTypeTemplateParm:
193194
case Decl::TemplateTemplateParm:
194195
case Decl::Using:
195-
case Decl::UsingShadow:
196196
case Decl::ObjCMethod:
197197
case Decl::ObjCCategory:
198198
case Decl::ObjCCategoryImpl:

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,12 +1134,14 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) {
11341134
}
11351135

11361136
void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) {
1137+
RedeclarableResult Redecl = VisitRedeclarable(D);
11371138
VisitNamedDecl(D);
11381139
D->setTargetDecl(ReadDeclAs<NamedDecl>(Record, Idx));
11391140
D->UsingOrNextShadow = ReadDeclAs<NamedDecl>(Record, Idx);
11401141
UsingShadowDecl *Pattern = ReadDeclAs<UsingShadowDecl>(Record, Idx);
11411142
if (Pattern)
11421143
Reader.getContext().setInstantiatedFromUsingShadowDecl(D, Pattern);
1144+
mergeRedeclarable(D, Redecl);
11431145
}
11441146

11451147
void ASTDeclReader::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) {
@@ -2151,6 +2153,12 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
21512153
// FIXME: Also check the value is odr-equivalent.
21522154
return true;
21532155

2156+
// Using shadow declarations with the same target match.
2157+
if (UsingShadowDecl *USX = dyn_cast<UsingShadowDecl>(X)) {
2158+
UsingShadowDecl *USY = cast<UsingShadowDecl>(Y);
2159+
return USX->getTargetDecl() == USY->getTargetDecl();
2160+
}
2161+
21542162
// FIXME: Many other cases to implement.
21552163
return false;
21562164
}
@@ -2258,6 +2266,8 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
22582266
VD->RedeclLink.setNext(cast<VarDecl>(previous));
22592267
} else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
22602268
TD->RedeclLink.setNext(cast<TypedefNameDecl>(previous));
2269+
} else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) {
2270+
USD->RedeclLink.setNext(cast<UsingShadowDecl>(previous));
22612271
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
22622272
ID->RedeclLink.setNext(cast<ObjCInterfaceDecl>(previous));
22632273
} else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
@@ -2285,7 +2295,7 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
22852295
TD->RedeclLink
22862296
= Redeclarable<TagDecl>::LatestDeclLink(cast<TagDecl>(Latest));
22872297
} else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
2288-
FD->RedeclLink
2298+
FD->RedeclLink
22892299
= Redeclarable<FunctionDecl>::LatestDeclLink(cast<FunctionDecl>(Latest));
22902300
} else if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
22912301
VD->RedeclLink
@@ -2294,6 +2304,10 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
22942304
TD->RedeclLink
22952305
= Redeclarable<TypedefNameDecl>::LatestDeclLink(
22962306
cast<TypedefNameDecl>(Latest));
2307+
} else if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) {
2308+
USD->RedeclLink
2309+
= Redeclarable<UsingShadowDecl>::LatestDeclLink(
2310+
cast<UsingShadowDecl>(Latest));
22972311
} else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
22982312
ID->RedeclLink
22992313
= Redeclarable<ObjCInterfaceDecl>::LatestDeclLink(

clang/lib/Serialization/ASTWriterDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,7 @@ void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) {
938938
}
939939

940940
void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) {
941+
VisitRedeclarable(D);
941942
VisitNamedDecl(D);
942943
Writer.AddDeclRef(D->getTargetDecl(), Record);
943944
Writer.AddDeclRef(D->UsingOrNextShadow, Record);

clang/test/Modules/Inputs/module.map

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,8 @@ module warning {
258258
module initializer_list {
259259
header "initializer_list"
260260
}
261+
262+
module using_decl {
263+
module a { header "using-decl-a.h" export * }
264+
module b { header "using-decl-b.h" export * }
265+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
typedef int using_decl_type;
2+
int using_decl_var;
3+
4+
namespace UsingDecl {
5+
using ::using_decl_type;
6+
using ::using_decl_var;
7+
8+
namespace A { typedef int inner; }
9+
using A::inner;
10+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
namespace UsingDecl {
2+
namespace B { typedef int inner; }
3+
using B::inner;
4+
}
5+
6+
#include "using-decl-a.h"
7+
8+
namespace UsingDecl {
9+
using ::using_decl_type;
10+
using ::using_decl_var;
11+
}

clang/test/Modules/using-decl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: rm -rf %t
2+
// RUN: %clang_cc1 -x objective-c++ -fmodules -fmodules-cache-path=%t -I %S/Inputs %s -verify
3+
4+
@import using_decl.a;
5+
6+
// expected-no-diagnostics
7+
UsingDecl::using_decl_type x = UsingDecl::using_decl_var;
8+
UsingDecl::inner y = x;

0 commit comments

Comments
 (0)