// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++14 -verify %s // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple i686 -verify %s // RUN: %clang_cc1 -verify=ref %s // RUN: %clang_cc1 -verify=ref -std=c++14 %s // RUN: %clang_cc1 -verify=ref -triple i686 %s struct BoolPair { bool first; bool second; }; struct Ints { int a = 20; int b = 30; bool c = true; BoolPair bp = {true, false}; int numbers[3] = {1,2,3}; static const int five = 5; static constexpr int getFive() { return five; } constexpr int getTen() const { return 10; } }; static_assert(Ints::getFive() == 5, ""); constexpr Ints ints; static_assert(ints.a == 20, ""); static_assert(ints.b == 30, ""); static_assert(ints.c, ""); static_assert(ints.getTen() == 10, ""); static_assert(ints.numbers[0] == 1, ""); static_assert(ints.numbers[1] == 2, ""); static_assert(ints.numbers[2] == 3, ""); constexpr const BoolPair &BP = ints.bp; static_assert(BP.first, ""); static_assert(!BP.second, ""); static_assert(ints.bp.first, ""); static_assert(!ints.bp.second, ""); constexpr Ints ints2{-20, -30, false}; static_assert(ints2.a == -20, ""); static_assert(ints2.b == -30, ""); static_assert(!ints2.c, ""); constexpr Ints getInts() { return {64, 128, true}; } constexpr Ints ints3 = getInts(); static_assert(ints3.a == 64, ""); static_assert(ints3.b == 128, ""); static_assert(ints3.c, ""); constexpr Ints ints4 = { .a = 40 * 50, .b = 0, .c = (ints.a > 0), }; static_assert(ints4.a == (40 * 50), ""); static_assert(ints4.b == 0, ""); static_assert(ints4.c, ""); static_assert(ints4.numbers[0] == 1, ""); static_assert(ints4.numbers[1] == 2, ""); static_assert(ints4.numbers[2] == 3, ""); constexpr Ints ints5 = ints4; static_assert(ints5.a == (40 * 50), ""); static_assert(ints5.b == 0, ""); static_assert(ints5.c, ""); static_assert(ints5.numbers[0] == 1, ""); static_assert(ints5.numbers[1] == 2, ""); static_assert(ints5.numbers[2] == 3, ""); struct Ints2 { int a = 10; int b; }; constexpr Ints2 ints22; // expected-error {{without a user-provided default constructor}} \ // expected-error {{must be initialized by a constant expression}} \ // ref-error {{without a user-provided default constructor}} constexpr Ints2 I2 = Ints2{12, 25}; static_assert(I2.a == 12, ""); static_assert(I2.b == 25, ""); class C { public: int a; int b; constexpr C() : a(100), b(200) {} constexpr C get() const { return *this; } }; constexpr C c; static_assert(c.a == 100, ""); static_assert(c.b == 200, ""); constexpr C c2 = C().get(); static_assert(c.a == 100, ""); static_assert(c.b == 200, ""); constexpr int getB() { C c; int &j = c.b; j = j * 2; return c.b; } static_assert(getB() == 400, ""); constexpr int getA(const C &c) { return c.a; } static_assert(getA(c) == 100, ""); constexpr const C* getPointer() { return &c; } static_assert(getPointer()->a == 100, ""); constexpr C RVOAndParams(const C *c) { return C(); } constexpr C RVOAndParamsResult = RVOAndParams(&c); /// Parameter and return value have different types. constexpr C RVOAndParams(int a) { return C(); } constexpr C RVOAndParamsResult2 = RVOAndParams(12); class Bar { // expected-note {{definition of 'Bar' is not complete}} \ // ref-note {{definition of 'Bar' is not complete}} public: constexpr Bar(){} constexpr Bar b; // expected-error {{cannot be constexpr}} \ // expected-error {{has incomplete type 'const Bar'}} \ // ref-error {{cannot be constexpr}} \ // ref-error {{has incomplete type 'const Bar'}} }; constexpr Bar B; // expected-error {{must be initialized by a constant expression}} \ // expected-error {{failed to evaluate an expression}} \ // ref-error {{must be initialized by a constant expression}} constexpr Bar *pb = nullptr; constexpr int locals() { C c; c.a = 10; // Assignment, not an initializer. c = C(); c.a = 10; // Assignment, not an initializer. c = RVOAndParams(&c); return c.a; } static_assert(locals() == 100, ""); namespace thisPointer { struct S { constexpr int get12() { return 12; } }; constexpr int foo() { // ref-error {{never produces a constant expression}} \ // expected-error {{never produces a constant expression}} S *s = nullptr; return s->get12(); // ref-note 2{{member call on dereferenced null pointer}} \ // expected-note 2{{member call on dereferenced null pointer}} } static_assert(foo() == 12, ""); // ref-error {{not an integral constant expression}} \ // ref-note {{in call to 'foo()'}} \ // expected-error {{not an integral constant expression}} \ // expected-note {{in call to 'foo()'}} }; struct FourBoolPairs { BoolPair v[4] = { {false, false}, {false, true}, {true, false}, {true, true }, }; }; // Init constexpr FourBoolPairs LT; // Copy ctor constexpr FourBoolPairs LT2 = LT; static_assert(LT2.v[0].first == false, ""); static_assert(LT2.v[0].second == false, ""); static_assert(LT2.v[2].first == true, ""); static_assert(LT2.v[2].second == false, ""); class Base { public: int i; constexpr Base() : i(10) {} constexpr Base(int i) : i(i) {} }; class A : public Base { public: constexpr A() : Base(100) {} constexpr A(int a) : Base(a) {} }; constexpr A a{}; static_assert(a.i == 100, ""); constexpr A a2{12}; static_assert(a2.i == 12, ""); static_assert(a2.i == 200, ""); // ref-error {{static assertion failed}} \ // ref-note {{evaluates to '12 == 200'}} \ // expected-error {{static assertion failed}} \ // expected-note {{evaluates to '12 == 200'}} struct S { int a = 0; constexpr int get5() const { return 5; } constexpr void fo() const { this; // expected-warning {{expression result unused}} \ // ref-warning {{expression result unused}} this->a; // expected-warning {{expression result unused}} \ // ref-warning {{expression result unused}} get5(); getInts(); } constexpr int m() const { fo(); return 1; } }; constexpr S s; static_assert(s.m() == 1, ""); namespace InitializerTemporaries { class Bar { private: int a; public: constexpr Bar() : a(10) {} constexpr int getA() const { return a; } }; class Foo { public: int a; constexpr Foo() : a(Bar().getA()) {} }; constexpr Foo F; static_assert(F.a == 10, ""); /// Needs constexpr destructors. #if __cplusplus >= 202002L /// Does /// Arr[Pos] = Value; /// ++Pos; /// in its destructor. class BitSetter { private: int *Arr; int &Pos; int Value; public: constexpr BitSetter(int *Arr, int &Pos, int Value) : Arr(Arr), Pos(Pos), Value(Value) {} constexpr int getValue() const { return 0; } constexpr ~BitSetter() { Arr[Pos] = Value; ++Pos; } }; class Test { int a, b, c; public: constexpr Test(int *Arr, int &Pos) : a(BitSetter(Arr, Pos, 1).getValue()), b(BitSetter(Arr, Pos, 2).getValue()), c(BitSetter(Arr, Pos, 3).getValue()) {} }; constexpr int T(int Index) { int Arr[] = {0, 0, 0}; int Pos = 0; { auto T = Test(Arr, Pos); // End of scope, should destroy Test. } return Arr[Index]; } static_assert(T(0) == 1); static_assert(T(1) == 2); static_assert(T(2) == 3); #endif } #if __cplusplus >= 201703L namespace BaseInit { class _A {public: int a;}; class _B : public _A {}; class _C : public _B {}; constexpr _C c{12}; constexpr const _B &b = c; static_assert(b.a == 12); class A {public: int a;}; class B : public A {}; class C : public A {}; class D : public B, public C {}; // This initializes D::B::A::a and not D::C::A::a. constexpr D d{12}; static_assert(d.B::a == 12); static_assert(d.C::a == 0); }; #endif namespace MI { class A { public: int a; constexpr A(int a) : a(a) {} }; class B { public: int b; constexpr B(int b) : b(b) {} }; class C : public A, public B { public: constexpr C() : A(10), B(20) {} }; constexpr C c = {}; static_assert(c.a == 10, ""); static_assert(c.b == 20, ""); constexpr const A *aPointer = &c; constexpr const B *bPointer = &c; class D : private A, private B { public: constexpr D() : A(20), B(30) {} constexpr int getA() const { return a; } constexpr int getB() const { return b; } }; constexpr D d = {}; static_assert(d.getA() == 20, ""); static_assert(d.getB() == 30, ""); }; namespace DeriveFailures { struct Base { // ref-note 2{{declared here}} expected-note {{declared here}} int Val; }; struct Derived : Base { int OtherVal; constexpr Derived(int i) : OtherVal(i) {} // ref-error {{never produces a constant expression}} \ // ref-note 2{{non-constexpr constructor 'Base' cannot be used in a constant expression}} \ // expected-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}} }; constexpr Derived D(12); // ref-error {{must be initialized by a constant expression}} \ // ref-note {{in call to 'Derived(12)'}} \ // ref-note {{declared here}} \ // expected-error {{must be initialized by a constant expression}} \ // expected-note {{in call to 'Derived(12)'}} static_assert(D.Val == 0, ""); // ref-error {{not an integral constant expression}} \ // ref-note {{initializer of 'D' is not a constant expression}} \ // expected-error {{not an integral constant expression}} \ // expected-note {{read of object outside its lifetime}} struct AnotherBase { int Val; constexpr AnotherBase(int i) : Val(12 / i) {} //ref-note {{division by zero}} \ //expected-note {{division by zero}} }; struct AnotherDerived : AnotherBase { constexpr AnotherDerived(int i) : AnotherBase(i) {} }; constexpr AnotherBase Derp(0); // ref-error {{must be initialized by a constant expression}} \ // ref-note {{in call to 'AnotherBase(0)'}} \ // expected-error {{must be initialized by a constant expression}} \ // expected-note {{in call to 'AnotherBase(0)'}} struct YetAnotherBase { int Val; constexpr YetAnotherBase(int i) : Val(i) {} }; struct YetAnotherDerived : YetAnotherBase { using YetAnotherBase::YetAnotherBase; // ref-note {{declared here}} \ // expected-note {{declared here}} int OtherVal; constexpr bool doit() const { return Val == OtherVal; } }; constexpr YetAnotherDerived Oops(0); // ref-error {{must be initialized by a constant expression}} \ // ref-note {{constructor inherited from base class 'YetAnotherBase' cannot be used in a constant expression}} \ // expected-error {{must be initialized by a constant expression}} \ // expected-note {{constructor inherited from base class 'YetAnotherBase' cannot be used in a constant expression}} }; namespace EmptyCtor { struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); }; namespace ConditionalInit { struct S { int a; }; constexpr S getS(bool b) { return b ? S{12} : S{13}; } static_assert(getS(true).a == 12, ""); static_assert(getS(false).a == 13, ""); }; /// FIXME: The following tests are broken. /// They are using CXXDefaultInitExprs which contain a CXXThisExpr. The This pointer /// in those refers to the declaration we are currently initializing, *not* the /// This pointer of the current stack frame. This is something we haven't /// implemented in the new interpreter yet. namespace DeclRefs { struct A{ int m; const int &f = m; }; // expected-note {{implicit use of 'this'}} constexpr A a{10}; // expected-error {{must be initialized by a constant expression}} static_assert(a.m == 10, ""); static_assert(a.f == 10, ""); // expected-error {{not an integral constant expression}} \ // expected-note {{read of object outside its lifetime}} class Foo { public: int z = 1337; constexpr int a() const { A b{this->z}; return b.f; } }; constexpr Foo f; static_assert(f.a() == 1337, ""); struct B { A a = A{100}; }; constexpr B b; /// FIXME: The following two lines don't work because we don't get the /// pointers on the LHS correct. They make us run into an assertion /// in CheckEvaluationResult. However, this may just be caused by the /// problems in the previous examples. //static_assert(b.a.m == 100, ""); //static_assert(b.a.f == 100, ""); }