From 992bdf1b45bdb71871975729583e193ffbd67d13 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 27 Oct 2014 22:33:06 +0000 Subject: [PATCH] Objective-C ARC [qoi]. Issue diagnostic if __bridge casting to C type a collection literal. rdar://18768214 llvm-svn: 220727 --- clang/include/clang/Basic/DiagnosticGroups.td | 1 + clang/include/clang/Basic/DiagnosticSemaKinds.td | 5 +++ clang/lib/Sema/SemaExprObjC.cpp | 21 +++++++++--- clang/test/SemaObjC/arc-cfbridge-warning.m | 41 ++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 clang/test/SemaObjC/arc-cfbridge-warning.m diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 7a813b0..0f25a15 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -422,6 +422,7 @@ def : DiagGroup<"arc-abi">; def ARCUnsafeRetainedAssign : DiagGroup<"arc-unsafe-retained-assign">; def ARCRetainCycles : DiagGroup<"arc-retain-cycles">; def ARCNonPodMemAccess : DiagGroup<"arc-non-pod-memaccess">; +def ARCBridgeCastRelease : DiagGroup<"arc-bridge-cast-release">; def AutomaticReferenceCounting : DiagGroup<"arc", [ARCUnsafeRetainedAssign, ARCRetainCycles, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index fe87872..d059e87 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4459,6 +4459,11 @@ def note_arc_retain_cycle_owner : Note< def warn_arc_object_memaccess : Warning< "%select{destination for|source of}0 this %1 call is a pointer to " "ownership-qualified type %2">, InGroup; + +def warn_arc_consumed_object_released : Warning< + "__bridge cast of collection literal of type %1 to \"bridgeable\" C " + "type %0 causes early release of the collection">, + InGroup; let CategoryName = "ARC and @properties" in { diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 40ab95b..5746e732 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -4075,11 +4075,22 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, // Okay: id -> CF CK = CK_BitCast; switch (Kind) { - case OBC_Bridge: - // Reclaiming a value that's going to be __bridge-casted to CF - // is very dangerous, so we don't do it. - SubExpr = maybeUndoReclaimObject(SubExpr); - break; + case OBC_Bridge: { + const ImplicitCastExpr *implCE = dyn_cast(SubExpr); + while (implCE && implCE->getCastKind() == CK_BitCast) + implCE = dyn_cast(implCE->getSubExpr()); + if (implCE && (implCE->getCastKind() == CK_ARCConsumeObject)) + if (const Expr *LitExp = implCE->getSubExpr()) + if ((isa(LitExp) || + isa(LitExp)) && + T->isCARCBridgableType()) + Diag(BridgeKeywordLoc, diag::warn_arc_consumed_object_released) + << T << implCE->getType(); + // Reclaiming a value that's going to be __bridge-casted to CF + // is very dangerous, so we don't do it. + SubExpr = maybeUndoReclaimObject(SubExpr); + break; + } case OBC_BridgeRetained: // Produce the object before casting it. diff --git a/clang/test/SemaObjC/arc-cfbridge-warning.m b/clang/test/SemaObjC/arc-cfbridge-warning.m new file mode 100644 index 0000000..142983f --- /dev/null +++ b/clang/test/SemaObjC/arc-cfbridge-warning.m @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -fsyntax-only -x objective-c -fobjc-arc -verify -Wno-objc-root-class %s +// rdar://18768214 + + +@class NSArray; +typedef const struct __attribute__((objc_bridge(NSArray))) __CFArray * CFArrayRef; +@class NSString; +typedef const void * CFTypeRef; + +typedef const struct __attribute__((objc_bridge(NSString))) __CFString * CFStringRef; + +typedef long NSInteger; +typedef unsigned long NSUInteger; + +@interface NSObject { + Class isa __attribute__((deprecated)); +} ++ (void)initialize; +- (instancetype)init; ++ (instancetype)new; ++ (instancetype)alloc; +- (void)dealloc; +@end + +@interface NSArray : NSObject +@property (readonly) NSUInteger count; +- (id)objectAtIndex:(NSUInteger)index; +- (instancetype)init __attribute__((objc_designated_initializer)); +- (instancetype)initWithObjects:(const id [])objects count:(NSUInteger)cnt __attribute__((objc_designated_initializer)); ++ (instancetype)array; ++ (instancetype)arrayWithObject:(id)anObject; ++ (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt; ++ (instancetype)arrayWithObjects:(id)firstObj, ... __attribute__((sentinel(0,1))); +@end + +static CFStringRef _s; + +CFArrayRef _array() +{ + return (__bridge CFArrayRef)@[(__bridge NSString *)_s]; // expected-warning {{__bridge cast of collection literal of type 'NSArray *' to "bridgeable" C type 'CFArrayRef' (aka 'const struct __CFArray *') causes early release of the collection}} +} -- 2.7.4