From: Fariborz Jahanian Date: Fri, 28 Oct 2011 20:06:07 +0000 (+0000) Subject: objective-c arc: type-casting of an objc pointer to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6d09f01af70bbd58ddbccb0a22f5479782b31797;p=clang objective-c arc: type-casting of an objc pointer to an rvalue retainable object type with life-time qualifier has no effect and wil be diagnosed as error. // rdar://10244607 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143219 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index bd8276fc0f..633da42b58 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3042,6 +3042,9 @@ def err_arc_mismatched_cast : Error< "%select{%2|a non-Objective-C pointer type %2|a block pointer|" "an Objective-C pointer|an indirect pointer to an Objective-C pointer}1" " to %3 is disallowed with ARC">; +def err_arc_nolifetime_behavior : Error< + "casting expression of type %1 to type %0 with qualified lifetime" + "will not change object lifetime">; def err_arc_objc_object_in_struct : Error< "ARC forbids Objective-C objects in structs or unions">; def err_arc_objc_property_default_assign_on_object : Error< diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index ceff1de3d4..edf8b72050 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1934,7 +1934,24 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExprType); ARCConversionTypeClass castACTC = classifyTypeForARCConversion(effCastType); - if (exprACTC == castACTC) return ACR_okay; + if (exprACTC == castACTC) { + // check for viablity and report error if casting an rvalue to a + // life-time qualifier. + if ((castACTC == ACTC_retainable) && + isa(castType) && + (castType.getObjCLifetime() != Qualifiers::OCL_None) && + (CCK == CCK_CStyleCast || CCK == CCK_OtherCast) && + castType != castExprType) { + SourceLocation loc = + (castRange.isValid() ? castRange.getBegin() + : castExpr->getExprLoc()); + Diag(loc, diag::err_arc_nolifetime_behavior) + << effCastType << castExprType + << castRange << castExpr->getSourceRange(); + } + return ACR_okay; + } + if (isAnyCLike(exprACTC) && isAnyCLike(castACTC)) return ACR_okay; // Allow all of these types to be cast to integer types (but not diff --git a/test/SemaObjC/arc-objc-lifetime.m b/test/SemaObjC/arc-objc-lifetime.m new file mode 100644 index 0000000000..19073c08c0 --- /dev/null +++ b/test/SemaObjC/arc-objc-lifetime.m @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -verify %s +// RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -verify %s +// rdar://10244607 + +typedef const struct __CFString * CFStringRef; +@class NSString; + +NSString *CFBridgingRelease(); + +typedef NSString * PNSString; + +typedef __autoreleasing NSString * AUTORELEASEPNSString; + +@interface I @end + +@implementation I +- (CFStringRef)myString +{ + CFStringRef myString = + (__bridge CFStringRef) (__strong NSString *)CFBridgingRelease(); // expected-error {{casting expression of type 'NSString *' to type 'NSString *__strong' with qualified lifetimewill not change object lifetime}} + + myString = + (__bridge CFStringRef) (__autoreleasing PNSString) CFBridgingRelease(); // expected-error {{casting expression of type 'NSString *' to type '__autoreleasing PNSString' (aka 'NSString *__autoreleasing') with qualified lifetimewill not change object}} + myString = + (__bridge CFStringRef) (AUTORELEASEPNSString) CFBridgingRelease(); // OK + return myString; +} + +- (void)decodeValueOfObjCType:(const char *)type at:(void *)addr { + __autoreleasing id *stuff = (__autoreleasing id *)addr; +} +@end diff --git a/test/SemaObjC/arc-unavailable-for-weakref.m b/test/SemaObjC/arc-unavailable-for-weakref.m index 6db2155f8c..712ccf4a11 100644 --- a/test/SemaObjC/arc-unavailable-for-weakref.m +++ b/test/SemaObjC/arc-unavailable-for-weakref.m @@ -15,7 +15,8 @@ int main() { id obj; ns1 = (__weak sub *)obj; // expected-error {{assignment of a weak-unavailable object to a __weak object}} \ - // expected-error {{class is incompatible with __weak references}} + // expected-error {{class is incompatible with __weak references}} \ + // expected-error {{casting expression of type 'id' to type 'sub *__weak' with qualified lifetimewill not change object lifetime}} } // rdar://9732636 @@ -30,7 +31,8 @@ NOWEAK * Test1() { weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} __weak id weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} - return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id'}} + return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id'}} \ + // expected-error {{casting expression of type 'NOWEAK *' to type '__weak id' with qualified lifetimewill not change object lifetime}} } @protocol P @end @@ -42,6 +44,7 @@ NOWEAK * Test2() { weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} __weak id

weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} - return (__weak id

)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id

'}} + return (__weak id

)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id

'}} \ + // expected-error {{casting expression of type 'NOWEAK *' to type '__weak id

' with qualified lifetimewill not change object lifetime}} } diff --git a/test/SemaObjCXX/arc-unavailable-for-weakref.mm b/test/SemaObjCXX/arc-unavailable-for-weakref.mm index 24593ce5e4..74fdd54d48 100644 --- a/test/SemaObjCXX/arc-unavailable-for-weakref.mm +++ b/test/SemaObjCXX/arc-unavailable-for-weakref.mm @@ -15,7 +15,8 @@ int main() { id obj; ns1 = (__weak sub *)obj; // expected-error {{assignment of a weak-unavailable object to a __weak object}} \ - // expected-error {{class is incompatible with __weak references}} + // expected-error {{class is incompatible with __weak references}} \ + // expected-error {{casting expression of type 'id' to type 'sub *__weak' with qualified lifetimewill not change object lifetime}} } // rdar://9732636 @@ -30,7 +31,8 @@ NOWEAK * Test1() { weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} __weak id weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} - return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id'}} + return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id'}} \ + // expected-error {{casting expression of type 'NOWEAK *' to type '__weak id' with qualified lifetimewill not change object lifetime}} } @protocol P @end @@ -42,6 +44,7 @@ NOWEAK * Test2() { weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} __weak id

weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}} - return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id'}} + return (__weak id)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK *' to a __weak object of type '__weak id'}} \ + // expected-error {{casting expression of type 'NOWEAK *' to type '__weak id' with qualified lifetimewill not change object lifetime}} }