Refine location reporting for unreachable code warnings for comma expressions.

llvm-svn: 93574
This commit is contained in:
Mike Stump 2010-01-15 23:17:13 +00:00
parent a7f7b17bc7
commit d4d6fb3374
2 changed files with 101 additions and 12 deletions

View File

@ -1328,14 +1328,47 @@ static void MarkLive(CFGBlock *e, llvm::BitVector &live) {
} }
} }
static SourceLocation GetUnreachableLoc(CFGBlock &b) {
Stmt *S;
if (!b.empty())
S = b[0].getStmt();
else if (b.getTerminator())
S = b.getTerminator();
else
return SourceLocation();
switch (S->getStmtClass()) {
case Expr::BinaryOperatorClass: {
BinaryOperator *Op = cast<BinaryOperator>(S);
if (Op->getOpcode() == BinaryOperator::Comma) {
if (b.size() < 2) {
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();
}
}
return b[1].getStmt()->getLocStart();
}
}
default: ;
}
return S->getLocStart();
}
static SourceLocation MarkLiveTop(CFGBlock *e, llvm::BitVector &live, static SourceLocation MarkLiveTop(CFGBlock *e, llvm::BitVector &live,
SourceManager &SM) { SourceManager &SM) {
std::queue<CFGBlock*> workq; std::queue<CFGBlock*> workq;
// Prep work queue // Prep work queue
workq.push(e); workq.push(e);
SourceLocation top; SourceLocation top = GetUnreachableLoc(*e);
if (!e->empty())
top = e[0][0].getStmt()->getLocStart();
bool FromMainFile = false; bool FromMainFile = false;
bool FromSystemHeader = false; bool FromSystemHeader = false;
bool TopValid = false; bool TopValid = false;
@ -1348,11 +1381,7 @@ static SourceLocation MarkLiveTop(CFGBlock *e, llvm::BitVector &live,
while (!workq.empty()) { while (!workq.empty()) {
CFGBlock *item = workq.front(); CFGBlock *item = workq.front();
workq.pop(); workq.pop();
SourceLocation c; SourceLocation c = GetUnreachableLoc(*item);
if (!item->empty())
c = item[0][0].getStmt()->getLocStart();
else if (item->getTerminator())
c = item->getTerminator()->getLocStart();
if (c.isValid() if (c.isValid()
&& (!TopValid && (!TopValid
|| (SM.isFromMainFile(c) && !FromMainFile) || (SM.isFromMainFile(c) && !FromMainFile)
@ -1412,10 +1441,14 @@ void Sema::CheckUnreachable(AnalysisContext &AC) {
CFGBlock &b = **I; CFGBlock &b = **I;
if (!live[b.getBlockID()]) { if (!live[b.getBlockID()]) {
if (b.pred_begin() == b.pred_end()) { if (b.pred_begin() == b.pred_end()) {
if (!b.empty()) SourceLocation c = GetUnreachableLoc(b);
lines.push_back(b[0].getStmt()->getLocStart()); if (!c.isValid()) {
else if (b.getTerminator()) // Blocks without a location can't produce a warning, so don't mark
lines.push_back(b.getTerminator()->getLocStart()); // reachable blocks from here as live.
live.set(b.getBlockID());
continue;
}
lines.push_back(c);
// Avoid excessive errors by marking everything reachable from here // Avoid excessive errors by marking everything reachable from here
MarkLive(&b, live); MarkLive(&b, live);
} }

View File

@ -1,5 +1,9 @@
// RUN: %clang %s -fsyntax-only -Xclang -verify -fblocks -Wunreachable-code // RUN: %clang %s -fsyntax-only -Xclang -verify -fblocks -Wunreachable-code
int halt() __attribute__((noreturn));
int live();
int dead();
void test1() { void test1() {
goto c; goto c;
d: d:
@ -18,3 +22,55 @@ void test1() {
goto d; goto d;
f: ; f: ;
} }
void test2() {
switch (live()) {
case 1:
halt(),
dead(); // expected-warning {{will never be executed}}
case 2:
live(),
halt(),
dead(); // expected-warning {{will never be executed}}
case 3:
live(),
halt();
dead(); // expected-warning {{will never be executed}}
case 4:
a4:
live(),
halt();
goto a4; // expected-warning {{will never be executed}}
case 5:
goto a5;
c5:
dead(); // expected-warning {{will never be executed}}
goto b5;
a5:
live(),
halt();
b5:
goto c5;
case 6:
if (live())
goto e6;
live(),
halt();
d6:
dead(); // expected-warning {{will never be executed}}
goto b6;
c6:
dead();
goto b6;
e6:
live(),
halt();
b6:
goto c6;
}
}