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