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