https://github.com/DataCorrupted updated 
https://github.com/llvm/llvm-project/pull/178524

>From f57c297bc41117d67a5d89d06f78ac2b030b4de3 Mon Sep 17 00:00:00 2001
From: Peter Rong <[email protected]>
Date: Thu, 22 Jan 2026 14:48:30 -0800
Subject: [PATCH 1/2] [clang] Fix sema

clang can't handle objc lifetime correctly when casting
add a test
---
 clang/lib/Sema/SemaInit.cpp | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index ff278bc7471bd..117c2e4e6674d 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5651,6 +5651,13 @@ static void TryReferenceInitializationCore(Sema &S,
       T1QualsIgnoreAS.removeAddressSpace();
       T2QualsIgnoreAS.removeAddressSpace();
     }
+    // Postpone ObjC lifetime conversions to after the temporary 
materialization
+    // conversion, similar to address space conversions. This handles cases 
like
+    // binding a __strong rvalue to a const __autoreleasing reference.
+    if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime()) {
+      T1QualsIgnoreAS.removeObjCLifetime();
+      T2QualsIgnoreAS.removeObjCLifetime();
+    }
     QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1QualsIgnoreAS);
     if (T1QualsIgnoreAS != T2QualsIgnoreAS)
       Sequence.AddQualificationConversionStep(cv1T4, ValueKind);
@@ -5664,6 +5671,14 @@ static void TryReferenceInitializationCore(Sema &S,
       Sequence.AddQualificationConversionStep(cv1T4WithAS, ValueKind);
       cv1T4 = cv1T4WithAS;
     }
+    // Add ObjC lifetime conversion if required.
+    if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime()) {
+      auto T4Quals = cv1T4.getQualifiers();
+      T4Quals.setObjCLifetime(T1Quals.getObjCLifetime());
+      QualType cv1T4WithLifetime = S.Context.getQualifiedType(T2, T4Quals);
+      Sequence.AddQualificationConversionStep(cv1T4WithLifetime, ValueKind);
+      cv1T4 = cv1T4WithLifetime;
+    }
 
     //   In any case, the reference is bound to the resulting glvalue (or to
     //   an appropriate base class subobject).

>From bea74c7aabe1bd5f2eba2567c374c6be3047bbcc Mon Sep 17 00:00:00 2001
From: Peter Rong <[email protected]>
Date: Thu, 22 Jan 2026 14:48:30 -0800
Subject: [PATCH 2/2] Address reviewers

---
 clang/lib/Sema/SemaInit.cpp                   | 22 ++++++-----
 .../arc-lifetime-rvalue-ref-binding.mm        | 39 +++++++++++++++++++
 2 files changed, 52 insertions(+), 9 deletions(-)
 create mode 100644 clang/test/SemaObjCXX/arc-lifetime-rvalue-ref-binding.mm

diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 117c2e4e6674d..fad1a7775dc5c 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -5645,21 +5645,22 @@ static void TryReferenceInitializationCore(Sema &S,
     //   applied.
     // Postpone address space conversions to after the temporary 
materialization
     // conversion to allow creating temporaries in the alloca address space.
-    auto T1QualsIgnoreAS = T1Quals;
-    auto T2QualsIgnoreAS = T2Quals;
+    auto T1QualsIgnoreConvertions = T1Quals;
+    auto T2QualsIgnoreConvertions = T2Quals;
     if (T1Quals.getAddressSpace() != T2Quals.getAddressSpace()) {
-      T1QualsIgnoreAS.removeAddressSpace();
-      T2QualsIgnoreAS.removeAddressSpace();
+      T1QualsIgnoreConvertions.removeAddressSpace();
+      T2QualsIgnoreConvertions.removeAddressSpace();
     }
     // Postpone ObjC lifetime conversions to after the temporary 
materialization
     // conversion, similar to address space conversions. This handles cases 
like
     // binding a __strong rvalue to a const __autoreleasing reference.
     if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime()) {
-      T1QualsIgnoreAS.removeObjCLifetime();
-      T2QualsIgnoreAS.removeObjCLifetime();
+      T1QualsIgnoreConvertions.removeObjCLifetime();
+      T2QualsIgnoreConvertions.removeObjCLifetime();
     }
-    QualType cv1T4 = S.Context.getQualifiedType(cv2T2, T1QualsIgnoreAS);
-    if (T1QualsIgnoreAS != T2QualsIgnoreAS)
+    QualType cv1T4 =
+        S.Context.getQualifiedType(cv2T2, T1QualsIgnoreConvertions);
+    if (T1QualsIgnoreConvertions != T2QualsIgnoreConvertions)
       Sequence.AddQualificationConversionStep(cv1T4, ValueKind);
     Sequence.AddReferenceBindingStep(cv1T4, ValueKind == VK_PRValue);
     ValueKind = isLValueRef ? VK_LValue : VK_XValue;
@@ -5675,7 +5676,10 @@ static void TryReferenceInitializationCore(Sema &S,
     if (T1Quals.getObjCLifetime() != T2Quals.getObjCLifetime()) {
       auto T4Quals = cv1T4.getQualifiers();
       T4Quals.setObjCLifetime(T1Quals.getObjCLifetime());
-      QualType cv1T4WithLifetime = S.Context.getQualifiedType(T2, T4Quals);
+      // Apply T4Quals to the unqualified base type to avoid conflicting
+      // ObjC lifetime qualifiers in getQualifiedType.
+      QualType cv1T4WithLifetime =
+          S.Context.getQualifiedType(cv1T4.getUnqualifiedType(), T4Quals);
       Sequence.AddQualificationConversionStep(cv1T4WithLifetime, ValueKind);
       cv1T4 = cv1T4WithLifetime;
     }
diff --git a/clang/test/SemaObjCXX/arc-lifetime-rvalue-ref-binding.mm 
b/clang/test/SemaObjCXX/arc-lifetime-rvalue-ref-binding.mm
new file mode 100644
index 0000000000000..5db3f59f8fa08
--- /dev/null
+++ b/clang/test/SemaObjCXX/arc-lifetime-rvalue-ref-binding.mm
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -fobjc-arc -verify %s
+// RUN: %clang_cc1 -std=c++17 -fobjc-arc -ast-dump %s 2>&1 | FileCheck %s
+// expected-no-diagnostics
+
+// Test for binding ObjC ARC __strong rvalues to const __autoreleasing 
references.
+// This previously caused an assertion failure in 
Qualifiers::addConsistentQualifiers
+// when the compiler attempted to add conflicting ObjC lifetime qualifiers.
+
+// The const id& parameter has implicit __autoreleasing lifetime.
+void take(const id&);
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_rvalue_binding
+// CHECK: CallExpr
+// CHECK: ImplicitCastExpr {{.*}} 'const __autoreleasing id' lvalue <NoOp>
+// CHECK-NEXT: CXXStaticCastExpr {{.*}} '__strong id' xvalue 
static_cast<__strong id &&> <NoOp>
+void test_rvalue_binding() {
+  id obj = nullptr;
+  take(static_cast<id&&>(obj));
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_lvalue_binding
+// CHECK: CallExpr
+// CHECK: ImplicitCastExpr {{.*}} 'const __autoreleasing id' lvalue <NoOp>
+// CHECK-NEXT: DeclRefExpr {{.*}} '__strong id' lvalue
+void test_lvalue_binding() {
+  id obj = nullptr;
+  take(obj);
+}
+
+// Test with fold expressions and perfect forwarding (original crash case).
+template <typename... Args>
+void call(Args... args) {
+  (take(static_cast<Args&&>(args)), ...);
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} test_fold_expression
+void test_fold_expression() {
+  call<id>(nullptr);
+}

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

Reply via email to