aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaChecking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaChecking.cpp')
-rw-r--r--lib/Sema/SemaChecking.cpp215
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;
}
}