Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 7fffce7

Browse files
committed
-Warc-repeated-use-of-weak: Check messages to property accessors as well.
Previously, [foo weakProp] was not being treated the same as foo.weakProp. Now, for every explicit message send, we check if it's a property access, and if so, if the property is weak. Then for every assignment of a message, we have to do the same thing again. This is a potentially expensive increase because determining whether a method is a property accessor requires searching through the methods it overrides. However, without it -Warc-repeated-use-of-weak will miss cases from people who prefer not to use dot syntax. If this turns out to be too expensive, we can try caching the result somewhere, or even lose precision by not checking superclass methods. The warning is off-by-default, though. <rdar://problem/12407765> git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165718 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 900ab95 commit 7fffce7

File tree

4 files changed

+76
-3
lines changed

4 files changed

+76
-3
lines changed

Diff for: include/clang/Sema/ScopeInfo.h

+6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace clang {
2525
class Decl;
2626
class BlockDecl;
2727
class CXXMethodDecl;
28+
class ObjCPropertyDecl;
2829
class IdentifierInfo;
2930
class LabelDecl;
3031
class ReturnStmt;
@@ -34,6 +35,7 @@ class VarDecl;
3435
class DeclRefExpr;
3536
class ObjCIvarRefExpr;
3637
class ObjCPropertyRefExpr;
38+
class ObjCMessageExpr;
3739

3840
namespace sema {
3941

@@ -166,6 +168,7 @@ class FunctionScopeInfo {
166168

167169
public:
168170
WeakObjectProfileTy(const ObjCPropertyRefExpr *RE);
171+
WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property);
169172
WeakObjectProfileTy(const DeclRefExpr *RE);
170173
WeakObjectProfileTy(const ObjCIvarRefExpr *RE);
171174

@@ -261,6 +264,9 @@ class FunctionScopeInfo {
261264
template <typename ExprT>
262265
inline void recordUseOfWeak(const ExprT *E, bool IsRead = true);
263266

267+
void recordUseOfWeak(const ObjCMessageExpr *Msg,
268+
const ObjCPropertyDecl *Prop);
269+
264270
/// Record that a given expression is a "safe" access of a weak object (e.g.
265271
/// assigning it to a strong variable.)
266272
///

Diff for: lib/Sema/ScopeInfo.cpp

+29-3
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
103103
}
104104
}
105105

106+
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE,
107+
const ObjCPropertyDecl *Prop)
108+
: Base(0, true), Property(Prop) {
109+
if (BaseE)
110+
Base = getBaseInfo(BaseE);
111+
// else, this is a message accessing a property on super.
112+
}
113+
106114
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
107115
const DeclRefExpr *DRE)
108116
: Base(0, true), Property(DRE->getDecl()) {
@@ -114,6 +122,14 @@ FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
114122
: Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) {
115123
}
116124

125+
void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg,
126+
const ObjCPropertyDecl *Prop) {
127+
assert(Msg && Prop);
128+
WeakUseVector &Uses =
129+
WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)];
130+
Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0));
131+
}
132+
117133
void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
118134
E = E->IgnoreParenCasts();
119135

@@ -138,11 +154,21 @@ void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
138154
// Has this weak object been seen before?
139155
FunctionScopeInfo::WeakObjectUseMap::iterator Uses;
140156
if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E))
141-
Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(RefExpr));
157+
Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr));
142158
else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E))
143-
Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(IvarE));
159+
Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE));
144160
else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
145-
Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(DRE));
161+
Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE));
162+
else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(MsgE)) {
163+
Uses = WeakObjectUses.end();
164+
if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) {
165+
if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) {
166+
Uses =
167+
WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(),
168+
Prop));
169+
}
170+
}
171+
}
146172
else
147173
return;
148174

Diff for: lib/Sema/SemaExprObjC.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -2434,6 +2434,24 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
24342434
// In ARC, check for message sends which are likely to introduce
24352435
// retain cycles.
24362436
checkRetainCycles(Result);
2437+
2438+
if (!isImplicit && Method) {
2439+
if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) {
2440+
bool IsWeak =
2441+
Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak;
2442+
if (!IsWeak && Sel.isUnarySelector())
2443+
IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak;
2444+
2445+
if (IsWeak) {
2446+
DiagnosticsEngine::Level Level =
2447+
Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
2448+
LBracLoc);
2449+
if (Level != DiagnosticsEngine::Ignored)
2450+
getCurFunction()->recordUseOfWeak(Result, Prop);
2451+
2452+
}
2453+
}
2454+
}
24372455
}
24382456

24392457
return MaybeBindToTemporary(Result);

Diff for: test/SemaObjC/arc-repeated-weak.mm

+23
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,29 @@ void globals() {
9999
use(a); // expected-note{{also accessed here}}
100100
}
101101

102+
void messageGetter(Test *a) {
103+
use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
104+
use([a weakProp]); // expected-note{{also accessed here}}
105+
}
106+
107+
void messageSetter(Test *a) {
108+
[a setWeakProp:get()]; // no-warning
109+
[a setWeakProp:get()]; // no-warning
110+
}
111+
112+
void messageSetterAndGetter(Test *a) {
113+
[a setWeakProp:get()]; // expected-note{{also accessed here}}
114+
use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
115+
}
116+
117+
void mixDotAndMessageSend(Test *a, Test *b) {
118+
use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
119+
use([a weakProp]); // expected-note{{also accessed here}}
120+
121+
use([b weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
122+
use(b.weakProp); // expected-note{{also accessed here}}
123+
}
124+
102125

103126
void assignToStrongWrongInit(Test *a) {
104127
id val = a.weakProp; // expected-note{{also accessed here}}

0 commit comments

Comments
 (0)