llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Matheus Izvekov (mizvekov) <details> <summary>Changes</summary> This patch relands the following PRs: * #<!-- -->111711 * #<!-- -->107350 * #<!-- -->111457 All of these patches were reverted due to issue reported in https://github.com/llvm/llvm-project/pull/111711#issuecomment-2406491485, due to interdependencies. In order to avoid churn, this relands all of them in one go. All of the patches are identical to the originally reverted ones, except "[clang] Changes to template argument list checking", which contains the changes which fix the revert-causing issue. --- Patch is 121.28 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/124137.diff 21 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+12-1) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+7) - (modified) clang/include/clang/Sema/Overload.h (+6) - (modified) clang/include/clang/Sema/Sema.h (+31-12) - (modified) clang/include/clang/Sema/TemplateDeduction.h (+13) - (modified) clang/lib/Frontend/FrontendActions.cpp (+2) - (modified) clang/lib/Sema/SemaLookup.cpp (+3-1) - (modified) clang/lib/Sema/SemaOverload.cpp (+32-18) - (modified) clang/lib/Sema/SemaTemplate.cpp (+133-119) - (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+333-134) - (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+29-10) - (modified) clang/test/CXX/temp/temp.arg/temp.arg.template/p3-0x.cpp (+26-13) - (modified) clang/test/CXX/temp/temp.param/p12.cpp (+11-10) - (modified) clang/test/Modules/cxx-templates.cpp (+3-12) - (modified) clang/test/SemaCXX/make_integer_seq.cpp (+2-3) - (modified) clang/test/SemaTemplate/cwg2398.cpp (+266-7) - (modified) clang/test/SemaTemplate/temp_arg_nontype.cpp (+18-8) - (modified) clang/test/SemaTemplate/temp_arg_template.cpp (+23-15) - (modified) clang/test/SemaTemplate/temp_arg_template_p0522.cpp (+52-30) - (modified) clang/test/Templight/templight-empty-entries-fix.cpp (+12) - (modified) clang/test/Templight/templight-prior-template-arg.cpp (+23-10) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5d4b182f29afa0..7801bad3439142 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -325,6 +325,10 @@ C++20 Feature Support - Implemented module level lookup for C++20 modules. (#GH90154) +C++17 Feature Support +^^^^^^^^^^^^^^^^^^^^^ +- The implementation of the relaxed template template argument matching rules is + more complete and reliable, and should provide more accurate diagnostics. Resolutions to C++ Defect Reports ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -351,7 +355,8 @@ Resolutions to C++ Defect Reports (`CWG2351: void{} <https://cplusplus.github.io/CWG/issues/2351.html>`_). - Clang now has improved resolution to CWG2398, allowing class templates to have - default arguments deduced when partial ordering. + default arguments deduced when partial ordering, and better backwards compatibility + in overload resolution. - Clang now allows comparing unequal object pointers that have been cast to ``void *`` in constant expressions. These comparisons always worked in non-constant expressions. @@ -636,6 +641,10 @@ Improvements to Clang's diagnostics - Clang now diagnoses when the result of a [[nodiscard]] function is discarded after being cast in C. Fixes #GH104391. +- Clang now properly explains the reason a template template argument failed to + match a template template parameter, in terms of the C++17 relaxed matching rules + instead of the old ones. + - Don't emit duplicated dangling diagnostics. (#GH93386). - Improved diagnostic when trying to befriend a concept. (#GH45182). @@ -885,6 +894,8 @@ Bug Fixes to C++ Support - Correctly check constraints of explicit instantiations of member functions. (#GH46029) - When performing partial ordering of function templates, clang now checks that the deduction was consistent. Fixes (#GH18291). +- Fixes to several issues in partial ordering of template template parameters, which + were documented in the test suite. - Fixed an assertion failure about a constraint of a friend function template references to a value with greater template depth than the friend function template. (#GH98258) - Clang now rebuilds the template parameters of out-of-line declarations and specializations in the context diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 36b693c6a304e7..774e5484cfa0e7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5323,6 +5323,13 @@ def note_template_arg_refers_here_func : Note< def err_template_arg_template_params_mismatch : Error< "template template argument has different template parameters than its " "corresponding template template parameter">; +def note_template_arg_template_params_mismatch : Note< + "template template argument has different template parameters than its " + "corresponding template template parameter">; +def err_non_deduced_mismatch : Error< + "could not match %diff{$ against $|types}0,1">; +def err_inconsistent_deduction : Error< + "conflicting deduction %diff{$ against $|types}0,1 for parameter">; def err_template_arg_not_integral_or_enumeral : Error< "non-type template argument of type %0 must have an integral or enumeration" " type">; diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 176a2a8d2a35e5..c7f2422b542dd1 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -930,6 +930,11 @@ class Sema; LLVM_PREFERRED_TYPE(bool) unsigned TookAddressOfOverload : 1; + /// Have we matched any packs on the parameter side, versus any non-packs on + /// the argument side, in a context where the opposite matching is also + /// allowed? + bool HasMatchedPackOnParmToNonPackOnArg : 1; + /// True if the candidate was found using ADL. LLVM_PREFERRED_TYPE(CallExpr::ADLCallKind) unsigned IsADLCandidate : 1; @@ -1006,6 +1011,7 @@ class Sema; OverloadCandidate() : IsSurrogate(false), IgnoreObjectArgument(false), TookAddressOfOverload(false), + HasMatchedPackOnParmToNonPackOnArg(false), IsADLCandidate(llvm::to_underlying(CallExpr::NotADL)), RewriteKind(CRK_None) {} }; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 9a9998b114e0f7..4d6e02fe2956e0 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10169,7 +10169,8 @@ class Sema final : public SemaBase { ADLCallKind IsADLCandidate = ADLCallKind::NotADL, ConversionSequenceList EarlyConversions = {}, OverloadCandidateParamOrder PO = {}, - bool AggregateCandidateDeduction = false); + bool AggregateCandidateDeduction = false, + bool HasMatchedPackOnParmToNonPackOnArg = false); /// Add all of the function declarations in the given function set to /// the overload candidate set. @@ -10204,7 +10205,8 @@ class Sema final : public SemaBase { bool SuppressUserConversions = false, bool PartialOverloading = false, ConversionSequenceList EarlyConversions = {}, - OverloadCandidateParamOrder PO = {}); + OverloadCandidateParamOrder PO = {}, + bool HasMatchedPackOnParmToNonPackOnArg = false); /// Add a C++ member function template as a candidate to the candidate /// set, using template argument deduction to produce an appropriate member @@ -10250,7 +10252,8 @@ class Sema final : public SemaBase { CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, - bool AllowExplicit, bool AllowResultConversion = true); + bool AllowExplicit, bool AllowResultConversion = true, + bool HasMatchedPackOnParmToNonPackOnArg = false); /// Adds a conversion function template specialization /// candidate to the overload set, using template argument deduction @@ -11678,7 +11681,8 @@ class Sema final : public SemaBase { SourceLocation RAngleLoc, unsigned ArgumentPackIndex, SmallVectorImpl<TemplateArgument> &SugaredConverted, SmallVectorImpl<TemplateArgument> &CanonicalConverted, - CheckTemplateArgumentKind CTAK); + CheckTemplateArgumentKind CTAK, bool PartialOrdering, + bool *MatchedPackOnParmToNonPackOnArg); /// Check that the given template arguments can be provided to /// the given template, converting the arguments along the way. @@ -11725,7 +11729,8 @@ class Sema final : public SemaBase { SmallVectorImpl<TemplateArgument> &SugaredConverted, SmallVectorImpl<TemplateArgument> &CanonicalConverted, bool UpdateArgsWithConversions = true, - bool *ConstraintsNotSatisfied = nullptr, bool PartialOrderingTTP = false); + bool *ConstraintsNotSatisfied = nullptr, bool PartialOrderingTTP = false, + bool *MatchedPackOnParmToNonPackOnArg = nullptr); bool CheckTemplateTypeArgument( TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg, @@ -11759,7 +11764,9 @@ class Sema final : public SemaBase { /// It returns true if an error occurred, and false otherwise. bool CheckTemplateTemplateArgument(TemplateTemplateParmDecl *Param, TemplateParameterList *Params, - TemplateArgumentLoc &Arg, bool IsDeduced); + TemplateArgumentLoc &Arg, + bool PartialOrdering, + bool *MatchedPackOnParmToNonPackOnArg); void NoteTemplateLocation(const NamedDecl &Decl, std::optional<SourceRange> ParamRange = {}); @@ -12270,8 +12277,8 @@ class Sema final : public SemaBase { SmallVectorImpl<DeducedTemplateArgument> &Deduced, unsigned NumExplicitlySpecified, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, - SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs = nullptr, - bool PartialOverloading = false, + SmallVectorImpl<OriginalCallArg> const *OriginalCallArgs, + bool PartialOverloading, bool PartialOrdering, llvm::function_ref<bool()> CheckNonDependent = [] { return false; }); /// Perform template argument deduction from a function call @@ -12305,7 +12312,8 @@ class Sema final : public SemaBase { TemplateArgumentListInfo *ExplicitTemplateArgs, ArrayRef<Expr *> Args, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info, bool PartialOverloading, bool AggregateDeductionCandidate, - QualType ObjectType, Expr::Classification ObjectClassification, + bool PartialOrdering, QualType ObjectType, + Expr::Classification ObjectClassification, llvm::function_ref<bool(ArrayRef<QualType>)> CheckNonDependent); /// Deduce template arguments when taking the address of a function @@ -12458,8 +12466,9 @@ class Sema final : public SemaBase { sema::TemplateDeductionInfo &Info); bool isTemplateTemplateParameterAtLeastAsSpecializedAs( - TemplateParameterList *PParam, TemplateDecl *AArg, - const DefaultArguments &DefaultArgs, SourceLocation Loc, bool IsDeduced); + TemplateParameterList *PParam, TemplateDecl *PArg, TemplateDecl *AArg, + const DefaultArguments &DefaultArgs, SourceLocation ArgLoc, + bool PartialOrdering, bool *MatchedPackOnParmToNonPackOnArg); /// Mark which template parameters are used in a given expression. /// @@ -12768,6 +12777,9 @@ class Sema final : public SemaBase { /// We are instantiating a type alias template declaration. TypeAliasTemplateInstantiation, + + /// We are performing partial ordering for template template parameters. + PartialOrderingTTP, } Kind; /// Was the enclosing context a non-instantiation SFINAE context? @@ -12989,6 +13001,12 @@ class Sema final : public SemaBase { TemplateDecl *Entity, BuildingDeductionGuidesTag, SourceRange InstantiationRange = SourceRange()); + struct PartialOrderingTTP {}; + /// \brief Note that we are partial ordering template template parameters. + InstantiatingTemplate(Sema &SemaRef, SourceLocation ArgLoc, + PartialOrderingTTP, TemplateDecl *PArg, + SourceRange InstantiationRange = SourceRange()); + /// Note that we have finished instantiating this template. void Clear(); @@ -13450,7 +13468,8 @@ class Sema final : public SemaBase { bool InstantiateClassTemplateSpecialization( SourceLocation PointOfInstantiation, ClassTemplateSpecializationDecl *ClassTemplateSpec, - TemplateSpecializationKind TSK, bool Complain = true); + TemplateSpecializationKind TSK, bool Complain = true, + bool PrimaryHasMatchedPackOnParmToNonPackOnArg = false); /// Instantiates the definitions of all of the member /// of the given class, which is an instantiation of a class template diff --git a/clang/include/clang/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h index 28b014fd84e4b3..9c12eef5c42a06 100644 --- a/clang/include/clang/Sema/TemplateDeduction.h +++ b/clang/include/clang/Sema/TemplateDeduction.h @@ -51,6 +51,11 @@ class TemplateDeductionInfo { /// Have we suppressed an error during deduction? bool HasSFINAEDiagnostic = false; + /// Have we matched any packs on the parameter side, versus any non-packs on + /// the argument side, in a context where the opposite matching is also + /// allowed? + bool MatchedPackOnParmToNonPackOnArg = false; + /// The template parameter depth for which we're performing deduction. unsigned DeducedDepth; @@ -87,6 +92,14 @@ class TemplateDeductionInfo { return DeducedDepth; } + bool hasMatchedPackOnParmToNonPackOnArg() const { + return MatchedPackOnParmToNonPackOnArg; + } + + void setMatchedPackOnParmToNonPackOnArg() { + MatchedPackOnParmToNonPackOnArg = true; + } + /// Get the number of explicitly-specified arguments. unsigned getNumExplicitArgs() const { return ExplicitArgs; diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 30dfa5481d070a..1ea4a2e9e88cf5 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -459,6 +459,8 @@ class DefaultTemplateInstCallback : public TemplateInstantiationCallback { return "BuildingDeductionGuides"; case CodeSynthesisContext::TypeAliasTemplateInstantiation: return "TypeAliasTemplateInstantiation"; + case CodeSynthesisContext::PartialOrderingTTP: + return "PartialOrderingTTP"; } return ""; } diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index e18e3c197383e2..2ed8d3608d49ec 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -3675,7 +3675,9 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, TemplateArgumentLoc Arg(TemplateArgument(StringLit), StringLit); if (CheckTemplateArgument( Params->getParam(0), Arg, FD, R.getNameLoc(), R.getNameLoc(), - 0, SugaredChecked, CanonicalChecked, CTAK_Specified) || + 0, SugaredChecked, CanonicalChecked, CTAK_Specified, + /*PartialOrdering=*/false, + /*MatchedPackOnParmToNonPackOnArg=*/nullptr) || Trap.hasErrorOccurred()) IsTemplate = false; } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 23056ca5deba3c..6ae9c51c06b315 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -6917,7 +6917,8 @@ void Sema::AddOverloadCandidate( OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, bool PartialOverloading, bool AllowExplicit, bool AllowExplicitConversions, ADLCallKind IsADLCandidate, ConversionSequenceList EarlyConversions, - OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction) { + OverloadCandidateParamOrder PO, bool AggregateCandidateDeduction, + bool HasMatchedPackOnParmToNonPackOnArg) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Function->getType()->getAs<FunctionType>()); assert(Proto && "Functions without a prototype cannot be overloaded"); @@ -6936,7 +6937,8 @@ void Sema::AddOverloadCandidate( AddMethodCandidate(Method, FoundDecl, Method->getParent(), QualType(), Expr::Classification::makeSimpleLValue(), Args, CandidateSet, SuppressUserConversions, - PartialOverloading, EarlyConversions, PO); + PartialOverloading, EarlyConversions, PO, + HasMatchedPackOnParmToNonPackOnArg); return; } // We treat a constructor like a non-member function, since its object @@ -6979,6 +6981,8 @@ void Sema::AddOverloadCandidate( CandidateSet.getRewriteInfo().getRewriteKind(Function, PO); Candidate.IsADLCandidate = llvm::to_underlying(IsADLCandidate); Candidate.ExplicitCallArguments = Args.size(); + Candidate.HasMatchedPackOnParmToNonPackOnArg = + HasMatchedPackOnParmToNonPackOnArg; // Explicit functions are not actually candidates at all if we're not // allowing them in this context, but keep them around so we can point @@ -7521,16 +7525,13 @@ void Sema::AddMethodCandidate(DeclAccessPair FoundDecl, QualType ObjectType, } } -void -Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, - CXXRecordDecl *ActingContext, QualType ObjectType, - Expr::Classification ObjectClassification, - ArrayRef<Expr *> Args, - OverloadCandidateSet &CandidateSet, - bool SuppressUserConversions, - bool PartialOverloading, - ConversionSequenceList EarlyConversions, - OverloadCandidateParamOrder PO) { +void Sema::AddMethodCandidate( + CXXMethodDecl *Method, DeclAccessPair FoundDecl, + CXXRecordDecl *ActingContext, QualType ObjectType, + Expr::Classification ObjectClassification, ArrayRef<Expr *> Args, + OverloadCandidateSet &CandidateSet, bool SuppressUserConversions, + bool PartialOverloading, ConversionSequenceList EarlyConversions, + OverloadCandidateParamOrder PO, bool HasMatchedPackOnParmToNonPackOnArg) { const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(Method->getType()->getAs<FunctionType>()); assert(Proto && "Methods without a prototype cannot be overloaded"); @@ -7561,6 +7562,8 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl, Candidate.TookAddressOfOverload = CandidateSet.getKind() == OverloadCandidateSet::CSK_AddressOfOverloadSet; Candidate.ExplicitCallArguments = Args.size(); + Candidate.HasMatchedPackOnParmToNonPackOnArg = + HasMatchedPackOnParmToNonPackOnArg; bool IgnoreExplicitObject = (Method->isExplicitObjectMemberFunction() && @@ -7731,8 +7734,8 @@ void Sema::AddMethodTemplateCandidate( ConversionSequenceList Conversions; if (TemplateDeductionResult Result = DeduceTemplateArguments( MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info, - PartialOverloading, /*AggregateDeductionCandidate=*/false, ObjectType, - ObjectClassification, + PartialOverloading, /*AggregateDeductionCandidate=*/false, + /*PartialOrdering=*/false, ObjectType, ObjectClassification, [&](ArrayRef<QualType> ParamTypes) { return CheckNonDependentConversions( MethodTmpl, ParamTypes, Args, CandidateSet, Conversions, @@ -7770,7 +7773,8 @@ void Sema::AddMethodTemplateCandidate( AddMethodCandidate(cast<CXXMethodDecl>(Specialization), FoundDecl, ActingContext, ObjectType, ObjectClassification, Args, CandidateSet, SuppressUserConversions, PartialOverloading, - Conversions, PO); + Conversions, PO, + Info.hasMatchedPackOnParmToNonPackOnArg()); } /// Determine whether a given function template has a simple explicit specifier @@ -7816,6 +7820,7 @@ void Sema::AddTemplateOverloadCandidate( if (TemplateDeductionResult Result = DeduceTemplateArguments( FunctionTemplate, ExplicitTemplateArgs, Args, Specialization, Info, PartialOverloading, AggregateCandidateDeduction, + /*PartialOrdering=*/false, /*ObjectType=*/QualType(), /*ObjectClassification=*/Expr::Classification(), [&](ArrayRef<QualType> ParamTypes) { @@ -7856,7 +7861,8 @@ void Sema::AddTemplateOverloadCandidate( Specialization, FoundDecl, Args, CandidateSet, SuppressUserConversions, PartialOverloading, AllowExplicit, /*AllowExplicitConversions=*/false, IsADLCandidate, Conversions, PO, - Info.AggregateDeductionCandidateHasMismatchedArity); + Info.AggregateDeductionCandidateHasMismatchedArity, + Info.hasMatchedPackOnParmToNonPackOnArg()); } bool Sema::CheckNonDependentConversions( @@ -7978,7 +7984,8 @@ void Sema::AddConversionCandidate( CXXConversionDecl *Conversion, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, - bool AllowExplicit, bool AllowResultConversion) { + bool AllowExplicit, bool AllowResultConversion, + bool HasMatchedPackOnParmToNonPackOnArg) { assert(!Conversion->getDescribedFunctionTemplate() && "Conversion function templates use AddTemplateConversionCandidate"); QualType ConvType = Convers... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/124137 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits