| // 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(void); | |
| #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(void) { | |
| switch (3) { | |
| case 1 ... 5: | |
| clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} | |
| break; | |
| default: | |
| clang_analyzer_warnIfReached(); // no-warning | |
| break; | |
| } | |
| } | |
| void testExhaustiveSwitch(unsigned int a) { | |
| switch (a & 5) { | |
| case 0 ... 5: | |
| clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} | |
| break; | |
| default: | |
| clang_analyzer_warnIfReached(); // no-warning | |
| break; | |
| } | |
| } |