xref: /aosp_15_r20/external/clang/test/Analysis/call-invalidation.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 void usePointer(int * const *);
6*67e74705SXin Li void useReference(int * const &);
7*67e74705SXin Li 
testPointer()8*67e74705SXin Li void testPointer() {
9*67e74705SXin Li   int x;
10*67e74705SXin Li   int *p;
11*67e74705SXin Li 
12*67e74705SXin Li   p = &x;
13*67e74705SXin Li   x = 42;
14*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
15*67e74705SXin Li   usePointer(&p);
16*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
17*67e74705SXin Li 
18*67e74705SXin Li   p = &x;
19*67e74705SXin Li   x = 42;
20*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
21*67e74705SXin Li   useReference(p);
22*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
23*67e74705SXin Li 
24*67e74705SXin Li   int * const cp1 = &x;
25*67e74705SXin Li   x = 42;
26*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
27*67e74705SXin Li   usePointer(&cp1);
28*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
29*67e74705SXin Li 
30*67e74705SXin Li   int * const cp2 = &x;
31*67e74705SXin Li   x = 42;
32*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
33*67e74705SXin Li   useReference(cp2);
34*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
35*67e74705SXin Li }
36*67e74705SXin Li 
37*67e74705SXin Li 
38*67e74705SXin Li struct Wrapper {
39*67e74705SXin Li   int *ptr;
40*67e74705SXin Li };
41*67e74705SXin Li 
42*67e74705SXin Li void useStruct(Wrapper &w);
43*67e74705SXin Li void useConstStruct(const Wrapper &w);
44*67e74705SXin Li 
testPointerStruct()45*67e74705SXin Li void testPointerStruct() {
46*67e74705SXin Li   int x;
47*67e74705SXin Li   Wrapper w;
48*67e74705SXin Li 
49*67e74705SXin Li   w.ptr = &x;
50*67e74705SXin Li   x = 42;
51*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
52*67e74705SXin Li   useStruct(w);
53*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
54*67e74705SXin Li 
55*67e74705SXin Li   w.ptr = &x;
56*67e74705SXin Li   x = 42;
57*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
58*67e74705SXin Li   useConstStruct(w);
59*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
60*67e74705SXin Li }
61*67e74705SXin Li 
62*67e74705SXin Li 
63*67e74705SXin Li struct RefWrapper {
64*67e74705SXin Li   int &ref;
65*67e74705SXin Li };
66*67e74705SXin Li 
67*67e74705SXin Li void useStruct(RefWrapper &w);
68*67e74705SXin Li void useConstStruct(const RefWrapper &w);
69*67e74705SXin Li 
testReferenceStruct()70*67e74705SXin Li void testReferenceStruct() {
71*67e74705SXin Li   int x;
72*67e74705SXin Li   RefWrapper w = { x };
73*67e74705SXin Li 
74*67e74705SXin Li   x = 42;
75*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
76*67e74705SXin Li   useStruct(w);
77*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
78*67e74705SXin Li }
79*67e74705SXin Li 
80*67e74705SXin Li // FIXME: This test is split into two functions because region invalidation
81*67e74705SXin Li // does not preserve reference bindings. <rdar://problem/13320347>
testConstReferenceStruct()82*67e74705SXin Li void testConstReferenceStruct() {
83*67e74705SXin Li   int x;
84*67e74705SXin Li   RefWrapper w = { x };
85*67e74705SXin Li 
86*67e74705SXin Li   x = 42;
87*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
88*67e74705SXin Li   useConstStruct(w);
89*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
90*67e74705SXin Li }
91*67e74705SXin Li 
92*67e74705SXin Li 
93*67e74705SXin Li void usePointerPure(int * const *) __attribute__((pure));
94*67e74705SXin Li void usePointerConst(int * const *) __attribute__((const));
95*67e74705SXin Li 
testPureConst()96*67e74705SXin Li void testPureConst() {
97*67e74705SXin Li   extern int global;
98*67e74705SXin Li   int x;
99*67e74705SXin Li   int *p;
100*67e74705SXin Li 
101*67e74705SXin Li   p = &x;
102*67e74705SXin Li   x = 42;
103*67e74705SXin Li   global = -5;
104*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
105*67e74705SXin Li   clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
106*67e74705SXin Li 
107*67e74705SXin Li   usePointerPure(&p);
108*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
109*67e74705SXin Li   clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
110*67e74705SXin Li 
111*67e74705SXin Li   usePointerConst(&p);
112*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
113*67e74705SXin Li   clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
114*67e74705SXin Li 
115*67e74705SXin Li   usePointer(&p);
116*67e74705SXin Li   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
117*67e74705SXin Li   clang_analyzer_eval(global == -5); // expected-warning{{UNKNOWN}}
118*67e74705SXin Li }
119*67e74705SXin Li 
120*67e74705SXin Li 
121*67e74705SXin Li struct PlainStruct {
122*67e74705SXin Li   int x, y;
123*67e74705SXin Li   mutable int z;
124*67e74705SXin Li };
125*67e74705SXin Li 
126*67e74705SXin Li PlainStruct glob;
127*67e74705SXin Li 
128*67e74705SXin Li void useAnything(void *);
129*67e74705SXin Li void useAnythingConst(const void *);
130*67e74705SXin Li 
testInvalidationThroughBaseRegionPointer()131*67e74705SXin Li void testInvalidationThroughBaseRegionPointer() {
132*67e74705SXin Li   PlainStruct s1;
133*67e74705SXin Li   s1.x = 1;
134*67e74705SXin Li   s1.z = 1;
135*67e74705SXin Li   clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}
136*67e74705SXin Li   clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}
137*67e74705SXin Li   // Not only passing a structure pointer through const pointer parameter,
138*67e74705SXin Li   // but also passing a field pointer through const pointer parameter
139*67e74705SXin Li   // should preserve the contents of the structure.
140*67e74705SXin Li   useAnythingConst(&(s1.y));
141*67e74705SXin Li   clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}
142*67e74705SXin Li   // FIXME: Should say "UNKNOWN", because it is not uncommon to
143*67e74705SXin Li   // modify a mutable member variable through const pointer.
144*67e74705SXin Li   clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}
145*67e74705SXin Li   useAnything(&(s1.y));
146*67e74705SXin Li   clang_analyzer_eval(s1.x == 1); // expected-warning{{UNKNOWN}}
147*67e74705SXin Li }
148*67e74705SXin Li 
149*67e74705SXin Li 
150*67e74705SXin Li void useFirstConstSecondNonConst(const void *x, void *y);
151*67e74705SXin Li void useFirstNonConstSecondConst(void *x, const void *y);
152*67e74705SXin Li 
testMixedConstNonConstCalls()153*67e74705SXin Li void testMixedConstNonConstCalls() {
154*67e74705SXin Li   PlainStruct s2;
155*67e74705SXin Li   s2.x = 1;
156*67e74705SXin Li   useFirstConstSecondNonConst(&(s2.x), &(s2.y));
157*67e74705SXin Li   clang_analyzer_eval(s2.x == 1); // expected-warning{{UNKNOWN}}
158*67e74705SXin Li   s2.x = 1;
159*67e74705SXin Li   useFirstNonConstSecondConst(&(s2.x), &(s2.y));
160*67e74705SXin Li   clang_analyzer_eval(s2.x == 1); // expected-warning{{UNKNOWN}}
161*67e74705SXin Li   s2.y = 1;
162*67e74705SXin Li   useFirstConstSecondNonConst(&(s2.x), &(s2.y));
163*67e74705SXin Li   clang_analyzer_eval(s2.y == 1); // expected-warning{{UNKNOWN}}
164*67e74705SXin Li   s2.y = 1;
165*67e74705SXin Li   useFirstNonConstSecondConst(&(s2.x), &(s2.y));
166*67e74705SXin Li   clang_analyzer_eval(s2.y == 1); // expected-warning{{UNKNOWN}}
167*67e74705SXin Li }
168