From: Fariborz Jahanian Date: Thu, 19 Apr 2012 21:44:57 +0000 (+0000) Subject: objective-c arc: Issue warning under -Wreceiver-is-weak X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=289677da2d3ef2f015af8b7e41150053891589f7;p=clang objective-c arc: Issue warning under -Wreceiver-is-weak if receiver is a 'weak' property, by type or by attribute. // rdar://10225276 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155159 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 986479921d..007869c437 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -660,7 +660,8 @@ def warn_arc_perform_selector_leaks : Warning< def err_gc_weak_property_strong_type : Error< "weak attribute declared on a __strong type property in GC mode">; def warn_receiver_is_weak : Warning < - "weak receiver may be unpredictably null in ARC mode">, + "weak %select{receiver|property|implicit property}0 may be " + "unpredictably null in ARC mode">, InGroup>, DefaultIgnore; def error_synthesized_ivar_yet_not_supported : Error< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index e84a554505..5ad60ee9e8 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -5901,6 +5901,9 @@ public: bool IsInstance); bool inferObjCARCLifetime(ValueDecl *decl); + + void DiagnoseARCUseOfWeakReceiver(NamedDecl *PDecl, + QualType T, SourceLocation Loc); ExprResult HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 41fd112c71..c187a8deb7 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1323,6 +1323,32 @@ ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, return 0; } +void +Sema::DiagnoseARCUseOfWeakReceiver(NamedDecl *PDecl, + QualType T, SourceLocation Loc) { + if (!getLangOpts().ObjCAutoRefCount) + return; + + if (T.getObjCLifetime() == Qualifiers::OCL_Weak) { + Diag(Loc, diag::warn_receiver_is_weak) + << (!PDecl ? 0 : (isa(PDecl) ? 1 : 2)); + if (PDecl) { + if (isa(PDecl)) + Diag(PDecl->getLocation(), diag::note_property_declare); + else + Diag(PDecl->getLocation(), diag::note_method_declared_at) << PDecl; + } + return; + } + + if (PDecl) + if (ObjCPropertyDecl *Prop = dyn_cast(PDecl)) + if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) { + Diag(Loc, diag::warn_receiver_is_weak) << 1; + Diag(Prop->getLocation(), diag::note_property_declare); + } +} + /// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an /// objective C interface. This is a property reference expression. ExprResult Sema:: @@ -1354,7 +1380,6 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); - if (Super) return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, VK_LValue, OK_ObjCProperty, @@ -1372,7 +1397,7 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); - + if (Super) return Owned(new (Context) ObjCPropertyRefExpr(PD, Context.PseudoObjectTy, @@ -2379,10 +2404,10 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } if (getLangOpts().ObjCAutoRefCount) { - if (Receiver && - (Receiver->IgnoreParenImpCasts()->getType().getObjCLifetime() - == Qualifiers::OCL_Weak)) - Diag(Receiver->getLocStart(), diag::warn_receiver_is_weak); + if (Receiver) + DiagnoseARCUseOfWeakReceiver(0 /* PDecl */, + Receiver->IgnoreParenImpCasts()->getType(), + Receiver->getLocStart()); // In ARC, annotate delegate init calls. if (Result->getMethodFamily() == OMF_init && diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index 0e6632964a..078b0e4bc4 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -478,6 +478,8 @@ bool ObjCPropertyOpBuilder::findGetter() { if (RefExpr->isImplicitProperty()) { if ((Getter = RefExpr->getImplicitPropertyGetter())) { GetterSelector = Getter->getSelector(); + S.DiagnoseARCUseOfWeakReceiver(Getter, Getter->getResultType(), + RefExpr->getLocation()); return true; } else { @@ -497,6 +499,8 @@ bool ObjCPropertyOpBuilder::findGetter() { } ObjCPropertyDecl *prop = RefExpr->getExplicitProperty(); + S.DiagnoseARCUseOfWeakReceiver(prop, prop->getType(), + RefExpr->getLocation()); Getter = LookupMethodInReceiverType(S, prop->getGetterName(), RefExpr); return (Getter != 0); } diff --git a/test/SemaObjC/weak-receiver-warn.m b/test/SemaObjC/weak-receiver-warn.m index f3955da3bc..5ee53fb063 100644 --- a/test/SemaObjC/weak-receiver-warn.m +++ b/test/SemaObjC/weak-receiver-warn.m @@ -17,3 +17,34 @@ void test0(Test0 *x) { [weakx setBlock: ^{ [x actNow]; }]; // expected-warning {{weak receiver may be unpredictably null in ARC mode}} weakx.block = ^{ [x actNow]; }; } + +@interface Test +{ + __weak Test* weak_prop; +} +- (void) Meth; +@property __weak Test* weak_prop; // expected-note 2 {{property declared here}} +@property (weak, atomic) id weak_atomic_prop; // expected-note 2 {{property declared here}} +- (__weak id) P; // expected-note 2 {{method 'P' declared here}} +@end + +@implementation Test +- (void) Meth { + if (self.weak_prop) { // expected-warning {{weak property may be unpredictably null in ARC mode}} + self.weak_prop = 0; + } + if (self.weak_atomic_prop) { // expected-warning {{weak property may be unpredictably null in ARC mode}} + self.weak_atomic_prop = 0; + } + [self.weak_prop Meth]; // expected-warning {{weak property may be unpredictably null in ARC mode}} + id pi = self.P; // expected-warning {{weak implicit property may be unpredictably null in ARC mode}} + + [self.weak_atomic_prop Meth]; // expected-warning {{weak property may be unpredictably null in ARC mode}} + + [self.P Meth]; // expected-warning {{weak implicit property may be unpredictably null in ARC mode}} +} + +- (__weak id) P { return 0; } +@dynamic weak_prop, weak_atomic_prop; +@end +