forked from OSchip/llvm-project
220 lines
4.2 KiB
Plaintext
220 lines
4.2 KiB
Plaintext
// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -fobjc-arc -analyzer-config c++-inlining=constructors -Wno-null-dereference -std=c++11 -verify %s
|
|
|
|
void clang_analyzer_eval(bool);
|
|
void clang_analyzer_checkInlined(bool);
|
|
|
|
// A simplified version of std::move.
|
|
template <typename T>
|
|
T &&move(T &obj) {
|
|
return static_cast<T &&>(obj);
|
|
}
|
|
|
|
|
|
struct Wrapper {
|
|
__strong id obj;
|
|
};
|
|
|
|
void test() {
|
|
Wrapper w;
|
|
// force a diagnostic
|
|
*(char *)0 = 1; // expected-warning{{Dereference of null pointer}}
|
|
}
|
|
|
|
|
|
struct IntWrapper {
|
|
int x;
|
|
};
|
|
|
|
void testCopyConstructor() {
|
|
IntWrapper a;
|
|
a.x = 42;
|
|
|
|
IntWrapper b(a);
|
|
clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
struct NonPODIntWrapper {
|
|
int x;
|
|
|
|
virtual int get();
|
|
};
|
|
|
|
void testNonPODCopyConstructor() {
|
|
NonPODIntWrapper a;
|
|
a.x = 42;
|
|
|
|
NonPODIntWrapper b(a);
|
|
clang_analyzer_eval(b.x == 42); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
|
|
namespace ConstructorVirtualCalls {
|
|
class A {
|
|
public:
|
|
int *out1, *out2, *out3;
|
|
|
|
virtual int get() { return 1; }
|
|
|
|
A(int *out1) {
|
|
*out1 = get();
|
|
}
|
|
};
|
|
|
|
class B : public A {
|
|
public:
|
|
virtual int get() { return 2; }
|
|
|
|
B(int *out1, int *out2) : A(out1) {
|
|
*out2 = get();
|
|
}
|
|
};
|
|
|
|
class C : public B {
|
|
public:
|
|
virtual int get() { return 3; }
|
|
|
|
C(int *out1, int *out2, int *out3) : B(out1, out2) {
|
|
*out3 = get();
|
|
}
|
|
};
|
|
|
|
void test() {
|
|
int a, b, c;
|
|
|
|
C obj(&a, &b, &c);
|
|
clang_analyzer_eval(a == 1); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(b == 2); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(c == 3); // expected-warning{{TRUE}}
|
|
|
|
clang_analyzer_eval(obj.get() == 3); // expected-warning{{TRUE}}
|
|
|
|
// Sanity check for devirtualization.
|
|
A *base = &obj;
|
|
clang_analyzer_eval(base->get() == 3); // expected-warning{{TRUE}}
|
|
}
|
|
}
|
|
|
|
namespace TemporaryConstructor {
|
|
class BoolWrapper {
|
|
public:
|
|
BoolWrapper() {
|
|
clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
|
|
value = true;
|
|
}
|
|
bool value;
|
|
};
|
|
|
|
void test() {
|
|
// PR13717 - Don't crash when a CXXTemporaryObjectExpr is inlined.
|
|
if (BoolWrapper().value)
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
namespace ConstructorUsedAsRValue {
|
|
using TemporaryConstructor::BoolWrapper;
|
|
|
|
bool extractValue(BoolWrapper b) {
|
|
return b.value;
|
|
}
|
|
|
|
void test() {
|
|
bool result = extractValue(BoolWrapper());
|
|
clang_analyzer_eval(result); // expected-warning{{TRUE}}
|
|
}
|
|
}
|
|
|
|
namespace PODUninitialized {
|
|
class POD {
|
|
public:
|
|
int x, y;
|
|
};
|
|
|
|
class PODWrapper {
|
|
public:
|
|
POD p;
|
|
};
|
|
|
|
class NonPOD {
|
|
public:
|
|
int x, y;
|
|
|
|
NonPOD() {}
|
|
NonPOD(const NonPOD &Other)
|
|
: x(Other.x), y(Other.y) // expected-warning {{undefined}}
|
|
{
|
|
}
|
|
NonPOD(NonPOD &&Other)
|
|
: x(Other.x), y(Other.y) // expected-warning {{undefined}}
|
|
{
|
|
}
|
|
};
|
|
|
|
class NonPODWrapper {
|
|
public:
|
|
class Inner {
|
|
public:
|
|
int x, y;
|
|
|
|
Inner() {}
|
|
Inner(const Inner &Other)
|
|
: x(Other.x), y(Other.y) // expected-warning {{undefined}}
|
|
{
|
|
}
|
|
Inner(Inner &&Other)
|
|
: x(Other.x), y(Other.y) // expected-warning {{undefined}}
|
|
{
|
|
}
|
|
};
|
|
|
|
Inner p;
|
|
};
|
|
|
|
void testPOD() {
|
|
POD p;
|
|
p.x = 1;
|
|
POD p2 = p; // no-warning
|
|
clang_analyzer_eval(p2.x == 1); // expected-warning{{TRUE}}
|
|
POD p3 = move(p); // no-warning
|
|
clang_analyzer_eval(p3.x == 1); // expected-warning{{TRUE}}
|
|
|
|
// Use rvalues as well.
|
|
clang_analyzer_eval(POD(p3).x == 1); // expected-warning{{TRUE}}
|
|
|
|
PODWrapper w;
|
|
w.p.y = 1;
|
|
PODWrapper w2 = w; // no-warning
|
|
clang_analyzer_eval(w2.p.y == 1); // expected-warning{{TRUE}}
|
|
PODWrapper w3 = move(w); // no-warning
|
|
clang_analyzer_eval(w3.p.y == 1); // expected-warning{{TRUE}}
|
|
|
|
// Use rvalues as well.
|
|
clang_analyzer_eval(PODWrapper(w3).p.y == 1); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
void testNonPOD() {
|
|
NonPOD p;
|
|
p.x = 1;
|
|
NonPOD p2 = p;
|
|
}
|
|
|
|
void testNonPODMove() {
|
|
NonPOD p;
|
|
p.x = 1;
|
|
NonPOD p2 = move(p);
|
|
}
|
|
|
|
void testNonPODWrapper() {
|
|
NonPODWrapper w;
|
|
w.p.y = 1;
|
|
NonPODWrapper w2 = w;
|
|
}
|
|
|
|
void testNonPODWrapperMove() {
|
|
NonPODWrapper w;
|
|
w.p.y = 1;
|
|
NonPODWrapper w2 = move(w);
|
|
}
|
|
}
|