blob: 902bdee27721861058c34207569bb6943b21d1e4 [file] [log] [blame]
George Karpenkova393e682018-08-29 20:29:17 +00001// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
Devin Coughlin4f770de2015-10-13 22:20:52 +00002
3void clang_analyzer_eval(bool);
4
5struct A {
6 int x;
7 void foo() const;
8 void bar();
Artem Dergachevf74ef4b2018-06-25 23:43:45 +00009
10 void testImplicitThisSyntax() {
11 x = 3;
12 foo();
13 clang_analyzer_eval(x == 3); // expected-warning{{TRUE}}
14 bar();
15 clang_analyzer_eval(x == 3); // expected-warning{{UNKNOWN}}
16 }
Devin Coughlin4f770de2015-10-13 22:20:52 +000017};
18
19struct B {
20 mutable int mut;
21 void foo() const;
22};
23
24struct C {
25 int *p;
26 void foo() const;
27};
28
29struct MutBase {
30 mutable int b_mut;
31};
32
33struct MutDerived : MutBase {
34 void foo() const;
35};
36
37struct PBase {
38 int *p;
39};
40
41struct PDerived : PBase {
42 void foo() const;
43};
44
45struct Inner {
46 int x;
47 int *p;
48 void bar() const;
49};
50
51struct Outer {
52 int x;
53 Inner in;
54 void foo() const;
55};
56
57void checkThatConstMethodWithoutDefinitionDoesNotInvalidateObject() {
58 A t;
59 t.x = 3;
60 t.foo();
61 clang_analyzer_eval(t.x == 3); // expected-warning{{TRUE}}
62 // Test non-const does invalidate
63 t.bar();
64 clang_analyzer_eval(t.x); // expected-warning{{UNKNOWN}}
65}
66
67void checkThatConstMethodDoesInvalidateMutableFields() {
68 B t;
69 t.mut = 4;
70 t.foo();
71 clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}}
72}
73
74void checkThatConstMethodDoesInvalidatePointedAtMemory() {
75 int x = 1;
76 C t;
77 t.p = &x;
78 t.foo();
79 clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
80 clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}}
81}
82
83void checkThatConstMethodDoesInvalidateInheritedMutableFields() {
84 MutDerived t;
85 t.b_mut = 4;
86 t.foo();
87 clang_analyzer_eval(t.b_mut); // expected-warning{{UNKNOWN}}
88}
89
90void checkThatConstMethodDoesInvalidateInheritedPointedAtMemory() {
91 int x = 1;
92 PDerived t;
93 t.p = &x;
94 t.foo();
95 clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
96 clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}}
97}
98
99void checkThatConstMethodDoesInvalidateContainedPointedAtMemory() {
100 int x = 1;
101 Outer t;
102 t.x = 2;
103 t.in.p = &x;
104 t.foo();
105 clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
106 clang_analyzer_eval(t.x == 2); // expected-warning{{TRUE}}
107 clang_analyzer_eval(t.in.p == &x); // expected-warning{{TRUE}}
108}
109
110void checkThatContainedConstMethodDoesNotInvalidateObjects() {
111 Outer t;
112 t.x = 1;
113 t.in.x = 2;
114 t.in.bar();
115 clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}}
116 clang_analyzer_eval(t.in.x == 2); // expected-warning{{TRUE}}
117}
118
Artem Dergachevf74ef4b2018-06-25 23:43:45 +0000119void checkPointerTypedThisExpression(A *a) {
120 a->x = 3;
121 a->foo();
122 clang_analyzer_eval(a->x == 3); // expected-warning{{TRUE}}
123 a->bar();
124 clang_analyzer_eval(a->x == 3); // expected-warning{{UNKNOWN}}
125}
126
127void checkReferenceTypedThisExpression(A &a) {
128 a.x = 3;
129 a.foo();
130 clang_analyzer_eval(a.x == 3); // expected-warning{{TRUE}}
131 a.bar();
132 clang_analyzer_eval(a.x == 3); // expected-warning{{UNKNOWN}}
133}
134
Devin Coughlin4f770de2015-10-13 22:20:52 +0000135// --- Versions of the above tests where the const method is inherited --- //
136
137struct B1 {
138 void foo() const;
139};
140
141struct D1 : public B1 {
142 int x;
143};
144
145struct D2 : public B1 {
146 mutable int mut;
147};
148
149struct D3 : public B1 {
150 int *p;
151};
152
153struct DInner : public B1 {
154 int x;
155 int *p;
156};
157
158struct DOuter : public B1 {
159 int x;
160 DInner in;
161};
162
163void checkThatInheritedConstMethodDoesNotInvalidateObject() {
164 D1 t;
165 t.x = 1;
166 t.foo();
167 clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}}
168}
169
170void checkThatInheritedConstMethodDoesInvalidateMutableFields() {
171 D2 t;
172 t.mut = 1;
173 t.foo();
174 clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}}
175}
176
177void checkThatInheritedConstMethodDoesInvalidatePointedAtMemory() {
178 int x = 1;
179 D3 t;
180 t.p = &x;
181 t.foo();
182 clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
183 clang_analyzer_eval(t.p == &x); // expected-warning{{TRUE}}
184}
185
186void checkThatInheritedConstMethodDoesInvalidateContainedPointedAtMemory() {
187 int x = 1;
188 DOuter t;
189 t.x = 2;
190 t.in.x = 3;
191 t.in.p = &x;
192 t.foo();
193 clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
194 clang_analyzer_eval(t.x == 2); // expected-warning{{TRUE}}
195 clang_analyzer_eval(t.in.x == 3); // expected-warning{{TRUE}}
196 clang_analyzer_eval(t.in.p == &x); // expected-warning{{TRUE}}
197}
198
199void checkThatInheritedContainedConstMethodDoesNotInvalidateObjects() {
200 DOuter t;
201 t.x = 1;
202 t.in.x = 2;
203 t.in.foo();
204 clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}}
205 clang_analyzer_eval(t.in.x == 2); // expected-warning{{TRUE}}
206}
207
208// --- PR21606 --- //
209
210struct s1 {
211 void g(const int *i) const;
212};
213
214struct s2 {
215 void f(int *i) {
216 m_i = i;
217 m_s.g(m_i);
218 if (m_i)
219 *i = 42; // no-warning
220 }
221
222 int *m_i;
223 s1 m_s;
224};
225
226void PR21606()
227{
228 s2().f(0);
229}
230
Devin Coughlin9c768692015-11-09 19:50:29 +0000231// --- PR25392 --- //
232
233struct HasConstMemberFunction {
234public:
235 void constMemberFunction() const;
236};
237
238HasConstMemberFunction hasNoReturn() { } // expected-warning {{control reaches end of non-void function}}
239
240void testUnknownWithConstMemberFunction() {
241 hasNoReturn().constMemberFunction();
242}
243
244void testNonRegionLocWithConstMemberFunction() {
245 (*((HasConstMemberFunction *)(&&label))).constMemberFunction();
246
247 label: return;
248}
249
Devin Coughlin4f770de2015-10-13 22:20:52 +0000250// FIXME
251// When there is a circular reference to an object and a const method is called
252// the object is not invalidated because TK_PreserveContents has already been
253// set.
254struct Outer2;
255
256struct InnerWithRef {
257 Outer2 *ref;
258};
259
260struct Outer2 {
261 int x;
262 InnerWithRef in;
263 void foo() const;
264};
265
266void checkThatConstMethodCallDoesInvalidateObjectForCircularReferences() {
267 Outer2 t;
268 t.x = 1;
269 t.in.ref = &t;
270 t.foo();
271 // FIXME: Should be UNKNOWN.
272 clang_analyzer_eval(t.x); // expected-warning{{TRUE}}
273}