// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++14 -verify=expected,both %s
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=expected,both %s
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -triple i686 -verify=expected,both %s
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++20 -verify=expected,both %s
// RUN: %clang_cc1 -verify=ref,both -std=c++14 %s
// RUN: %clang_cc1 -verify=ref,both -std=c++17 %s
// RUN: %clang_cc1 -verify=ref,both -std=c++17 -triple i686 %s
// RUN: %clang_cc1 -verify=ref,both -std=c++20 %s
/// Used to crash.
struct Empty {};
constexpr Empty e = {Empty()};
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; // both-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(c2.a == 100, "");
static_assert(c2.b == 200, "");
/// A global, composite temporary variable.
constexpr const C &c3 = C().get();
/// Same, but with a bitfield.
class D {
public:
unsigned a : 4;
constexpr D() : a(15) {}
constexpr D get() const {
return *this;
}
};
constexpr const D &d4 = D().get();
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 { // both-note {{definition of 'Bar' is not complete}}
public:
constexpr Bar(){}
constexpr Bar b; // both-error {{cannot be constexpr}} \
// both-error {{has incomplete type 'const Bar'}}
};
constexpr Bar B; // both-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() { // both-error {{never produces a constant expression}}
S *s = nullptr;
return s->get12(); // both-note 2{{member call on dereferenced null pointer}}
}
static_assert(foo() == 12, ""); // both-error {{not an integral constant expression}} \
// both-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, ""); // both-error {{static assertion failed}} \
// both-note {{evaluates to '12 == 200'}}
struct S {
int a = 0;
constexpr int get5() const { return 5; }
constexpr void fo() const {
this; // both-warning {{expression result unused}}
this->a; // both-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;
{
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);
// Invalid destructor.
struct S {
constexpr S() {}
constexpr ~S() noexcept(false) { throw 12; } // both-error {{cannot use 'throw'}} \
// both-error {{never produces a constant expression}} \
// both-note 2{{subexpression not valid}}
};
constexpr int f() {
S{}; // both-note {{in call to 'S{}.~S()'}}
return 12;
}
static_assert(f() == 12); // both-error {{not an integral constant expression}} \
// both-note {{in call to 'f()'}}
#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 {
#if __cplusplus < 202002L
struct Base { // both-note {{declared here}} \
// ref-note {{declared here}}
int Val;
};
struct Derived : Base {
int OtherVal;
constexpr Derived(int i) : OtherVal(i) {} // ref-error {{never produces a constant expression}} \
// both-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}} \
// ref-note {{non-constexpr constructor 'Base' cannot be used in a constant expression}}
};
constexpr Derived D(12); // both-error {{must be initialized by a constant expression}} \
// both-note {{in call to 'Derived(12)'}} \
// both-note {{declared here}}
static_assert(D.Val == 0, ""); // both-error {{not an integral constant expression}} \
// both-note {{initializer of 'D' is not a constant expression}}
#endif
struct AnotherBase {
int Val;
constexpr AnotherBase(int i) : Val(12 / i) {} // both-note {{division by zero}}
};
struct AnotherDerived : AnotherBase {
constexpr AnotherDerived(int i) : AnotherBase(i) {}
};
constexpr AnotherBase Derp(0); // both-error {{must be initialized by a constant expression}} \
// both-note {{in call to 'AnotherBase(0)'}}
struct YetAnotherBase {
int Val;
constexpr YetAnotherBase(int i) : Val(i) {}
};
struct YetAnotherDerived : YetAnotherBase {
using YetAnotherBase::YetAnotherBase; // both-note {{declared here}}
int OtherVal;
constexpr bool doit() const { return Val == OtherVal; }
};
constexpr YetAnotherDerived Oops(0); // both-error {{must be initialized by a constant expression}} \
// both-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, "");
};
namespace DeclRefs {
struct A{ int m; const int &f = m; };
constexpr A a{10};
static_assert(a.m == 10, "");
static_assert(a.f == 10, "");
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;
static_assert(b.a.m == 100, "");
static_assert(b.a.f == 100, "");
constexpr B b2{};
static_assert(b2.a.m == 100, "");
static_assert(b2.a.f == 100, "");
static_assert(b2.a.f == 101, ""); // both-error {{failed}} \
// both-note {{evaluates to '100 == 101'}}
}
namespace PointerArith {
struct A {};
struct B : A { int n; };
B b = {};
constexpr A *a1 = &b;
constexpr B *b1 = &b + 1;
constexpr B *b2 = &b + 0;
constexpr A *a2 = &b + 1; // both-error {{must be initialized by a constant expression}} \
// both-note {{cannot access base class of pointer past the end of object}}
constexpr const int *pn = &(&b + 1)->n; // both-error {{must be initialized by a constant expression}} \
// both-note {{cannot access field of pointer past the end of object}}
}
#if __cplusplus >= 202002L
namespace VirtualCalls {
namespace Obvious {
class A {
public:
constexpr A(){}
constexpr virtual int foo() {
return 3;
}
};
class B : public A {
public:
constexpr int foo() override {
return 6;
}
};
constexpr int getFooB(bool b) {
A *a;
A myA;
B myB;
if (b)
a = &myA;
else
a = &myB;
return a->foo();
}
static_assert(getFooB(true) == 3, "");
static_assert(getFooB(false) == 6, "");
}
namespace MultipleBases {
class A {
public:
constexpr virtual int getInt() const { return 10; }
};
class B {
public:
};
class C : public A, public B {
public:
constexpr int getInt() const override { return 20; }
};
constexpr int callGetInt(const A& a) { return a.getInt(); }
static_assert(callGetInt(C()) == 20, "");
static_assert(callGetInt(A()) == 10, "");
}
namespace Destructors {
class Base {
public:
int i;
constexpr Base(int &i) : i(i) {i++;}
constexpr virtual ~Base() {i--;}
};
class Derived : public Base {
public:
constexpr Derived(int &i) : Base(i) {}
constexpr virtual ~Derived() {i--;}
};
constexpr int test() {
int i = 0;
Derived d(i);
return i;
}
static_assert(test() == 1);
struct S {
constexpr S() {}
constexpr ~S() { // both-error {{never produces a constant expression}}
int i = 1 / 0; // both-warning {{division by zero}} \
// both-note 2{{division by zero}}
}
};
constexpr int testS() {
S{}; // both-note {{in call to 'S{}.~S()'}}
return 1;
}
static_assert(testS() == 1); // both-error {{not an integral constant expression}} \
// both-note {{in call to 'testS()'}}
}
namespace BaseToDerived {
namespace A {
struct A {};
struct B : A { int n; };
struct C : B {};
C c = {};
constexpr C *pb = (C*)((A*)&c + 1); // both-error {{must be initialized by a constant expression}} \
// both-note {{cannot access derived class of pointer past the end of object}}
}
namespace B {
struct A {};
struct Z {};
struct B : Z, A {
int n;
constexpr B() : n(10) {}
};
struct C : B {
constexpr C() : B() {}
};
constexpr C c = {};
constexpr const A *pa = &c;
constexpr const C *cp = (C*)pa;
constexpr const B *cb = (B*)cp;
static_assert(cb->n == 10);
static_assert(cp->n == 10);
}
namespace C {
struct Base { int *a; };
struct Base2 : Base { int f[12]; };
struct Middle1 { int b[3]; };
struct Middle2 : Base2 { char c; };
struct Middle3 : Middle2 { char g[3]; };
struct Middle4 { int f[3]; };
struct Middle5 : Middle4, Middle3 { char g2[3]; };
struct NotQuiteDerived : Middle1, Middle5 { bool d; };
struct Derived : NotQuiteDerived { int e; };
constexpr NotQuiteDerived NQD1 = {};
constexpr Middle5 *M4 = (Middle5*)((Base2*)&NQD1);
static_assert(M4->a == nullptr);
static_assert(M4->g2[0] == 0);
}
}
namespace VirtualDtors {
class A {
public:
unsigned &v;
constexpr A(unsigned &v) : v(v) {}
constexpr virtual ~A() {
v |= (1 << 0);
}
};
class B : public A {
public:
constexpr B(unsigned &v) : A(v) {}
constexpr virtual ~B() {
v |= (1 << 1);
}
};
class C : public B {
public:
constexpr C(unsigned &v) : B(v) {}
constexpr virtual ~C() {
v |= (1 << 2);
}
};
constexpr bool foo() {
unsigned a = 0;
{
C c(a);
}
return ((a & (1 << 0)) && (a & (1 << 1)) && (a & (1 << 2)));
}
static_assert(foo());
};
namespace QualifiedCalls {
class A {
public:
constexpr virtual int foo() const {
return 5;
}
};
class B : public A {};
class C : public B {
public:
constexpr int foo() const override {
return B::foo(); // B doesn't have a foo(), so this should call A::foo().
}
constexpr int foo2() const {
return this->A::foo();
}
};
constexpr C c;
static_assert(c.foo() == 5);
static_assert(c.foo2() == 5);
struct S {
int _c = 0;
virtual constexpr int foo() const { return 1; }
};
struct SS : S {
int a;
constexpr SS() {
a = S::foo();
}
constexpr int foo() const override {
return S::foo();
}
};
constexpr SS ss;
static_assert(ss.a == 1);
}
namespace CtorDtor {
struct Base {
int i = 0;
int j = 0;
constexpr Base() : i(func()) {
j = func();
}
constexpr Base(int i) : i(i), j(i) {}
constexpr virtual int func() const { return 1; }
};
struct Derived : Base {
constexpr Derived() {}
constexpr Derived(int i) : Base(i) {}
constexpr int func() const override { return 2; }
};
struct Derived2 : Derived {
constexpr Derived2() : Derived(func()) {} // ref-note {{subexpression not valid in a constant expression}}
constexpr int func() const override { return 3; }
};
constexpr Base B;
static_assert(B.i == 1 && B.j == 1, "");
constexpr Derived D;
static_assert(D.i == 1, ""); // expected-error {{static assertion failed}} \
// expected-note {{2 == 1}}
static_assert(D.j == 1, ""); // expected-error {{static assertion failed}} \
// expected-note {{2 == 1}}
constexpr Derived2 D2; // ref-error {{must be initialized by a constant expression}} \
// ref-note {{in call to 'Derived2()'}} \
// ref-note 2{{declared here}}
static_assert(D2.i == 3, ""); // ref-error {{not an integral constant expression}} \
// ref-note {{initializer of 'D2' is not a constant expression}}
static_assert(D2.j == 3, ""); // ref-error {{not an integral constant expression}} \
// ref-note {{initializer of 'D2' is not a constant expression}}
}
namespace VirtualFunctionPointers {
struct S {
virtual constexpr int func() const { return 1; }
};
struct Middle : S {
constexpr Middle(int i) : i(i) {}
int i;
};
struct Other {
constexpr Other(int k) : k(k) {}
int k;
};
struct S2 : Middle, Other {
int j;
constexpr S2(int i, int j, int k) : Middle(i), Other(k), j(j) {}
virtual constexpr int func() const { return i + j + k + S::func(); }
};
constexpr S s;
constexpr decltype(&S::func) foo = &S::func;
constexpr int value = (s.*foo)();
static_assert(value == 1);
constexpr S2 s2(1, 2, 3);
static_assert(s2.i == 1);
static_assert(s2.j == 2);
static_assert(s2.k == 3);
constexpr int value2 = s2.func();
constexpr int value3 = (s2.*foo)();
static_assert(value3 == 7);
constexpr int dynamicDispatch(const S &s) {
constexpr decltype(&S::func) SFunc = &S::func;
return (s.*SFunc)();
}
static_assert(dynamicDispatch(s) == 1);
static_assert(dynamicDispatch(s2) == 7);
};
};
#endif
#if __cplusplus < 202002L
namespace VirtualFromBase {
struct S1 {
virtual int f() const;
};
struct S2 {
virtual int f();
};
template <typename T> struct X : T {
constexpr X() {}
double d = 0.0;
constexpr int f() { return sizeof(T); }
};
// Non-virtual f(), OK.
constexpr X<X<S1>> xxs1;
constexpr X<S1> *p = const_cast<X<X<S1>>*>(&xxs1);
static_assert(p->f() == sizeof(S1), "");
// Virtual f(), not OK.
constexpr X<X<S2>> xxs2;
constexpr X<S2> *q = const_cast<X<X<S2>>*>(&xxs2);
static_assert(q->f() == sizeof(X<S2>), ""); // both-error {{not an integral constant expression}} \
// both-note {{cannot evaluate call to virtual function}}
}
#endif
namespace CompositeDefaultArgs {
struct Foo {
int a;
int b;
constexpr Foo() : a(12), b(13) {}
};
class Bar {
public:
bool B = false;
constexpr int someFunc(Foo F = Foo()) {
this->B = true;
return 5;
}
};
constexpr bool testMe() {
Bar B;
B.someFunc();
return B.B;
}
static_assert(testMe(), "");
}
constexpr bool BPand(BoolPair bp) {
return bp.first && bp.second;
}
static_assert(BPand(BoolPair{true, false}) == false, "");
namespace TemporaryObjectExpr {
struct F {
int a;
constexpr F() : a(12) {}
};
constexpr int foo(F f) {
return 0;
}
static_assert(foo(F()) == 0, "");
}
namespace ZeroInit {
struct F {
int a;
};
namespace Simple {
struct A {
char a;
bool b;
int c[4];
float d;
};
constexpr int foo(A x) {
return x.a + static_cast<int>(x.b) + x.c[0] + x.c[3] + static_cast<int>(x.d);
}
static_assert(foo(A()) == 0, "");
}
namespace Inheritance {
struct F2 : F {
float f;
};
constexpr int foo(F2 f) {
return (int)f.f + f.a;
}
static_assert(foo(F2()) == 0, "");
}
namespace BitFields {
struct F {
unsigned a : 6;
};
constexpr int foo(F f) {
return f.a;
}
static_assert(foo(F()) == 0, "");
}
namespace Nested {
struct F2 {
float f;
char c;
};
struct F {
F2 f2;
int i;
};
constexpr int foo(F f) {
return f.i + f.f2.f + f.f2.c;
}
static_assert(foo(F()) == 0, "");
}
namespace CompositeArrays {
struct F2 {
float f;
char c;
};
struct F {
F2 f2[2];
int i;
};
constexpr int foo(F f) {
return f.i + f.f2[0].f + f.f2[0].c + f.f2[1].f + f.f2[1].c;
}
static_assert(foo(F()) == 0, "");
}
#if __cplusplus > 201402L
namespace Unions {
struct F {
union {
int a;
char c[4];
float f;
} U;
int i;
};
constexpr int foo(F f) {
return f.i + f.U.f; // both-note {{read of member 'f' of union with active member 'a'}}
}
static_assert(foo(F()) == 0, ""); // both-error {{not an integral constant expression}} \
// both-note {{in call to}}
}
#endif
#if __cplusplus >= 202002L
namespace Failure {
struct S {
int a;
F f{12};
};
constexpr int foo(S x) {
return x.a;
}
static_assert(foo(S()) == 0, "");
};
#endif
}
#if __cplusplus >= 202002L
namespace ParenInit {
struct A {
int a;
};
struct B : A {
int b;
};
constexpr B b(A(1),2);
struct O {
int &&j;
};
/// Not constexpr!
O o1(0);
constinit O o2(0); // both-error {{variable does not have a constant initializer}} \
// both-note {{required by 'constinit' specifier}} \
// both-note {{reference to temporary is not a constant expression}} \
// both-note {{temporary created here}}
/// Initializing an array.
constexpr void bar(int i, int j) {
int arr[4](i, j);
}
}
#endif
namespace DelegatingConstructors {
struct S {
int a;
constexpr S() : S(10) {}
constexpr S(int a) : a(a) {}
};
constexpr S s = {};
static_assert(s.a == 10, "");
struct B {
int a;
int b;
constexpr B(int a) : a(a), b(a + 2) {}
};
struct A : B {
constexpr A() : B(10) {};
};
constexpr A d4 = {};
static_assert(d4.a == 10, "");
static_assert(d4.b == 12, "");
}
namespace AccessOnNullptr {
struct F {
int a;
};
constexpr int a() { // both-error {{never produces a constant expression}}
F *f = nullptr;
f->a = 0; // both-note 2{{cannot access field of null pointer}}
return f->a;
}
static_assert(a() == 0, ""); // both-error {{not an integral constant expression}} \
// both-note {{in call to 'a()'}}
constexpr int a2() { // both-error {{never produces a constant expression}}
F *f = nullptr;
const int *a = &(f->a); // both-note 2{{cannot access field of null pointer}}
return f->a;
}
static_assert(a2() == 0, ""); // both-error {{not an integral constant expression}} \
// both-note {{in call to 'a2()'}}
}
namespace IndirectFieldInit {
#if __cplusplus >= 202002L
/// Primitive.
struct Nested1 {
struct {
int first;
};
int x;
constexpr Nested1(int x) : first(12), x() { x = 4; }
constexpr Nested1() : Nested1(42) {}
};
constexpr Nested1 N1{};
static_assert(N1.first == 12, "");
/// Composite.
struct Nested2 {
struct First { int x = 42; };
struct {
First first;
};
int x;
constexpr Nested2(int x) : first(12), x() { x = 4; }
constexpr Nested2() : Nested2(42) {}
};
constexpr Nested2 N2{};
static_assert(N2.first.x == 12, "");
/// Bitfield.
struct Nested3 {
struct {
unsigned first : 2;
};
int x;
constexpr Nested3(int x) : first(3), x() { x = 4; }
constexpr Nested3() : Nested3(42) {}
};
constexpr Nested3 N3{};
static_assert(N3.first == 3, "");
/// Test that we get the offset right if the
/// record has a base.
struct Nested4Base {
int a;
int b;
char c;
};
struct Nested4 : Nested4Base{
struct {
int first;
};
int x;
constexpr Nested4(int x) : first(123), x() { a = 1; b = 2; c = 3; x = 4; }
constexpr Nested4() : Nested4(42) {}
};
constexpr Nested4 N4{};
static_assert(N4.first == 123, "");
struct S {
struct {
int x, y;
};
constexpr S(int x_, int y_) : x(x_), y(y_) {}
};
constexpr S s(1, 2);
static_assert(s.x == 1 && s.y == 2);
struct S2 {
int a;
struct {
int b;
struct {
int x, y;
};
};
constexpr S2(int x_, int y_) : a(3), b(4), x(x_), y(y_) {}
};
constexpr S2 s2(1, 2);
static_assert(s2.x == 1 && s2.y == 2 && s2.a == 3 && s2.b == 4);
#endif
}
namespace InheritedConstructor {
namespace PR47555 {
struct A {
int c;
int d;
constexpr A(int c, int d) : c(c), d(d){}
};
struct B : A { using A::A; };
constexpr B b = {13, 1};
static_assert(b.c == 13, "");
static_assert(b.d == 1, "");
}
namespace PR47555_2 {
struct A {
int c;
int d;
double e;
constexpr A(int c, int &d, double e) : c(c), d(++d), e(e){}
};
struct B : A { using A::A; };
constexpr int f() {
int a = 10;
B b = {10, a, 40.0};
return a;
}
static_assert(f() == 11, "");
}
namespace AaronsTest {
struct T {
constexpr T(float) {}
};
struct Base {
constexpr Base(T t = 1.0f) {}
constexpr Base(float) {}
};
struct FirstMiddle : Base {
using Base::Base;
constexpr FirstMiddle() : Base(2.0f) {}
};
struct SecondMiddle : Base {
constexpr SecondMiddle() : Base(3.0f) {}
constexpr SecondMiddle(T t) : Base(t) {}
};
struct S : FirstMiddle, SecondMiddle {
using FirstMiddle::FirstMiddle;
constexpr S(int i) : S(4.0f) {}
};
constexpr S s(1);
}
}
namespace InvalidCtorInitializer {
struct X {
int Y;
constexpr X()
: Y(fo_o_()) {} // both-error {{use of undeclared identifier 'fo_o_'}}
};
// no crash on evaluating the constexpr ctor.
constexpr int Z = X().Y; // both-error {{constexpr variable 'Z' must be initialized by a constant expression}}
}
extern int f(); // both-note {{here}}
struct HasNonConstExprMemInit {
int x = f(); // both-note {{non-constexpr function}}
constexpr HasNonConstExprMemInit() {} // both-error {{never produces a constant expression}}
};
namespace {
template <class Tp, Tp v>
struct integral_constant {
static const Tp value = v;
};
template <class Tp, Tp v>
const Tp integral_constant<Tp, v>::value;
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;
/// This might look innocent, but we get an evaluateAsInitializer call for the
/// static bool member before evaluating the first static_assert, but we do NOT
/// get such a call for the second one. So the second one needs to lazily visit
/// the data member itself.
static_assert(true_type::value, "");
static_assert(true_type::value, "");
}
#if __cplusplus >= 202002L
namespace {
/// Used to crash because the CXXDefaultInitExpr is of compound type.
struct A {
int &x;
constexpr ~A() { --x; }
};
struct B {
int &x;
const A &a = A{x};
};
constexpr int a() {
int x = 1;
int f = B{x}.x;
B{x}; // both-warning {{expression result unused}}
return 1;
}
}
#endif
namespace pr18633 {
struct A1 {
static const int sz;
static const int sz2;
};
const int A1::sz2 = 11;
template<typename T>
void func () {
int arr[A1::sz];
// both-warning@-1 {{variable length arrays in C++ are a Clang extension}}
// both-note@-2 {{initializer of 'sz' is unknown}}
// both-note@-9 {{declared here}}
}
template<typename T>
void func2 () {
int arr[A1::sz2];
}
const int A1::sz = 12;
void func2() {
func<int>();
func2<int>();
}
}
namespace {
struct F {
static constexpr int Z = 12;
};
F f;
static_assert(f.Z == 12, "");
}
namespace UnnamedBitFields {
struct A {
int : 1;
double f;
int : 1;
char c;
};
constexpr A a = (A){1.0, 'a'};
static_assert(a.f == 1.0, "");
static_assert(a.c == 'a', "");
}
namespace VirtualBases {
/// This used to crash.
namespace One {
class A {
protected:
int x;
};
class B : public virtual A {
public:
int getX() { return x; } // both-note {{declared here}}
};
class DV : virtual public B{};
void foo() {
DV b;
int a[b.getX()]; // both-warning {{variable length arrays}} \
// both-note {{non-constexpr function 'getX' cannot be used}}
}
}
namespace Two {
struct U { int n; };
struct A : virtual U { int n; };
struct B : A {};
B a;
static_assert((U*)(A*)(&a) == (U*)(&a), "");
struct C : virtual A {};
struct D : B, C {};
D d;
constexpr B *p = &d;
constexpr C *q = &d;
static_assert((A*)p == (A*)q, ""); // both-error {{failed}}
}
namespace Three {
struct U { int n; };
struct V : U { int n; };
struct A : virtual V { int n; };
struct Aa { int n; };
struct B : virtual A, Aa {};
struct C : virtual A, Aa {};
struct D : B, C {};
D d;
constexpr B *p = &d;
constexpr C *q = &d;
static_assert((void*)p != (void*)q, "");
static_assert((A*)p == (A*)q, "");
static_assert((Aa*)p != (Aa*)q, "");
constexpr V *v = p;
constexpr V *w = q;
constexpr V *x = (A*)p;
static_assert(v == w, "");
static_assert(v == x, "");
static_assert((U*)&d == p, "");
static_assert((U*)&d == q, "");
static_assert((U*)&d == v, "");
static_assert((U*)&d == w, "");
static_assert((U*)&d == x, "");
struct X {};
struct Y1 : virtual X {};
struct Y2 : X {};
struct Z : Y1, Y2 {};
Z z;
static_assert((X*)(Y1*)&z != (X*)(Y2*)&z, "");
}
}
namespace ZeroInit {
struct S3 {
S3() = default;
S3(const S3&) = default;
S3(S3&&) = default;
constexpr S3(int n) : n(n) {}
int n;
};
constexpr S3 s3d; // both-error {{default initialization of an object of const type 'const S3' without a user-provided default constructor}}
static_assert(s3d.n == 0, "");
struct P {
int a = 10;
};
static_assert(P().a == 10, "");
}
namespace {
#if __cplusplus >= 202002L
struct C {
template <unsigned N> constexpr C(const char (&)[N]) : n(N) {}
unsigned n;
};
template <C c>
constexpr auto operator""_c() { return c.n; }
constexpr auto waldo = "abc"_c;
static_assert(waldo == 4, "");
#endif
}
namespace TemporaryWithInvalidDestructor {
#if __cplusplus >= 202002L
struct A {
bool a = true;
constexpr ~A() noexcept(false) { // both-error {{never produces a constant expression}}
throw; // both-note 2{{not valid in a constant expression}} \
// both-error {{cannot use 'throw' with exceptions disabled}}
}
};
static_assert(A().a, ""); // both-error {{not an integral constant expression}} \
// both-note {{in call to}}
#endif
}
namespace IgnoredCtorWithZeroInit {
struct S {
int a;
};
bool get_status() {
return (S(), true);
}
}
#if __cplusplus >= 202002L
namespace VirtOperator {
/// This used to crash because it's a virtual CXXOperatorCallExpr.
struct B {
virtual constexpr bool operator==(const B&) const { return true; }
};
struct D : B {
constexpr bool operator==(const B&) const override{ return false; } // both-note {{operator}}
};
constexpr bool cmp_base_derived = D() == D(); // both-warning {{ambiguous}}
}
namespace FloatAPValue {
struct ClassTemplateArg {
int a;
float f;
};
template<ClassTemplateArg A> struct ClassTemplateArgTemplate {
static constexpr const ClassTemplateArg &Arg = A;
};
ClassTemplateArgTemplate<ClassTemplateArg{1, 2.0f}> ClassTemplateArgObj;
template<const ClassTemplateArg&> struct ClassTemplateArgRefTemplate {};
ClassTemplateArgRefTemplate<ClassTemplateArgObj.Arg> ClassTemplateArgRefObj;
}
#endif
namespace LocalWithThisPtrInit {
struct S {
int i;
int *p = &i;
};
constexpr int foo() {
S s{2};
return *s.p;
}
static_assert(foo() == 2, "");
}
namespace OnePastEndAndBack {
struct Base {
constexpr Base() {}
int n = 0;
};
constexpr Base a;
constexpr const Base *c = &a + 1;
constexpr const Base *d = c - 1;
static_assert(d == &a, "");
}
namespace BitSet {
class Bitset {
unsigned Bit = 0;
public:
constexpr Bitset() {
int Init[2] = {1,2};
for (auto I : Init)
set(I);
}
constexpr void set(unsigned I) {
this->Bit++;
this->Bit = 1u << 1;
}
};
struct ArchInfo {
Bitset DefaultExts;
};
constexpr ArchInfo ARMV8A = {
Bitset()
};
}
namespace ArrayInitChain {
struct StringLiteral {
const char *S;
};
struct CustomOperandVal {
StringLiteral Str;
unsigned Width;
unsigned Mask = Width + 1;
};
constexpr CustomOperandVal A[] = {
{},
{{"depctr_hold_cnt"}, 12, 13},
};
static_assert(A[0].Str.S == nullptr, "");
static_assert(A[0].Width == 0, "");
static_assert(A[0].Mask == 1, "");
static_assert(A[1].Width == 12, "");
static_assert(A[1].Mask == 13, "");
}
#if __cplusplus >= 202002L
namespace ctorOverrider {
// Ensure that we pick the right final overrider during construction.
struct A {
virtual constexpr char f() const { return 'A'; }
char a = f();
};
struct Covariant1 {
A d;
};
constexpr Covariant1 cb;
}
#endif
#if __cplusplus >= 202002L
namespace VirtDtor {
struct X { char *p; constexpr ~X() { *p++ = 'X'; } };
struct Y : X { int y; virtual constexpr ~Y() { *p++ = 'Y'; } };
struct Z : Y { int z; constexpr ~Z() override { *p++ = 'Z'; } };
union VU {
constexpr VU() : z() {}
constexpr ~VU() {}
Z z;
};
constexpr char virt_dtor(int mode, const char *expected) {
char buff[4] = {};
VU vu;
vu.z.p = buff;
((Y&)vu.z).~Y();
return true;
}
static_assert(virt_dtor(0, "ZYX"));
}
namespace DtorDestroysFieldsAfterSelf {
struct S {
int a = 10;
constexpr ~S() {
a = 0;
}
};
struct F {
S s;
int a;
int &b;
constexpr F(int a, int &b) : a(a), b(b) {}
constexpr ~F() {
b += s.a;
}
};
constexpr int foo() {
int a = 10;
int b = 5;
{
F f(a, b);
}
return b;
}
static_assert(foo() == 15);
}
#endif
namespace ExprWithCleanups {
struct A { A(); ~A(); int get(); };
constexpr int get() {return false ? A().get() : 1;}
static_assert(get() == 1, "");
struct S {
int V;
constexpr S(int V) : V(V) {}
constexpr int get() {
return V;
}
};
constexpr int get(bool b) {
S a = b ? S(1) : S(2);
return a.get();
}
static_assert(get(true) == 1, "");
static_assert(get(false) == 2, "");
constexpr auto F = true ? 1i : 2i;
static_assert(F == 1i, "");
}
namespace NullptrUpcast {
struct A {};
struct B : A { int n; };
constexpr B *nb = nullptr;
constexpr A &ra = *nb; // both-error {{constant expression}} \
// both-note {{cannot access base class of null pointer}}
}