comparison-implicit-casts.cpp revision e3f3825bd82f84f2a1ae0a02274a33298bb720b3
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'. 5void clang_analyzer_eval(int); 6typedef 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). 18void 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 48void 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. 74size_t strlen(const char *s); 75void 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