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)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 test2(unsigned a)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 test3(unsigned a)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 test4()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 50 extern void bar(char c); 51 test5(const char * c)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 test6(const char * c)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 71 enum test_enum { Off, On }; test7()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 test8()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 test9(unsigned a)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 test10()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. 129 enum foobar { FOO, BAR }; 130 extern void error(); test11(enum foobar fb)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 inlined(int condition)144void inlined(int condition) { 145 if (condition) { 146 foo(5); // no-warning 147 } else { 148 foo(6); 149 } 150 } 151 testInlined()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. 164 void dostuff(int*A); varDecl1(int X)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 } varDecl2(int X)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. test12(int x)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. 200 extern int table[]; inlineFunction(const int i)201static int inlineFunction(const int i) { 202 if (table[i] != 0) 203 return 1; 204 return 0; 205 } test13(int i)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) macro(void)213void 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)224void macro2(void) { 225 MACRO(1); 226 } 227