diff options
author | Alexander Kornienko <alexfh@google.com> | 2013-01-30 03:49:44 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2013-01-30 03:49:44 +0000 |
commit | 4874a8143dc3032205f97527ff619730db3d1f57 (patch) | |
tree | fd6f43451e458f74a7ff35f7756820bca0651a84 /lib/Sema/AnalysisBasedWarnings.cpp | |
parent | e28f6abf588f51a21d1db638e460f9c086c08db4 (diff) |
Don't warn on fall-through from unreachable code.
Summary:
A motivating example:
class ClassWithDtor {
public:
~ClassWithDtor() {}
};
void fallthrough3(int n) {
switch (n) {
case 2:
do {
ClassWithDtor temp;
return;
} while (0); // This generates a chain of unreachable CFG blocks.
case 3:
break;
}
}
Reviewers: rsmith, doug.gregor, alexfh
Reviewed By: alexfh
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D330
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173889 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/AnalysisBasedWarnings.cpp')
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index 1687f69f47..b362239163 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -702,7 +702,27 @@ namespace { return FallthroughStmts; } + void fillReachableBlocks(CFG *Cfg) { + assert(ReachableBlocks.empty() && "ReachableBlocks already filled"); + std::deque<const CFGBlock *> BlockQueue; + + ReachableBlocks.insert(&Cfg->getEntry()); + BlockQueue.push_back(&Cfg->getEntry()); + while (!BlockQueue.empty()) { + const CFGBlock *P = BlockQueue.front(); + BlockQueue.pop_front(); + for (CFGBlock::const_succ_iterator I = P->succ_begin(), + E = P->succ_end(); + I != E; ++I) { + if (ReachableBlocks.insert(*I)) + BlockQueue.push_back(*I); + } + } + } + bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) { + assert(!ReachableBlocks.empty() && "ReachableBlocks empty"); + int UnannotatedCnt = 0; AnnotatedCnt = 0; @@ -726,8 +746,7 @@ namespace { if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end()) continue; // Case label is preceded with a normal label, good. - if (P->pred_begin() == P->pred_end()) { // The block is unreachable. - // This only catches trivially unreachable blocks. + if (!ReachableBlocks.count(P)) { for (CFGBlock::const_iterator ElIt = P->begin(), ElEnd = P->end(); ElIt != ElEnd; ++ElIt) { if (const CFGStmt *CS = ElIt->getAs<CFGStmt>()){ @@ -816,6 +835,7 @@ namespace { bool FoundSwitchStatements; AttrStmts FallthroughStmts; Sema &S; + llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks; }; } @@ -847,7 +867,7 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, if (!Cfg) return; - int AnnotatedCnt; + FM.fillReachableBlocks(Cfg); for (CFG::reverse_iterator I = Cfg->rbegin(), E = Cfg->rend(); I != E; ++I) { const CFGBlock *B = *I; @@ -856,6 +876,8 @@ static void DiagnoseSwitchLabelsFallthrough(Sema &S, AnalysisDeclContext &AC, if (!Label || !isa<SwitchCase>(Label)) continue; + int AnnotatedCnt; + if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt)) continue; |