Added an path-sensitive unreachable code checker to the experimental analyzer checks.
- Created a new class to do post-analysis
- Updated several test cases with unreachable code to expect a warning
- Added some general tests

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109286 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/additive-folding.c b/test/Analysis/additive-folding.c
index 15d7588..6e81fcf 100644
--- a/test/Analysis/additive-folding.c
+++ b/test/Analysis/additive-folding.c
@@ -18,7 +18,7 @@
 
   char* buf = malloc(1);
   if (a != 0 && b == 0)
-    return; // no-warning
+    return; // expected-warning{{never executed}}
   free(buf);
 }
 
@@ -29,7 +29,7 @@
 
   char* buf = malloc(1);
   if (a != 0 && b == 0)
-    return; // no-warning
+    return; // expected-warning{{never executed}}
   free(buf);
 }
 
@@ -40,11 +40,11 @@
   // This is part of PR7406.
   int b = a + 1LL;
   if (a != 0 && (b-1) == 0) // not crash
-    return; // no warning
+    return; // expected-warning{{never executed}}
 
   int c = a + 1U;
   if (a != 0 && (c-1) == 0) // not crash
-    return; // no warning
+    return; // expected-warning{{never executed}}
 
   free(buf);
 }
@@ -61,7 +61,7 @@
   if (a+1 != 0)
     return; // no-warning
   if (a-1 != UINT_MAX-1)
-    return; // no-warning
+    return; // expected-warning{{never executed}}
   free(b);
 }
 
@@ -72,7 +72,7 @@
   if (a+1 == 0)
     return; // no-warning
   if (a-1 == UINT_MAX-1)
-    return; // no-warning
+    return; // expected-warning{{never executed}}
   free(b);
 }
 
@@ -85,7 +85,7 @@
   if (a+1U != 2)
     return; // no-warning
   if (a-1U != 0)
-    return; // no-warning
+    return; // expected-warning{{never executed}}
   free(b);
 }
 
@@ -96,7 +96,7 @@
   if (a+1U == 2)
     return; // no-warning
   if (a-1U == 0)
-    return; // no-warning
+    return; // expected-warning{{never executed}}
   free(b);
 }
 
@@ -177,7 +177,7 @@
 void tautologyGT (unsigned a) {
   char* b = malloc(1);
   if (a > UINT_MAX)
-    return; // no-warning
+    return; // expected-warning{{never executed}}
   free(b);
 }
 
@@ -191,7 +191,7 @@
 void tautologyLT (unsigned a) {
   char* b = malloc(1);
   if (a < 0)
-    return; // no-warning
+    return; // expected-warning{{never executed}}
   free(b);
 }
 
diff --git a/test/Analysis/bstring.c b/test/Analysis/bstring.c
index f4ddb0a..3a5dfab 100644
--- a/test/Analysis/bstring.c
+++ b/test/Analysis/bstring.c
@@ -53,7 +53,7 @@
   memcpy(dst, src, 4); // no-warning
 
   if (memcpy(dst, src, 4) != dst) {
-    (void)*(char*)0; // no-warning -- should be unreachable
+    (void)*(char*)0; // expected-warning{{never executed}}
   }
 }
 
@@ -155,7 +155,7 @@
   memmove(dst, src, 4); // no-warning
 
   if (memmove(dst, src, 4) != dst) {
-    (void)*(char*)0; // no-warning -- should be unreachable
+    (void)*(char*)0; // expected-warning{{never executed}}
   }
 }
 
@@ -217,7 +217,7 @@
   char a[] = {1, 2, 3, 4};
 
   if (memcmp(a, a, 4))
-    (void)*(char*)0; // no-warning
+    (void)*(char*)0; // expected-warning{{never executed}}
 }
 
 void memcmp4 (char *input) {
@@ -231,11 +231,11 @@
   char a[] = {1, 2, 3, 4};
 
   if (memcmp(a, 0, 0)) // no-warning
-    (void)*(char*)0;   // no-warning
+    (void)*(char*)0;   // expected-warning{{never executed}}
   if (memcmp(0, a, 0)) // no-warning
-    (void)*(char*)0;   // no-warning
+    (void)*(char*)0;   // expected-warning{{never executed}}
   if (memcmp(a, input, 0)) // no-warning
-    (void)*(char*)0;   // no-warning
+    (void)*(char*)0;   // expected-warning{{never executed}}
 }
 
 void memcmp6 (char *a, char *b, size_t n) {
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
index b4c1314..91974f6 100644
--- a/test/Analysis/malloc.c
+++ b/test/Analysis/malloc.c
@@ -117,7 +117,7 @@
 	char *buf = calloc(2,2);
 	char result = buf[3]; // no-warning
 	if (buf[1] != 0) {
-	  free(buf);
+	  free(buf); // expected-warning{{never executed}}
 	}
 	return result; // expected-warning{{never released}}
 }
diff --git a/test/Analysis/unreachable-code-path.c b/test/Analysis/unreachable-code-path.c
new file mode 100644
index 0000000..cfe0408
--- /dev/null
+++ b/test/Analysis/unreachable-code-path.c
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -analyze -analyzer-experimental-checks -analyzer-check-objc-mem -analyzer-check-dead-stores -verify -analyzer-opt-analyze-nested-blocks %s
+
+extern void foo(int a);
+
+void test(unsigned a) {
+  switch (a) {
+    a += 5; // expected-warning{{never executed}}
+  case 2:
+    a *= 10;
+  case 3:
+    a %= 2;
+  }
+  foo(a);
+}
+
+void test2(unsigned a) {
+ help:
+  if (a > 0)
+    return;
+  if (a == 0)
+    return;
+  foo(a); // expected-warning{{never executed}}
+  goto help;
+}
+
+void test3() {
+  int a = 5;
+
+  while (a > 1)
+    a -= 2;
+
+  if (a > 1) {
+    a = a + 56; // expected-warning{{never executed}}
+  }
+
+  foo(a);
+}
+
+void test4(unsigned a) {
+  while(1);
+  if (a > 5) { // expected-warning{{never executed}}
+    return;
+  }
+}
+
+extern void bar(char c);
+
+void test5(const char *c) {
+  foo(c[0]);
+
+  if (!c) {
+    bar(1); // expected-warning{{never executed}}
+  }
+}
+