llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Vlad Serebrennikov (Endilll) <details> <summary>Changes</summary> This patch adds examples from [[dcl.init.aggr]](http://eel.is/c++draft/dcl.init.aggr) to C++ conformance tests. Testing is done via constant evaluation and static asserts. As far as I can see, the rest of the conformance suite is typically testing the latest language mode at the time of writing (with a notable exception of defect report tests), so I'm also testing in the latest language mode. --- Full diff: https://github.com/llvm/llvm-project/pull/91435.diff 1 Files Affected: - (added) clang/test/CXX/dcl/dcl.init/aggr.cpp (+294) ``````````diff diff --git a/clang/test/CXX/dcl/dcl.init/aggr.cpp b/clang/test/CXX/dcl/dcl.init/aggr.cpp new file mode 100644 index 0000000000000..3206d2e7f616a --- /dev/null +++ b/clang/test/CXX/dcl/dcl.init/aggr.cpp @@ -0,0 +1,294 @@ +// RUN: %clang_cc1 -std=c++2c -verify %s + +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 `````````` </details> https://github.com/llvm/llvm-project/pull/91435 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits