Skip to content

[clang][NFC] Add examples from [dcl.init.aggr] to C++ conformance tests #91435

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 9, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
294 changes: 294 additions & 0 deletions clang/test/CXX/dcl/dcl.init/aggr.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
// RUN: %clang_cc1 -std=c++2c -verify %s

Comment on lines +1 to +2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future reference, can you say this is testing c++2c and maybe quote a paper number (latest working draft?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reference would become outdated the moment this file is touched next time, so I added one to the PR description, so it makes it into the commit message.

namespace ex1 {
struct C {
union {
int a;
const char* p;
};
int x;
};

constexpr C c = { .a = 1, .x = 3 };
static_assert(c.a == 1);
static_assert(c.x == 3);

static constexpr C c2 = { .a = 1.0, .x = 3 };
// expected-error@-1 {{type 'double' cannot be narrowed to 'int' in initializer list}}
// expected-note@-2 {{insert an explicit cast to silence this issue}}
} // namespace ex1

namespace ex2 {
struct A {
int x;
struct B {
int i;
int j;
} b;
};

constexpr A a = { 1, { 2, 3 } };
static_assert(a.x == 1);
static_assert(a.b.i == 2);
static_assert(a.b.j == 3);

struct base1 { int b1, b2 = 42; };
struct base2 {
constexpr base2() {
b3 = 43;
}
int b3;
};
struct derived : base1, base2 {
int d;
};

constexpr derived d1{{1, 2}, {}, 4};
static_assert(d1.b1 == 1);
static_assert(d1.b2 == 2);
static_assert(d1.b3 == 43);
static_assert(d1.d == 4);

constexpr derived d2{{}, {}, 4};
static_assert(d2.b1 == 0);
static_assert(d2.b2 == 42);
static_assert(d2.b3 == 43);
static_assert(d2.d == 4);
} // namespace ex2

namespace ex3 {
struct S {
int a;
const char* b;
int c;
int d = b[a];
};

constexpr S ss = { 1, "asdf" };
static_assert(ss.a == 1);
static_assert(__builtin_strcmp(ss.b, "asdf") == 0);
static_assert(ss.c == int{});
static_assert(ss.d == ss.b[ss.a]);

struct string {
int d = 43;
};

struct A {
string a;
int b = 42;
int c = -1;
};

constexpr A a{.c = 21};
static_assert(a.a.d == string{}.d);
static_assert(a.b == 42);
static_assert(a.c == 21);
} // namespace ex3

namespace ex4 {
int x[] = { 1, 3, 5 };
static_assert(sizeof(x) / sizeof(int) == 3);
} // namespace ex4

namespace ex5 {
struct X { int i, j, k; };

constexpr X a[] = { 1, 2, 3, 4, 5, 6 };
constexpr X b[2] = { { 1, 2, 3 }, { 4, 5, 6 } };
static_assert(sizeof(a) == sizeof(b));
static_assert(a[0].i == b[0].i);
static_assert(a[0].j == b[0].j);
static_assert(a[0].k == b[0].k);
static_assert(a[1].i == b[1].i);
static_assert(a[1].j == b[1].j);
static_assert(a[1].k == b[1].k);
} // namespace ex5

namespace ex6 {
struct S {
int y[] = { 0 };
// expected-error@-1 {{array bound cannot be deduced from a default member initializer}}
};
} // namespace ex6

namespace ex7 {
struct A {
int i;
static int s;
int j;
int :17;
int k;
};

constexpr A a = { 1, 2, 3 };
static_assert(a.i == 1);
static_assert(a.j == 2);
static_assert(a.k == 3);
} // namespace ex7

namespace ex8 {
struct A;
extern A a;
struct A {
const A& a1 { A{a,a} };
const A& a2 { A{} };
// expected-error@-1 {{default member initializer for 'a2' needed within definition of enclosing class 'A' outside of member functions}}
// expected-note@-2 {{default member initializer declared here}}
};
A a{a,a};

struct B {
int n = B{}.n;
// expected-error@-1 {{default member initializer for 'n' needed within definition of enclosing class 'B' outside of member functions}}
// expected-note@-2 {{default member initializer declared here}}
};
} // namespace ex8

namespace ex9 {
constexpr int x[2][2] = { 3, 1, 4, 2 };
static_assert(x[0][0] == 3);
static_assert(x[0][1] == 1);
static_assert(x[1][0] == 4);
static_assert(x[1][1] == 2);

constexpr float y[4][3] = {
{ 1 }, { 2 }, { 3 }, { 4 }
};
static_assert(y[0][0] == 1);
static_assert(y[0][1] == 0);
static_assert(y[0][2] == 0);
static_assert(y[1][0] == 2);
static_assert(y[1][1] == 0);
static_assert(y[1][2] == 0);
static_assert(y[2][0] == 3);
static_assert(y[2][1] == 0);
static_assert(y[2][2] == 0);
static_assert(y[3][0] == 4);
static_assert(y[3][1] == 0);
static_assert(y[3][2] == 0);
} // namespace ex9

namespace ex10 {
struct S1 { int a, b; };
struct S2 { S1 s, t; };

constexpr S2 x[2] = { 1, 2, 3, 4, 5, 6, 7, 8 };
constexpr S2 y[2] = {
{
{ 1, 2 },
{ 3, 4 }
},
{
{ 5, 6 },
{ 7, 8 }
}
};
static_assert(x[0].s.a == 1);
static_assert(x[0].s.b == 2);
static_assert(x[0].t.a == 3);
static_assert(x[0].t.b == 4);
static_assert(x[1].s.a == 5);
static_assert(x[1].s.b == 6);
static_assert(x[1].t.a == 7);
static_assert(x[1].t.b == 8);
} // namespace ex10

namespace ex11 {
char cv[4] = { 'a', 's', 'd', 'f', 0 };
// expected-error@-1 {{excess elements in array initializer}}
} // namespace ex11

namespace ex12 {
constexpr float y[4][3] = {
{ 1, 3, 5 },
{ 2, 4, 6 },
{ 3, 5, 7 },
};
static_assert(y[0][0] == 1);
static_assert(y[0][1] == 3);
static_assert(y[0][2] == 5);
static_assert(y[1][0] == 2);
static_assert(y[1][1] == 4);
static_assert(y[1][2] == 6);
static_assert(y[2][0] == 3);
static_assert(y[2][1] == 5);
static_assert(y[2][2] == 7);
static_assert(y[3][0] == 0.0);
static_assert(y[3][1] == 0.0);
static_assert(y[3][2] == 0.0);

constexpr float z[4][3] = {
1, 3, 5, 2, 4, 6, 3, 5, 7
};
static_assert(z[0][0] == 1);
static_assert(z[0][1] == 3);
static_assert(z[0][2] == 5);
static_assert(z[1][0] == 2);
static_assert(z[1][1] == 4);
static_assert(z[1][2] == 6);
static_assert(z[2][0] == 3);
static_assert(z[2][1] == 5);
static_assert(z[2][2] == 7);
static_assert(z[3][0] == 0.0);
static_assert(z[3][1] == 0.0);
static_assert(z[3][2] == 0.0);
} // namespace ex12

namespace ex13 {
struct S { } s;
struct A {
S s1;
int i1;
S s2;
int i2;
S s3;
int i3;
} a = {
{ }, // Required initialization
0,
s, // Required initialization
0
}; // Initialization not required for A​::​s3 because A​::​i3 is also not initialized
} // namespace ex13

namespace ex14 {
struct A {
int i;
constexpr operator int() const { return 42; };
};
struct B {
A a1, a2;
int z;
};
constexpr A a{};
constexpr B b = { 4, a, a };
static_assert(b.a1.i == 4);
static_assert(b.a2.i == a.i);
static_assert(b.z == a.operator int());
} // namespace ex14

namespace ex15 {
union u { // #ex15-u
int a;
const char* b;
};

u a = { 1 };
u b = a;
u c = 1;
// expected-error@-1 {{no viable conversion from 'int' to 'u'}}
// expected-note@#ex15-u {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const u &' for 1st argument}}
// expected-note@#ex15-u {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'u &&' for 1st argument}}
u d = { 0, "asdf" };
// expected-error@-1 {{excess elements in union initializer}}
u e = { "asdf" };
// expected-error@-1 {{cannot initialize a member subobject of type 'int' with an lvalue of type 'const char[5]'}}
u f = { .b = "asdf" };
u g = {
.a = 1, // #ex15-g-a
.b = "asdf"
// expected-error@-1 {{initializer partially overrides prior initialization of this subobject}}
// expected-note@#ex15-g-a {{previous initialization is here}}
};
} // namespace ex15