aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td5
-rw-r--r--lib/Sema/SemaChecking.cpp39
-rw-r--r--test/SemaObjC/arc.m31
-rw-r--r--test/SemaObjC/warn-retain-block-property.m43
4 files changed, 112 insertions, 6 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index c49b875c61..c66b9702fa 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -3689,6 +3689,11 @@ def warn_arc_retained_property_assign : Warning<
"assigning retained object to unsafe property"
"; object will be released after assignment">,
InGroup<ARCUnsafeRetainedAssign>;
+def warn_arc_literal_assign : Warning<
+ "assigning %select{dictionary literal|array literal|block literal|boxed expression}0"
+ " to a weak %select{property|variable}1"
+ "; object will be released after assignment">,
+ InGroup<ARCUnsafeRetainedAssign>;
def err_arc_new_array_without_ownership : Error<
"'new' cannot allocate an array of %0 with no explicit ownership">;
def err_arc_autoreleasing_var : Error<
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index eafe595687..f58396f14b 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -5766,6 +5766,39 @@ static bool checkUnsafeAssignObject(Sema &S, SourceLocation Loc,
return false;
}
+static bool checkUnsafeAssignLiteral(Sema &S, SourceLocation Loc,
+ Expr *RHS, bool isProperty) {
+ // Check if RHS is an Objective-C object literal, which also can get
+ // immediately zapped in a weak reference. Note that we explicitly
+ // allow ObjCStringLiterals, since those are designed to never really die.
+ RHS = RHS->IgnoreParenImpCasts();
+ unsigned kind = 4;
+ switch (RHS->getStmtClass()) {
+ default:
+ break;
+ case Stmt::ObjCDictionaryLiteralClass:
+ kind = 0;
+ break;
+ case Stmt::ObjCArrayLiteralClass:
+ kind = 1;
+ break;
+ case Stmt::BlockExprClass:
+ kind = 2;
+ break;
+ case Stmt::ObjCBoxedExprClass:
+ kind = 3;
+ break;
+ }
+ if (kind < 4) {
+ S.Diag(Loc, diag::warn_arc_literal_assign)
+ << kind
+ << (isProperty ? 0 : 1)
+ << RHS->getSourceRange();
+ return true;
+ }
+ return false;
+}
+
bool Sema::checkUnsafeAssigns(SourceLocation Loc,
QualType LHS, Expr *RHS) {
Qualifiers::ObjCLifetime LT = LHS.getObjCLifetime();
@@ -5776,6 +5809,10 @@ bool Sema::checkUnsafeAssigns(SourceLocation Loc,
if (checkUnsafeAssignObject(*this, Loc, LT, RHS, false))
return true;
+ if (LT == Qualifiers::OCL_Weak &&
+ checkUnsafeAssignLiteral(*this, Loc, RHS, false))
+ return true;
+
return false;
}
@@ -5840,6 +5877,8 @@ void Sema::checkUnsafeExprAssigns(SourceLocation Loc,
else if (Attributes & ObjCPropertyDecl::OBJC_PR_weak) {
if (checkUnsafeAssignObject(*this, Loc, Qualifiers::OCL_Weak, RHS, true))
return;
+ if (checkUnsafeAssignLiteral(*this, Loc, RHS, true))
+ return;
}
}
}
diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m
index bd30715a6b..08216b6d80 100644
--- a/test/SemaObjC/arc.m
+++ b/test/SemaObjC/arc.m
@@ -4,6 +4,21 @@ typedef unsigned long NSUInteger;
typedef const void * CFTypeRef;
CFTypeRef CFBridgingRetain(id X);
id CFBridgingRelease(CFTypeRef);
+@protocol NSCopying @end
+@interface NSDictionary
++ (id)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
+- (void)setObject:(id)object forKeyedSubscript:(id)key;
+@end
+@class NSFastEnumerationState;
+@protocol NSFastEnumeration
+- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id [])buffer count:(NSUInteger)len;
+@end
+@interface NSNumber
++ (NSNumber *)numberWithInt:(int)value;
+@end
+@interface NSArray <NSFastEnumeration>
++ (id)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
+@end
void test0(void (*fn)(int), int val) {
fn(val);
@@ -717,3 +732,19 @@ void _NSCalcBeze(NSColor* color, NSColor* bezelColors[]); // expected-error {{mu
- init { return 0; }
@end
+// <rdar://problem/12569201>. Warn on cases of initializing a weak variable
+// with an Objective-C object literal.
+void rdar12569201(id key, id value) {
+ // Declarations.
+ __weak id x = @"foo"; // no-warning
+ __weak id y = @{ key : value }; // expected-warning {{assigning dictionary literal to a weak variable; object will be released after assignment}}
+ __weak id z = @[ value ]; // expected-warning {{assigning array literal to a weak variable; object will be released after assignment}}
+ __weak id b = ^() {}; // expected-warning {{assigning block literal to a weak variable; object will be released after assignment}}
+ __weak id e = @(42); // expected-warning {{assigning boxed expression to a weak variable; object will be released after assignment}}
+
+ // Assignments.
+ y = @{ key : value }; // expected-warning {{assigning dictionary literal to a weak variable; object will be released after assignment}}
+ z = @[ value ]; // expected-warning {{assigning array literal to a weak variable; object will be released after assignment}}
+ b = ^() {}; // expected-warning {{assigning block literal to a weak variable; object will be released after assignment}}
+ e = @(42); // expected-warning {{assigning boxed expression to a weak variable; object will be released after assignment}}
+}
diff --git a/test/SemaObjC/warn-retain-block-property.m b/test/SemaObjC/warn-retain-block-property.m
index 3a54baf0f5..94a2f7ff94 100644
--- a/test/SemaObjC/warn-retain-block-property.m
+++ b/test/SemaObjC/warn-retain-block-property.m
@@ -1,6 +1,7 @@
-// RUN: %clang_cc1 -fsyntax-only -fblocks -fobjc-arc -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -fsyntax-only -fblocks -fobjc-arc -Wno-objc-root-class %s > %t.arc 2>&1 ; FileCheck --check-prefix=CHECK-ARC --input-file=%t.arc %s
// rdar://9829425
-// RUN: %clang_cc1 -fsyntax-only -fblocks -verify -Wno-objc-root-class %s
+
+// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-objc-root-class %s > %t 2>&1 ; FileCheck --input-file=%t %s
// rdar://11761511
extern void doSomething();
@@ -10,12 +11,12 @@ extern void doSomething();
@public
void (^aBlock)(void);
}
-@property (retain) void (^aBlock)(void); // expected-warning {{retain'ed block property does not copy the block - use copy attribute instead}}
-@property (weak, retain) void (^aBlockW)(void); // expected-error {{property attributes 'retain' and 'weak' are mutually exclusive}}
+@property (retain) void (^aBlock)(void);
+@property (weak, retain) void (^aBlockW)(void);
@property (strong, retain) void (^aBlockS)(void); // OK
@property (readonly, retain) void (^aBlockR)(void); // OK
-@property (copy, retain) void (^aBlockC)(void); // expected-error {{property attributes 'copy' and 'retain' are mutually exclusive}}
-@property (assign, retain) void (^aBlockA)(void); // expected-error {{property attributes 'assign' and 'retain' are mutually exclusive}}
+@property (copy, retain) void (^aBlockC)(void);
+@property (assign, retain) void (^aBlockA)(void);
@end
@implementation Test
@@ -30,3 +31,33 @@ int main() {
t.aBlockS = ^{ doSomething(); };
}
+// CHECK-ARC: 14:1: warning: retain'ed block property does not copy the block - use copy attribute instead
+// CHECK-ARC: @property (retain) void (^aBlock)(void);
+// CHECK-ARC: ^
+// CHECK-ARC: 15:1: error: property attributes 'retain' and 'weak' are mutually exclusive
+// CHECK-ARC: @property (weak, retain) void (^aBlockW)(void);
+// CHECK-ARC: ^
+// CHECK-ARC: 18:1: error: property attributes 'copy' and 'retain' are mutually exclusive
+// CHECK-ARC: @property (copy, retain) void (^aBlockC)(void);
+// CHECK-ARC: ^
+// CHECK-ARC: 19:1: error: property attributes 'assign' and 'retain' are mutually exclusive
+// CHECK-ARC: @property (assign, retain) void (^aBlockA)(void);
+// CHECK-ARC: ^
+// CHECK-ARC: 30:13: warning: assigning block literal to a weak property; object will be released after assignment
+// CHECK-ARC: t.aBlockW = ^{ doSomething(); };
+// CHECK-ARC: ^ ~~~~~~~~~~~~~~~~~~~
+// CHECK-ARC: 2 warnings and 3 errors generated.
+
+// CHECK: 14:1: warning: retain'ed block property does not copy the block - use copy attribute instead
+// CHECK: @property (retain) void (^aBlock)(void);
+// CHECK: ^
+// CHECK: 15:1: error: property attributes 'retain' and 'weak' are mutually exclusive
+// CHECK: @property (weak, retain) void (^aBlockW)(void);
+// CHECK: ^
+// CHECK: 18:1: error: property attributes 'copy' and 'retain' are mutually exclusive
+// CHECK: @property (copy, retain) void (^aBlockC)(void);
+// CHECK: ^
+// CHECK: 19:1: error: property attributes 'assign' and 'retain' are mutually exclusive
+// CHECK: @property (assign, retain) void (^aBlockA)(void);
+// CHECK: ^
+// CHECK: 1 warning and 3 errors generated.