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