Jordy Rose | 6d2b92e | 2012-05-16 21:13:36 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=range -triple i386-apple-darwin9 -verify %s |
| 2 | // RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.cstring,debug.ExprInspection -analyzer-constraints=range -triple x86_64-apple-darwin9 -verify %s |
Jordy Rose | f158b71 | 2012-05-16 20:29:44 +0000 | [diff] [blame] | 3 | |
| 4 | // This file runs in C++ mode so that the comparison type is 'bool', not 'int'. |
| 5 | void clang_analyzer_eval(int); |
| 6 | typedef typeof(sizeof(int)) size_t; |
| 7 | |
| 8 | // PR12206/12510 - When SimpleSValBuilder figures out that a symbol is fully |
| 9 | // constrained, it should cast the value to the result type in a binary |
| 10 | // operation...unless the binary operation is a comparison, in which case the |
| 11 | // two arguments should be the same type, but won't match the result type. |
| 12 | // |
| 13 | // This is not directly related to additive folding, but we use SValBuilder's |
| 14 | // additive folding to tickle the bug. ExprEngine will simplify fully-constrained |
| 15 | // symbols, so SValBuilder will only see them if they are (a) part of an evaluated |
| 16 | // SymExpr (e.g. with additive folding) or (b) generated by a checker (e.g. |
| 17 | // unix.cstring's strlen() modelling). |
| 18 | void PR12206(int x) { |
| 19 | size_t comparisonSize = sizeof(1 == 1); |
| 20 | |
| 21 | // Sanity check. This test is useless if size_t isn't bigger than bool. |
| 22 | clang_analyzer_eval(sizeof(size_t) > comparisonSize); // expected-warning{{TRUE}} |
| 23 | |
| 24 | // Build a SymIntExpr, dependent on x. |
| 25 | int local = x - 1; |
| 26 | |
| 27 | // Create a value that requires more bits to store than a comparison result. |
| 28 | int value = 1; |
| 29 | value <<= 8 * comparisonSize; |
| 30 | value += 1; |
| 31 | |
| 32 | // Constrain the value of x. |
| 33 | if (x != value) return; |
| 34 | |
| 35 | // Constant-folding will turn (local+1) back into the symbol for x. |
| 36 | // The point of this dance is to make SValBuilder be responsible for |
| 37 | // turning the symbol into a ConcreteInt, rather than ExprEngine. |
| 38 | |
| 39 | // Test relational operators. |
| 40 | clang_analyzer_eval((local + 1) >= 2); // expected-warning{{TRUE}} |
| 41 | clang_analyzer_eval(2 <= (local + 1)); // expected-warning{{TRUE}} |
| 42 | |
| 43 | // Test equality operators. |
| 44 | clang_analyzer_eval((local + 1) != 1); // expected-warning{{TRUE}} |
| 45 | clang_analyzer_eval(1 != (local + 1)); // expected-warning{{TRUE}} |
| 46 | } |
| 47 | |
| 48 | void PR12206_truncation(signed char x) { |
| 49 | // Build a SymIntExpr, dependent on x. |
| 50 | signed char local = x - 1; |
| 51 | |
| 52 | // Constrain the value of x. |
| 53 | if (x != 1) return; |
| 54 | |
| 55 | // Constant-folding will turn (local+1) back into the symbol for x. |
| 56 | // The point of this dance is to make SValBuilder be responsible for |
| 57 | // turning the symbol into a ConcreteInt, rather than ExprEngine. |
| 58 | |
| 59 | // Construct a value that cannot be represented by 'char', |
| 60 | // but that has the same lower bits as x. |
| 61 | signed int value = 1 + (1 << 8); |
| 62 | |
| 63 | // Test relational operators. |
| 64 | clang_analyzer_eval((local + 1) < value); // expected-warning{{TRUE}} |
| 65 | clang_analyzer_eval(value > (local + 1)); // expected-warning{{TRUE}} |
| 66 | |
| 67 | // Test equality operators. |
| 68 | clang_analyzer_eval((local + 1) != value); // expected-warning{{TRUE}} |
| 69 | clang_analyzer_eval(value != (local + 1)); // expected-warning{{TRUE}} |
| 70 | } |
| 71 | |
| 72 | // This test is insurance in case we significantly change how SymExprs are |
| 73 | // evaluated. |
| 74 | size_t strlen(const char *s); |
| 75 | void PR12206_strlen(const char *x) { |
| 76 | size_t comparisonSize = sizeof(1 == 1); |
| 77 | |
| 78 | // Sanity check. This test is useless if size_t isn't bigger than bool. |
| 79 | clang_analyzer_eval(sizeof(size_t) > comparisonSize); // expected-warning{{TRUE}} |
| 80 | |
| 81 | // Create a value that requires more bits to store than a comparison result. |
| 82 | size_t value = 1UL; |
| 83 | value <<= 8 * comparisonSize; |
| 84 | value += 1; |
| 85 | |
| 86 | // Constrain the length of x. |
| 87 | if (strlen(x) != value) return; |
| 88 | |
| 89 | // Test relational operators. |
| 90 | clang_analyzer_eval(strlen(x) >= 2); // expected-warning{{TRUE}} |
| 91 | clang_analyzer_eval(2 <= strlen(x)); // expected-warning{{TRUE}} |
| 92 | |
| 93 | // Test equality operators. |
| 94 | clang_analyzer_eval(strlen(x) != 1); // expected-warning{{TRUE}} |
| 95 | clang_analyzer_eval(1 != strlen(x)); // expected-warning{{TRUE}} |
| 96 | } |