From 5230c3d825aee39da28c73705bc5852fae9f92a6 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 14 Nov 2016 08:54:50 +0100 Subject: [PATCH] Implement P0217R3 - C++17 structured bindings Implement P0217R3 - C++17 structured bindings * g++.dg/cpp1z/decomp1.C: New test. * g++.dg/cpp1z/decomp2.C: New test. * g++.dg/cpp1z/decomp3.C: New test. * g++.dg/cpp1z/decomp4.C: New test. * g++.dg/cpp1z/decomp5.C: New test. * g++.dg/cpp1z/decomp6.C: New test. * g++.dg/cpp1z/decomp7.C: New test. * g++.dg/cpp1z/decomp8.C: New test. * g++.dg/cpp1z/decomp9.C: New test. * g++.dg/cpp1z/decomp10.C: New test. Co-Authored-By: Jason Merrill From-SVN: r242378 --- gcc/testsuite/ChangeLog | 15 +++++ gcc/testsuite/g++.dg/cpp1z/decomp1.C | 35 ++++++++++ gcc/testsuite/g++.dg/cpp1z/decomp10.C | 48 ++++++++++++++ gcc/testsuite/g++.dg/cpp1z/decomp2.C | 54 ++++++++++++++++ gcc/testsuite/g++.dg/cpp1z/decomp3.C | 66 +++++++++++++++++++ gcc/testsuite/g++.dg/cpp1z/decomp4.C | 32 ++++++++++ gcc/testsuite/g++.dg/cpp1z/decomp5.C | 40 ++++++++++++ gcc/testsuite/g++.dg/cpp1z/decomp6.C | 92 +++++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp1z/decomp7.C | 60 +++++++++++++++++ gcc/testsuite/g++.dg/cpp1z/decomp8.C | 88 +++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp1z/decomp9.C | 47 ++++++++++++++ 11 files changed, 577 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp1.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp10.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp2.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp3.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp4.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp5.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp6.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp7.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp8.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/decomp9.C diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5757bb4ca89..385a2b65361 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2016-11-14 Jakub Jelinek + Jason Merrill + + Implement P0217R3 - C++17 structured bindings + * g++.dg/cpp1z/decomp1.C: New test. + * g++.dg/cpp1z/decomp2.C: New test. + * g++.dg/cpp1z/decomp3.C: New test. + * g++.dg/cpp1z/decomp4.C: New test. + * g++.dg/cpp1z/decomp5.C: New test. + * g++.dg/cpp1z/decomp6.C: New test. + * g++.dg/cpp1z/decomp7.C: New test. + * g++.dg/cpp1z/decomp8.C: New test. + * g++.dg/cpp1z/decomp9.C: New test. + * g++.dg/cpp1z/decomp10.C: New test. + 2016-11-13 Kugan Vivekanandarajah * g++.dg/torture/pr78268.C: New test. diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp1.C b/gcc/testsuite/g++.dg/cpp1z/decomp1.C new file mode 100644 index 00000000000..98f60905e1a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp1.C @@ -0,0 +1,35 @@ +// { dg-do run { target c++11 } } +// { dg-options "" } + +int a[2] = { 1, 2 }; +struct S { int a; signed char b; float c; } s = { 6, 7, 8.0f }; + +int +main () +{ + auto & [ c, d ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto [ e, f ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto [ g, h, i ] = s; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto & [ j, k, l ] = s; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + c++; + d++; + e += 6; + f += 7; + g++; + h++; + j += 10; + k += 11; + if (c != 2 || &c != &a[0] + || d != 3 || &d != &a[1] + || e != 7 || &e == &a[0] + || f != 9 || &f == &a[1] + || g != 7 || &g == &s.a + || h != 8 || &h == &s.b + || i != 8.0f || &i == &s.c + || j != 16 || &j != &s.a + || k != 18 || &k != &s.b + || l != 8.0f || &l != &s.c + || a[0] != 2 || a[1] != 3 + || s.a != 16 || s.b != 18 || s.c != 8.0f) + __builtin_abort (); +} diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp10.C b/gcc/testsuite/g++.dg/cpp1z/decomp10.C new file mode 100644 index 00000000000..316cea98811 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp10.C @@ -0,0 +1,48 @@ +// { dg-options -std=c++1z } + +namespace std { + template struct tuple_size; + template struct tuple_element; +} + +struct A1 { int i,j; } a1; +template<> struct std::tuple_size { }; +void f1() { auto [ x ] = a1; } // { dg-error "decomposes into 2" } + +struct A2 { int i,j; } a2; +template<> struct std::tuple_size { enum { value = 5 }; }; +void f2() { auto [ x ] = a2; } // { dg-error "decomposes into 5" } + +struct A3 { int i,j; } a3; +template<> struct std::tuple_size { enum { value = 1 }; }; +void f3() { auto [ x ] = a3; } // { dg-error "get" } + +struct A3a { int i,j; int get(); } a3a; +template<> struct std::tuple_size { enum { value = 1 }; }; +void f3a() { auto [ x ] = a3a; } // { dg-error "get<0>" } + +struct A3b { int i,j; } a3b; +int get(A3b&&); +template<> struct std::tuple_size { enum { value = 1 }; }; +void f3b() { auto [ x ] = a3b; } // { dg-error "get<0>" } + +struct A4 { + int ar[3]; + template int& get() { return ar[I]; } +} a4; +template<> struct std::tuple_size { enum { value = 3 }; }; +template +void f4() { auto [ x, y, z ] = a4; } // { dg-error "tuple_element" } + +struct A5 { } a5; +template int& get(A5&& a); +template<> struct std::tuple_size { enum { value = 3 }; }; +template +void f5() { auto [ x, y, z ] = a5; } // { dg-error "tuple_element" } + +struct A6 { } a6; +template int& get(A6&& a); +template<> struct std::tuple_size { enum { value = 3 }; }; +template<> struct std::tuple_element<0, A6> { }; +template +void f6() { auto [ x, y, z ] = a6; } // { dg-error "no type named .type" } diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp2.C b/gcc/testsuite/g++.dg/cpp1z/decomp2.C new file mode 100644 index 00000000000..5831fc74940 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp2.C @@ -0,0 +1,54 @@ +// { dg-do run { target c++11 } } +// { dg-options "" } + +typedef int V __attribute__((vector_size (4 * sizeof (int)))); +V a = (V) { 1, 2, 3, 4 }; +__complex__ double b = 5.0 + 6.0i; +__complex__ int c = 7 + 8i; + +int +main () +{ + auto & [ d, e, f, g ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto [ h, i, j, k ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto [ l, m ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto & [ n, o ] = b; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto & [ p, q ] = c; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto [ r, s ] = c; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + d += 10; + e += 11; + f += 12; + g += 13; + h += 14; + i += 15; + j += 16; + k += 17; + l = l * 2.; + m = m * 3.; + n = n * 3.; + o = o * 2.; + p += 18; + q += 19; + r += 22; + s += 23; + if (d != 11 || &d != &a[0] + || e != 13 || &e != &a[1] + || f != 15 || &f != &a[2] + || g != 17 || &g != &a[3] + || h != 15 || &h == &a[0] + || i != 17 || &i == &a[1] + || j != 19 || &j == &a[2] + || k != 21 || &k == &a[3] + || l != 10.0 || &l == &__real__ b + || m != 18.0 || &m == &__imag__ b + || n != 15.0 || &n != &__real__ b + || o != 12.0 || &o != &__imag__ b + || p != 25 || &p != &__real__ c + || q != 27 || &q != &__imag__ c + || r != 29 || &r == &__real__ c + || s != 31 || &s == &__imag__ c + || a[0] != 11 || a[1] != 13 || a[2] != 15 || a[3] != 17 + || b != 15.0 + 12.0i + || c != 25 + 27i) + __builtin_abort (); +} diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp3.C b/gcc/testsuite/g++.dg/cpp1z/decomp3.C new file mode 100644 index 00000000000..a739d3ace37 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp3.C @@ -0,0 +1,66 @@ +// { dg-do compile { target c++11 } } +// { dg-options "" } + +struct A { int a, b; float c; }; +A &bar (); +struct B { int d; }; +B baz (); + +void +test (A &b, B c) +{ + int && [ d ] = c; // { dg-error "decomposition declaration cannot be declared with type 'int'" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + char & [ e, f, ff ] { b }; // { dg-error "decomposition declaration cannot be declared with type 'char'" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + auto&[g,h,i]=b; // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } } + decltype (auto) [ j ] = c; // { dg-error "decomposition declaration cannot be declared with type 'decltype.auto.'" "" { target c++14 } } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + // { dg-error "expected primary-expression before 'decltype'" "" { target c++11_down } .-2 } + auto & & && & [ m, n, o ] = b; // { dg-error "multiple ref-qualifiers" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + constexpr auto [ p ] = c; // { dg-error "decomposition declaration cannot be declared 'constexpr'" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + friend auto [ q ] = c; // { dg-error "'friend' used outside of class" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + typedef auto [ r ] = c; // { dg-error "decomposition declaration cannot be declared 'typedef'" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + inline auto [ s ] = c; // { dg-error "decomposition declaration cannot be declared 'inline'" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + __restrict auto [ t ] = c; // { dg-error "invalid use of 'restrict'" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + long long auto [ u ] = c; // { dg-error "'long long' invalid for 'decomposition'" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + virtual auto [ v ] = c; // { dg-error "'virtual' outside class declaration" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + explicit auto [ w ] = c; // { dg-error "'explicit' outside class declaration" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + static auto [ x ] = c; // { dg-error "decomposition declaration cannot be declared 'static'" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + extern auto [ y ] { c }; // { dg-error "decomposition declaration cannot be declared 'extern'" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } +} + +void +test2 (auto & [ p ] = bar ()) // { dg-error "'p' was not declared in this scope" } +{ +} + +int arr[4]; + +void +test3 (A &b, B c) +{ + auto [ d, e, f ] = arr; // { dg-error "only 3 names provided while 'int .4.' decomposes into 4 elements" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + auto & [ g, h, i, j, k ] = arr; // { dg-error "5 names provided while 'int .4.' decomposes into 4 elements" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + auto [ l, m ] = b; // { dg-error "only 2 names provided while 'A' decomposes into 3 elements" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + auto & [ n, o, p, q ] = b; // { dg-error "4 names provided while 'A' decomposes into 3 elements" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + auto [] { c }; // { dg-error "empty decomposition declaration" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + auto [ r, s ] = c; // { dg-error "2 names provided while 'B' decomposes into 1 elements" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } +} diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp4.C b/gcc/testsuite/g++.dg/cpp1z/decomp4.C new file mode 100644 index 00000000000..95a02ec27df --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp4.C @@ -0,0 +1,32 @@ +// { dg-do compile { target c++11 } } +// { dg-options "" } + +struct A { int a; struct { int b; }; }; +struct B { int a; union { int c; long d; }; }; +struct C { int a; private: int b; }; +struct D { int a; private: static int b; }; +struct E { protected: int a; }; +struct F { int a; }; +struct G : public F { int b; }; +struct H { int b; }; +struct I : public F, H {}; + +void +test (A &a, B &b, C &c, D &d, E &e, F &f, G &g, H &h, I &i) +{ + auto [ j ] = a; // { dg-error "cannot decompose class type 'A' because it has an anonymous struct member" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + auto [ k ] { b }; // { dg-error "cannot decompose class type 'B' because it has an anonymous union member" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + auto [ l ] = c; // { dg-error "cannot decompose non-public member 'C::b' of 'C'" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + auto [ m ] = d; // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } } + auto [ n ] { e }; // { dg-error "cannot decompose non-public member 'E::a' of 'E'" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + auto [ o ] { f }; // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } } + auto & [ p ] { g }; // { dg-error "cannot decompose class type 'G': both it and its base class 'F' have non-static data members" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } + auto [ q ] { h }; // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } } + auto [ r ] { i }; // { dg-error "cannot decompose class type 'I': its base classes 'F' and 'H' have non-static data members" } + // { dg-warning "decomposition declaration only available with -std=c..1z or -std=gnu..1z" "" { target c++14_down } .-1 } +} diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp5.C b/gcc/testsuite/g++.dg/cpp1z/decomp5.C new file mode 100644 index 00000000000..86b2c22f37a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp5.C @@ -0,0 +1,40 @@ +// { dg-do run { target c++11 } } +// { dg-options "" } + +struct A { int i; long long j; } a[64]; + +int +main () +{ + int i = 0; + for (auto &x : a) + { + x.i = i; + x.j = 2 * i++; + } + for (auto & [ x, y ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + { + x += 2; + y += 3; + } + i = 0; + for (const auto [ u, v ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + { + if (u != i + 2 || v != 2 * i++ + 3) + __builtin_abort (); + } + i = 0; + for (auto [ x, y ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + { + x += 4; + y += 5; + if (x != i + 6 || y != 2 * i++ + 8) + __builtin_abort (); + } + i = 0; + for (const auto x : a) + { + if (x.i != i + 2 || x.j != 2 * i++ + 3) + __builtin_abort (); + } +} diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp6.C b/gcc/testsuite/g++.dg/cpp1z/decomp6.C new file mode 100644 index 00000000000..ed6fce49ec5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp6.C @@ -0,0 +1,92 @@ +// { dg-do run { target c++11 } } +// { dg-options "" } + +int ccnt, dcnt, cccnt, tccnt; + +struct A +{ + A () : a (6) { ccnt++; } + ~A () { dcnt++; } + explicit A (const A &x) : a (x.a) { cccnt++; } + template + A (const T &x) : a (x.a) { tccnt++; } + int a; +}; + +int +main () +{ + if (ccnt || dcnt || cccnt || tccnt) + __builtin_abort (); + { + A a[6]; + if (ccnt != 6 || dcnt || cccnt || tccnt) + __builtin_abort (); + { + auto [b,c,d,e,f,g] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + if (ccnt != 6 || dcnt || cccnt || tccnt != 6) + __builtin_abort (); + b.a++; + c.a += 2; + f.a += 3; + if (b.a != 7 || c.a != 8 || d.a != 6 || e.a != 6 || f.a != 9 || g.a != 6) + __builtin_abort (); + if (&b == &a[0] || &c == &a[1] || &d == &a[2] || &e == &a[3] || &f == &a[4] || &g == &a[5]) + __builtin_abort (); + { + auto&[ h, i, j, k, l, m ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + if (ccnt != 6 || dcnt || cccnt || tccnt != 6) + __builtin_abort (); + j.a += 4; + k.a += 5; + m.a += 6; + if (a[0].a != 6 || a[1].a != 6 || a[2].a != 10 || a[3].a != 11 || a[4].a != 6 || a[5].a != 12) + __builtin_abort (); + if (&h != &a[0] || &i != &a[1] || &j != &a[2] || &k != &a[3] || &l != &a[4] || &m != &a[5]) + __builtin_abort (); + } + if (ccnt != 6 || dcnt || cccnt || tccnt != 6) + __builtin_abort (); + } + if (ccnt != 6 || dcnt != 6 || cccnt || tccnt != 6) + __builtin_abort (); + } + if (ccnt != 6 || dcnt != 12 || cccnt || tccnt != 6) + __builtin_abort (); + + { + A a[6]; + if (ccnt != 12 || dcnt != 12 || cccnt || tccnt != 6) + __builtin_abort (); + { + auto [b,c,d,e,f,g] { a }; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + if (ccnt != 12 || dcnt != 12 || cccnt != 6 || tccnt != 6) + __builtin_abort (); + b.a++; + c.a += 2; + f.a += 3; + if (b.a != 7 || c.a != 8 || d.a != 6 || e.a != 6 || f.a != 9 || g.a != 6) + __builtin_abort (); + if (&b == &a[0] || &c == &a[1] || &d == &a[2] || &e == &a[3] || &f == &a[4] || &g == &a[5]) + __builtin_abort (); + { + auto&[ h, i, j, k, l, m ] {a}; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + if (ccnt != 12 || dcnt != 12 || cccnt != 6 || tccnt != 6) + __builtin_abort (); + j.a += 4; + k.a += 5; + m.a += 6; + if (a[0].a != 6 || a[1].a != 6 || a[2].a != 10 || a[3].a != 11 || a[4].a != 6 || a[5].a != 12) + __builtin_abort (); + if (&h != &a[0] || &i != &a[1] || &j != &a[2] || &k != &a[3] || &l != &a[4] || &m != &a[5]) + __builtin_abort (); + } + if (ccnt != 12 || dcnt != 12 || cccnt != 6 || tccnt != 6) + __builtin_abort (); + } + if (ccnt != 12 || dcnt != 18 || cccnt != 6 || tccnt != 6) + __builtin_abort (); + } + if (ccnt != 12 || dcnt != 24 || cccnt != 6 || tccnt != 6) + __builtin_abort (); +} diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp7.C b/gcc/testsuite/g++.dg/cpp1z/decomp7.C new file mode 100644 index 00000000000..d366adecc4c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp7.C @@ -0,0 +1,60 @@ +// { dg-do run { target c++11 } } +// { dg-options "" } + +int a[2] = { 1, 2 }; +int b[2] = { 4, 5 }; +struct S { int a; signed char b; float c; } sa = { 6, 7, 8.0f }; +S sb = { 9, 10, 11.0f }; + +template +void +foo (T &x, U &y) +{ + auto & [ c, d ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto [ e, f ] = a; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto [ g, h, i ] = sa; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto & [ j, k, l ] = sa; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto & [ m, n ] = x; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto [ o, p ] = x; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto [ q, r, s ] = y; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + auto & [ t, u, v ] = y; // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + c += 1; + e += 2; + g += 3; + j += 4; + m += 5; + o += 6; + q += 7; + t += 8; + if (c != 2 || &c != &a[0] + || d != 2 || &d != &a[1] + || e != 3 || &e == &a[0] + || f != 2 || &f == &a[1] + || g != 9 || &g == &sa.a + || h != 7 || &h == &sa.b + || i != 8.0f || &i == &sa.c + || j != 10 || &j != &sa.a + || k != 7 || &k != &sa.b + || l != 8.0f || &l != &sa.c + || m != 9 || &m != &b[0] + || n != 5 || &n != &b[1] + || o != 10 || &o == &b[0] + || p != 5 || &p == &b[1] + || q != 16 || &q == &sb.a + || r != 10 || &r == &sb.b + || s != 11.0f || &s == &sb.c + || t != 17 || &t != &sb.a + || u != 10 || &u != &sb.b + || v != 11.0f || &v != &sb.c + || a[0] != 2 || a[1] != 2 + || sa.a != 10 || sa.b != 7 || sa.c != 8.0f + || b[0] != 9 || b[1] != 5 + || sb.a != 17 || sb.b != 10 || sb.c != 11.0f) + __builtin_abort (); +} + +int +main () +{ + foo (b, sb); +} diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp8.C b/gcc/testsuite/g++.dg/cpp1z/decomp8.C new file mode 100644 index 00000000000..9e1ea5d5da1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp8.C @@ -0,0 +1,88 @@ +// { dg-do run { target c++11 } } +// { dg-options "" } + +struct A { int i; long long j; } a[64]; +A b[32]; + +template +void +foo (T &b) +{ + int i = 0; + for (auto &x : a) + { + x.i = i; + x.j = 2 * i++; + } + for (auto & [ x, y ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + { + x += 2; + y += 3; + } + i = 0; + for (const auto [ u, v ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + { + if (u != i + 2 || v != 2 * i++ + 3) + __builtin_abort (); + } + i = 0; + for (auto [ x, y ] : a) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + { + x += 4; + y += 5; + if (x != i + 6 || y != 2 * i++ + 8) + __builtin_abort (); + } + i = 0; + for (const auto x : a) + { + if (x.i != i + 2 || x.j != 2 * i++ + 3) + __builtin_abort (); + } + i = 0; + for (auto &x : b) + { + x.i = i; + x.j = 2 * i++; + } + for (auto & [ x, y ] : b) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + { + x -= 2; + y -= 3; + } + i = 0; + for (const auto [ u, v ] : b) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + { + if (u != i - 2 || v != 2 * i++ - 3) + __builtin_abort (); + } + i = 0; + for (auto [ x, y ] : b) // { dg-warning "decomposition declaration only available with" "" { target c++14_down } } + { + x -= 4; + y -= 5; + if (x != i - 6 || y != 2 * i++ - 8) + __builtin_abort (); + } + i = 0; + for (const auto x : b) + { + if (x.i != i - 2 || x.j != 2 * i++ - 3) + __builtin_abort (); + } +} + +int +main () +{ + foo (b); + for (int i = 0; i < 64; i++) + { + if (a[i].i != i + 2 || a[i].j != 2 * i + 3) + __builtin_abort (); + if (i >= 32) + continue; + if (b[i].i != i - 2 || b[i].j != 2 * i - 3) + __builtin_abort (); + } +} diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp9.C b/gcc/testsuite/g++.dg/cpp1z/decomp9.C new file mode 100644 index 00000000000..f7c6f56b8d5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp9.C @@ -0,0 +1,47 @@ +// { dg-do run } +// { dg-options -std=c++1z } + +#define assert(X) do { if (!(X)) __builtin_abort(); } while (0) + +namespace std { + template struct tuple_size; + template struct tuple_element; +} + +struct A { + int i; + template int& get() { return i; } +}; + +template<> struct std::tuple_size { static const int value = 2; }; +template struct std::tuple_element { using type = int; }; + +struct B { + int i; +}; +template int& get(B&& b) { return b.i; } +template int& get(B& b) { return b.i; } + +template<> struct std::tuple_size { static const int value = 2; }; +template struct std::tuple_element { using type = int; }; + +int main() +{ + { + A a = { 42 }; + auto& [ x, y ] = a; + assert (&x == &y && &x == &a.i && x == 42); + + auto [ x2, y2 ] = a; + assert (&x2 == &y2 && &x2 != &a.i && x2 == 42); + } + + { + B b = { 42 }; + auto& [ x, y ] = b; + assert (&x == &y && &x == &b.i && x == 42); + + auto [ x2, y2 ] = b; + assert (&x2 == &y2 && &x2 != &b.i && x2 == 42); + } +} -- 2.30.2