diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index a9357ede700e3..568f5404dc0b6 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( + auto *Inst = cast_or_null( 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 7094462e74c9c..37dace3bee7f6 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(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(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 a73b6ce3610fa..99801115626f8 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 -concept C = true; +concept C = false; // expected-note 9{{because}} template struct S { template static void foo1(U a, auto b); static void foo2(T a, C auto b); + // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} static void foo3(T a, C auto b); + // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} static void foo4(T a, C auto b, const C auto &&c); + // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} }; using sf1 = decltype(S::foo1(1, 2)); -using sf2 = decltype(S::foo2(1, 2)); -using sf3 = decltype(S::foo3(1, 2)); -using sf4 = decltype(S::foo4(1, 2, 3)); +using sf2 = decltype(S::foo2(1, 2)); // expected-error{{no matching function}} +using sf3 = decltype(S::foo3(1, 2)); // expected-error{{no matching function}} +using sf4 = decltype(S::foo4(1, 2, 3)); // expected-error{{no matching function}} template struct G { static void foo1(auto a, const C auto &&... b); + // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} expected-note@-1 3{{and}} static void foo2(auto a, const C auto &&... b); + // expected-note@-1{{candidate template ignored}} expected-note@-1{{because}} expected-note@-1{{and}} }; -using gf1 = decltype(G::foo1('a', 1, 2, 3, 4)); -using gf2 = decltype(G::foo2('a', 1, 2)); +using gf1 = decltype(G::foo1('a', 1, 2, 3, 4)); // expected-error{{no matching function}} +using gf2 = decltype(G::foo2('a', 1, 2)); // expected-error{{no matching function}}