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 
test(unsigned a)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 
test2(unsigned a)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 
test3(unsigned a)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 
test4()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 
test5(const char * c)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 
test6(const char * c)62 void test6(const char *c) {
63   if (c) return;
64   if (!c) return;
65   __builtin_unreachable(); // no-warning
66   __builtin_assume(0); // no-warning
67 }
68 
69 // Compile-time constant false positives
70 #define CONSTANT 0
71 enum test_enum { Off, On };
test7()72 void test7() {
73   if (CONSTANT)
74     return; // no-warning
75 
76   if (sizeof(int))
77     return; // no-warning
78 
79   if (Off)
80     return; // no-warning
81 }
82 
test8()83 void test8() {
84   static unsigned a = 0;
85 
86   if (a)
87     a = 123; // no-warning
88 
89   a = 5;
90 }
91 
92 // Check for bugs where multiple statements are reported
test9(unsigned a)93 void test9(unsigned a) {
94   switch (a) {
95     if (a) // expected-warning{{never executed}}
96       foo(a + 5); // no-warning
97     else          // no-warning
98       foo(a);     // no-warning
99     case 1:
100     case 2:
101       break;
102     default:
103       break;
104   }
105 }
106 
107 // Tests from flow-sensitive version
test10()108 void test10() {
109   goto c;
110   d:
111   goto e; // expected-warning {{never executed}}
112   c: ;
113   int i;
114   return;
115   goto b; // expected-warning {{never executed}}
116   goto a; // expected-warning {{never executed}}
117   b:
118   i = 1; // no-warning
119   a:
120   i = 2;  // no-warning
121   goto f;
122   e:
123   goto d;
124   f: ;
125 }
126 
127 // test11: we can actually end up in the default case, even if it is not
128 // obvious: there might be something wrong with the given argument.
129 enum foobar { FOO, BAR };
130 extern void error();
test11(enum foobar fb)131 void test11(enum foobar fb) {
132   switch (fb) {
133     case FOO:
134       break;
135     case BAR:
136       break;
137     default:
138       error(); // no-warning
139       return;
140       error(); // expected-warning {{never executed}}
141   }
142 }
143 
inlined(int condition)144 void inlined(int condition) {
145   if (condition) {
146     foo(5); // no-warning
147   } else {
148     foo(6);
149   }
150 }
151 
testInlined()152 void testInlined() {
153   extern int coin();
154   int cond = coin();
155   if (!cond) {
156     inlined(0);
157     if (cond) {
158       foo(5); // expected-warning {{never executed}}
159     }
160   }
161 }
162 
163 // Don't warn about unreachable VarDecl.
164 void dostuff(int*A);
varDecl1(int X)165 void varDecl1(int X) {
166   switch (X) {
167     int A; // No warning here.
168   case 1:
169     dostuff(&A);
170     break;
171   case 2:
172     dostuff(&A);
173     break;
174   }
175 }
varDecl2(int X)176 void varDecl2(int X) {
177   switch (X) {
178     int A=1; // expected-warning {{never executed}}
179   case 1:
180     dostuff(&A);
181     break;
182   case 2:
183     dostuff(&A);
184     break;
185   }
186 }
187 
188 // Ensure that ExplodedGraph and unoptimized CFG match.
test12(int x)189 void test12(int x) {
190   switch (x) {
191   case 1:
192     break; // not unreachable
193   case 2:
194     do { } while (0);
195     break;
196   }
197 }
198 
199 // Don't merge return nodes in ExplodedGraph unless they are same.
200 extern int table[];
inlineFunction(const int i)201 static int inlineFunction(const int i) {
202   if (table[i] != 0)
203     return 1;
204   return 0;
205 }
test13(int i)206 void test13(int i) {
207   int x = inlineFunction(i);
208   x && x < 10; // no-warning
209 }
210 
211 // Don't warn in a macro
212 #define RETURN(X)  do { return; } while (0)
macro(void)213 void macro(void) {
214   RETURN(1); // no-warning
215 }
216 
217 // Avoid FP when macro argument is known
218 void writeSomething(int *x);
219 #define MACRO(C)        \
220   if (!C) {             \
221     static int x;       \
222     writeSomething(&x); \
223   }
macro2(void)224 void macro2(void) {
225   MACRO(1);
226 }
227