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 bd8276f..633da42 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3042,6 +3042,9 @@
"%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 ceff1de..edf8b72 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -1934,7 +1934,24 @@
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
index 0000000..19073c0
--- /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 6db2155..712ccf4 100644
--- a/test/SemaObjC/arc-unavailable-for-weakref.m
+++ b/test/SemaObjC/arc-unavailable-for-weakref.m
@@ -15,7 +15,8 @@
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 @@
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 @@
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}}
}
diff --git a/test/SemaObjCXX/arc-unavailable-for-weakref.mm b/test/SemaObjCXX/arc-unavailable-for-weakref.mm
index 24593ce..74fdd54 100644
--- a/test/SemaObjCXX/arc-unavailable-for-weakref.mm
+++ b/test/SemaObjCXX/arc-unavailable-for-weakref.mm
@@ -15,7 +15,8 @@
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 @@
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 @@
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}}
}