Skip to content

Commit 96ed02d

Browse files
committed
[Concepts] Fix incorrect check when instantiating abbreviated template type-constraints
We would incorrectly check whether the type-constraint had already been initialized, causing us to ignore the invented template type constraints entirely. Also, TemplateParameterList would store incorrect information about invented type parameters when it observed them before their type-constraint was initialized, so we recreate it after initializing the function type of an abbreviated template. (cherry picked from commit 38fd699)
1 parent c0c5ab3 commit 96ed02d

File tree

3 files changed

+47
-9
lines changed

3 files changed

+47
-9
lines changed

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2290,12 +2290,12 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
22902290
if (TemplateTypeParmDecl *TTP =
22912291
GetContainedInventedTypeParmVisitor().Visit(OldDI->getType())) {
22922292
if (const TypeConstraint *TC = TTP->getTypeConstraint()) {
2293-
auto *Inst = cast<TemplateTypeParmDecl>(
2293+
auto *Inst = cast_or_null<TemplateTypeParmDecl>(
22942294
FindInstantiatedDecl(TTP->getLocation(), TTP, TemplateArgs));
22952295
// We will first get here when instantiating the abbreviated function
22962296
// template's described function, but we might also get here later.
22972297
// Make sure we do not instantiate the TypeConstraint more than once.
2298-
if (Inst && !Inst->hasTypeConstraint()) {
2298+
if (Inst && !Inst->getTypeConstraint()) {
22992299
// TODO: Concepts: do not instantiate the constraint (delayed constraint
23002300
// substitution)
23012301
const ASTTemplateArgumentListInfo *TemplArgInfo

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1837,6 +1837,23 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
18371837
return nullptr;
18381838
QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo);
18391839

1840+
if (TemplateParams && TemplateParams->size()) {
1841+
auto *LastParam =
1842+
dyn_cast<TemplateTypeParmDecl>(TemplateParams->asArray().back());
1843+
if (LastParam && LastParam->isImplicit() &&
1844+
LastParam->hasTypeConstraint()) {
1845+
// In abbreviated templates, the type-constraints of invented template
1846+
// type parameters are instantiated with the function type, invalidating
1847+
// the TemplateParameterList which relied on the template type parameter
1848+
// not having a type constraint. Recreate the TemplateParameterList with
1849+
// the updated parameter list.
1850+
TemplateParams = TemplateParameterList::Create(
1851+
SemaRef.Context, TemplateParams->getTemplateLoc(),
1852+
TemplateParams->getLAngleLoc(), TemplateParams->asArray(),
1853+
TemplateParams->getRAngleLoc(), TemplateParams->getRequiresClause());
1854+
}
1855+
}
1856+
18401857
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
18411858
if (QualifierLoc) {
18421859
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
@@ -2177,6 +2194,23 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
21772194
return nullptr;
21782195
QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo);
21792196

2197+
if (TemplateParams && TemplateParams->size()) {
2198+
auto *LastParam =
2199+
dyn_cast<TemplateTypeParmDecl>(TemplateParams->asArray().back());
2200+
if (LastParam && LastParam->isImplicit() &&
2201+
LastParam->hasTypeConstraint()) {
2202+
// In abbreviated templates, the type-constraints of invented template
2203+
// type parameters are instantiated with the function type, invalidating
2204+
// the TemplateParameterList which relied on the template type parameter
2205+
// not having a type constraint. Recreate the TemplateParameterList with
2206+
// the updated parameter list.
2207+
TemplateParams = TemplateParameterList::Create(
2208+
SemaRef.Context, TemplateParams->getTemplateLoc(),
2209+
TemplateParams->getLAngleLoc(), TemplateParams->asArray(),
2210+
TemplateParams->getRAngleLoc(), TemplateParams->getRequiresClause());
2211+
}
2212+
}
2213+
21802214
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
21812215
if (QualifierLoc) {
21822216
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
11
// RUN: %clang_cc1 -std=c++2a -x c++ %s -verify
2-
// expected-no-diagnostics
32

43
template<typename...>
5-
concept C = true;
4+
concept C = false; // expected-note 9{{because}}
65

76
template<typename T>
87
struct S {
98
template<typename U>
109
static void foo1(U a, auto b);
1110
static void foo2(T a, C<T> auto b);
11+
// expected-note@-1{{candidate template ignored}} expected-note@-1{{because}}
1212
static void foo3(T a, C<decltype(a)> auto b);
13+
// expected-note@-1{{candidate template ignored}} expected-note@-1{{because}}
1314
static void foo4(T a, C<decltype(a)> auto b, const C<decltype(b)> auto &&c);
15+
// expected-note@-1{{candidate template ignored}} expected-note@-1{{because}}
1416
};
1517

1618
using sf1 = decltype(S<int>::foo1(1, 2));
17-
using sf2 = decltype(S<int>::foo2(1, 2));
18-
using sf3 = decltype(S<int>::foo3(1, 2));
19-
using sf4 = decltype(S<int>::foo4(1, 2, 3));
19+
using sf2 = decltype(S<int>::foo2(1, 2)); // expected-error{{no matching function}}
20+
using sf3 = decltype(S<int>::foo3(1, 2)); // expected-error{{no matching function}}
21+
using sf4 = decltype(S<int>::foo4(1, 2, 3)); // expected-error{{no matching function}}
2022

2123

2224
template<typename... T>
2325
struct G {
2426
static void foo1(auto a, const C<decltype(a)> auto &&... b);
27+
// expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} expected-note@-1 3{{and}}
2528
static void foo2(auto a, const C<decltype(a), T> auto &&... b);
29+
// expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} expected-note@-1{{and}}
2630
};
2731

28-
using gf1 = decltype(G<int, char>::foo1('a', 1, 2, 3, 4));
29-
using gf2 = decltype(G<int, char>::foo2('a', 1, 2));
32+
using gf1 = decltype(G<int, char>::foo1('a', 1, 2, 3, 4)); // expected-error{{no matching function}}
33+
using gf2 = decltype(G<int, char>::foo2('a', 1, 2)); // expected-error{{no matching function}}

0 commit comments

Comments
 (0)