From 6a11229dc87ec5fb1277b5845d247ff980e7a93b Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Fri, 15 Jan 2010 02:06:42 +0000 Subject: [PATCH] Refine unreachable warnings. WIP. llvm-svn: 93500 --- clang/lib/Sema/SemaDecl.cpp | 91 +++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 8176710e35a1..0ccb8f2b1d5f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/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 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 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::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