xref: /minix3/external/bsd/llvm/dist/clang/test/Analysis/reference.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=range -verify -Wno-null-dereference -Wno-tautological-undefined-compare %s
2f4a2713aSLionel Sambuc 
3f4a2713aSLionel Sambuc void clang_analyzer_eval(bool);
4f4a2713aSLionel Sambuc 
5f4a2713aSLionel Sambuc typedef typeof(sizeof(int)) size_t;
6f4a2713aSLionel Sambuc void malloc (size_t);
7f4a2713aSLionel Sambuc 
f1()8f4a2713aSLionel Sambuc void f1() {
9f4a2713aSLionel Sambuc   int const &i = 3;
10f4a2713aSLionel Sambuc   int b = i;
11f4a2713aSLionel Sambuc 
12f4a2713aSLionel Sambuc   int *p = 0;
13f4a2713aSLionel Sambuc 
14f4a2713aSLionel Sambuc   if (b != 3)
15f4a2713aSLionel Sambuc     *p = 1; // no-warning
16f4a2713aSLionel Sambuc }
17f4a2713aSLionel Sambuc 
18f4a2713aSLionel Sambuc char* ptr();
19f4a2713aSLionel Sambuc char& ref();
20f4a2713aSLionel Sambuc 
21f4a2713aSLionel Sambuc // These next two tests just shouldn't crash.
t1()22f4a2713aSLionel Sambuc char t1 () {
23f4a2713aSLionel Sambuc   ref() = 'c';
24f4a2713aSLionel Sambuc   return '0';
25f4a2713aSLionel Sambuc }
26f4a2713aSLionel Sambuc 
27f4a2713aSLionel Sambuc // just a sanity test, the same behavior as t1()
t2()28f4a2713aSLionel Sambuc char t2 () {
29f4a2713aSLionel Sambuc   *ptr() = 'c';
30f4a2713aSLionel Sambuc   return '0';
31f4a2713aSLionel Sambuc }
32f4a2713aSLionel Sambuc 
33f4a2713aSLionel Sambuc // Each of the tests below is repeated with pointers as well as references.
34f4a2713aSLionel Sambuc // This is mostly a sanity check, but then again, both should work!
t3()35f4a2713aSLionel Sambuc char t3 () {
36f4a2713aSLionel Sambuc   char& r = ref();
37f4a2713aSLionel Sambuc   r = 'c'; // no-warning
38f4a2713aSLionel Sambuc   if (r) return r;
39f4a2713aSLionel Sambuc   return *(char*)0; // no-warning
40f4a2713aSLionel Sambuc }
41f4a2713aSLionel Sambuc 
t4()42f4a2713aSLionel Sambuc char t4 () {
43f4a2713aSLionel Sambuc   char* p = ptr();
44f4a2713aSLionel Sambuc   *p = 'c'; // no-warning
45f4a2713aSLionel Sambuc   if (*p) return *p;
46f4a2713aSLionel Sambuc   return *(char*)0; // no-warning
47f4a2713aSLionel Sambuc }
48f4a2713aSLionel Sambuc 
t5(char & r)49f4a2713aSLionel Sambuc char t5 (char& r) {
50f4a2713aSLionel Sambuc   r = 'c'; // no-warning
51f4a2713aSLionel Sambuc   if (r) return r;
52f4a2713aSLionel Sambuc   return *(char*)0; // no-warning
53f4a2713aSLionel Sambuc }
54f4a2713aSLionel Sambuc 
t6(char * p)55f4a2713aSLionel Sambuc char t6 (char* p) {
56f4a2713aSLionel Sambuc   *p = 'c'; // no-warning
57f4a2713aSLionel Sambuc   if (*p) return *p;
58f4a2713aSLionel Sambuc   return *(char*)0; // no-warning
59f4a2713aSLionel Sambuc }
60f4a2713aSLionel Sambuc 
61f4a2713aSLionel Sambuc 
62f4a2713aSLionel Sambuc // PR13440 / <rdar://problem/11977113>
63f4a2713aSLionel Sambuc // Test that the array-to-pointer decay works for array references as well.
64f4a2713aSLionel Sambuc // More generally, when we want an lvalue for a reference field, we still need
65f4a2713aSLionel Sambuc // to do one level of load.
66f4a2713aSLionel Sambuc namespace PR13440 {
67f4a2713aSLionel Sambuc   typedef int T[1];
68f4a2713aSLionel Sambuc   struct S {
69f4a2713aSLionel Sambuc     T &x;
70f4a2713aSLionel Sambuc 
mPR13440::S71f4a2713aSLionel Sambuc     int *m() { return x; }
72f4a2713aSLionel Sambuc   };
73f4a2713aSLionel Sambuc 
74f4a2713aSLionel Sambuc   struct S2 {
75f4a2713aSLionel Sambuc     int (&x)[1];
76f4a2713aSLionel Sambuc 
mPR13440::S277f4a2713aSLionel Sambuc     int *m() { return x; }
78f4a2713aSLionel Sambuc 
testArrayToPointerDecayWithNonTypedValueRegionPR13440::S279f4a2713aSLionel Sambuc     void testArrayToPointerDecayWithNonTypedValueRegion() {
80f4a2713aSLionel Sambuc       int *p = x;
81f4a2713aSLionel Sambuc       int *q = x;
82f4a2713aSLionel Sambuc       clang_analyzer_eval(p[0] == q[0]); // expected-warning{{TRUE}}
83f4a2713aSLionel Sambuc     }
84f4a2713aSLionel Sambuc 
85f4a2713aSLionel Sambuc   };
86f4a2713aSLionel Sambuc 
test()87f4a2713aSLionel Sambuc   void test() {
88f4a2713aSLionel Sambuc     int a[1];
89f4a2713aSLionel Sambuc     S s = { a };
90f4a2713aSLionel Sambuc     S2 s2 = { a };
91f4a2713aSLionel Sambuc 
92f4a2713aSLionel Sambuc     if (s.x != a) return;
93f4a2713aSLionel Sambuc     if (s2.x != a) return;
94f4a2713aSLionel Sambuc 
95f4a2713aSLionel Sambuc     a[0] = 42;
96f4a2713aSLionel Sambuc     clang_analyzer_eval(s.x[0] == 42); // expected-warning{{TRUE}}
97f4a2713aSLionel Sambuc     clang_analyzer_eval(s2.x[0] == 42); // expected-warning{{TRUE}}
98f4a2713aSLionel Sambuc   }
99f4a2713aSLionel Sambuc }
100f4a2713aSLionel Sambuc 
testNullReference()101f4a2713aSLionel Sambuc void testNullReference() {
102f4a2713aSLionel Sambuc   int *x = 0;
103f4a2713aSLionel Sambuc   int &y = *x; // expected-warning{{Dereference of null pointer}}
104f4a2713aSLionel Sambuc   y = 5;
105f4a2713aSLionel Sambuc }
106f4a2713aSLionel Sambuc 
testRetroactiveNullReference(int * x)107f4a2713aSLionel Sambuc void testRetroactiveNullReference(int *x) {
108f4a2713aSLionel Sambuc   // According to the C++ standard, there is no such thing as a
109f4a2713aSLionel Sambuc   // "null reference". So the 'if' statement ought to be dead code.
110f4a2713aSLionel Sambuc   // However, Clang (and other compilers) don't actually check that a pointer
111f4a2713aSLionel Sambuc   // value is non-null in the implementation of references, so it is possible
112f4a2713aSLionel Sambuc   // to produce a supposed "null reference" at runtime. The analyzer should
113f4a2713aSLionel Sambuc   // still warn when it can prove such errors.
114f4a2713aSLionel Sambuc   int &y = *x;
115f4a2713aSLionel Sambuc   if (x != 0)
116f4a2713aSLionel Sambuc     return;
117f4a2713aSLionel Sambuc   y = 5; // expected-warning{{Dereference of null pointer}}
118f4a2713aSLionel Sambuc }
119f4a2713aSLionel Sambuc 
testReferenceAddress(int & x)120f4a2713aSLionel Sambuc void testReferenceAddress(int &x) {
121f4a2713aSLionel Sambuc   clang_analyzer_eval(&x != 0); // expected-warning{{TRUE}}
122f4a2713aSLionel Sambuc   clang_analyzer_eval(&ref() != 0); // expected-warning{{TRUE}}
123f4a2713aSLionel Sambuc 
124f4a2713aSLionel Sambuc   struct S { int &x; };
125f4a2713aSLionel Sambuc 
126f4a2713aSLionel Sambuc   extern S getS();
127f4a2713aSLionel Sambuc   clang_analyzer_eval(&getS().x != 0); // expected-warning{{TRUE}}
128f4a2713aSLionel Sambuc 
129f4a2713aSLionel Sambuc   extern S *getSP();
130f4a2713aSLionel Sambuc   clang_analyzer_eval(&getSP()->x != 0); // expected-warning{{TRUE}}
131f4a2713aSLionel Sambuc }
132f4a2713aSLionel Sambuc 
133f4a2713aSLionel Sambuc 
testFunctionPointerReturn(void * opaque)134f4a2713aSLionel Sambuc void testFunctionPointerReturn(void *opaque) {
135f4a2713aSLionel Sambuc   typedef int &(*RefFn)();
136f4a2713aSLionel Sambuc 
137f4a2713aSLionel Sambuc   RefFn getRef = (RefFn)opaque;
138f4a2713aSLionel Sambuc 
139f4a2713aSLionel Sambuc   // Don't crash writing to or reading from this reference.
140f4a2713aSLionel Sambuc   int &x = getRef();
141f4a2713aSLionel Sambuc   x = 42;
142f4a2713aSLionel Sambuc   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
143f4a2713aSLionel Sambuc }
144f4a2713aSLionel Sambuc 
testReturnNullReference()145f4a2713aSLionel Sambuc int &testReturnNullReference() {
146f4a2713aSLionel Sambuc   int *x = 0;
147f4a2713aSLionel Sambuc   return *x; // expected-warning{{Returning null reference}}
148f4a2713aSLionel Sambuc }
149f4a2713aSLionel Sambuc 
refFromPointer()150f4a2713aSLionel Sambuc char &refFromPointer() {
151f4a2713aSLionel Sambuc   return *ptr();
152f4a2713aSLionel Sambuc }
153f4a2713aSLionel Sambuc 
testReturnReference()154f4a2713aSLionel Sambuc void testReturnReference() {
155f4a2713aSLionel Sambuc   clang_analyzer_eval(ptr() == 0); // expected-warning{{UNKNOWN}}
156f4a2713aSLionel Sambuc   clang_analyzer_eval(&refFromPointer() == 0); // expected-warning{{FALSE}}
157f4a2713aSLionel Sambuc }
158f4a2713aSLionel Sambuc 
intRefParam(int & r)159f4a2713aSLionel Sambuc void intRefParam(int &r) {
160f4a2713aSLionel Sambuc 	;
161f4a2713aSLionel Sambuc }
162f4a2713aSLionel Sambuc 
test(int * ptr)163f4a2713aSLionel Sambuc void test(int *ptr) {
164f4a2713aSLionel Sambuc 	clang_analyzer_eval(ptr == 0); // expected-warning{{UNKNOWN}}
165f4a2713aSLionel Sambuc 
166f4a2713aSLionel Sambuc 	extern void use(int &ref);
167f4a2713aSLionel Sambuc 	use(*ptr);
168f4a2713aSLionel Sambuc 
169f4a2713aSLionel Sambuc 	clang_analyzer_eval(ptr == 0); // expected-warning{{FALSE}}
170f4a2713aSLionel Sambuc }
171f4a2713aSLionel Sambuc 
testIntRefParam()172f4a2713aSLionel Sambuc void testIntRefParam() {
173f4a2713aSLionel Sambuc 	int i = 0;
174f4a2713aSLionel Sambuc 	intRefParam(i); // no-warning
175f4a2713aSLionel Sambuc }
176f4a2713aSLionel Sambuc 
refParam(int & byteIndex)177f4a2713aSLionel Sambuc int refParam(int &byteIndex) {
178f4a2713aSLionel Sambuc 	return byteIndex;
179f4a2713aSLionel Sambuc }
180f4a2713aSLionel Sambuc 
testRefParam(int * p)181f4a2713aSLionel Sambuc void testRefParam(int *p) {
182f4a2713aSLionel Sambuc 	if (p)
183f4a2713aSLionel Sambuc 		;
184f4a2713aSLionel Sambuc 	refParam(*p); // expected-warning {{Forming reference to null pointer}}
185f4a2713aSLionel Sambuc }
186f4a2713aSLionel Sambuc 
ptrRefParam(int * & byteIndex)187f4a2713aSLionel Sambuc int ptrRefParam(int *&byteIndex) {
188f4a2713aSLionel Sambuc 	return *byteIndex;  // expected-warning {{Dereference of null pointer}}
189f4a2713aSLionel Sambuc }
testRefParam2()190f4a2713aSLionel Sambuc void testRefParam2() {
191f4a2713aSLionel Sambuc 	int *p = 0;
192f4a2713aSLionel Sambuc 	int *&rp = p;
193f4a2713aSLionel Sambuc 	ptrRefParam(rp);
194f4a2713aSLionel Sambuc }
195f4a2713aSLionel Sambuc 
maybeNull()196f4a2713aSLionel Sambuc int *maybeNull() {
197f4a2713aSLionel Sambuc 	extern bool coin();
198f4a2713aSLionel Sambuc 	static int x;
199f4a2713aSLionel Sambuc 	return coin() ? &x : 0;
200f4a2713aSLionel Sambuc }
201f4a2713aSLionel Sambuc 
use(int & x)202f4a2713aSLionel Sambuc void use(int &x) {
203f4a2713aSLionel Sambuc 	x = 1; // no-warning
204f4a2713aSLionel Sambuc }
205f4a2713aSLionel Sambuc 
testSuppression()206f4a2713aSLionel Sambuc void testSuppression() {
207f4a2713aSLionel Sambuc 	use(*maybeNull());
208f4a2713aSLionel Sambuc }
209f4a2713aSLionel Sambuc 
210f4a2713aSLionel Sambuc namespace rdar11212286 {
211f4a2713aSLionel Sambuc   class B{};
212f4a2713aSLionel Sambuc 
test()213f4a2713aSLionel Sambuc   B test() {
214f4a2713aSLionel Sambuc     B *x = 0;
215f4a2713aSLionel Sambuc     return *x; // expected-warning {{Forming reference to null pointer}}
216f4a2713aSLionel Sambuc   }
217f4a2713aSLionel Sambuc 
testif(B * x)218f4a2713aSLionel Sambuc   B testif(B *x) {
219f4a2713aSLionel Sambuc     if (x)
220f4a2713aSLionel Sambuc       ;
221f4a2713aSLionel Sambuc     return *x; // expected-warning {{Forming reference to null pointer}}
222f4a2713aSLionel Sambuc   }
223f4a2713aSLionel Sambuc 
idc(B * x)224f4a2713aSLionel Sambuc   void idc(B *x) {
225f4a2713aSLionel Sambuc     if (x)
226f4a2713aSLionel Sambuc       ;
227f4a2713aSLionel Sambuc   }
228f4a2713aSLionel Sambuc 
testidc(B * x)229f4a2713aSLionel Sambuc   B testidc(B *x) {
230f4a2713aSLionel Sambuc     idc(x);
231f4a2713aSLionel Sambuc     return *x; // no-warning
232f4a2713aSLionel Sambuc   }
233f4a2713aSLionel Sambuc }
234f4a2713aSLionel Sambuc 
235f4a2713aSLionel Sambuc namespace PR15694 {
236f4a2713aSLionel Sambuc   class C {
237f4a2713aSLionel Sambuc     bool bit : 1;
bar(const T & obj)238f4a2713aSLionel Sambuc     template <class T> void bar(const T &obj) {}
foo()239f4a2713aSLionel Sambuc     void foo() {
240f4a2713aSLionel Sambuc       bar(bit); // don't crash
241f4a2713aSLionel Sambuc     }
242f4a2713aSLionel Sambuc   };
243f4a2713aSLionel Sambuc }
244