]> granicus.if.org Git - clang/commitdiff
Refine location reporting for unreachable code warnings for comma expressions.
authorMike Stump <mrs@apple.com>
Fri, 15 Jan 2010 23:17:13 +0000 (23:17 +0000)
committerMike Stump <mrs@apple.com>
Fri, 15 Jan 2010 23:17:13 +0000 (23:17 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93574 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/Sema/warn-unreachable.c

index 0ccb8f2b1d5f0139b1c421ba449b11ea0a86d5b2..d81e187bb304d2bffbd1afed00ae23fc5b1c3605 100644 (file)
@@ -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,
                                SourceManager &SM) {
   std::queue<CFGBlock*> workq;
   // Prep work queue
   workq.push(e);
-  SourceLocation top;
-  if (!e->empty())
-    top = e[0][0].getStmt()->getLocStart();
+  SourceLocation top = GetUnreachableLoc(*e);
   bool FromMainFile = false;
   bool FromSystemHeader = false;
   bool TopValid = false;
@@ -1348,11 +1381,7 @@ static SourceLocation MarkLiveTop(CFGBlock *e, llvm::BitVector &live,
   while (!workq.empty()) {
     CFGBlock *item = workq.front();
     workq.pop();
-    SourceLocation c;
-    if (!item->empty())
-      c = item[0][0].getStmt()->getLocStart();
-    else if (item->getTerminator())
-      c = item->getTerminator()->getLocStart();
+    SourceLocation c = GetUnreachableLoc(*item);
     if (c.isValid()
         && (!TopValid
             || (SM.isFromMainFile(c) && !FromMainFile)
@@ -1412,10 +1441,14 @@ void Sema::CheckUnreachable(AnalysisContext &AC) {
     CFGBlock &b = **I;
     if (!live[b.getBlockID()]) {
       if (b.pred_begin() == b.pred_end()) {
-        if (!b.empty())
-          lines.push_back(b[0].getStmt()->getLocStart());
-        else if (b.getTerminator())
-          lines.push_back(b.getTerminator()->getLocStart());
+        SourceLocation c = GetUnreachableLoc(b);
+        if (!c.isValid()) {
+          // Blocks without a location can't produce a warning, so don't mark
+          // reachable blocks from here as live.
+          live.set(b.getBlockID());
+          continue;
+        }
+        lines.push_back(c);
         // Avoid excessive errors by marking everything reachable from here
         MarkLive(&b, live);
       }
index 2c123d0b0fc4cad16b255f603a2ad914d4fc673d..08ad6536987b62805d3049cae17cc7c88c6c6fac 100644 (file)
@@ -1,5 +1,9 @@
 // RUN: %clang %s -fsyntax-only -Xclang -verify -fblocks -Wunreachable-code
 
+int halt() __attribute__((noreturn));
+int live();
+int dead();
+
 void test1() {
   goto c;
   d:
@@ -18,3 +22,55 @@ void test1() {
   goto d;
   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;
+  }
+}