aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/AnalysisBasedWarnings.cpp
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2013-01-30 03:49:44 +0000
committerAlexander Kornienko <alexfh@google.com>2013-01-30 03:49:44 +0000
commit4874a8143dc3032205f97527ff619730db3d1f57 (patch)
treefd6f43451e458f74a7ff35f7756820bca0651a84 /lib/Sema/AnalysisBasedWarnings.cpp
parente28f6abf588f51a21d1db638e460f9c086c08db4 (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.cpp28
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;