1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,debug.ExprInspection -triple i386-apple-darwin9 -verify %s |
2 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.cstring,debug.ExprInspection -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 | |