https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/192018
>From 7124eafc69f02363f9289e6bb83d4d95dbf5138d Mon Sep 17 00:00:00 2001 From: Corentin Jabot <[email protected]> Date: Tue, 14 Apr 2026 09:57:57 +0200 Subject: [PATCH 1/2] [Clang] Fix handling of overloads differing only by constraints and ref-qualifiers. We ashould only error about inconsistent qualifiers if the functions are actually overloads. Fixes #120812 --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/Sema/SemaOverload.cpp | 26 +++++++++++++++++--------- clang/test/CXX/drs/cwg24xx.cpp | 11 +++++++++++ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3e2d287d1eb1f..9e4699d642332 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -434,6 +434,7 @@ Bug Fixes to C++ Support - We no longer caches invalid variable specializations. (#GH132592) - Fixed an incorrect template argument deduction when matching packs of template template parameters when one of its parameters is also a pack. (#GH181166) +- Clang no longer errors on overloads with different ref-qualifiers and constraints. (#GH120812) - Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639) - Fixed an alias template CTAD crash. - Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 11e771bc240f1..170699085ea11 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1521,6 +1521,12 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, return false; }; + // We look at the parameters first, as it is the common case. + // However we should not emit diagnostic before checking + // the overloads do not differ by constraints or other discriminant. + bool ShouldDiagnoseInconsistentRefQualifiers = false; + bool HaveInconsistentQualifiers = false; + if (OldMethod && OldMethod->isExplicitObjectMemberFunction()) OldParamsOffset++; if (NewMethod && NewMethod->isExplicitObjectMemberFunction()) @@ -1557,17 +1563,20 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, }(OldMethod, NewMethod); if (!HaveCorrespondingObjectParameters) { - if (DiagnoseInconsistentRefQualifiers()) - return true; + ShouldDiagnoseInconsistentRefQualifiers = true; // CWG2554 // and, if at least one is an explicit object member function, ignoring // object parameters if (!UseOverrideRules || (!NewMethod->isExplicitObjectMemberFunction() && !OldMethod->isExplicitObjectMemberFunction())) - return true; + HaveInconsistentQualifiers = true; } } + if (NewMethod && OldMethod && OldMethod->isImplicitObjectMemberFunction() && + NewMethod->isImplicitObjectMemberFunction()) + ShouldDiagnoseInconsistentRefQualifiers = true; + if (!UseOverrideRules && New->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) { AssociatedConstraint NewRC = New->getTrailingRequiresClause(), @@ -1582,12 +1591,6 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, return true; } - if (NewMethod && OldMethod && OldMethod->isImplicitObjectMemberFunction() && - NewMethod->isImplicitObjectMemberFunction()) { - if (DiagnoseInconsistentRefQualifiers()) - return true; - } - // Though pass_object_size is placed on parameters and takes an argument, we // consider it to be a function-level modifier for the sake of function // identity. Either the function has one or more parameters with @@ -1612,6 +1615,11 @@ static bool IsOverloadOrOverrideImpl(Sema &SemaRef, FunctionDecl *New, return true; } + if ((ShouldDiagnoseInconsistentRefQualifiers && + DiagnoseInconsistentRefQualifiers()) || + HaveInconsistentQualifiers) + return true; + // At this point, it is known that the two functions have the same signature. if (SemaRef.getLangOpts().CUDA && ConsiderCudaAttrs) { // Don't allow overloading of destructors. (In theory we could, but it diff --git a/clang/test/CXX/drs/cwg24xx.cpp b/clang/test/CXX/drs/cwg24xx.cpp index b27c6b823940c..0a6a05c125451 100644 --- a/clang/test/CXX/drs/cwg24xx.cpp +++ b/clang/test/CXX/drs/cwg24xx.cpp @@ -212,5 +212,16 @@ struct T : S { virtual void k() &; virtual void l() &&; }; +#if __cplusplus >= 202002L + +// We should not error on inconsistent ref-qualifiers if the functions +// have different constraints. +template <unsigned R> struct type { + void func() const requires(R == 0); + void func() & requires(R == 1); +}; + +#endif + #endif } >From 213b47c591caebf61477a44d9a3930e47da55645 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <[email protected]> Date: Tue, 14 Apr 2026 16:38:16 +0200 Subject: [PATCH 2/2] [Clang] Add default arguments to the parameter mapping. We were not adding default argument to the parameter mapping as such, two constraint which only differed by the mapping of a parameter only referenced in a default argument were considered identical. Fixes #188640 --- clang/docs/ReleaseNotes.rst | 2 +- clang/include/clang/AST/ASTContext.h | 4 +++ clang/lib/AST/ASTContext.cpp | 4 +-- clang/lib/Sema/SemaConcept.cpp | 19 ++++++++++++ clang/test/SemaTemplate/concepts.cpp | 45 ++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 3 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 9e4699d642332..e5040109edcf3 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -386,7 +386,7 @@ Bug Fixes in This Version ------------------------- - Fixed atomic boolean compound assignment; the conversion back to atomic bool would be miscompiled. (#GH33210) - +- Correctly handle default template argument when establishing subsumption. (#GH188640) - Fixed a failed assertion in the preprocessor when ``__has_embed`` parameters are missing parentheses. (#GH175088) - Fix lifetime extension of temporaries in for-range-initializers in templates. (#GH165182) - Fixed a preprocessor crash in ``__has_cpp_attribute`` on incomplete scoped attributes. (#GH178098) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ba1b58489c327..a412ef91ef16d 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -3071,6 +3071,10 @@ class ASTContext : public RefCountedBase<ASTContext> { TemplateName getCanonicalTemplateName(TemplateName Name, bool IgnoreDeduced = false) const; + /// Return the default argument of a template parameter, if one exists. + const TemplateArgument * + getDefaultTemplateArgumentOrNone(const NamedDecl *P) const; + /// Determine whether the given template names refer to the same /// template. bool hasSameTemplateName(const TemplateName &X, const TemplateName &Y, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index ee7f823b014b2..f73f613a2d35a 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -7305,8 +7305,8 @@ ASTContext::getNameForTemplate(TemplateName Name, llvm_unreachable("bad template name kind!"); } -static const TemplateArgument * -getDefaultTemplateArgumentOrNone(const NamedDecl *P) { +const TemplateArgument * +ASTContext::getDefaultTemplateArgumentOrNone(const NamedDecl *P) const { auto handleParam = [](auto *TP) -> const TemplateArgument * { if (!TP->hasDefaultArgument()) return nullptr; diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 3f04922a5647e..dfab7c919a303 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -2105,6 +2105,25 @@ void SubstituteParameterMappings::buildParameterMapping( SemaRef.MarkUsedTemplateParameters(Args->arguments(), /*Depth=*/0, OccurringIndices); } + + // If a parameter is only referenced in a default template argument, + // we need to add it to the mapping explicitly. + { + llvm::SmallVector<TemplateArgument> DefaultArgs; + for (unsigned I = TemplateParams->getMinRequiredArguments(); + I < TemplateParams->size(); I++) { + const NamedDecl *Param = TemplateParams->getParam(I); + if (Param->isParameterPack()) + break; + const TemplateArgument *Arg = + SemaRef.getASTContext().getDefaultTemplateArgumentOrNone(Param); + assert(Arg && "expected a default argument"); + DefaultArgs.emplace_back(std::move(*Arg)); + } + SemaRef.MarkUsedTemplateParameters(DefaultArgs, /*Depth=*/0, + OccurringIndices); + } + unsigned Size = OccurringIndices.count(); // When the constraint is independent of any template parameters, // we build an empty mapping so that we can distinguish these cases diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp index ac80d16b4ccf8..c8b5cbac82f89 100644 --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -1835,3 +1835,48 @@ namespace GH191016 { }; void test(){ S<int> s; } } + + +namespace GH188640 { + +namespace Ex1 { +template <typename T> constexpr bool CC = true; + +template <typename V, typename U = V> +concept C = CC<U>; + +template <typename T> +constexpr int f() + requires C<T> && C<T *> +{ + return 21; +} + +template <typename T> +void f() + requires C<T>; + +void g() { static_assert(f<void>() == 21); } + +} // namespace Ex1 + +namespace VAR { +template <auto N> constexpr bool CC = true; +template <auto V, auto U = V> +concept C = CC<U>; + +template <auto V> +constexpr int f() + requires C<V> && C<V + 1> +{ + return 42; +} + +template <auto N> +int f() + requires C<N>; + +void g() { static_assert(f<1>() == 42); } +} // namespace VAR + +} // namespace GH188640 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
