From 7c441069a41e164498047aaed542d0d64bc11962 Mon Sep 17 00:00:00 2001 From: Ted Kremenek <kremenek@apple.com> Date: Thu, 20 Dec 2012 20:55:03 +0000 Subject: [PATCH] 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 --- include/clang/Basic/DiagnosticSemaKinds.td | 4 ++++ lib/Sema/SemaDecl.cpp | 19 ++++++++++++++++- test/SemaObjC/arc.m | 24 ++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index c49b875c613..0b0f8bef4fe 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 96e911d17bc..9ca77821645 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 bd30715a6b3..c6cb88c6459 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}} +} -- GitLab