[cfe-commits] r76133 - in /cfe/trunk: lib/Analysis/CFG.cpp test/Analysis/dead-stores.c

Mike Stump mrs at apple.com
Thu Jul 16 18:04:40 PDT 2009


Author: mrs
Date: Thu Jul 16 20:04:31 2009
New Revision: 76133

URL: http://llvm.org/viewvc/llvm-project?rev=76133&view=rev
Log:
Make noreturn functions alter the CFG.

Modified:
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/test/Analysis/dead-stores.c

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=76133&r1=76132&r2=76133&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Thu Jul 16 20:04:31 2009
@@ -117,9 +117,9 @@
   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 @@
 /// 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 @@
     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 @@
       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);
   

Modified: cfe/trunk/test/Analysis/dead-stores.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dead-stores.c?rev=76133&r1=76132&r2=76133&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/dead-stores.c (original)
+++ cfe/trunk/test/Analysis/dead-stores.c Thu Jul 16 20:04:31 2009
@@ -138,7 +138,8 @@
 
 // <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 @@
 #pragma unused(x)
 }
 
+void halt() __attribute__((noreturn));
+int f21() {
+  int x = 4;
+  
+  ++x; // expected-warning{{never read}}
+  if (1) {
+    halt();
+    (void)x;
+  }
+  return 1;
+}





More information about the cfe-commits mailing list