Skip to content

Commit 12b885c

Browse files
committed
[modules] Properly look up the owning module for an instantiation of a merged template.
When looking for the template instantiation pattern of a templated entity, consistently select the definition of the pattern if there is one. This means we'll pick the same owning module when we start instantiating a template that we'll later pick when determining which modules are visible during that instantiation. This reinstates r300650, reverted in r300659, with a fix for a regression reported by Chandler after commit. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@300938 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 6ae3e4a commit 12b885c

File tree

6 files changed

+80
-40
lines changed

6 files changed

+80
-40
lines changed

lib/AST/Decl.cpp

+29-26
Original file line numberDiff line numberDiff line change
@@ -2251,6 +2251,14 @@ bool VarDecl::checkInitIsICE() const {
22512251
return Eval->IsICE;
22522252
}
22532253

2254+
template<typename DeclT>
2255+
static DeclT *getDefinitionOrSelf(DeclT *D) {
2256+
assert(D);
2257+
if (auto *Def = D->getDefinition())
2258+
return Def;
2259+
return D;
2260+
}
2261+
22542262
VarDecl *VarDecl::getTemplateInstantiationPattern() const {
22552263
// If it's a variable template specialization, find the template or partial
22562264
// specialization from which it was instantiated.
@@ -2262,7 +2270,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
22622270
break;
22632271
VTD = NewVTD;
22642272
}
2265-
return VTD->getTemplatedDecl()->getDefinition();
2273+
return getDefinitionOrSelf(VTD->getTemplatedDecl());
22662274
}
22672275
if (auto *VTPSD =
22682276
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
@@ -2271,7 +2279,7 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
22712279
break;
22722280
VTPSD = NewVTPSD;
22732281
}
2274-
return VTPSD->getDefinition();
2282+
return getDefinitionOrSelf<VarDecl>(VTPSD);
22752283
}
22762284
}
22772285

@@ -2280,23 +2288,18 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
22802288
VarDecl *VD = getInstantiatedFromStaticDataMember();
22812289
while (auto *NewVD = VD->getInstantiatedFromStaticDataMember())
22822290
VD = NewVD;
2283-
return VD->getDefinition();
2291+
return getDefinitionOrSelf(VD);
22842292
}
22852293
}
22862294

22872295
if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) {
2288-
22892296
while (VarTemplate->getInstantiatedFromMemberTemplate()) {
22902297
if (VarTemplate->isMemberSpecialization())
22912298
break;
22922299
VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate();
22932300
}
22942301

2295-
assert((!VarTemplate->getTemplatedDecl() ||
2296-
!isTemplateInstantiation(getTemplateSpecializationKind())) &&
2297-
"couldn't find pattern for variable instantiation");
2298-
2299-
return VarTemplate->getTemplatedDecl();
2302+
return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());
23002303
}
23012304
return nullptr;
23022305
}
@@ -3198,9 +3201,12 @@ bool FunctionDecl::isTemplateInstantiation() const {
31983201

31993202
FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
32003203
// Handle class scope explicit specialization special case.
3201-
if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
3202-
return getClassScopeSpecializationPattern();
3203-
3204+
if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
3205+
if (auto *Spec = getClassScopeSpecializationPattern())
3206+
return getDefinitionOrSelf(Spec);
3207+
return nullptr;
3208+
}
3209+
32043210
// If this is a generic lambda call operator specialization, its
32053211
// instantiation pattern is always its primary template's pattern
32063212
// even if its primary template was instantiated from another
@@ -3212,16 +3218,10 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
32123218

32133219
if (isGenericLambdaCallOperatorSpecialization(
32143220
dyn_cast<CXXMethodDecl>(this))) {
3215-
assert(getPrimaryTemplate() && "A generic lambda specialization must be "
3216-
"generated from a primary call operator "
3217-
"template");
3218-
assert(getPrimaryTemplate()->getTemplatedDecl()->getBody() &&
3219-
"A generic lambda call operator template must always have a body - "
3220-
"even if instantiated from a prototype (i.e. as written) member "
3221-
"template");
3222-
return getPrimaryTemplate()->getTemplatedDecl();
3221+
assert(getPrimaryTemplate() && "not a generic lambda call operator?");
3222+
return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl());
32233223
}
3224-
3224+
32253225
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
32263226
while (Primary->getInstantiatedFromMemberTemplate()) {
32273227
// If we have hit a point where the user provided a specialization of
@@ -3230,11 +3230,14 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {
32303230
break;
32313231
Primary = Primary->getInstantiatedFromMemberTemplate();
32323232
}
3233-
3234-
return Primary->getTemplatedDecl();
3233+
3234+
return getDefinitionOrSelf(Primary->getTemplatedDecl());
32353235
}
3236-
3237-
return getInstantiatedFromMemberFunction();
3236+
3237+
if (auto *MFD = getInstantiatedFromMemberFunction())
3238+
return getDefinitionOrSelf(MFD);
3239+
3240+
return nullptr;
32383241
}
32393242

32403243
FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {
@@ -3778,7 +3781,7 @@ EnumDecl *EnumDecl::getTemplateInstantiationPattern() const {
37783781
EnumDecl *ED = getInstantiatedFromMemberEnum();
37793782
while (auto *NewED = ED->getInstantiatedFromMemberEnum())
37803783
ED = NewED;
3781-
return ED;
3784+
return getDefinitionOrSelf(ED);
37823785
}
37833786
}
37843787

lib/AST/DeclCXX.cpp

+10-3
Original file line numberDiff line numberDiff line change
@@ -1364,6 +1364,13 @@ CXXRecordDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
13641364
}
13651365

13661366
const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
1367+
auto GetDefinitionOrSelf =
1368+
[](const CXXRecordDecl *D) -> const CXXRecordDecl * {
1369+
if (auto *Def = D->getDefinition())
1370+
return Def;
1371+
return D;
1372+
};
1373+
13671374
// If it's a class template specialization, find the template or partial
13681375
// specialization from which it was instantiated.
13691376
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
@@ -1374,7 +1381,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
13741381
break;
13751382
CTD = NewCTD;
13761383
}
1377-
return CTD->getTemplatedDecl()->getDefinition();
1384+
return GetDefinitionOrSelf(CTD->getTemplatedDecl());
13781385
}
13791386
if (auto *CTPSD =
13801387
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
@@ -1383,7 +1390,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
13831390
break;
13841391
CTPSD = NewCTPSD;
13851392
}
1386-
return CTPSD->getDefinition();
1393+
return GetDefinitionOrSelf(CTPSD);
13871394
}
13881395
}
13891396

@@ -1392,7 +1399,7 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
13921399
const CXXRecordDecl *RD = this;
13931400
while (auto *NewRD = RD->getInstantiatedFromMemberClass())
13941401
RD = NewRD;
1395-
return RD->getDefinition();
1402+
return GetDefinitionOrSelf(RD);
13961403
}
13971404
}
13981405

lib/Sema/SemaLookup.cpp

+4-11
Original file line numberDiff line numberDiff line change
@@ -1326,12 +1326,6 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
13261326
return !R.empty();
13271327
}
13281328

1329-
/// \brief Find the declaration that a class temploid member specialization was
1330-
/// instantiated from, or the member itself if it is an explicit specialization.
1331-
static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) {
1332-
return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom();
1333-
}
1334-
13351329
Module *Sema::getOwningModule(Decl *Entity) {
13361330
// If it's imported, grab its owning module.
13371331
Module *M = Entity->getImportedOwningModule();
@@ -1413,12 +1407,11 @@ static Module *getDefiningModule(Sema &S, Decl *Entity) {
14131407
if (CXXRecordDecl *Pattern = RD->getTemplateInstantiationPattern())
14141408
Entity = Pattern;
14151409
} else if (EnumDecl *ED = dyn_cast<EnumDecl>(Entity)) {
1416-
if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInfo())
1417-
Entity = getInstantiatedFrom(ED, MSInfo);
1410+
if (auto *Pattern = ED->getTemplateInstantiationPattern())
1411+
Entity = Pattern;
14181412
} else if (VarDecl *VD = dyn_cast<VarDecl>(Entity)) {
1419-
// FIXME: Map from variable template specializations back to the template.
1420-
if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo())
1421-
Entity = getInstantiatedFrom(VD, MSInfo);
1413+
if (VarDecl *Pattern = VD->getTemplateInstantiationPattern())
1414+
Entity = Pattern;
14221415
}
14231416

14241417
// Walk up to the containing context. That might also have been instantiated

test/Modules/Inputs/template-default-args/a.h

+13
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,16 @@ struct FriendL {
1414
template<typename T> friend struct L;
1515
};
1616
END
17+
18+
namespace DeferredLookup {
19+
template<typename T, typename U = T> using X = U;
20+
template<typename T> void f() { (void) X<T>(); }
21+
template<typename T> int n = X<T>();
22+
template<typename T> struct S { X<T> xt; enum E : int; };
23+
template<typename T> enum S<T>::E : int { a = X<T>() };
24+
25+
namespace Indirect {
26+
template<typename, bool = true> struct A {};
27+
template<typename> struct B { template<typename T> using C = A<T>; };
28+
}
29+
}

test/Modules/Inputs/template-default-args/d.h

+7
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,10 @@ struct FriendL {
44
template<typename T> friend struct L;
55
};
66
END
7+
8+
namespace DeferredLookup {
9+
namespace Indirect {
10+
template<typename, bool = true> struct A {};
11+
template<typename> struct B { template<typename T> using C = A<T>; };
12+
}
13+
}

test/Modules/template-default-args.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,20 @@ H<> h; // expected-error {{default argument of 'H' must be imported from module
4444
I<> i;
4545
L<> *l;
4646
END
47+
48+
namespace DeferredLookup {
49+
template<typename T, typename U = T> using X = U;
50+
template<typename T> void f() { (void) X<T>(); }
51+
template<typename T> int n = X<T>(); // expected-warning {{extension}}
52+
template<typename T> struct S { X<T> xt; enum E : int; };
53+
template<typename T> enum S<T>::E : int { a = X<T>() };
54+
55+
void test() {
56+
f<int>();
57+
n<int> = 1;
58+
S<int> s;
59+
S<int>::E e = S<int>::E::a;
60+
61+
Indirect::B<int>::C<int> indirect;
62+
}
63+
}

0 commit comments

Comments
 (0)