1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,deadcode.DeadStores,alpha.deadcode.UnreachableCode -verify -analyzer-opt-analyze-nested-blocks -Wno-unused-value %s
2 
3 extern void foo(int a);
4 
5 // The first few tests are non-path specific - we should be able to find them
6 
7 void test(unsigned a) {
8   switch (a) {
9     a += 5; // expected-warning{{never executed}}
10   case 2:
11     a *= 10;
12   case 3:
13     a %= 2;
14   }
15   foo(a);
16 }
17 
18 void test2(unsigned a) {
19  help:
20   if (a > 0)
21     return;
22   if (a == 0)
23     return;
24   foo(a); // expected-warning{{never executed}}
25   goto help;
26 }
27 
28 void test3(unsigned a) {
29   while(1);
30   if (a > 5) { // expected-warning{{never executed}}
31     return;
32   }
33 }
34 
35 // These next tests are path-sensitive
36 
37 void test4() {
38   int a = 5;
39 
40   while (a > 1)
41     a -= 2;
42 
43   if (a > 1) {
44     a = a + 56; // expected-warning{{never executed}}
45   }
46 
47   foo(a);
48 }
49 
50 extern void bar(char c);
51 
52 void test5(const char *c) {
53   foo(c[0]);
54 
55   if (!c) {
56     bar(1); // expected-warning{{never executed}}
57   }
58 }
59 
60 // These next tests are false positives and should not generate warnings
61 
62 void test6(const char *c) {
63   if (c) return;
64   if (!c) return;
65   __builtin_unreachable(); // no-warning
66 }
67 
68 // Compile-time constant false positives
69 #define CONSTANT 0
70 enum test_enum { Off, On };
71 void test7() {
72   if (CONSTANT)
73     return; // no-warning
74 
75   if (sizeof(int))
76     return; // no-warning
77 
78   if (Off)
79     return; // no-warning
80 }
81 
82 void test8() {
83   static unsigned a = 0;
84 
85   if (a)
86     a = 123; // no-warning
87 
88   a = 5;
89 }
90 
91 // Check for bugs where multiple statements are reported
92 void test9(unsigned a) {
93   switch (a) {
94     if (a) // expected-warning{{never executed}}
95       foo(a + 5); // no-warning
96     else          // no-warning
97       foo(a);     // no-warning
98     case 1:
99     case 2:
100       break;
101     default:
102       break;
103   }
104 }
105 
106 // Tests from flow-sensitive version
107 void test10() {
108   goto c;
109   d:
110   goto e; // expected-warning {{never executed}}
111   c: ;
112   int i;
113   return;
114   goto b; // expected-warning {{never executed}}
115   goto a; // expected-warning {{never executed}}
116   b:
117   i = 1; // no-warning
118   a:
119   i = 2;  // no-warning
120   goto f;
121   e:
122   goto d;
123   f: ;
124 }
125 
126 // test11: we can actually end up in the default case, even if it is not
127 // obvious: there might be something wrong with the given argument.
128 enum foobar { FOO, BAR };
129 extern void error();
130 void test11(enum foobar fb) {
131   switch (fb) {
132     case FOO:
133       break;
134     case BAR:
135       break;
136     default:
137       error(); // no-warning
138       return;
139       error(); // expected-warning {{never executed}}
140   }
141 }
142 
143 void inlined(int condition) {
144   if (condition) {
145     foo(5); // no-warning
146   } else {
147     foo(6);
148   }
149 }
150 
151 void testInlined() {
152   extern int coin();
153   int cond = coin();
154   if (!cond) {
155     inlined(0);
156     if (cond) {
157       foo(5); // expected-warning {{never executed}}
158     }
159   }
160 }
161 
162 // Don't warn about unreachable VarDecl.
163 void dostuff(int*A);
164 void varDecl1(int X) {
165   switch (X) {
166     int A; // No warning here.
167   case 1:
168     dostuff(&A);
169     break;
170   case 2:
171     dostuff(&A);
172     break;
173   }
174 }
175 void varDecl2(int X) {
176   switch (X) {
177     int A=1; // expected-warning {{never executed}}
178   case 1:
179     dostuff(&A);
180     break;
181   case 2:
182     dostuff(&A);
183     break;
184   }
185 }
186 
187 // Ensure that ExplodedGraph and unoptimized CFG match.
188 void test12(int x) {
189   switch (x) {
190   case 1:
191     break; // not unreachable
192   case 2:
193     do { } while (0);
194     break;
195   }
196 }
197 
198 // Don't merge return nodes in ExplodedGraph unless they are same.
199 extern int table[];
200 static int inlineFunction(const int i) {
201   if (table[i] != 0)
202     return 1;
203   return 0;
204 }
205 void test13(int i) {
206   int x = inlineFunction(i);
207   x && x < 10; // no-warning
208 }
209 
210 // Don't warn in a macro
211 #define RETURN(X)  do { return; } while (0)
212 void macro(void) {
213   RETURN(1); // no-warning
214 }
215 
216