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