1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection %s -analyzer-store=region -verify |
2 | |
3 | void clang_analyzer_eval(int); |
4 | |
5 | unsigned foo(); |
6 | typedef struct bf { unsigned x:2; } bf; |
7 | void bar() { |
8 | bf y; |
9 | *(unsigned*)&y = foo(); |
10 | y.x = 1; |
11 | } |
12 | |
13 | struct s { |
14 | int n; |
15 | }; |
16 | |
17 | void f() { |
18 | struct s a; |
19 | int *p = &(a.n) + 1; // expected-warning{{Pointer arithmetic on}} |
20 | } |
21 | |
22 | typedef struct { |
23 | int x,y; |
24 | } Point; |
25 | |
26 | Point getit(void); |
27 | void test() { |
28 | Point p; |
29 | (void)(p = getit()).x; |
30 | } |
31 | |
32 | #define true ((bool)1) |
33 | #define false ((bool)0) |
34 | typedef _Bool bool; |
35 | |
36 | |
37 | void testLazyCompoundVal() { |
38 | Point p = {42, 0}; |
39 | Point q; |
40 | clang_analyzer_eval((q = p).x == 42); // expected-warning{{TRUE}} |
41 | clang_analyzer_eval(q.x == 42); // expected-warning{{TRUE}} |
42 | } |
43 | |
44 | |
45 | struct Bits { |
46 | unsigned a : 1; |
47 | unsigned b : 2; |
48 | unsigned c : 1; |
49 | |
50 | bool x; |
51 | |
52 | struct InnerBits { |
53 | bool y; |
54 | |
55 | unsigned d : 16; |
56 | unsigned e : 6; |
57 | unsigned f : 2; |
58 | } inner; |
59 | }; |
60 | |
61 | void testBitfields() { |
62 | struct Bits bits; |
63 | |
64 | if (foo() && bits.b) // expected-warning {{garbage}} |
65 | return; |
66 | if (foo() && bits.inner.e) // expected-warning {{garbage}} |
67 | return; |
68 | |
69 | bits.c = 1; |
70 | clang_analyzer_eval(bits.c == 1); // expected-warning {{TRUE}} |
71 | |
72 | if (foo() && bits.b) // expected-warning {{garbage}} |
73 | return; |
74 | if (foo() && bits.x) // expected-warning {{garbage}} |
75 | return; |
76 | |
77 | bits.x = true; |
78 | clang_analyzer_eval(bits.x == true); // expected-warning{{TRUE}} |
79 | bits.b = 2; |
80 | clang_analyzer_eval(bits.x == true); // expected-warning{{TRUE}} |
81 | if (foo() && bits.c) // no-warning |
82 | return; |
83 | |
84 | bits.inner.e = 50; |
85 | if (foo() && bits.inner.e) // no-warning |
86 | return; |
87 | if (foo() && bits.inner.y) // expected-warning {{garbage}} |
88 | return; |
89 | if (foo() && bits.inner.f) // expected-warning {{garbage}} |
90 | return; |
91 | |
92 | extern struct InnerBits getInner(); |
93 | bits.inner = getInner(); |
94 | |
95 | if (foo() && bits.inner.e) // no-warning |
96 | return; |
97 | if (foo() && bits.inner.y) // no-warning |
98 | return; |
99 | if (foo() && bits.inner.f) // no-warning |
100 | return; |
101 | |
102 | bits.inner.f = 1; |
103 | |
104 | if (foo() && bits.inner.e) // no-warning |
105 | return; |
106 | if (foo() && bits.inner.y) // no-warning |
107 | return; |
108 | if (foo() && bits.inner.f) // no-warning |
109 | return; |
110 | |
111 | if (foo() && bits.a) // expected-warning {{garbage}} |
112 | return; |
113 | } |
114 | |
115 | |
116 | //----------------------------------------------------------------------------- |
117 | // Incorrect behavior |
118 | //----------------------------------------------------------------------------- |
119 | |
120 | void testTruncation() { |
121 | struct Bits bits; |
122 | bits.c = 0x11; // expected-warning{{implicit truncation}} |
123 | // FIXME: We don't model truncation of bitfields. |
124 | clang_analyzer_eval(bits.c == 1); // expected-warning {{FALSE}} |
125 | } |
126 | |