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:
Mike Stump 2009-07-17 01:04:31 +00:00
Родитель 808825cd08
Коммит cd7bf230a7
2 изменённых файлов: 47 добавлений и 5 удалений

Просмотреть файл

@ -117,9 +117,9 @@ public:
CFGBlock* VisitStmt(Stmt* Statement);
CFGBlock* VisitSwitchStmt(SwitchStmt* Terminator);
CFGBlock* VisitWhileStmt(WhileStmt* W);
// FIXME: Add support for ObjC-specific control-flow structures.
// NYS == Not Yet Supported
CFGBlock* NYS() {
badCFG = true;
@ -280,7 +280,7 @@ CFGBlock* CFGBuilder::addStmt(Stmt* Terminator) {
/// WalkAST - Used by addStmt to walk the subtree of a statement and
/// add extra blocks for ternary operators, &&, and ||. We also
/// process "," and DeclStmts (which may contain nested control-flow).
CFGBlock* CFGBuilder::WalkAST(Stmt* Terminator, bool AlwaysAddStmt = false) {
CFGBlock* CFGBuilder::WalkAST(Stmt* Terminator, bool AlwaysAddStmt = false) {
switch (Terminator->getStmtClass()) {
case Stmt::ConditionalOperatorClass: {
ConditionalOperator* C = cast<ConditionalOperator>(Terminator);
@ -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;
}