1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=basic -verify -Wno-null-dereference %s
2 // RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=range -verify -Wno-null-dereference %s
3 
4 void clang_analyzer_eval(bool);
5 
6 typedef typeof(sizeof(int)) size_t;
7 void malloc (size_t);
8 
9 void f1() {
10   int const &i = 3;
11   int b = i;
12 
13   int *p = 0;
14 
15   if (b != 3)
16     *p = 1; // no-warning
17 }
18 
19 char* ptr();
20 char& ref();
21 
22 // These next two tests just shouldn't crash.
23 char t1 () {
24   ref() = 'c';
25   return '0';
26 }
27 
28 // just a sanity test, the same behavior as t1()
29 char t2 () {
30   *ptr() = 'c';
31   return '0';
32 }
33 
34 // Each of the tests below is repeated with pointers as well as references.
35 // This is mostly a sanity check, but then again, both should work!
36 char t3 () {
37   char& r = ref();
38   r = 'c'; // no-warning
39   if (r) return r;
40   return *(char*)0; // no-warning
41 }
42 
43 char t4 () {
44   char* p = ptr();
45   *p = 'c'; // no-warning
46   if (*p) return *p;
47   return *(char*)0; // no-warning
48 }
49 
50 char t5 (char& r) {
51   r = 'c'; // no-warning
52   if (r) return r;
53   return *(char*)0; // no-warning
54 }
55 
56 char t6 (char* p) {
57   *p = 'c'; // no-warning
58   if (*p) return *p;
59   return *(char*)0; // no-warning
60 }
61 
62 
63 // PR13440 / <rdar://problem/11977113>
64 // Test that the array-to-pointer decay works for array references as well.
65 // More generally, when we want an lvalue for a reference field, we still need
66 // to do one level of load.
67 namespace PR13440 {
68   typedef int T[1];
69   struct S {
70     T &x;
71 
72     int *m() { return x; }
73   };
74 
75   struct S2 {
76     int (&x)[1];
77 
78     int *m() { return x; }
79   };
80 
81   void test() {
82     int a[1];
83     S s = { a };
84     S2 s2 = { a };
85 
86     if (s.x != a) return;
87     if (s2.x != a) return;
88 
89     a[0] = 42;
90     clang_analyzer_eval(s.x[0] == 42); // expected-warning{{TRUE}}
91     clang_analyzer_eval(s2.x[0] == 42); // expected-warning{{TRUE}}
92   }
93 }
94 
95 void testNullReference() {
96   int *x = 0;
97   int &y = *x; // expected-warning{{Dereference of null pointer}}
98   y = 5;
99 }
100 
101 void testRetroactiveNullReference(int *x) {
102   // According to the C++ standard, there is no such thing as a
103   // "null reference". So the 'if' statement ought to be dead code.
104   // However, Clang (and other compilers) don't actually check that a pointer
105   // value is non-null in the implementation of references, so it is possible
106   // to produce a supposed "null reference" at runtime. The analyzer shoeuld
107   // still warn when it can prove such errors.
108   int &y = *x;
109   if (x != 0)
110     return;
111   y = 5; // expected-warning{{Dereference of null pointer}}
112 }
113 
114 void testReferenceAddress(int &x) {
115   clang_analyzer_eval(&x != 0); // expected-warning{{TRUE}}
116   clang_analyzer_eval(&ref() != 0); // expected-warning{{TRUE}}
117 
118   struct S { int &x; };
119 
120   extern S *getS();
121   clang_analyzer_eval(&getS()->x != 0); // expected-warning{{TRUE}}
122 }
123 
124 
125 // ------------------------------------
126 // False negatives
127 // ------------------------------------
128 
129 namespace rdar11212286 {
130   class B{};
131 
132   B test() {
133     B *x = 0;
134     return *x; // should warn here!
135   }
136 
137   B &testRef() {
138     B *x = 0;
139     return *x; // should warn here!
140   }
141 }
142 
143 void testReferenceFieldAddress() {
144   struct S { int &x; };
145 
146   extern S getS();
147   clang_analyzer_eval(&getS().x != 0); // expected-warning{{UNKNOWN}}
148 }
149