diff options
author | Mike Stump <mrs@apple.com> | 2010-01-15 02:06:42 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2010-01-15 02:06:42 +0000 |
commit | a609f56ab5cc680ee778174665fe6c66a5160dd6 (patch) | |
tree | fd9f7d9ed411a90b3c3e5a976a219bb7ded97157 /lib | |
parent | 7d3f576dc9ea6e866757abcd1736eb7e7433c325 (diff) |
Refine unreachable warnings. WIP.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93500 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 91 |
1 files changed, 87 insertions, 4 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 8176710e35..0ccb8f2b1d 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1328,6 +1328,66 @@ static void MarkLive(CFGBlock *e, llvm::BitVector &live) { } } +static SourceLocation MarkLiveTop(CFGBlock *e, llvm::BitVector &live, + SourceManager &SM) { + std::queue<CFGBlock*> workq; + // Prep work queue + workq.push(e); + SourceLocation top; + if (!e->empty()) + top = e[0][0].getStmt()->getLocStart(); + bool FromMainFile = false; + bool FromSystemHeader = false; + bool TopValid = false; + if (top.isValid()) { + FromMainFile = SM.isFromMainFile(top); + FromSystemHeader = SM.isInSystemHeader(top); + TopValid = true; + } + // Solve + while (!workq.empty()) { + CFGBlock *item = workq.front(); + workq.pop(); + SourceLocation c; + if (!item->empty()) + c = item[0][0].getStmt()->getLocStart(); + else if (item->getTerminator()) + c = item->getTerminator()->getLocStart(); + if (c.isValid() + && (!TopValid + || (SM.isFromMainFile(c) && !FromMainFile) + || (FromSystemHeader && !SM.isInSystemHeader(c)) + || SM.isBeforeInTranslationUnit(c, top))) { + top = c; + FromMainFile = SM.isFromMainFile(top); + FromSystemHeader = SM.isInSystemHeader(top); + } + live.set(item->getBlockID()); + for (CFGBlock::succ_iterator I=item->succ_begin(), + E=item->succ_end(); + I != E; + ++I) { + if ((*I) && !live[(*I)->getBlockID()]) { + live.set((*I)->getBlockID()); + workq.push(*I); + } + } + } + return top; +} + +namespace { +class LineCmp { + SourceManager &SM; +public: + LineCmp(SourceManager &sm) : SM(sm) { + } + bool operator () (SourceLocation l1, SourceLocation l2) { + return l1 < l2; + } +}; +} + /// CheckUnreachable - Check for unreachable code. void Sema::CheckUnreachable(AnalysisContext &AC) { // We avoid checking when there are errors, as the CFG won't faithfully match @@ -1345,15 +1405,38 @@ void Sema::CheckUnreachable(AnalysisContext &AC) { // Mark all live things first. MarkLive(&cfg->getEntry(), live); + llvm::SmallVector<SourceLocation, 24> lines; + // First, give warnings for blocks with no predecessors, as they + // can't be part of a loop. for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { CFGBlock &b = **I; if (!live[b.getBlockID()]) { - if (!b.empty()) - Diag(b[0].getStmt()->getLocStart(), diag::warn_unreachable); - // Avoid excessive errors by marking everything reachable from here - MarkLive(&b, live); + if (b.pred_begin() == b.pred_end()) { + if (!b.empty()) + lines.push_back(b[0].getStmt()->getLocStart()); + else if (b.getTerminator()) + lines.push_back(b.getTerminator()->getLocStart()); + // Avoid excessive errors by marking everything reachable from here + MarkLive(&b, live); + } } } + + // And then give warnings for the tops of loops. + for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) { + CFGBlock &b = **I; + if (!live[b.getBlockID()]) + // Avoid excessive errors by marking everything reachable from here + lines.push_back(MarkLiveTop(&b, live, Context.getSourceManager())); + } + + std::sort(lines.begin(), lines.end(), LineCmp(Context.getSourceManager())); + for (llvm::SmallVector<SourceLocation, 24>::iterator I = lines.begin(), + E = lines.end(); + I != E; + ++I) + if (I->isValid()) + Diag(*I, diag::warn_unreachable); } /// CheckFallThrough - Check that we don't fall off the end of a |