forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			221 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			221 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			C
		
	
	
	
| // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
 | |
| 
 | |
| void clang_analyzer_eval(int);
 | |
| void clang_analyzer_warnIfReached();
 | |
| 
 | |
| #define INT_MIN 0x80000000
 | |
| #define INT_MAX 0x7fffffff
 | |
| 
 | |
| // PR16833: Analyzer consumes memory until killed by kernel OOM killer
 | |
| // while analyzing large case ranges.
 | |
| void PR16833(unsigned op) {
 | |
|   switch (op) {
 | |
|   case 0x02 << 26 ... 0x03 << 26: // Analyzer should not hang here.
 | |
|     return;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void testAdjustment(int t) {
 | |
|   switch (t + 1) {
 | |
|   case 2:
 | |
|     clang_analyzer_eval(t == 1); // expected-warning{{TRUE}}
 | |
|     break;
 | |
|   case 3 ... 10:
 | |
|     clang_analyzer_eval(t > 1);        // expected-warning{{TRUE}}
 | |
|     clang_analyzer_eval(t + 2 <= 11);  // expected-warning{{TRUE}}
 | |
|     clang_analyzer_eval(t > 2);        // expected-warning{{UNKNOWN}}
 | |
|     clang_analyzer_eval(t + 1 == 3);   // expected-warning{{UNKNOWN}}
 | |
|     clang_analyzer_eval(t + 1 == 10);  // expected-warning{{UNKNOWN}}
 | |
|     break;
 | |
|   default:
 | |
|     clang_analyzer_warnIfReached();    // expected-warning{{REACHABLE}}
 | |
|   }
 | |
| }
 | |
| 
 | |
| void testUnknownVal(int value, int mask) {
 | |
|   // Once ConstraintManager will process '&' and this test will require some changes.
 | |
|   switch (value & mask) {
 | |
|     case 1:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|       break;
 | |
|     case 3 ... 10:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|       break;
 | |
|     default:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|   }
 | |
| }
 | |
| 
 | |
| void testSwitchCond(int arg) {
 | |
|   if (arg > 10) {
 | |
|     switch (arg) {
 | |
|     case INT_MIN ... 10:
 | |
|       clang_analyzer_warnIfReached(); // no-warning
 | |
|       break;
 | |
|     case 11 ... 20:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|       break;
 | |
|     default:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|     }
 | |
| 
 | |
|     switch (arg) {
 | |
|     case INT_MIN ... 9:
 | |
|       clang_analyzer_warnIfReached();  // no-warning
 | |
|       break;
 | |
|     case 10 ... 20:
 | |
|       clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
 | |
|       clang_analyzer_eval(arg > 10);   // expected-warning{{TRUE}}
 | |
|       break;
 | |
|     default:
 | |
|       clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
 | |
|     }
 | |
|   } // arg > 10
 | |
| }
 | |
| 
 | |
| void testDefaultUnreachable(int arg) {
 | |
|   if (arg > 10) {
 | |
|     switch (arg) {
 | |
|     case INT_MIN ... 9:
 | |
|       clang_analyzer_warnIfReached();   // no-warning
 | |
|       break;
 | |
|     case 10 ... INT_MAX:
 | |
|       clang_analyzer_warnIfReached();   // expected-warning{{REACHABLE}}
 | |
|       clang_analyzer_eval(arg > 10);    // expected-warning{{TRUE}}
 | |
|       break;
 | |
|     default:
 | |
|       clang_analyzer_warnIfReached();   // no-warning
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void testBranchReachability(int arg) {
 | |
|   if (arg > 10 && arg < 20) {
 | |
|     switch (arg) {
 | |
|     case INT_MIN ... 4:
 | |
|       clang_analyzer_warnIfReached(); // no-warning
 | |
|       break;
 | |
|     case 5 ... 9:
 | |
|       clang_analyzer_warnIfReached(); // no-warning
 | |
|       break;
 | |
|     case 10 ... 15:
 | |
|       clang_analyzer_warnIfReached();              // expected-warning{{REACHABLE}}
 | |
|       clang_analyzer_eval(arg > 10 && arg <= 15);  // expected-warning{{TRUE}}
 | |
|       break;
 | |
|     default:
 | |
|       clang_analyzer_warnIfReached(); // no-warning
 | |
|       break;
 | |
|     case 17 ... 25:
 | |
|       clang_analyzer_warnIfReached();              // expected-warning{{REACHABLE}}
 | |
|       clang_analyzer_eval(arg >= 17 && arg < 20);  // expected-warning{{TRUE}}
 | |
|       break;
 | |
|     case 26 ... INT_MAX:
 | |
|       clang_analyzer_warnIfReached();   // no-warning
 | |
|       break;
 | |
|     case 16:
 | |
|       clang_analyzer_warnIfReached();   // expected-warning{{REACHABLE}}
 | |
|       clang_analyzer_eval(arg == 16);   // expected-warning{{TRUE}}
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void testDefaultBranchRange(int arg) {
 | |
|   switch (arg) {
 | |
|   case INT_MIN ... 9:
 | |
|     clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
 | |
|     break;
 | |
|   case 20 ... INT_MAX:
 | |
|     clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
 | |
|     clang_analyzer_eval(arg >= 20);  // expected-warning{{TRUE}}
 | |
|     break;
 | |
|   default:
 | |
|     clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
 | |
|     clang_analyzer_eval(arg == 16);  // expected-warning{{FALSE}}
 | |
|     clang_analyzer_eval(arg > 9);    // expected-warning{{TRUE}}
 | |
|     clang_analyzer_eval(arg <= 20);  // expected-warning{{TRUE}}
 | |
| 
 | |
|   case 16:
 | |
|     clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
 | |
|   }
 | |
| }
 | |
| 
 | |
| void testAllUnreachableButDefault(int arg) {
 | |
|   if (arg < 0) {
 | |
|     switch (arg) {
 | |
|     case 0 ... 9:
 | |
|       clang_analyzer_warnIfReached(); // no-warning
 | |
|       break;
 | |
|     case 20 ... INT_MAX:
 | |
|       clang_analyzer_warnIfReached(); // no-warning
 | |
|       break;
 | |
|     default:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|       break;
 | |
|     case 16:
 | |
|       clang_analyzer_warnIfReached(); // no-warning
 | |
|     }
 | |
|     clang_analyzer_warnIfReached();   // expected-warning{{REACHABLE}}
 | |
|   }
 | |
| }
 | |
| 
 | |
| void testAllUnreachable(int arg) {
 | |
|   if (arg < 0) {
 | |
|     switch (arg) {
 | |
|     case 0 ... 9:
 | |
|       clang_analyzer_warnIfReached(); // no-warning
 | |
|       break;
 | |
|     case 20 ... INT_MAX:
 | |
|       clang_analyzer_warnIfReached(); // no-warning
 | |
|       break;
 | |
|     case 16:
 | |
|       clang_analyzer_warnIfReached(); // no-warning
 | |
|     }
 | |
|     clang_analyzer_warnIfReached();   // expected-warning{{REACHABLE}}
 | |
|   }
 | |
| }
 | |
| 
 | |
| void testDifferentTypes(int arg) {
 | |
|   switch (arg) {
 | |
|   case -1U ... 400000000LL:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|       break;
 | |
|     default:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|       break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void testDifferentTypes2(unsigned long arg) {
 | |
|   switch (arg) {
 | |
|   case 1UL ... 400000000UL:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|       break;
 | |
|     default:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|       break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void testDifferentTypes3(int arg) {
 | |
|   switch (arg) {
 | |
|   case 1UL ... 400000000UL:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|       break;
 | |
|     default:
 | |
|       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|       break;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void testConstant() {
 | |
|   switch (3) {
 | |
|   case 1 ... 5:
 | |
|     clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
 | |
|     break;
 | |
|   default:
 | |
|     clang_analyzer_warnIfReached(); // no-warning
 | |
|     break;
 | |
|   }
 | |
| }
 |