Author: Younan Zhang Date: 2025-01-08T18:27:25+01:00 New Revision: 3972ed57088f6515b787d7d38dec03dc74e51827
URL: https://github.com/llvm/llvm-project/commit/3972ed57088f6515b787d7d38dec03dc74e51827 DIFF: https://github.com/llvm/llvm-project/commit/3972ed57088f6515b787d7d38dec03dc74e51827.diff LOG: Revert "[Clang] Implement CWG2369 "Ordering between constraints and substitution"" (#122130) Unfortunately that breaks some code on Windows when lambdas come into play, as reported in https://github.com/llvm/llvm-project/pull/102857#issuecomment-2577861178 This reverts commit 96eced624e0f120155256033fdcb8342e7e58d6e. Added: Modified: clang/include/clang/Sema/Sema.h clang/include/clang/Sema/Template.h clang/lib/Sema/SemaConcept.cpp clang/lib/Sema/SemaTemplateDeduction.cpp clang/lib/Sema/SemaTemplateDeductionGuide.cpp clang/lib/Sema/SemaTemplateInstantiate.cpp clang/lib/Sema/TreeTransform.h clang/test/CXX/drs/cwg23xx.cpp clang/test/CXX/drs/cwg26xx.cpp clang/test/CXX/drs/cwg27xx.cpp clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp clang/test/SemaCXX/concept-crash-on-diagnostic.cpp clang/test/SemaCXX/cxx20-ctad-type-alias.cpp clang/test/SemaCXX/cxx23-assume.cpp clang/test/SemaCXX/cxx2c-fold-exprs.cpp clang/test/SemaCXX/lambda-unevaluated.cpp clang/test/SemaTemplate/concepts-recursive-inst.cpp clang/test/SemaTemplate/cxx2a-constraint-exprs.cpp clang/test/SemaTemplate/deduction-guide.cpp clang/test/SemaTemplate/nested-implicit-deduction-guides.cpp clang/www/cxx_dr_status.html Removed: ################################################################################ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 18fd95f77ec227..a41f16f6dc8c9b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13062,7 +13062,6 @@ class Sema final : public SemaBase { /// /// \param SkipForSpecialization when specified, any template specializations /// in a traversal would be ignored. - /// /// \param ForDefaultArgumentSubstitution indicates we should continue looking /// when encountering a specialized member function template, rather than /// returning immediately. @@ -13074,17 +13073,6 @@ class Sema final : public SemaBase { bool SkipForSpecialization = false, bool ForDefaultArgumentSubstitution = false); - /// Apart from storing the result to \p Result, this behaves the same as - /// another overload. - void getTemplateInstantiationArgs( - MultiLevelTemplateArgumentList &Result, const NamedDecl *D, - const DeclContext *DC = nullptr, bool Final = false, - std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt, - bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr, - bool ForConstraintInstantiation = false, - bool SkipForSpecialization = false, - bool ForDefaultArgumentSubstitution = false); - /// RAII object to handle the state changes required to synthesize /// a function body. class SynthesizedFunctionScope { @@ -13354,7 +13342,7 @@ class Sema final : public SemaBase { ExprResult SubstConstraintExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs); - // Unlike the above, this does not evaluate constraints. + // Unlike the above, this does not evaluates constraints. ExprResult SubstConstraintExprWithoutSatisfaction( Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -14475,10 +14463,10 @@ class Sema final : public SemaBase { const MultiLevelTemplateArgumentList &TemplateArgs, SourceRange TemplateIDRange); - bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation, - FunctionDecl *Decl, - ArrayRef<TemplateArgument> TemplateArgs, - ConstraintSatisfaction &Satisfaction); + bool CheckInstantiatedFunctionTemplateConstraints( + SourceLocation PointOfInstantiation, FunctionDecl *Decl, + ArrayRef<TemplateArgument> TemplateArgs, + ConstraintSatisfaction &Satisfaction); /// \brief Emit diagnostics explaining why a constraint expression was deemed /// unsatisfied. diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index 59a0575ca98036..9800f75f676aaf 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -522,12 +522,6 @@ enum class TemplateSubstitutionKind : char { llvm::PointerUnion<Decl *, DeclArgumentPack *> * findInstantiationOf(const Decl *D); - /// Similar to \p findInstantiationOf(), but it wouldn't assert if the - /// instantiation was not found within the current instantiation scope. This - /// is helpful for on-demand declaration instantiation. - llvm::PointerUnion<Decl *, DeclArgumentPack *> * - findInstantiationUnsafe(const Decl *D); - void InstantiatedLocal(const Decl *D, Decl *Inst); void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst); void MakeInstantiatedLocalArgPack(const Decl *D); diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 10f4920a761f3c..539de00bd104f5 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -846,7 +846,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 - // CheckFunctionTemplateConstraints after this will check it + // CheckinstantiatedFunctionTemplateConstraints after this will check it // better. if (FD->isDependentContext() || FD->getTemplatedKind() == @@ -1111,55 +1111,12 @@ bool Sema::EnsureTemplateArgumentListConstraints( return false; } -static bool CheckFunctionConstraintsWithoutInstantiation( - Sema &SemaRef, SourceLocation PointOfInstantiation, - FunctionTemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs, - ConstraintSatisfaction &Satisfaction) { - SmallVector<const Expr *, 3> TemplateAC; - Template->getAssociatedConstraints(TemplateAC); - if (TemplateAC.empty()) { - Satisfaction.IsSatisfied = true; - return false; - } - - LocalInstantiationScope Scope(SemaRef); - - FunctionDecl *FD = Template->getTemplatedDecl(); - // 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. - - // FIXME: Add TemplateArgs through the 'Innermost' parameter once - // the refactoring of getTemplateInstantiationArgs() relands. - MultiLevelTemplateArgumentList MLTAL; - MLTAL.addOuterTemplateArguments(Template, std::nullopt, /*Final=*/false); - SemaRef.getTemplateInstantiationArgs( - MLTAL, /*D=*/FD, FD, - /*Final=*/false, /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true); - MLTAL.replaceInnermostTemplateArguments(Template, TemplateArgs); - - Sema::ContextRAII SavedContext(SemaRef, FD); - std::optional<Sema::CXXThisScopeRAII> ThisScope; - if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) - ThisScope.emplace(SemaRef, /*Record=*/Method->getParent(), - /*ThisQuals=*/Method->getMethodQualifiers()); - return SemaRef.CheckConstraintSatisfaction( - Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction); -} - -bool Sema::CheckFunctionTemplateConstraints( +bool Sema::CheckInstantiatedFunctionTemplateConstraints( SourceLocation PointOfInstantiation, FunctionDecl *Decl, ArrayRef<TemplateArgument> TemplateArgs, ConstraintSatisfaction &Satisfaction) { // In most cases we're not going to have constraints, so check for that first. FunctionTemplateDecl *Template = Decl->getPrimaryTemplate(); - - if (!Template) - return ::CheckFunctionConstraintsWithoutInstantiation( - *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(), - TemplateArgs, Satisfaction); - // Note - code synthesis context for the constraints check is created // inside CheckConstraintsSatisfaction. SmallVector<const Expr *, 3> TemplateAC; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index acd1151184e42f..1c1f6e30ab7b83 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3936,6 +3936,18 @@ 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); @@ -3965,39 +3977,6 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( FD = const_cast<FunctionDecl *>(FDFriend); Owner = FD->getLexicalDeclContext(); } - // C++20 [temp.deduct.general]p5: [CWG2369] - // If the function template has associated constraints, those constraints - // are checked for satisfaction. If the constraints are not satisfied, type - // deduction fails. - // - // FIXME: We haven't implemented CWG2369 for lambdas yet, because we need - // to figure out how to instantiate lambda captures to the scope without - // first instantiating the lambda. - bool IsLambda = isLambdaCallOperator(FD) || isLambdaConversionOperator(FD); - if (!IsLambda && !IsIncomplete) { - if (CheckFunctionTemplateConstraints( - Info.getLocation(), - FunctionTemplate->getCanonicalDecl()->getTemplatedDecl(), - CanonicalBuilder, Info.AssociatedConstraintsSatisfaction)) - return TemplateDeductionResult::MiscellaneousDeductionFailure; - if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) { - Info.reset(Info.takeSugared(), - TemplateArgumentList::CreateCopy(Context, CanonicalBuilder)); - return TemplateDeductionResult::ConstraintsNotSatisfied; - } - } - // C++ [temp.deduct.call]p10: [CWG1391] - // 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(), /*Final=*/false); @@ -4032,8 +4011,8 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction( // ([temp.constr.decl]), those constraints are checked for satisfaction // ([temp.constr.constr]). If the constraints are not satisfied, type // deduction fails. - if (IsLambda && !IsIncomplete) { - if (CheckFunctionTemplateConstraints( + if (!IsIncomplete) { + if (CheckInstantiatedFunctionTemplateConstraints( Info.getLocation(), Specialization, CanonicalBuilder, Info.AssociatedConstraintsSatisfaction)) return TemplateDeductionResult::MiscellaneousDeductionFailure; diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 5d6c11a75303df..d42c3765aa534f 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -902,12 +902,10 @@ Expr *buildIsDeducibleConstraint(Sema &SemaRef, Context.getTrivialTypeSourceInfo( Context.getDeducedTemplateSpecializationType( TemplateName(AliasTemplate), /*DeducedType=*/QualType(), - /*IsDependent=*/true), - AliasTemplate->getLocation()), // template specialization type whose - // arguments will be deduced. + /*IsDependent=*/true)), // template specialization type whose + // arguments will be deduced. Context.getTrivialTypeSourceInfo( - ReturnType, AliasTemplate->getLocation()), // type from which template - // arguments are deduced. + ReturnType), // type from which template arguments are deduced. }; return TypeTraitExpr::Create( Context, Context.getLogicalOperationType(), AliasTemplate->getLocation(), diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index cab9ae79ce5cb0..fb0f38df62a744 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -475,21 +475,6 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( 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; - getTemplateInstantiationArgs( - Result, ND, DC, Final, Innermost, RelativeToPrimary, Pattern, - ForConstraintInstantiation, SkipForSpecialization, - ForDefaultArgumentSubstitution); - return Result; -} - -void Sema::getTemplateInstantiationArgs( - MultiLevelTemplateArgumentList &Result, const NamedDecl *ND, - const DeclContext *DC, bool Final, - std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary, - const FunctionDecl *Pattern, bool ForConstraintInstantiation, - bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) { - 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. using namespace TemplateInstArgsHelpers; const Decl *CurDecl = ND; @@ -550,12 +535,14 @@ void Sema::getTemplateInstantiationArgs( } if (R.IsDone) - return; + return Result; if (R.ClearRelativeToPrimary) RelativeToPrimary = false; assert(R.NextDecl); CurDecl = R.NextDecl; } + + return Result; } bool Sema::CodeSynthesisContext::isInstantiationRecord() const { @@ -1362,19 +1349,6 @@ namespace { // Whether an incomplete substituion should be treated as an error. bool BailOutOnIncomplete; - private: - bool isSubstitutingConstraints() const { - return llvm::any_of(SemaRef.CodeSynthesisContexts, [](auto &Context) { - return Context.Kind == - Sema::CodeSynthesisContext::ConstraintSubstitution; - }); - } - - // CWG2770: Function parameters should be instantiated when they are - // needed by a satisfaction check of an atomic constraint or - // (recursively) by another function parameter. - bool maybeInstantiateFunctionParameterToScope(ParmVarDecl *OldParm); - public: typedef TreeTransform<TemplateInstantiator> inherited; @@ -1431,19 +1405,12 @@ namespace { ArrayRef<UnexpandedParameterPack> Unexpanded, bool &ShouldExpand, bool &RetainExpansion, std::optional<unsigned> &NumExpansions) { - if (SemaRef.CurrentInstantiationScope && isSubstitutingConstraints()) { - for (UnexpandedParameterPack ParmPack : Unexpanded) { - NamedDecl *VD = ParmPack.first.dyn_cast<NamedDecl *>(); - if (!isa_and_present<ParmVarDecl>(VD)) - continue; - if (maybeInstantiateFunctionParameterToScope(cast<ParmVarDecl>(VD))) - return true; - } - } - - return getSema().CheckParameterPacksForExpansion( - EllipsisLoc, PatternRange, Unexpanded, TemplateArgs, ShouldExpand, - RetainExpansion, NumExpansions); + return getSema().CheckParameterPacksForExpansion(EllipsisLoc, + PatternRange, Unexpanded, + TemplateArgs, + ShouldExpand, + RetainExpansion, + NumExpansions); } void ExpandingFunctionParameterPack(ParmVarDecl *Pack) { @@ -1944,62 +1911,9 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { // template parameter. } - if (SemaRef.CurrentInstantiationScope) { - if (isSubstitutingConstraints() && isa<ParmVarDecl>(D) && - maybeInstantiateFunctionParameterToScope(cast<ParmVarDecl>(D))) - return nullptr; - } - return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs); } -bool TemplateInstantiator::maybeInstantiateFunctionParameterToScope( - ParmVarDecl *OldParm) { - if (SemaRef.CurrentInstantiationScope->findInstantiationUnsafe(OldParm)) - return false; - // We're instantiating a function parameter whose associated function template - // has not been instantiated at this point for constraint evaluation, so make - // sure the instantiated parameters are owned by a function declaration such - // that they can be correctly 'captured' in tryCaptureVariable(). - Sema::ContextRAII Context(SemaRef, OldParm->getDeclContext()); - - if (!OldParm->isParameterPack()) - return !TransformFunctionTypeParam(OldParm, /*indexAdjustment=*/0, - /*NumExpansions=*/std::nullopt, - /*ExpectParameterPack=*/false); - - SmallVector<UnexpandedParameterPack, 2> Unexpanded; - - // Find the parameter packs that could be expanded. - TypeLoc TL = OldParm->getTypeSourceInfo()->getTypeLoc(); - PackExpansionTypeLoc ExpansionTL = TL.castAs<PackExpansionTypeLoc>(); - TypeLoc Pattern = ExpansionTL.getPatternLoc(); - SemaRef.collectUnexpandedParameterPacks(Pattern, Unexpanded); - assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); - - bool ShouldExpand = false; - bool RetainExpansion = false; - std::optional<unsigned> OrigNumExpansions = - ExpansionTL.getTypePtr()->getNumExpansions(); - std::optional<unsigned> NumExpansions = OrigNumExpansions; - if (TryExpandParameterPacks(ExpansionTL.getEllipsisLoc(), - Pattern.getSourceRange(), Unexpanded, - ShouldExpand, RetainExpansion, NumExpansions)) - return true; - - assert(ShouldExpand && !RetainExpansion && - "Shouldn't preserve pack expansion when evaluating constraints"); - ExpandingFunctionParameterPack(OldParm); - for (unsigned I = 0; I != *NumExpansions; ++I) { - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), I); - if (!TransformFunctionTypeParam(OldParm, /*indexAdjustment=*/0, - /*NumExpansions=*/OrigNumExpansions, - /*ExpectParameterPack=*/false)) - return true; - } - return false; -} - Decl *TemplateInstantiator::TransformDefinition(SourceLocation Loc, Decl *D) { Decl *Inst = getSema().SubstDecl(D, getSema().CurContext, TemplateArgs); if (!Inst) @@ -4677,8 +4591,9 @@ static const Decl *getCanonicalParmVarDecl(const Decl *D) { return D; } + llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> * -LocalInstantiationScope::findInstantiationUnsafe(const Decl *D) { +LocalInstantiationScope::findInstantiationOf(const Decl *D) { D = getCanonicalParmVarDecl(D); for (LocalInstantiationScope *Current = this; Current; Current = Current->Outer) { @@ -4703,14 +4618,6 @@ LocalInstantiationScope::findInstantiationUnsafe(const Decl *D) { break; } - return nullptr; -} - -llvm::PointerUnion<Decl *, LocalInstantiationScope::DeclArgumentPack *> * -LocalInstantiationScope::findInstantiationOf(const Decl *D) { - auto *Result = findInstantiationUnsafe(D); - if (Result) - return Result; // If we're performing a partial substitution during template argument // deduction, we may not have values for template parameters yet. if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index bff1e5bd8f078e..15ea8c7128f38d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -713,7 +713,7 @@ class TreeTransform { /// variables vector are acceptable. /// /// LastParamTransformed, if non-null, will be set to the index of the last - /// parameter on which transformation was started. In the event of an error, + /// parameter on which transfromation was started. In the event of an error, /// this will contain the parameter which failed to instantiate. /// /// Return true on error. diff --git a/clang/test/CXX/drs/cwg23xx.cpp b/clang/test/CXX/drs/cwg23xx.cpp index d0ec48e3f86cd6..d144cf9e4e8681 100644 --- a/clang/test/CXX/drs/cwg23xx.cpp +++ b/clang/test/CXX/drs/cwg23xx.cpp @@ -365,35 +365,6 @@ struct A { #endif } // namespace cwg2363 -namespace cwg2369 { // cwg2369: partial -#if __cplusplus >= 202002L -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 -} - -#endif -} // namespace cwg2369 - namespace cwg2370 { // cwg2370: no namespace N { typedef int type; diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp index 23d7635ff90658..efc49b0b502a7c 100644 --- a/clang/test/CXX/drs/cwg26xx.cpp +++ b/clang/test/CXX/drs/cwg26xx.cpp @@ -319,7 +319,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 {{while substituting deduced template arguments into function template 'f' [with T = int]}} +// since-cxx20-note@#cwg2672-f-0 {{in instantiation of function template specialization 'cwg2672::f<int>' requested here}} void f(...); template <class T> diff --git a/clang/test/CXX/drs/cwg27xx.cpp b/clang/test/CXX/drs/cwg27xx.cpp index 7caf36a9f23b25..a87d26dfc9acf9 100644 --- a/clang/test/CXX/drs/cwg27xx.cpp +++ b/clang/test/CXX/drs/cwg27xx.cpp @@ -174,26 +174,6 @@ static_assert(!__is_layout_compatible(StructWithAnonUnion, StructWithAnonUnion3) #endif } // namespace cwg2759 -namespace cwg2770 { // cwg2770: 20 open 2023-07-14 -#if __cplusplus >= 202002L -template<typename T> -struct B { - static_assert(sizeof(T) == 1); - using type = int; -}; - -template<typename T> -int f(T t, typename B<T>::type u) requires (sizeof(t) == 1); - -template<typename T> -int f(T t, long); - -int i = f(1, 2); -int j = f('a', 2); - -#endif -} // namespace cwg2770 - namespace cwg2789 { // cwg2789: 18 #if __cplusplus >= 202302L template <typename T = int> 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 a23f7dc595171e..763d983d20f615 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 {{while substituting deduced template arguments into function template 'bar' [with T = int]}} + // expected-note@-1 {{in instantiation of function template specialization}} // 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 c41de77986bcae..ba8e2dc372e984 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{{while substituting deduced template arguments into function template 'f' [with T = int]}} +// expected-note@#FINST{{in instantiation of function template specialization}} 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{{while substituting deduced template arguments into function template 'f2' [with T = int]}} +// expected-note@#F2INST{{in instantiation of function template specialization}} 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{{while substituting deduced template arguments into function template 'f3' [with T = int]}} + // expected-note@#F3INST{{in instantiation of function template specialization}} // } void f3(T); diff --git a/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp b/clang/test/SemaCXX/concept-crash-on-diagnostic.cpp index ccc109cbca0f19..71e55c8290ee4a 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 {{while substituting deduced template arguments into function template 'compare' [with IteratorL = Object *, IteratorR = Object *]}} +// expected-note@#5 {{in instantiation of function template specialization 'compare<Object *, Object *>' requested here}} // 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 23c898e6379b05..2d43e46b9e3d76 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: constraints not satisfied}} +// expected-note@-1 {{candidate template ignored: could not match}} // 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 726cb3bff652e7..7f80cdfe7d4523 100644 --- a/clang/test/SemaCXX/cxx23-assume.cpp +++ b/clang/test/SemaCXX/cxx23-assume.cpp @@ -129,12 +129,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 {{while substituting deduced template arguments}} + // expected-note@-1 3 {{in instantiation of}} // 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 {{while substituting deduced template arguments}} -static_assert(f5<F>() == 2); // expected-note {{while checking constraint satisfaction}} expected-note {{while substituting deduced template arguments}} +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}} // 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 4220486d3aed30..48061439941f23 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 {{while substituting deduced template arguments}} + // expected-note {{in instantiation of function template specialization}} } } diff --git a/clang/test/SemaCXX/lambda-unevaluated.cpp b/clang/test/SemaCXX/lambda-unevaluated.cpp index d3f937281f201a..a9bcab58464e26 100644 --- a/clang/test/SemaCXX/lambda-unevaluated.cpp +++ b/clang/test/SemaCXX/lambda-unevaluated.cpp @@ -174,7 +174,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 {{while substituting deduced template arguments into function template 'func' [with T = int]}} + // expected-note@-1 {{in instantiation of function template specialization 'lambda_in_constraints::func<int>'}} static_assert(__is_same(decltype(func(WithFoo())), int*)); template <class T> @@ -252,7 +252,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 {{while substituting deduced template arguments into function template 'S' [with value:auto = const char *]}} +// expected-note@#use {{requested here}} // 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 30a410cef91ee9..9330df8cdd0398 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<DirectRecursiveCheck::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<DirectRecursiveCheck::my_range>' required here}} -// expected-note@#BEGIN_CALL {{while substituting deduced template arguments into function template}} +// expected-note@#BEGIN_CALL {{in instantiation of function template specialization}} // 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<GH50891::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 {{while substituting deduced template arguments into function template}} + // expected-note@#FOO_CALL {{in instantiation of function template specialization}} // 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 5809ef684bbf3b..f4403587a62594 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 {{while substituting}} + expected-note@-1 {{in instantiation}} 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 67d00bb49f77d7..d03c783313dd71 100644 --- a/clang/test/SemaTemplate/deduction-guide.cpp +++ b/clang/test/SemaTemplate/deduction-guide.cpp @@ -234,6 +234,11 @@ 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 5c7a90273d0e0f..af3e3358f61382 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; // #False +concept 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> // #INIT_LIST_INNER_INVALID_HEADER + template<False F> struct concept_fail { // #INIT_LIST_INNER_INVALID X x; F f; @@ -81,9 +81,7 @@ 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: 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 {{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 {{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>'}} diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index 70f57a0c00a7f6..f2716f1e4c6537 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -14045,7 +14045,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/2369.html";>2369</a></td> <td>CD6</td> <td>Ordering between constraints and substitution</td> - <td class="partial" align="center">Partial</td> + <td class="unknown" align="center">Unknown</td> </tr> <tr id="2370"> <td><a href="https://cplusplus.github.io/CWG/issues/2370.html";>2370</a></td> @@ -16464,11 +16464,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://cplusplus.github.io/CWG/issues/2770.html";>2770</a></td> <td>open</td> <td>Trailing <I>requires-clause</I> can refer to function parameters before they are substituted into</td> - <td align="center"> - <details> - <summary>Not resolved</summary> - Clang 20 implements 2023-07-14 resolution - </details></td> + <td align="center">Not resolved</td> </tr> <tr id="2771"> <td><a href="https://cplusplus.github.io/CWG/issues/2771.html";>2771</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits