зеркало из https://github.com/microsoft/clang-1.git
Make noreturn functions alter the CFG.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76133 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
808825cd08
Коммит
cd7bf230a7
|
@ -478,6 +478,36 @@ CFGBlock* CFGBuilder::WalkAST(Stmt* Terminator, bool AlwaysAddStmt = false) {
|
|||
case Stmt::ParenExprClass:
|
||||
return WalkAST(cast<ParenExpr>(Terminator)->getSubExpr(), AlwaysAddStmt);
|
||||
|
||||
case Stmt::CallExprClass: {
|
||||
bool NoReturn = false;
|
||||
CallExpr *C = cast<CallExpr>(Terminator);
|
||||
Expr *CEE = C->getCallee()->IgnoreParenCasts();
|
||||
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
|
||||
// FIXME: We can follow objective-c methods and C++ member functions...
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
|
||||
if (FD->hasAttr<NoReturnAttr>())
|
||||
NoReturn = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!NoReturn)
|
||||
break;
|
||||
|
||||
if (Block) {
|
||||
if (!FinishBlock(Block))
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create new block with no successor for the remaining pieces.
|
||||
Block = createBlock(false);
|
||||
Block->appendStmt(Terminator);
|
||||
|
||||
// Wire this to the exit block directly.
|
||||
Block->addSuccessor(&cfg->getExit());
|
||||
|
||||
return WalkAST_VisitChildren(Terminator);
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
@ -1190,7 +1220,7 @@ CFGBlock* CFGBuilder::VisitBreakStmt(BreakStmt* B) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Now create a new block that ends with the continue statement.
|
||||
// Now create a new block that ends with the break statement.
|
||||
Block = createBlock(false);
|
||||
Block->setTerminator(B);
|
||||
|
||||
|
|
|
@ -138,7 +138,8 @@ int f17() {
|
|||
|
||||
// <rdar://problem/6506065>
|
||||
// The values of dead stores are only "consumed" in an enclosing expression
|
||||
// what that value is actually used. In other words, don't say "Although the value stored to 'x' is used...".
|
||||
// what that value is actually used. In other words, don't say "Although the
|
||||
// value stored to 'x' is used...".
|
||||
int f18() {
|
||||
int x = 0; // no-warning
|
||||
if (1)
|
||||
|
@ -173,3 +174,14 @@ void f20(void) {
|
|||
#pragma unused(x)
|
||||
}
|
||||
|
||||
void halt() __attribute__((noreturn));
|
||||
int f21() {
|
||||
int x = 4;
|
||||
|
||||
++x; // expected-warning{{never read}}
|
||||
if (1) {
|
||||
halt();
|
||||
(void)x;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче