};
}
-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;
}
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.
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));
}
}
+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
use(a.strongProp.weakProp); // no-warning
}
+