diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 633da42b58..4c1e868548 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3043,8 +3043,7 @@ def err_arc_mismatched_cast : Error< "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">; + "explicit ownership qualifier on cast result would have no effect">; 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 edf8b72050..019dc81764 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1937,17 +1937,27 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, 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) && + if ((castACTC == ACTC_retainable) && (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(); + (castType != castExprType)) { + const Type *DT = castType.getTypePtr(); + QualType QDT = castType; + // We desugar some types but not others. We ignore those + // that cannot happen in a cast; i.e. auto, and those which + // should not be de-sugared; i.e typedef. + if (const ParenType *PT = dyn_cast(DT)) + QDT = PT->desugar(); + else if (const TypeOfType *TP = dyn_cast(DT)) + QDT = TP->desugar(); + else if (const AttributedType *AT = dyn_cast(DT)) + QDT = AT->desugar(); + if (QDT != castType && + QDT.getObjCLifetime() != Qualifiers::OCL_None) { + SourceLocation loc = + (castRange.isValid() ? castRange.getBegin() + : castExpr->getExprLoc()); + Diag(loc, diag::err_arc_nolifetime_behavior); + } } return ACR_okay; } diff --git a/test/SemaObjC/arc-objc-lifetime.m b/test/SemaObjC/arc-objc-lifetime.m index 19073c08c0..2318fbfccd 100644 --- a/test/SemaObjC/arc-objc-lifetime.m +++ b/test/SemaObjC/arc-objc-lifetime.m @@ -17,12 +17,14 @@ @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}} + (__bridge CFStringRef) (__strong NSString *)CFBridgingRelease(); // expected-error {{explicit ownership qualifier on cast result would have no effect}} 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}} + (__bridge CFStringRef) (__autoreleasing PNSString) CFBridgingRelease(); // expected-error {{explicit ownership qualifier on cast result would have no effect}} myString = (__bridge CFStringRef) (AUTORELEASEPNSString) CFBridgingRelease(); // OK + myString = + (__bridge CFStringRef) (typeof(__strong NSString *)) CFBridgingRelease(); // expected-error {{explicit ownership qualifier on cast result would have no effect}} return myString; } diff --git a/test/SemaObjC/arc-unavailable-for-weakref.m b/test/SemaObjC/arc-unavailable-for-weakref.m index 712ccf4a11..210727ad39 100644 --- a/test/SemaObjC/arc-unavailable-for-weakref.m +++ b/test/SemaObjC/arc-unavailable-for-weakref.m @@ -16,7 +16,7 @@ int main() { 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 {{casting expression of type 'id' to type 'sub *__weak' with qualified lifetimewill not change object lifetime}} + // expected-error {{explicit ownership qualifier on cast result would have no effect}} } // rdar://9732636 @@ -32,7 +32,7 @@ + (id) new; __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'}} \ - // expected-error {{casting expression of type 'NOWEAK *' to type '__weak id' with qualified lifetimewill not change object lifetime}} + // expected-error {{explicit ownership qualifier on cast result would have no effect}} } @protocol P @end @@ -45,6 +45,6 @@ @protocol P1 @end __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

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

' with qualified lifetimewill not change object lifetime}} + // expected-error {{explicit ownership qualifier on cast result would have no effect}} } diff --git a/test/SemaObjCXX/arc-unavailable-for-weakref.mm b/test/SemaObjCXX/arc-unavailable-for-weakref.mm index 74fdd54d48..2347061cfd 100644 --- a/test/SemaObjCXX/arc-unavailable-for-weakref.mm +++ b/test/SemaObjCXX/arc-unavailable-for-weakref.mm @@ -16,7 +16,7 @@ int main() { 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 {{casting expression of type 'id' to type 'sub *__weak' with qualified lifetimewill not change object lifetime}} + // expected-error {{explicit ownership qualifier on cast result would have no effect}} } // rdar://9732636 @@ -32,7 +32,7 @@ + (id) new; __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'}} \ - // expected-error {{casting expression of type 'NOWEAK *' to type '__weak id' with qualified lifetimewill not change object lifetime}} + // expected-error {{explicit ownership qualifier on cast result would have no effect}} } @protocol P @end @@ -45,6 +45,6 @@ @protocol P1 @end __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'}} \ - // expected-error {{casting expression of type 'NOWEAK *' to type '__weak id' with qualified lifetimewill not change object lifetime}} + // expected-error {{explicit ownership qualifier on cast result would have no effect}} }