forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			142 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
| // RUN: %clang_cc1 -analyze -analyzer-checker=core,deadcode.DeadStores,alpha.deadcode.UnreachableCode -verify -analyzer-opt-analyze-nested-blocks -Wno-unused-value %s
 | |
| 
 | |
| extern void foo(int a);
 | |
| 
 | |
| // The first few tests are non-path specific - we should be able to find them
 | |
| 
 | |
| void test(unsigned a) {
 | |
|   switch (a) {
 | |
|     a += 5; // expected-warning{{never executed}}
 | |
|   case 2:
 | |
|     a *= 10;
 | |
|   case 3:
 | |
|     a %= 2;
 | |
|   }
 | |
|   foo(a);
 | |
| }
 | |
| 
 | |
| void test2(unsigned a) {
 | |
|  help:
 | |
|   if (a > 0)
 | |
|     return;
 | |
|   if (a == 0)
 | |
|     return;
 | |
|   foo(a); // expected-warning{{never executed}}
 | |
|   goto help;
 | |
| }
 | |
| 
 | |
| void test3(unsigned a) {
 | |
|   while(1);
 | |
|   if (a > 5) { // expected-warning{{never executed}}
 | |
|     return;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // These next tests are path-sensitive
 | |
| 
 | |
| void test4() {
 | |
|   int a = 5;
 | |
| 
 | |
|   while (a > 1)
 | |
|     a -= 2;
 | |
| 
 | |
|   if (a > 1) {
 | |
|     a = a + 56; // expected-warning{{never executed}}
 | |
|   }
 | |
| 
 | |
|   foo(a);
 | |
| }
 | |
| 
 | |
| extern void bar(char c);
 | |
| 
 | |
| void test5(const char *c) {
 | |
|   foo(c[0]);
 | |
| 
 | |
|   if (!c) {
 | |
|     bar(1); // expected-warning{{never executed}}
 | |
|   }
 | |
| }
 | |
| 
 | |
| // These next tests are false positives and should not generate warnings
 | |
| 
 | |
| void test6(const char *c) {
 | |
|   if (c) return;
 | |
|   if (!c) return;
 | |
|   __builtin_unreachable(); // no-warning
 | |
| }
 | |
| 
 | |
| // Compile-time constant false positives
 | |
| #define CONSTANT 0
 | |
| enum test_enum { Off, On };
 | |
| void test7() {
 | |
|   if (CONSTANT)
 | |
|     return; // no-warning
 | |
| 
 | |
|   if (sizeof(int))
 | |
|     return; // no-warning
 | |
| 
 | |
|   if (Off)
 | |
|     return; // no-warning
 | |
| }
 | |
| 
 | |
| void test8() {
 | |
|   static unsigned a = 0;
 | |
| 
 | |
|   if (a)
 | |
|     a = 123; // no-warning
 | |
| 
 | |
|   a = 5;
 | |
| }
 | |
| 
 | |
| // Check for bugs where multiple statements are reported
 | |
| void test9(unsigned a) {
 | |
|   switch (a) {
 | |
|     if (a) // expected-warning{{never executed}}
 | |
|       foo(a + 5); // no-warning
 | |
|     else          // no-warning
 | |
|       foo(a);     // no-warning
 | |
|     case 1:
 | |
|     case 2:
 | |
|       break;
 | |
|     default:
 | |
|       break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Tests from flow-sensitive version
 | |
| void test10() {
 | |
|   goto c;
 | |
|   d:
 | |
|   goto e; // expected-warning {{never executed}}
 | |
|   c: ;
 | |
|   int i;
 | |
|   return;
 | |
|   goto b; // expected-warning {{never executed}}
 | |
|   goto a; // expected-warning {{never executed}}
 | |
|   b:
 | |
|   i = 1; // no-warning
 | |
|   a:
 | |
|   i = 2;  // no-warning
 | |
|   goto f;
 | |
|   e:
 | |
|   goto d;
 | |
|   f: ;
 | |
| }
 | |
| 
 | |
| // test11: we can actually end up in the default case, even if it is not
 | |
| // obvious: there might be something wrong with the given argument.
 | |
| enum foobar { FOO, BAR };
 | |
| extern void error();
 | |
| void test11(enum foobar fb) {
 | |
|   switch (fb) {
 | |
|     case FOO:
 | |
|       break;
 | |
|     case BAR:
 | |
|       break;
 | |
|     default:
 | |
|       error(); // no-warning
 | |
|       return;
 | |
|       error(); // expected-warning {{never executed}}
 | |
|   }
 | |
| }
 |