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