[cfe-commits] r164855 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/ScopeInfo.h lib/Sema/AnalysisBasedWarnings.cpp lib/Sema/Sema.cpp lib/Sema/SemaChecking.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprMember.cpp lib/Sema/SemaPseudoObject.cpp test/SemaObjC/arc-repeated-weak.mm
Jordan Rose
jordan_rose at apple.com
Fri Sep 28 15:21:35 PDT 2012
Author: jrose
Date: Fri Sep 28 17:21:35 2012
New Revision: 164855
URL: http://llvm.org/viewvc/llvm-project?rev=164855&view=rev
Log:
-Warc-repeated-use-of-weak: check ivars and variables as well.
Like properties, loading from a weak ivar twice in the same function can
give you inconsistent results if the object is deallocated between the
two loads. It is safer to assign to a strong local variable and use that.
Second half of <rdar://problem/12280249>.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/ScopeInfo.h
cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
cfe/trunk/lib/Sema/Sema.cpp
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprMember.cpp
cfe/trunk/lib/Sema/SemaPseudoObject.cpp
cfe/trunk/test/SemaObjC/arc-repeated-weak.mm
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Sep 28 17:21:35 2012
@@ -710,14 +710,16 @@
"unpredictably null in ARC mode">,
InGroup<DiagGroup<"receiver-is-weak">>, DefaultIgnore;
def warn_arc_repeated_use_of_weak : Warning <
- "weak property is accessed multiple times in this "
- "%select{function|method|block|lambda}0 but may be unpredictably set to nil; "
- "assign to a strong variable to keep the object alive">,
+ "weak %select{variable|property|implicit property|instance variable}0 %1 is "
+ "accessed multiple times in this %select{function|method|block|lambda}2 "
+ "but may be unpredictably set to nil; assign to a strong variable to keep "
+ "the object alive">,
InGroup<ARCRepeatedUseOfWeak>, DefaultIgnore;
def warn_arc_possible_repeated_use_of_weak : Warning <
- "weak property may be accessed multiple times in this "
- "%select{function|method|block|lambda}0 but may be unpredictably set to nil; "
- "assign to a strong variable to keep the object alive">,
+ "weak %select{variable|property|implicit property|instance variable}0 %1 may "
+ "be accessed multiple times in this %select{function|method|block|lambda}2 "
+ "and may be unpredictably set to nil; assign to a strong variable to keep "
+ "the object alive">,
InGroup<ARCRepeatedUseOfWeakMaybe>, DefaultIgnore;
def note_arc_weak_also_accessed_here : Note<
"also accessed here">;
Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Fri Sep 28 17:21:35 2012
@@ -30,6 +30,8 @@
class Scope;
class SwitchStmt;
class VarDecl;
+class DeclRefExpr;
+class ObjCIvarRefExpr;
class ObjCPropertyRefExpr;
namespace sema {
@@ -132,6 +134,8 @@
/// [self foo].prop | 0 (unknown) | prop (ObjCPropertyDecl)
/// self.prop1.prop2 | prop1 (ObjCPropertyDecl) | prop2 (ObjCPropertyDecl)
/// MyClass.prop | MyClass (ObjCInterfaceDecl) | -prop (ObjCMethodDecl)
+ /// weakVar | 0 (known) | weakVar (VarDecl)
+ /// self->weakIvar | self (VarDecl) | weakIvar (ObjCIvarDecl)
///
/// Objects are identified with only two Decls to make it reasonably fast to
/// compare them.
@@ -151,6 +155,9 @@
/// case of "implicit" properties (regular methods accessed via dot syntax).
const NamedDecl *Property;
+ /// Used to find the proper base profile for a given base expression.
+ static BaseInfoTy getBaseInfo(const Expr *BaseE);
+
// For use in DenseMap.
friend struct llvm::DenseMapInfo<WeakObjectProfileTy>;
inline WeakObjectProfileTy();
@@ -158,6 +165,8 @@
public:
WeakObjectProfileTy(const ObjCPropertyRefExpr *RE);
+ WeakObjectProfileTy(const DeclRefExpr *RE);
+ WeakObjectProfileTy(const ObjCIvarRefExpr *RE);
const NamedDecl *getProperty() const { return Property; }
@@ -219,10 +228,11 @@
WeakObjectUseMap WeakObjectUses;
public:
- /// Record that a weak property was accessed.
+ /// Record that a weak object was accessed.
///
/// Part of the implementation of -Wrepeated-use-of-weak.
- void recordUseOfWeak(const ObjCPropertyRefExpr *PropE);
+ template <typename ExprT>
+ inline void recordUseOfWeak(const ExprT *E, bool IsRead = true);
/// Record that a given expression is a "safe" access of a weak object (e.g.
/// assigning it to a strong variable.)
@@ -518,8 +528,15 @@
return Result;
}
+template <typename ExprT>
+void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) {
+ assert(E);
+ WeakUseVector &Uses = WeakObjectUses[WeakObjectProfileTy(E)];
+ Uses.push_back(WeakUseTy(E, IsRead));
}
-}
+
+} // end namespace sema
+} // end namespace clang
namespace llvm {
template <>
Modified: cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp (original)
+++ cfe/trunk/lib/Sema/AnalysisBasedWarnings.cpp Fri Sep 28 17:21:35 2012
@@ -957,19 +957,42 @@
const WeakObjectProfileTy &Key = I->second->first;
const WeakUseVector &Uses = I->second->second;
- // For complicated expressions like self.foo.bar, it's hard to keep track
- // of whether 'self.foo' is the same between two cases. We can only be
- // 100% sure of a repeated use if the "base" part of the key is a variable,
- // rather than, say, another property.
+ // For complicated expressions like 'a.b.c' and 'x.b.c', WeakObjectProfileTy
+ // may not contain enough information to determine that these are different
+ // properties. We can only be 100% sure of a repeated use in certain cases,
+ // and we adjust the diagnostic kind accordingly so that the less certain
+ // case can be turned off if it is too noisy.
unsigned DiagKind;
if (Key.isExactProfile())
DiagKind = diag::warn_arc_repeated_use_of_weak;
else
DiagKind = diag::warn_arc_possible_repeated_use_of_weak;
+ // Classify the weak object being accessed for better warning text.
+ // This enum should stay in sync with the cases in
+ // warn_arc_repeated_use_of_weak and warn_arc_possible_repeated_use_of_weak.
+ enum {
+ Variable,
+ Property,
+ ImplicitProperty,
+ Ivar
+ } ObjectKind;
+
+ const NamedDecl *D = Key.getProperty();
+ if (isa<VarDecl>(D))
+ ObjectKind = Variable;
+ else if (isa<ObjCPropertyDecl>(D))
+ ObjectKind = Property;
+ else if (isa<ObjCMethodDecl>(D))
+ ObjectKind = ImplicitProperty;
+ else if (isa<ObjCIvarDecl>(D))
+ ObjectKind = Ivar;
+ else
+ llvm_unreachable("Unexpected weak object kind!");
+
// Show the first time the object was read.
S.Diag(FirstRead->getLocStart(), DiagKind)
- << FunctionKind
+ << ObjectKind << D << FunctionKind
<< FirstRead->getSourceRange();
// Print all the other accesses as notes.
Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Fri Sep 28 17:21:35 2012
@@ -82,65 +82,77 @@
return M->getSelfDecl() == Param;
}
+FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy
+FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) {
+ E = E->IgnoreParenCasts();
+
+ const NamedDecl *D = 0;
+ bool IsExact = false;
+
+ switch (E->getStmtClass()) {
+ case Stmt::DeclRefExprClass:
+ D = cast<DeclRefExpr>(E)->getDecl();
+ IsExact = isa<VarDecl>(D);
+ break;
+ case Stmt::MemberExprClass: {
+ const MemberExpr *ME = cast<MemberExpr>(E);
+ D = ME->getMemberDecl();
+ IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts());
+ break;
+ }
+ case Stmt::ObjCIvarRefExprClass: {
+ const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E);
+ D = IE->getDecl();
+ IsExact = isSelfExpr(IE->getBase());
+ break;
+ }
+ case Stmt::PseudoObjectExprClass: {
+ const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E);
+ const ObjCPropertyRefExpr *BaseProp =
+ dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
+ if (BaseProp) {
+ D = getBestPropertyDecl(BaseProp);
+
+ const Expr *DoubleBase = BaseProp->getBase();
+ if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase))
+ DoubleBase = OVE->getSourceExpr();
+
+ IsExact = isSelfExpr(DoubleBase);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return BaseInfoTy(D, IsExact);
+}
+
+
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
const ObjCPropertyRefExpr *PropE)
- : Base(0, false), Property(getBestPropertyDecl(PropE)) {
+ : Base(0, true), Property(getBestPropertyDecl(PropE)) {
if (PropE->isObjectReceiver()) {
const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase());
- const Expr *E = OVE->getSourceExpr()->IgnoreParenCasts();
-
- switch (E->getStmtClass()) {
- case Stmt::DeclRefExprClass:
- Base.setPointer(cast<DeclRefExpr>(E)->getDecl());
- Base.setInt(isa<VarDecl>(Base.getPointer()));
- break;
- case Stmt::MemberExprClass: {
- const MemberExpr *ME = cast<MemberExpr>(E);
- Base.setPointer(ME->getMemberDecl());
- Base.setInt(isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()));
- break;
- }
- case Stmt::ObjCIvarRefExprClass: {
- const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E);
- Base.setPointer(IE->getDecl());
- if (isSelfExpr(IE->getBase()))
- Base.setInt(true);
- break;
- }
- case Stmt::PseudoObjectExprClass: {
- const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E);
- const ObjCPropertyRefExpr *BaseProp =
- dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
- if (BaseProp) {
- Base.setPointer(getBestPropertyDecl(BaseProp));
-
- const Expr *DoubleBase = BaseProp->getBase();
- if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase))
- DoubleBase = OVE->getSourceExpr();
-
- if (isSelfExpr(DoubleBase))
- Base.setInt(true);
- }
- break;
- }
- default:
- break;
- }
+ const Expr *E = OVE->getSourceExpr();
+ Base = getBaseInfo(E);
} else if (PropE->isClassReceiver()) {
Base.setPointer(PropE->getClassReceiver());
- Base.setInt(true);
} else {
assert(PropE->isSuperReceiver());
- Base.setInt(true);
}
}
-void FunctionScopeInfo::recordUseOfWeak(const ObjCPropertyRefExpr *RefExpr) {
- assert(RefExpr);
- WeakUseVector &Uses =
- WeakObjectUses[FunctionScopeInfo::WeakObjectProfileTy(RefExpr)];
- Uses.push_back(WeakUseTy(RefExpr, RefExpr->isMessagingGetter()));
+FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
+ const DeclRefExpr *DRE)
+ : Base(0, true), Property(DRE->getDecl()) {
+ assert(isa<VarDecl>(Property));
+}
+
+FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
+ const ObjCIvarRefExpr *IvarE)
+ : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) {
}
void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
@@ -164,22 +176,27 @@
return;
}
- if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) {
- // Has this property been seen as a weak property?
- FunctionScopeInfo::WeakObjectUseMap::iterator Uses =
- WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(RefExpr));
- if (Uses == WeakObjectUses.end())
- return;
+ // Has this weak object been seen before?
+ FunctionScopeInfo::WeakObjectUseMap::iterator Uses;
+ if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E))
+ Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(RefExpr));
+ else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E))
+ Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(IvarE));
+ else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(DRE));
+ else
+ return;
- // Has there been a read from the property using this Expr?
- FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse =
- std::find(Uses->second.rbegin(), Uses->second.rend(), WeakUseTy(E, true));
- if (ThisUse == Uses->second.rend())
- return;
+ if (Uses == WeakObjectUses.end())
+ return;
- ThisUse->markSafe();
+ // Has there been a read from the object using this Expr?
+ FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse =
+ std::find(Uses->second.rbegin(), Uses->second.rend(), WeakUseTy(E, true));
+ if (ThisUse == Uses->second.rend())
return;
- }
+
+ ThisUse->markSafe();
}
BlockScopeInfo::~BlockScopeInfo() { }
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Fri Sep 28 17:21:35 2012
@@ -5639,9 +5639,19 @@
if (LHSType.isNull())
LHSType = LHS->getType();
+
+ Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();
+
+ if (LT == Qualifiers::OCL_Weak) {
+ DiagnosticsEngine::Level Level =
+ Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc);
+ if (Level != DiagnosticsEngine::Ignored)
+ getCurFunction()->markSafeWeakUse(LHS);
+ }
+
if (checkUnsafeAssigns(Loc, LHSType, RHS))
return;
- Qualifiers::ObjCLifetime LT = LHSType.getObjCLifetime();
+
// FIXME. Check for other life times.
if (LT != Qualifiers::OCL_None)
return;
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Sep 28 17:21:35 2012
@@ -1425,6 +1425,15 @@
MarkDeclRefReferenced(E);
+ if (getLangOpts().ObjCARCWeak && isa<VarDecl>(D) &&
+ Ty.getObjCLifetime() == Qualifiers::OCL_Weak) {
+ DiagnosticsEngine::Level Level =
+ Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
+ E->getLocStart());
+ if (Level != DiagnosticsEngine::Ignored)
+ getCurFunction()->recordUseOfWeak(E);
+ }
+
// Just in case we're building an illegal pointer-to-member.
FieldDecl *FD = dyn_cast<FieldDecl>(D);
if (FD && FD->isBitField())
@@ -1986,9 +1995,22 @@
ObjCMethodFamily MF = CurMethod->getMethodFamily();
if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize)
Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();
- return Owned(new (Context)
- ObjCIvarRefExpr(IV, IV->getType(), Loc,
- SelfExpr.take(), true, true));
+
+ ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
+ Loc,
+ SelfExpr.take(),
+ true, true);
+
+ if (getLangOpts().ObjCAutoRefCount) {
+ if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
+ DiagnosticsEngine::Level Level =
+ Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, Loc);
+ if (Level != DiagnosticsEngine::Ignored)
+ getCurFunction()->recordUseOfWeak(Result);
+ }
+ }
+
+ return Owned(Result);
}
} else if (CurMethod->isInstanceMethod()) {
// We should warn if a local variable hides an ivar.
Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprMember.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprMember.cpp Fri Sep 28 17:21:35 2012
@@ -13,6 +13,7 @@
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
+#include "clang/Sema/ScopeInfo.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
@@ -1272,9 +1273,23 @@
if (warn)
Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();
}
- return Owned(new (Context) ObjCIvarRefExpr(IV, IV->getType(),
- MemberLoc, BaseExpr.take(),
- IsArrow));
+
+ ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
+ MemberLoc,
+ BaseExpr.take(),
+ IsArrow);
+
+ if (getLangOpts().ObjCAutoRefCount) {
+ if (IV->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
+ DiagnosticsEngine::Level Level =
+ Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
+ MemberLoc);
+ if (Level != DiagnosticsEngine::Ignored)
+ getCurFunction()->recordUseOfWeak(Result);
+ }
+ }
+
+ return Owned(Result);
}
// Objective-C property access.
Modified: cfe/trunk/lib/Sema/SemaPseudoObject.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaPseudoObject.cpp?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaPseudoObject.cpp (original)
+++ cfe/trunk/lib/Sema/SemaPseudoObject.cpp Fri Sep 28 17:21:35 2012
@@ -845,7 +845,8 @@
S.Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
SyntacticForm->getLocStart());
if (Level != DiagnosticsEngine::Ignored)
- S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr);
+ S.getCurFunction()->recordUseOfWeak(SyntacticRefExpr,
+ SyntacticRefExpr->isMessagingGetter());
}
return PseudoOpBuilder::complete(SyntacticForm);
Modified: cfe/trunk/test/SemaObjC/arc-repeated-weak.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-repeated-weak.mm?rev=164855&r1=164854&r2=164855&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-repeated-weak.mm (original)
+++ cfe/trunk/test/SemaObjC/arc-repeated-weak.mm Fri Sep 28 17:21:35 2012
@@ -3,6 +3,7 @@
@interface Test {
@public
Test *ivar;
+ __weak id weakIvar;
}
@property(weak) Test *weakProp;
@property(strong) Test *strongProp;
@@ -18,7 +19,7 @@
#define nil ((id)0)
void sanity(Test *a) {
- use(a.weakProp); // expected-warning{{weak property is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
+ use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
use(a.weakProp); // expected-note{{also accessed here}}
use(a.strongProp);
@@ -38,11 +39,22 @@
id next = get();
if (next)
a.weakProp = next; // no-warning
+
+ a->weakIvar = get(); // no-warning
+ next = get();
+ if (next)
+ a->weakIvar = next; // no-warning
+
+ extern __weak id x;
+ x = get(); // no-warning
+ next = get();
+ if (next)
+ x = next; // no-warning
}
void assignThenRead(Test *a) {
a.weakProp = get(); // expected-note{{also accessed here}}
- use(a.weakProp); // expected-warning{{weak property is accessed multiple times}}
+ use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
}
void twoVariables(Test *a, Test *b) {
@@ -51,22 +63,22 @@
}
void doubleLevelAccess(Test *a) {
- use(a.strongProp.weakProp); // expected-warning{{weak property may be accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
+ use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times in this function and may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
use(a.strongProp.weakProp); // expected-note{{also accessed here}}
}
void doubleLevelAccessIvar(Test *a) {
- use(a.strongProp.weakProp); // expected-warning{{weak property may be accessed multiple times}}
+ use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(a.strongProp.weakProp); // expected-note{{also accessed here}}
}
void implicitProperties(Test *a) {
- use(a.implicitProp); // expected-warning{{weak property is accessed multiple times}}
+ use(a.implicitProp); // expected-warning{{weak implicit property 'implicitProp' is accessed multiple times}}
use(a.implicitProp); // expected-note{{also accessed here}}
}
void classProperties() {
- use(Test.weakProp); // expected-warning{{weak property is accessed multiple times}}
+ use(Test.weakProp); // expected-warning{{weak implicit property 'weakProp' is accessed multiple times}}
use(Test.weakProp); // expected-note{{also accessed here}}
}
@@ -76,16 +88,38 @@
use(a.strongProp.weakProp); // no-warning
}
+void ivars(Test *a) {
+ use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
+ use(a->weakIvar); // expected-note{{also accessed here}}
+}
+
+void globals() {
+ extern __weak id a;
+ use(a); // expected-warning{{weak variable 'a' is accessed multiple times}}
+ use(a); // expected-note{{also accessed here}}
+}
+
void assignToStrongWrongInit(Test *a) {
id val = a.weakProp; // expected-note{{also accessed here}}
- use(a.weakProp); // expected-warning{{weak property is accessed multiple times}}
+ use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
}
void assignToStrongWrong(Test *a) {
id val;
val = a.weakProp; // expected-note{{also accessed here}}
- use(a.weakProp); // expected-warning{{weak property is accessed multiple times}}
+ use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
+}
+
+void assignToIvarWrong(Test *a) {
+ a->weakIvar = get(); // expected-note{{also accessed here}}
+ use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
+}
+
+void assignToGlobalWrong() {
+ extern __weak id a;
+ a = get(); // expected-note{{also accessed here}}
+ use(a); // expected-warning{{weak variable 'a' is accessed multiple times}}
}
void assignToStrongOK(Test *a) {
@@ -108,7 +142,7 @@
use(a.weakProp); // no-warning
use(^{
- use(a.weakProp); // expected-warning{{weak property is accessed multiple times in this block}}
+ use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this block}}
use(a.weakProp); // expected-note{{also accessed here}}
});
}
@@ -119,16 +153,24 @@
@implementation Test (Methods)
- (void)sanity {
- use(self.weakProp); // expected-warning{{weak property is accessed multiple times in this method but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
+ use(self.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this method but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
use(self.weakProp); // expected-note{{also accessed here}}
}
+- (void)ivars {
+ use(weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times in this method but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
+ use(weakIvar); // expected-note{{also accessed here}}
+}
+
- (void)doubleLevelAccessForSelf {
- use(self.strongProp.weakProp); // expected-warning{{weak property is accessed multiple times}}
+ use(self.strongProp.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
use(self.strongProp.weakProp); // expected-note{{also accessed here}}
- use(self->ivar.weakProp); // expected-warning{{weak property is accessed multiple times}}
+ use(self->ivar.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
use(self->ivar.weakProp); // expected-note{{also accessed here}}
+
+ use(self->ivar->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
+ use(self->ivar->weakIvar); // expected-note{{also accessed here}}
}
- (void)distinctFromOther:(Test *)other {
@@ -137,6 +179,9 @@
use(self->ivar.weakProp); // no-warning
use(other->ivar.weakProp); // no-warning
+
+ use(self.strongProp->weakIvar); // no-warning
+ use(other.strongProp->weakIvar); // no-warning
}
@end
@@ -146,7 +191,7 @@
public:
void fields() {
- use(a.weakProp); // expected-warning{{weak property is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
+ use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
use(a.weakProp); // expected-note{{also accessed here}}
}
@@ -157,7 +202,7 @@
}
static void doubleLevelAccessField(const Wrapper &x, const Wrapper &y) {
- use(x.a.weakProp); // expected-warning{{weak property may be accessed multiple times}}
+ use(x.a.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(y.a.weakProp); // expected-note{{also accessed here}}
}
};
@@ -170,7 +215,7 @@
// Most of these would require flow-sensitive analysis to silence correctly.
void assignAfterRead(Test *a) {
- if (!a.weakProp) // expected-warning{{weak property is accessed multiple times}}
+ if (!a.weakProp) // expected-warning{{weak property 'weakProp' is accessed multiple times}}
a.weakProp = get(); // expected-note{{also accessed here}}
}
@@ -178,25 +223,25 @@
if (condition())
a.weakProp = nil; // expected-note{{also accessed here}}
- use(a.weakProp); // expected-warning{{weak property is accessed multiple times}}
+ use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
}
void branch(Test *a) {
if (condition())
- use(a.weakProp); // expected-warning{{weak property is accessed multiple times}}
+ use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
else
use(a.weakProp); // expected-note{{also accessed here}}
}
void doubleLevelAccess(Test *a, Test *b) {
- use(a.strongProp.weakProp); // expected-warning{{weak property may be accessed multiple times}}
+ use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(b.strongProp.weakProp); // expected-note{{also accessed here}}
use(a.weakProp.weakProp); // no-warning
}
void doubleLevelAccessIvar(Test *a, Test *b) {
- use(a->ivar.weakProp); // expected-warning{{weak property may be accessed multiple times}}
+ use(a->ivar.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
use(b->ivar.weakProp); // expected-note{{also accessed here}}
use(a.strongProp.weakProp); // no-warning
More information about the cfe-commits
mailing list