aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-12-20 20:55:03 +0000
committerTed Kremenek <kremenek@apple.com>2012-12-20 20:55:03 +0000
commit7c441069a41e164498047aaed542d0d64bc11962 (patch)
tree6a63262ce9cb3185116c7bba59f4517d51faa9fe
parent7b00b84752b7f3cbd4079f88ddb359170b7073c1 (diff)
Warn if a __weak variable is initialized with an Objective-C object literal.
Such variables may immediately become nil or may have unpredictable behavior. Fixes <rdar://problem/12569201>. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@170763 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td4
-rw-r--r--lib/Sema/SemaDecl.cpp19
-rw-r--r--test/SemaObjC/arc.m24
3 files changed, 46 insertions, 1 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index c49b875c61..0b0f8bef4f 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1788,6 +1788,10 @@ def warn_attribute_weak_on_local : Warning<
"__weak attribute cannot be specified on an automatic variable when ARC "
"is not enabled">,
InGroup<IgnoredAttributes>;
+def warn_attribute_weak_objc_literal : Warning<
+ "__weak variable initialized with an object literal may "
+ "immediately become nil">,
+ InGroup<DiagGroup<"objc-weak-assigned-literal">>;
def warn_weak_identifier_undeclared : Warning<
"weak identifier %0 never declared">;
def err_attribute_weak_static : Error<
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 96e911d17b..9ca7782164 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -6780,13 +6780,30 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
// we do not warn to warn spuriously when 'x' and 'y' are on separate
// paths through the function. This should be revisited if
// -Wrepeated-use-of-weak is made flow-sensitive.
- if (VDecl->getType().getObjCLifetime() == Qualifiers::OCL_Strong) {
+ Qualifiers::ObjCLifetime Lifetime = VDecl->getType().getObjCLifetime();
+ if (Lifetime == Qualifiers::OCL_Strong) {
DiagnosticsEngine::Level Level =
Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
Init->getLocStart());
if (Level != DiagnosticsEngine::Ignored)
getCurFunction()->markSafeWeakUse(Init);
}
+ else if (Lifetime == Qualifiers::OCL_Weak) {
+ // Check if we are initializing a __weak variable with an Objective-C
+ // object literal. Since there is no other strong reference, the
+ // __weak variable may immediately become nil.
+ Expr *InitSansParen = Init->IgnoreParenImpCasts();
+ switch (InitSansParen->getStmtClass()) {
+ default: break;
+ case Stmt::BlockExprClass:
+ case Stmt::ObjCArrayLiteralClass:
+ case Stmt::ObjCDictionaryLiteralClass:
+ case Stmt::ObjCStringLiteralClass:
+ Diag(VDecl->getLocation(), diag::warn_attribute_weak_objc_literal)
+ << Init->getSourceRange();
+ break;
+ }
+ }
}
Init = MaybeCreateExprWithCleanups(Init);
diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m
index bd30715a6b..c6cb88c645 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,12 @@ 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) {
+ __weak id x = @"foo"; // expected-warning {{__weak variable initialized with an object literal may immediately become nil}}
+ __weak id y = @{ key : value }; // expected-warning {{__weak variable initialized with an object literal may immediately become nil}}
+ __weak id z = @[ value ]; // expected-warning {{__weak variable initialized with an object literal may immediately become nil}}
+ __weak id b = ^() {}; // expected-warning {{__weak variable initialized with an object literal may immediately become nil}}
+ __weak __block id b2 = ^() {}; // expected-warning {{__weak variable initialized with an object literal may immediately become nil}}
+}