From 4ab423cd70ddc40a8b8306ec468ef6436b3540e4 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 22 Apr 2014 17:42:01 +0000 Subject: [PATCH] Objective-C ARC. Under ARC, addition of 'bridge' attribute on CF type is not sufficient and bridge casting is still required for proper ownership semantics. // rdar://16650445 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206910 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ lib/Sema/SemaExprObjC.cpp | 20 ++++++++++++++------ test/SemaObjC/objcbridge-attribute-arc.m | 6 +++--- test/SemaObjCXX/objcbridge-attribute-arc.mm | 6 +++--- 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 843f69d38c..d04b69d669 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2551,6 +2551,8 @@ def warn_objc_invalid_bridge : Warning< "%0 bridges to %1, not %2">, InGroup; def warn_objc_invalid_bridge_to_cf : Warning< "%0 cannot bridge to %1">, InGroup; +def err_objc_invalid_bridge : Error< + "under ARC %0 bridges to %1, but it still requires an explicit bridge cast">; // objc_bridge_related attribute diagnostics. def err_objc_bridged_related_invalid_class : Error< diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 8dd319c98b..d316c13f94 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -3289,7 +3289,8 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, } template -static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) { +static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr, + bool TollFreeBridgeCast) { QualType T = castExpr->getType(); while (const TypedefType *TD = dyn_cast(T.getTypePtr())) { TypedefNameDecl *TDNDecl = TD->getDecl(); @@ -3308,8 +3309,15 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) { ObjCInterfaceDecl *CastClass = InterfacePointerType->getObjectType()->getInterface(); if ((CastClass == ExprClass) || - (CastClass && ExprClass->isSuperClassOf(CastClass))) + (CastClass && ExprClass->isSuperClassOf(CastClass))) { + if (!TollFreeBridgeCast && S.getLangOpts().ObjCAutoRefCount) { + // bridge attribute is ok. However, under ARC, cast still requires + // an explicit cast and should not compile under ARC. + S.Diag(castExpr->getLocStart(), diag::err_objc_invalid_bridge) + << T << Target->getName(); + } return true; + } S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge) << T << Target->getName() << castType->getPointeeType(); return true; @@ -3402,8 +3410,8 @@ void Sema::CheckTollFreeBridgeCast(QualType castType, Expr *castExpr) { ARCConversionTypeClass exprACTC = classifyTypeForARCConversion(castExpr->getType()); ARCConversionTypeClass castACTC = classifyTypeForARCConversion(castType); if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation) { - (void)CheckObjCBridgeNSCast(*this, castType, castExpr); - (void)CheckObjCBridgeNSCast(*this, castType, castExpr); + (void)CheckObjCBridgeNSCast(*this, castType, castExpr, true); + (void)CheckObjCBridgeNSCast(*this, castType, castExpr, true); } else if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable) { (void)CheckObjCBridgeCFCast(*this, castType, castExpr); @@ -3624,8 +3632,8 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation && (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast)) - if (CheckObjCBridgeNSCast(*this, castType, castExpr) || - CheckObjCBridgeNSCast(*this, castType, castExpr)) + if (CheckObjCBridgeNSCast(*this, castType, castExpr, false) || + CheckObjCBridgeNSCast(*this, castType, castExpr, false)) return ACR_okay; if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable && diff --git a/test/SemaObjC/objcbridge-attribute-arc.m b/test/SemaObjC/objcbridge-attribute-arc.m index adc6cfcda4..194f8d5719 100644 --- a/test/SemaObjC/objcbridge-attribute-arc.m +++ b/test/SemaObjC/objcbridge-attribute-arc.m @@ -64,9 +64,9 @@ typedef CFErrorRef1 CFErrorRef2; // expected-note 2 {{declared here}} void Test2(CFErrorRef2 cf, NSError *ns, NSString *str, Class c, CFUColor2Ref cf2) { (void)(NSString *)cf; // expected-warning {{'CFErrorRef2' (aka 'struct __CFErrorRef *') bridges to NSError, not 'NSString'}} - (void)(NSError *)cf; // okay - (void)(MyError*)cf; // okay, - (void)(NSUColor *)cf2; // okay + (void)(NSError *)cf; // expected-error {{under ARC 'CFErrorRef2' (aka 'struct __CFErrorRef *') bridges to NSError, but it still requires an explicit bridge cast}} + (void)(MyError*)cf; // expected-error {{under ARC 'CFErrorRef2' (aka 'struct __CFErrorRef *') bridges to NSError, but it still requires an explicit bridge cast}} + (void)(NSUColor *)cf2; // expected-error {{under ARC 'CFUColor2Ref' (aka 'union __CFUPrimeColor *') bridges to NSUColor, but it still requires an explicit bridge cast}} (void)(CFErrorRef)ns; // okay (void)(CFErrorRef)str; // expected-warning {{'NSString' cannot bridge to 'CFErrorRef' (aka 'struct __CFErrorRef *')}} (void)(Class)cf; // expected-warning {{'CFErrorRef2' (aka 'struct __CFErrorRef *') bridges to NSError, not 'Class'}} diff --git a/test/SemaObjCXX/objcbridge-attribute-arc.mm b/test/SemaObjCXX/objcbridge-attribute-arc.mm index 0e184a4a29..4224854a69 100644 --- a/test/SemaObjCXX/objcbridge-attribute-arc.mm +++ b/test/SemaObjCXX/objcbridge-attribute-arc.mm @@ -64,9 +64,9 @@ typedef CFErrorRef1 CFErrorRef2; // expected-note 2 {{declared here}} void Test2(CFErrorRef2 cf, NSError *ns, NSString *str, Class c, CFUColor2Ref cf2) { (void)(NSString *)cf; // expected-warning {{'CFErrorRef2' (aka '__CFErrorRef *') bridges to NSError, not 'NSString'}} - (void)(NSError *)cf; // okay - (void)(MyError*)cf; // okay, - (void)(NSUColor *)cf2; // okay + (void)(NSError *)cf; // expected-error {{under ARC 'CFErrorRef2' (aka '__CFErrorRef *') bridges to NSError, but it still requires an explicit bridge cast}} + (void)(MyError*)cf; // expected-error {{under ARC 'CFErrorRef2' (aka '__CFErrorRef *') bridges to NSError, but it still requires an explicit bridge cast}}, + (void)(NSUColor *)cf2; // expected-error {{under ARC 'CFUColor2Ref' (aka '__CFUPrimeColor *') bridges to NSUColor, but it still requires an explicit bridge cast}} (void)(CFErrorRef)ns; // okay (void)(CFErrorRef)str; // expected-warning {{'NSString' cannot bridge to 'CFErrorRef' (aka '__CFErrorRef *')}} (void)(Class)cf; // expected-warning {{'CFErrorRef2' (aka '__CFErrorRef *') bridges to NSError, not 'Class'}} -- 2.40.0