summaryrefslogtreecommitdiff
path: root/clang/test/Analysis/unreachable-code-path.c
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/Analysis/unreachable-code-path.c')
-rw-r--r--clang/test/Analysis/unreachable-code-path.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/clang/test/Analysis/unreachable-code-path.c b/clang/test/Analysis/unreachable-code-path.c
new file mode 100644
index 0000000..48a3462
--- /dev/null
+++ b/clang/test/Analysis/unreachable-code-path.c
@@ -0,0 +1,141 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,deadcode.DeadStores,experimental.deadcode.UnreachableCode -verify -analyzer-opt-analyze-nested-blocks -Wno-unused-value %s
+
+extern void foo(int a);
+
+// The first few tests are non-path specific - we should be able to find them
+
+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(unsigned a) {
+ while(1);
+ if (a > 5) { // expected-warning{{never executed}}
+ return;
+ }
+}
+
+// These next tests are path-sensitive
+
+void test4() {
+ int a = 5;
+
+ while (a > 1)
+ a -= 2;
+
+ if (a > 1) {
+ a = a + 56; // expected-warning{{never executed}}
+ }
+
+ foo(a);
+}
+
+extern void bar(char c);
+
+void test5(const char *c) {
+ foo(c[0]);
+
+ if (!c) {
+ bar(1); // expected-warning{{never executed}}
+ }
+}
+
+// These next tests are false positives and should not generate warnings
+
+void test6(const char *c) {
+ if (c) return;
+ if (!c) return;
+ __builtin_unreachable(); // no-warning
+}
+
+// Compile-time constant false positives
+#define CONSTANT 0
+enum test_enum { Off, On };
+void test7() {
+ if (CONSTANT)
+ return; // no-warning
+
+ if (sizeof(int))
+ return; // no-warning
+
+ if (Off)
+ return; // no-warning
+}
+
+void test8() {
+ static unsigned a = 0;
+
+ if (a)
+ a = 123; // no-warning
+
+ a = 5;
+}
+
+// Check for bugs where multiple statements are reported
+void test9(unsigned a) {
+ switch (a) {
+ if (a) // expected-warning{{never executed}}
+ foo(a + 5); // no-warning
+ else // no-warning
+ foo(a); // no-warning
+ case 1:
+ case 2:
+ break;
+ default:
+ break;
+ }
+}
+
+// Tests from flow-sensitive version
+void test10() {
+ goto c;
+ d:
+ goto e; // expected-warning {{never executed}}
+ c: ;
+ int i;
+ return;
+ goto b; // expected-warning {{never executed}}
+ goto a; // expected-warning {{never executed}}
+ b:
+ i = 1; // no-warning
+ a:
+ i = 2; // no-warning
+ goto f;
+ e:
+ goto d;
+ f: ;
+}
+
+// test11: we can actually end up in the default case, even if it is not
+// obvious: there might be something wrong with the given argument.
+enum foobar { FOO, BAR };
+extern void error();
+void test11(enum foobar fb) {
+ switch (fb) {
+ case FOO:
+ break;
+ case BAR:
+ break;
+ default:
+ error(); // no-warning
+ return;
+ error(); // expected-warning {{never executed}}
+ }
+}