https://github.com/zyn0217 created https://github.com/llvm/llvm-project/pull/102857
Some things are not completed yet: - [ ] CWG2369 for lambdas. We currently don't perform the concept checking before the substitution into lambdas because that requires us to put/instantiate captures to the scope, which is much more arduous than we should've done for ordinary functions. So constraints checking for lambdas are left as-is for now. - [ ] Code cleanups, refactoring. - [ ] Instantiate "used" parameters that a type constraint references to. Currently this patch instantiates all function parameters before checking the constraint. Closes https://github.com/llvm/llvm-project/issues/54440 >From de90a38cd1e8c1ea9316a05e0f68a56fd5a7240b Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Sun, 11 Aug 2024 16:51:34 +0800 Subject: [PATCH 1/2] CWG 2369 --- clang/include/clang/Sema/Sema.h | 3 +- clang/lib/Sema/SemaConcept.cpp | 2 +- clang/lib/Sema/SemaTemplateDeduction.cpp | 94 ++++++++++++++++--- clang/lib/Sema/SemaTemplateInstantiate.cpp | 5 +- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 48 +++++++--- 5 files changed, 122 insertions(+), 30 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 2ec6367eccea01..bd7b4c2d9b97ec 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13058,7 +13058,8 @@ class Sema final : public SemaBase { std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt, bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr, bool ForConstraintInstantiation = false, - bool SkipForSpecialization = false); + bool SkipForSpecialization = false, + MultiLevelTemplateArgumentList *Merged = nullptr); /// RAII object to handle the state changes required to synthesize /// a function body. diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index d4c9d044985e34..45318109d47963 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -842,7 +842,7 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, bool ForOverloadResolution) { // Don't check constraints if the function is dependent. Also don't check if // this is a function template specialization, as the call to - // CheckinstantiatedFunctionTemplateConstraints after this will check it + // CheckInstantiatedFunctionTemplateConstraints after this will check it // better. if (FD->isDependentContext() || FD->getTemplatedKind() == diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 978f1a9dc1a933..1880104625e4cb 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3834,18 +3834,6 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( Result != TemplateDeductionResult::Success) return Result; - // C++ [temp.deduct.call]p10: [DR1391] - // If deduction succeeds for all parameters that contain - // template-parameters that participate in template argument deduction, - // and all template arguments are explicitly specified, deduced, or - // obtained from default template arguments, remaining parameters are then - // compared with the corresponding arguments. For each remaining parameter - // P with a type that was non-dependent before substitution of any - // explicitly-specified template arguments, if the corresponding argument - // A cannot be implicitly converted to P, deduction fails. - if (CheckNonDependent()) - return TemplateDeductionResult::NonDependentConversionFailure; - // Form the template argument list from the deduced template arguments. TemplateArgumentList *SugaredDeducedArgumentList = TemplateArgumentList::CreateCopy(Context, SugaredBuilder); @@ -3875,6 +3863,76 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( FD = const_cast<FunctionDecl *>(FDFriend); Owner = FD->getLexicalDeclContext(); } +#if 1 + // FIXME: We have to partially instantiate lambda's captures for constraint + // evaluation. + if (!isLambdaCallOperator(FD) && !isLambdaConversionOperator(FD) && + (!PartialOverloading || + (CanonicalBuilder.size() == + FunctionTemplate->getTemplateParameters()->size()))) { + FunctionTemplateDecl *Template = FunctionTemplate->getCanonicalDecl(); + FunctionDecl *FD = Template->getTemplatedDecl(); + SmallVector<const Expr *, 3> TemplateAC; + Template->getAssociatedConstraints(TemplateAC); + if (!TemplateAC.empty()) { + + // Enter the scope of this instantiation. We don't use + // PushDeclContext because we don't have a scope. + LocalInstantiationScope Scope(*this); + + // Collect the list of template arguments relative to the 'primary' + // template. We need the entire list, since the constraint is completely + // uninstantiated at this point. + + MultiLevelTemplateArgumentList MLTAL(FD, SugaredBuilder, /*Final=*/false); + getTemplateInstantiationArgs(nullptr, FD->getLexicalDeclContext(), + /*Final=*/false, + /*Innermost=*/std::nullopt, + /*RelativeToPrimary=*/true, + /*Pattern=*/nullptr, + /*ForConstraintInstantiation=*/true, + /*SkipForSpecialization=*/false, + /*Merged=*/&MLTAL); + + // if (SetupConstraintScope(FD, SugaredBuilder, MLTAL, Scope)) + // return TemplateDeductionResult::MiscellaneousDeductionFailure; + + MultiLevelTemplateArgumentList JustTemplArgs( + Template, CanonicalDeducedArgumentList->asArray(), + /*Final=*/false); + if (addInstantiatedParametersToScope(nullptr, FD, Scope, JustTemplArgs)) + return TemplateDeductionResult::MiscellaneousDeductionFailure; + + if (FunctionTemplateDecl *FromMemTempl = + Template->getInstantiatedFromMemberTemplate()) { + while (FromMemTempl->getInstantiatedFromMemberTemplate()) + FromMemTempl = FromMemTempl->getInstantiatedFromMemberTemplate(); + if (addInstantiatedParametersToScope( + nullptr, FromMemTempl->getTemplatedDecl(), Scope, MLTAL)) + return TemplateDeductionResult::MiscellaneousDeductionFailure; + } + + Qualifiers ThisQuals; + CXXRecordDecl *Record = nullptr; + if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) { + ThisQuals = Method->getMethodQualifiers(); + Record = Method->getParent(); + } + CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); + llvm::SmallVector<Expr *, 1> Converted; + if (CheckConstraintSatisfaction(Template, TemplateAC, MLTAL, + Template->getSourceRange(), + Info.AssociatedConstraintsSatisfaction)) + return TemplateDeductionResult::MiscellaneousDeductionFailure; + if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) { + Info.reset(TemplateArgumentList::CreateCopy(Context, SugaredBuilder), + Info.takeCanonical()); + return TemplateDeductionResult::ConstraintsNotSatisfied; + } + } + } +#endif + MultiLevelTemplateArgumentList SubstArgs( FunctionTemplate, CanonicalDeducedArgumentList->asArray(), /*Final=*/false); @@ -3924,6 +3982,18 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( } } + // C++ [temp.deduct.call]p10: [DR1391] + // If deduction succeeds for all parameters that contain + // template-parameters that participate in template argument deduction, + // and all template arguments are explicitly specified, deduced, or + // obtained from default template arguments, remaining parameters are then + // compared with the corresponding arguments. For each remaining parameter + // P with a type that was non-dependent before substitution of any + // explicitly-specified template arguments, if the corresponding argument + // A cannot be implicitly converted to P, deduction fails. + if (CheckNonDependent()) + return TemplateDeductionResult::NonDependentConversionFailure; + // We skipped the instantiation of the explicit-specifier during the // substitution of `FD` before. So, we try to instantiate it back if // `Specialization` is either a constructor or a conversion function. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index de470739ab78e7..663bc6a57b0d91 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -467,10 +467,11 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( const NamedDecl *ND, const DeclContext *DC, bool Final, std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary, const FunctionDecl *Pattern, bool ForConstraintInstantiation, - bool SkipForSpecialization) { + bool SkipForSpecialization, MultiLevelTemplateArgumentList *Merged) { assert((ND || DC) && "Can't find arguments for a decl if one isn't provided"); // Accumulate the set of template argument lists in this structure. - MultiLevelTemplateArgumentList Result; + MultiLevelTemplateArgumentList Ret; + MultiLevelTemplateArgumentList &Result = Merged ? *Merged : Ret; using namespace TemplateInstArgsHelpers; const Decl *CurDecl = ND; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index f93cd113988ae4..5a7cb294a1c86d 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4577,17 +4577,17 @@ void Sema::addInstantiatedLocalVarsToScope(FunctionDecl *Function, } } -bool Sema::addInstantiatedParametersToScope( - FunctionDecl *Function, const FunctionDecl *PatternDecl, - LocalInstantiationScope &Scope, +static bool addInstantiatedParametersToScope( + Sema &SemaRef, MutableArrayRef<ParmVarDecl *> InstantiatedParamDecls, + const FunctionDecl *PatternDecl, LocalInstantiationScope &Scope, const MultiLevelTemplateArgumentList &TemplateArgs) { unsigned FParamIdx = 0; for (unsigned I = 0, N = PatternDecl->getNumParams(); I != N; ++I) { const ParmVarDecl *PatternParam = PatternDecl->getParamDecl(I); if (!PatternParam->isParameterPack()) { // Simple case: not a parameter pack. - assert(FParamIdx < Function->getNumParams()); - ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); + assert(FParamIdx < InstantiatedParamDecls.size()); + ParmVarDecl *FunctionParam = InstantiatedParamDecls[FParamIdx]; FunctionParam->setDeclName(PatternParam->getDeclName()); // If the parameter's type is not dependent, update it to match the type // in the pattern. They can differ in top-level cv-qualifiers, and we want @@ -4596,9 +4596,9 @@ bool Sema::addInstantiatedParametersToScope( // it's instantiation-dependent. // FIXME: Updating the type to work around this is at best fragile. if (!PatternDecl->getType()->isDependentType()) { - QualType T = SubstType(PatternParam->getType(), TemplateArgs, - FunctionParam->getLocation(), - FunctionParam->getDeclName()); + QualType T = SemaRef.SubstType(PatternParam->getType(), TemplateArgs, + FunctionParam->getLocation(), + FunctionParam->getDeclName()); if (T.isNull()) return true; FunctionParam->setType(T); @@ -4612,18 +4612,19 @@ bool Sema::addInstantiatedParametersToScope( // Expand the parameter pack. Scope.MakeInstantiatedLocalArgPack(PatternParam); std::optional<unsigned> NumArgumentsInExpansion = - getNumArgumentsInExpansion(PatternParam->getType(), TemplateArgs); + SemaRef.getNumArgumentsInExpansion(PatternParam->getType(), + TemplateArgs); if (NumArgumentsInExpansion) { QualType PatternType = PatternParam->getType()->castAs<PackExpansionType>()->getPattern(); for (unsigned Arg = 0; Arg < *NumArgumentsInExpansion; ++Arg) { - ParmVarDecl *FunctionParam = Function->getParamDecl(FParamIdx); + ParmVarDecl *FunctionParam = InstantiatedParamDecls[FParamIdx]; FunctionParam->setDeclName(PatternParam->getDeclName()); if (!PatternDecl->getType()->isDependentType()) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, Arg); - QualType T = - SubstType(PatternType, TemplateArgs, FunctionParam->getLocation(), - FunctionParam->getDeclName()); + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, Arg); + QualType T = SemaRef.SubstType(PatternType, TemplateArgs, + FunctionParam->getLocation(), + FunctionParam->getDeclName()); if (T.isNull()) return true; FunctionParam->setType(T); @@ -4638,6 +4639,25 @@ bool Sema::addInstantiatedParametersToScope( return false; } +bool Sema::addInstantiatedParametersToScope( + FunctionDecl *Function, const FunctionDecl *PatternDecl, + LocalInstantiationScope &Scope, + const MultiLevelTemplateArgumentList &TemplateArgs) { + if (Function) + return ::addInstantiatedParametersToScope(*this, Function->parameters(), + PatternDecl, Scope, TemplateArgs); + FunctionTypeLoc TypeLoc = PatternDecl->getFunctionTypeLoc(); + assert(!TypeLoc.isNull() && "Invalid function TypeLoc?"); + SmallVector<QualType> ParamTypes; + SmallVector<ParmVarDecl *> OutParams; + Sema::ExtParameterInfoBuilder ExtParamInfos; + if (SubstParmTypes(PatternDecl->getLocation(), TypeLoc.getParams(), nullptr, + TemplateArgs, ParamTypes, &OutParams, ExtParamInfos)) + return true; + return ::addInstantiatedParametersToScope(*this, OutParams, PatternDecl, + Scope, TemplateArgs); +} + bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, ParmVarDecl *Param) { assert(Param->hasUninstantiatedDefaultArg()); >From 3aa27cce0f4c57b568a117040b0067e9a39819f6 Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Mon, 12 Aug 2024 15:22:42 +0800 Subject: [PATCH 2/2] Rectify diagnostics --- clang/lib/Sema/SemaTemplateDeduction.cpp | 32 ++++++++----------- clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 8 +++-- clang/test/CXX/drs/cwg23xx.cpp | 32 +++++++++++++++++++ clang/test/CXX/drs/cwg26xx.cpp | 2 +- .../expr.prim.req/nested-requirement.cpp | 2 +- .../constrant-satisfaction-conversions.cpp | 6 ++-- .../SemaCXX/concept-crash-on-diagnostic.cpp | 2 +- clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 2 +- clang/test/SemaCXX/cxx23-assume.cpp | 6 ++-- clang/test/SemaCXX/cxx2c-fold-exprs.cpp | 2 +- clang/test/SemaCXX/lambda-unevaluated.cpp | 4 +-- .../SemaTemplate/concepts-recursive-inst.cpp | 4 +-- .../SemaTemplate/cxx2a-constraint-exprs.cpp | 2 +- clang/test/SemaTemplate/deduction-guide.cpp | 5 --- .../nested-implicit-deduction-guides.cpp | 8 +++-- 15 files changed, 72 insertions(+), 45 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 1880104625e4cb..04904ce06c49a8 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3863,7 +3863,7 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( FD = const_cast<FunctionDecl *>(FDFriend); Owner = FD->getLexicalDeclContext(); } -#if 1 + // [DR2369] // FIXME: We have to partially instantiate lambda's captures for constraint // evaluation. if (!isLambdaCallOperator(FD) && !isLambdaConversionOperator(FD) && @@ -3894,9 +3894,6 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( /*SkipForSpecialization=*/false, /*Merged=*/&MLTAL); - // if (SetupConstraintScope(FD, SugaredBuilder, MLTAL, Scope)) - // return TemplateDeductionResult::MiscellaneousDeductionFailure; - MultiLevelTemplateArgumentList JustTemplArgs( Template, CanonicalDeducedArgumentList->asArray(), /*Final=*/false); @@ -3921,7 +3918,7 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); llvm::SmallVector<Expr *, 1> Converted; if (CheckConstraintSatisfaction(Template, TemplateAC, MLTAL, - Template->getSourceRange(), + Info.getLocation(), Info.AssociatedConstraintsSatisfaction)) return TemplateDeductionResult::MiscellaneousDeductionFailure; if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) { @@ -3931,7 +3928,18 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( } } } -#endif + + // C++ [temp.deduct.call]p10: [DR1391] + // If deduction succeeds for all parameters that contain + // template-parameters that participate in template argument deduction, + // and all template arguments are explicitly specified, deduced, or + // obtained from default template arguments, remaining parameters are then + // compared with the corresponding arguments. For each remaining parameter + // P with a type that was non-dependent before substitution of any + // explicitly-specified template arguments, if the corresponding argument + // A cannot be implicitly converted to P, deduction fails. + if (CheckNonDependent()) + return TemplateDeductionResult::NonDependentConversionFailure; MultiLevelTemplateArgumentList SubstArgs( FunctionTemplate, CanonicalDeducedArgumentList->asArray(), @@ -3982,18 +3990,6 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( } } - // C++ [temp.deduct.call]p10: [DR1391] - // If deduction succeeds for all parameters that contain - // template-parameters that participate in template argument deduction, - // and all template arguments are explicitly specified, deduced, or - // obtained from default template arguments, remaining parameters are then - // compared with the corresponding arguments. For each remaining parameter - // P with a type that was non-dependent before substitution of any - // explicitly-specified template arguments, if the corresponding argument - // A cannot be implicitly converted to P, deduction fails. - if (CheckNonDependent()) - return TemplateDeductionResult::NonDependentConversionFailure; - // We skipped the instantiation of the explicit-specifier during the // substitution of `FD` before. So, we try to instantiate it back if // `Specialization` is either a constructor or a conversion function. diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 545da21183c3c4..405a733550fd54 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -904,10 +904,12 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef, Context.getTrivialTypeSourceInfo( Context.getDeducedTemplateSpecializationType( TemplateName(AliasTemplate), /*DeducedType=*/QualType(), - /*IsDependent=*/true)), // template specialization type whose - // arguments will be deduced. + /*IsDependent=*/true), + AliasTemplate->getLocation()), // template specialization type whose + // arguments will be deduced. Context.getTrivialTypeSourceInfo( - ReturnType), // type from which template arguments are deduced. + ReturnType, AliasTemplate->getLocation()), // type from which template + // arguments are deduced. }; return TypeTraitExpr::Create( Context, Context.getLogicalOperationType(), AliasTemplate->getLocation(), diff --git a/clang/test/CXX/drs/cwg23xx.cpp b/clang/test/CXX/drs/cwg23xx.cpp index e4a1e90941dbf0..4a0131aad1436f 100644 --- a/clang/test/CXX/drs/cwg23xx.cpp +++ b/clang/test/CXX/drs/cwg23xx.cpp @@ -392,3 +392,35 @@ namespace cwg2397 { // cwg2397: 17 } // namespace cwg2397 #endif + +#if __cplusplus >= 202002L + +namespace cwg2369 { // cwg2369: 20 + +template <class T> struct Z { + typedef typename T::x xx; +}; + +template <class T> +concept C = requires { typename T::A; }; +template <C T> typename Z<T>::xx f(void *, T); // #1 +template <class T> void f(int, T); // #2 + +struct A { +} a; + +struct ZZ { + template <class T, class = typename Z<T>::xx> operator T *(); + operator int(); +}; + +void foo() { + ZZ zz; + f(1, a); // OK, deduction fails for #1 because there is no conversion from int + // to void* + f(zz, 42); // OK, deduction fails for #1 because C<int> is not satisfied +} + +} // namespace cwg2369 + +#endif diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp index d843b09ee075ae..3107c6130b81c4 100644 --- a/clang/test/CXX/drs/cwg26xx.cpp +++ b/clang/test/CXX/drs/cwg26xx.cpp @@ -210,7 +210,7 @@ void f(T) requires requires { []() { T::invalid; } (); }; // since-cxx20-note@-3 {{in instantiation of requirement here}} // since-cxx20-note@-4 {{while substituting template arguments into constraint expression here}} // since-cxx20-note@#cwg2672-f-0 {{while checking constraint satisfaction for template 'f<int>' required here}} -// since-cxx20-note@#cwg2672-f-0 {{in instantiation of function template specialization 'cwg2672::f<int>' requested here}} +// since-cxx20-note@#cwg2672-f-0 {{while substituting deduced template arguments into function template 'f' [with T = int]}} void f(...); template <class T> diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp index 00ac9d0422d67e..d7973986185847 100644 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp +++ b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp @@ -154,7 +154,7 @@ void func() { bar<int>(); // expected-note@-1 {{while checking constraint satisfaction for template 'bar<int>' required here}} \ - // expected-note@-1 {{in instantiation of function template specialization}} + // expected-note@-1 {{while substituting deduced template arguments into function template 'bar' [with T = int]}} // expected-note@#bar {{in instantiation of static data member}} // expected-note@#bar {{in instantiation of requirement here}} // expected-note@#bar {{while checking the satisfaction of nested requirement requested here}} diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp index ba8e2dc372e984..c41de77986bcae 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp @@ -11,7 +11,7 @@ template<typename T> struct S { // expected-error@+3{{atomic constraint must be of type 'bool' (found 'S<int>')}} // expected-note@#FINST{{while checking constraint satisfaction}} -// expected-note@#FINST{{in instantiation of function template specialization}} +// expected-note@#FINST{{while substituting deduced template arguments into function template 'f' [with T = int]}} template<typename T> requires (S<T>{}) void f(T); void f(int); @@ -19,7 +19,7 @@ void f(int); // Ensure this applies to operator && as well. // expected-error@+3{{atomic constraint must be of type 'bool' (found 'S<int>')}} // expected-note@#F2INST{{while checking constraint satisfaction}} -// expected-note@#F2INST{{in instantiation of function template specialization}} +// expected-note@#F2INST{{while substituting deduced template arguments into function template 'f2' [with T = int]}} template<typename T> requires (S<T>{} && true) void f2(T); void f2(int); @@ -32,7 +32,7 @@ template<typename T> requires requires { // expected-note@-4{{while checking the satisfaction}} // expected-note@-6{{while substituting template arguments}} // expected-note@#F3INST{{while checking constraint satisfaction}} - // expected-note@#F3INST{{in instantiation of function template specialization}} + // expected-note@#F3INST{{while substituting deduced template arguments into function template 'f3' [with T = int]}} // } void f3(T); diff --git a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp index 71e55c8290ee4a..ccc109cbca0f19 100644 --- a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp +++ b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp @@ -31,7 +31,7 @@ void function() { // expected-note@#3 {{checking the satisfaction of concept 'convertible_to<bool, bool>'}} // expected-note@#2 {{substituting template arguments into constraint expression here}} // expected-note@#5 {{checking constraint satisfaction for template 'compare<Object *, Object *>'}} -// expected-note@#5 {{in instantiation of function template specialization 'compare<Object *, Object *>' requested here}} +// expected-note@#5 {{while substituting deduced template arguments into function template 'compare' [with IteratorL = Object *, IteratorR = Object *]}} // expected-note@#4 {{candidate template ignored: constraints not satisfied [with IteratorL = Object *, IteratorR = Object *]}} // We don't know exactly the substituted type for `lhs == rhs`, thus a placeholder 'expr-type' is emitted. diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp index 5392573fcdb9d5..dff7f611635582 100644 --- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp +++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp @@ -196,7 +196,7 @@ struct Foo { template <int K> using Bar = Foo<double, K>; // expected-note {{constraints not satisfied for class template 'Foo'}} -// expected-note@-1 {{candidate template ignored: could not match}} +// expected-note@-1 {{candidate template ignored: could not match}} expected-note@-1 {{candidate template ignored: constraints not satisfied}} // expected-note@-2 {{implicit deduction guide declared as 'template <int K> requires __is_deducible(test14::Bar, Foo<double, K>) Bar(Foo<double, K>) -> Foo<double, K>'}} // expected-note@-3 {{implicit deduction guide declared as 'template <int K> requires __is_deducible(test14::Bar, Foo<double, K>) Bar(const double (&)[K]) -> Foo<double, K>'}} double abc[3]; diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp index 9138501d726dd6..35971a58331ff3 100644 --- a/clang/test/SemaCXX/cxx23-assume.cpp +++ b/clang/test/SemaCXX/cxx23-assume.cpp @@ -127,12 +127,12 @@ constexpr int f5() requires (!C<T>) { return 2; } // expected-note 4 {{while che static_assert(f5<int>() == 1); static_assert(f5<D>() == 1); // expected-note 3 {{while checking constraint satisfaction}} - // expected-note@-1 3 {{in instantiation of}} + // expected-note@-1 3 {{while substituting deduced template arguments}} // expected-error@-2 {{no matching function for call}} static_assert(f5<double>() == 2); -static_assert(f5<E>() == 1); // expected-note {{while checking constraint satisfaction}} expected-note {{in instantiation of}} -static_assert(f5<F>() == 2); // expected-note {{while checking constraint satisfaction}} expected-note {{in instantiation of}} +static_assert(f5<E>() == 1); // expected-note {{while checking constraint satisfaction}} expected-note {{while substituting deduced template arguments}} +static_assert(f5<F>() == 2); // expected-note {{while checking constraint satisfaction}} expected-note {{while substituting deduced template arguments}} // Do not validate assumptions whose evaluation would have side-effects. constexpr int foo() { diff --git a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp index 0674135aac483f..70644e3aef8a71 100644 --- a/clang/test/SemaCXX/cxx2c-fold-exprs.cpp +++ b/clang/test/SemaCXX/cxx2c-fold-exprs.cpp @@ -233,7 +233,7 @@ void g() { A<Thingy, Thingy> *ap; f(ap, ap); // expected-error{{no matching function for call to 'f'}} \ // expected-note {{while checking constraint satisfaction}} \ - // expected-note {{in instantiation of function template specialization}} + // expected-note {{while substituting deduced template arguments}} } } diff --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp index 39ee89bc797f84..242d1fc0c1219d 100644 --- a/clang/test/SemaCXX/lambda-unevaluated.cpp +++ b/clang/test/SemaCXX/lambda-unevaluated.cpp @@ -172,7 +172,7 @@ int* func(T) requires requires { []() { T::foo(); }; }; // expected-error{{type double* func(...); static_assert(__is_same(decltype(func(0)), double*)); // expected-note {{while checking constraint satisfaction for template 'func<int>' required here}} - // expected-note@-1 {{in instantiation of function template specialization 'lambda_in_constraints::func<int>'}} + // expected-note@-1 {{while substituting deduced template arguments into function template 'func' [with T = int]}} static_assert(__is_same(decltype(func(WithFoo())), int*)); template <class T> @@ -250,7 +250,7 @@ S s("a"); // #use // expected-note@#S-requires {{substituting template arguments into constraint expression here}} // expected-note@#S-requires {{in instantiation of requirement here}} // expected-note@#use {{checking constraint satisfaction for template 'S<const char *>' required here}} -// expected-note@#use {{requested here}} +// expected-note@#use {{while substituting deduced template arguments into function template 'S' [with value:auto = const char *]}} // expected-note-re@#S 2{{candidate constructor {{.*}} not viable}} // expected-note@#S-ctor {{constraints not satisfied}} // expected-note-re@#S-requires {{because {{.*}} would be invalid}} diff --git a/clang/test/SemaTemplate/concepts-recursive-inst.cpp b/clang/test/SemaTemplate/concepts-recursive-inst.cpp index 8ac5a0e753a340..c5381c376602b5 100644 --- a/clang/test/SemaTemplate/concepts-recursive-inst.cpp +++ b/clang/test/SemaTemplate/concepts-recursive-inst.cpp @@ -76,7 +76,7 @@ auto it = begin(rng); // #BEGIN_CALL // expected-note@#INF_BEGIN {{while checking the satisfaction of concept 'Inf<struct my_range>' requested here}} // expected-note@#INF_BEGIN {{while substituting template arguments into constraint expression here}} // expected-note@#BEGIN_CALL {{while checking constraint satisfaction for template 'begin<struct my_range>' required here}} -// expected-note@#BEGIN_CALL {{in instantiation of function template specialization}} +// expected-note@#BEGIN_CALL {{while substituting deduced template arguments into function template}} // Fallout of the failure is failed lookup, which is necessary to stop odd // cascading errors. @@ -103,7 +103,7 @@ namespace GH50891 { // expected-note@#OP_TO {{while checking the satisfaction of concept 'Numeric<Deferred>' requested here}} // expected-note@#OP_TO {{while substituting template arguments into constraint expression here}} // expected-note@#FOO_CALL {{while checking constraint satisfaction for template}} - // expected-note@#FOO_CALL {{in instantiation of function template specialization}} + // expected-note@#FOO_CALL {{while substituting deduced template arguments into function template}} // expected-note@#FOO_CALL {{in instantiation of requirement here}} // expected-note@#NUMERIC {{while substituting template arguments into constraint expression here}} diff --git a/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp b/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp index f4403587a62594..5809ef684bbf3b 100644 --- a/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp +++ b/clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp @@ -34,7 +34,7 @@ namespace constant_evaluated { expected-note@-1{{candidate template ignored}} int a = (foo<int>(), 0); // expected-note@-1 {{while checking}} expected-error@-1{{no matching function}} \ - expected-note@-1 {{in instantiation}} + expected-note@-1 {{while substituting}} template<typename T> void bar() requires requires { requires f<int[2]>; } { }; // expected-note@-1{{in instantiation}} \ expected-note@-1{{while substituting}} \ diff --git a/clang/test/SemaTemplate/deduction-guide.cpp b/clang/test/SemaTemplate/deduction-guide.cpp index d03c783313dd71..67d00bb49f77d7 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -234,11 +234,6 @@ F s(0); // CHECK: | `-CXXBoolLiteralExpr {{.*}} 'bool' false // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (U) -> F<>' // CHECK: | `-ParmVarDecl {{.*}} 'U' -// CHECK: `-CXXDeductionGuideDecl {{.*}} implicit <deduction guide for F> 'auto (int) -> F<>' -// CHECK: |-TemplateArgument integral ''x'' -// CHECK: |-TemplateArgument type 'int' -// CHECK: | `-BuiltinType {{.*}} 'int' -// CHECK: `-ParmVarDecl {{.*}} 'int' // CHECK: FunctionProtoType {{.*}} 'auto (U) -> F<>' dependent trailing_return cdecl // CHECK: |-InjectedClassNameType {{.*}} 'F<>' dependent // CHECK: | `-CXXRecord {{.*}} 'F' diff --git a/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp index af3e3358f61382..5c7a90273d0e0f 100644 --- a/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp +++ b/clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp @@ -38,7 +38,7 @@ template<typename A, typename T> concept True = true; template<typename T> -concept False = false; +concept False = false; // #False template<class X> struct concepts { template<class Y> struct B { @@ -68,7 +68,7 @@ template<typename X> struct nested_init_list { Y y; }; - template<False F> + template<False F> // #INIT_LIST_INNER_INVALID_HEADER struct concept_fail { // #INIT_LIST_INNER_INVALID X x; F f; @@ -81,7 +81,9 @@ using NIL = nested_init_list<int>::B<int>; // expected-error@+1 {{no viable constructor or deduction guide for deduction of template arguments of 'nested_init_list<int>::concept_fail'}} nested_init_list<int>::concept_fail nil_invalid{1, ""}; -// expected-note@#INIT_LIST_INNER_INVALID {{candidate template ignored: substitution failure [with F = const char *]: constraints not satisfied for class template 'concept_fail' [with F = const char *]}} +// expected-note@#INIT_LIST_INNER_INVALID {{candidate template ignored: constraints not satisfied [with F = const char *]}} +// expected-note@#INIT_LIST_INNER_INVALID_HEADER {{because 'const char *' does not satisfy 'False'}} +// expected-note@#False {{because 'false' evaluated to false}} // expected-note@#INIT_LIST_INNER_INVALID {{implicit deduction guide declared as 'template <False F> concept_fail(int, F) -> concept_fail<F>'}} // expected-note@#INIT_LIST_INNER_INVALID {{candidate function template not viable: requires 1 argument, but 2 were provided}} // expected-note@#INIT_LIST_INNER_INVALID {{implicit deduction guide declared as 'template <False F> concept_fail(concept_fail<F>) -> concept_fail<F>'}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits