• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify -analyzer-config eagerly-assume=false %s
2 
3 void clang_analyzer_eval(bool);
4 
5 struct A {
6   int x;
7   void foo() const;
8   void bar();
9 
testImplicitThisSyntaxA10   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   }
17 };
18 
19 struct B {
20   mutable int mut;
21   void foo() const;
22 };
23 
24 struct C {
25   int *p;
26   void foo() const;
27 };
28 
29 struct MutBase {
30   mutable int b_mut;
31 };
32 
33 struct MutDerived : MutBase {
34   void foo() const;
35 };
36 
37 struct PBase {
38   int *p;
39 };
40 
41 struct PDerived : PBase {
42   void foo() const;
43 };
44 
45 struct Inner {
46   int x;
47   int *p;
48   void bar() const;
49 };
50 
51 struct Outer {
52   int x;
53   Inner in;
54   void foo() const;
55 };
56 
checkThatConstMethodWithoutDefinitionDoesNotInvalidateObject()57 void 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 
checkThatConstMethodDoesInvalidateMutableFields()67 void checkThatConstMethodDoesInvalidateMutableFields() {
68   B t;
69   t.mut = 4;
70   t.foo();
71   clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}}
72 }
73 
checkThatConstMethodDoesInvalidatePointedAtMemory()74 void 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 
checkThatConstMethodDoesInvalidateInheritedMutableFields()83 void checkThatConstMethodDoesInvalidateInheritedMutableFields() {
84   MutDerived t;
85   t.b_mut = 4;
86   t.foo();
87   clang_analyzer_eval(t.b_mut); // expected-warning{{UNKNOWN}}
88 }
89 
checkThatConstMethodDoesInvalidateInheritedPointedAtMemory()90 void 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 
checkThatConstMethodDoesInvalidateContainedPointedAtMemory()99 void 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 
checkThatContainedConstMethodDoesNotInvalidateObjects()110 void 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 
checkPointerTypedThisExpression(A * a)119 void 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 
checkReferenceTypedThisExpression(A & a)127 void 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 
135 // --- Versions of the above tests where the const method is inherited --- //
136 
137 struct B1 {
138   void foo() const;
139 };
140 
141 struct D1 : public B1 {
142   int x;
143 };
144 
145 struct D2 : public B1 {
146   mutable int mut;
147 };
148 
149 struct D3 : public B1 {
150   int *p;
151 };
152 
153 struct DInner : public B1 {
154   int x;
155   int *p;
156 };
157 
158 struct DOuter : public B1 {
159   int x;
160   DInner in;
161 };
162 
checkThatInheritedConstMethodDoesNotInvalidateObject()163 void checkThatInheritedConstMethodDoesNotInvalidateObject() {
164   D1 t;
165   t.x = 1;
166   t.foo();
167   clang_analyzer_eval(t.x == 1); // expected-warning{{TRUE}}
168 }
169 
checkThatInheritedConstMethodDoesInvalidateMutableFields()170 void checkThatInheritedConstMethodDoesInvalidateMutableFields() {
171   D2 t;
172   t.mut = 1;
173   t.foo();
174   clang_analyzer_eval(t.mut); // expected-warning{{UNKNOWN}}
175 }
176 
checkThatInheritedConstMethodDoesInvalidatePointedAtMemory()177 void 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 
checkThatInheritedConstMethodDoesInvalidateContainedPointedAtMemory()186 void 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 
checkThatInheritedContainedConstMethodDoesNotInvalidateObjects()199 void 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 
210 struct s1 {
211     void g(const int *i) const;
212 };
213 
214 struct s2 {
fs2215     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 
PR21606()226 void PR21606()
227 {
228     s2().f(0);
229 }
230 
231 // --- PR25392 --- //
232 
233 struct HasConstMemberFunction {
234 public:
235   void constMemberFunction() const;
236 };
237 
hasNoReturn()238 HasConstMemberFunction hasNoReturn() { } // expected-warning {{non-void function does not return a value}}
239 
testUnknownWithConstMemberFunction()240 void testUnknownWithConstMemberFunction() {
241   hasNoReturn().constMemberFunction();
242 }
243 
testNonRegionLocWithConstMemberFunction()244 void testNonRegionLocWithConstMemberFunction() {
245   (*((HasConstMemberFunction *)(&&label))).constMemberFunction();
246 
247   label: return;
248 }
249 
250 // 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.
254 struct Outer2;
255 
256 struct InnerWithRef {
257   Outer2 *ref;
258 };
259 
260 struct Outer2 {
261   int x;
262   InnerWithRef in;
263   void foo() const;
264 };
265 
checkThatConstMethodCallDoesInvalidateObjectForCircularReferences()266 void 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 }
274