Clang Project

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