diff options
author | Ted Kremenek <kremenek@apple.com> | 2010-02-23 05:59:20 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2010-02-23 05:59:20 +0000 |
commit | 72919a334752bc87001a7e3a0b6e5892768fac20 (patch) | |
tree | f144a5ccaf780264cc706ed0463722f2ae5173e4 /lib/Sema/SemaChecking.cpp | |
parent | 8de3cc6827afb70f4a6ce278d30549ff92a2fe49 (diff) |
Move the rest of the unreachable code analysis from libSema
to libAnalysis (with only the error reporting in libSema).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96893 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 215 |
1 files changed, 14 insertions, 201 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 3863e15587..5a2ab2c7ba 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2105,148 +2105,18 @@ void Sema::CheckImplicitConversion(Expr *E, QualType T) { return; } -static SourceLocation GetUnreachableLoc(CFGBlock &b, SourceRange &R1, - SourceRange &R2) { - Stmt *S; - unsigned sn = 0; - R1 = R2 = SourceRange(); - - top: - if (sn < b.size()) - S = b[sn].getStmt(); - else if (b.getTerminator()) - S = b.getTerminator(); - else - return SourceLocation(); - - switch (S->getStmtClass()) { - case Expr::BinaryOperatorClass: { - BinaryOperator *BO = cast<BinaryOperator>(S); - if (BO->getOpcode() == BinaryOperator::Comma) { - if (sn+1 < b.size()) - return b[sn+1].getStmt()->getLocStart(); - CFGBlock *n = &b; - while (1) { - if (n->getTerminator()) - return n->getTerminator()->getLocStart(); - if (n->succ_size() != 1) - return SourceLocation(); - n = n[0].succ_begin()[0]; - if (n->pred_size() != 1) - return SourceLocation(); - if (!n->empty()) - return n[0][0].getStmt()->getLocStart(); - } - } - R1 = BO->getLHS()->getSourceRange(); - R2 = BO->getRHS()->getSourceRange(); - return BO->getOperatorLoc(); - } - case Expr::UnaryOperatorClass: { - const UnaryOperator *UO = cast<UnaryOperator>(S); - R1 = UO->getSubExpr()->getSourceRange(); - return UO->getOperatorLoc(); - } - case Expr::CompoundAssignOperatorClass: { - const CompoundAssignOperator *CAO = cast<CompoundAssignOperator>(S); - R1 = CAO->getLHS()->getSourceRange(); - R2 = CAO->getRHS()->getSourceRange(); - return CAO->getOperatorLoc(); - } - case Expr::ConditionalOperatorClass: { - const ConditionalOperator *CO = cast<ConditionalOperator>(S); - return CO->getQuestionLoc(); - } - case Expr::MemberExprClass: { - const MemberExpr *ME = cast<MemberExpr>(S); - R1 = ME->getSourceRange(); - return ME->getMemberLoc(); - } - case Expr::ArraySubscriptExprClass: { - const ArraySubscriptExpr *ASE = cast<ArraySubscriptExpr>(S); - R1 = ASE->getLHS()->getSourceRange(); - R2 = ASE->getRHS()->getSourceRange(); - return ASE->getRBracketLoc(); - } - case Expr::CStyleCastExprClass: { - const CStyleCastExpr *CSC = cast<CStyleCastExpr>(S); - R1 = CSC->getSubExpr()->getSourceRange(); - return CSC->getLParenLoc(); - } - case Expr::CXXFunctionalCastExprClass: { - const CXXFunctionalCastExpr *CE = cast <CXXFunctionalCastExpr>(S); - R1 = CE->getSubExpr()->getSourceRange(); - return CE->getTypeBeginLoc(); - } - case Expr::ImplicitCastExprClass: - ++sn; - goto top; - case Stmt::CXXTryStmtClass: { - return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc(); - } - default: ; - } - R1 = S->getSourceRange(); - return S->getLocStart(); -} -static SourceLocation MarkLiveTop(CFGBlock *e, llvm::BitVector &live, - SourceManager &SM) { - std::queue<CFGBlock*> workq; - // Prep work queue - workq.push(e); - SourceRange R1, R2; - SourceLocation top = GetUnreachableLoc(*e, R1, R2); - 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 = GetUnreachableLoc(*item, R1, R2); - 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; -} - -static int LineCmp(const void *p1, const void *p2) { - SourceLocation *Line1 = (SourceLocation *)p1; - SourceLocation *Line2 = (SourceLocation *)p2; - return !(*Line1 < *Line2); -} namespace { - struct ErrLoc { - SourceLocation Loc; - SourceRange R1; - SourceRange R2; - ErrLoc(SourceLocation l, SourceRange r1, SourceRange r2) - : Loc(l), R1(r1), R2(r2) { } - }; +class UnreachableCodeHandler : public reachable_code::Callback { + Sema &S; +public: + UnreachableCodeHandler(Sema *s) : S(*s) {} + + void HandleUnreachable(SourceLocation L, SourceRange R1, SourceRange R2) { + S.Diag(L, diag::warn_unreachable) << R1 << R2; + } +}; } /// CheckUnreachable - Check for unreachable code. @@ -2257,66 +2127,8 @@ void Sema::CheckUnreachable(AnalysisContext &AC) { Diags.getDiagnosticLevel(diag::warn_unreachable) == Diagnostic::Ignored) return; - CFG *cfg = AC.getCFG(); - if (cfg == 0) - return; - - // Mark all live things first. - llvm::BitVector reachable(cfg->getNumBlockIDs()); - unsigned numReachable = ScanReachableFromBlock(cfg->getEntry(), reachable); - - // If there are no dead blocks, we're done. - if (numReachable == cfg->getNumBlockIDs()) - return; - - SourceRange R1, R2; - - llvm::SmallVector<ErrLoc, 24> lines; - bool AddEHEdges = AC.getAddEHEdges(); - // 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 (!reachable[b.getBlockID()]) { - if (b.pred_empty()) { - if (!AddEHEdges && dyn_cast_or_null<CXXTryStmt>(b.getTerminator())) { - // When not adding EH edges from calls, catch clauses - // can otherwise seem dead. Avoid noting them as dead. - numReachable += ScanReachableFromBlock(b, reachable); - continue; - } - SourceLocation c = GetUnreachableLoc(b, R1, R2); - if (!c.isValid()) { - // Blocks without a location can't produce a warning, so don't mark - // reachable blocks from here as live. - reachable.set(b.getBlockID()); - ++numReachable; - continue; - } - lines.push_back(ErrLoc(c, R1, R2)); - // Avoid excessive errors by marking everything reachable from here - numReachable += ScanReachableFromBlock(b, reachable); - } - } - } - - if (numReachable < cfg->getNumBlockIDs()) { - // 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 (!reachable[b.getBlockID()]) - // Avoid excessive errors by marking everything reachable from here - lines.push_back(ErrLoc(MarkLiveTop(&b, reachable, - Context.getSourceManager()), - SourceRange(), SourceRange())); - } - } - - llvm::array_pod_sort(lines.begin(), lines.end(), LineCmp); - for (llvm::SmallVectorImpl<ErrLoc>::iterator I=lines.begin(), E=lines.end(); - I != E; ++I) - if (I->Loc.isValid()) - Diag(I->Loc, diag::warn_unreachable) << I->R1 << I->R2; + UnreachableCodeHandler UC(this); + reachable_code::FindUnreachableCode(AC, UC); } /// CheckFallThrough - Check that we don't fall off the end of a @@ -2338,7 +2150,8 @@ Sema::ControlFlowKind Sema::CheckFallThrough(AnalysisContext &AC) { // confuse us, so we mark all live things first. std::queue<CFGBlock*> workq; llvm::BitVector live(cfg->getNumBlockIDs()); - unsigned count = ScanReachableFromBlock(cfg->getEntry(), live); + unsigned count = reachable_code::ScanReachableFromBlock(cfg->getEntry(), + live); bool AddEHEdges = AC.getAddEHEdges(); if (!AddEHEdges && count != cfg->getNumBlockIDs()) @@ -2352,7 +2165,7 @@ Sema::ControlFlowKind Sema::CheckFallThrough(AnalysisContext &AC) { if (b.getTerminator() && isa<CXXTryStmt>(b.getTerminator())) // When not adding EH edges from calls, catch clauses // can otherwise seem dead. Avoid noting them as dead. - count += ScanReachableFromBlock(b, live); + count += reachable_code::ScanReachableFromBlock(b, live); continue; } } |