Clang Project

clang_source_code/test/Analysis/unreachable-code-path.c
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,deadcode.DeadStores,alpha.deadcode.UnreachableCode -verify -analyzer-opt-analyze-nested-blocks -Wno-unused-value %s
2
3extern void foo(int a);
4
5// The first few tests are non-path specific - we should be able to find them
6
7void 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
18void 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
28void 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
37void 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
50extern void bar(char c);
51
52void 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
62void 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
71enum test_enum { Off, On };
72void 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
83void 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
93void 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
108void 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.
129enum foobar { FOO, BAR };
130extern void error();
131void 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
144void inlined(int condition) {
145  if (condition) {
146    foo(5); // no-warning
147  } else {
148    foo(6);
149  }
150}
151
152void 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.
164void dostuff(int*A);
165void 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}
176void 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.
189void 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.
200extern int table[];
201static int inlineFunction(const int i) {
202  if (table[i] != 0)
203    return 1;
204  return 0;
205}
206void 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)
213void macro(void) {
214  RETURN(1); // no-warning
215}
216
217// Avoid FP when macro argument is known
218void writeSomething(int *x);
219#define MACRO(C)        \
220  if (!C) {             \
221    static int x;       \
222    writeSomething(&x); \
223  }
224void macro2(void) {
225  MACRO(1);
226}
227