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
This commit is contained in:
Jonathan Wakely 2019-05-20 12:32:51 +01:00 committed by Jonathan Wakely
parent eefa592aa0
commit 58487c21b6
10 changed files with 86 additions and 47 deletions

View File

@ -1,3 +1,9 @@
2019-05-20 Jonathan Wakely <jwakely@redhat.com>
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 <thomas@codesourcery.com>
PR c++/89433

View File

@ -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;

View File

@ -1,3 +1,8 @@
2019-05-20 Jonathan Wakely <jwakely@redhat.com>
PR c++/90532 Ensure __is_constructible(T[]) is false
* g++.dg/ext/90532.C: New test.
2019-05-20 Jakub Jelinek <jakub@redhat.com>
* gcc.target/i386/avx512f-simd-1.c: New test.

View File

@ -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), "" );

View File

@ -1,3 +1,16 @@
2019-05-20 Jonathan Wakely <jwakely@redhat.com>
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 <pbrady@fb.com>
* libstdc++-v3/include/ext/new_allocator.h (deallocate): Pass the size

View File

@ -878,58 +878,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
: public __is_nt_destructible_safe<_Tp>::type
{ };
struct __do_is_default_constructible_impl
{
template<typename _Tp, typename = decltype(_Tp())>
static true_type __test(int);
template<typename>
static false_type __test(...);
};
template<typename _Tp>
struct __is_default_constructible_impl
: public __do_is_default_constructible_impl
{
typedef decltype(__test<_Tp>(0)) type;
};
template<typename _Tp>
struct __is_default_constructible_atom
: public __and_<__not_<is_void<_Tp>>,
__is_default_constructible_impl<_Tp>>
{ };
template<typename _Tp, bool = is_array<_Tp>::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<typename _Tp>
struct __is_default_constructible_safe<_Tp, true>
: public __and_<__is_array_known_bounds<_Tp>,
__is_default_constructible_atom<typename
remove_all_extents<_Tp>::type>>
{ };
template<typename _Tp>
struct __is_default_constructible_safe<_Tp, false>
: public __is_default_constructible_atom<_Tp>::type
/// is_constructible
template<typename _Tp, typename... _Args>
struct is_constructible
: public __bool_constant<__is_constructible(_Tp, _Args...)>
{ };
/// is_default_constructible
template<typename _Tp>
struct is_default_constructible
: public __is_default_constructible_safe<_Tp>::type
{ };
/// is_constructible
template<typename _Tp, typename... _Args>
struct is_constructible
: public __bool_constant<__is_constructible(_Tp, _Args...)>
: public is_constructible<_Tp>::type
{ };
template<typename _Tp, bool = __is_referenceable<_Tp>::value>

View File

@ -35,4 +35,11 @@ void test01()
static_assert(test_property<is_constructible, ExplicitClass>(false), "");
static_assert(test_property<is_constructible, ExplicitClass,
int, double>(false), "");
static_assert(test_property<is_constructible, int[]>(false), "PR c++/90532");
static_assert(test_property<is_constructible,
__gnu_test::construct::Empty[]>(false), "PR c++/90532");
static_assert(test_property<is_constructible,
__gnu_test::construct::Ukn[]>(false), "PR c++/90532");
static_assert(test_property<is_constructible,
__gnu_test::construct::nAny[]>(false), "PR c++/90532");
}

View File

@ -138,3 +138,13 @@ static_assert(!std::is_default_constructible<DelCopy>::value, "Error");
static_assert(!std::is_default_constructible<const DelCopy>::value, "Error");
static_assert(!std::is_default_constructible<DelDtor>::value, "Error");
static_assert(!std::is_default_constructible<const DelDtor>::value, "Error");
static_assert(!std::is_default_constructible<int[]>::value, "PR c++/90532");
static_assert(!std::is_default_constructible<Empty[]>::value, "PR c++/90532");
static_assert(!std::is_default_constructible<B[]>::value, "PR c++/90532");
static_assert(!std::is_default_constructible<D[]>::value, "PR c++/90532");
static_assert(!std::is_default_constructible<U[]>::value, "PR c++/90532");
static_assert(!std::is_default_constructible<Ukn[]>::value, "PR c++/90532");
static_assert(!std::is_default_constructible<Ellipsis[]>::value, "PR c++/90532");
static_assert(!std::is_default_constructible<Any[]>::value, "PR c++/90532");
static_assert(!std::is_default_constructible<nAny[]>::value, "PR c++/90532");

View File

@ -180,4 +180,6 @@ void test01()
MoveOnly, const MoveOnly&>(false), "");
static_assert(test_property<is_trivially_constructible,
MoveOnly2>(false), "");
static_assert(test_property<is_trivially_constructible,
int[]>(false), "PR c++/90532");
}

View File

@ -62,4 +62,13 @@ void test01()
construct::Nontrivial>(false), "");
static_assert(test_category<is_trivially_default_constructible,
HasTemplateCtor>(true), "");
static_assert(test_category<is_trivially_default_constructible,
int[]>(false), "PR c++/90532");
struct A { };
static_assert(test_category<is_trivially_default_constructible,
A[]>(false), "PR c++/90532");
struct B { B() { } };
static_assert(test_category<is_trivially_default_constructible,
B[]>(false), "PR c++/90532");
}