PR libstdc++/71579 assert that type traits are not misused with incomplete types
This patch adds static asserts for type traits misuse with incomplete classes and unions. This gives a nice readable error message instead of an UB and odr-violations. Some features of the patch: * each type trait has it's own static_assert inside. This gives better diagnostics than the approach with putting the assert into a helper structure and using it in each trait. * the result of completeness check is not memorized by the compiler. This gives no false positive after the first failed check. * some of the compiler builtins already implement the check. But not all of them! So the asserts are in all the type_traits that may benefit from the check. This also makes the behavior of libstdc++ more consistent across different (non GCC) compilers. * std::is_base_of does not have the assert as it works well in many cases with incomplete types 2019-05-31 Antony Polukhin <antoshkka@gmail.com> PR libstdc++/71579 * include/std/type_traits __type_identity, __is_complete_or_unbounded): New helpers for checking preconditions in traits. (is_trivial, is_trivially_copyable, is_standard_layout, is_pod) (is_literal_type, is_empty, is_polymorphic, is_final, is_abstract) (is_destructible, is_nothrow_destructible, is_constructible) (is_default_constructible, is_copy_constructible) (is_move_constructible, is_nothrow_default_constructible) (is_nothrow_constructible, is_nothrow_copy_constructible) (is_nothrow_move_constructible, is_copy_assignable, is_move_assignable) (is_nothrow_assignable, is_nothrow_copy_assignable) (is_nothrow_move_assignable, is_trivially_constructible) (is_trivially_copy_constructible, is_trivially_move_constructible) is_trivially_assignable, is_trivially_copy_assignable) (is_trivially_move_assignable, is_trivially_destructible) (alignment_of, is_swappable, is_nothrow_swappable, is_invocable) (is_invocable_r, is_nothrow_invocable) (has_unique_object_representations, is_aggregate): Add static_asserts to make sure that type traits are not misused with incomplete types. (__is_constructible_impl, __is_nothrow_default_constructible_impl) (__is_nothrow_constructible_impl, __is_nothrow_assignable_impl): New base characteristics without assertions that can be reused in other traits. * testsuite/20_util/is_complete_or_unbounded/memoization.cc: New test. * testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc: New test. * testsuite/20_util/is_complete_or_unbounded/value.cc: New test. * testsuite/20_util/is_abstract/incomplete_neg.cc: New test. * testsuite/20_util/is_aggregate/incomplete_neg.cc: New test. * testsuite/20_util/is_class/value.cc: Check incomplete type. * testsuite/20_util/is_function/value.cc: Likewise. * testsuite/20_util/is_move_constructible/incomplete_neg.cc: New test. * testsuite/20_util/is_nothrow_move_assignable/incomplete_neg.cc: New test. * testsuite/20_util/is_polymorphic/incomplete_neg.cc: New test. * testsuite/20_util/is_reference/value.cc: Check incomplete types. * testsuite/20_util/is_unbounded_array/value.cc: Likewise. * testsuite/20_util/is_union/value.cc: Likewise. * testsuite/20_util/is_void/value.cc: Likewise. * testsuite/util/testsuite_tr1.h: Add incomplete union type. From-SVN: r271806
This commit is contained in:
parent
aeedf07705
commit
608a080c3f
|
@ -1,3 +1,46 @@
|
|||
2019-05-31 Antony Polukhin <antoshkka@gmail.com>
|
||||
|
||||
PR libstdc++/71579
|
||||
* include/std/type_traits __type_identity, __is_complete_or_unbounded):
|
||||
New helpers for checking preconditions in traits.
|
||||
(is_trivial, is_trivially_copyable, is_standard_layout, is_pod)
|
||||
(is_literal_type, is_empty, is_polymorphic, is_final, is_abstract)
|
||||
(is_destructible, is_nothrow_destructible, is_constructible)
|
||||
(is_default_constructible, is_copy_constructible)
|
||||
(is_move_constructible, is_nothrow_default_constructible)
|
||||
(is_nothrow_constructible, is_nothrow_copy_constructible)
|
||||
(is_nothrow_move_constructible, is_copy_assignable, is_move_assignable)
|
||||
(is_nothrow_assignable, is_nothrow_copy_assignable)
|
||||
(is_nothrow_move_assignable, is_trivially_constructible)
|
||||
(is_trivially_copy_constructible, is_trivially_move_constructible)
|
||||
is_trivially_assignable, is_trivially_copy_assignable)
|
||||
(is_trivially_move_assignable, is_trivially_destructible)
|
||||
(alignment_of, is_swappable, is_nothrow_swappable, is_invocable)
|
||||
(is_invocable_r, is_nothrow_invocable)
|
||||
(has_unique_object_representations, is_aggregate): Add static_asserts
|
||||
to make sure that type traits are not misused with incomplete types.
|
||||
(__is_constructible_impl, __is_nothrow_default_constructible_impl)
|
||||
(__is_nothrow_constructible_impl, __is_nothrow_assignable_impl): New
|
||||
base characteristics without assertions that can be reused in other
|
||||
traits.
|
||||
* testsuite/20_util/is_complete_or_unbounded/memoization.cc: New test.
|
||||
* testsuite/20_util/is_complete_or_unbounded/memoization_neg.cc: New
|
||||
test.
|
||||
* testsuite/20_util/is_complete_or_unbounded/value.cc: New test.
|
||||
* testsuite/20_util/is_abstract/incomplete_neg.cc: New test.
|
||||
* testsuite/20_util/is_aggregate/incomplete_neg.cc: New test.
|
||||
* testsuite/20_util/is_class/value.cc: Check incomplete type.
|
||||
* testsuite/20_util/is_function/value.cc: Likewise.
|
||||
* testsuite/20_util/is_move_constructible/incomplete_neg.cc: New test.
|
||||
* testsuite/20_util/is_nothrow_move_assignable/incomplete_neg.cc: New
|
||||
test.
|
||||
* testsuite/20_util/is_polymorphic/incomplete_neg.cc: New test.
|
||||
* testsuite/20_util/is_reference/value.cc: Check incomplete types.
|
||||
* testsuite/20_util/is_unbounded_array/value.cc: Likewise.
|
||||
* testsuite/20_util/is_union/value.cc: Likewise.
|
||||
* testsuite/20_util/is_void/value.cc: Likewise.
|
||||
* testsuite/util/testsuite_tr1.h: Add incomplete union type.
|
||||
|
||||
2019-05-31 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/bits/random.h (random_device::_M_init(const char*, size_t)):
|
||||
|
|
|
@ -91,6 +91,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<bool, typename, typename>
|
||||
struct conditional;
|
||||
|
||||
template <typename _Type>
|
||||
struct __type_identity {
|
||||
using type = _Type;
|
||||
};
|
||||
|
||||
template<typename...>
|
||||
struct __or_;
|
||||
|
||||
|
@ -177,6 +182,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
#endif // C++17
|
||||
|
||||
// Forward declarations
|
||||
template<typename>
|
||||
struct is_reference;
|
||||
template<typename>
|
||||
struct is_function;
|
||||
template<typename>
|
||||
struct is_void;
|
||||
template<typename>
|
||||
struct __is_array_unknown_bounds;
|
||||
|
||||
// Helper functions that return false_type for incomplete classes,
|
||||
// incomplete unions and arrays of known bound from those.
|
||||
|
||||
template <typename _T, size_t = sizeof(_T)>
|
||||
constexpr true_type __is_complete_or_unbounded(__type_identity<_T>)
|
||||
{ return {}; }
|
||||
|
||||
template <typename _TypeIdentity,
|
||||
typename _NestedType = typename _TypeIdentity::type>
|
||||
constexpr typename __or_<
|
||||
is_reference<_NestedType>,
|
||||
is_function<_NestedType>,
|
||||
is_void<_NestedType>,
|
||||
__is_array_unknown_bounds<_NestedType>
|
||||
>::type __is_complete_or_unbounded(_TypeIdentity)
|
||||
{ return {}; }
|
||||
|
||||
// For several sfinae-friendly trait implementations we transport both the
|
||||
// result information (as the member type) and the failure information (no
|
||||
// member type). This is very similar to std::enable_if, but we cannot use
|
||||
|
@ -398,9 +430,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
struct is_rvalue_reference<_Tp&&>
|
||||
: public true_type { };
|
||||
|
||||
template<typename>
|
||||
struct is_function;
|
||||
|
||||
template<typename>
|
||||
struct __is_member_object_pointer_helper
|
||||
: public false_type { };
|
||||
|
@ -671,44 +700,65 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _Tp>
|
||||
struct is_trivial
|
||||
: public integral_constant<bool, __is_trivial(_Tp)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
// is_trivially_copyable
|
||||
template<typename _Tp>
|
||||
struct is_trivially_copyable
|
||||
: public integral_constant<bool, __is_trivially_copyable(_Tp)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_standard_layout
|
||||
template<typename _Tp>
|
||||
struct is_standard_layout
|
||||
: public integral_constant<bool, __is_standard_layout(_Tp)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_pod
|
||||
// Could use is_standard_layout && is_trivial instead of the builtin.
|
||||
template<typename _Tp>
|
||||
struct is_pod
|
||||
: public integral_constant<bool, __is_pod(_Tp)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_literal_type
|
||||
template<typename _Tp>
|
||||
struct is_literal_type
|
||||
: public integral_constant<bool, __is_literal_type(_Tp)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_empty
|
||||
template<typename _Tp>
|
||||
struct is_empty
|
||||
: public integral_constant<bool, __is_empty(_Tp)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_polymorphic
|
||||
template<typename _Tp>
|
||||
struct is_polymorphic
|
||||
: public integral_constant<bool, __is_polymorphic(_Tp)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
#define __cpp_lib_is_final 201402L
|
||||
|
@ -716,14 +766,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _Tp>
|
||||
struct is_final
|
||||
: public integral_constant<bool, __is_final(_Tp)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
#endif
|
||||
|
||||
/// is_abstract
|
||||
template<typename _Tp>
|
||||
struct is_abstract
|
||||
: public integral_constant<bool, __is_abstract(_Tp)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp,
|
||||
bool = is_arithmetic<_Tp>::value>
|
||||
|
@ -828,7 +884,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _Tp>
|
||||
struct is_destructible
|
||||
: public __is_destructible_safe<_Tp>::type
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
// is_nothrow_destructible requires that is_destructible is
|
||||
// satisfied as well. We realize that by mimicing the
|
||||
|
@ -876,19 +935,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _Tp>
|
||||
struct is_nothrow_destructible
|
||||
: public __is_nt_destructible_safe<_Tp>::type
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
struct __is_constructible_impl
|
||||
: public __bool_constant<__is_constructible(_Tp, _Args...)>
|
||||
{ };
|
||||
|
||||
/// is_constructible
|
||||
template<typename _Tp, typename... _Args>
|
||||
struct is_constructible
|
||||
: public __bool_constant<__is_constructible(_Tp, _Args...)>
|
||||
{ };
|
||||
: public __is_constructible_impl<_Tp, _Args...>
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_default_constructible
|
||||
template<typename _Tp>
|
||||
struct is_default_constructible
|
||||
: public is_constructible<_Tp>::type
|
||||
{ };
|
||||
: public __is_constructible_impl<_Tp>::type
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_copy_constructible_impl;
|
||||
|
@ -899,14 +972,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
struct __is_copy_constructible_impl<_Tp, true>
|
||||
: public is_constructible<_Tp, const _Tp&>
|
||||
: public __is_constructible_impl<_Tp, const _Tp&>
|
||||
{ };
|
||||
|
||||
/// is_copy_constructible
|
||||
template<typename _Tp>
|
||||
struct is_copy_constructible
|
||||
: public __is_copy_constructible_impl<_Tp>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_move_constructible_impl;
|
||||
|
@ -917,14 +993,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
struct __is_move_constructible_impl<_Tp, true>
|
||||
: public is_constructible<_Tp, _Tp&&>
|
||||
: public __is_constructible_impl<_Tp, _Tp&&>
|
||||
{ };
|
||||
|
||||
/// is_move_constructible
|
||||
template<typename _Tp>
|
||||
struct is_move_constructible
|
||||
: public __is_move_constructible_impl<_Tp>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
struct __is_nt_default_constructible_atom
|
||||
|
@ -946,12 +1025,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
: public __is_nt_default_constructible_atom<_Tp>
|
||||
{ };
|
||||
|
||||
template<typename _Tp>
|
||||
using __is_nothrow_default_constructible_impl
|
||||
= __and_<__is_constructible_impl<_Tp>,
|
||||
__is_nt_default_constructible_impl<_Tp>>;
|
||||
|
||||
/// is_nothrow_default_constructible
|
||||
template<typename _Tp>
|
||||
struct is_nothrow_default_constructible
|
||||
: public __and_<is_default_constructible<_Tp>,
|
||||
__is_nt_default_constructible_impl<_Tp>>
|
||||
{ };
|
||||
: public __is_nothrow_default_constructible_impl<_Tp>::type
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
struct __is_nt_constructible_impl
|
||||
|
@ -966,15 +1052,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
struct __is_nt_constructible_impl<_Tp>
|
||||
: public is_nothrow_default_constructible<_Tp>
|
||||
: public __is_nothrow_default_constructible_impl<_Tp>
|
||||
{ };
|
||||
|
||||
template<typename _Tp, typename... _Args>
|
||||
struct __is_nothrow_constructible_impl
|
||||
: public __and_<__is_constructible_impl<_Tp, _Args...>,
|
||||
__is_nt_constructible_impl<_Tp, _Args...>>
|
||||
{ };
|
||||
|
||||
/// is_nothrow_constructible
|
||||
template<typename _Tp, typename... _Args>
|
||||
struct is_nothrow_constructible
|
||||
: public __and_<is_constructible<_Tp, _Args...>,
|
||||
__is_nt_constructible_impl<_Tp, _Args...>>
|
||||
{ };
|
||||
: public __is_nothrow_constructible_impl<_Tp, _Args...>::type
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_nothrow_copy_constructible_impl;
|
||||
|
@ -985,14 +1079,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
struct __is_nothrow_copy_constructible_impl<_Tp, true>
|
||||
: public is_nothrow_constructible<_Tp, const _Tp&>
|
||||
: public __is_nothrow_constructible_impl<_Tp, const _Tp&>
|
||||
{ };
|
||||
|
||||
/// is_nothrow_copy_constructible
|
||||
template<typename _Tp>
|
||||
struct is_nothrow_copy_constructible
|
||||
: public __is_nothrow_copy_constructible_impl<_Tp>
|
||||
{ };
|
||||
: public __is_nothrow_copy_constructible_impl<_Tp>::type
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_nothrow_move_constructible_impl;
|
||||
|
@ -1003,20 +1100,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
struct __is_nothrow_move_constructible_impl<_Tp, true>
|
||||
: public is_nothrow_constructible<_Tp, _Tp&&>
|
||||
: public __is_nothrow_constructible_impl<_Tp, _Tp&&>
|
||||
{ };
|
||||
|
||||
/// is_nothrow_move_constructible
|
||||
template<typename _Tp>
|
||||
struct is_nothrow_move_constructible
|
||||
: public __is_nothrow_move_constructible_impl<_Tp>
|
||||
{ };
|
||||
: public __is_nothrow_move_constructible_impl<_Tp>::type
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_assignable
|
||||
template<typename _Tp, typename _Up>
|
||||
struct is_assignable
|
||||
: public __bool_constant<__is_assignable(_Tp, _Up)>
|
||||
{ };
|
||||
: public __bool_constant<__is_assignable(_Tp, _Up)>
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_copy_assignable_impl;
|
||||
|
@ -1027,14 +1130,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
struct __is_copy_assignable_impl<_Tp, true>
|
||||
: public is_assignable<_Tp&, const _Tp&>
|
||||
: public __bool_constant<__is_assignable(_Tp&, const _Tp&)>
|
||||
{ };
|
||||
|
||||
/// is_copy_assignable
|
||||
template<typename _Tp>
|
||||
struct is_copy_assignable
|
||||
: public __is_copy_assignable_impl<_Tp>
|
||||
{ };
|
||||
: public __is_copy_assignable_impl<_Tp>::type
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_move_assignable_impl;
|
||||
|
@ -1045,26 +1151,37 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
struct __is_move_assignable_impl<_Tp, true>
|
||||
: public is_assignable<_Tp&, _Tp&&>
|
||||
: public __bool_constant<__is_assignable(_Tp&, _Tp&&)>
|
||||
{ };
|
||||
|
||||
/// is_move_assignable
|
||||
template<typename _Tp>
|
||||
struct is_move_assignable
|
||||
: public __is_move_assignable_impl<_Tp>
|
||||
{ };
|
||||
: public __is_move_assignable_impl<_Tp>::type
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __is_nt_assignable_impl
|
||||
: public integral_constant<bool, noexcept(declval<_Tp>() = declval<_Up>())>
|
||||
{ };
|
||||
|
||||
template<typename _Tp, typename _Up>
|
||||
struct __is_nothrow_assignable_impl
|
||||
: public __and_<__bool_constant<__is_assignable(_Tp, _Up)>,
|
||||
__is_nt_assignable_impl<_Tp, _Up>>
|
||||
{ };
|
||||
|
||||
/// is_nothrow_assignable
|
||||
template<typename _Tp, typename _Up>
|
||||
struct is_nothrow_assignable
|
||||
: public __and_<is_assignable<_Tp, _Up>,
|
||||
__is_nt_assignable_impl<_Tp, _Up>>
|
||||
{ };
|
||||
: public __is_nothrow_assignable_impl<_Tp, _Up>
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_nt_copy_assignable_impl;
|
||||
|
@ -1075,14 +1192,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
struct __is_nt_copy_assignable_impl<_Tp, true>
|
||||
: public is_nothrow_assignable<_Tp&, const _Tp&>
|
||||
: public __is_nothrow_assignable_impl<_Tp&, const _Tp&>
|
||||
{ };
|
||||
|
||||
/// is_nothrow_copy_assignable
|
||||
template<typename _Tp>
|
||||
struct is_nothrow_copy_assignable
|
||||
: public __is_nt_copy_assignable_impl<_Tp>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_nt_move_assignable_impl;
|
||||
|
@ -1093,26 +1213,35 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
struct __is_nt_move_assignable_impl<_Tp, true>
|
||||
: public is_nothrow_assignable<_Tp&, _Tp&&>
|
||||
: public __is_nothrow_assignable_impl<_Tp&, _Tp&&>
|
||||
{ };
|
||||
|
||||
/// is_nothrow_move_assignable
|
||||
template<typename _Tp>
|
||||
struct is_nothrow_move_assignable
|
||||
: public __is_nt_move_assignable_impl<_Tp>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_trivially_constructible
|
||||
template<typename _Tp, typename... _Args>
|
||||
struct is_trivially_constructible
|
||||
: public __bool_constant<__is_trivially_constructible(_Tp, _Args...)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_trivially_default_constructible
|
||||
template<typename _Tp>
|
||||
struct is_trivially_default_constructible
|
||||
: public is_trivially_constructible<_Tp>::type
|
||||
{ };
|
||||
: public __bool_constant<__is_trivially_constructible(_Tp)>
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
struct __do_is_implicitly_default_constructible_impl
|
||||
{
|
||||
|
@ -1140,12 +1269,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template <typename _Tp>
|
||||
struct __is_implicitly_default_constructible
|
||||
: public __and_<is_default_constructible<_Tp>,
|
||||
: public __and_<__is_constructible_impl<_Tp>,
|
||||
__is_implicitly_default_constructible_safe<_Tp>>
|
||||
{ };
|
||||
|
||||
/// is_trivially_copy_constructible
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_trivially_copy_constructible_impl;
|
||||
|
||||
|
@ -1155,17 +1282,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
struct __is_trivially_copy_constructible_impl<_Tp, true>
|
||||
: public __and_<is_copy_constructible<_Tp>,
|
||||
: public __and_<__is_copy_constructible_impl<_Tp>,
|
||||
integral_constant<bool,
|
||||
__is_trivially_constructible(_Tp, const _Tp&)>>
|
||||
{ };
|
||||
|
||||
/// is_trivially_copy_constructible
|
||||
template<typename _Tp>
|
||||
struct is_trivially_copy_constructible
|
||||
: public __is_trivially_copy_constructible_impl<_Tp>
|
||||
{ };
|
||||
|
||||
/// is_trivially_move_constructible
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_trivially_move_constructible_impl;
|
||||
|
@ -1176,23 +1305,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
template<typename _Tp>
|
||||
struct __is_trivially_move_constructible_impl<_Tp, true>
|
||||
: public __and_<is_move_constructible<_Tp>,
|
||||
: public __and_<__is_move_constructible_impl<_Tp>,
|
||||
integral_constant<bool,
|
||||
__is_trivially_constructible(_Tp, _Tp&&)>>
|
||||
{ };
|
||||
|
||||
/// is_trivially_move_constructible
|
||||
template<typename _Tp>
|
||||
struct is_trivially_move_constructible
|
||||
: public __is_trivially_move_constructible_impl<_Tp>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_trivially_assignable
|
||||
template<typename _Tp, typename _Up>
|
||||
struct is_trivially_assignable
|
||||
: public __bool_constant<__is_trivially_assignable(_Tp, _Up)>
|
||||
{ };
|
||||
|
||||
/// is_trivially_copy_assignable
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_trivially_copy_assignable_impl;
|
||||
|
@ -1206,12 +1340,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
: public __bool_constant<__is_trivially_assignable(_Tp&, const _Tp&)>
|
||||
{ };
|
||||
|
||||
/// is_trivially_copy_assignable
|
||||
template<typename _Tp>
|
||||
struct is_trivially_copy_assignable
|
||||
: public __is_trivially_copy_assignable_impl<_Tp>
|
||||
{ };
|
||||
|
||||
/// is_trivially_move_assignable
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp, bool = __is_referenceable<_Tp>::value>
|
||||
struct __is_trivially_move_assignable_impl;
|
||||
|
@ -1225,24 +1361,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
: public __bool_constant<__is_trivially_assignable(_Tp&, _Tp&&)>
|
||||
{ };
|
||||
|
||||
/// is_trivially_move_assignable
|
||||
template<typename _Tp>
|
||||
struct is_trivially_move_assignable
|
||||
: public __is_trivially_move_assignable_impl<_Tp>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_trivially_destructible
|
||||
template<typename _Tp>
|
||||
struct is_trivially_destructible
|
||||
: public __and_<is_destructible<_Tp>,
|
||||
: public __and_<__is_destructible_safe<_Tp>,
|
||||
__bool_constant<__has_trivial_destructor(_Tp)>>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
|
||||
/// has_virtual_destructor
|
||||
template<typename _Tp>
|
||||
struct has_virtual_destructor
|
||||
: public integral_constant<bool, __has_virtual_destructor(_Tp)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
|
||||
// type property queries.
|
||||
|
@ -1250,7 +1396,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
/// alignment_of
|
||||
template<typename _Tp>
|
||||
struct alignment_of
|
||||
: public integral_constant<std::size_t, alignof(_Tp)> { };
|
||||
: public integral_constant<std::size_t, alignof(_Tp)>
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// rank
|
||||
template<typename>
|
||||
|
@ -1336,7 +1486,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
: public __is_convertible_helper<_From, _To>::type
|
||||
{ };
|
||||
|
||||
template<typename _From, typename _To,
|
||||
template<typename _From, typename _To,
|
||||
bool = __or_<is_void<_From>, is_function<_To>,
|
||||
is_array<_To>>::value>
|
||||
struct __is_nt_convertible_helper
|
||||
|
@ -2577,13 +2727,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _Tp>
|
||||
struct is_swappable
|
||||
: public __is_swappable_impl<_Tp>::type
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_nothrow_swappable
|
||||
template<typename _Tp>
|
||||
struct is_nothrow_swappable
|
||||
: public __is_nothrow_swappable_impl<_Tp>::type
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
/// is_swappable_v
|
||||
|
@ -2774,20 +2930,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
template<typename _Fn, typename... _ArgTypes>
|
||||
struct is_invocable
|
||||
: __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
|
||||
"_Fn must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// std::is_invocable_r
|
||||
template<typename _Ret, typename _Fn, typename... _ArgTypes>
|
||||
struct is_invocable_r
|
||||
: __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>::type
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
|
||||
"_Fn must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// std::is_nothrow_invocable
|
||||
template<typename _Fn, typename... _ArgTypes>
|
||||
struct is_nothrow_invocable
|
||||
: __and_<__is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>,
|
||||
__call_is_nothrow_<_Fn, _ArgTypes...>>::type
|
||||
{ };
|
||||
__call_is_nothrow_<_Fn, _ArgTypes...>>::type
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}),
|
||||
"_Fn must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Result, typename _Ret, typename = void>
|
||||
struct __is_nt_invocable_impl : false_type { };
|
||||
|
@ -2993,7 +3158,10 @@ template <typename _From, typename _To>
|
|||
: bool_constant<__has_unique_object_representations(
|
||||
remove_cv_t<remove_all_extents_t<_Tp>>
|
||||
)>
|
||||
{ };
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
template<typename _Tp>
|
||||
inline constexpr bool has_unique_object_representations_v
|
||||
|
@ -3005,7 +3173,11 @@ template <typename _From, typename _To>
|
|||
/// is_aggregate
|
||||
template<typename _Tp>
|
||||
struct is_aggregate
|
||||
: bool_constant<__is_aggregate(remove_cv_t<_Tp>)> { };
|
||||
: bool_constant<__is_aggregate(remove_cv_t<_Tp>)>
|
||||
{
|
||||
static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}),
|
||||
"template argument must be a complete class or an unbounded array");
|
||||
};
|
||||
|
||||
/// is_aggregate_v
|
||||
template<typename _Tp>
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// { dg-prune-output "invalid use of incomplete type" }
|
||||
// { dg-prune-output "must be a complete" }
|
||||
//
|
||||
// Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
class X;
|
||||
|
||||
void test01()
|
||||
{
|
||||
std::is_abstract<X>(); // { dg-error "required from here" }
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// { dg-do compile { target c++17 } }
|
||||
//
|
||||
// Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-error "must be a complete class" "" { target *-*-* } 0 }
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
class X;
|
||||
|
||||
void test01()
|
||||
{
|
||||
std::is_aggregate<X>(); // { dg-error "required from here" }
|
||||
}
|
|
@ -27,6 +27,7 @@ void test01()
|
|||
|
||||
// Positive tests.
|
||||
static_assert(test_category<is_class, ClassType>(true), "");
|
||||
static_assert(test_category<is_class, IncompleteClass>(true), "");
|
||||
static_assert(test_category<is_class, DerivedType>(true), "");
|
||||
static_assert(test_category<is_class, ConvType>(true), "");
|
||||
static_assert(test_category<is_class, AbstractClass>(true), "");
|
||||
|
@ -47,4 +48,5 @@ void test01()
|
|||
static_assert(test_category<is_class, int (ClassType::*) (int)>(false), "");
|
||||
static_assert(test_category<is_class, int (int)>(false), "");
|
||||
static_assert(test_category<is_class, EnumType>(false), "");
|
||||
static_assert(test_category<is_class, IncompleteUnion>(false), "");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
// Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
struct X;
|
||||
static_assert(
|
||||
!std::__is_complete_or_unbounded(std::__type_identity<X>{}), "error");
|
||||
|
||||
struct X{};
|
||||
static_assert(
|
||||
std::__is_complete_or_unbounded(std::__type_identity<X>{}),
|
||||
"Result memoized. This leads to worse diagnostics");
|
|
@ -0,0 +1,27 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// { dg-prune-output "must be a complete" }
|
||||
|
||||
// Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
struct X;
|
||||
constexpr bool res_incomplete = std::is_move_constructible<X>::value; // { dg-error "required from here" }
|
||||
|
||||
struct X{};
|
||||
constexpr bool res_complete = std::is_default_constructible<X>::value; // { dg-bogus "required from here" }
|
|
@ -0,0 +1,100 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
|
||||
// Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
struct incomplete_type;
|
||||
class incomplete_type2;
|
||||
union incomplete_union;
|
||||
enum class incomplete_enum: int;
|
||||
enum incomplete_enum2: int;
|
||||
static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_type>{}), "");
|
||||
static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_type2>{}), "");
|
||||
static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_union>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum2>{}), "");
|
||||
|
||||
static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_type[42]>{}), "");
|
||||
static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_type2[42]>{}), "");
|
||||
static_assert(!std::__is_complete_or_unbounded(std::__type_identity<incomplete_union[42]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum[42]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum2[42]>{}), "");
|
||||
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_type[]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_type2[]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_union[]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum[]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_enum2[]>{}), "");
|
||||
|
||||
|
||||
struct complete_type{ ~complete_type() = delete; };
|
||||
class complete_type2{ int i; };
|
||||
union complete_union{};
|
||||
enum class complete_enum: int {};
|
||||
enum complete_enum2: int {};
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type2>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_union>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum2>{}), "");
|
||||
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type[42]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type2[42]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_union[42]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum[42]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum2[42]>{}), "");
|
||||
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type[]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type2[]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_union[]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum[]>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_enum2[]>{}), "");
|
||||
|
||||
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_type>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_type2>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_union>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_enum>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_enum2>{}), "");
|
||||
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_type*>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type*>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<const incomplete_type*>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<const complete_type*>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_type&>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type&>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<incomplete_type&&>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<complete_type&&>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<int complete_type::*>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<int (complete_type::*)(int)>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<int incomplete_type::*>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<int (incomplete_type::*)(int)>{}), "");
|
||||
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(*)() noexcept>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(...) noexcept>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(&)(int)>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(*)()>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(incomplete_type)>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<void(&)()>{}), "");
|
||||
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<std::nullptr_t>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<void>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<void*>{}), "");
|
||||
static_assert(std::__is_complete_or_unbounded(std::__type_identity<const void* const>{}), "");
|
|
@ -46,4 +46,6 @@ void test01()
|
|||
|
||||
// Sanity check.
|
||||
static_assert(test_category<is_function, ClassType>(false), "");
|
||||
static_assert(test_category<is_function, IncompleteClass>(false), "");
|
||||
static_assert(test_category<is_function, IncompleteUnion>(false), "");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
//
|
||||
// Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-error "must be a complete class" "" { target *-*-* } 0 }
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
class X;
|
||||
|
||||
void test01()
|
||||
{
|
||||
std::is_move_constructible<X>(); // { dg-error "required from here" }
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
//
|
||||
// Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
// { dg-error "must be a complete class" "" { target *-*-* } 0 }
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
class X;
|
||||
|
||||
void test01()
|
||||
{
|
||||
std::is_nothrow_move_assignable<X>(); // { dg-error "required from here" }
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// { dg-do compile { target c++11 } }
|
||||
// { dg-prune-output "invalid use of incomplete type" }
|
||||
// { dg-prune-output "must be a complete" }
|
||||
//
|
||||
// Copyright (C) 2019 Free Software Foundation, Inc.
|
||||
//
|
||||
// This file is part of the GNU ISO C++ Library. This library is free
|
||||
// software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU General Public License as published by the
|
||||
// Free Software Foundation; either version 3, or (at your option)
|
||||
// any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this library; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
class X;
|
||||
|
||||
void test01()
|
||||
{
|
||||
std::is_polymorphic<X>(); // { dg-error "required from here" }
|
||||
}
|
|
@ -33,8 +33,11 @@ void test01()
|
|||
static_assert(test_category<is_reference, int&&>(true), "");
|
||||
static_assert(test_category<is_reference, ClassType&&>(true), "");
|
||||
static_assert(test_category<is_reference, int(&&)(int)>(true), "");
|
||||
static_assert(test_category<is_reference, IncompleteClass&>(true), "");
|
||||
static_assert(test_category<is_reference, const IncompleteClass&>(true), "");
|
||||
|
||||
// Sanity check.
|
||||
static_assert(test_category<is_reference, ClassType>(false), "");
|
||||
static_assert(test_category<is_reference, IncompleteClass>(false), "");
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,8 @@ void test01()
|
|||
static_assert(test_category<is_unbounded_array, ClassType[]>(true), "");
|
||||
static_assert(test_category<is_unbounded_array, ClassType[2][3]>(false), "");
|
||||
static_assert(test_category<is_unbounded_array, ClassType[][3]>(true), "");
|
||||
static_assert(test_category<is_unbounded_array, IncompleteClass[2][3]>(false), "");
|
||||
static_assert(test_category<is_unbounded_array, IncompleteClass[][3]>(true), "");
|
||||
static_assert(test_category<is_unbounded_array, int(*)[2]>(false), "");
|
||||
static_assert(test_category<is_unbounded_array, int(*)[]>(false), "");
|
||||
static_assert(test_category<is_unbounded_array, int(&)[2]>(false), "");
|
||||
|
@ -51,6 +53,8 @@ void test01()
|
|||
|
||||
// Sanity check.
|
||||
static_assert(test_category<is_unbounded_array, ClassType>(false), "");
|
||||
static_assert(test_category<is_unbounded_array, IncompleteClass>(false), "");
|
||||
static_assert(test_category<is_unbounded_array, IncompleteUnion>(false), "");
|
||||
}
|
||||
|
||||
template <class... T> void pos()
|
||||
|
|
|
@ -27,6 +27,7 @@ void test01()
|
|||
|
||||
// Positive tests.
|
||||
static_assert(test_category<is_union, UnionType>(true), "");
|
||||
static_assert(test_category<is_union, IncompleteUnion>(true), "");
|
||||
|
||||
// Negative tests.
|
||||
static_assert(test_category<is_union, ClassType>(false), "");
|
||||
|
@ -47,4 +48,5 @@ void test01()
|
|||
static_assert(test_category<is_union, int (ClassType::*) (int)>(false), "");
|
||||
static_assert(test_category<is_union, int (int)>(false), "");
|
||||
static_assert(test_category<is_union, EnumType>(false), "");
|
||||
static_assert(test_category<is_union, IncompleteClass>(false), "");
|
||||
}
|
||||
|
|
|
@ -47,4 +47,6 @@ void test01()
|
|||
|
||||
// Sanity check.
|
||||
static_assert(test_category<is_void, ClassType>(false), "");
|
||||
static_assert(test_category<is_void, IncompleteClass>(false), "");
|
||||
static_assert(test_category<is_void, IncompleteUnion>(false), "");
|
||||
}
|
||||
|
|
|
@ -126,6 +126,8 @@ namespace __gnu_test
|
|||
|
||||
union UnionType { };
|
||||
|
||||
union IncompleteUnion;
|
||||
|
||||
class IncompleteClass;
|
||||
|
||||
struct ExplicitClass
|
||||
|
|
Loading…
Reference in New Issue