From a2f156b84ab124ccfbbe2bd6cbbdb2f3bcbba0ce Mon Sep 17 00:00:00 2001 From: cor3ntin Date: Thu, 15 May 2025 15:29:56 +0200 Subject: [PATCH] [Clang] Fix deduction of explicit object member functions (#140030) When taking the address of an overload set containing an explicit object member, we should not take the explicit object parameter into account. --- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/Sema/Sema.h | 1 + clang/lib/Sema/SemaOverload.cpp | 4 ++++ clang/lib/Sema/SemaTemplateDeduction.cpp | 11 ++++++++- clang/test/SemaCXX/cxx2b-deducing-this.cpp | 27 ++++++++++++++++++++++ 5 files changed, 43 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 31c517338c21..1f17bc6e5c8e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -710,6 +710,7 @@ Bug Fixes to C++ Support - Clang now correctly parses arbitrary order of ``[[]]``, ``__attribute__`` and ``alignas`` attributes for declarations (#GH133107) - Fixed a crash when forming an invalid function type in a dependent context. (#GH138657) (#GH115725) (#GH68852) - Clang no longer segfaults when there is a configuration mismatch between modules and their users (http://crbug.com/400353616). +- Fix an incorrect deduction when calling an explicit object member function template through an overload set address. Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6ea7ee281e14..5ec67087aeea 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -12576,6 +12576,7 @@ public: bool PartialOverloading, bool AggregateDeductionCandidate, bool PartialOrdering, QualType ObjectType, Expr::Classification ObjectClassification, + bool ForOverloadSetAddressResolution, llvm::function_ref)> CheckNonDependent); /// Deduce template arguments when taking the address of a function diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index e20a41c10cca..23304e12f8c3 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -7846,6 +7846,8 @@ static void AddMethodTemplateCandidateImmediately( MethodTmpl, ExplicitTemplateArgs, Args, Specialization, Info, PartialOverloading, /*AggregateDeductionCandidate=*/false, /*PartialOrdering=*/false, ObjectType, ObjectClassification, + CandidateSet.getKind() == + clang::OverloadCandidateSet::CSK_AddressOfOverloadSet, [&](ArrayRef ParamTypes) { return S.CheckNonDependentConversions( MethodTmpl, ParamTypes, Args, CandidateSet, Conversions, @@ -7960,6 +7962,8 @@ static void AddTemplateOverloadCandidateImmediately( /*PartialOrdering=*/false, /*ObjectType=*/QualType(), /*ObjectClassification=*/Expr::Classification(), + CandidateSet.getKind() == + OverloadCandidateSet::CSK_AddressOfOverloadSet, [&](ArrayRef ParamTypes) { return S.CheckNonDependentConversions( FunctionTemplate, ParamTypes, Args, CandidateSet, Conversions, diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 5dc06ebc2a23..217d57d67f06 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -4432,6 +4432,7 @@ TemplateDeductionResult Sema::DeduceTemplateArguments( bool PartialOverloading, bool AggregateDeductionCandidate, bool PartialOrdering, QualType ObjectType, Expr::Classification ObjectClassification, + bool ForOverloadSetAddressResolution, llvm::function_ref)> CheckNonDependent) { if (FunctionTemplate->isInvalidDecl()) return TemplateDeductionResult::Invalid; @@ -4440,7 +4441,15 @@ TemplateDeductionResult Sema::DeduceTemplateArguments( unsigned NumParams = Function->getNumParams(); bool HasExplicitObject = false; int ExplicitObjectOffset = 0; - if (Function->hasCXXExplicitFunctionObjectParameter()) { + + // [C++26] [over.call.func]p3 + // If the primary-expression is the address of an overload set, + // the argument list is the same as the expression-list in the call. + // Otherwise, the argument list is the expression-list in the call augmented + // by the addition of an implied object argument as in a qualified function + // call. + if (!ForOverloadSetAddressResolution && + Function->hasCXXExplicitFunctionObjectParameter()) { HasExplicitObject = true; ExplicitObjectOffset = 1; } diff --git a/clang/test/SemaCXX/cxx2b-deducing-this.cpp b/clang/test/SemaCXX/cxx2b-deducing-this.cpp index 7e392213710a..2286da8d1c0e 100644 --- a/clang/test/SemaCXX/cxx2b-deducing-this.cpp +++ b/clang/test/SemaCXX/cxx2b-deducing-this.cpp @@ -926,6 +926,33 @@ struct C { (&fref)(); } }; + +struct CTpl { + template + constexpr int c(this const CTpl&, T) { // #P2797-ctpl-1 + return 42; + } + + template + void c(T)&; // #P2797-ctpl-2 + + template + static void c(T = 0, T = 0); // #P2797-ctpl-3 + + void d() { + c(0); // expected-error {{call to member function 'c' is ambiguous}} + // expected-note@#P2797-ctpl-1{{candidate}} + // expected-note@#P2797-ctpl-2{{candidate}} + // expected-note@#P2797-ctpl-3{{candidate}} + (CTpl::c)(0); // expected-error {{call to member function 'c' is ambiguous}} + // expected-note@#P2797-ctpl-1{{candidate}} + // expected-note@#P2797-ctpl-2{{candidate}} + // expected-note@#P2797-ctpl-3{{candidate}} + + static_assert((&CTpl::c)(CTpl{}, 0) == 42); // selects #1 + } +}; + } namespace GH85992 {