summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp4
-rwxr-xr-xclang/lib/Sema/SemaTemplateInstantiateDecl.cpp34
-rw-r--r--clang/test/SemaTemplate/instantiate-abbreviated-template.cpp18
3 files changed, 47 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index a9357ede700..568f5404dc0 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2290,12 +2290,12 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
if (TemplateTypeParmDecl *TTP =
GetContainedInventedTypeParmVisitor().Visit(OldDI->getType())) {
if (const TypeConstraint *TC = TTP->getTypeConstraint()) {
- auto *Inst = cast<TemplateTypeParmDecl>(
+ auto *Inst = cast_or_null<TemplateTypeParmDecl>(
FindInstantiatedDecl(TTP->getLocation(), TTP, TemplateArgs));
// We will first get here when instantiating the abbreviated function
// template's described function, but we might also get here later.
// Make sure we do not instantiate the TypeConstraint more than once.
- if (Inst && !Inst->hasTypeConstraint()) {
+ if (Inst && !Inst->getTypeConstraint()) {
// TODO: Concepts: do not instantiate the constraint (delayed constraint
// substitution)
const ASTTemplateArgumentListInfo *TemplArgInfo
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 7094462e74c..37dace3bee7 100755
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1837,6 +1837,23 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
return nullptr;
QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo);
+ if (TemplateParams && TemplateParams->size()) {
+ auto *LastParam =
+ dyn_cast<TemplateTypeParmDecl>(TemplateParams->asArray().back());
+ if (LastParam && LastParam->isImplicit() &&
+ LastParam->hasTypeConstraint()) {
+ // In abbreviated templates, the type-constraints of invented template
+ // type parameters are instantiated with the function type, invalidating
+ // the TemplateParameterList which relied on the template type parameter
+ // not having a type constraint. Recreate the TemplateParameterList with
+ // the updated parameter list.
+ TemplateParams = TemplateParameterList::Create(
+ SemaRef.Context, TemplateParams->getTemplateLoc(),
+ TemplateParams->getLAngleLoc(), TemplateParams->asArray(),
+ TemplateParams->getRAngleLoc(), TemplateParams->getRequiresClause());
+ }
+ }
+
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
if (QualifierLoc) {
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
@@ -2177,6 +2194,23 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
return nullptr;
QualType T = adjustFunctionTypeForInstantiation(SemaRef.Context, D, TInfo);
+ if (TemplateParams && TemplateParams->size()) {
+ auto *LastParam =
+ dyn_cast<TemplateTypeParmDecl>(TemplateParams->asArray().back());
+ if (LastParam && LastParam->isImplicit() &&
+ LastParam->hasTypeConstraint()) {
+ // In abbreviated templates, the type-constraints of invented template
+ // type parameters are instantiated with the function type, invalidating
+ // the TemplateParameterList which relied on the template type parameter
+ // not having a type constraint. Recreate the TemplateParameterList with
+ // the updated parameter list.
+ TemplateParams = TemplateParameterList::Create(
+ SemaRef.Context, TemplateParams->getTemplateLoc(),
+ TemplateParams->getLAngleLoc(), TemplateParams->asArray(),
+ TemplateParams->getRAngleLoc(), TemplateParams->getRequiresClause());
+ }
+ }
+
NestedNameSpecifierLoc QualifierLoc = D->getQualifierLoc();
if (QualifierLoc) {
QualifierLoc = SemaRef.SubstNestedNameSpecifierLoc(QualifierLoc,
diff --git a/clang/test/SemaTemplate/instantiate-abbreviated-template.cpp b/clang/test/SemaTemplate/instantiate-abbreviated-template.cpp
index a73b6ce3610..99801115626 100644
--- a/clang/test/SemaTemplate/instantiate-abbreviated-template.cpp
+++ b/clang/test/SemaTemplate/instantiate-abbreviated-template.cpp
@@ -1,29 +1,33 @@
// RUN: %clang_cc1 -std=c++2a -x c++ %s -verify
-// expected-no-diagnostics
template<typename...>
-concept C = true;
+concept C = false; // expected-note 9{{because}}
template<typename T>
struct S {
template<typename U>
static void foo1(U a, auto b);
static void foo2(T a, C<T> auto b);
+ // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}}
static void foo3(T a, C<decltype(a)> auto b);
+ // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}}
static void foo4(T a, C<decltype(a)> auto b, const C<decltype(b)> auto &&c);
+ // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}}
};
using sf1 = decltype(S<int>::foo1(1, 2));
-using sf2 = decltype(S<int>::foo2(1, 2));
-using sf3 = decltype(S<int>::foo3(1, 2));
-using sf4 = decltype(S<int>::foo4(1, 2, 3));
+using sf2 = decltype(S<int>::foo2(1, 2)); // expected-error{{no matching function}}
+using sf3 = decltype(S<int>::foo3(1, 2)); // expected-error{{no matching function}}
+using sf4 = decltype(S<int>::foo4(1, 2, 3)); // expected-error{{no matching function}}
template<typename... T>
struct G {
static void foo1(auto a, const C<decltype(a)> auto &&... b);
+ // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} expected-note@-1 3{{and}}
static void foo2(auto a, const C<decltype(a), T> auto &&... b);
+ // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} expected-note@-1{{and}}
};
-using gf1 = decltype(G<int, char>::foo1('a', 1, 2, 3, 4));
-using gf2 = decltype(G<int, char>::foo2('a', 1, 2));
+using gf1 = decltype(G<int, char>::foo1('a', 1, 2, 3, 4)); // expected-error{{no matching function}}
+using gf2 = decltype(G<int, char>::foo2('a', 1, 2)); // expected-error{{no matching function}}
OpenPOWER on IntegriCloud