| // RUN: %clang_analyze_cc1 -x c++ -std=c++14 -analyzer-checker=core -analyzer-output=text -verify %s |
| |
| int initializer1(int &p, int x) { |
| if (x) { // expected-note{{'x' is 0}} |
| // expected-note@-1{{Taking false branch}} |
| p = 1; |
| return 0; |
| } else { |
| return 1; // expected-note {{Returning without writing to 'p'}} |
| } |
| } |
| |
| int param_not_initialized_by_func() { |
| int outP; // expected-note {{'outP' declared without an initial value}} |
| int out = initializer1(outP, 0); // expected-note{{Calling 'initializer1'}} |
| // expected-note@-1{{Returning from 'initializer1'}} |
| return outP; // expected-note{{Undefined or garbage value returned to caller}} |
| // expected-warning@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| struct S { |
| int initialize(int *p, int param) { |
| if (param) { // expected-note{{'param' is 0}} |
| // expected-note@-1{{Taking false branch}} |
| *p = 1; |
| return 1; |
| } |
| return 0; // expected-note{{Returning without writing to '*p'}} |
| } |
| }; |
| |
| int use(S *s) { |
| int p; //expected-note{{'p' declared without an initial value}} |
| s->initialize(&p, 0); //expected-note{{Calling 'S::initialize'}} |
| //expected-note@-1{{Returning from 'S::initialize'}} |
| return p; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| int initializer2(const int &p) { |
| return 0; |
| } |
| |
| int no_msg_const_ref() { |
| int p; //expected-note{{'p' declared without an initial value}} |
| initializer2(p); |
| return p; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| void nested() {} |
| void init_in_nested_func(int **x) { |
| *x = 0; // expected-note{{Null pointer value stored to 'y'}} |
| nested(); |
| } // no-note |
| |
| int call_init_nested() { |
| int x = 0; |
| int *y = &x; |
| init_in_nested_func(&y); // expected-note{{Calling 'init_in_nested_func'}} |
| // expected-note@-1{{Returning from 'init_in_nested_func'}} |
| return *y; //expected-warning{{Dereference of null pointer (loaded from variable 'y')}} |
| //expected-note@-1{{Dereference of null pointer (loaded from variable 'y')}} |
| } |
| |
| struct A { |
| int x; |
| int y; |
| }; |
| |
| void partial_init_by_reference(A &a) { |
| a.x = 0; |
| } // expected-note {{Returning without writing to 'a.y'}} |
| |
| int use_partial_init_by_reference() { |
| A a; |
| partial_init_by_reference(a); // expected-note{{Calling 'partial_init_by_reference'}} |
| // expected-note@-1{{Returning from 'partial_init_by_reference'}} |
| return a.y; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| struct B : A { |
| }; |
| |
| void partially_init_inherited_struct(B *b) { |
| b->x = 0; |
| } // expected-note{{Returning without writing to 'b->y'}} |
| |
| int use_partially_init_inherited_struct() { |
| B b; |
| partially_init_inherited_struct(&b); // expected-note{{Calling 'partially_init_inherited_struct'}} |
| // expected-note@-1{{Returning from 'partially_init_inherited_struct'}} |
| return b.y; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| struct C { |
| int x; |
| int y; |
| C(int pX, int pY) : x(pX) {} // expected-note{{Returning without writing to 'this->y'}} |
| |
| C(int pX, int pY, bool Flag) { |
| x = pX; |
| if (Flag) // expected-note{{Assuming 'Flag' is true}} |
| // expected-note@-1{{Taking true branch}} |
| return; // expected-note{{Returning without writing to 'this->y'}} |
| y = pY; |
| } |
| }; |
| |
| int use_constructor() { |
| C c(0, 0); // expected-note{{Calling constructor for 'C'}} |
| // expected-note@-1{{Returning from constructor for 'C'}} |
| return c.y; // expected-note{{Undefined or garbage value returned to caller}} |
| // expected-warning@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| int coin(); |
| |
| int use_other_constructor() { |
| C c(0, 0, coin()); // expected-note{{Calling constructor for 'C'}} |
| // expected-note@-1{{Returning from constructor for 'C'}} |
| return c.y; // expected-note{{Undefined or garbage value returned to caller}} |
| // expected-warning@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| struct D { |
| void initialize(int *); |
| }; |
| |
| void D::initialize(int *p) { |
| |
| } // expected-note{{Returning without writing to '*p'}} |
| |
| int use_d_initializer(D* d) { |
| int p; // expected-note {{'p' declared without an initial value}} |
| d->initialize(&p); // expected-note{{Calling 'D::initialize'}} |
| // expected-note@-1{{Returning from 'D::initialize'}} |
| return p; // expected-note{{Undefined or garbage value returned to caller}} |
| // expected-warning@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| struct S2 { |
| int x; |
| }; |
| |
| int pointerreference(S2* &s) { |
| if (coin()) // expected-note{{Assuming the condition is true}} |
| // expected-note@-1{{Taking true branch}} |
| return 1; // expected-note{{Returning without writing to 's->x'}} |
| |
| s->x = 0; |
| return 0; |
| } |
| |
| int usepointerreference() { |
| S2 s; |
| S2* p = &s; |
| pointerreference(p); //expected-note{{Calling 'pointerreference'}} |
| //expected-note@-1{{Returning from 'pointerreference'}} |
| return s.x; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| void *has_no_argument_and_returns_null(void) { |
| return 0; |
| } |
| |
| void rdar40335545() { |
| int local; // expected-note{{}} |
| void (*takes_int_ptr_argument)(int *) = (void (*)(int*))has_no_argument_and_returns_null; |
| |
| takes_int_ptr_argument(&local); // no-crash |
| |
| int useLocal = local; //expected-warning{{}} |
| //expected-note@-1{{}} |
| (void)useLocal; |
| } |
| |
| //////// |
| |
| struct HasRef { |
| int &a; |
| HasRef(int &a) : a(a) {} |
| }; |
| |
| |
| void maybeInitialize(const HasRef &&pA) { |
| if (coin()) // expected-note{{Assuming the condition is false}} |
| // expected-note@-1{{Taking false branch}} |
| pA.a = 120; |
| } // expected-note{{Returning without writing to 'pA.a'}} |
| |
| int useMaybeInitializerWritingIntoField() { |
| int z; // expected-note{{'z' declared without an initial value}} |
| maybeInitialize(HasRef(z)); // expected-note{{Calling constructor for 'HasRef'}} |
| // expected-note@-1{{Returning from constructor for 'HasRef'}} |
| // expected-note@-2{{Calling 'maybeInitialize'}} |
| // expected-note@-3{{Returning from 'maybeInitialize'}} |
| return z; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| //////// |
| |
| struct HasRefToItself { |
| HasRefToItself &Ref; // no infinite loop |
| int &z; |
| HasRefToItself(int &z) : Ref(*this), z(z) {} |
| }; |
| |
| void maybeInitialize(const HasRefToItself &&pA) { |
| if (coin()) // expected-note{{Assuming the condition is false}} |
| // expected-note@-1{{Taking false branch}} |
| pA.z = 120; |
| } // expected-note{{Returning without writing to 'pA.Ref.z'}} |
| |
| int useMaybeInitializerWritingIntoFieldWithRefToItself() { |
| int z; // expected-note{{'z' declared without an initial value}} |
| maybeInitialize(HasRefToItself(z)); // expected-note{{Calling constructor for 'HasRefToItself'}} |
| // expected-note@-1{{Returning from constructor for 'HasRefToItself'}} |
| // expected-note@-2{{Calling 'maybeInitialize'}} |
| // expected-note@-3{{Returning from 'maybeInitialize'}} |
| return z; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| //// |
| |
| void maybeInitialize(const HasRef *pA) { |
| if (coin()) // expected-note{{Assuming the condition is false}} |
| // expected-note@-1{{Taking false branch}} |
| pA->a = 120; |
| } // expected-note{{Returning without writing to 'pA->a'}} |
| |
| int useMaybeInitializerStructByPointer() { |
| int z; // expected-note{{'z' declared without an initial value}} |
| HasRef wrapper(z); // expected-note{{Calling constructor for 'HasRef'}} |
| // expected-note@-1{{Returning from constructor for 'HasRef'}} |
| maybeInitialize(&wrapper); // expected-note{{Calling 'maybeInitialize'}} |
| // expected-note@-1{{Returning from 'maybeInitialize'}} |
| return z; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| //////// |
| |
| struct HasParentWithRef : public HasRef { |
| HasParentWithRef(int &a) : HasRef(a) {} // expected-note{{Calling constructor for 'HasRef'}} |
| // expected-note@-1{{Returning from constructor for 'HasRef'}} |
| }; |
| |
| void maybeInitializeWithParent(const HasParentWithRef &pA) { |
| if (coin()) // expected-note{{Assuming the condition is false}} |
| // expected-note@-1{{Taking false branch}} |
| pA.a = 120; |
| } // expected-note{{Returning without writing to 'pA.a'}} |
| |
| int useMaybeInitializerWritingIntoParentField() { |
| int z; // expected-note{{'z' declared without an initial value}} |
| maybeInitializeWithParent(HasParentWithRef(z)); // expected-note{{Calling constructor for 'HasParentWithRef'}} |
| // expected-note@-1{{Returning from constructor for 'HasParentWithRef'}} |
| // expected-note@-2{{Calling 'maybeInitializeWithParent'}} |
| // expected-note@-3{{Returning from 'maybeInitializeWithParent'}} |
| return z; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| //////// |
| |
| struct HasIndirectRef { |
| HasRef &Ref; |
| HasIndirectRef(HasRef &Ref) : Ref(Ref) {} |
| }; |
| |
| void maybeInitializeIndirectly(const HasIndirectRef &pA) { |
| if (coin()) // expected-note{{Assuming the condition is false}} |
| // expected-note@-1{{Taking false branch}} |
| pA.Ref.a = 120; |
| } // expected-note{{Returning without writing to 'pA.Ref.a'}} |
| |
| int useMaybeInitializeIndirectly() { |
| int z; // expected-note{{'z' declared without an initial value}} |
| HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}} |
| // expected-note@-1{{Returning from constructor for 'HasRef'}} |
| maybeInitializeIndirectly(HasIndirectRef(r)); // expected-note{{Calling 'maybeInitializeIndirectly'}} |
| // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}} |
| return z; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| //////// |
| |
| struct HasIndirectRefByValue { |
| HasRef Ref; |
| HasIndirectRefByValue(HasRef Ref) : Ref(Ref) {} |
| }; |
| |
| void maybeInitializeIndirectly(const HasIndirectRefByValue &pA) { |
| if (coin()) // expected-note{{Assuming the condition is false}} |
| // expected-note@-1{{Taking false branch}} |
| pA.Ref.a = 120; |
| } // expected-note{{Returning without writing to 'pA.Ref.a'}} |
| |
| int useMaybeInitializeIndirectlyIndirectRefByValue() { |
| int z; // expected-note{{'z' declared without an initial value}} |
| HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}} |
| // expected-note@-1{{Returning from constructor for 'HasRef'}} |
| maybeInitializeIndirectly(HasIndirectRefByValue(r)); // expected-note{{Calling 'maybeInitializeIndirectly'}} |
| // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}} |
| return z; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| //////// |
| |
| struct HasIndirectPointerRef { |
| HasRef *Ref; |
| HasIndirectPointerRef(HasRef *Ref) : Ref(Ref) {} |
| }; |
| |
| void maybeInitializeIndirectly(const HasIndirectPointerRef &pA) { |
| if (coin()) // expected-note{{Assuming the condition is false}} |
| // expected-note@-1{{Taking false branch}} |
| pA.Ref->a = 120; |
| } // expected-note{{Returning without writing to 'pA.Ref->a'}} |
| |
| int useMaybeInitializeIndirectlyWithPointer() { |
| int z; // expected-note{{'z' declared without an initial value}} |
| HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}} |
| // expected-note@-1{{Returning from constructor for 'HasRef'}} |
| maybeInitializeIndirectly(HasIndirectPointerRef(&r)); // expected-note{{Calling 'maybeInitializeIndirectly'}} |
| // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}} |
| return z; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| //////// |
| |
| struct HasFieldA { |
| int x; |
| }; |
| |
| struct HasFieldB { |
| int x; |
| }; |
| |
| void maybeInitializeHasField(HasFieldA *b) { |
| if (coin()) // expected-note{{Assuming the condition is false}} |
| // expected-note@-1{{Taking false branch}} |
| ((HasFieldB*)b)->x = 120; |
| } |
| |
| int forceElementRegionApperence() { |
| HasFieldA a; |
| maybeInitializeHasField(&a); // expected-note{{Calling 'maybeInitializeHasField'}} |
| // expected-note@-1{{Returning from 'maybeInitializeHasField'}} |
| return ((HasFieldB*)&a)->x; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |
| |
| //////// |
| |
| struct HasForgottenField { |
| int x; |
| HasForgottenField() {} // expected-note{{Returning without writing to 'this->x'}} |
| }; |
| |
| // Test that tracking across exclamation mark works. |
| bool tracksThroughExclamationMark() { |
| HasForgottenField a; // expected-note{{Calling default constructor for 'HasForgottenField'}} |
| // expected-note@-1{{Returning from default constructor for 'HasForgottenField'}} |
| return !a.x; // expected-warning{{Undefined or garbage value returned to caller}} |
| // expected-note@-1{{Undefined or garbage value returned to caller}} |
| } |