forked from OSchip/llvm-project
Refine location reporting for unreachable code warnings for comma expressions.
llvm-svn: 93574
This commit is contained in:
parent
a7f7b17bc7
commit
d4d6fb3374
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue