[RISCV] Add shrinkwrap test cases showing gaps in current impl
[llvm-project.git] / clang / test / Analysis / array-struct-region.cpp
blob31cbb60ba991e6cc075d4299cb13d38124b7d9d0
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
2 // RUN: -analyzer-checker=debug.ExprInspection -verify\
3 // RUN: -Wno-tautological-compare\
4 // RUN: -x c %s
5 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
6 // RUN: -analyzer-checker=debug.ExprInspection -verify\
7 // RUN: -Wno-tautological-compare\
8 // RUN: -x c++ -std=c++14 %s
9 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
10 // RUN: -analyzer-checker=debug.ExprInspection -verify\
11 // RUN: -Wno-tautological-compare\
12 // RUN: -x c++ -std=c++17 %s
13 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
14 // RUN: -analyzer-checker=debug.ExprInspection -verify\
15 // RUN: -Wno-tautological-compare\
16 // RUN: -DINLINE -x c %s
17 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
18 // RUN: -analyzer-checker=debug.ExprInspection -verify\
19 // RUN: -Wno-tautological-compare\
20 // RUN: -DINLINE -x c++ -std=c++14 %s
21 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
22 // RUN: -analyzer-checker=debug.ExprInspection -verify\
23 // RUN: -Wno-tautological-compare\
24 // RUN: -DINLINE -x c++ -std=c++17 %s
26 void clang_analyzer_eval(int);
28 struct S {
29 int field;
31 #if __cplusplus
32 const struct S *getThis() const { return this; }
33 const struct S *operator +() const { return this; }
35 bool check() const { return this == this; }
36 bool operator !() const { return this != this; }
38 int operator *() const { return field; }
39 #endif
42 #if __cplusplus
43 const struct S *operator -(const struct S &s) { return &s; }
44 bool operator ~(const struct S &s) { return (&s) != &s; }
45 #endif
48 #ifdef INLINE
49 struct S getS(void) {
50 struct S s = { 42 };
51 return s;
53 #else
54 struct S getS(void);
55 #endif
58 void testAssignment(void) {
59 struct S s = getS();
61 if (s.field != 42) return;
62 clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
64 s.field = 0;
65 clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}}
67 #if __cplusplus
68 clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
69 clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}
70 clang_analyzer_eval(-s == &s); // expected-warning{{TRUE}}
72 clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}
73 clang_analyzer_eval(!s); // expected-warning{{FALSE}}
74 clang_analyzer_eval(~s); // expected-warning{{FALSE}}
76 clang_analyzer_eval(*s == 0); // expected-warning{{TRUE}}
77 #endif
81 void testImmediateUse(void) {
82 int x = getS().field;
84 if (x != 42) return;
85 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
87 #if __cplusplus
88 clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}}
89 clang_analyzer_eval((void *)+getS() == (void *)&x); // expected-warning{{FALSE}}
90 clang_analyzer_eval((void *)-getS() == (void *)&x); // expected-warning{{FALSE}}
92 clang_analyzer_eval(getS().check()); // expected-warning{{TRUE}}
93 clang_analyzer_eval(!getS()); // expected-warning{{FALSE}}
94 clang_analyzer_eval(~getS()); // expected-warning{{FALSE}}
95 #endif
98 int getConstrainedField(struct S s) {
99 if (s.field != 42) return 42;
100 return s.field;
103 int getAssignedField(struct S s) {
104 s.field = 42;
105 return s.field;
108 void testArgument(void) {
109 clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}}
110 clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}
113 void testImmediateUseParens(void) {
114 int x = ((getS())).field;
116 if (x != 42) return;
117 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
119 clang_analyzer_eval(getConstrainedField(((getS()))) == 42); // expected-warning{{TRUE}}
120 clang_analyzer_eval(getAssignedField(((getS()))) == 42); // expected-warning{{TRUE}}
122 #if __cplusplus
123 clang_analyzer_eval(((getS())).check()); // expected-warning{{TRUE}}
124 clang_analyzer_eval(!((getS()))); // expected-warning{{FALSE}}
125 clang_analyzer_eval(~((getS()))); // expected-warning{{FALSE}}
126 #endif
130 //--------------------
131 // C++-only tests
132 //--------------------
134 #if __cplusplus
135 void testReferenceAssignment() {
136 const S &s = getS();
138 if (s.field != 42) return;
139 clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
141 clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
142 clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}
144 clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}
145 clang_analyzer_eval(!s); // expected-warning{{FALSE}}
146 clang_analyzer_eval(~s); // expected-warning{{FALSE}}
148 clang_analyzer_eval(*s == 42); // expected-warning{{TRUE}}
152 int getConstrainedFieldRef(const S &s) {
153 if (s.field != 42) return 42;
154 return s.field;
157 bool checkThis(const S &s) {
158 return s.getThis() == &s;
161 bool checkThisOp(const S &s) {
162 return +s == &s;
165 bool checkThisStaticOp(const S &s) {
166 return -s == &s;
169 void testReferenceArgument() {
170 clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
171 clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
172 clang_analyzer_eval(checkThisOp(getS())); // expected-warning{{TRUE}}
173 clang_analyzer_eval(checkThisStaticOp(getS())); // expected-warning{{TRUE}}
177 int getConstrainedFieldOp(S s) {
178 if (*s != 42) return 42;
179 return *s;
182 int getConstrainedFieldRefOp(const S &s) {
183 if (*s != 42) return 42;
184 return *s;
187 void testImmediateUseOp() {
188 int x = *getS();
189 if (x != 42) return;
190 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
192 clang_analyzer_eval(getConstrainedFieldOp(getS()) == 42); // expected-warning{{TRUE}}
193 clang_analyzer_eval(getConstrainedFieldRefOp(getS()) == 42); // expected-warning{{TRUE}}
196 namespace EmptyClass {
197 struct Base {
198 int& x;
200 Base(int& x) : x(x) {}
203 struct Derived : public Base {
204 Derived(int& x) : Base(x) {}
206 void operator=(int a) { x = a; }
209 Derived ref(int& a) { return Derived(a); }
211 // There used to be a warning here, because analyzer treated Derived as empty.
212 int test() {
213 int a;
214 ref(a) = 42;
215 return a; // no warning
219 #if __cplusplus >= 201703L
220 namespace aggregate_inheritance_cxx17 {
221 struct A {
222 int x;
225 struct B {
226 int y;
229 struct C: B {
230 int z;
233 struct D: A, C {
234 int w;
237 void foo() {
238 D d{1, 2, 3, 4};
239 clang_analyzer_eval(d.x == 1); // expected-warning{{TRUE}}
240 clang_analyzer_eval(d.y == 2); // expected-warning{{TRUE}}
241 clang_analyzer_eval(d.z == 3); // expected-warning{{TRUE}}
242 clang_analyzer_eval(d.w == 4); // expected-warning{{TRUE}}
244 } // namespace aggregate_inheritance_cxx17
245 #endif
247 namespace flex_array_inheritance_cxx17 {
248 struct A {
249 int flexible_array[];
252 struct B {
253 long cookie;
256 struct C : B {
257 A a;
260 void foo() {
261 C c{}; // no-crash
263 } // namespace flex_array_inheritance_cxx17
264 #endif