aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Sema/ScopeInfo.h1
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp35
-rw-r--r--test/SemaObjC/arc-repeated-weak.mm33
3 files changed, 64 insertions, 5 deletions
diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h
index c49dee7b41..feda9c96b8 100644
--- a/include/clang/Sema/ScopeInfo.h
+++ b/include/clang/Sema/ScopeInfo.h
@@ -169,6 +169,7 @@ public:
WeakObjectProfileTy(const DeclRefExpr *RE);
WeakObjectProfileTy(const ObjCIvarRefExpr *RE);
+ const NamedDecl *getBase() const { return Base.getPointer(); }
const NamedDecl *getProperty() const { return Property; }
/// Returns true if the object base specifies a known object in memory,
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index b039bc6f92..a20817f965 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -904,17 +904,24 @@ public:
};
}
-static bool isInLoop(const ParentMap &PM, const Stmt *S) {
+static bool isInLoop(const ASTContext &Ctx, const ParentMap &PM,
+ const Stmt *S) {
assert(S);
do {
switch (S->getStmtClass()) {
- case Stmt::DoStmtClass:
case Stmt::ForStmtClass:
case Stmt::WhileStmtClass:
case Stmt::CXXForRangeStmtClass:
case Stmt::ObjCForCollectionStmtClass:
return true;
+ case Stmt::DoStmtClass: {
+ const Expr *Cond = cast<DoStmt>(S)->getCond();
+ llvm::APSInt Val;
+ if (!Cond->EvaluateAsInt(Val, Ctx))
+ return true;
+ return Val.getBoolValue();
+ }
default:
break;
}
@@ -932,6 +939,8 @@ static void diagnoseRepeatedUseOfWeak(Sema &S,
typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap;
typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector;
+ ASTContext &Ctx = S.getASTContext();
+
const WeakObjectUseMap &WeakMap = CurFn->getWeakObjectUses();
// Extract all weak objects that are referenced more than once.
@@ -952,16 +961,32 @@ static void diagnoseRepeatedUseOfWeak(Sema &S,
continue;
// If there was only one read, followed by any number of writes, and the
- // read is not within a loop, don't warn.
+ // read is not within a loop, don't warn. Additionally, don't warn in a
+ // loop if the base object is a local variable -- local variables are often
+ // changed in loops.
if (UI == Uses.begin()) {
WeakUseVector::const_iterator UI2 = UI;
for (++UI2; UI2 != UE; ++UI2)
if (UI2->isUnsafe())
break;
- if (UI2 == UE)
- if (!isInLoop(PM, UI->getUseExpr()))
+ if (UI2 == UE) {
+ if (!isInLoop(Ctx, PM, UI->getUseExpr()))
continue;
+
+ const WeakObjectProfileTy &Profile = I->first;
+ if (!Profile.isExactProfile())
+ continue;
+
+ const NamedDecl *Base = Profile.getBase();
+ if (!Base)
+ Base = Profile.getProperty();
+ assert(Base && "A profile always has a base or property.");
+
+ if (const VarDecl *BaseVar = dyn_cast<VarDecl>(Base))
+ if (BaseVar->hasLocalStorage() && !isa<ParmVarDecl>(Base))
+ continue;
+ }
}
UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I));
diff --git a/test/SemaObjC/arc-repeated-weak.mm b/test/SemaObjC/arc-repeated-weak.mm
index 1539a9bcae..e652bee82d 100644
--- a/test/SemaObjC/arc-repeated-weak.mm
+++ b/test/SemaObjC/arc-repeated-weak.mm
@@ -257,6 +257,38 @@ void readOnlyLoop(Test *a) {
}
}
+void readInIterationLoop() {
+ for (Test *a in get())
+ use(a.weakProp); // no-warning
+}
+
+void readDoubleLevelAccessInLoop() {
+ for (Test *a in get()) {
+ use(a.strongProp.weakProp); // no-warning
+ }
+}
+
+void readParameterInLoop(Test *a) {
+ for (id unused in get()) {
+ use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
+ (void)unused;
+ }
+}
+
+void readGlobalInLoop() {
+ static __weak id a;
+ for (id unused in get()) {
+ use(a); // expected-warning{{weak variable 'a' is accessed multiple times in this function}}
+ (void)unused;
+ }
+}
+
+void doWhileLoop(Test *a) {
+ do {
+ use(a.weakProp); // no-warning
+ } while(0);
+}
+
@interface Test (Methods)
@end
@@ -351,3 +383,4 @@ void doubleLevelAccessIvar(Test *a, Test *b) {
use(a.strongProp.weakProp); // no-warning
}
+