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