diff --git a/src/libcxx/header_test.cpp b/src/libcxx/header_test.cpp index daac2dfce..44bd33564 100644 --- a/src/libcxx/header_test.cpp +++ b/src/libcxx/header_test.cpp @@ -1,4 +1,5 @@ #include <__config> +#include #include #include #include diff --git a/src/libcxx/include/concepts b/src/libcxx/include/concepts index 4beec7265..2c77fc624 100644 --- a/src/libcxx/include/concepts +++ b/src/libcxx/include/concepts @@ -1,30 +1,56 @@ -// -*- C++ -*- -#ifndef _EZCXX_CONCEPTS -#define _EZCXX_CONCEPTS - -#include - -#pragma clang system_header - -namespace std { - -template -concept same_as = is_same<_Tp, _Up>::value && is_same<_Up, _Tp>::value; - -// arithmetic: - -template -concept integral = is_integral_v<_Tp>; - -template -concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; - -template -concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; - -template -concept floating_point = is_floating_point_v<_Tp>; - -} // namespace std - -#endif // _EZCXX_CONCEPTS +// -*- C++ -*- +#ifndef _EZCXX_CONCEPTS +#define _EZCXX_CONCEPTS + +#include + +#pragma clang system_header + +namespace std { + +template +concept same_as = is_same<_Tp, _Up>::value && is_same<_Up, _Tp>::value; + +template +concept convertible_to = + is_convertible_v<_From, _To> && + requires { static_cast<_To>(std::declval<_From>()); }; + +template +concept derived_from = + is_base_of_v<_Bp, _Dp> && + is_convertible_v; + +template +concept destructible = is_nothrow_destructible_v<_Tp>; + +template +concept constructible_from = + destructible<_Tp> && is_constructible_v<_Tp, _Args...>; + +template +concept integral = is_integral_v<_Tp>; + +template +concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; + +template +concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; + +template +concept floating_point = is_floating_point_v<_Tp>; + +template +concept move_constructible = + constructible_from<_Tp, _Tp> && std::convertible_to<_Tp, _Tp>; + +template +concept copy_constructible = + move_constructible<_Tp> && + constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> && + constructible_from<_Tp, const _Tp&> && convertible_to && + constructible_from<_Tp, const _Tp> && convertible_to; + +} // namespace std + +#endif // _EZCXX_CONCEPTS diff --git a/src/libcxx/include/type_traits b/src/libcxx/include/type_traits index b6e03ff43..fe4981bde 100644 --- a/src/libcxx/include/type_traits +++ b/src/libcxx/include/type_traits @@ -38,10 +38,21 @@ template using void_t = void; template using __require = true_type; +// type relationships: template struct is_same : false_type {}; template struct is_same<_Tp, _Tp> : true_type {}; template inline constexpr bool is_same_v = is_same<_Lp, _Rp>::value; +#if __has_builtin(__is_base_of) +template inline constexpr bool is_base_of_v = __is_base_of(_Lp, _Rp); +template using is_base_of = bool_constant>; +#endif + +#if __has_builtin(__is_convertible) +template inline constexpr bool is_convertible_v = __is_convertible(_Lp, _Rp); +template using is_convertible = bool_constant>; +#endif + // logical operator traits: template struct conjunction : true_type {}; template struct conjunction<_Tp> : _Tp {}; @@ -68,180 +79,186 @@ template using remove_volatile_t = typename remove_volatile<_Tp>::typ template using remove_cv = remove_const>; template using remove_cv_t = typename remove_cv<_Tp>::type; -// classification traits: -template struct is_const : false_type {}; -template struct is_const<_Tp const> : true_type {}; -template inline constexpr bool is_const_v = is_const<_Tp>::value; - -template struct is_volatile : false_type {}; -template struct is_volatile<_Tp volatile> : true_type {}; -template inline constexpr bool is_volatile_v = is_volatile<_Tp>::value; - -template using is_void = is_same, void>; -template inline constexpr bool is_void_v = is_void<_Tp>::value; +// primary type categories: +#if __has_builtin(__is_void) +template inline constexpr bool is_void_v = __is_void(_Tp); +template using is_void = bool_constant>; +#endif template using is_null_pointer = is_same, nullptr_t>; template inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value; -template struct __integral : false_type {}; -template<> struct __integral< bool> : true_type {}; -template<> struct __integral< char> : true_type {}; -template<> struct __integral< signed char> : true_type {}; -template<> struct __integral : true_type {}; -template<> struct __integral< wchar_t> : true_type {}; -#if __cplusplus >= 202002L -template<> struct __integral< char8_t> : true_type {}; -#endif -template<> struct __integral< char16_t> : true_type {}; -template<> struct __integral< char32_t> : true_type {}; -template<> struct __integral< signed short> : true_type {}; -template<> struct __integral : true_type {}; -template<> struct __integral< signed int> : true_type {}; -template<> struct __integral : true_type {}; -template<> struct __integral< signed long> : true_type {}; -template<> struct __integral : true_type {}; -template<> struct __integral< signed __int48> : true_type {}; -template<> struct __integral : true_type {}; -template<> struct __integral< signed long long> : true_type {}; -template<> struct __integral : true_type {}; -template using is_integral = __integral>; -template inline constexpr bool is_integral_v = is_integral<_Tp>::value; - -template struct __floating_point : false_type {}; -template<> struct __floating_point< float> : true_type {}; -template<> struct __floating_point< double> : true_type {}; -template<> struct __floating_point : true_type {}; -template using is_floating_point = __floating_point>; -template inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value; - -template using is_arithmetic = disjunction, is_floating_point<_Tp>>; -template inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value; - -template using is_fundamental = disjunction, is_null_pointer<_Tp>, is_arithmetic<_Tp>>; -template inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value; - -template struct is_compound : std::integral_constant::value> {}; -template inline constexpr bool is_compound_v = is_compound<_Tp>::value; - -template::value> struct __is_signed : integral_constant {}; -template struct __is_signed<_Tp, false> : false_type {}; -template struct is_signed : __is_signed<_Tp>::type {}; -template constexpr bool is_signed_v = is_signed<_Tp>::value; - -template::value> struct __is_unsigned : integral_constant {}; -template struct __is_unsigned<_Tp, false> : false_type {}; -template struct is_unsigned : __is_unsigned<_Tp>::type {}; -template constexpr bool is_unsigned_v = is_unsigned<_Tp>::value; - -template struct is_array : false_type {}; -template struct is_array<_Tp[]> : true_type {}; -template struct is_array<_Tp[_Np]> : true_type {}; -template inline constexpr bool is_array_v = is_array<_Tp>::value; - -#if __has_feature(is_enum) +#if __has_builtin(__is_integral) +template inline constexpr bool is_integral_v = __is_integral(_Tp); +template using is_integral = bool_constant>; +#endif + +#if __has_builtin(__is_floating_point) +template inline constexpr bool is_floating_point_v = __is_floating_point(_Tp); +template using is_floating_point = bool_constant>; +#endif + +#if __has_builtin(__is_array) +template inline constexpr bool is_array_v = __is_array(_Tp); +template using is_array = bool_constant>; +#endif + +#if __has_builtin(__is_enum) template inline constexpr bool is_enum_v = __is_enum(_Tp); template using is_enum = bool_constant>; #endif -#if __has_feature(is_union) +#if __has_builtin(__is_union) template inline constexpr bool is_union_v = __is_union(_Tp); template using is_union = bool_constant>; #endif -#if __has_feature(is_class) +#if __has_builtin(__is_class) template inline constexpr bool is_class_v = __is_class(_Tp); template using is_class = bool_constant>; #endif -#if __has_feature(is_trivial) +#if __has_builtin(__is_function) +template inline constexpr bool is_function_v = __is_function(_Tp); +template using is_function = bool_constant>; +#endif + +#if __has_builtin(__is_pointer) +template inline constexpr bool is_pointer_v = __is_pointer(_Tp); +template using is_pointer = bool_constant>; +#endif + +#if __has_builtin(__is_lvalue_reference) +template inline constexpr bool is_lvalue_reference_v = __is_lvalue_reference(_Tp); +template using is_lvalue_reference = bool_constant>; +#endif + +#if __has_builtin(__is_rvalue_reference) +template inline constexpr bool is_rvalue_reference_v = __is_rvalue_reference(_Tp); +template using is_rvalue_reference = bool_constant>; +#endif + +#if __has_builtin(__is_member_object_pointer) +template inline constexpr bool is_member_object_pointer_v = __is_member_object_pointer(_Tp); +template using is_member_object_pointer = bool_constant>; +#endif + +#if __has_builtin(__is_member_function_pointer) +template inline constexpr bool is_member_function_pointer_v = __is_member_function_pointer(_Tp); +template using is_member_function_pointer = bool_constant>; +#endif + +// composite type categories: +#if __has_builtin(__is_fundamental) +template inline constexpr bool is_fundamental_v = __is_fundamental(_Tp); +template using is_fundamental = bool_constant>; +#endif + +#if __has_builtin(__is_arithmetic) +template inline constexpr bool is_arithmetic_v = __is_arithmetic(_Tp); +template using is_arithmetic = bool_constant>; +#endif + +#if __has_builtin(__is_scalar) +template inline constexpr bool is_scalar_v = __is_scalar(_Tp); +template using is_scalar = bool_constant>; +#endif + +#if __has_builtin(__is_object) +template inline constexpr bool is_object_v = __is_object(_Tp); +template using is_object = bool_constant>; +#endif + +#if __has_builtin(__is_compound) +template inline constexpr bool is_compound_v = __is_compound(_Tp); +template using is_compound = bool_constant>; +#endif + +#if __has_builtin(__is_reference) +template inline constexpr bool is_reference_v = __is_reference(_Tp); +template using is_reference = bool_constant>; +#endif + +#if __has_builtin(__is_member_pointer) +template inline constexpr bool is_member_pointer_v = __is_member_pointer(_Tp); +template using is_member_pointer = bool_constant>; +#endif + +// type properties: +#if __has_builtin(__is_const) +template inline constexpr bool is_const_v = __is_const(_Tp); +template using is_const = bool_constant>; +#endif + +#if __has_builtin(__is_volatile) +template inline constexpr bool is_volatile_v = __is_volatile(_Tp); +template using is_volatile = bool_constant>; +#endif + +#if __has_builtin(__is_trivial) template inline constexpr bool is_trivial_v = __is_trivial(_Tp); template using is_trivial = bool_constant>; #endif -#if __has_feature(is_trivially_copyable) +#if __has_builtin(__is_trivially_copyable) template inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(_Tp); template using is_trivially_copyable = bool_constant>; #endif -#if __has_feature(is_standard_layout) +#if __has_builtin(__is_standard_layout) template inline constexpr bool is_standard_layout_v = __is_standard_layout(_Tp); template using is_standard_layout = bool_constant>; #endif -#if __has_feature(is_pod) +#if __has_builtin(__is_pod) template inline constexpr bool is_pod_v = __is_pod(_Tp); template using is_pod = bool_constant>; #endif -#if __has_feature(is_empty) +#if __has_builtin(__is_literal_type) +template inline constexpr bool is_literal_type_v = __is_literal_type(_Tp); +template using is_literal_type = bool_constant>; +#endif + +#if __has_builtin(__has_unique_object_representations) +template inline constexpr bool has_unique_object_representations_v = __has_unique_object_representations(_Tp); +template using has_unique_object_representations = bool_constant>; +#endif + +#if __has_builtin(__is_empty) template inline constexpr bool is_empty_v = __is_empty(_Tp); template using is_empty = bool_constant>; #endif -#if __has_feature(is_polymorphic) +#if __has_builtin(__is_polymorphic) template inline constexpr bool is_polymorphic_v = __is_polymorphic(_Tp); template using is_polymorphic = bool_constant>; #endif -#if __has_feature(is_abstract) +#if __has_builtin(__is_abstract) template inline constexpr bool is_abstract_v = __is_abstract(_Tp); template using is_abstract = bool_constant>; #endif -#if __has_feature(is_final) +#if __has_builtin(__is_final) template inline constexpr bool is_final_v = __is_final(_Tp); template using is_final = bool_constant>; #endif -template struct is_pointer : false_type {}; -template struct is_pointer<_Tp*> : true_type {}; -template inline constexpr bool is_pointer_v = is_pointer<_Tp>::value; - -template struct is_lvalue_reference : false_type {}; -template struct is_lvalue_reference<_Tp&> : true_type {}; -template inline constexpr bool is_lvalue_reference_v = is_lvalue_reference<_Tp>::value; - -template struct is_rvalue_reference : false_type {}; -template struct is_rvalue_reference<_Tp&&> : true_type {}; -template inline constexpr bool is_rvalue_reference_v = is_rvalue_reference<_Tp>::value; - -template using is_reference = disjunction, is_rvalue_reference<_Tp>>; -template inline constexpr bool is_reference_v = is_reference<_Tp>::value; - -template using is_function = negation, is_reference<_Tp>>>; -template inline constexpr bool is_function_v = is_function<_Tp>::value; - -template struct __member_pointer : false_type {}; -template struct __member_pointer<_Tp _Cp::*> : true_type {}; -template using is_member_pointer = __member_pointer>; -template inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value; - -template struct __member_function_pointer : false_type {}; -template struct __member_function_pointer<_Tp _Cp::*> : is_function<_Tp> {}; -template using is_member_function_pointer = __member_function_pointer>; -template inline constexpr bool is_member_function_pointer_v = is_member_function_pointer<_Tp>::value; - -template struct __member_object_pointer : false_type {}; -template struct __member_object_pointer<_Tp _Cp::*> : negation> {}; -template using is_member_object_pointer = __member_object_pointer>; -template inline constexpr bool is_member_object_pointer_v = is_member_object_pointer<_Tp>::value; - -template struct is_scalar : public integral_constant::value || - is_member_pointer<_Tp>::value || - is_pointer<_Tp>::value || - is_null_pointer<_Tp>::value || - is_enum<_Tp>::value -> {}; -template inline constexpr bool is_scalar_v = is_scalar<_Tp>::value; - -template struct is_object : integral_constant::value || - is_array<_Tp>::value || - is_union<_Tp>::value || - is_class<_Tp>::value -> {}; -template inline constexpr bool is_object_v = is_object<_Tp>::value; +#if __has_builtin(__is_aggregate) +template inline constexpr bool is_aggregate_v = __is_aggregate(_Tp); +template using is_aggregate = bool_constant>; +#endif + +#if __has_builtin(__is_signed) +template inline constexpr bool is_signed_v = __is_signed(_Tp); +template using is_signed = bool_constant>; +#endif + +#if __has_builtin(__is_unsigned) +template inline constexpr bool is_unsigned_v = __is_unsigned(_Tp); +template using is_unsigned = bool_constant>; +#endif // const/volatile addition traits: template using add_const = conditional, is_function<_Tp>, is_const<_Tp>>, @@ -268,60 +285,60 @@ template struct remove_reference<_Tp&> : type_identity<_Tp> {}; template struct remove_reference<_Tp&&> : type_identity<_Tp> {}; template using remove_reference_t = typename remove_reference<_Tp>::type; -template using __remove_cvref_t = typename remove_cv::type>::type; -template struct remove_cvref { using type = __remove_cvref_t<_Tp>; }; -template using remove_cvref_t = typename remove_cvref<_Tp>::type; +template using __remove_cvref_t = typename remove_cv::type>::type; +template struct remove_cvref { using type = __remove_cvref_t<_Tp>; }; +template using remove_cvref_t = typename remove_cvref<_Tp>::type; -template auto __add_pointer(int) -> type_identity<_Tp*>; -template auto __add_pointer(...) -> type_identity<_Tp>; -template using add_pointer = decltype(__add_pointer<_Tp>(0)); +template auto __ezcxx_add_pointer(int) -> type_identity<_Tp*>; +template auto __ezcxx_add_pointer(...) -> type_identity<_Tp>; +template using add_pointer = decltype(__ezcxx_add_pointer<_Tp>(0)); template using add_pointer_t = typename add_pointer<_Tp>::type; -template auto __add_lvalue_reference(int) -> type_identity<_Tp&>; -template auto __add_lvalue_reference(...) -> type_identity<_Tp>; -template using add_lvalue_reference = decltype(__add_lvalue_reference<_Tp>(0)); +template auto __ezcxx_add_lvalue_reference(int) -> type_identity<_Tp&>; +template auto __ezcxx_add_lvalue_reference(...) -> type_identity<_Tp>; +template using add_lvalue_reference = decltype(__ezcxx_add_lvalue_reference<_Tp>(0)); template using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type; -template auto __add_rvalue_reference(int) -> type_identity<_Tp&&>; -template auto __add_rvalue_reference(...) -> type_identity<_Tp>; -template using add_rvalue_reference = decltype(__add_rvalue_reference<_Tp>(0)); +template auto __ezcxx_add_rvalue_reference(int) -> type_identity<_Tp&&>; +template auto __ezcxx_add_rvalue_reference(...) -> type_identity<_Tp>; +template using add_rvalue_reference = decltype(__ezcxx_add_rvalue_reference<_Tp>(0)); template using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type; // alignment_of: -template struct alignment_of +template struct alignment_of : public integral_constant {}; -template inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value; +template inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value; // rank/extent: -template struct rank +template struct rank : public integral_constant {}; -template struct rank<_Tp[]> +template struct rank<_Tp[]> : public integral_constant::value + 1> {}; -template struct rank<_Tp[_Np]> +template struct rank<_Tp[_Np]> : public integral_constant::value + 1> {}; -template inline constexpr size_t rank_v = rank<_Tp>::value; +template inline constexpr size_t rank_v = rank<_Tp>::value; -template struct extent +template struct extent : public integral_constant {}; -template struct extent<_Tp[], 0> +template struct extent<_Tp[], 0> : public integral_constant {}; -template struct extent<_Tp[], _Ip> +template struct extent<_Tp[], _Ip> : public integral_constant::value> {}; -template struct extent<_Tp[_Np], 0> +template struct extent<_Tp[_Np], 0> : public integral_constant {}; -template struct extent<_Tp[_Np], _Ip> +template struct extent<_Tp[_Np], _Ip> : public integral_constant::value> {}; -template inline constexpr size_t extent_v = extent<_Tp, _Ip>::value; +template inline constexpr size_t extent_v = extent<_Tp, _Ip>::value; template struct remove_extent { typedef _Tp type; }; template struct remove_extent<_Tp[]> { typedef _Tp type; }; template struct remove_extent<_Tp[_Np]> { typedef _Tp type; }; -template using remove_extent_t = typename remove_extent<_Tp>::type; +template using remove_extent_t = typename remove_extent<_Tp>::type; -template struct remove_all_extents { typedef _Tp type; }; -template struct remove_all_extents<_Tp[]> { typedef typename remove_all_extents<_Tp>::type type; }; -template struct remove_all_extents<_Tp[_Np]> { typedef typename remove_all_extents<_Tp>::type type; }; -template using remove_all_extents_t = typename remove_all_extents<_Tp>::type; +template struct remove_all_extents { typedef _Tp type; }; +template struct remove_all_extents<_Tp[]> { typedef typename remove_all_extents<_Tp>::type type; }; +template struct remove_all_extents<_Tp[_Np]> { typedef typename remove_all_extents<_Tp>::type type; }; +template using remove_all_extents_t = typename remove_all_extents<_Tp>::type; // decay: template @@ -339,7 +356,18 @@ public: >::type >::type type; }; -template using decay_t = typename decay<_Tp>::type; +template using decay_t = typename decay<_Tp>::type; + +// underlying_type: + +#if __has_builtin(__underlying_type) +template::value> struct __underlying_type_impl; +template struct __underlying_type_impl<_Tp, false> {}; +template struct __underlying_type_impl<_Tp, true> { typedef __underlying_type(_Tp) type; }; + +template struct underlying_type : __underlying_type_impl<_Tp, is_enum<_Tp>::value> {}; +template using underlying_type_t = typename underlying_type<_Tp>::type; +#endif // functions: template add_rvalue_reference_t<_Tp> declval() noexcept; @@ -350,7 +378,7 @@ template auto __constructible(...) -> false_type; template using is_constructible = decltype(__constructible<_Tp, _As...>(0)); template inline constexpr bool is_constructible_v = is_constructible<_Tp, _As...>::value; -#if __has_feature(is_trivially_constructible) +#if __has_builtin(__is_trivially_constructible) template inline constexpr bool is_trivially_constructible_v = __is_trivially_constructible(_Tp, _As...); template using is_trivially_constructible = bool_constant>; #endif @@ -392,6 +420,11 @@ template auto __assignable(...) -> false_type; template using is_assignable = decltype(__assignable<_Lp, _Rp>(0)); template inline constexpr bool is_assignable_v = is_assignable<_Lp, _Rp>::value; +#if __has_builtin(__is_trivially_assignable) +template inline constexpr bool is_trivially_assignable_v = __is_trivially_assignable(_Lp, _Rp); +template using is_trivially_assignable = bool_constant>; +#endif + template auto __nt_assignable(int) -> enable_if_t() = declval<_Rp>()), true_type>; template auto __nt_assignable(...) -> false_type; template using is_nothrow_assignable = decltype(__nt_assignable<_Lp, _Rp>(0)); @@ -399,6 +432,7 @@ template inline constexpr bool is_nothrow_assignable_v = i template using is_copy_assignable = is_assignable, add_lvalue_reference_t>>; + template inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value; template using is_nothrow_copy_assignable = is_nothrow_assignable, @@ -413,7 +447,38 @@ template using is_nothrow_move_assignable = is_nothrow_assignable>; template inline constexpr bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<_Tp>::value; -#if __has_feature(has_virtual_destructor) +/* Clang 16.0.0 required */ +#if 0 +#if __has_builtin(__is_destructible) +template inline constexpr bool is_destructible_v = __is_destructible(_Tp); +template using is_destructible = bool_constant>; +#endif +#elif __cplusplus >= 201907L +template struct is_destructible + : std::integral_constant +{}; +template inline constexpr bool is_destructible_v = is_destructible<_Tp>::value; +#endif + +#if __has_builtin(__is_trivially_destructible) +template inline constexpr bool is_trivially_destructible_v = __is_trivially_destructible(_Tp); +template using is_trivially_destructible = bool_constant>; +#endif + +/* Clang 16.0.0 required */ +#if 0 +#if __has_builtin(__is_nothrow_destructible) +template inline constexpr bool is_nothrow_destructible_v = __is_nothrow_destructible(_Tp); +template using is_nothrow_destructible = bool_constant>; +#endif +#elif __cplusplus >= 201907L +template struct is_nothrow_destructible + : std::integral_constant +{}; +template inline constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<_Tp>::value; +#endif + +#if __has_builtin(__has_virtual_destructor) template inline constexpr bool has_virtual_destructor_v = __has_virtual_destructor(_Tp); template using has_virtual_destructor = bool_constant>; #endif diff --git a/src/libcxx/include/utility b/src/libcxx/include/utility index 97d4535ac..73a854e85 100644 --- a/src/libcxx/include/utility +++ b/src/libcxx/include/utility @@ -33,6 +33,8 @@ template _EZCXX_INLINE constexpr std::add_const_t<_Tp>& as_const(_Tp& template _EZCXX_INLINE constexpr auto as_const(_Tp const&& __value) noexcept = delete; #endif // __cplusplus > 201103L +[[noreturn]] inline void unreachable() { __builtin_unreachable(); } + } // namespace std #endif // _EZCXX_UTILITY diff --git a/src/libcxx/include/version b/src/libcxx/include/version index 60a3e56d9..24a66cd33 100644 --- a/src/libcxx/include/version +++ b/src/libcxx/include/version @@ -53,11 +53,11 @@ // # define __cpp_lib_filesystem 201703L // # define __cpp_lib_gcd_lcm 201606L // # define __cpp_lib_hardware_interference_size 201703L -// # define __cpp_lib_has_unique_object_representations 201606L +# define __cpp_lib_has_unique_object_representations 201606L # define __cpp_lib_hypot 201603L // # define __cpp_lib_incomplete_container_elements 201505L // # define __cpp_lib_invoke 201411L -// # define __cpp_lib_is_aggregate 201703L +# define __cpp_lib_is_aggregate 201703L // # define __cpp_lib_is_invocable 201703L // # define __cpp_lib_is_swappable 201603L // # define __cpp_lib_launder 201606L @@ -213,7 +213,7 @@ // # define __cpp_lib_string_resize_and_overwrite 202110L // # define __cpp_lib_to_underlying 202102L // # define __cpp_lib_tuple_like 202207L -// # define __cpp_lib_unreachable 202202L +# define __cpp_lib_unreachable 202202L #endif // __cplusplus >= 202302L #endif // _EZCXX_VERSION diff --git a/src/libcxx/type_traits.cpp b/src/libcxx/type_traits.cpp index 0ba554783..f57e0ea86 100644 --- a/src/libcxx/type_traits.cpp +++ b/src/libcxx/type_traits.cpp @@ -19,6 +19,9 @@ class test_class { test_class(test_class const&) noexcept; test_class(test_class&&) noexcept; }; +struct test_struct { + int test; +}; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunneeded-internal-declaration" const auto test_lambda = [](){}; @@ -28,11 +31,53 @@ const auto test_lambda = [](){}; template void test_type_identity(integral_constant, type_identity_t); C((is_void_v{}, 0))>)); +//------------------------------------------------------------------------------ +// type relationships +//------------------------------------------------------------------------------ + // test is_same C((is_same_v)); C((!is_same::value)); C((!is_same_v)); +// test is_base_of +namespace test_is_base_of { + class A {}; + class B : A {}; + class Z : B {}; + class D {}; + union E {}; + using I = int; + + C(( is_base_of_v)); + C(( is_base_of_v)); + C(( is_base_of_v)); + C((!is_base_of_v)); + C((!is_base_of_v)); + C((!is_base_of_v)); + C((!is_base_of_v)); +} + +// test is_convertible +namespace test_is_convertible { + class E { public: template E(T&&) {} }; + static constexpr void __attribute__((unused)) test(void) { + class A {}; + class B : public A {}; + class Z {}; + class D { public: operator Z() { return c; } Z c; }; + C((is_convertible_v)); + C((!is_convertible_v)); + C((is_convertible_v)); + C((!is_convertible_v)); + C((is_convertible_v)); + } +} + +//------------------------------------------------------------------------------ +// logical operator traits +//------------------------------------------------------------------------------ + // test conjunction C((conjunction_v<>)); C((!conjunction::test)); @@ -67,6 +112,10 @@ C((disjunction::test)); C((disjunction::test)); C((disjunction::test)); +//------------------------------------------------------------------------------ +// const/volatile removal traits +//------------------------------------------------------------------------------ + // test negation C((negation_v)); C((!negation::value)); @@ -88,19 +137,9 @@ C((is_same_v>)); C((is_same_v::type>)); C((is_same_v>)); -// test is_const -C((is_const_v)); -C((is_const::value)); -C((!is_const_v)); -C((!is_const::value)); -C((!is_const_v)); - -// test is_volatile -C((is_volatile_v)); -C((is_volatile::value)); -C((!is_volatile_v)); -C((!is_volatile::value)); -C((!is_volatile_v)); +//------------------------------------------------------------------------------ +// primary type categories +//------------------------------------------------------------------------------ // test is_void C((is_void_v)); @@ -142,26 +181,6 @@ C((!is_floating_point_v)); C((!is_floating_point::value)); C((!is_floating_point_v)); -// test is_arithmetic -C((is_arithmetic_v)); -C((is_arithmetic::value)); -C((is_arithmetic_v)); -C((is_arithmetic::value)); -C((!is_arithmetic_v)); -C((!is_arithmetic::value)); -C((!is_arithmetic_v>)); -C((!is_arithmetic::value)); - -// test is_fundamental -C((is_fundamental_v)); -C((is_fundamental::value)); -C((is_fundamental_v)); -C((is_fundamental::value)); -C((is_fundamental_v)); -C((is_fundamental::value)); -C((!is_fundamental_v>)); -C((!is_fundamental::value)); - // test is_enum C((is_enum_v)); C((!is_enum::value)); @@ -189,6 +208,23 @@ C((!is_class_v)); C((!is_class::value)); C((!is_class_v)); +// test is_function +C((is_function_v)); +C((is_function::value)); +C((is_function_v)); +C((is_function::value)); +C((!is_function_v)); +C((!is_function::value)); +C((!is_function_v)); +C((!is_function::value)); +C((!is_function_v)); +C((!is_function::value)); +C((!is_function_v)); +C((!is_function::value)); +C((!is_function_v)); +C((!is_function::value)); +C((!is_function_v)); + // test is_pointer C((is_pointer_v)); C((is_pointer::value)); @@ -251,6 +287,107 @@ C((!is_rvalue_reference_v)); C((!is_rvalue_reference::value)); C((!is_rvalue_reference_v)); +// test is_member_object_pointer +C((is_member_object_pointer_v)); +C((!is_member_object_pointer::value)); +C((!is_member_object_pointer_v)); +C((!is_member_object_pointer::value)); +C((!is_member_object_pointer_v)); +C((!is_member_object_pointer::value)); +C((!is_member_object_pointer_v)); +C((!is_member_object_pointer::value)); + +// test is_member_function_pointer +C((is_member_function_pointer_v)); +C((!is_member_function_pointer::value)); +C((!is_member_function_pointer_v)); +C((!is_member_function_pointer::value)); +C((!is_member_function_pointer_v)); +C((!is_member_function_pointer::value)); +C((!is_member_function_pointer_v)); +C((!is_member_function_pointer::value)); + +//------------------------------------------------------------------------------ +// composite type categories +//------------------------------------------------------------------------------ + +// test is_fundamental +C((is_fundamental_v)); +C((is_fundamental::value)); +C((is_fundamental_v)); +C((is_fundamental::value)); +C((is_fundamental_v)); +C((is_fundamental::value)); +C((!is_fundamental_v>)); +C((!is_fundamental::value)); + +// test is_arithmetic +C((is_arithmetic_v)); +C((is_arithmetic::value)); +C((is_arithmetic_v)); +C((is_arithmetic::value)); +C((!is_arithmetic_v)); +C((!is_arithmetic::value)); +C((!is_arithmetic_v>)); +C((!is_arithmetic::value)); + +// test is_scalar +namespace test_is_scalar { + static __attribute__((unused)) struct S { int m; } s; + static __attribute__((unused)) int S::* mp = &S::m; + enum class E { e }; + C((is_scalar_v)); + C((is_scalar_v)); + C((is_scalar_v)); + C((is_scalar_v)); + C((is_scalar_v)); + C((is_scalar_v)); + C((!is_scalar_v)); +} + +// test is_object +C((!is_object_v)); +C(( is_object_v)); +C((!is_object_v)); +C(( is_object_v)); +C((!is_object_v)); +C(( is_object_v)); +C((!is_object_v)); +C(( is_object_v)); +C((!is_object_v)); +C(( is_object_v)); +C((!is_object_v)); + +// test is_compound +namespace test_is_compound { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunneeded-internal-declaration" + static void f(); + #pragma GCC diagnostic pop + class Z {}; + union U {}; + enum struct E { e }; + struct S { + int i : 8; + int j; + void foo(); + }; + C((!is_compound_v)); + C((is_compound_v)); + C((is_compound_v)); + C((is_compound_v)); + C((is_compound_v)); + C((is_compound_v)); + C((is_compound_v)); + C((is_compound_v)); + C((is_compound_v)); + C((is_compound_v)); + C((!is_compound_v)); + C((!is_compound_v)); + C((is_compound_v)); + C((is_compound_v)); +} + // test is_reference C((is_reference_v)); C((is_reference::value)); @@ -275,23 +412,6 @@ C((!is_reference::value)); C((!is_reference_v)); C((!is_reference::value)); -// test is_function -C((is_function_v)); -C((is_function::value)); -C((is_function_v)); -C((is_function::value)); -C((!is_function_v)); -C((!is_function::value)); -C((!is_function_v)); -C((!is_function::value)); -C((!is_function_v)); -C((!is_function::value)); -C((!is_function_v)); -C((!is_function::value)); -C((!is_function_v)); -C((!is_function::value)); -C((!is_function_v)); - // test is_member_pointer C((is_member_pointer_v)); C((is_member_pointer::value)); @@ -302,25 +422,191 @@ C((!is_member_pointer::value)); C((!is_member_pointer_v)); C((!is_member_pointer::value)); -// test is_member_function_pointer -C((is_member_function_pointer_v)); -C((!is_member_function_pointer::value)); -C((!is_member_function_pointer_v)); -C((!is_member_function_pointer::value)); -C((!is_member_function_pointer_v)); -C((!is_member_function_pointer::value)); -C((!is_member_function_pointer_v)); -C((!is_member_function_pointer::value)); +//------------------------------------------------------------------------------ +// type properties +//------------------------------------------------------------------------------ -// test is_member_object_pointer -C((is_member_object_pointer_v)); -C((!is_member_object_pointer::value)); -C((!is_member_object_pointer_v)); -C((!is_member_object_pointer::value)); -C((!is_member_object_pointer_v)); -C((!is_member_object_pointer::value)); -C((!is_member_object_pointer_v)); -C((!is_member_object_pointer::value)); +// test is_const +C((is_const_v)); +C((is_const::value)); +C((!is_const_v)); +C((!is_const::value)); +C((!is_const_v)); + +// test is_volatile +C((is_volatile_v)); +C((is_volatile::value)); +C((!is_volatile_v)); +C((!is_volatile::value)); +C((!is_volatile_v)); + +// test is_trivial +namespace test_is_trivial { + struct A { int m; }; + struct B { B() {} }; + class Z { + private: + Z() = default; + }; + C((is_trivial_v)); + C((!is_trivial_v)); + C((is_trivial_v)); +} + +// test is_trivially_copyable +namespace is_trivially_copyable { + struct A { int m; }; + struct B { B(B const&) {} }; + struct Z { virtual void foo(); }; + struct D { + int m; + D(D const&) = default; + D(int x) : m(x + 1) {} + }; + C((is_trivially_copyable_v)); + C((!is_trivially_copyable_v)); + C((!is_trivially_copyable_v)); + C((is_trivially_copyable_v)); +} + +// test is_standard_layout +namespace is_standard_layout { + struct A { int m; }; + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-private-field" + class B: public A { int m; }; + #pragma GCC diagnostic pop + struct Z { virtual void foo(); }; + C((!is_standard_layout_v)); + C((is_standard_layout_v)); + C((!is_standard_layout_v)); +} + +// test is_pod +namespace test_is_pod { + struct A { int m; }; + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wunused-private-field" + class B: public A { int m; }; + #pragma GCC diagnostic pop + struct Z { virtual void foo(); }; + C((is_pod_v)); + C((!is_pod_v)); + C((!is_pod_v)); +} + +// test is_literal_type +namespace test_is_literal_type { + struct A { int m; }; + struct B { virtual ~B(); }; + C((is_literal_type_v)); + C((!is_literal_type_v)); +} + +// test has_unique_object_representations +/** @todo */ + +// test is_empty +namespace test_is_empty { + struct A {}; + struct B { int m; }; + struct Z { static __attribute__((unused)) int m; }; + struct D { virtual ~D(); }; + union E {}; + struct F { [[no_unique_address]] E e; }; + struct G { + int : 0; + }; + C((is_empty_v)); + C((!is_empty_v)); + C((is_empty_v)); + C((!is_empty_v)); + C((!is_empty_v)); + C((is_empty_v)); +} + +// test is_polymorphic +namespace test_is_polymorphic { + struct A { int m; }; + struct B { virtual void foo(); }; + struct Z: B {}; + struct D { virtual ~D() = default; }; + struct E : A {}; + struct F : virtual A {}; + struct AX : A {}; + struct AY : A {}; + struct XY : virtual AX, virtual AY {}; + C((!is_polymorphic_v)); + C((is_polymorphic_v)); + C((is_polymorphic_v)); + C((is_polymorphic_v)); + C((!is_polymorphic_v)); + C((!is_polymorphic_v)); + C((!is_polymorphic_v)); +} + +// test is_abstract +namespace test_is_abstract { + struct A { int m; }; + struct B { virtual void foo(); }; + struct Z{ virtual void foo() = 0; }; + struct D : Z{}; + C((!is_abstract_v)); + C((!is_abstract_v)); + C((is_abstract_v)); + C((is_abstract_v)); +} + +// test is_final +namespace test_is_final { + class A {}; + class B final {}; + union U final { + int x; + double d; + }; + C((!is_final_v)); + C((is_final_v)); + C((is_final_v)); +} + +// test is_aggregate +/** @todo get more complicated tests */ +namespace test_is_aggregate { + struct A { int x, y; }; + C((!is_aggregate_v)); + C((is_aggregate_v)); +} + +// test is_signed +C((!is_signed_v)); +C((!is_signed_v)); +C(( is_signed_v)); +C((!is_signed_v)); +C((!is_signed_v)); +C((!is_signed_v)); +C(( is_signed_v)); +C(( is_signed_v)); +C(( is_signed_v< signed __int48>)); +C((!is_signed_v)); +C((!is_signed_v)); + +// test is_unsigned +C((!is_unsigned_v)); +C((!is_unsigned_v)); +C((!is_unsigned_v)); +C((!is_unsigned_v)); +C(( is_unsigned_v)); +C((!is_unsigned_v)); +C((!is_unsigned_v)); +C((!is_unsigned_v)); +C((!is_unsigned_v< signed __int48>)); +C(( is_unsigned_v)); +C(( is_unsigned_v)); + +//------------------------------------------------------------------------------ +// const/volatile addition traits +//------------------------------------------------------------------------------ // test add_const C((is_same_v>)); @@ -339,6 +625,10 @@ C((is_same_v>)); C((is_same_v::type>)); C((is_same_v>)); +//------------------------------------------------------------------------------ +// reference/pointer transformation traits +//------------------------------------------------------------------------------ + // test remove_pointer C((is_same_v>)); C((is_same_v::type>)); @@ -361,6 +651,15 @@ C((is_same_v::type>)); C((is_same_v>)); C((is_same_v::type>)); +// test remove_cvref +C((is_same_v, int>)); +C((is_same_v, int>)); +C((is_same_v, int>)); +C((is_same_v, int>)); +C((is_same_v, int[2]>)); +C((is_same_v, int[2]>)); +C((is_same_v, int(int)>)); + // test add_pointer C((is_same_v>)); C((is_same_v::type>)); @@ -395,6 +694,73 @@ C((is_same_v::type>)); C((is_same_v>)); C((is_same_v::type>)); +//------------------------------------------------------------------------------ +// alignment_of +//------------------------------------------------------------------------------ + +// test alignment_of +/** @todo */ + +//------------------------------------------------------------------------------ +// rank/extent +//------------------------------------------------------------------------------ + +// test rank +C((rank{} == 0)); +C((rank{} == 1)); +C((rank{} == 2)); +C((rank{} == 3)); + +// test extent +C((extent_v == 3)); +C((extent_v == 3)); +C((extent_v == 3)); +C((extent_v == 4)); +C((extent_v == 0)); +C((extent_v == 0)); + +// test remove_extent +/** @todo */ + +// test remove_all_extents +/** @todo */ + +//------------------------------------------------------------------------------ +// decay +//------------------------------------------------------------------------------ + +// test decay +C(( is_same_v, int >)); +C((!is_same_v, float >)); +C(( is_same_v, int >)); +C(( is_same_v, int >)); +C(( is_same_v, int >)); +C(( is_same_v, int* >)); +C((!is_same_v, int* >)); +C((!is_same_v, int** >)); +C(( is_same_v, int(*)[2] >)); +C(( is_same_v, int(*)(int)>)); + +//------------------------------------------------------------------------------ +// underlying_type +//------------------------------------------------------------------------------ + +// test underlying_type +namespace test_underlying_type { + enum e1 {}; + enum class e2 {}; + enum class e3 : unsigned {}; + enum class e4 : int {}; + C((!is_same_v, int>)); + C((is_same_v, int>)); + C((!is_same_v, int>)); + C((is_same_v, int>)); +} + +//------------------------------------------------------------------------------ +// member classification traits +//------------------------------------------------------------------------------ + // test is_constructible C((is_constructible_v)); C((is_constructible::value)); @@ -481,66 +847,95 @@ C((is_nothrow_move_constructible::value)); C((is_nothrow_move_constructible_v)); C((!is_nothrow_move_constructible::value)); -// test is_signed -C((std::is_signed_v == false)); -C((std::is_signed_v == false)); -C((std::is_signed_v == true)); -C((std::is_signed_v == false)); -C((std::is_signed_v == false)); -C((std::is_signed_v == false)); -C((std::is_signed_v == true)); -C((std::is_signed_v == true)); -C((std::is_signed_v< signed __int48> == true)); -C((std::is_signed_v == false)); -C((std::is_signed_v == false)); - -// test is_unsigned -C((std::is_unsigned_v == false)); -C((std::is_unsigned_v == false)); -C((std::is_unsigned_v == false)); -C((std::is_unsigned_v == false)); -C((std::is_unsigned_v == true)); -C((std::is_unsigned_v == false)); -C((std::is_unsigned_v == false)); -C((std::is_unsigned_v == false)); -C((std::is_unsigned_v< signed __int48> == false)); -C((std::is_unsigned_v == true)); -C((std::is_unsigned_v == true)); - -// test rank -C((std::rank{} == 0)); -C((std::rank{} == 1)); -C((std::rank{} == 2)); -C((std::rank{} == 3)); - -// test extent -C((std::extent_v == 3)); -C((std::extent_v == 3)); -C((std::extent_v == 3)); -C((std::extent_v == 4)); -C((std::extent_v == 0)); -C((std::extent_v == 0)); - -// test remove_cvref -C((std::is_same_v, int>)); -C((std::is_same_v, int>)); -C((std::is_same_v, int>)); -C((std::is_same_v, int>)); -C((std::is_same_v, int[2]>)); -C((std::is_same_v, int[2]>)); -C((std::is_same_v, int(int)>)); - -// test decay -C(( std::is_same_v, int >)); -C((!std::is_same_v, float >)); -C(( std::is_same_v, int >)); -C(( std::is_same_v, int >)); -C(( std::is_same_v, int >)); -C(( std::is_same_v, int* >)); -C((!std::is_same_v, int* >)); -C((!std::is_same_v, int** >)); -C(( std::is_same_v, int(*)[2] >)); -C(( std::is_same_v, int(*)(int)>)); +// test is_assignable +/** @todo get more complicated tests */ +C((!is_assignable_v)); +C((is_assignable_v)); +C((!is_assignable_v)); + +// test is_trivially_assignable +/** @todo get more complicated tests */ +C((is_trivially_assignable_v)); + +// test is_nothrow_assignable +/** @todo get more complicated tests */ +C((is_nothrow_assignable_v)); + +// test is_copy_assignable +/** @todo get more complicated tests */ +C((is_copy_assignable_v)); +C((!is_copy_assignable_v)); + +// test is_nothrow_copy_assignable +/** @todo get more complicated tests */ +C((is_nothrow_copy_assignable_v)); + +// test is_move_assignable +/** @todo get more complicated tests */ +namespace test_is_move_assignable { + struct NoMove { + NoMove& operator=(const NoMove&) { return *this; } + }; + C((is_move_assignable_v)); + C((!is_move_assignable_v)); + C((is_move_assignable_v)); +} + +// test is_nothrow_move_assignable +/** @todo get more complicated tests */ +namespace test_is_nothrow_move_assignable { + struct NoMove { + NoMove& operator=(const NoMove&) { return *this; } + }; + C((!is_nothrow_move_assignable_v)); +} + +/* Clang 16.0.0 required */ +#if 0 +// test is_destructible +/** @todo */ +#endif + +// test is_trivially_destructible +/** @todo get more complicated tests */ +namespace test_is_trivially_destructible { + struct Bar { + ~Bar() = default; + }; + C((is_trivially_destructible{} == true)); +} + +/* Clang 16.0.0 required */ +#if 0 +// test is_nothrow_destructible +/** @todo */ +#endif + +// test has_virtual_destructor +namespace test_has_virtual_destructor { + struct S {}; + struct B { virtual ~B() {} }; + struct D : B { ~D() {} }; + C((!has_virtual_destructor_v)); + C((has_virtual_destructor_v)); + C((has_virtual_destructor_v)); +} + +//------------------------------------------------------------------------------ +// swappable classification traits +//------------------------------------------------------------------------------ + +// test is_swappable_with +/** @todo */ + +// test is_swappable +/** @todo */ + +// test is_nothrow_swappable_with +/** @todo */ + +// test is_nothrow_swappable +/** @todo */ #undef C diff --git a/test/standalone/concepts/autotest.json b/test/standalone/concepts/autotest.json new file mode 100644 index 000000000..7e2ca87a9 --- /dev/null +++ b/test/standalone/concepts/autotest.json @@ -0,0 +1,40 @@ +{ + "transfer_files": [ + "bin/DEMO.8xp" + ], + "target": { + "name": "DEMO", + "isASM": true + }, + "sequence": [ + "action|launch", + "delay|200", + "hashWait|1", + "key|enter", + "delay|300", + "hashWait|2" + ], + "hashes": { + "1": { + "description": "All tests passed", + "timeout": 5000, + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "38E2AD5A" + ] + }, + "2": { + "description": "Exit", + "start": "vram_start", + "size": "vram_16_size", + "expected_CRCs": [ + "FFAF89BA", + "101734A5", + "9DA19F44", + "A32840C8", + "349F4775" + ] + } + } +} diff --git a/test/standalone/concepts/makefile b/test/standalone/concepts/makefile new file mode 100644 index 000000000..99a76d357 --- /dev/null +++ b/test/standalone/concepts/makefile @@ -0,0 +1,18 @@ +# ---------------------------- +# Makefile Options +# ---------------------------- + +NAME = DEMO +ICON = icon.png +DESCRIPTION = "CE C Toolchain Demo" +COMPRESSED = NO +ARCHIVED = NO + +CFLAGS = -Wall -Wextra -Wconversion -Wformat=2 -std=c17 -Oz +CXXFLAGS = -Wall -Wextra -Wconversion -Wformat=2 -std=c++20 -Oz + +PREFER_OS_LIBC = NO + +# ---------------------------- + +include $(shell cedev-config --makefile) diff --git a/test/standalone/concepts/src/main.cpp b/test/standalone/concepts/src/main.cpp new file mode 100644 index 000000000..93097566b --- /dev/null +++ b/test/standalone/concepts/src/main.cpp @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +#include + +// test derived_from +namespace test_derived_from { + class A {}; + class B : public A {}; + class C : private A {}; + + static_assert(std::derived_from == true); + static_assert(std::derived_from == false); + static_assert(std::derived_from == true); + static_assert(std::derived_from == false); + + static_assert(std::is_base_of_v == true); + static_assert(std::is_base_of_v == false); + static_assert(std::is_base_of_v == true); + static_assert(std::is_base_of_v == true); +} + +// test integral +static_assert(std::integral); +static_assert(std::integral); +static_assert(std::integral); +static_assert( ! std::integral ); +static_assert( ! std::integral ); + +// test floating_point +namespace test_floating_point { + constexpr std::floating_point auto x2(std::floating_point auto x) { + return x + x; + } + constexpr std::integral auto x2(std::integral auto x) { + return x << 1; + } + + constexpr auto d = x2(1.1); + constexpr auto f = x2(2.2f); + constexpr auto i = x2(444); + + static_assert(std::is_same_v); + static_assert(std::is_same_v); + static_assert(std::is_same_v); +} + +int run_tests(void) { + return 0; +} + +int main(void) { + os_ClrHome(); + int failed_test = run_tests(); + if (failed_test != 0) { + printf("Failed test L%d\n", failed_test); + } else { + printf("All tests passed"); + } + + while (!os_GetCSC()); + + return 0; +}