void Constants() { char c_i = 1; char c_c = 'A'; signed char sc_i = -1; signed char sc_c = 'A'; unsigned char uc_i = 5; unsigned char uc_c = 'A'; short s = 5; unsigned short us = 5; int i = 5; unsigned int ui = 5; long l = 5; unsigned long ul = 5; long long ll_i = 5; long long ll_ll = 5LL; unsigned long long ull_i = 5; unsigned long long ull_ull = 5ULL; bool b_t = true; bool b_f = false; wchar_t wc_i = 5; wchar_t wc_c = L'A'; char16_t c16 = u'A'; char32_t c32 = U'A'; float f_i = 1; float f_f = 1.0f; float f_d = 1.0; double d_i = 1; double d_f = 1.0f; double d_d = 1.0; } void Foo() { int x = 5 + 12; short y = 7; y = x + y; x = x * y; } void IntegerOps(int x, int y) { int z; z = x + y; z = x - y; z = x * y; z = x / y; z = x % y; z = x & y; z = x | y; z = x ^ y; z = x << y; z = x >> y; z = x; z += x; z -= x; z *= x; z /= x; z %= x; z &= x; z |= x; z ^= x; z <<= x; z >>= x; z = +x; z = -x; z = ~x; z = !x; } void IntegerCompare(int x, int y) { bool b; b = x == y; b = x != y; b = x < y; b = x > y; b = x <= y; b = x >= y; } void IntegerCrement(int x) { int y; y = ++x; y = --x; y = x++; y = x--; } void IntegerCrement_LValue(int x) { int* p; p = &(++x); p = &(--x); } void FloatOps(double x, double y) { double z; z = x + y; z = x - y; z = x * y; z = x / y; z = x; z += x; z -= x; z *= x; z /= x; z = +x; z = -x; } void FloatCompare(double x, double y) { bool b; b = x == y; b = x != y; b = x < y; b = x > y; b = x <= y; b = x >= y; } void FloatCrement(float x) { float y; y = ++x; y = --x; y = x++; y = x--; } void PointerOps(int* p, int i) { int* q; bool b; q = p + i; q = i + p; q = p - i; i = p - q; q = p; q += i; q -= i; b = p; b = !p; } void ArrayAccess(int* p, int i) { int x; x = p[i]; x = i[p]; p[i] = x; i[p] = x; int a[10]; x = a[i]; x = i[a]; a[i] = x; i[a] = x; } void StringLiteral(int i) { char c = "Foo"[i]; wchar_t* pwc = L"Bar"; wchar_t wc = pwc[i]; } void PointerCompare(int* p, int* q) { bool b; b = p == q; b = p != q; b = p < q; b = p > q; b = p <= q; b = p >= q; } void PointerCrement(int* p) { int* q; q = ++p; q = --p; q = p++; q = p--; } void CompoundAssignment() { // No conversion necessary int x = 5; x += 7; // Left side is converted to 'int' short y = 5; y += x; // Technically the left side is promoted to int, but we don't model that y <<= 1; // Left side is converted to 'float' long z = 7; z += 2.0f; } void UninitializedVariables() { int x; int y = x; } int Parameters(int x, int y) { return x % y; } void IfStatements(bool b, int x, int y) { if (b) { } if (b) { x = y; } if (x < 7) x = 2; else x = 7; } void WhileStatements(int n) { while (n > 0) { n -= 1; } } void DoStatements(int n) { do { n -= 1; } while (n > 0); } void For_Empty() { int j; for (;;) { ; } } void For_Init() { for (int i = 0;;) { ; } } void For_Condition() { int i = 0; for (; i < 10;) { ; } } void For_Update() { int i = 0; for (;; i += 1) { ; } } void For_InitCondition() { for (int i = 0; i < 10;) { ; } } void For_InitUpdate() { for (int i = 0;; i += 1) { ; } } void For_ConditionUpdate() { int i = 0; for (; i < 10; i += 1) { ; } } void For_InitConditionUpdate() { for (int i = 0; i < 10; i += 1) { ; } } void For_Break() { for (int i = 0; i < 10; i += 1) { if (i == 5) { break; } } } void For_Continue_Update() { for (int i = 0; i < 10; i += 1) { if (i == 5) { continue; } } } void For_Continue_NoUpdate() { for (int i = 0; i < 10;) { if (i == 5) { continue; } } } int Dereference(int* p) { *p = 1; return *p; } int g; int* AddressOf() { return &g; } void Break(int n) { while (n > 0) { if (n == 1) break; n -= 1; } } void Continue(int n) { do { if (n == 1) { continue; } n -= 1; } while (n > 0); } void VoidFunc(); int Add(int x, int y); void Call() { VoidFunc(); } int CallAdd(int x, int y) { return Add(x, y); } int Comma(int x, int y) { return VoidFunc(), CallAdd(x, y); } void Switch(int x) { int y; switch (x) { y = 1234; case -1: y = -1; break; case 1: case 2: y = 1; break; case 3: y = 3; case 4: y = 4; break; default: y = 0; break; y = 5678; } } struct Point { int x; int y; }; struct Rect { Point topLeft; Point bottomRight; }; Point ReturnStruct(Point pt) { return pt; } void FieldAccess() { Point pt; pt.x = 5; pt.y = pt.x; int* p = &pt.y; } void LogicalOr(bool a, bool b) { int x; if (a || b) { x = 7; } if (a || b) { x = 1; } else { x = 5; } } void LogicalAnd(bool a, bool b) { int x; if (a && b) { x = 7; } if (a && b) { x = 1; } else { x = 5; } } void LogicalNot(bool a, bool b) { int x; if (!a) { x = 1; } if (!(a && b)) { x = 2; } else { x = 3; } } void ConditionValues(bool a, bool b) { bool x; x = a && b; x = a || b; x = !(a || b); } void Conditional(bool a, int x, int y) { int z = a ? x : y; } void Conditional_LValue(bool a) { int x; int y; (a ? x : y) = 5; } void Conditional_Void(bool a) { a ? VoidFunc() : VoidFunc(); } void Nullptr() { int* p = nullptr; int* q = 0; p = nullptr; q = 0; } void InitList(int x, float f) { Point pt1 = { x, f }; Point pt2 = { x }; Point pt3 = {}; int x1 = { 1 }; int x2 = {}; } void NestedInitList(int x, float f) { Rect r1 = {}; Rect r2 = { { x, f } }; Rect r3 = { { x, f }, { x, f } }; Rect r4 = { { x }, { x } }; } void ArrayInit(int x, float f) { int a1[3] = {}; int a2[3] = { x, f, 0 }; int a3[3] = { x }; } union U { double d; int i; }; void UnionInit(int x, float f) { U u1 = { f }; // U u2 = {}; Waiting for fix } void EarlyReturn(int x, int y) { if (x < y) { return; } y = x; } int EarlyReturnValue(int x, int y) { if (x < y) { return x; } return x + y; } int CallViaFuncPtr(int (*pfn)(int)) { return pfn(5); } typedef enum { E_0, E_1 } E; int EnumSwitch(E e) { switch (e) { case E_0: return 0; case E_1: return 1; default: return -1; } } void InitArray() { char a_pad[32] = ""; char a_nopad[4] = "foo"; char a_infer[] = "blah"; char b[2]; char c[2] = {}; char d[2] = { 0 }; char e[2] = { 0, 1 }; char f[3] = { 0 }; } void VarArgFunction(const char* s, ...); void VarArgs() { VarArgFunction("%d %s", 1, "string"); } int FuncPtrTarget(int); void SetFuncPtr() { int (*pfn)(int) = FuncPtrTarget; pfn = &FuncPtrTarget; pfn = *FuncPtrTarget; pfn = ***&FuncPtrTarget; } struct String { String(); String(const String&); String(String&&); String(const char*); ~String(); String& operator=(const String&); String& operator=(String&&); const char* c_str() const; char pop_back(); private: const char* p; }; String ReturnObject(); void DeclareObject() { String s1; String s2("hello"); String s3 = ReturnObject(); String s4 = String("test"); } void CallMethods(String& r, String* p, String s) { r.c_str(); p->c_str(); s.c_str(); } class C { public: static int StaticMemberFunction(int x) { return x; } int InstanceMemberFunction(int x) { return x; } virtual int VirtualMemberFunction(int x) { return x; } void FieldAccess() { this->m_a = 0; (*this).m_a = 1; m_a = 2; int x; x = this->m_a; x = (*this).m_a; x = m_a; } void MethodCalls() { this->InstanceMemberFunction(0); (*this).InstanceMemberFunction(1); InstanceMemberFunction(2); } C() : m_a(1), m_c(3), m_e{}, m_f("test") { } private: int m_a; String m_b; char m_c; float m_d; void* m_e; String m_f; }; int DerefReference(int& r) { return r; } int& TakeReference() { return g; } String& ReturnReference(); void InitReference(int x) { int& r = x; int& r2 = r; const String& r3 = ReturnReference(); } void ArrayReferences() { int a[10]; int (&ra)[10] = a; int x = ra[5]; } void FunctionReferences() { int(&rfn)(int) = FuncPtrTarget; int(*pfn)(int) = rfn; rfn(5); } template T min(T x, T y) { return (x < y) ? x : y; } int CallMin(int x, int y) { return min(x, y); } template struct Outer { template static T Func(U x, V y) { return T(); } }; double CallNestedTemplateFunc() { return Outer::Func(nullptr, 'o'); } void TryCatch(bool b) { try { int x = 5; if (b) { throw "string literal"; } else if (x < 2) { x = b ? 7 : throw String("String object"); } x = 7; } catch (const char* s) { throw String(s); } catch (const String& e) { } catch (...) { throw; } } struct Base { String base_s; Base() { } ~Base() { } }; struct Middle : Base { String middle_s; Middle() { } ~Middle() { } }; struct Derived : Middle { String derived_s; Derived() { } ~Derived() { } }; struct MiddleVB1 : virtual Base { String middlevb1_s; MiddleVB1() { } ~MiddleVB1() { } }; struct MiddleVB2 : virtual Base { String middlevb2_s; MiddleVB2() { } ~MiddleVB2() { } }; struct DerivedVB : MiddleVB1, MiddleVB2 { String derivedvb_s; DerivedVB() { } ~DerivedVB() { } }; void HierarchyConversions() { Base b; Middle m; Derived d; Base* pb = &b; Middle* pm = &m; Derived* pd = &d; b = m; b = (Base)m; b = static_cast(m); pb = pm; pb = (Base*)pm; pb = static_cast(pm); pb = reinterpret_cast(pm); m = (Middle&)b; m = static_cast(b); pm = (Middle*)pb; pm = static_cast(pb); pm = reinterpret_cast(pb); b = d; b = (Base)d; b = static_cast(d); pb = pd; pb = (Base*)pd; pb = static_cast(pd); pb = reinterpret_cast(pd); d = (Derived&)b; d = static_cast(b); pd = (Derived*)pb; pd = static_cast(pb); pd = reinterpret_cast(pb); MiddleVB1* pmv = nullptr; DerivedVB* pdv = nullptr; pb = pmv; pb = pdv; } struct PolymorphicBase { virtual ~PolymorphicBase(); }; struct PolymorphicDerived : PolymorphicBase { }; void DynamicCast() { PolymorphicBase b; PolymorphicDerived d; PolymorphicBase* pb = &b; PolymorphicDerived* pd = &d; // These two casts are represented as BaseClassCasts because they can be resolved at compile time. pb = dynamic_cast(pd); PolymorphicBase& rb = dynamic_cast(d); pd = dynamic_cast(pb); PolymorphicDerived& rd = dynamic_cast(b); void* pv = dynamic_cast(pb); const void* pcv = dynamic_cast(pd); } String::String() : String("") { // Delegating constructor call } void ArrayConversions() { char a[5]; const char* p = a; p = "test"; p = &a[0]; p = &"test"[0]; char (&ra)[5] = a; const char (&rs)[5] = "test"; const char (*pa)[5] = &a; pa = &"test"; } void FuncPtrConversions(int(*pfn)(int), void* p) { p = (void*)pfn; pfn = (int(*)(int))p; } void VAListUsage(int x, __builtin_va_list args) { __builtin_va_list args2; __builtin_va_copy(args2, args); double d = __builtin_va_arg(args, double); float f = __builtin_va_arg(args, int); __builtin_va_end(args2); } void VarArgUsage(int x, ...) { __builtin_va_list args; __builtin_va_start(args, x); __builtin_va_list args2; __builtin_va_copy(args2, args); double d = __builtin_va_arg(args, double); float f = __builtin_va_arg(args, int); __builtin_va_end(args); VAListUsage(x, args2); __builtin_va_end(args2); } void CastToVoid(int x) { (void)x; } void ConstantConditions(int x) { bool a = true && true; int b = (true) ? x : x; } typedef unsigned long size_t; namespace std { enum class align_val_t : size_t {}; } void* operator new(size_t, float); void* operator new[](size_t, float); void* operator new(size_t, std::align_val_t, float); void* operator new[](size_t, std::align_val_t, float); void operator delete(void*, float); void operator delete[](void*, float); void operator delete(void*, std::align_val_t, float); void operator delete[](void*, std::align_val_t, float); struct SizedDealloc { char a[32]; void* operator new(size_t); void* operator new[](size_t); void operator delete(void*, size_t); void operator delete[](void*, size_t); }; struct alignas(128) Overaligned { char a[256]; }; struct DefaultCtorWithDefaultParam { DefaultCtorWithDefaultParam(double d = 1.0); }; void OperatorNew() { new int; // No constructor new(1.0f) int; // Placement new, no constructor new int(); // Zero-init new String(); // Constructor new(1.0f) String("hello"); // Placement new, constructor with args new Overaligned; // Aligned new new(1.0f) Overaligned(); // Placement aligned new with zero-init } void OperatorNewArray(int n) { new int[10]; // Constant size new int[n]; // No constructor new(1.0f) int[n]; // Placement new, no constructor new String[n]; // Constructor new Overaligned[n]; // Aligned new new(1.0f) Overaligned[10]; // Aligned placement new new DefaultCtorWithDefaultParam[n]; new int[n] { 0, 1, 2 }; } int designatedInit() { int a1[1000] = { [2] = 10002, [900] = 10900 }; return a1[900]; } void IfStmtWithDeclaration(int x, int y) { if (bool b = x < y) { x = 5; } else if (int z = x + y) { y = 7; } else if (int* p = &x) { *p = 2; } } void WhileStmtWithDeclaration(int x, int y) { while (bool b = x < y) { } while (int z = x + y) { } while (int* p = &x) { } } int PointerDecay(int a[], int fn(float)) { return a[0] + fn(1.0); } int StmtExpr(int b, int y, int z) { int x = ({ int w; if (b) { w = y; } else { w = z; } w; }); return ({x;}); } // TODO: `delete` gets translated to NoOp void OperatorDelete() { delete static_cast(nullptr); // No destructor delete static_cast(nullptr); // Non-virtual destructor, with size. delete static_cast(nullptr); // No destructor, with size. delete static_cast(nullptr); // No destructor, with size and alignment. delete static_cast(nullptr); // Virtual destructor } // TODO: `delete[]` gets translated to NoOp void OperatorDeleteArray() { delete[] static_cast(nullptr); // No destructor delete[] static_cast(nullptr); // Non-virtual destructor, with size. delete[] static_cast(nullptr); // No destructor, with size. delete[] static_cast(nullptr); // No destructor, with size and alignment. delete[] static_cast(nullptr); // Virtual destructor } struct EmptyStruct {}; void EmptyStructInit() { EmptyStruct s = {}; } auto lam = []() {}; void Lambda(int x, const String& s) { auto lambda_empty = [](float f) { return 'A'; }; lambda_empty(0); auto lambda_ref = [&](float f) { return s.c_str()[x]; }; lambda_ref(1); auto lambda_val = [=](float f) { return s.c_str()[x]; }; lambda_val(2); auto lambda_ref_explicit = [&s](float f) { return s.c_str()[0]; }; lambda_ref_explicit(3); auto lambda_val_explicit = [s](float f) { return s.c_str()[0]; }; lambda_val_explicit(4); auto lambda_mixed_explicit = [&s, x](float f) { return s.c_str()[x]; }; lambda_mixed_explicit(5); int r = x - 1; auto lambda_inits = [&s, x, i = x + 1, &j = r](float f) { return s.c_str()[x + i - j]; }; lambda_inits(6); } namespace std { template struct remove_const { typedef T type; }; template struct remove_const { typedef T type; }; // `remove_const_t` removes any `const` specifier from `T` template using remove_const_t = typename remove_const::type; struct ptrdiff_t; template struct iterator_traits; template struct iterator { typedef Category iterator_category; iterator(); iterator(iterator > const &other); // non-const -> const conversion constructor iterator &operator++(); iterator operator++(int); iterator &operator--(); iterator operator--(int); bool operator==(iterator other) const; bool operator!=(iterator other) const; reference_type operator*() const; pointer_type operator->() const; iterator operator+(int); iterator operator-(int); iterator &operator+=(int); iterator &operator-=(int); int operator-(iterator); reference_type operator[](int); }; struct input_iterator_tag {}; struct forward_iterator_tag : public input_iterator_tag {}; struct bidirectional_iterator_tag : public forward_iterator_tag {}; struct random_access_iterator_tag : public bidirectional_iterator_tag {}; struct output_iterator_tag {}; template struct vector { vector(T); ~vector(); using iterator = std::iterator; using const_iterator = std::iterator; iterator begin() const; iterator end() const; }; template bool operator==(typename vector::iterator left, typename vector::iterator right); template bool operator!=(typename vector::iterator left, typename vector::iterator right); } void RangeBasedFor(const std::vector& v) { for (int e : v) { if (e > 0) { continue; } } for (const int& e : v) { if (e < 5) { break; } } } #if 0 // Explicit capture of `this` requires possible extractor fixes. struct LambdaContainer { int x; void LambdaMember(const String& s) { auto lambda_implicit_this = [=](float f) { return s.c_str()[x]; }; lambda_implicit_this(1); auto lambda_explicit_this_byref = [this, &s](float f) { return s.c_str()[x]; }; lambda_explicit_this_byref(2); auto lambda_explicit_this_bycopy = [*this, &s](float f) { return s.c_str()[x]; }; lambda_explicit_this_bycopy(3); } }; #endif int AsmStmt(int x) { __asm__(""); return x; } static void AsmStmtWithOutputs(unsigned int& a, unsigned int b, unsigned int& c, unsigned int d) { __asm__ __volatile__ ( "cpuid\n\t" : "+a" (a), "+b" (b) : "c" (c), "d" (d) ); } void ExternDeclarations() { extern int g; int x; int y, f(float); int z(float), w(float), h; typedef double d; } #define EXTERNS_IN_MACRO \ extern int g; \ for (int i = 0; i < 10; ++i) { \ extern int g; \ } void ExternDeclarationsInMacro() { EXTERNS_IN_MACRO; } void TryCatchNoCatchAny(bool b) { try { int x = 5; if (b) { throw "string literal"; } else if (x < 2) { x = b ? 7 : throw String("String object"); } x = 7; } catch (const char* s) { throw String(s); } catch (const String& e) { } } #define vector(elcount, type) __attribute__((vector_size((elcount)*sizeof(type)))) type void VectorTypes(int i) { vector(4, int) vi4 = { 0, 1, 2, 3 }; int x = vi4[i]; vi4[i] = x; vector(4, int) vi4_shuffle = __builtin_shufflevector(vi4, vi4, 3+0, 2, 1, 0); vi4 = vi4 + vi4_shuffle; vi4 = vi4 && vi4_shuffle; vi4 = vi4 || vi4_shuffle; } void *memcpy(void *dst, void *src, int size); int ModeledCallTarget(int x) { int y; memcpy(&y, &x, sizeof(int)); return y; } String ReturnObjectImpl() { return String("foo"); } void switch1Case(int x) { int y = 0; switch(x) { case 1: y = 2; } int z = y; } void switch2Case_fallthrough(int x) { int y = 0; switch(x) { case 1: y = 2; case 2: y = 3; } int z = y; } void switch2Case(int x) { int y = 0; switch(x) { case 1: y = 2; break; case 2: y = 3; } int z = y; } void switch2Case_default(int x) { int y = 0; switch(x) { case 1: y = 2; break; case 2: y = 3; break; default: y = 4; } int z = y; } int staticLocalInit(int x) { static int a = 0; // Constant initialization static int b = sizeof(x); // Constant initialization static int c = x; // Dynamic initialization static int d; // Zero initialization return a + b + c + d; } void staticLocalWithConstructor(const char* dynamic) { static String a; static String b("static"); static String c(dynamic); } // --- strings --- char *strcpy(char *destination, const char *source); char *strcat(char *destination, const char *source); void test_strings(char *s1, char *s2) { char buffer[1024] = {0}; strcpy(buffer, s1); strcat(buffer, s2); } struct A { int member; static void static_member(A* a, int x) { a->member = x; } static void static_member_without_def(); }; A* getAnInstanceOfA(); void test_static_member_functions(int int_arg, A* a_arg) { C c; c.StaticMemberFunction(10); C::StaticMemberFunction(10); A a; a.static_member(&a, int_arg); A::static_member(&a, int_arg); (&a)->static_member(a_arg, int_arg + 2); (*a_arg).static_member(&a, 99); a_arg->static_member(a_arg, -1); a.static_member_without_def(); A::static_member_without_def(); getAnInstanceOfA()->static_member_without_def(); } int missingReturnValue(bool b, int x) { if (b) { return x; } } void returnVoid(int x, int y) { return IntegerOps(x, y); } void gccBinaryConditional(bool b, int x, long y) { int z = x; z = b ?: x; z = b ?: y; z = x ?: x; z = x ?: y; z = y ?: x; z = y ?: y; z = (x && b || y) ?: x; } bool predicateA(); bool predicateB(); int shortCircuitConditional(int x, int y) { return predicateA() && predicateB() ? x : y; } void *operator new(size_t, void *) noexcept; void f(int* p) { new (p) int; } template T defaultConstruct() { return T(); } class constructor_only { public: int x; public: constructor_only(int x); }; class copy_constructor { public: int y; public: copy_constructor(); copy_constructor(const copy_constructor&); void method(); }; class destructor_only { public: ~destructor_only(); void method(); }; template void acceptRef(const T& v); template void acceptValue(T v); template T returnValue(); void temporary_string() { String s = returnValue(); // No temporary const String& rs = returnValue(); // Binding a reference variable to a temporary acceptRef(s); // No temporary acceptRef("foo"); // Binding a const reference to a temporary acceptValue(s); acceptValue("foo"); String().c_str(); returnValue().c_str(); // Member access on a temporary defaultConstruct(); } void temporary_destructor_only() { destructor_only d = returnValue(); const destructor_only& rd = returnValue(); destructor_only d2; acceptRef(d); acceptValue(d); destructor_only().method(); returnValue().method(); defaultConstruct(); } void temporary_copy_constructor() { copy_constructor d = returnValue(); const copy_constructor& rd = returnValue(); copy_constructor d2; acceptRef(d); acceptValue(d); copy_constructor().method(); returnValue().method(); defaultConstruct(); int y = returnValue().y; } void temporary_point() { Point p = returnValue(); // No temporary const Point& rp = returnValue(); // Binding a reference variable to a temporary acceptRef(p); // No temporary acceptValue(p); Point().x; int y = returnValue().y; defaultConstruct(); } struct UnusualFields { int& r; float a[10]; }; void temporary_unusual_fields() { const int& rx = returnValue().r; int x = returnValue().r; const float& rf = returnValue().a[3]; float f = returnValue().a[5]; } struct POD_Base { int x; float f() const; }; struct POD_Middle : POD_Base { int y; }; struct POD_Derived : POD_Middle { int z; }; void temporary_hierarchy() { POD_Base b = returnValue(); b = (returnValue()); // Multiple conversions plus parens int x = returnValue().x; float f = (returnValue()).f(); } struct Inheritance_Test_B { ~Inheritance_Test_B() {} }; struct Inheritance_Test_A : public Inheritance_Test_B { int x; int y; Inheritance_Test_A() : x(42) { y = 3; } }; void array_structured_binding() { int xs[2] = {1, 2}; // structured binding use { auto& [x0, x1] = xs; x1 = 3; int &rx1 = x1; int x = x1; } // explicit reference version { auto& unnamed_local_variable = xs; auto& x0 = unnamed_local_variable[0]; auto& x1 = unnamed_local_variable[1]; x1 = 3; int &rx1 = x1; int x = x1; } } struct StructuredBindingDataMemberMemberStruct { int x = 5; }; struct StructuredBindingDataMemberStruct { typedef int ArrayType[2]; typedef int &RefType; int i = 1; double d = 2.0; unsigned int b : 3; int& r = i; int* p = &i; ArrayType xs = {1, 2}; RefType r_alt = i; StructuredBindingDataMemberMemberStruct m; }; void data_member_structured_binding() { StructuredBindingDataMemberStruct s; // structured binding use { auto [i, d, b, r, p, xs, r_alt, m] = s; d = 4.0; double& rd = d; int v = i; r = 5; *p = 6; int& rr = r; int* pr = &r; int w = r; } // explicit reference version { auto unnamed_local_variable = s; auto& i = unnamed_local_variable.i; auto& d = unnamed_local_variable.d; // no equivalent for b auto& r = unnamed_local_variable.r; auto& p = unnamed_local_variable.p; d = 4.0; double& rd = d; int v = i; r = 5; *p = 6; int& rr = r; int* pr = &r; int w = r; } } namespace std { template struct tuple_size; template struct tuple_element; } struct StructuredBindingTupleRefGet { int i = 1; double d = 2.2; int& r = i; template typename std::tuple_element::type& get(); }; template<> struct std::tuple_size { static const unsigned int value = 3; }; template<> struct std::tuple_element<0, StructuredBindingTupleRefGet> { using type = int; }; template<> struct std::tuple_element<1, StructuredBindingTupleRefGet> { using type = double; }; template<> struct std::tuple_element<2, StructuredBindingTupleRefGet> { using type = int&; }; template<> std::tuple_element<0, StructuredBindingTupleRefGet>::type& StructuredBindingTupleRefGet::get<0>() { return i; } template<> std::tuple_element<1, StructuredBindingTupleRefGet>::type& StructuredBindingTupleRefGet::get<1>() { return d; } template<> std::tuple_element<2, StructuredBindingTupleRefGet>::type& StructuredBindingTupleRefGet::get<2>() { return r; } void tuple_structured_binding_ref_get() { StructuredBindingTupleRefGet t; // structured binding use { auto [i, d, r] = t; d = 4.0; double& rd = d; int v = i; r = 5; int& rr = r; int w = r; } // explicit reference version { auto unnamed_local_variable = t; auto& i = unnamed_local_variable.get<0>(); auto& d = unnamed_local_variable.get<1>(); auto& r = unnamed_local_variable.get<2>(); d = 4.0; double& rd = d; int v = i; r = 5; int& rr = r; int w = r; } } struct StructuredBindingTupleNoRefGet { int i = 1; int& r = i; template typename std::tuple_element::type get(); }; template<> struct std::tuple_size { static const unsigned int value = 3; }; template<> struct std::tuple_element<0, StructuredBindingTupleNoRefGet> { using type = int; }; template<> struct std::tuple_element<1, StructuredBindingTupleNoRefGet> { using type = int&; }; template<> struct std::tuple_element<2, StructuredBindingTupleNoRefGet> { using type = int&&; }; template<> std::tuple_element<0, StructuredBindingTupleNoRefGet>::type StructuredBindingTupleNoRefGet::get<0>() { return i; } template<> std::tuple_element<1, StructuredBindingTupleNoRefGet>::type StructuredBindingTupleNoRefGet::get<1>() { return r; } template<> std::tuple_element<2, StructuredBindingTupleNoRefGet>::type StructuredBindingTupleNoRefGet::get<2>() { return 5; } void tuple_structured_binding_no_ref_get() { StructuredBindingTupleNoRefGet t; //structured binding use { auto&& [i, r, rv] = t; i = 4; int& ri = i; int v = i; r = 5; int& rr = r; int w = r; } // explicit reference version { auto&& unnamed_local_variable = t; auto&& i = unnamed_local_variable.get<0>(); auto& r = unnamed_local_variable.get<1>(); auto&& rv = unnamed_local_variable.get<2>(); i = 4; int& ri = i; int v = i; r = 5; int& rr = r; int w = r; } } void array_structured_binding_non_ref_init() { int xs[2] = {1, 2}; auto [x0, x1] = xs; } class CapturedLambdaMyObj { public: CapturedLambdaMyObj() {} }; void captured_lambda(int x, int &y, int &&z) { const auto &obj1 = CapturedLambdaMyObj(); auto obj2 = CapturedLambdaMyObj(); auto lambda_outer = [obj1, obj2, x, y, z](){ auto lambda_inner = [obj1, obj2, x, y, z](){;}; }; } int goto_on_same_line() { int x = 42; goto next; next: return x; } class TrivialLambdaClass { public: void m() const { auto l_m_outer = [*this] { m(); auto l_m_inner = [*this] { m(); }; }; }; }; void captured_lambda2(TrivialLambdaClass p1, TrivialLambdaClass &p2, TrivialLambdaClass &&p3) { const TrivialLambdaClass l1; const TrivialLambdaClass &l2 = TrivialLambdaClass(); auto l_outer1 = [p1, p2, p3, l1, l2] { auto l_inner1 = [p1] {}; }; } class CopyConstructorWithImplicitArgumentClass { int x; public: CopyConstructorWithImplicitArgumentClass() {} CopyConstructorWithImplicitArgumentClass(const CopyConstructorWithImplicitArgumentClass &c) { x = c.x; } }; class CopyConstructorWithBitwiseCopyClass { int y; public: CopyConstructorWithBitwiseCopyClass() {} }; class CopyConstructorTestNonVirtualClass : public CopyConstructorWithImplicitArgumentClass, public CopyConstructorWithBitwiseCopyClass { public: CopyConstructorTestNonVirtualClass() {} }; class CopyConstructorTestVirtualClass : public virtual CopyConstructorWithImplicitArgumentClass, public virtual CopyConstructorWithBitwiseCopyClass { public: CopyConstructorTestVirtualClass() {} }; int implicit_copy_constructor_test( const CopyConstructorTestNonVirtualClass &x, const CopyConstructorTestVirtualClass &y) { CopyConstructorTestNonVirtualClass cx = x; CopyConstructorTestVirtualClass cy = y; } void if_initialization(int x) { if (int y = x; x + 1) { x = x + y; } int w; if (w = x; x + 1) { x = x + w; } if (w = x; int w2 = w) { x = x + w; } if (int v = x; int v2 = v) { x = x + v; } int z = x; if (z) { x = x + z; } if (int z2 = z) { x += z2; } } void switch_initialization(int x) { switch (int y = x; x + 1) { default: x = x + y; } int w; switch (w = x; x + 1) { default: x = x + w; } switch (w = x; int w2 = w) { default: x = x + w; } switch (int v = x; int v2 = v) { default: x = x + v; } int z = x; switch (z) { default: x = x + z; } switch (int z2 = z) { default: x += z2; } } int global_1; int global_2 = 1; const int global_3 = 2; constructor_only global_4(1); constructor_only global_5 = constructor_only(2); char *global_string = "global string"; int global_6 = global_2; namespace block_assignment { class A { enum {} e[1]; virtual void f(); }; struct B : A { B(A *); }; void foo() { B v(0); v = 0; } } void magicvars() { const char *pf = __PRETTY_FUNCTION__; const char *strfunc = __func__; } namespace missing_declaration_entries { struct S {}; template struct pair{}; template struct Bar1 { typedef S* pointer; void* missing_type_decl_entry(pointer p) { typedef pair _Res; return p; } }; void test1() { Bar1 b; b.missing_type_decl_entry(nullptr); } template struct Bar2 { int two_missing_variable_declaration_entries() { int x[10], y[10]; *x = 10; *y = 10; return *x + *y; } }; void test2() { Bar2 b; b.two_missing_variable_declaration_entries(); } template struct Bar3 { int two_more_missing_variable_declaration_entries() { extern int g; int z(float); return g; } }; void test3() { Bar3 b; b.two_more_missing_variable_declaration_entries(); } } template T global_template = 42; int test_global_template_int() { int local_int = global_template; char local_char = global_template; return local_int + (int)local_char; } [[noreturn]] void noreturnFunc(); int noreturnTest(int x) { if (x < 10) { return x; } else { noreturnFunc(); } } int noreturnTest2(int x) { if (x < 10) { noreturnFunc(); } return x; } int static_function(int x) { return x; } void test_static_functions_with_assignments() { C c; int x; x = c.StaticMemberFunction(10); int y; y = C::StaticMemberFunction(10); int z; z = static_function(10); } void test_double_assign() { int i, j; i = j = 40; } void test_assign_with_assign_operation() { int i, j = 0; i = (j += 40); } class D { static D x; public: static D& ReferenceStaticMemberFunction() { return x; } static D ObjectStaticMemberFunction() { return x; } }; void test_static_member_functions_with_reference_return() { D d; d.ReferenceStaticMemberFunction(); D::ReferenceStaticMemberFunction(); d.ObjectStaticMemberFunction(); D::ObjectStaticMemberFunction(); D x; x = d.ReferenceStaticMemberFunction(); D y; y = D::ReferenceStaticMemberFunction(); D j; j = d.ObjectStaticMemberFunction(); D k; k = D::ObjectStaticMemberFunction(); } void test_volatile() { volatile int x; x; } struct ValCat { static ValCat& lvalue(); static ValCat&& xvalue(); static ValCat prvalue(); }; void value_category_test() { ValCat c; c.lvalue() = {}; c.xvalue() = {}; c.prvalue() = {}; ValCat::lvalue() = {}; ValCat::xvalue() = {}; ValCat::prvalue() = {}; } void SetStaticFuncPtr() { C c; int (*pfn)(int) = C::StaticMemberFunction; pfn = c.StaticMemberFunction; } void TernaryTestInt(bool a, int x, int y, int z) { z = a ? x : y; z = a ? x : 5; z = a ? 3 : 5; (a ? x : y) = 7; } struct TernaryPodObj { }; void TernaryTestPodObj(bool a, TernaryPodObj x, TernaryPodObj y, TernaryPodObj z) { z = a ? x : y; z = a ? x : TernaryPodObj(); z = a ? TernaryPodObj() : TernaryPodObj(); (z = a ? x : y) = TernaryPodObj(); } struct TernaryNonPodObj { virtual ~TernaryNonPodObj() {} }; void TernaryTestNonPodObj(bool a, TernaryNonPodObj x, TernaryNonPodObj y, TernaryNonPodObj z) { z = a ? x : y; z = a ? x : TernaryNonPodObj(); z = a ? TernaryNonPodObj() : TernaryNonPodObj(); (z = a ? x : y) = TernaryNonPodObj(); } void CommaTestHelper(unsigned int); unsigned int CommaTest(unsigned int x) { unsigned int y; y = x < 100 ? (CommaTestHelper(x), x) : (CommaTestHelper(x), 10); } void NewDeleteMem() { int* x = new int; // No constructor *x = 6; delete x; } class Base2 { public: void operator delete(void* p) { } virtual ~Base2() {}; }; class Derived2 : public Base2 { int i; public: ~Derived2() {}; void operator delete(void* p) { } }; // Delete is kind-of virtual in these cases int virtual_delete() { Base2* b1 = new Base2{}; delete b1; Base2* b2 = new Derived2{}; delete b2; Derived2* d = new Derived2{}; delete d; } void test_constant_folding_use(int); void test_constant_folding() { const int x = 116; test_constant_folding_use(x); } void exit(int code); int NonExit() { int x = Add(3,4); if (x == 7) exit(3); VoidFunc(); return x; } void CallsNonExit() { VoidFunc(); exit(3); } int TransNonExit() { int x = Add(3,4); if (x == 7) CallsNonExit(); VoidFunc(); return x; } void newArrayCorrectType(size_t n) { new int[n]; // No constructor new(1.0f) int[n]; // Placement new, no constructor new String[n]; // Constructor new Overaligned[n]; // Aligned new new DefaultCtorWithDefaultParam[n]; new int[n] { 0, 1, 2 }; } double strtod (const char* str, char** endptr); char* test_strtod(char *s) { char *end; double d = strtod(s, &end); return end; } struct HasOperatorBool { operator bool(); }; void call_as_child_of_ConditionDeclExpr() { if(HasOperatorBool b = HasOperatorBool()) {} } class ClassWithDestructor { char *x; public: ClassWithDestructor() { x = new char; } ~ClassWithDestructor() { delete x; } void set_x(char y) { *x = y; } char get_x() { return *x; } operator bool() const; }; constexpr bool initialization_with_destructor_bool = true; void initialization_with_destructor(bool b, char c) { if (ClassWithDestructor x; b) x.set_x('a'); if constexpr (ClassWithDestructor x; initialization_with_destructor_bool) x.set_x('a'); switch(ClassWithDestructor x; c) { case 'a': x.set_x('a'); break; default: x.set_x('b'); break; } ClassWithDestructor x; for(std::vector ys(x); ClassWithDestructor y : ys) y.set_x('a'); for(std::vector ys(x); ClassWithDestructor y : ys) { y.set_x('a'); if (y.get_x() == 'b') return; } for(std::vector ys(1); int y : ys) { if (y == 1) return; } for(std::vector ys(x); ClassWithDestructor y : ys) { ClassWithDestructor z1; ClassWithDestructor z2; } } void static_variable_with_destructor_1() { ClassWithDestructor a; static ClassWithDestructor b; } void static_variable_with_destructor_2() { static ClassWithDestructor a; ClassWithDestructor b; } void static_variable_with_destructor_3() { ClassWithDestructor a; ClassWithDestructor b; static ClassWithDestructor c; } static ClassWithDestructor global_class_with_destructor; namespace vacuous_destructor_call { template T& get(T& t) { return t; } template void call_destructor(T& t) { get(t).~T(); } void non_vacuous_destructor_call() { ClassWithDestructor c; call_destructor(c); } void vacuous_destructor_call() { int i; call_destructor(i); } } void TryCatchDestructors(bool b) { try { String s; if (b) { throw "string literal"; } String s2; } catch (const char* s) { throw String(s); } catch (const String& e) { } catch (...) { throw; } } void IfDestructors(bool b) { String s1; if(b) { String s2; } else { String s3; } String s4; } void ForDestructors() { char c = 'a'; for(String s("hello"); c != 0; c = s.pop_back()) { String s2; } for(String s : std::vector(String("hello"))) { String s2; } for(String s("hello"), s2("world"); c != 0; c = s.pop_back()) { c = 0; } } void IfDestructors2(bool b) { if(String s = String("hello"); b) { int x = 0; } else { int y = 0; } } class Bool { public: Bool(bool b_); operator bool(); ~Bool(); }; void IfDestructors3(bool b) { if(Bool B = Bool(b)) { String s1; } else { String s2; } } void WhileLoopDestructors(bool b) { { String s; while(b) { b = false; } } { while (Bool B = Bool(b)) { b = false; } } } void VoidFunc() {} void IfReturnDestructors(bool b) { String s; if(b) { return; } if(b) { return VoidFunc(); } s; } int IfReturnDestructors3(bool b) { String s; if(b) { return 1; } return 0; } void VoidReturnDestructors() { String s; return VoidFunc(); } namespace return_routine_type { struct HasVoidToIntFunc { void VoidToInt(int); }; typedef void (HasVoidToIntFunc::*VoidToIntMemberFunc)(int); static VoidToIntMemberFunc GetVoidToIntFunc() { return &HasVoidToIntFunc::VoidToInt; } } int small_operation_should_not_be_constant_folded() { return 1 ^ 2; } #define BINOP2(x) (x ^ x) #define BINOP4(x) (BINOP2(x) ^ BINOP2(x)) #define BINOP8(x) (BINOP4(x) ^ BINOP4(x)) #define BINOP16(x) (BINOP8(x) ^ BINOP8(x)) #define BINOP32(x) (BINOP16(x) ^ BINOP16(x)) #define BINOP64(x) (BINOP32(x) ^ BINOP32(x)) int large_operation_should_be_constant_folded() { return BINOP64(1); } void initialization_with_temp_destructor() { if (char x = ClassWithDestructor().get_x()) x++; if (char x = ClassWithDestructor().get_x(); x) x++; if constexpr (char x = ClassWithDestructor().get_x(); initialization_with_destructor_bool) x++; switch(char x = ClassWithDestructor().get_x()) { case 'a': x++; } switch(char x = ClassWithDestructor().get_x(); x) { case 'a': x++; } for(char x = ClassWithDestructor().get_x(); char y : std::vector(x)) y += x; } void param_with_destructor_by_value(ClassWithDestructor c) { // The call to ~ClassWithDestructor::ClassWithDestructor() happens on the side of the caller } void param_with_destructor_by_pointer(ClassWithDestructor* c) { // No destructor call should be here } void param_with_destructor_by_ref(ClassWithDestructor& c) { // No destructor call should be here } void param_with_destructor_by_rref(ClassWithDestructor&& c) { // No destructor call should be here } void rethrow_with_destruction(int x) { ClassWithDestructor c; throw; } struct ByValueConstructor { ByValueConstructor(ClassWithDestructor); }; void new_with_destructor(ClassWithDestructor a) { ByValueConstructor* b = new ByValueConstructor(a); } namespace rvalue_conversion_with_destructor { struct A { unsigned a; }; struct B { ~B(); inline A *operator->() const; }; B get(); void test() { auto a = get()->a; } } void destructor_without_block(bool b) { if (b) ClassWithDestructor c; if (b) ClassWithDestructor d; else ClassWithDestructor e; while (b) ClassWithDestructor f; for(int i = 0; i < 42; ++i) ClassWithDestructor g; } void destruction_in_switch_1(int c) { switch (c) { case 0: { ClassWithDestructor x; break; } } } void destruction_in_switch_2(int c) { switch (ClassWithDestructor y; c) { case 0: { break; } default: { break; } } } void destruction_in_switch_3(int c) { switch (ClassWithDestructor y; c) { case 0: { ClassWithDestructor x; break; } default: { break; } } } void destructor_possibly_not_handled() { ClassWithDestructor x; try { throw 42; } catch(char) { } } ClassWithDestructor getClassWithDestructor(); void this_inconsistency(bool b) { if (const ClassWithDestructor& a = getClassWithDestructor()) ; } void constexpr_inconsistency(bool b) { if constexpr (const ClassWithDestructor& a = getClassWithDestructor(); initialization_with_destructor_bool) ; } void builtin_bitcast(unsigned long ul) { double d = __builtin_bit_cast(double, ul); } void p_points_to_x_or_y(int a, int b) { int x; int y; int* p; if (a < b) { p = &x; } else { p = &y; } *p = 5; int z = x; int w = y; } int phi_after_while() { int r; int *rP = &r; while(predicateA()) { int s = 0; *rP = s; rP = &s; } return r; } // This testcase will loop infinitely if the analysis attempts to propagate // phi inputs with a non-unknown bit offset. char *recursive_conditional_call_with_increment(char *d, bool b) { if (b) { d = recursive_conditional_call_with_increment(d, b); } d++; return d; } struct Recursive { Recursive *next; }; static Recursive *merge(Recursive *a) { Recursive *b; Recursive **p = &b; while (predicateA()) { *p = a; p = &a->next; } return b; } void use_const_int(const int*); void escaping_pointer(bool b) { int *data; int l1, l2; if (b) { data = &l1; } else { data = &l2; } use_const_int(data); } using int64_t = long long; #define NULL ((void *)0) void *malloc(unsigned long); void use_const_void_pointer(const void *); static void needs_chi_for_initialize_groups() { if (predicateA()) { int64_t *data = (int64_t *)malloc(100); if (data != NULL) { data = (int64_t *)malloc(100); } use_const_void_pointer(data); } else { int64_t *data = (int64_t *)malloc(100); if (data != NULL) { data = (int64_t *)malloc(200); } use_const_void_pointer(data); } } void use_int(int); static void phi_with_single_input_at_merge(bool b) { int *data = nullptr; if(b) { int intBuffer = 8; data = &intBuffer; } use_int(*data); } void use(const char *fmt); #define call_use(format) use(format) #define twice_call_use(format) \ do \ { \ call_use(format); \ call_use(format); \ } while (0) void test(bool b) { twice_call_use(b ? "" : ""); } namespace concepts { int requires_use() { int y = requires { sizeof(int) > 0; }; return y; } } void branch_on_integral_in_cpp(int x1, int x2) { if (x1) {} if(!x1) {} int y = !x1; if(y) {} if(!y) {} if(x1 && x2) {} if(!x1 && x2) {} if(x1 && !x2) {} if(!x1 && !x2) {} if(x1 || x2) {} if(!x1 || x2) {} if(x1 || !x2) {} if(!x1 || !x2) {} int x_1_and_2 = x1 && x2; if(x_1_and_2) {} if(!x_1_and_2) {} } struct WithBracketOperator { const char& operator[](int pos) const; }; char UseBracketOperator(const WithBracketOperator x, int i) { return x[i]; } void test_postfix_crement(int *p, int q) { p++; q++; (p++); (q++); (void)(p++); (void)(q++); (void)p++; (void)q++; int *p1 = p++; int q1 = q++; (int*)(p++); (int)(q++); int *p2 = (int*)(p++); int q2 = (int)(q++); } namespace std { enum class _Order : signed char { __less = -1, __equiv = 0, __greater = 1 }; class strong_ordering { explicit constexpr strong_ordering(_Order v) {} public: static const strong_ordering less; static const strong_ordering equal; static const strong_ordering equivalent; static const strong_ordering greater; }; inline constexpr strong_ordering strong_ordering::less(_Order::__less); inline constexpr strong_ordering strong_ordering::equal(_Order::__equiv); inline constexpr strong_ordering strong_ordering::equivalent(_Order::__equiv); inline constexpr strong_ordering strong_ordering::greater(_Order::__greater); } class ThreeWay { int x; public: std::strong_ordering operator<=>(ThreeWay &y) { return this->x <=> y.x; } }; void test_three_way(int a, int b, ThreeWay c, ThreeWay d) { auto x = a <=> b; auto y = c <=> d; } void test_allocation_with_initializer() { int* p1 = new int(42); long* p2 = new long(42); } void vla_sizeof_test(int len1, size_t len2, char len3) { char tmp1[len1]; size_t x = sizeof(tmp1); int tmp2[len1][len2]; size_t y = sizeof(tmp2); size_t z = sizeof(*tmp2); int tmp3[len1][len2][len3]; size_t w = sizeof(tmp3); size_t v = sizeof(*tmp3); size_t u = sizeof(**tmp3); size_t t = sizeof(***tmp3); } void vla_sizeof_test2(int len1, size_t len2, char len3) { int tmp1[len1][len2]; size_t z = sizeof(tmp1[1]); int tmp2[len1][len2][len3]; size_t v = sizeof(tmp2[1]); size_t u = sizeof(tmp2[1][2]); size_t t = sizeof(tmp2[1][2][3]); } size_t vla_sizeof_test3(int len1, size_t len2, char len3, bool b) { typedef long arr[len1][len2]; typedef arr arr2; typedef arr2 arr3[len3]; if (b) { arr3 tmp; return sizeof(tmp[1]); } return 0; } void vla_sizeof_test4(int len1, size_t len2) { int tmp1[len1][len2]; size_t z = sizeof(1[tmp1]); } void vla_sizeof_test5(int len1, size_t len2) { int tmp1[len1][len2]; size_t z = sizeof((*&tmp1)[1]); } // Common definitions for assertions in release builds #define assert(x) ((void)0) #define __analysis_assume(x) void test_assert_simple(int x, int y, unsigned u, int shadowed) { assert(x > 0); // $ var=2830:x assert(0 < x); // $ var=2830:x assert(x < y); // $ var=2830:x var=2830:y __analysis_assume(x != 2); // $ var=2830:x assert(u < x); // $ var=2830:u var=2830:x { int shadowed = x; assert(shadowed > 0); // no assertion generated since the variable is shadowed } } template void test_assert_in_template(T x, int y, unsigned u) { assert(x > 0); // $ var=2846:x assert(0 < x); // $ var=2846:x assert(x < y); // $ var=2846:x var=2846:y __analysis_assume(x != 2); // $ var=2846:x assert(u < x); // $ var=2846:u var=2846:x { int shadowed = x; assert(shadowed > 0); // $ var=2856:shadowed } assert(x> 0); // $ var=2846:x } template void test_assert_in_template(int, int, unsigned); template void test_assert_in_template(short, int, unsigned); namespace { int shadowed; void complex_assertions(int x, bool b, int max) { int y = (assert(x > 0), x); // no assertion generated int z = b ? (assert(x != 0), 0) : 1; // no assertion generated try { throw 41; } catch (int c) { assert(c < 42); // $ var=2873:c assert(shadowed < 42); // no assertion generated } assert(shadowed > 0); // no assertion generated int shadowed; try { throw 41; } catch (int shadowed) { assert(shadowed < 42); // no assertion generated } } } struct StructInit { int i = 42; int j = 42; int k = 42; int l = k; int m = get_val(); int n = 42; StructInit(int j) : j(j), n(get_val()) {} StructInit() : i(41), k(41) {} int get_val() { return k; } }; template struct StructInitFromTemplate { T t = T(); }; StructInitFromTemplate StructInitFromTemplateVar; template constexpr T VariableTemplate = T(42); template T VariableTemplateFunc(T x) { return VariableTemplate + x; } int VariableTemplateFuncUse = VariableTemplateFunc(2.3); // semmle-extractor-options: -std=c++20 --clang