1 // RUN: %clang_analyze_cc1 -x c++ -std=c++14 -analyzer-checker=core -analyzer-output=text -verify %s 2 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 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 { 22 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 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 40 int initializer2(const int &p) { 41 return 0; 42 } 43 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 51 void nested() {} 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 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 71 void partial_init_by_reference(A &a) { 72 a.x = 0; 73 } // expected-note {{Returning without writing to 'a.y'}} 74 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 86 void partially_init_inherited_struct(B *b) { 87 b->x = 0; 88 } // expected-note{{Returning without writing to 'b->y'}} 89 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; 101 C(int pX, int pY) : x(pX) {} // expected-note{{Returning without writing to 'this->y'}} 102 103 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 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 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 132 void D::initialize(int *p) { 133 134 } // expected-note{{Returning without writing to '*p'}} 135 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 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 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 166 void *has_no_argument_and_returns_null(void) { 167 return 0; 168 } 169 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; 185 HasRef(int &a) : a(a) {} 186 }; 187 188 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 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; 210 HasRefToItself(int &z) : Ref(*this), z(z) {} 211 }; 212 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 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 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 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 { 250 HasParentWithRef(int &a) : HasRef(a) {} // expected-note{{Calling constructor for 'HasRef'}} 251 // expected-note@-1{{Returning from constructor for 'HasRef'}} 252 }; 253 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 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; 274 HasIndirectRef(HasRef &Ref) : Ref(Ref) {} 275 }; 276 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 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; 297 HasIndirectRefByValue(HasRef Ref) : Ref(Ref) {} 298 }; 299 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 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; 320 HasIndirectPointerRef(HasRef *Ref) : Ref(Ref) {} 321 }; 322 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 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 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 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; 367 HasForgottenField() {} // expected-note{{Returning without writing to 'this->x'}} 368 }; 369 370 // Test that tracking across exclamation mark works. 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