Tested on x86_64-pc-linux-gnu, ok for trunk? I'll also update cxx-status.html.
-- >8 -- This proposal was implemented a long time ago by my r9-5271, but it took me this long to verify that it still works as per P2308. This patch adds assorted tests, both from clang and from [temp.arg.nontype]. Fortunately I did not discover any issues in the compiler. PR c++/113800 DR 2450 gcc/testsuite/ChangeLog: * g++.dg/cpp26/pack-indexing15.C: New test. * g++.dg/cpp2a/nontype-class68.C: New test. * g++.dg/cpp2a/nontype-class69.C: New test. * g++.dg/cpp2a/nontype-class70.C: New test. * g++.dg/cpp2a/nontype-class71.C: New test. * g++.dg/cpp2a/nontype-class72.C: New test. --- gcc/testsuite/g++.dg/cpp26/pack-indexing15.C | 20 +++++++++ gcc/testsuite/g++.dg/cpp2a/nontype-class68.C | 24 ++++++++++ gcc/testsuite/g++.dg/cpp2a/nontype-class69.C | 27 +++++++++++ gcc/testsuite/g++.dg/cpp2a/nontype-class70.C | 47 ++++++++++++++++++++ gcc/testsuite/g++.dg/cpp2a/nontype-class71.C | 19 ++++++++ gcc/testsuite/g++.dg/cpp2a/nontype-class72.C | 41 +++++++++++++++++ 6 files changed, 178 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp26/pack-indexing15.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class68.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class69.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class70.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class71.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/nontype-class72.C diff --git a/gcc/testsuite/g++.dg/cpp26/pack-indexing15.C b/gcc/testsuite/g++.dg/cpp26/pack-indexing15.C new file mode 100644 index 00000000000..3f8382b12cd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp26/pack-indexing15.C @@ -0,0 +1,20 @@ +// PR c++/113800 +// { dg-do compile { target c++26 } } +// From LLVM's temp_arg_nontype_cxx2c.cpp. + +template<class... T> +concept C = sizeof(T...[1]) == 1; + +struct A {}; + +template<class T, C<T> auto = A{}> struct Set {}; + +template<class T> +void +foo () +{ + Set<T> u; +} + +Set<bool> sb; +Set<float> sf; // { dg-error "placeholder constraints not satisfied" } diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class68.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class68.C new file mode 100644 index 00000000000..ade646e391b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class68.C @@ -0,0 +1,24 @@ +// PR c++/113800 +// { dg-do compile { target c++20 } } +// From [temp.arg.nontype]. + +template<auto n> struct B { /* ... */ }; +B<5> b1; // OK, template parameter type is int +B<'a'> b2; // OK, template parameter type is char +B<2.5> b3; // OK, template parameter type is double +B<void(0)> b4; // { dg-error ".void. is not a valid type for a template non-type parameter" } + +template<int i> struct C { /* ... */ }; +C<{ 42 }> c1; // OK + +struct J1 { + J1 *self = this; +}; +B<J1{}> j1; // { dg-error "not a constant expression" } + +struct J2 { + J2 *self = this; + constexpr J2() {} + constexpr J2(const J2&) {} +}; +B<J2{}> j2; // { dg-error "not a constant expression" } diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class69.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class69.C new file mode 100644 index 00000000000..08b0a5ef73c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class69.C @@ -0,0 +1,27 @@ +// PR c++/113800 +// { dg-do compile { target c++20 } } + +// DR 2450 +struct S { int a; }; + +template<S s> +void +f () +{ +} + +void +test () +{ + f<{0}>(); + f<{.a= 0}>(); +} + +// DR 2459 +struct A { + constexpr A (float) {} +}; + +template<A> +struct X {}; +X<1> x; diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class70.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class70.C new file mode 100644 index 00000000000..0e50847e440 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class70.C @@ -0,0 +1,47 @@ +// PR c++/113800 +// P2308R1 - Template parameter initialization +// { dg-do compile { target c++20 } } + +struct S { + int a = 0; + int b = 42; +}; + +template <S t> +struct A { + static constexpr auto a = t.a; + static constexpr auto b = t.b; +}; + +static_assert(A<{}>::a == 0); +static_assert(A<{}>::b == 42); +static_assert(A<{.a = 3}>::a == 3); +static_assert(A<{.b = 4}>::b == 4); + +template<S = {}> +struct D1 {}; + +template<S = {1, 2}> +struct D2 {}; + +template <S = {.b = 5}> +struct D3 {}; + +struct E {}; + +struct I { + constexpr I(E) {}; +}; + +template<typename T, T> +struct W {}; + +void +g () +{ + D1<> d1; + D2<> d2; + D3<> d3; + + W<I, {E{}}> w; +} diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class71.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class71.C new file mode 100644 index 00000000000..36ce5b16dee --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class71.C @@ -0,0 +1,19 @@ +// PR c++/113800 +// { dg-do compile { target c++20 } } +// From LLVM's temp_arg_nontype_cxx2c.cpp. + +template<class T, int I> +struct A { + T x[I]; +}; + +template<class T, class... U> +A(T, U...) -> A<T, 1 + sizeof...(U)>; + +template<A a> void foo() { } + +void +bar () +{ + foo<{1}>(); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class72.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class72.C new file mode 100644 index 00000000000..1c48ff57add --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class72.C @@ -0,0 +1,41 @@ +// PR c++/113800 +// P2308R1 - Template parameter initialization +// { dg-do compile { target c++20 } } +// Invalid cases. + +namespace std { +template <typename T> class initializer_list { + const T *_M_array; + decltype (sizeof 0) _M_len; +}; +} + +template<auto> +struct X {}; + +struct A { + int i; +}; + +template<A> +struct B { }; + +struct E {}; + +struct I { // { dg-message "not literal" } + I(E) {}; +}; + +template<typename T, T> +struct W {}; + +void +g () +{ + X<{0}> x; // { dg-error "unable to deduce" } + + int i = 42; // { dg-message "not const" } + B<{i}> b; // { dg-error "not usable" } + + W<I, {E{}}> w; // { dg-error "not a valid type for a template non-type parameter" } +} base-commit: cfdb961588ba318a78e995d2e2cde43130acd993 -- 2.48.1