From 9277ff426d39053dfc7c02aa441d9c99607fed13 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 17 Jun 2014 23:35:13 +0000 Subject: [PATCH] Objective-C ARC. Do not warn about properties with both IBOutlet and weak attributes when accessed being unpredictably set to nil because usage of such properties are always single threaded and its ivar cannot be set to nil asynchronously. // rdar://15885642 llvm-svn: 211132 --- clang/lib/Sema/ScopeInfo.cpp | 10 ++++++++-- clang/lib/Sema/SemaExprObjC.cpp | 9 ++++++++- clang/lib/Sema/SemaPseudoObject.cpp | 21 ++++++++++++++------- clang/test/SemaObjC/iboutlet.m | 16 ++++++++++++++-- 4 files changed, 44 insertions(+), 12 deletions(-) diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp index d9b2ca310a89..4d079e705f62 100644 --- a/clang/lib/Sema/ScopeInfo.cpp +++ b/clang/lib/Sema/ScopeInfo.cpp @@ -158,8 +158,14 @@ void FunctionScopeInfo::markSafeWeakUse(const Expr *E) { // Has this weak object been seen before? FunctionScopeInfo::WeakObjectUseMap::iterator Uses; - if (const ObjCPropertyRefExpr *RefExpr = dyn_cast(E)) - Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr)); + if (const ObjCPropertyRefExpr *RefExpr = dyn_cast(E)) { + if (isa(RefExpr->getBase())) + Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr)); + else { + markSafeWeakUse(RefExpr->getBase()); + return; + } + } else if (const ObjCIvarRefExpr *IvarE = dyn_cast(E)) Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE)); else if (const DeclRefExpr *DRE = dyn_cast(E)) diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index ffb6b037ec0f..c6a7d7c13dcc 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -2640,7 +2640,14 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } if (getLangOpts().ObjCAutoRefCount) { - DiagnoseARCUseOfWeakReceiver(*this, Receiver); + // Do not warn about IBOutlet weak property receivers being set to null + // as this cannot asynchronously happen. + bool WarnWeakReceiver = true; + if (isImplicit && Method) + if (const ObjCPropertyDecl *PropertyDecl = Method->findPropertyDecl()) + WarnWeakReceiver = !PropertyDecl->hasAttr(); + if (WarnWeakReceiver) + DiagnoseARCUseOfWeakReceiver(*this, Receiver); // In ARC, annotate delegate init calls. if (Result->getMethodFamily() == OMF_init && diff --git a/clang/lib/Sema/SemaPseudoObject.cpp b/clang/lib/Sema/SemaPseudoObject.cpp index eaf170c176bc..35684b4fa22a 100644 --- a/clang/lib/Sema/SemaPseudoObject.cpp +++ b/clang/lib/Sema/SemaPseudoObject.cpp @@ -542,7 +542,7 @@ bool ObjCPropertyOpBuilder::isWeakProperty() const { if (RefExpr->isExplicitProperty()) { const ObjCPropertyDecl *Prop = RefExpr->getExplicitProperty(); if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) - return true; + return !Prop->hasAttr(); T = Prop->getType(); } else if (Getter) { @@ -816,13 +816,20 @@ ExprResult ObjCPropertyOpBuilder::buildRValueOperation(Expr *op) { // As a special case, if the method returns 'id', try to get // a better type from the property. - if (RefExpr->isExplicitProperty() && result.get()->isRValue() && - result.get()->getType()->isObjCIdType()) { + if (RefExpr->isExplicitProperty() && result.get()->isRValue()) { QualType propType = RefExpr->getExplicitProperty()->getType(); - if (const ObjCObjectPointerType *ptr - = propType->getAs()) { - if (!ptr->isObjCIdType()) - result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); + if (result.get()->getType()->isObjCIdType()) { + if (const ObjCObjectPointerType *ptr + = propType->getAs()) { + if (!ptr->isObjCIdType()) + result = S.ImpCastExprToType(result.get(), propType, CK_BitCast); + } + } + if (S.getLangOpts().ObjCAutoRefCount) { + Qualifiers::ObjCLifetime LT = propType.getObjCLifetime(); + if (LT == Qualifiers::OCL_Weak) + if (!S.Diags.isIgnored(diag::warn_arc_repeated_use_of_weak, RefExpr->getLocation())) + S.getCurFunction()->markSafeWeakUse(RefExpr); } } diff --git a/clang/test/SemaObjC/iboutlet.m b/clang/test/SemaObjC/iboutlet.m index 3c7f9581e663..63eac9af8a52 100644 --- a/clang/test/SemaObjC/iboutlet.m +++ b/clang/test/SemaObjC/iboutlet.m @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -fsyntax-only -Wno-objc-root-class -verify %s -// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -Wno-objc-root-class -verify %s +// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -Wno-objc-root-class -Wreceiver-is-weak -Warc-repeated-use-of-weak -fobjc-runtime-has-weak -verify %s +// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -fobjc-arc -Wno-objc-root-class -Wreceiver-is-weak -Warc-repeated-use-of-weak -fobjc-runtime-has-weak -verify %s // rdar://11448209 #define READONLY readonly @@ -40,3 +40,15 @@ @implementation RKTFHView @synthesize synthReadOnlyReadWrite=_synthReadOnlyReadWrite; @end + +// rdar://15885642 +@interface WeakOutlet +@property IBOutlet __weak WeakOutlet* WeakProp; +@end + +WeakOutlet* func() { + __weak WeakOutlet* pwi; + pwi.WeakProp = (WeakOutlet*)0; + pwi.WeakProp = pwi.WeakProp; + return pwi.WeakProp; +}