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.cpp38
1 files changed, 36 insertions, 2 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index e61110f195..9a6f950c24 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -2091,6 +2091,9 @@ static SourceLocation GetUnreachableLoc(CFGBlock &b) {
}
return b[1].getStmt()->getLocStart();
}
+ case Stmt::CXXTryStmtClass: {
+ return cast<CXXTryStmt>(S)->getHandler(0)->getCatchLoc();
+ }
default: ;
}
return S->getLocStart();
@@ -2167,12 +2170,20 @@ void Sema::CheckUnreachable(AnalysisContext &AC) {
return;
llvm::SmallVector<SourceLocation, 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 (!live[b.getBlockID()]) {
if (b.pred_begin() == b.pred_end()) {
+ if (!AddEHEdges && 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 += MarkLive(&b, live);
+ continue;
+ }
SourceLocation c = GetUnreachableLoc(b);
if (!c.isValid()) {
// Blocks without a location can't produce a warning, so don't mark
@@ -2222,11 +2233,29 @@ Sema::ControlFlowKind Sema::CheckFallThrough(AnalysisContext &AC) {
// FIXME: This should be NeverFallThrough
return NeverFallThroughOrReturn;
- // The CFG leaves in dead things, and we don't want to dead code paths to
+ // The CFG leaves in dead things, and we don't want the dead code paths to
// confuse us, so we mark all live things first.
std::queue<CFGBlock*> workq;
llvm::BitVector live(cfg->getNumBlockIDs());
- MarkLive(&cfg->getEntry(), live);
+ unsigned count = MarkLive(&cfg->getEntry(), live);
+
+ bool AddEHEdges = AC.getAddEHEdges();
+ if (!AddEHEdges && count != cfg->getNumBlockIDs())
+ // When there are things remaining dead, and we didn't add EH edges
+ // from CallExprs to the catch clauses, we have to go back and
+ // mark them as live.
+ for (CFG::iterator I = cfg->begin(), E = cfg->end(); I != E; ++I) {
+ CFGBlock &b = **I;
+ if (!live[b.getBlockID()]) {
+ if (b.pred_begin() == b.pred_end()) {
+ 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 += MarkLive(&b, live);
+ continue;
+ }
+ }
+ }
// Now we know what is live, we check the live precessors of the exit block
// and look for fall through paths, being careful to ignore normal returns,
@@ -2243,6 +2272,11 @@ Sema::ControlFlowKind Sema::CheckFallThrough(AnalysisContext &AC) {
if (!live[B.getBlockID()])
continue;
if (B.size() == 0) {
+ if (B.getTerminator() && isa<CXXTryStmt>(B.getTerminator())) {
+ HasAbnormalEdge = true;
+ continue;
+ }
+
// A labeled empty statement, or the entry block...
HasPlainEdge = true;
continue;