1 // RUN: %clang_analyze_cc1 -x c++ -std=c++14 -analyzer-checker=core -analyzer-output=text -verify %s
2 
initializer1(int & p,int x)3 int initializer1(int &p, int x) {
4   if (x) { // expected-note{{'x' is 0}}
5            // expected-note@-1{{Taking false branch}}
6     p = 1;
7     return 0;
8   } else {
9     return 1; // expected-note {{Returning without writing to 'p'}}
10   }
11 }
12 
param_not_initialized_by_func()13 int param_not_initialized_by_func() {
14   int outP;                        // expected-note {{'outP' declared without an initial value}}
15   int out = initializer1(outP, 0); // expected-note{{Calling 'initializer1'}}
16                                 // expected-note@-1{{Returning from 'initializer1'}}
17   return outP;                     // expected-note{{Undefined or garbage value returned to caller}}
18                                 // expected-warning@-1{{Undefined or garbage value returned to caller}}
19 }
20 
21 struct S {
initializeS22   int initialize(int *p, int param) {
23     if (param) { // expected-note{{'param' is 0}}
24                  // expected-note@-1{{Taking false branch}}
25       *p = 1;
26       return 1;
27     }
28     return 0; // expected-note{{Returning without writing to '*p'}}
29   }
30 };
31 
use(S * s)32 int use(S *s) {
33   int p;                //expected-note{{'p' declared without an initial value}}
34   s->initialize(&p, 0); //expected-note{{Calling 'S::initialize'}}
35                         //expected-note@-1{{Returning from 'S::initialize'}}
36   return p;             // expected-warning{{Undefined or garbage value returned to caller}}
37                         // expected-note@-1{{Undefined or garbage value returned to caller}}
38 }
39 
initializer2(const int & p)40 int initializer2(const int &p) {
41   return 0;
42 }
43 
no_msg_const_ref()44 int no_msg_const_ref() {
45   int p; //expected-note{{'p' declared without an initial value}}
46   initializer2(p);
47   return p; // expected-warning{{Undefined or garbage value returned to caller}}
48             // expected-note@-1{{Undefined or garbage value returned to caller}}
49 }
50 
nested()51 void nested() {}
init_in_nested_func(int ** x)52 void init_in_nested_func(int **x) {
53   *x = 0; // expected-note{{Null pointer value stored to 'y'}}
54   nested();
55 } // no-note
56 
call_init_nested()57 int call_init_nested() {
58   int x = 0;
59   int *y = &x;
60   init_in_nested_func(&y); // expected-note{{Calling 'init_in_nested_func'}}
61                            // expected-note@-1{{Returning from 'init_in_nested_func'}}
62   return *y;               //expected-warning{{Dereference of null pointer (loaded from variable 'y')}}
63                            //expected-note@-1{{Dereference of null pointer (loaded from variable 'y')}}
64 }
65 
66 struct A {
67   int x;
68   int y;
69 };
70 
partial_init_by_reference(A & a)71 void partial_init_by_reference(A &a) {
72   a.x = 0;
73 } // expected-note {{Returning without writing to 'a.y'}}
74 
use_partial_init_by_reference()75 int use_partial_init_by_reference() {
76   A a;
77   partial_init_by_reference(a); // expected-note{{Calling 'partial_init_by_reference'}}
78                                 // expected-note@-1{{Returning from 'partial_init_by_reference'}}
79   return a.y;                   // expected-warning{{Undefined or garbage value returned to caller}}
80                                 // expected-note@-1{{Undefined or garbage value returned to caller}}
81 }
82 
83 struct B : A {
84 };
85 
partially_init_inherited_struct(B * b)86 void partially_init_inherited_struct(B *b) {
87   b->x = 0;
88 } // expected-note{{Returning without writing to 'b->y'}}
89 
use_partially_init_inherited_struct()90 int use_partially_init_inherited_struct() {
91   B b;
92   partially_init_inherited_struct(&b); // expected-note{{Calling 'partially_init_inherited_struct'}}
93                                        // expected-note@-1{{Returning from 'partially_init_inherited_struct'}}
94   return b.y;                          // expected-warning{{Undefined or garbage value returned to caller}}
95                                        // expected-note@-1{{Undefined or garbage value returned to caller}}
96 }
97 
98 struct C {
99   int x;
100   int y;
CC101   C(int pX, int pY) : x(pX) {} // expected-note{{Returning without writing to 'this->y'}}
102 
CC103   C(int pX, int pY, bool Flag) {
104     x = pX;
105     if (Flag) // expected-note{{Assuming 'Flag' is true}}
106               // expected-note@-1{{Taking true branch}}
107       return; // expected-note{{Returning without writing to 'this->y'}}
108     y = pY;
109   }
110 };
111 
use_constructor()112 int use_constructor() {
113   C c(0, 0); // expected-note{{Calling constructor for 'C'}}
114              // expected-note@-1{{Returning from constructor for 'C'}}
115   return c.y; // expected-note{{Undefined or garbage value returned to caller}}
116               // expected-warning@-1{{Undefined or garbage value returned to caller}}
117 }
118 
119 int coin();
120 
use_other_constructor()121 int use_other_constructor() {
122   C c(0, 0, coin()); // expected-note{{Calling constructor for 'C'}}
123                      // expected-note@-1{{Returning from constructor for 'C'}}
124   return c.y; // expected-note{{Undefined or garbage value returned to caller}}
125               // expected-warning@-1{{Undefined or garbage value returned to caller}}
126 }
127 
128 struct D {
129   void initialize(int *);
130 };
131 
initialize(int * p)132 void D::initialize(int *p) {
133 
134 } // expected-note{{Returning without writing to '*p'}}
135 
use_d_initializer(D * d)136 int use_d_initializer(D* d) {
137   int p; // expected-note {{'p' declared without an initial value}}
138   d->initialize(&p); // expected-note{{Calling 'D::initialize'}}
139                      // expected-note@-1{{Returning from 'D::initialize'}}
140   return p;                     // expected-note{{Undefined or garbage value returned to caller}}
141                                 // expected-warning@-1{{Undefined or garbage value returned to caller}}
142 }
143 
144 struct S2 {
145   int x;
146 };
147 
pointerreference(S2 * & s)148 int pointerreference(S2* &s) {
149   if (coin()) // expected-note{{Assuming the condition is true}}
150               // expected-note@-1{{Taking true branch}}
151     return 1; // expected-note{{Returning without writing to 's->x'}}
152 
153   s->x = 0;
154   return 0;
155 }
156 
usepointerreference()157 int usepointerreference() {
158   S2 s;
159   S2* p = &s;
160   pointerreference(p); //expected-note{{Calling 'pointerreference'}}
161                          //expected-note@-1{{Returning from 'pointerreference'}}
162   return s.x; // expected-warning{{Undefined or garbage value returned to caller}}
163               // expected-note@-1{{Undefined or garbage value returned to caller}}
164 }
165 
has_no_argument_and_returns_null(void)166 void *has_no_argument_and_returns_null(void) {
167   return 0;
168 }
169 
rdar40335545()170 void rdar40335545() {
171     int local; // expected-note{{}}
172     void (*takes_int_ptr_argument)(int *) = (void (*)(int*))has_no_argument_and_returns_null;
173 
174     takes_int_ptr_argument(&local); // no-crash
175 
176     int useLocal = local; //expected-warning{{}}
177                           //expected-note@-1{{}}
178     (void)useLocal;
179 }
180 
181 ////////
182 
183 struct HasRef {
184   int &a;
HasRefHasRef185   HasRef(int &a) : a(a) {}
186 };
187 
188 
maybeInitialize(const HasRef && pA)189 void maybeInitialize(const HasRef &&pA) {
190   if (coin()) // expected-note{{Assuming the condition is false}}
191               // expected-note@-1{{Taking false branch}}
192     pA.a = 120;
193 } // expected-note{{Returning without writing to 'pA.a'}}
194 
useMaybeInitializerWritingIntoField()195 int useMaybeInitializerWritingIntoField() {
196   int z; // expected-note{{'z' declared without an initial value}}
197   maybeInitialize(HasRef(z)); // expected-note{{Calling constructor for 'HasRef'}}
198                               // expected-note@-1{{Returning from constructor for 'HasRef'}}
199                               // expected-note@-2{{Calling 'maybeInitialize'}}
200                               // expected-note@-3{{Returning from 'maybeInitialize'}}
201   return z; // expected-warning{{Undefined or garbage value returned to caller}}
202             // expected-note@-1{{Undefined or garbage value returned to caller}}
203 }
204 
205 ////////
206 
207 struct HasRefToItself {
208   HasRefToItself &Ref; // no infinite loop
209   int &z;
HasRefToItselfHasRefToItself210   HasRefToItself(int &z) : Ref(*this), z(z) {}
211 };
212 
maybeInitialize(const HasRefToItself && pA)213 void maybeInitialize(const HasRefToItself &&pA) {
214   if (coin()) // expected-note{{Assuming the condition is false}}
215               // expected-note@-1{{Taking false branch}}
216     pA.z = 120;
217 } // expected-note{{Returning without writing to 'pA.Ref.z'}}
218 
useMaybeInitializerWritingIntoFieldWithRefToItself()219 int useMaybeInitializerWritingIntoFieldWithRefToItself() {
220   int z; // expected-note{{'z' declared without an initial value}}
221   maybeInitialize(HasRefToItself(z)); // expected-note{{Calling constructor for 'HasRefToItself'}}
222                               // expected-note@-1{{Returning from constructor for 'HasRefToItself'}}
223                               // expected-note@-2{{Calling 'maybeInitialize'}}
224                               // expected-note@-3{{Returning from 'maybeInitialize'}}
225   return z; // expected-warning{{Undefined or garbage value returned to caller}}
226             // expected-note@-1{{Undefined or garbage value returned to caller}}
227 }
228 
229 ////
230 
maybeInitialize(const HasRef * pA)231 void maybeInitialize(const HasRef *pA) {
232   if (coin()) // expected-note{{Assuming the condition is false}}
233               // expected-note@-1{{Taking false branch}}
234     pA->a = 120;
235 } // expected-note{{Returning without writing to 'pA->a'}}
236 
useMaybeInitializerStructByPointer()237 int useMaybeInitializerStructByPointer() {
238   int z; // expected-note{{'z' declared without an initial value}}
239   HasRef wrapper(z); // expected-note{{Calling constructor for 'HasRef'}}
240                      // expected-note@-1{{Returning from constructor for 'HasRef'}}
241   maybeInitialize(&wrapper); // expected-note{{Calling 'maybeInitialize'}}
242                              // expected-note@-1{{Returning from 'maybeInitialize'}}
243   return z; // expected-warning{{Undefined or garbage value returned to caller}}
244             // expected-note@-1{{Undefined or garbage value returned to caller}}
245 }
246 
247 ////////
248 
249 struct HasParentWithRef : public HasRef {
HasParentWithRefHasParentWithRef250   HasParentWithRef(int &a) : HasRef(a) {} // expected-note{{Calling constructor for 'HasRef'}}
251                                           // expected-note@-1{{Returning from constructor for 'HasRef'}}
252 };
253 
maybeInitializeWithParent(const HasParentWithRef & pA)254 void maybeInitializeWithParent(const HasParentWithRef &pA) {
255   if (coin()) // expected-note{{Assuming the condition is false}}
256               // expected-note@-1{{Taking false branch}}
257     pA.a = 120;
258 } // expected-note{{Returning without writing to 'pA.a'}}
259 
useMaybeInitializerWritingIntoParentField()260 int useMaybeInitializerWritingIntoParentField() {
261   int z; // expected-note{{'z' declared without an initial value}}
262   maybeInitializeWithParent(HasParentWithRef(z)); // expected-note{{Calling constructor for 'HasParentWithRef'}}
263                               // expected-note@-1{{Returning from constructor for 'HasParentWithRef'}}
264                               // expected-note@-2{{Calling 'maybeInitializeWithParent'}}
265                               // expected-note@-3{{Returning from 'maybeInitializeWithParent'}}
266   return z; // expected-warning{{Undefined or garbage value returned to caller}}
267             // expected-note@-1{{Undefined or garbage value returned to caller}}
268 }
269 
270 ////////
271 
272 struct HasIndirectRef {
273   HasRef &Ref;
HasIndirectRefHasIndirectRef274   HasIndirectRef(HasRef &Ref) : Ref(Ref) {}
275 };
276 
maybeInitializeIndirectly(const HasIndirectRef & pA)277 void maybeInitializeIndirectly(const HasIndirectRef &pA) {
278   if (coin()) // expected-note{{Assuming the condition is false}}
279               // expected-note@-1{{Taking false branch}}
280     pA.Ref.a = 120;
281 } // expected-note{{Returning without writing to 'pA.Ref.a'}}
282 
useMaybeInitializeIndirectly()283 int useMaybeInitializeIndirectly() {
284   int z; // expected-note{{'z' declared without an initial value}}
285   HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}}
286                // expected-note@-1{{Returning from constructor for 'HasRef'}}
287   maybeInitializeIndirectly(HasIndirectRef(r)); // expected-note{{Calling 'maybeInitializeIndirectly'}}
288                                                 // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}}
289   return z; // expected-warning{{Undefined or garbage value returned to caller}}
290             // expected-note@-1{{Undefined or garbage value returned to caller}}
291 }
292 
293 ////////
294 
295 struct HasIndirectRefByValue {
296   HasRef Ref;
HasIndirectRefByValueHasIndirectRefByValue297   HasIndirectRefByValue(HasRef Ref) : Ref(Ref) {}
298 };
299 
maybeInitializeIndirectly(const HasIndirectRefByValue & pA)300 void maybeInitializeIndirectly(const HasIndirectRefByValue &pA) {
301   if (coin()) // expected-note{{Assuming the condition is false}}
302               // expected-note@-1{{Taking false branch}}
303     pA.Ref.a = 120;
304 } // expected-note{{Returning without writing to 'pA.Ref.a'}}
305 
useMaybeInitializeIndirectlyIndirectRefByValue()306 int useMaybeInitializeIndirectlyIndirectRefByValue() {
307   int z; // expected-note{{'z' declared without an initial value}}
308   HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}}
309                // expected-note@-1{{Returning from constructor for 'HasRef'}}
310   maybeInitializeIndirectly(HasIndirectRefByValue(r)); // expected-note{{Calling 'maybeInitializeIndirectly'}}
311                                                 // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}}
312   return z; // expected-warning{{Undefined or garbage value returned to caller}}
313             // expected-note@-1{{Undefined or garbage value returned to caller}}
314 }
315 
316 ////////
317 
318 struct HasIndirectPointerRef {
319   HasRef *Ref;
HasIndirectPointerRefHasIndirectPointerRef320   HasIndirectPointerRef(HasRef *Ref) : Ref(Ref) {}
321 };
322 
maybeInitializeIndirectly(const HasIndirectPointerRef & pA)323 void maybeInitializeIndirectly(const HasIndirectPointerRef &pA) {
324   if (coin()) // expected-note{{Assuming the condition is false}}
325               // expected-note@-1{{Taking false branch}}
326     pA.Ref->a = 120;
327 } // expected-note{{Returning without writing to 'pA.Ref->a'}}
328 
useMaybeInitializeIndirectlyWithPointer()329 int useMaybeInitializeIndirectlyWithPointer() {
330   int z; // expected-note{{'z' declared without an initial value}}
331   HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}}
332                // expected-note@-1{{Returning from constructor for 'HasRef'}}
333   maybeInitializeIndirectly(HasIndirectPointerRef(&r)); // expected-note{{Calling 'maybeInitializeIndirectly'}}
334                                                 // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}}
335   return z; // expected-warning{{Undefined or garbage value returned to caller}}
336             // expected-note@-1{{Undefined or garbage value returned to caller}}
337 }
338 
339 ////////
340 
341 struct HasFieldA {
342   int x;
343 };
344 
345 struct HasFieldB {
346   int x;
347 };
348 
maybeInitializeHasField(HasFieldA * b)349 void maybeInitializeHasField(HasFieldA *b) {
350   if (coin()) // expected-note{{Assuming the condition is false}}
351               // expected-note@-1{{Taking false branch}}
352     ((HasFieldB*)b)->x = 120;
353 }
354 
forceElementRegionApperence()355 int forceElementRegionApperence() {
356   HasFieldA a;
357   maybeInitializeHasField(&a); // expected-note{{Calling 'maybeInitializeHasField'}}
358                                // expected-note@-1{{Returning from 'maybeInitializeHasField'}}
359   return ((HasFieldB*)&a)->x; // expected-warning{{Undefined or garbage value returned to caller}}
360                               // expected-note@-1{{Undefined or garbage value returned to caller}}
361 }
362 
363 ////////
364 
365 struct HasForgottenField {
366   int x;
HasForgottenFieldHasForgottenField367   HasForgottenField() {} // expected-note{{Returning without writing to 'this->x'}}
368 };
369 
370 // Test that tracking across exclamation mark works.
tracksThroughExclamationMark()371 bool tracksThroughExclamationMark() {
372   HasForgottenField a; // expected-note{{Calling default constructor for 'HasForgottenField'}}
373                        // expected-note@-1{{Returning from default constructor for 'HasForgottenField'}}
374   return !a.x; // expected-warning{{Undefined or garbage value returned to caller}}
375                // expected-note@-1{{Undefined or garbage value returned to caller}}
376 }
377