https://github.com/IvyXu420 created https://github.com/llvm/llvm-project/pull/237738
This reverts commit https://github.com/llvm/llvm-project/commit/9022da974a0df0d4f09021f2ee141278e0b34b38. This reland rejects invalid template specializations in `AddTemplateConversionCandidateImmediately(...)`, which was the missed part in the previous fix. Closes #226984. >From e766792d49b06235127d95d6ad3480101ec4b00f Mon Sep 17 00:00:00 2001 From: Ivy Xu <[email protected]> Date: Sun, 1 Nov 2026 20:41:36 +0800 Subject: [PATCH 1/2] Reapply "[Clang][Sema] Fix rejecting valid reference initialization with conversion function templates" (#237716) This reverts commit 9022da974a0df0d4f09021f2ee141278e0b34b38. --- clang/docs/ReleaseNotes.md | 3 +++ clang/lib/Sema/SemaInit.cpp | 7 ++++--- clang/test/SemaCXX/conversion-function.cpp | 13 +++++++++++++ clang/test/SemaCXX/cxx1y-generic-lambdas.cpp | 4 +++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index d2df8fe262fbff..a2ad6d06815c7c 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -897,6 +897,9 @@ documentation](CIR/index.md) for more information regarding ClangIR's status and `sized_by_or_null` describe the size in bytes rather than a count of elements, they are now correctly accepted on such pointers. +- Fixed rejecting valid reference initialization with conversion function templates whose returned type is depending on + template parameters. (#GH226984) + - Fixed a crash when an `address_space` attribute with a dependent argument was written after the declarator-id, where it appertains to the declared entity rather than to a declarator chunk. (#GH196982, #GH111463) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 2e3c6309fec20e..d9134c052fa9df 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -5384,12 +5384,13 @@ static OverloadingResult TryRefInitWithConversionFunction( // If the conversion function doesn't return a reference type, // it can't be considered for this conversion unless we're allowed to - // consider rvalues. + // consider rvalues. If it's a template, we should accept it first + // and specialize it before deciding whether to reject it. // FIXME: Do we need to make sure that we only consider conversion // candidates with reference-compatible results? That might be needed to // break recursion. - if ((AllowRValues || - Conv->getConversionType()->isLValueReferenceType())) { + if (ConvTemplate || AllowRValues || + Conv->getConversionType()->isLValueReferenceType()) { if (ConvTemplate) S.AddTemplateConversionCandidate( ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, diff --git a/clang/test/SemaCXX/conversion-function.cpp b/clang/test/SemaCXX/conversion-function.cpp index 1a09a527b750cc..629c818b89c004 100644 --- a/clang/test/SemaCXX/conversion-function.cpp +++ b/clang/test/SemaCXX/conversion-function.cpp @@ -557,3 +557,16 @@ namespace GH189146 { int s = S{}(0); // expected-error {{attempt to use a deleted function}} } #endif + +#if __cplusplus >= 201402L +namespace GH226984 { + struct A { + int& ref; + + template<int dependent = 0> + operator decltype(dependent, ref)(); +}; + int x = 0; + int& y = A(x); +} +#endif diff --git a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp b/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp index 3066bb0d0f0cc3..bb621666319046 100644 --- a/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp +++ b/clang/test/SemaCXX/cxx1y-generic-lambdas.cpp @@ -214,7 +214,9 @@ namespace conversion_operator { void test() { auto L = [](auto a) -> int { return a; }; // expected-error {{cannot initialize}} int (*fp)(int) = L; - int (&fp2)(int) = [](auto a) { return a; }; // expected-error{{non-const lvalue}} + int (&fp2)(int) = [](auto a) { return a; }; + // expected-error@-1 {{no viable conversion}} + // expected-note-re@-2 {{candidate template ignored: could not match 'auto (*)(auto){{.*}}' against 'int (int)'}} int (&&fp3)(int) = [](auto a) { return a; }; // expected-error@-1 {{no viable conversion}} // expected-note-re@-2 {{candidate template ignored: could not match 'auto (*)(auto){{.*}}' against 'int (int)'}} >From ae5864876af60e2eff6bcb8b6e5c0aed2de7c28c Mon Sep 17 00:00:00 2001 From: Ivy Xu <[email protected]> Date: Sun, 1 Nov 2026 22:03:21 +0800 Subject: [PATCH 2/2] Reject invalid template specializations in `AddTemplateConversionCandidateImmediately()` --- clang/include/clang/Sema/Overload.h | 3 ++- clang/include/clang/Sema/Sema.h | 3 ++- clang/lib/Sema/SemaInit.cpp | 3 ++- clang/lib/Sema/SemaOverload.cpp | 21 +++++++++++++-------- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index f280c6ffa5a810..bb317aa094172c 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -1154,6 +1154,7 @@ class Sema; CXXRecordDecl *ActingContext; Expr *From; QualType ToType; + bool AllowRValues; }; static_assert(std::is_trivially_destructible_v< @@ -1459,7 +1460,7 @@ class Sema; FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, bool AllowObjCConversionOnExplicit, bool AllowExplicit, - bool AllowResultConversion); + bool AllowResultConversion, bool AllowRValues); void InjectNonDeducedTemplateCandidates(Sema &S); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index ba215e7e18d7ba..698bfe1da75e09 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10743,7 +10743,8 @@ class Sema final : public SemaBase { FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, - bool AllowExplicit, bool AllowResultConversion = true); + bool AllowExplicit, bool AllowResultConversion = true, + bool AllowRValues = true); /// AddSurrogateCandidate - Adds a "surrogate" candidate function that /// converts the given @c Object to a function pointer via the diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index d9134c052fa9df..4b241714a1cea0 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -5395,7 +5395,8 @@ static OverloadingResult TryRefInitWithConversionFunction( S.AddTemplateConversionCandidate( ConvTemplate, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, - /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs); + /*AllowObjCConversionOnExplicit=*/false, AllowExplicitConvs, + /*AllowResultConversion=*/true, AllowRValues); else S.AddConversionCandidate( Conv, I.getPair(), ActingDC, Initializer, DestType, CandidateSet, diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 8219d5568bdfdd..87f20465a56b75 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -8818,7 +8818,7 @@ static void AddTemplateConversionCandidateImmediately( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, bool AllowObjCConversionOnExplicit, bool AllowExplicit, - bool AllowResultConversion) { + bool AllowResultConversion, bool AllowRValues) { // If the function template has a non-dependent explicit specification, // exclude it now if appropriate; we are not permitted to perform deduction @@ -8852,9 +8852,13 @@ static void AddTemplateConversionCandidateImmediately( return; } + assert(Specialization && "Missing function template specialization?"); + // Reject invalid template specialization. + if (!AllowRValues && + !Specialization->getConversionType()->isLValueReferenceType()) + return; // Add the conversion function template specialization produced by // template argument deduction as a candidate. - assert(Specialization && "Missing function template specialization?"); S.AddConversionCandidate(Specialization, FoundDecl, ActingContext, From, ToType, CandidateSet, AllowObjCConversionOnExplicit, AllowExplicit, AllowResultConversion, @@ -8865,7 +8869,7 @@ void Sema::AddTemplateConversionCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, CXXRecordDecl *ActingDC, Expr *From, QualType ToType, OverloadCandidateSet &CandidateSet, bool AllowObjCConversionOnExplicit, - bool AllowExplicit, bool AllowResultConversion) { + bool AllowExplicit, bool AllowResultConversion, bool AllowRValues) { assert(isa<CXXConversionDecl>(FunctionTemplate->getTemplatedDecl()) && "Only conversion function templates permitted here"); @@ -8879,7 +8883,7 @@ void Sema::AddTemplateConversionCandidate( AddTemplateConversionCandidateImmediately( *this, CandidateSet, FunctionTemplate, FoundDecl, ActingDC, From, ToType, AllowObjCConversionOnExplicit, AllowExplicit, - AllowResultConversion); + AllowResultConversion, AllowRValues); CandidateSet.DisableResolutionByPerfectCandidate(); return; @@ -8887,7 +8891,7 @@ void Sema::AddTemplateConversionCandidate( CandidateSet.AddDeferredConversionTemplateCandidate( FunctionTemplate, FoundDecl, ActingDC, From, ToType, - AllowObjCConversionOnExplicit, AllowExplicit, AllowResultConversion); + AllowObjCConversionOnExplicit, AllowExplicit, AllowResultConversion, AllowRValues); } void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion, @@ -11593,7 +11597,7 @@ void OverloadCandidateSet::AddDeferredConversionTemplateCandidate( FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, Expr *From, QualType ToType, bool AllowObjCConversionOnExplicit, bool AllowExplicit, - bool AllowResultConversion) { + bool AllowResultConversion, bool AllowRValues) { auto *C = allocateDeferredCandidate<DeferredConversionTemplateOverloadCandidate>(); @@ -11609,7 +11613,8 @@ void OverloadCandidateSet::AddDeferredConversionTemplateCandidate( FoundDecl, ActingContext, From, - ToType}; + ToType, + AllowRValues}; } static void @@ -11638,7 +11643,7 @@ AddTemplateOverloadCandidate(Sema &S, OverloadCandidateSet &CandidateSet, return AddTemplateConversionCandidateImmediately( S, CandidateSet, C.FunctionTemplate, C.FoundDecl, C.ActingContext, C.From, C.ToType, C.AllowObjCConversionOnExplicit, C.AllowExplicit, - C.AllowResultConversion); + C.AllowResultConversion, C.AllowRValues); } void OverloadCandidateSet::InjectNonDeducedTemplateCandidates(Sema &S) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
