1// RUN: %clang_cc1 -analyze -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}
67
68// Compile-time constant false positives
69#define CONSTANT 0
70enum test_enum { Off, On };
71void 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
82void 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
92void 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
107void 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.
128enum foobar { FOO, BAR };
129extern void error();
130void 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
143void inlined(int condition) {
144  if (condition) {
145    foo(5); // no-warning
146  } else {
147    foo(6);
148  }
149}
150
151void 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