blob: c2a3d648018879bb0b6a24af6195b6e9685ae7b4 [file] [log] [blame]
// 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}}
}