[LLVM][IR] Use splat syntax when printing ConstantExpr based splats. (#116856)
[llvm-project.git] / clang / test / Analysis / call-invalidation.cpp
blobfb2b892b31a1f73676fc82c8f61db9842463cc4f
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
3 template <class T> void clang_analyzer_dump(T);
4 void clang_analyzer_eval(bool);
6 void usePointer(int * const *);
7 void useReference(int * const &);
9 void testPointer() {
10 int x;
11 int *p;
13 p = &x;
14 x = 42;
15 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
16 usePointer(&p);
17 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
19 p = &x;
20 x = 42;
21 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
22 useReference(p);
23 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
25 int * const cp1 = &x;
26 x = 42;
27 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
28 usePointer(&cp1);
29 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
31 int * const cp2 = &x;
32 x = 42;
33 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
34 useReference(cp2);
35 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
39 struct Wrapper {
40 int *ptr;
43 void useStruct(Wrapper &w);
44 void useConstStruct(const Wrapper &w);
46 void testPointerStruct() {
47 int x;
48 Wrapper w;
50 w.ptr = &x;
51 x = 42;
52 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
53 useStruct(w);
54 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
56 w.ptr = &x;
57 x = 42;
58 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
59 useConstStruct(w);
60 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
64 struct RefWrapper {
65 int &ref;
68 void useStruct(RefWrapper &w);
69 void useConstStruct(const RefWrapper &w);
71 void testReferenceStruct() {
72 int x;
73 RefWrapper w = { x };
75 x = 42;
76 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
77 useStruct(w);
78 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
81 // FIXME: This test is split into two functions because region invalidation
82 // does not preserve reference bindings.
83 void testConstReferenceStruct() {
84 int x;
85 RefWrapper w = { x };
87 x = 42;
88 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
89 useConstStruct(w);
90 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
94 int usePointerPure(int * const *) __attribute__((pure));
95 int usePointerConst(int * const *) __attribute__((const));
97 void testPureConst() {
98 extern int global;
99 int x;
100 int *p;
102 p = &x;
103 x = 42;
104 global = -5;
105 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
106 clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
108 (void)usePointerPure(&p);
109 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
110 clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
112 (void)usePointerConst(&p);
113 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
114 clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
116 usePointer(&p);
117 clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
118 clang_analyzer_eval(global == -5); // expected-warning{{UNKNOWN}}
122 struct PlainStruct {
123 int x, y;
124 mutable int z;
127 PlainStruct glob;
129 void useAnything(void *);
130 void useAnythingConst(const void *);
132 void testInvalidationThroughBaseRegionPointer() {
133 PlainStruct s1;
134 s1.x = 1;
135 s1.z = 1;
136 clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}
137 clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}
138 // Not only passing a structure pointer through const pointer parameter,
139 // but also passing a field pointer through const pointer parameter
140 // should preserve the contents of the structure.
141 useAnythingConst(&(s1.y));
142 clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}
143 // FIXME: Should say "UNKNOWN", because it is not uncommon to
144 // modify a mutable member variable through const pointer.
145 clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}
146 useAnything(&(s1.y));
147 clang_analyzer_eval(s1.x == 1); // expected-warning{{UNKNOWN}}
151 void useFirstConstSecondNonConst(const void *x, void *y);
152 void useFirstNonConstSecondConst(void *x, const void *y);
154 void testMixedConstNonConstCalls() {
155 PlainStruct s2;
156 s2.x = 1;
157 useFirstConstSecondNonConst(&(s2.x), &(s2.y));
158 clang_analyzer_eval(s2.x == 1); // expected-warning{{UNKNOWN}}
159 s2.x = 1;
160 useFirstNonConstSecondConst(&(s2.x), &(s2.y));
161 clang_analyzer_eval(s2.x == 1); // expected-warning{{UNKNOWN}}
162 s2.y = 1;
163 useFirstConstSecondNonConst(&(s2.x), &(s2.y));
164 clang_analyzer_eval(s2.y == 1); // expected-warning{{UNKNOWN}}
165 s2.y = 1;
166 useFirstNonConstSecondConst(&(s2.x), &(s2.y));
167 clang_analyzer_eval(s2.y == 1); // expected-warning{{UNKNOWN}}
170 namespace std {
171 class Opaque {
172 public:
173 Opaque();
174 int nested_member;
176 } // namespace std
178 struct StdWrappingOpaque {
179 std::Opaque o; // first member
180 int uninit;
182 struct StdWrappingOpaqueSwapped {
183 int uninit; // first member
184 std::Opaque o;
187 int testStdCtorDoesNotInvalidateParentObject() {
188 StdWrappingOpaque obj;
189 int x = obj.o.nested_member; // no-garbage: std::Opaque::ctor might initialized this
190 int y = obj.uninit; // FIXME: We should have a garbage read here. Read the details.
191 // As the first member ("obj.o") is invalidated, a conjured default binding is bound
192 // to the offset 0 within cluster "obj", and this masks every uninitialized fields
193 // that follows. We need a better store with extents to fix this.
194 return x + y;
197 int testStdCtorDoesNotInvalidateParentObjectSwapped() {
198 StdWrappingOpaqueSwapped obj;
199 int x = obj.o.nested_member; // no-garbage: std::Opaque::ctor might initialized this
200 int y = obj.uninit; // expected-warning {{Assigned value is garbage or undefined}}
201 return x + y;
204 class UserProvidedOpaque {
205 public:
206 UserProvidedOpaque(); // might reinterpret_cast(this)
207 int nested_member;
210 struct WrappingUserProvidedOpaque {
211 UserProvidedOpaque o; // first member
212 int uninit;
214 struct WrappingUserProvidedOpaqueSwapped {
215 int uninit; // first member
216 UserProvidedOpaque o;
219 int testUserProvidedCtorInvalidatesParentObject() {
220 WrappingUserProvidedOpaque obj;
221 int x = obj.o.nested_member; // no-garbage: UserProvidedOpaque::ctor might initialized this
222 int y = obj.uninit; // no-garbage: UserProvidedOpaque::ctor might reinterpret_cast(this) and write to the "uninit" member.
223 return x + y;
226 int testUserProvidedCtorInvalidatesParentObjectSwapped() {
227 WrappingUserProvidedOpaqueSwapped obj;
228 int x = obj.o.nested_member; // no-garbage: same as above
229 int y = obj.uninit; // no-garbage: same as above
230 return x + y;
233 struct WrappingStdWrappingOpaqueOuterInits {
234 int first = 1;
235 std::Opaque second;
236 int third = 3;
237 WrappingStdWrappingOpaqueOuterInits() {
238 clang_analyzer_dump(first); // expected-warning {{1 S32b}}
239 clang_analyzer_dump(second.nested_member); // expected-warning {{derived_}}
240 clang_analyzer_dump(third); // expected-warning {{3 S32b}}
244 struct WrappingUserProvidedOpaqueOuterInits {
245 int first = 1; // Potentially overwritten by UserProvidedOpaque::ctor
246 UserProvidedOpaque second; // Invalidates the object so far.
247 int third = 3; // Happens after UserProvidedOpaque::ctor, thus preserved!
248 WrappingUserProvidedOpaqueOuterInits() {
249 clang_analyzer_dump(first); // expected-warning {{derived_}}
250 clang_analyzer_dump(second.nested_member); // expected-warning {{derived_}}
251 clang_analyzer_dump(third); // expected-warning {{3 S32b}}
255 extern "C++" {
256 namespace std {
257 inline namespace v1 {
258 namespace custom_ranges {
259 struct Fancy {
260 struct iterator {
261 struct Opaque {
262 Opaque();
263 int nested_member;
264 }; // struct Opaque
265 }; // struct iterator
266 }; // struct Fancy
267 } // namespace custom_ranges
268 } // namespace v1
269 } // namespace std
270 } // extern "C++"
272 struct StdWrappingFancyOpaque {
273 int uninit;
274 std::custom_ranges::Fancy::iterator::Opaque o;
277 int testNestedStdNamespacesAndRecords() {
278 StdWrappingFancyOpaque obj;
279 int x = obj.o.nested_member; // no-garbage: ctor
280 int y = obj.uninit; // expected-warning {{Assigned value is garbage or undefined}}
281 return x + y;