]> granicus.if.org Git - clang/commitdiff
objective-c arc: type-casting of an objc pointer to
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 28 Oct 2011 20:06:07 +0000 (20:06 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 28 Oct 2011 20:06:07 +0000 (20:06 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExprObjC.cpp
test/SemaObjC/arc-objc-lifetime.m [new file with mode: 0644]
test/SemaObjC/arc-unavailable-for-weakref.m
test/SemaObjCXX/arc-unavailable-for-weakref.mm

index bd8276fc0f926a5a3753070ea240a4f189768615..633da42b587e1afa43d736802d7aefd523cfb1b2 100644 (file)
@@ -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<
index ceff1de3d491bb0fbd8b505524330d71f00e2094..edf8b720504e52f67fddb4998a5235f7d1b13f9e 100644 (file)
@@ -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<AttributedType>(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 (file)
index 0000000..19073c0
--- /dev/null
@@ -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
index 6db2155f8c64e4d94348b0304017936c8e0950f8..712ccf4a115dc2331a11b9231c0c2d79dfd4435d 100644 (file)
@@ -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<P, P1> * Test2() {
   weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
 
   __weak id<P> weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
-  return (__weak id<P>)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK<P,P1> *' to a __weak object of type '__weak id<P>'}}
+  return (__weak id<P>)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK<P,P1> *' to a __weak object of type '__weak id<P>'}} \
+                                // expected-error {{casting expression of type 'NOWEAK<P,P1> *' to type '__weak id<P>' with qualified lifetimewill not change object lifetime}}
 }
 
index 24593ce5e4ed7b1b5e708bb83d94d9274660b29c..74fdd54d48e334c50b18bccb638f9ebc04bb6036 100644 (file)
@@ -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<P, P1> * Test2() {
   weak1 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
 
   __weak id<P> weak2 = strong1; // expected-error {{assignment of a weak-unavailable object to a __weak object}}
-  return (__weak id<P, P1>)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK<P,P1> *' to a __weak object of type '__weak id<P,P1>'}}
+  return (__weak id<P, P1>)strong1; // expected-error {{cast of weak-unavailable object of type 'NOWEAK<P,P1> *' to a __weak object of type '__weak id<P,P1>'}} \
+                                    // expected-error {{casting expression of type 'NOWEAK<P,P1> *' to type '__weak id<P,P1>' with qualified lifetimewill not change object lifetime}}
 }