Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
------------------
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Sema/SemaObjC.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
11 changes: 7 additions & 4 deletions clang/lib/Sema/SemaCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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))
Expand Down
12 changes: 8 additions & 4 deletions clang/lib/Sema/SemaExprObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -4450,13 +4450,17 @@ 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->isAnyPointerType())))
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->isAnyPointerType())))
return ACR_okay;

switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {
Expand Down
19 changes: 17 additions & 2 deletions clang/test/SemaObjCXX/arc-type-conversion.mm
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// 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'}}
{
void* voidp_val;
Expand Down Expand Up @@ -72,6 +75,20 @@ 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 *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 *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}}
}

void test_cstyle_cast(__strong id *sip, __weak id *wip,
Expand Down Expand Up @@ -194,8 +211,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);
Expand Down