summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/ScopeInfo.h6
-rw-r--r--clang/lib/Sema/ScopeInfo.cpp32
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp18
-rw-r--r--clang/test/SemaObjC/arc-repeated-weak.mm23
4 files changed, 76 insertions, 3 deletions
diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h
index 0592265ccdf..7fbe07dc942 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -25,6 +25,7 @@ namespace clang {
class Decl;
class BlockDecl;
class CXXMethodDecl;
+class ObjCPropertyDecl;
class IdentifierInfo;
class LabelDecl;
class ReturnStmt;
@@ -34,6 +35,7 @@ class VarDecl;
class DeclRefExpr;
class ObjCIvarRefExpr;
class ObjCPropertyRefExpr;
+class ObjCMessageExpr;
namespace sema {
@@ -166,6 +168,7 @@ public:
public:
WeakObjectProfileTy(const ObjCPropertyRefExpr *RE);
+ WeakObjectProfileTy(const Expr *Base, const ObjCPropertyDecl *Property);
WeakObjectProfileTy(const DeclRefExpr *RE);
WeakObjectProfileTy(const ObjCIvarRefExpr *RE);
@@ -261,6 +264,9 @@ public:
template <typename ExprT>
inline void recordUseOfWeak(const ExprT *E, bool IsRead = true);
+ void recordUseOfWeak(const ObjCMessageExpr *Msg,
+ const ObjCPropertyDecl *Prop);
+
/// Record that a given expression is a "safe" access of a weak object (e.g.
/// assigning it to a strong variable.)
///
diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp
index 76f967d588b..c1d66299058 100644
--- a/clang/lib/Sema/ScopeInfo.cpp
+++ b/clang/lib/Sema/ScopeInfo.cpp
@@ -103,6 +103,14 @@ FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
}
}
+FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE,
+ const ObjCPropertyDecl *Prop)
+ : Base(0, true), Property(Prop) {
+ if (BaseE)
+ Base = getBaseInfo(BaseE);
+ // else, this is a message accessing a property on super.
+}
+
FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
const DeclRefExpr *DRE)
: Base(0, true), Property(DRE->getDecl()) {
@@ -114,6 +122,14 @@ FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
: Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) {
}
+void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg,
+ const ObjCPropertyDecl *Prop) {
+ assert(Msg && Prop);
+ WeakUseVector &Uses =
+ WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)];
+ Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0));
+}
+
void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
E = E->IgnoreParenCasts();
@@ -138,11 +154,21 @@ void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
// 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));
+ Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr));
else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E))
- Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(IvarE));
+ Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE));
else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- Uses = WeakObjectUses.find(FunctionScopeInfo::WeakObjectProfileTy(DRE));
+ Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE));
+ else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(MsgE)) {
+ Uses = WeakObjectUses.end();
+ if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) {
+ if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) {
+ Uses =
+ WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(),
+ Prop));
+ }
+ }
+ }
else
return;
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index 1bb4df04836..3f9c14c6852 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -2434,6 +2434,24 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
// In ARC, check for message sends which are likely to introduce
// retain cycles.
checkRetainCycles(Result);
+
+ if (!isImplicit && Method) {
+ if (const ObjCPropertyDecl *Prop = Method->findPropertyDecl()) {
+ bool IsWeak =
+ Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak;
+ if (!IsWeak && Sel.isUnarySelector())
+ IsWeak = ReturnType.getObjCLifetime() & Qualifiers::OCL_Weak;
+
+ if (IsWeak) {
+ DiagnosticsEngine::Level Level =
+ Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak,
+ LBracLoc);
+ if (Level != DiagnosticsEngine::Ignored)
+ getCurFunction()->recordUseOfWeak(Result, Prop);
+
+ }
+ }
+ }
}
return MaybeBindToTemporary(Result);
diff --git a/clang/test/SemaObjC/arc-repeated-weak.mm b/clang/test/SemaObjC/arc-repeated-weak.mm
index 1c6578ef131..ca13e20dcf2 100644
--- a/clang/test/SemaObjC/arc-repeated-weak.mm
+++ b/clang/test/SemaObjC/arc-repeated-weak.mm
@@ -99,6 +99,29 @@ void globals() {
use(a); // expected-note{{also accessed here}}
}
+void messageGetter(Test *a) {
+ use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
+ use([a weakProp]); // expected-note{{also accessed here}}
+}
+
+void messageSetter(Test *a) {
+ [a setWeakProp:get()]; // no-warning
+ [a setWeakProp:get()]; // no-warning
+}
+
+void messageSetterAndGetter(Test *a) {
+ [a setWeakProp:get()]; // expected-note{{also accessed here}}
+ use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
+}
+
+void mixDotAndMessageSend(Test *a, Test *b) {
+ use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
+ use([a weakProp]); // expected-note{{also accessed here}}
+
+ use([b weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
+ use(b.weakProp); // expected-note{{also accessed here}}
+}
+
void assignToStrongWrongInit(Test *a) {
id val = a.weakProp; // expected-note{{also accessed here}}
OpenPOWER on IntegriCloud