https://github.com/ahatanak updated 
https://github.com/llvm/llvm-project/pull/144458

>From 180213a360c7b25784f84ada7112b30ee0bd1212 Mon Sep 17 00:00:00 2001
From: Akira Hatanaka <ahatan...@apple.com>
Date: Fri, 13 Jun 2025 15:01:26 -0700
Subject: [PATCH 1/5] [Sema][ObjC] Loosen restrictions on reinterpret_cast
 involving indirect ARC-managed pointers

Allow using reinterpret_cast for conversions between indirect ARC
pointers and other pointer types.

rdar://152905399
---
 clang/include/clang/Sema/SemaObjC.h          |  3 ++-
 clang/lib/Sema/SemaCast.cpp                  | 11 +++++++----
 clang/lib/Sema/SemaExprObjC.cpp              | 14 ++++++++++----
 clang/test/SemaObjCXX/arc-type-conversion.mm | 14 ++++++++++++--
 4 files changed, 31 insertions(+), 11 deletions(-)

diff --git a/clang/include/clang/Sema/SemaObjC.h 
b/clang/include/clang/Sema/SemaObjC.h
index b629c6d291402..ed08ff0acf89d 100644
--- a/clang/include/clang/Sema/SemaObjC.h
+++ b/clang/include/clang/Sema/SemaObjC.h
@@ -812,7 +812,8 @@ class SemaObjC : public SemaBase {
                                           CheckedConversionKind CCK,
                                           bool Diagnose = true,
                                           bool DiagnoseCFAudited = false,
-                                          BinaryOperatorKind Opc = BO_PtrMemD);
+                                          BinaryOperatorKind Opc = BO_PtrMemD,
+                                          bool IsReinterpretCast = false);
 
   Expr *stripARCUnbridgedCast(Expr *e);
   void diagnoseARCUnbridgedCast(Expr *e);
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp
index 14e16bc39eb3a..e15a43c116516 100644
--- a/clang/lib/Sema/SemaCast.cpp
+++ b/clang/lib/Sema/SemaCast.cpp
@@ -161,12 +161,14 @@ namespace {
       Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
     }
 
-    void checkObjCConversion(CheckedConversionKind CCK) {
+    void checkObjCConversion(CheckedConversionKind CCK,
+                             bool IsReinterpretCast = false) {
       assert(Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers());
 
       Expr *src = SrcExpr.get();
-      if (Self.ObjC().CheckObjCConversion(OpRange, DestType, src, CCK) ==
-          SemaObjC::ACR_unbridged)
+      if (Self.ObjC().CheckObjCConversion(
+              OpRange, DestType, src, CCK, true, false, BO_PtrMemD,
+              IsReinterpretCast) == SemaObjC::ACR_unbridged)
         IsARCUnbridgedCast = true;
       SrcExpr = src;
     }
@@ -1263,7 +1265,8 @@ void CastOperation::CheckReinterpretCast() {
 
   if (isValidCast(tcr)) {
     if (Self.getLangOpts().allowsNonTrivialObjCLifetimeQualifiers())
-      checkObjCConversion(CheckedConversionKind::OtherCast);
+      checkObjCConversion(CheckedConversionKind::OtherCast,
+                          /*IsReinterpretCast=*/true);
     DiagnoseReinterpretUpDownCast(Self, SrcExpr.get(), DestType, OpRange);
 
     if (unsigned DiagID = checkCastFunctionType(Self, SrcExpr, DestType))
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 3505d9f38d23c..59a2e660364de 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -4390,7 +4390,7 @@ SemaObjC::ARCConversionResult
 SemaObjC::CheckObjCConversion(SourceRange castRange, QualType castType,
                               Expr *&castExpr, CheckedConversionKind CCK,
                               bool Diagnose, bool DiagnoseCFAudited,
-                              BinaryOperatorKind Opc) {
+                              BinaryOperatorKind Opc, bool IsReinterpretCast) {
   ASTContext &Context = getASTContext();
   QualType castExprType = castExpr->getType();
 
@@ -4450,13 +4450,19 @@ SemaObjC::CheckObjCConversion(SourceRange castRange, 
QualType castType,
   // must be explicit.
   // Allow conversions between pointers to lifetime types and coreFoundation
   // pointers too, but only when the conversions are explicit.
+  // Allow conversions requested with a reinterpret_cast that converts an
+  // expression of type T* to type U*.
   if (exprACTC == ACTC_indirectRetainable &&
       (castACTC == ACTC_voidPtr ||
-       (castACTC == ACTC_coreFoundation && SemaRef.isCast(CCK))))
+       (castACTC == ACTC_coreFoundation && SemaRef.isCast(CCK)) ||
+       (IsReinterpretCast && (effCastType->isPointerType() ||
+                              effCastType->isObjCObjectPointerType()))))
     return ACR_okay;
   if (castACTC == ACTC_indirectRetainable &&
-      (exprACTC == ACTC_voidPtr || exprACTC == ACTC_coreFoundation) &&
-      SemaRef.isCast(CCK))
+      (((exprACTC == ACTC_voidPtr || exprACTC == ACTC_coreFoundation) &&
+        SemaRef.isCast(CCK)) ||
+       (IsReinterpretCast && (castExprType->isPointerType() ||
+                              castExprType->isObjCObjectPointerType()))))
     return ACR_okay;
 
   switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {
diff --git a/clang/test/SemaObjCXX/arc-type-conversion.mm 
b/clang/test/SemaObjCXX/arc-type-conversion.mm
index 64cfd02ec18c0..2b44624121504 100644
--- a/clang/test/SemaObjCXX/arc-type-conversion.mm
+++ b/clang/test/SemaObjCXX/arc-type-conversion.mm
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify 
-fblocks %s
 
+@class NSString;
+
 void * cvt(id arg) // expected-note{{candidate function not viable: cannot 
convert argument of incomplete type 'void *' to '__strong id'}}
 {
   void* voidp_val;
@@ -72,6 +74,16 @@ void test_reinterpret_cast(__strong id *sip, __weak id *wip,
   (void)reinterpret_cast<__weak id *>(cwip); // 
expected-error{{reinterpret_cast from '__weak id const *' to '__weak id *' 
casts away qualifiers}}
   (void)reinterpret_cast<__weak id *>(csip); // 
expected-error{{reinterpret_cast from '__strong id const *' to '__weak id *' 
casts away qualifiers}}
   (void)reinterpret_cast<__strong id *>(cwip); // 
expected-error{{reinterpret_cast from '__weak id const *' to '__strong id *' 
casts away qualifiers}}
+
+  auto *p0 = reinterpret_cast<unsigned long *>(sip);
+  (void)reinterpret_cast<__strong id *>(p0);
+  auto *p1 = reinterpret_cast<__weak NSString *>(sip);
+  (void)reinterpret_cast<__strong id *>(p1);
+  (void)reinterpret_cast<unsigned long *>(csip); // expected-error 
{{reinterpret_cast from '__strong id const *' to 'unsigned long *' casts away 
qualifiers}}
+  const unsigned long *p2 = nullptr;
+  (void)reinterpret_cast<__strong id *>(p2); // expected-error 
{{reinterpret_cast from 'const unsigned long *' to '__strong id *' casts away 
qualifiers}}
+  auto ul = reinterpret_cast<unsigned long>(sip);
+  (void)reinterpret_cast<__strong id *>(ul); // expected-error {{cast of 
'unsigned long' to '__strong id *' is disallowed with ARC}}
 }
 
 void test_cstyle_cast(__strong id *sip, __weak id *wip, 
@@ -194,8 +206,6 @@ void from_void(void *vp) {
 typedef void (^Block_strong)() __strong;
 typedef void (^Block_autoreleasing)() __autoreleasing;
 
-@class NSString;
-
 void ownership_transfer_in_cast(void *vp, Block *pblk) {
   __strong NSString **sip2 = static_cast<NSString **>(static_cast<__strong id 
*>(vp));
   __strong NSString **&si2pref = static_cast<NSString **&>(sip2);

>From 1ce9dc056a4456c95567ee2741fa1d45600dfda3 Mon Sep 17 00:00:00 2001
From: Akira Hatanaka <ahatan...@apple.com>
Date: Mon, 16 Jun 2025 19:05:13 -0700
Subject: [PATCH 2/5] Use isAnyPointerType()

---
 clang/lib/Sema/SemaExprObjC.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 59a2e660364de..395f2f340dbd6 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -4455,14 +4455,12 @@ SemaObjC::CheckObjCConversion(SourceRange castRange, 
QualType castType,
   if (exprACTC == ACTC_indirectRetainable &&
       (castACTC == ACTC_voidPtr ||
        (castACTC == ACTC_coreFoundation && SemaRef.isCast(CCK)) ||
-       (IsReinterpretCast && (effCastType->isPointerType() ||
-                              effCastType->isObjCObjectPointerType()))))
+       (IsReinterpretCast && effCastType->isAnyPointerType())))
     return ACR_okay;
   if (castACTC == ACTC_indirectRetainable &&
       (((exprACTC == ACTC_voidPtr || exprACTC == ACTC_coreFoundation) &&
         SemaRef.isCast(CCK)) ||
-       (IsReinterpretCast && (castExprType->isPointerType() ||
-                              castExprType->isObjCObjectPointerType()))))
+       (IsReinterpretCast && castExprType->isAnyPointerType())))
     return ACR_okay;
 
   switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {

>From 1a5777da63d7a396f717c1becdd4fbbd5625b71e Mon Sep 17 00:00:00 2001
From: Akira Hatanaka <ahatan...@apple.com>
Date: Mon, 16 Jun 2025 21:53:54 -0700
Subject: [PATCH 3/5] Fix test failure on Windows

---
 clang/test/SemaObjCXX/arc-type-conversion.mm | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/test/SemaObjCXX/arc-type-conversion.mm 
b/clang/test/SemaObjCXX/arc-type-conversion.mm
index 2b44624121504..9c82cfa2bb2a7 100644
--- a/clang/test/SemaObjCXX/arc-type-conversion.mm
+++ b/clang/test/SemaObjCXX/arc-type-conversion.mm
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -fobjc-runtime-has-weak -fsyntax-only -fobjc-arc -verify 
-fblocks %s
 
 @class NSString;
+typedef unsigned __INTPTR_TYPE__ uintptr_t;
 
 void * cvt(id arg) // expected-note{{candidate function not viable: cannot 
convert argument of incomplete type 'void *' to '__strong id'}}
 {
@@ -82,8 +83,8 @@ void test_reinterpret_cast(__strong id *sip, __weak id *wip,
   (void)reinterpret_cast<unsigned long *>(csip); // expected-error 
{{reinterpret_cast from '__strong id const *' to 'unsigned long *' casts away 
qualifiers}}
   const unsigned long *p2 = nullptr;
   (void)reinterpret_cast<__strong id *>(p2); // expected-error 
{{reinterpret_cast from 'const unsigned long *' to '__strong id *' casts away 
qualifiers}}
-  auto ul = reinterpret_cast<unsigned long>(sip);
-  (void)reinterpret_cast<__strong id *>(ul); // expected-error {{cast of 
'unsigned long' to '__strong id *' is disallowed with ARC}}
+  auto uip = reinterpret_cast<uintptr_t>(sip);
+  (void)reinterpret_cast<__strong id *>(uip); // expected-error {{to '__strong 
id *' is disallowed with ARC}}
 }
 
 void test_cstyle_cast(__strong id *sip, __weak id *wip, 

>From 92e7ad7507ef7c56208f1d63e1890bd72f10cb95 Mon Sep 17 00:00:00 2001
From: Akira Hatanaka <ahatan...@apple.com>
Date: Tue, 17 Jun 2025 09:11:56 -0700
Subject: [PATCH 4/5] Add a release note and test cases for const and volatile
 pointers

---
 clang/docs/ReleaseNotes.rst                  |  3 +++
 clang/test/SemaObjCXX/arc-type-conversion.mm | 16 ++++++++++------
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 59d9612268d30..bea39088c6380 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -325,6 +325,9 @@ Non-comprehensive list of changes in this release
   ``__reference_constructs_from_temporary`` should be used instead. (#GH44056)
 - Added `__builtin_get_vtable_pointer` to directly load the primary vtable 
pointer from a
   polymorphic object.
+- Clang no longer rejects reinterpret_cast conversions between indirect
+  ARC-managed pointers and other pointer types. The prior behavior was overly
+  strict and inconsistent with the ARC specification.
 
 New Compiler Flags
 ------------------
diff --git a/clang/test/SemaObjCXX/arc-type-conversion.mm 
b/clang/test/SemaObjCXX/arc-type-conversion.mm
index 9c82cfa2bb2a7..a8e711cbe309d 100644
--- a/clang/test/SemaObjCXX/arc-type-conversion.mm
+++ b/clang/test/SemaObjCXX/arc-type-conversion.mm
@@ -76,13 +76,17 @@ void test_reinterpret_cast(__strong id *sip, __weak id *wip,
   (void)reinterpret_cast<__weak id *>(csip); // 
expected-error{{reinterpret_cast from '__strong id const *' to '__weak id *' 
casts away qualifiers}}
   (void)reinterpret_cast<__strong id *>(cwip); // 
expected-error{{reinterpret_cast from '__weak id const *' to '__strong id *' 
casts away qualifiers}}
 
-  auto *p0 = reinterpret_cast<unsigned long *>(sip);
-  (void)reinterpret_cast<__strong id *>(p0);
-  auto *p1 = reinterpret_cast<__weak NSString *>(sip);
-  (void)reinterpret_cast<__strong id *>(p1);
+  auto *ul = reinterpret_cast<unsigned long *>(sip);
+  (void)reinterpret_cast<__strong id *>(ul);
+  auto *wp = reinterpret_cast<__weak NSString *>(sip);
+  (void)reinterpret_cast<__strong id *>(wp);
   (void)reinterpret_cast<unsigned long *>(csip); // expected-error 
{{reinterpret_cast from '__strong id const *' to 'unsigned long *' casts away 
qualifiers}}
-  const unsigned long *p2 = nullptr;
-  (void)reinterpret_cast<__strong id *>(p2); // expected-error 
{{reinterpret_cast from 'const unsigned long *' to '__strong id *' casts away 
qualifiers}}
+  const unsigned long *cul = nullptr;
+  (void)reinterpret_cast<__strong id *>(cul); // expected-error 
{{reinterpret_cast from 'const unsigned long *' to '__strong id *' casts away 
qualifiers}}
+  volatile __strong id *vsip = nullptr;
+  (void)reinterpret_cast<unsigned long *>(vsip); // expected-error 
{{reinterpret_cast from '__strong id volatile *' to 'unsigned long *' casts 
away qualifiers}}
+  volatile unsigned long *vul = nullptr;
+  (void)reinterpret_cast<__strong id *>(vul); // expected-error 
{{reinterpret_cast from 'volatile unsigned long *' to '__strong id *' casts 
away qualifiers}}
   auto uip = reinterpret_cast<uintptr_t>(sip);
   (void)reinterpret_cast<__strong id *>(uip); // expected-error {{to '__strong 
id *' is disallowed with ARC}}
 }

>From 889e109113345d0f221b7b0c05dfd084bbe93fc1 Mon Sep 17 00:00:00 2001
From: Akira Hatanaka <ahata...@gmail.com>
Date: Tue, 17 Jun 2025 18:13:34 -0700
Subject: [PATCH 5/5] Test casts which preserve qualifiers work as expected

---
 clang/test/SemaObjCXX/arc-type-conversion.mm | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/clang/test/SemaObjCXX/arc-type-conversion.mm 
b/clang/test/SemaObjCXX/arc-type-conversion.mm
index a8e711cbe309d..0d281bf3e5c45 100644
--- a/clang/test/SemaObjCXX/arc-type-conversion.mm
+++ b/clang/test/SemaObjCXX/arc-type-conversion.mm
@@ -81,12 +81,16 @@ void test_reinterpret_cast(__strong id *sip, __weak id *wip,
   auto *wp = reinterpret_cast<__weak NSString *>(sip);
   (void)reinterpret_cast<__strong id *>(wp);
   (void)reinterpret_cast<unsigned long *>(csip); // expected-error 
{{reinterpret_cast from '__strong id const *' to 'unsigned long *' casts away 
qualifiers}}
+  (void)reinterpret_cast<const unsigned long *>(csip);
   const unsigned long *cul = nullptr;
   (void)reinterpret_cast<__strong id *>(cul); // expected-error 
{{reinterpret_cast from 'const unsigned long *' to '__strong id *' casts away 
qualifiers}}
+  (void)reinterpret_cast<const __strong id *>(cul);
   volatile __strong id *vsip = nullptr;
   (void)reinterpret_cast<unsigned long *>(vsip); // expected-error 
{{reinterpret_cast from '__strong id volatile *' to 'unsigned long *' casts 
away qualifiers}}
+  (void)reinterpret_cast<volatile unsigned long *>(vsip);
   volatile unsigned long *vul = nullptr;
   (void)reinterpret_cast<__strong id *>(vul); // expected-error 
{{reinterpret_cast from 'volatile unsigned long *' to '__strong id *' casts 
away qualifiers}}
+  (void)reinterpret_cast<volatile __strong id *>(vul);
   auto uip = reinterpret_cast<uintptr_t>(sip);
   (void)reinterpret_cast<__strong id *>(uip); // expected-error {{to '__strong 
id *' is disallowed with ARC}}
 }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to