From 58487c21b6a47c3fff6c6958684de866216a5593 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 20 May 2019 12:32:51 +0100 Subject: [PATCH] PR c++/90532 Ensure __is_constructible(T[]) is false An array of an unknown bound is an incomplete type, so no object of such a type can be constructed. This means __is_constructible should always be false for an array of unknown bound. This patch also changes the std::is_default_constructible trait to use std::is_constructible, which now gives the right answer for arrays of unknown bound. gcc/cp: PR c++/90532 Ensure __is_constructible(T[]) is false * method.c (is_xible_helper): Return error_mark_node for construction of an array of unknown bound. gcc/testsuite: PR c++/90532 Ensure __is_constructible(T[]) is false * g++.dg/ext/90532.C: New test. libstdc++-v3: PR c++/90532 Ensure __is_constructible(T[]) is false * include/std/type_traits (__do_is_default_constructible_impl) (__is_default_constructible_atom, __is_default_constructible_safe): Remove. (is_default_constructible): Use is_constructible. * testsuite/20_util/is_constructible/value.cc: Check int[] case. * testsuite/20_util/is_default_constructible/value.cc: Likewise. * testsuite/20_util/is_trivially_constructible/value.cc: Likewise. * testsuite/20_util/is_trivially_default_constructible/value.cc: Likewise. From-SVN: r271412 --- gcc/cp/ChangeLog | 6 +++ gcc/cp/method.c | 2 + gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/ext/90532.C | 27 ++++++++++ libstdc++-v3/ChangeLog | 13 +++++ libstdc++-v3/include/std/type_traits | 52 ++----------------- .../20_util/is_constructible/value.cc | 7 +++ .../20_util/is_default_constructible/value.cc | 10 ++++ .../is_trivially_constructible/value.cc | 2 + .../value.cc | 9 ++++ 10 files changed, 86 insertions(+), 47 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/90532.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 39aaab966c9..c8eb936aec3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2019-05-20 Jonathan Wakely + + PR c++/90532 Ensure __is_constructible(T[]) is false + * method.c (is_xible_helper): Return error_mark_node for construction + of an array of unknown bound. + 2019-05-17 Thomas Schwinge PR c++/89433 diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 3fb3b5a9091..53fa85b9790 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1201,6 +1201,8 @@ is_xible_helper (enum tree_code code, tree to, tree from, bool trivial) expr = assignable_expr (to, from); else if (trivial && from && TREE_CHAIN (from)) return error_mark_node; // only 0- and 1-argument ctors can be trivial + else if (TREE_CODE (to) == ARRAY_TYPE && !TYPE_DOMAIN (to)) + return error_mark_node; // can't construct an array of unknown bound else expr = constructible_expr (to, from); return expr; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3ecff36b7b5..36db11bb183 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-05-20 Jonathan Wakely + + PR c++/90532 Ensure __is_constructible(T[]) is false + * g++.dg/ext/90532.C: New test. + 2019-05-20 Jakub Jelinek * gcc.target/i386/avx512f-simd-1.c: New test. diff --git a/gcc/testsuite/g++.dg/ext/90532.C b/gcc/testsuite/g++.dg/ext/90532.C new file mode 100644 index 00000000000..acdc4e2b07e --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/90532.C @@ -0,0 +1,27 @@ +// { dg-do compile { target c++11 } } +// PR c++/90532 +static_assert( !__is_constructible(int[]), "" ); +static_assert( !__is_constructible(int[], int), "" ); +static_assert( !__is_constructible(int[], int[]), "" ); +static_assert( !__is_trivially_constructible(int[]), "" ); +static_assert( !__is_trivially_constructible(int[], int), "" ); +static_assert( !__is_trivially_constructible(int[], int[]), "" ); +static_assert( !__is_trivially_constructible(int[], int(&)[]), "" ); +static_assert( !__is_trivially_constructible(int[], void), "" ); +struct A { }; +static_assert( !__is_constructible(A[]), "" ); +static_assert( !__is_constructible(A[], const A&), "" ); +static_assert( !__is_constructible(A[], const A[]), "" ); +static_assert( !__is_trivially_constructible(A[]), "" ); +static_assert( !__is_trivially_constructible(A[], const A&), "" ); +static_assert( !__is_trivially_constructible(A[], const A[]), "" ); +static_assert( !__is_trivially_constructible(A[], A(&)[]), "" ); +static_assert( !__is_trivially_constructible(A[], void), "" ); +struct B { B(); }; +static_assert( !__is_constructible(B[]), "" ); +static_assert( !__is_constructible(B[], const B&), "" ); +static_assert( !__is_trivially_constructible(B[]), "" ); +static_assert( !__is_trivially_constructible(B[], const B&), "" ); +static_assert( !__is_trivially_constructible(B[], const B[]), "" ); +static_assert( !__is_trivially_constructible(B[], B(&)[]), "" ); +static_assert( !__is_trivially_constructible(B[], void), "" ); diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 74717dea5a0..c5b8d6016b0 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2019-05-20 Jonathan Wakely + + PR c++/90532 Ensure __is_constructible(T[]) is false + * include/std/type_traits (__do_is_default_constructible_impl) + (__is_default_constructible_atom, __is_default_constructible_safe): + Remove. + (is_default_constructible): Use is_constructible. + * testsuite/20_util/is_constructible/value.cc: Check int[] case. + * testsuite/20_util/is_default_constructible/value.cc: Likewise. + * testsuite/20_util/is_trivially_constructible/value.cc: Likewise. + * testsuite/20_util/is_trivially_default_constructible/value.cc: + Likewise. + 2019-05-20 Pádraig Brady * libstdc++-v3/include/ext/new_allocator.h (deallocate): Pass the size diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index b1c3e943e79..3a622eb61e0 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -878,58 +878,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : public __is_nt_destructible_safe<_Tp>::type { }; - struct __do_is_default_constructible_impl - { - template - static true_type __test(int); - - template - static false_type __test(...); - }; - - template - struct __is_default_constructible_impl - : public __do_is_default_constructible_impl - { - typedef decltype(__test<_Tp>(0)) type; - }; - - template - struct __is_default_constructible_atom - : public __and_<__not_>, - __is_default_constructible_impl<_Tp>> - { }; - - template::value> - struct __is_default_constructible_safe; - - // The following technique is a workaround for a current core language - // restriction, which does not allow for array types to occur in - // functional casts of the form T(). Complete arrays can be default- - // constructed, if the element type is default-constructible, but - // arrays with unknown bounds are not. - template - struct __is_default_constructible_safe<_Tp, true> - : public __and_<__is_array_known_bounds<_Tp>, - __is_default_constructible_atom::type>> - { }; - - template - struct __is_default_constructible_safe<_Tp, false> - : public __is_default_constructible_atom<_Tp>::type + /// is_constructible + template + struct is_constructible + : public __bool_constant<__is_constructible(_Tp, _Args...)> { }; /// is_default_constructible template struct is_default_constructible - : public __is_default_constructible_safe<_Tp>::type - { }; - - /// is_constructible - template - struct is_constructible - : public __bool_constant<__is_constructible(_Tp, _Args...)> + : public is_constructible<_Tp>::type { }; template::value> diff --git a/libstdc++-v3/testsuite/20_util/is_constructible/value.cc b/libstdc++-v3/testsuite/20_util/is_constructible/value.cc index acd7a5f5703..a8b40921d92 100644 --- a/libstdc++-v3/testsuite/20_util/is_constructible/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_constructible/value.cc @@ -35,4 +35,11 @@ void test01() static_assert(test_property(false), ""); static_assert(test_property(false), ""); + static_assert(test_property(false), "PR c++/90532"); + static_assert(test_property(false), "PR c++/90532"); + static_assert(test_property(false), "PR c++/90532"); + static_assert(test_property(false), "PR c++/90532"); } diff --git a/libstdc++-v3/testsuite/20_util/is_default_constructible/value.cc b/libstdc++-v3/testsuite/20_util/is_default_constructible/value.cc index bd66ed0ab92..f6df45d841b 100644 --- a/libstdc++-v3/testsuite/20_util/is_default_constructible/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_default_constructible/value.cc @@ -138,3 +138,13 @@ static_assert(!std::is_default_constructible::value, "Error"); static_assert(!std::is_default_constructible::value, "Error"); static_assert(!std::is_default_constructible::value, "Error"); static_assert(!std::is_default_constructible::value, "Error"); + +static_assert(!std::is_default_constructible::value, "PR c++/90532"); +static_assert(!std::is_default_constructible::value, "PR c++/90532"); +static_assert(!std::is_default_constructible::value, "PR c++/90532"); +static_assert(!std::is_default_constructible::value, "PR c++/90532"); +static_assert(!std::is_default_constructible::value, "PR c++/90532"); +static_assert(!std::is_default_constructible::value, "PR c++/90532"); +static_assert(!std::is_default_constructible::value, "PR c++/90532"); +static_assert(!std::is_default_constructible::value, "PR c++/90532"); +static_assert(!std::is_default_constructible::value, "PR c++/90532"); diff --git a/libstdc++-v3/testsuite/20_util/is_trivially_constructible/value.cc b/libstdc++-v3/testsuite/20_util/is_trivially_constructible/value.cc index 0c8ad62dbbc..0979ceff7e3 100644 --- a/libstdc++-v3/testsuite/20_util/is_trivially_constructible/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_trivially_constructible/value.cc @@ -180,4 +180,6 @@ void test01() MoveOnly, const MoveOnly&>(false), ""); static_assert(test_property(false), ""); + static_assert(test_property(false), "PR c++/90532"); } diff --git a/libstdc++-v3/testsuite/20_util/is_trivially_default_constructible/value.cc b/libstdc++-v3/testsuite/20_util/is_trivially_default_constructible/value.cc index 8baca915df3..f457721925d 100644 --- a/libstdc++-v3/testsuite/20_util/is_trivially_default_constructible/value.cc +++ b/libstdc++-v3/testsuite/20_util/is_trivially_default_constructible/value.cc @@ -62,4 +62,13 @@ void test01() construct::Nontrivial>(false), ""); static_assert(test_category(true), ""); + + static_assert(test_category(false), "PR c++/90532"); + struct A { }; + static_assert(test_category(false), "PR c++/90532"); + struct B { B() { } }; + static_assert(test_category(false), "PR c++/90532"); } -- 2.30.2