diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-10-11 16:10:19 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-10-11 16:10:19 +0000 |
commit | b5cd1220dd650a358622241237aa595c5d675506 (patch) | |
tree | 1b4974ec3c6daf56686833e1202d7125c681f922 /lib/Sema/AnalysisBasedWarnings.cpp | |
parent | 7fffce781e6ecbf4058b24df7e5ae3037569aa56 (diff) |
-Warc-repeated-use-of-weak: Don't warn on a single read followed by writes.
This is a "safe" pattern, or at least one that cannot be helped by using
a strong local variable. However, if the single read is within a loop,
it should /always/ be treated as potentially dangerous.
<rdar://problem/12437490>
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@165719 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/AnalysisBasedWarnings.cpp')
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 6d09f2c116..b039bc6f92 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -27,6 +27,7 @@ #include "clang/AST/StmtObjC.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/EvaluatedExprVisitor.h" +#include "clang/AST/ParentMap.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Analysis/AnalysisContext.h" @@ -903,10 +904,30 @@ public: }; } +static bool isInLoop(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; + default: + break; + } + } while ((S = PM.getParent(S))); + + return false; +} + static void diagnoseRepeatedUseOfWeak(Sema &S, const sema::FunctionScopeInfo *CurFn, - const Decl *D) { + const Decl *D, + const ParentMap &PM) { typedef sema::FunctionScopeInfo::WeakObjectProfileTy WeakObjectProfileTy; typedef sema::FunctionScopeInfo::WeakObjectUseMap WeakObjectUseMap; typedef sema::FunctionScopeInfo::WeakUseVector WeakUseVector; @@ -918,8 +939,6 @@ static void diagnoseRepeatedUseOfWeak(Sema &S, for (WeakObjectUseMap::const_iterator I = WeakMap.begin(), E = WeakMap.end(); I != E; ++I) { const WeakUseVector &Uses = I->second; - if (Uses.size() <= 1) - continue; // Find the first read of the weak object. WeakUseVector::const_iterator UI = Uses.begin(), UE = Uses.end(); @@ -932,6 +951,19 @@ static void diagnoseRepeatedUseOfWeak(Sema &S, if (UI == UE) continue; + // If there was only one read, followed by any number of writes, and the + // read is not within a loop, don't warn. + 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())) + continue; + } + UsesByStmt.push_back(StmtUsesPair(UI->getUseExpr(), I)); } @@ -1519,7 +1551,7 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, if (S.getLangOpts().ObjCARCWeak && Diags.getDiagnosticLevel(diag::warn_arc_repeated_use_of_weak, D->getLocStart()) != DiagnosticsEngine::Ignored) - diagnoseRepeatedUseOfWeak(S, fscope, D); + diagnoseRepeatedUseOfWeak(S, fscope, D, AC.getParentMap()); // Collect statistics about the CFG if it was built. if (S.CollectStats && AC.isCFGBuilt()) { |