]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Analysis/const-method-call.cpp
Vendor import of clang trunk r300422:
[FreeBSD/FreeBSD.git] / test / Analysis / const-method-call.cpp
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
2
3 void clang_analyzer_eval(bool);
4
5 struct A {
6   int x;
7   void foo() const;
8   void bar();
9 };
10
11 struct B {
12   mutable int mut;
13   void foo() const;
14 };
15
16 struct C {
17   int *p;
18   void foo() const;
19 };
20
21 struct MutBase {
22   mutable int b_mut;
23 };
24
25 struct MutDerived : MutBase {
26   void foo() const;
27 };
28
29 struct PBase {
30   int *p;
31 };
32
33 struct PDerived : PBase {
34   void foo() const;
35 };
36
37 struct Inner {
38   int x;
39   int *p;
40   void bar() const;
41 };
42
43 struct Outer {
44   int x;
45   Inner in;
46   void foo() const;
47 };
48
49 void 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
59 void checkThatConstMethodDoesInvalidateMutableFields() {
60   B t;
61   t.mut = 4;
62   t.foo();
63   clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}}
64 }
65
66 void 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
75 void checkThatConstMethodDoesInvalidateInheritedMutableFields() {
76   MutDerived t;
77   t.b_mut = 4;
78   t.foo();
79   clang_analyzer_eval(t.b_mut); // expected-warning{{UNKNOWN}}
80 }
81
82 void 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
91 void 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
102 void 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
113 struct B1 {
114   void foo() const;
115 };
116
117 struct D1 : public B1 {
118   int x;
119 };
120
121 struct D2 : public B1 {
122   mutable int mut;
123 };
124
125 struct D3 : public B1 {
126   int *p;
127 };
128
129 struct DInner : public B1 {
130   int x;
131   int *p;
132 };
133
134 struct DOuter : public B1 {
135   int x;
136   DInner in;
137 };
138
139 void checkThatInheritedConstMethodDoesNotInvalidateObject() {
140   D1 t;
141   t.x = 1;
142   t.foo();
143   clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}}
144 }
145
146 void checkThatInheritedConstMethodDoesInvalidateMutableFields() {
147   D2 t;
148   t.mut = 1;
149   t.foo();
150   clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}}
151 }
152
153 void 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
162 void 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
175 void 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
186 struct s1 {
187     void g(const int *i) const;
188 };
189
190 struct 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
202 void PR21606()
203 {
204     s2().f(0);
205 }
206
207 // --- PR25392 --- //
208
209 struct HasConstMemberFunction {
210 public:
211   void constMemberFunction() const;
212 };
213
214 HasConstMemberFunction hasNoReturn() { } // expected-warning {{control reaches end of non-void function}}
215
216 void testUnknownWithConstMemberFunction() {
217   hasNoReturn().constMemberFunction();
218 }
219
220 void testNonRegionLocWithConstMemberFunction() {
221   (*((HasConstMemberFunction *)(&&label))).constMemberFunction();
222
223   label: return;
224 }
225
226 // 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.
230 struct Outer2;
231
232 struct InnerWithRef {
233   Outer2 *ref;
234 };
235
236 struct Outer2 {
237   int x;
238   InnerWithRef in;
239   void foo() const;
240 };
241
242 void 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 }