[cfe-commits] r76906 - /cfe/trunk/lib/Sema/SemaDecl.cpp

Mike Stump mrs at apple.com
Thu Jul 23 15:40:34 PDT 2009


Author: mrs
Date: Thu Jul 23 17:40:11 2009
New Revision: 76906

URL: http://llvm.org/viewvc/llvm-project?rev=76906&view=rev
Log:
Some cleanups suggested by Daniel.

Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=76906&r1=76905&r2=76906&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jul 23 17:40:11 2009
@@ -1021,8 +1021,8 @@
   // FIXME: They should never return 0, fix that, delete this code.
   if (cfg == 0)
     return NeverFallThrough;
-  // The CFG leaves in dead things, run a simple mark and sweep on it
-  // to weed out the trivially dead things.
+  // The CFG leaves in dead things, and we don't want to dead code paths to
+  // confuse us, so we mark all live things first.
   std::queue<CFGBlock*> workq;
   llvm::BitVector live(cfg->getNumBlockIDs());
   // Prep work queue
@@ -1032,28 +1032,36 @@
     CFGBlock *item = workq.front();
     workq.pop();
     live.set(item->getBlockID());
-    CFGBlock::succ_iterator i;
-    for (i=item->succ_begin(); i != item->succ_end(); ++i) {
-      if ((*i) && ! live[(*i)->getBlockID()]) {
-        live.set((*i)->getBlockID());
-        workq.push(*i);
+    for (CFGBlock::succ_iterator I=item->succ_begin(),
+           E=item->succ_end();
+         I != E;
+         ++I) {
+      if ((*I) && !live[(*I)->getBlockID()]) {
+        live.set((*I)->getBlockID());
+        workq.push(*I);
       }
     }
   }
 
-  CFGBlock::succ_iterator i;
+  // Now we know what is live, we check the live precessors of the exit block
+  // and look for fall through paths, being careful to ignore normal returns,
+  // and exceptional paths.
   bool HasLiveReturn = false;
   bool HasFakeEdge = false;
   bool HasPlainEdge = false;
-  for (i=cfg->getExit().pred_begin(); i != cfg->getExit().pred_end(); ++i) {
-    if (!live[(*i)->getBlockID()])
+  for (CFGBlock::succ_iterator I=cfg->getExit().pred_begin(),
+         E = cfg->getExit().pred_end();
+       I != E;
+       ++I) {
+    CFGBlock& B = **I;
+    if (!live[B.getBlockID()])
       continue;
-    if ((*i)->size() == 0) {
+    if (B.size() == 0) {
       // A labeled empty statement, or the entry block...
       HasPlainEdge = true;
       continue;
     }
-    Stmt *S = (**i)[(*i)->size()-1];
+    Stmt *S = B[B.size()-1];
     if (isa<ReturnStmt>(S)) {
       HasLiveReturn = true;
       continue;
@@ -1067,42 +1075,45 @@
       continue;
     }
     bool NoReturnEdge = false;
-    if (CallExpr *C = dyn_cast<CallExpr>(S))
-      {
-        Expr *CEE = C->getCallee()->IgnoreParenCasts();
-        if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
-          if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
-            if (FD->hasAttr<NoReturnAttr>()) {
-              NoReturnEdge = true;
-              HasFakeEdge = true;
-            }
+    if (CallExpr *C = dyn_cast<CallExpr>(S)) {
+      Expr *CEE = C->getCallee()->IgnoreParenCasts();
+      if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CEE)) {
+        if (FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) {
+          if (FD->hasAttr<NoReturnAttr>()) {
+            NoReturnEdge = true;
+            HasFakeEdge = true;
           }
         }
       }
+    }
+    // FIXME: Add noreturn message sends.
     if (NoReturnEdge == false)
       HasPlainEdge = true;
   }
-  if (HasPlainEdge) {
-    if (HasFakeEdge|HasLiveReturn)
-      return MaybeFallThrough;
-    // This says never for calls to functions that are not marked noreturn, that
-    // don't return.  For people that don't like this, we encourage marking the
-    // functions as noreturn.
-    return AlwaysFallThrough;
-  }
-  return NeverFallThrough;
+  if (!HasPlainEdge)
+    return NeverFallThrough;
+  if (HasFakeEdge || HasLiveReturn)
+    return MaybeFallThrough;
+  // This says AlwaysFallThrough for calls to functions that are not marked
+  // noreturn, that don't return.  If people would like this warning to be more
+  // accurate, such functions should be marked as noreturn.
+  return AlwaysFallThrough;
 }
 
 /// CheckFallThroughForFunctionDef - Check that we don't fall off the end of a
 /// function that should return a value.
 ///
-/// \returns Never iff we can never alter control flow (we always fall off the
-/// end of the statement, Conditional iff we might or might not alter
-/// control-flow and Always iff we always alter control flow (we never fall off
-/// the end of the statement).
+/// \returns AlwaysFallThrough iff we always fall off the end of the statement,
+/// MaybeFallThrough iff we might or might not fall off the end and
+/// NeverFallThrough iff we never fall off the end of the statement.  We assume
+/// that functions not marked noreturn will return.
 void Sema::CheckFallThroughForFunctionDef(Decl *D, Stmt *Body) {
-  // FIXME: Would be nice if we had a better way to control cascding errors, but
-  // for now, avoid them.
+  // FIXME: Would be nice if we had a better way to control cascading errors,
+  // but for now, avoid them.  The problem is that when Parse sees:
+  //   int foo() { return a; }
+  // The return is eaten and the Sema code sees just:
+  //   int foo() { }
+  // which this code would then warn about.
   if (getDiagnostics().hasErrorOccurred())
     return;
   if (Diags.getDiagnosticLevel(diag::warn_maybe_falloff_nonvoid_function)





More information about the cfe-commits mailing list