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