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{{Taking false branch}} 5 p = 1; 6 return 0; 7 } else { 8 return 1; // expected-note {{Returning without writing to 'p'}} 9 } 10 } 11 12 int 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 20 struct 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 30 int 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 38 int initializer2(const int &p) { 39 return 0; 40 } 41 42 int 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 49 void nested() {} 50 void init_in_nested_func(int **x) { 51 *x = 0; // expected-note{{Null pointer value stored to 'y'}} 52 nested(); 53 } // no-note 54 55 int 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 64 struct A { 65 int x; 66 int y; 67 }; 68 69 void partial_init_by_reference(A &a) { 70 a.x = 0; 71 } // expected-note {{Returning without writing to 'a.y'}} 72 73 int 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 81 struct B : A { 82 }; 83 84 void partially_init_inherited_struct(B *b) { 85 b->x = 0; 86 } // expected-note{{Returning without writing to 'b->y'}} 87 88 int 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 96 struct 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 110 int 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 117 int coin(); 118 119 int 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 126 struct D { 127 void initialize(int *); 128 }; 129 130 void D::initialize(int *p) { 131 132 } // expected-note{{Returning without writing to '*p'}} 133 134 int 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 142 struct S2 { 143 int x; 144 }; 145 146 int 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 155 int 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 164 void *has_no_argument_and_returns_null(void) { 165 return 0; 166 } 167 168 void 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 181 struct HasRef { 182 int &a; 183 HasRef(int &a) : a(a) {} 184 }; 185 186 187 void 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 193 int 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 205 struct HasRefToItself { 206 HasRefToItself &Ref; // no infinite loop 207 int &z; 208 HasRefToItself(int &z) : Ref(*this), z(z) {} 209 }; 210 211 void 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 217 int 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 229 void 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 235 int 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 247 struct 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 252 void 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 258 int 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 270 struct HasIndirectRef { 271 HasRef &Ref; 272 HasIndirectRef(HasRef &Ref) : Ref(Ref) {} 273 }; 274 275 void 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 281 int 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 293 struct HasIndirectRefByValue { 294 HasRef Ref; 295 HasIndirectRefByValue(HasRef Ref) : Ref(Ref) {} 296 }; 297 298 void 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 304 int 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 316 struct HasIndirectPointerRef { 317 HasRef *Ref; 318 HasIndirectPointerRef(HasRef *Ref) : Ref(Ref) {} 319 }; 320 321 void 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 327 int 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 339 struct HasFieldA { 340 int x; 341 }; 342 343 struct HasFieldB { 344 int x; 345 }; 346 347 void 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 353 int 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 363 struct HasForgottenField { 364 int x; 365 HasForgottenField() {} // expected-note{{Returning without writing to 'this->x'}} 366 }; 367 368 // Test that tracking across exclamation mark works. 369 bool 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