https://github.com/IvyXu420 updated 
https://github.com/llvm/llvm-project/pull/237738

>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/3] 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/3] 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) {

>From 4a8f3e193a8596a33ceae04f04fd66ab4477a58b Mon Sep 17 00:00:00 2001
From: Ivy Xu <[email protected]>
Date: Sun, 1 Nov 2026 22:28:45 +0800
Subject: [PATCH 3/3] Fix code formatting

---
 clang/lib/Sema/SemaOverload.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index 87f20465a56b75..02f95db586906f 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -8891,7 +8891,8 @@ void Sema::AddTemplateConversionCandidate(
 
   CandidateSet.AddDeferredConversionTemplateCandidate(
       FunctionTemplate, FoundDecl, ActingDC, From, ToType,
-      AllowObjCConversionOnExplicit, AllowExplicit, AllowResultConversion, 
AllowRValues);
+      AllowObjCConversionOnExplicit, AllowExplicit, AllowResultConversion,
+      AllowRValues);
 }
 
 void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to