161 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			2.8 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}}
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void inlined(int condition) {
 | 
						|
  if (condition) {
 | 
						|
    foo(5); // no-warning
 | 
						|
  } else {
 | 
						|
    foo(6);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void testInlined() {
 | 
						|
  extern int coin();
 | 
						|
  int cond = coin();
 | 
						|
  if (!cond) {
 | 
						|
    inlined(0);
 | 
						|
    if (cond) {
 | 
						|
      foo(5); // expected-warning {{never executed}}
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |