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