extern bool clang_analyzer_eval(bool);
extern bool clang_analyzer_warnIfReached();
void clang_analyzer_checkInlined(bool);
#include "Inputs/system-header-simulator-cxx.h"
struct Trivial {
Trivial(int x) : value(x) {}
int value;
};
struct NonTrivial : public Trivial {
NonTrivial(int x) : Trivial(x) {}
~NonTrivial();
};
Trivial getTrivial() {
return Trivial(42); }
const Trivial &getTrivialRef() {
return Trivial(42); }
NonTrivial getNonTrivial() {
return NonTrivial(42); }
const NonTrivial &getNonTrivialRef() {
return NonTrivial(42); }
namespace rdar13265460 {
struct TrivialSubclass : public Trivial {
TrivialSubclass(int x) : Trivial(x), anotherValue(-x) {}
int anotherValue;
};
TrivialSubclass getTrivialSub() {
TrivialSubclass obj(1);
obj.value = 42;
obj.anotherValue = -42;
return obj;
}
void testImmediate() {
TrivialSubclass obj = getTrivialSub();
clang_analyzer_eval(obj.value == 42); clang_analyzer_eval(obj.anotherValue == -42);
clang_analyzer_eval(getTrivialSub().value == 42); clang_analyzer_eval(getTrivialSub().anotherValue == -42); }
void testMaterializeTemporaryExpr() {
const TrivialSubclass &ref = getTrivialSub();
clang_analyzer_eval(ref.value == 42);
const Trivial &baseRef = getTrivialSub();
clang_analyzer_eval(baseRef.value == 42); }
}
namespace rdar13281951 {
struct Derived : public Trivial {
Derived(int value) : Trivial(value), value2(-value) {}
int value2;
};
void test() {
Derived obj(1);
obj.value = 42;
const Trivial * const &pointerRef = &obj;
clang_analyzer_eval(pointerRef->value == 42); }
}
namespace compound_literals {
struct POD {
int x, y;
};
struct HasCtor {
HasCtor(int x, int y) : x(x), y(y) {}
int x, y;
};
struct HasDtor {
int x, y;
~HasDtor();
};
struct HasCtorDtor {
HasCtorDtor(int x, int y) : x(x), y(y) {}
~HasCtorDtor();
int x, y;
};
void test() {
clang_analyzer_eval(((POD){1, 42}).y == 42); clang_analyzer_eval(((HasDtor){1, 42}).y == 42);
#if __cplusplus >= 201103L
clang_analyzer_eval(((HasCtor){1, 42}).y == 42);
clang_analyzer_eval(((HasCtorDtor){1, 42}).y == 42); #endif
}
}
namespace destructors {
struct Dtor {
~Dtor();
};
extern bool coin();
extern bool check(const Dtor &);
void testPR16664andPR18159Crash() {
if (coin() && (coin() || coin() || check(Dtor()))) {
Dtor();
}
}
#ifdef TEMPORARY_DTORS
struct NoReturnDtor {
~NoReturnDtor() __attribute__((noreturn));
};
void noReturnTemp(int *x) {
if (! x) NoReturnDtor();
*x = 47; }
void noReturnInline(int **x) {
NoReturnDtor();
}
void callNoReturn() {
int *x;
noReturnInline(&x);
*x = 47; }
extern bool check(const NoReturnDtor &);
void testConsistencyIf(int i) {
if (i != 5)
return;
if (i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) {
clang_analyzer_eval(true); }
}
void testConsistencyTernary(int i) {
(i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
clang_analyzer_eval(true);
if (i != 5)
return;
(i == 5 && (i == 4 || check(NoReturnDtor()) || i == 5)) ? 1 : 0;
clang_analyzer_eval(true); }
void testConsistencyNested(int i) {
extern bool compute(bool);
if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
clang_analyzer_eval(true);
if (i == 5 && (i == 4 || i == 5 || check(NoReturnDtor())))
clang_analyzer_eval(true);
if (i != 5)
return;
if (compute(i == 5 &&
(i == 4 || compute(true) ||
compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
i != 4) {
clang_analyzer_eval(true); }
if (compute(i == 5 &&
(i == 4 || i == 4 ||
compute(i == 5 && (i == 4 || check(NoReturnDtor()))))) ||
i != 4) {
clang_analyzer_eval(true); }
}
void testConsistencyNestedSimple(bool value) {
if (value) {
if (!value || check(NoReturnDtor())) {
clang_analyzer_eval(true); }
}
}
void testConsistencyNestedComplex(bool value) {
if (value) {
if (!value || !value || check(NoReturnDtor())) {
clang_analyzer_eval(true); }
}
}
void testConsistencyNestedWarning(bool value) {
if (value) {
if (!value || value || check(NoReturnDtor())) {
clang_analyzer_eval(true); }
}
}
void testConsistencyNestedComplexMidBranch(bool value) {
if (value) {
if (!value || !value || check(NoReturnDtor()) || value) {
clang_analyzer_eval(true); }
}
}
void testConsistencyNestedComplexNestedBranch(bool value) {
if (value) {
if (!value || (!value || check(NoReturnDtor()) || value)) {
clang_analyzer_eval(true); }
}
}
void testConsistencyNestedVariableModification(bool value) {
bool other = true;
if (value) {
if (!other || !value || (other = false) || check(NoReturnDtor()) ||
!other) {
clang_analyzer_eval(true); }
}
}
void testTernaryNoReturnTrueBranch(bool value) {
if (value) {
bool b = value && (value ? check(NoReturnDtor()) : true);
clang_analyzer_eval(true); }
}
void testTernaryNoReturnFalseBranch(bool value) {
if (value) {
bool b = !value && !value ? true : check(NoReturnDtor());
clang_analyzer_eval(true); }
}
void testTernaryIgnoreNoreturnBranch(bool value) {
if (value) {
bool b = !value && !value ? check(NoReturnDtor()) : true;
clang_analyzer_eval(true); }
}
void testTernaryTrueBranchReached(bool value) {
value ? clang_analyzer_warnIfReached() : check(NoReturnDtor());
}
void testTernaryFalseBranchReached(bool value) {
value ? check(NoReturnDtor()) :
clang_analyzer_warnIfReached(); }
void testLoop() {
for (int i = 0; i < 10; ++i) {
if (i < 3 && (i >= 2 || check(NoReturnDtor()))) {
clang_analyzer_eval(true); }
}
}
bool testRecursiveFrames(bool isInner) {
if (isInner ||
(clang_analyzer_warnIfReached(), false) || check(NoReturnDtor()) ||
testRecursiveFrames(true)) {
clang_analyzer_warnIfReached(); }
}
void testRecursiveFramesStart() { testRecursiveFrames(false); }
void testLambdas() {
[]() { check(NoReturnDtor()); } != nullptr || check(Dtor());
}
void testGnuExpressionStatements(int v) {
({ ++v; v == 10 || check(NoReturnDtor()); v == 42; }) || v == 23;
clang_analyzer_warnIfReached();
({ ++v; check(NoReturnDtor()); v == 42; }) || v == 23;
clang_analyzer_warnIfReached(); }
void testGnuExpressionStatementsDestructionPoint(int v) {
(++v, check(NoReturnDtor()), v == 42),
clang_analyzer_warnIfReached();
({ ++v; check(NoReturnDtor()); v == 42; }),
clang_analyzer_warnIfReached(); }
void testMultipleTemporaries(bool value) {
if (value) {
if (!value || check((NoReturnDtor(), Dtor())) || value) {
clang_analyzer_eval(true); }
}
}
void testBinaryOperatorShortcut(bool value) {
if (value) {
if (false && false && check(NoReturnDtor()) && true) {
clang_analyzer_eval(true);
}
}
}
void testIfAtEndOfLoop() {
int y = 0;
while (true) {
if (y > 0) {
clang_analyzer_warnIfReached(); }
++y;
if (true) (void)0; else (void)check(NoReturnDtor());
}
}
void testTernaryAtEndOfLoop() {
int y = 0;
while (true) {
if (y > 0) {
clang_analyzer_warnIfReached(); }
++y;
true ? (void)0 : (void)check(NoReturnDtor());
}
}
void testNoReturnInComplexCondition() {
check(Dtor()) &&
(check(NoReturnDtor()) || check(NoReturnDtor())) && check(Dtor());
clang_analyzer_warnIfReached(); }
void testSequencingOfConditionalTempDtors(bool b) {
b || (check(Dtor()), check(NoReturnDtor()));
clang_analyzer_warnIfReached(); }
void testSequencingOfConditionalTempDtors2(bool b) {
(b || check(Dtor())), check(NoReturnDtor());
clang_analyzer_warnIfReached(); }
void testSequencingOfConditionalTempDtorsWithinBinaryOperators(bool b) {
b || (check(Dtor()) + check(NoReturnDtor()));
clang_analyzer_warnIfReached(); }
void f(Dtor d = Dtor());
void testDefaultParameters() {
f();
}
struct DefaultParam {
DefaultParam(int, const Dtor& d = Dtor());
~DefaultParam();
};
void testDefaultParamConstructorsInLoops() {
while (true) {
DefaultParam(42);
DefaultParam(42);
}
}
void testDefaultParamConstructorsInTernariesInLoops(bool value) {
while (true) {
value ? DefaultParam(42) : DefaultParam(42);
}
}
#else
struct CtorWithNoReturnDtor {
CtorWithNoReturnDtor() = default;
CtorWithNoReturnDtor(int x) {
clang_analyzer_checkInlined(false); }
~CtorWithNoReturnDtor() __attribute__((noreturn));
};
void testDefaultContructorWithNoReturnDtor() {
CtorWithNoReturnDtor();
clang_analyzer_warnIfReached(); }
void testLifeExtensionWithNoReturnDtor() {
const CtorWithNoReturnDtor &c = CtorWithNoReturnDtor();
clang_analyzer_warnIfReached(); }
#if __cplusplus >= 201103L
struct CtorWithNoReturnDtor2 {
CtorWithNoReturnDtor2() = default;
CtorWithNoReturnDtor2(int x) {
clang_analyzer_checkInlined(true); }
~CtorWithNoReturnDtor2() __attribute__((noreturn));
};
CtorWithNoReturnDtor2 returnNoReturnDtor() {
return {1}; }
#endif
#endif }
namespace default_param_elided_destructors {
struct a {
~a();
};
struct F {
a d;
F(char *, a = a());
};
void g() {
char h[1];
for (int i = 0;;)
F j(i ? j : h);
}
}
void testStaticMaterializeTemporaryExpr() {
static const Trivial &ref = getTrivial();
clang_analyzer_eval(ref.value == 42);
static const Trivial &directRef = Trivial(42);
clang_analyzer_eval(directRef.value == 42);
#if __has_feature(cxx_thread_local)
thread_local static const Trivial &threadRef = getTrivial();
clang_analyzer_eval(threadRef.value == 42);
thread_local static const Trivial &threadDirectRef = Trivial(42);
clang_analyzer_eval(threadDirectRef.value == 42); #endif
}
namespace PR16629 {
struct A {
explicit A(int* p_) : p(p_) {}
int* p;
};
extern void escape(const A*[]);
extern void check(int);
void callEscape(const A& a) {
const A* args[] = { &a };
escape(args);
}
void testNoWarning() {
int x;
callEscape(A(&x));
check(x); }
void set(const A*a[]) {
*a[0]->p = 47;
}
void callSet(const A& a) {
const A* args[] = { &a };
set(args);
}
void testConsistency() {
int x;
callSet(A(&x));
clang_analyzer_eval(x == 47); }
}
namespace PR32088 {
void testReturnFromStmtExprInitializer() {
const NonTrivial &obj = ({
return; NonTrivial(42);
});
}
}
namespace CopyToTemporaryCorrectly {
class Super {
public:
void m() {
mImpl();
}
virtual void mImpl() = 0;
};
class Sub : public Super {
public:
Sub(const int &p) : j(p) {}
virtual void mImpl() override {
(void)(j + 1); if (j != 22) {
clang_analyzer_warnIfReached(); }
}
const int &j;
};
void run() {
int i = 22;
Sub(i).m();
}
}
namespace test_return_temporary {
class C {
int x, y;
public:
C(int x, int y) : x(x), y(y) {}
int getX() const { return x; }
int getY() const { return y; }
~C() {}
};
class D: public C {
public:
D() : C(1, 2) {}
D(const D &d): C(d.getX(), d.getY()) {}
};
C returnTemporaryWithVariable() { C c(1, 2); return c; }
C returnTemporaryWithAnotherFunctionWithVariable() {
return returnTemporaryWithVariable();
}
C returnTemporaryWithCopyConstructionWithVariable() {
return C(returnTemporaryWithVariable());
}
C returnTemporaryWithConstruction() { return C(1, 2); }
C returnTemporaryWithAnotherFunctionWithConstruction() {
return returnTemporaryWithConstruction();
}
C returnTemporaryWithCopyConstructionWithConstruction() {
return C(returnTemporaryWithConstruction());
}
D returnTemporaryWithVariableAndNonTrivialCopy() { D d; return d; }
D returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy() {
return returnTemporaryWithVariableAndNonTrivialCopy();
}
D returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy() {
return D(returnTemporaryWithVariableAndNonTrivialCopy());
}
#if __cplusplus >= 201103L
C returnTemporaryWithBraces() { return {1, 2}; }
C returnTemporaryWithAnotherFunctionWithBraces() {
return returnTemporaryWithBraces();
}
C returnTemporaryWithCopyConstructionWithBraces() {
return C(returnTemporaryWithBraces());
}
#endif
void test() {
C c1 = returnTemporaryWithVariable();
clang_analyzer_eval(c1.getX() == 1); clang_analyzer_eval(c1.getY() == 2);
C c2 = returnTemporaryWithAnotherFunctionWithVariable();
clang_analyzer_eval(c2.getX() == 1); clang_analyzer_eval(c2.getY() == 2);
C c3 = returnTemporaryWithCopyConstructionWithVariable();
clang_analyzer_eval(c3.getX() == 1); clang_analyzer_eval(c3.getY() == 2);
C c4 = returnTemporaryWithConstruction();
clang_analyzer_eval(c4.getX() == 1); clang_analyzer_eval(c4.getY() == 2);
C c5 = returnTemporaryWithAnotherFunctionWithConstruction();
clang_analyzer_eval(c5.getX() == 1); clang_analyzer_eval(c5.getY() == 2);
C c6 = returnTemporaryWithCopyConstructionWithConstruction();
clang_analyzer_eval(c5.getX() == 1); clang_analyzer_eval(c5.getY() == 2);
#if __cplusplus >= 201103L
C c7 = returnTemporaryWithBraces();
clang_analyzer_eval(c7.getX() == 1); clang_analyzer_eval(c7.getY() == 2);
C c8 = returnTemporaryWithAnotherFunctionWithBraces();
clang_analyzer_eval(c8.getX() == 1); clang_analyzer_eval(c8.getY() == 2);
C c9 = returnTemporaryWithCopyConstructionWithBraces();
clang_analyzer_eval(c9.getX() == 1); clang_analyzer_eval(c9.getY() == 2);
#endif
D d1 = returnTemporaryWithVariableAndNonTrivialCopy();
clang_analyzer_eval(d1.getX() == 1); clang_analyzer_eval(d1.getY() == 2);
D d2 = returnTemporaryWithAnotherFunctionWithVariableAndNonTrivialCopy();
clang_analyzer_eval(d2.getX() == 1); clang_analyzer_eval(d2.getY() == 2);
D d3 = returnTemporaryWithCopyConstructionWithVariableAndNonTrivialCopy();
clang_analyzer_eval(d3.getX() == 1); clang_analyzer_eval(d3.getY() == 2); }
}
namespace test_temporary_object_expr_without_dtor {
class C {
int x;
public:
C(int x) : x(x) {}
int getX() const { return x; }
};
void test() {
clang_analyzer_eval(C(3).getX() == 3); };
}
namespace test_temporary_object_expr_with_dtor {
class C {
int x;
public:
C(int x) : x(x) {}
~C() {}
int getX() const { return x; }
};
void test(int coin) {
clang_analyzer_eval(C(3).getX() == 3);
#ifdef TEMPORARY_DTORS
#else
#endif
const C &c1 = coin ? C(1) : C(2);
if (coin) {
clang_analyzer_eval(c1.getX() == 1);
#ifdef TEMPORARY_DTORS
#else
#endif
} else {
clang_analyzer_eval(c1.getX() == 2);
#ifdef TEMPORARY_DTORS
#else
#endif
}
C c2 = coin ? C(1) : C(2);
if (coin) {
clang_analyzer_eval(c2.getX() == 1); } else {
clang_analyzer_eval(c2.getX() == 2); }
}
}
namespace test_match_constructors_and_destructors {
class C {
public:
int &x, &y;
C(int &_x, int &_y) : x(_x), y(_y) { ++x; }
C(const C &c): x(c.x), y(c.y) { ++x; }
~C() { ++y; }
};
void test_simple_temporary() {
int x = 0, y = 0;
{
const C &c = C(x, y);
}
clang_analyzer_eval(x == 1);
clang_analyzer_eval(y == 1);
#ifdef TEMPORARY_DTORS
#else
#endif
}
void test_simple_temporary_with_copy() {
int x = 0, y = 0;
{
C c = C(x, y);
}
clang_analyzer_eval(x == 1); clang_analyzer_eval(y == 1); }
void test_ternary_temporary(int coin) {
int x = 0, y = 0, z = 0, w = 0;
{
const C &c = coin ? C(x, y) : C(z, w);
}
if (coin) {
clang_analyzer_eval(x == 1);
clang_analyzer_eval(y == 1);
#ifdef TEMPORARY_DTORS
#else
#endif
clang_analyzer_eval(z == 0); clang_analyzer_eval(w == 0);
} else {
clang_analyzer_eval(x == 0); clang_analyzer_eval(y == 0); clang_analyzer_eval(z == 1);
clang_analyzer_eval(w == 1);
#ifdef TEMPORARY_DTORS
#else
#endif
}
}
void test_ternary_temporary_with_copy(int coin) {
int x = 0, y = 0, z = 0, w = 0;
{
C c = coin ? C(x, y) : C(z, w);
}
if (coin) {
clang_analyzer_eval(x == 1); clang_analyzer_eval(y == 1); clang_analyzer_eval(z == 0); clang_analyzer_eval(w == 0);
} else {
clang_analyzer_eval(x == 0); clang_analyzer_eval(y == 0); clang_analyzer_eval(z == 1); clang_analyzer_eval(w == 1); }
}
}
namespace destructors_for_return_values {
class C {
public:
~C() {
1 / 0; }
};
C make();
void testFloatingCall() {
make();
clang_analyzer_warnIfReached();
#ifndef TEMPORARY_DTORS
#endif
}
void testLifetimeExtendedCall() {
{
const C &c = make();
clang_analyzer_warnIfReached(); }
clang_analyzer_warnIfReached(); }
void testCopiedCall() {
{
C c = make();
clang_analyzer_warnIfReached(); }
clang_analyzer_warnIfReached(); }
}
namespace dont_forget_destructor_around_logical_op {
int glob;
class C {
public:
~C() {
glob = 1;
clang_analyzer_checkInlined(true);
#ifdef TEMPORARY_DTORS
#endif
}
};
C get();
bool is(C);
void test(int coin) {
coin && is(get()); if (coin) {
clang_analyzer_eval(glob);
#ifdef TEMPORARY_DTORS
#else
#endif
} else {
clang_analyzer_eval(glob); }
}
}
#if __cplusplus >= 201103L
namespace temporary_list_crash {
class C {
public:
C() {}
~C() {}
};
void test() {
std::initializer_list<C>{C(), C()}; }
} #endif
namespace implicit_constructor_conversion {
struct S {
int x;
S(int x) : x(x) {}
~S() {}
};
class C {
int x;
public:
C(const S &s) : x(s.x) {}
~C() {}
int getX() const { return x; }
};
void test() {
const C &c1 = S(10);
clang_analyzer_eval(c1.getX() == 10);
#ifdef TEMPORARY_DTORS
#else
#endif
S s = 20;
clang_analyzer_eval(s.x == 20);
C c2 = s;
clang_analyzer_eval(c2.getX() == 20); }
}
namespace pass_references_through {
class C {
public:
~C() {}
};
const C &foo1();
C &&foo2();
const C &bar1() { return foo1(); } C &&bar2() { return foo2(); } }
namespace arguments {
int glob;
struct S {
int x;
S(int x): x(x) {}
S(const S &s) : x(s.x) {}
~S() {}
S &operator+(S s) {
glob = s.x;
x += s.x;
return *this;
}
};
class C {
public:
virtual void bar3(S s) {}
};
class D: public C {
public:
D() {}
virtual void bar3(S s) override { glob = s.x; }
};
void bar1(S s) {
glob = s.x;
}
S bar2(S s) {
glob = s.x;
return S(3);
}
void bar5(int, ...);
void foo(void (*bar4)(S)) {
bar1(S(1));
clang_analyzer_eval(glob == 1);
#ifdef TEMPORARY_DTORS
#else
#endif
bar2(S(2));
clang_analyzer_eval(glob == 2);
#ifdef TEMPORARY_DTORS
#else
#endif
C *c = new D();
c->bar3(S(3));
clang_analyzer_eval(glob == 3); delete c;
bar4(S(4));
S(5) + S(6);
clang_analyzer_eval(glob == 6);
#ifdef TEMPORARY_DTORS
#else
#endif
bar5(7, S(7)); clang_analyzer_warnIfReached(); }
}
namespace ctor_argument {
struct IntPtr {
IntPtr(): i(new int) {}
IntPtr(IntPtr &&o): i(o.i) { o.i = 0; }
~IntPtr() { delete i; }
int *i;
};
struct Foo {
Foo(IntPtr);
void bar();
IntPtr i;
};
void bar() {
IntPtr ptr;
int *i = ptr.i;
Foo f(static_cast<IntPtr &&>(ptr));
*i = 99; }
}
namespace operator_implicit_argument {
struct S {
bool x;
S(bool x): x(x) {}
operator bool() const { return x; }
};
void foo() {
if (S(false)) {
clang_analyzer_warnIfReached(); }
if (S(true)) {
clang_analyzer_warnIfReached(); }
}
}
#if __cplusplus >= 201103L
namespace argument_lazy_bindings {
int glob;
struct S {
int x, y, z;
};
struct T {
S s;
int w;
T(int w): s{5, 6, 7}, w(w) {}
};
void foo(T t) {
t.s = {1, 2, 3};
glob = t.w;
}
void bar() {
foo(T(4));
clang_analyzer_eval(glob == 4); }
} #endif
namespace operator_argument_cleanup {
struct S {
S();
};
class C {
public:
void operator=(S);
};
void foo() {
C c;
c = S(); }
}
namespace argument_decl_lookup {
class C {};
int foo(C);
int bar(C c) { foo(c); }
int foo(C c) {}
}
namespace argument_virtual_decl_lookup {
class C {};
struct T {
virtual void foo(C);
};
void run() {
T *t;
t->foo(C()); }
void T::foo(C) {}
}
namespace union_indirect_field_crash {
union U {
struct {
int x;
};
};
template <typename T> class C {
public:
void foo() const {
(void)(true ? U().x : 0);
}
};
void test() {
C<int> c;
c.foo();
}
}
namespace return_from_top_frame {
struct S {
int *p;
S() { p = new int; }
S(S &&s) : p(s.p) { s.p = 0; }
~S(); };
S foo() {
S s;
return s;
}
S bar1() {
return foo(); }
S bar2() {
return S();
}
S bar3(int coin) {
return coin ? S() : foo(); }
}
#if __cplusplus >= 201103L
namespace arguments_of_operators {
struct S {
S() {}
S(const S &) {}
};
void test() {
int x = 0;
auto foo = [](S s, int &y) { y = 1; };
foo(S(), x);
clang_analyzer_eval(x == 1); }
} #endif