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 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 } 97