Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions libcxx/docs/CodingGuidelines.rst
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,13 @@ headers (which is sometimes required for ``constexpr`` support).

When defining a function at the ABI boundary, it can also be useful to consider which attributes (like ``[[gnu::pure]]``
and ``[[clang::noescape]]``) can be added to the function to improve the compiler's ability to optimize.

Don't use type traits builtins directly
=======================================

Except for ``<__type_traits/*>`` and ``<__concepts/*>``, headers should avoid using the builtins for any type traits
directly, since that makes it a lot harder to work around compiler bugs or add support for new compilers. Since the type
traits and concepts themselves are instantiated a lot it is worth the speedup to use the builtins directly instead of
instantiating additional templates. Note that the builtins cannot be used directly in cases where they may become part
of the mangling of a function, since GCC doesn't mangle them. If you are unsure whether that is the case somewhere, use
the library trait instead of the builtin.
6 changes: 1 addition & 5 deletions libcxx/include/__concepts/class_or_enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
#define _LIBCPP___CONCEPTS_CLASS_OR_ENUM_H

#include <__config>
#include <__type_traits/is_class.h>
#include <__type_traits/is_enum.h>
#include <__type_traits/is_union.h>
#include <__type_traits/remove_cvref.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -26,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// Whether a type is a class type or enumeration type according to the Core wording.

template <class _Tp>
concept __class_or_enum = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>;
concept __class_or_enum = __is_class(_Tp) || __is_union(_Tp) || __is_enum(_Tp);

#endif // _LIBCPP_STD_VER >= 20

Expand Down
3 changes: 1 addition & 2 deletions libcxx/include/__concepts/constructible.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include <__concepts/convertible_to.h>
#include <__concepts/destructible.h>
#include <__config>
#include <__type_traits/is_constructible.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -24,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD

// [concept.constructible]
template <class _Tp, class... _Args>
concept constructible_from = destructible<_Tp> && is_constructible_v<_Tp, _Args...>;
concept constructible_from = destructible<_Tp> && __is_constructible(_Tp, _Args...);

// [concept.default.init]

Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/__concepts/convertible_to.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// [concept.convertible]

template <class _From, class _To>
concept convertible_to = is_convertible_v<_From, _To> && requires { static_cast<_To>(std::declval<_From>()); };
concept convertible_to = __is_convertible(_From, _To) && requires { static_cast<_To>(std::declval<_From>()); };

#endif // _LIBCPP_STD_VER >= 20

Expand Down
4 changes: 1 addition & 3 deletions libcxx/include/__concepts/derived_from.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
#define _LIBCPP___CONCEPTS_DERIVED_FROM_H

#include <__config>
#include <__type_traits/is_base_of.h>
#include <__type_traits/is_convertible.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -24,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// [concept.derived]

template <class _Dp, class _Bp>
concept derived_from = is_base_of_v<_Bp, _Dp> && is_convertible_v<const volatile _Dp*, const volatile _Bp*>;
concept derived_from = __is_base_of(_Bp, _Dp) && __is_convertible(const volatile _Dp*, const volatile _Bp*);

#endif // _LIBCPP_STD_VER >= 20

Expand Down
3 changes: 1 addition & 2 deletions libcxx/include/__concepts/different_from.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

#include <__concepts/same_as.h>
#include <__config>
#include <__type_traits/remove_cvref.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -22,7 +21,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20

template <class _Tp, class _Up>
concept __different_from = !same_as<remove_cvref_t<_Tp>, remove_cvref_t<_Up>>;
concept __different_from = !same_as<__remove_cvref(_Tp), __remove_cvref(_Up)>;

#endif // _LIBCPP_STD_VER >= 20

Expand Down
3 changes: 1 addition & 2 deletions libcxx/include/__concepts/movable.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include <__concepts/constructible.h>
#include <__concepts/swappable.h>
#include <__config>
#include <__type_traits/is_object.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -26,7 +25,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// [concepts.object]

template <class _Tp>
concept movable = is_object_v<_Tp> && move_constructible<_Tp> && assignable_from<_Tp&, _Tp> && swappable<_Tp>;
concept movable = __is_object(_Tp) && move_constructible<_Tp> && assignable_from<_Tp&, _Tp> && swappable<_Tp>;

#endif // _LIBCPP_STD_VER >= 20

Expand Down
3 changes: 1 addition & 2 deletions libcxx/include/__concepts/same_as.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#define _LIBCPP___CONCEPTS_SAME_AS_H

#include <__config>
#include <__type_traits/is_same.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -23,7 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// [concept.same]

template <class _Tp, class _Up>
concept __same_as_impl = _IsSame<_Tp, _Up>::value;
concept __same_as_impl = __is_same(_Tp, _Up);

template <class _Tp, class _Up>
concept same_as = __same_as_impl<_Tp, _Up> && __same_as_impl<_Up, _Tp>;
Expand Down
3 changes: 1 addition & 2 deletions libcxx/include/__concepts/swappable.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include <__type_traits/extent.h>
#include <__type_traits/is_nothrow_assignable.h>
#include <__type_traits/is_nothrow_constructible.h>
#include <__type_traits/remove_cvref.h>
#include <__utility/exchange.h>
#include <__utility/forward.h>
#include <__utility/move.h>
Expand Down Expand Up @@ -46,7 +45,7 @@ void swap(_Tp&, _Tp&) = delete;
// clang-format off
template <class _Tp, class _Up>
concept __unqualified_swappable_with =
(__class_or_enum<remove_cvref_t<_Tp>> || __class_or_enum<remove_cvref_t<_Up>>) &&
(__class_or_enum<__remove_cvref(_Tp)> || __class_or_enum<__remove_cvref(_Up)>) &&
requires(_Tp&& __t, _Up&& __u) {
swap(std::forward<_Tp>(__t), std::forward<_Up>(__u));
};
Expand Down
10 changes: 4 additions & 6 deletions libcxx/include/__type_traits/can_extract_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include <__fwd/pair.h>
#include <__type_traits/conditional.h>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_same.h>
#include <__type_traits/remove_const.h>
#include <__type_traits/remove_const_ref.h>

Expand All @@ -29,19 +28,18 @@ struct __extract_key_self_tag {};
struct __extract_key_first_tag {};

template <class _ValTy, class _Key, class _RawValTy = __remove_const_ref_t<_ValTy> >
struct __can_extract_key
: __conditional_t<_IsSame<_RawValTy, _Key>::value, __extract_key_self_tag, __extract_key_fail_tag> {};
struct __can_extract_key : __conditional_t<__is_same(_RawValTy, _Key), __extract_key_self_tag, __extract_key_fail_tag> {
};

template <class _Pair, class _Key, class _First, class _Second>
struct __can_extract_key<_Pair, _Key, pair<_First, _Second> >
: __conditional_t<_IsSame<__remove_const_t<_First>, _Key>::value, __extract_key_first_tag, __extract_key_fail_tag> {
};
: __conditional_t<__is_same(__remove_const_t<_First>, _Key), __extract_key_first_tag, __extract_key_fail_tag> {};

// __can_extract_map_key uses true_type/false_type instead of the tags.
// It returns true if _Key != _ContainerValueTy (the container is a map not a set)
// and _ValTy == _Key.
template <class _ValTy, class _Key, class _ContainerValueTy, class _RawValTy = __remove_const_ref_t<_ValTy> >
struct __can_extract_map_key : integral_constant<bool, _IsSame<_RawValTy, _Key>::value> {};
struct __can_extract_map_key : integral_constant<bool, __is_same(_RawValTy, _Key)> {};

// This specialization returns __extract_key_fail_tag for non-map containers
// because _Key == _ContainerValueTy
Expand Down
18 changes: 7 additions & 11 deletions libcxx/include/__type_traits/common_reference.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@
#include <__type_traits/common_type.h>
#include <__type_traits/copy_cv.h>
#include <__type_traits/copy_cvref.h>
#include <__type_traits/is_convertible.h>
#include <__type_traits/is_reference.h>
#include <__type_traits/remove_cv.h>
#include <__type_traits/remove_cvref.h>
#include <__type_traits/remove_reference.h>
#include <__utility/declval.h>

Expand Down Expand Up @@ -59,7 +55,7 @@ using __cv_cond_res = __cond_res<__copy_cv_t<_Xp, _Yp>&, __copy_cv_t<_Yp, _Xp>&>
template <class _Ap, class _Bp, class _Xp, class _Yp>
requires
requires { typename __cv_cond_res<_Xp, _Yp>; } &&
is_reference_v<__cv_cond_res<_Xp, _Yp>>
__is_reference(__cv_cond_res<_Xp, _Yp>)
struct __common_ref<_Ap&, _Bp&, _Xp, _Yp> {
using __type = __cv_cond_res<_Xp, _Yp>;
};
Expand All @@ -75,8 +71,8 @@ using __common_ref_C = remove_reference_t<__common_ref_t<_Xp&, _Yp&>>&&;
template <class _Ap, class _Bp, class _Xp, class _Yp>
requires
requires { typename __common_ref_C<_Xp, _Yp>; } &&
is_convertible_v<_Ap&&, __common_ref_C<_Xp, _Yp>> &&
is_convertible_v<_Bp&&, __common_ref_C<_Xp, _Yp>>
__is_convertible(_Ap&&, __common_ref_C<_Xp, _Yp>) &&
__is_convertible(_Bp&&, __common_ref_C<_Xp, _Yp>)
struct __common_ref<_Ap&&, _Bp&&, _Xp, _Yp> {
using __type = __common_ref_C<_Xp, _Yp>;
};
Expand All @@ -92,7 +88,7 @@ using __common_ref_D = __common_ref_t<const _Tp&, _Up&>;
template <class _Ap, class _Bp, class _Xp, class _Yp>
requires
requires { typename __common_ref_D<_Xp, _Yp>; } &&
is_convertible_v<_Ap&&, __common_ref_D<_Xp, _Yp>>
__is_convertible(_Ap&&, __common_ref_D<_Xp, _Yp>)
struct __common_ref<_Ap&&, _Bp&, _Xp, _Yp> {
using __type = __common_ref_D<_Xp, _Yp>;
};
Expand Down Expand Up @@ -139,7 +135,7 @@ template <class _Tp, class _Up>
struct common_reference<_Tp, _Up> : __common_reference_sub_bullet1<_Tp, _Up> {};

template <class _Tp, class _Up>
requires is_reference_v<_Tp> && is_reference_v<_Up> && requires { typename __common_ref_t<_Tp, _Up>; }
requires(__is_reference(_Tp) && __is_reference(_Up) && requires { typename __common_ref_t<_Tp, _Up>; })
struct __common_reference_sub_bullet1<_Tp, _Up> {
using type = __common_ref_t<_Tp, _Up>;
};
Expand All @@ -151,8 +147,8 @@ struct basic_common_reference {};

template <class _Tp, class _Up>
using __basic_common_reference_t =
typename basic_common_reference<remove_cvref_t<_Tp>,
remove_cvref_t<_Up>,
typename basic_common_reference<__remove_cvref(_Tp),
__remove_cvref(_Up),
__xref<_Tp>::template __apply,
__xref<_Up>::template __apply>::type;

Expand Down
6 changes: 2 additions & 4 deletions libcxx/include/__type_traits/common_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
#include <__config>
#include <__type_traits/conditional.h>
#include <__type_traits/decay.h>
#include <__type_traits/is_same.h>
#include <__type_traits/remove_cvref.h>
#include <__type_traits/type_identity.h>
#include <__type_traits/void_t.h>
#include <__utility/declval.h>
Expand Down Expand Up @@ -48,7 +46,7 @@ struct __common_type3 {};
// sub-bullet 4 - "if COND_RES(CREF(D1), CREF(D2)) denotes a type..."
template <class _Tp, class _Up>
struct __common_type3<_Tp, _Up, void_t<__cond_type<const _Tp&, const _Up&>>> {
using type = remove_cvref_t<__cond_type<const _Tp&, const _Up&>>;
using type = __remove_cvref(__cond_type<const _Tp&, const _Up&>);
};

template <class _Tp, class _Up, class = void>
Expand Down Expand Up @@ -96,7 +94,7 @@ struct _LIBCPP_TEMPLATE_VIS common_type<_Tp> : public common_type<_Tp, _Tp> {};
// sub-bullet 1 - "If is_same_v<T1, D1> is false or ..."
template <class _Tp, class _Up>
struct _LIBCPP_TEMPLATE_VIS common_type<_Tp, _Up>
: __conditional_t<_IsSame<_Tp, __decay_t<_Tp> >::value && _IsSame<_Up, __decay_t<_Up> >::value,
: __conditional_t<__is_same(_Tp, __decay_t<_Tp>) && __is_same(_Up, __decay_t<_Up>),
__common_type2_imp<_Tp, _Up>,
common_type<__decay_t<_Tp>, __decay_t<_Up> > > {};

Expand Down
2 changes: 0 additions & 2 deletions libcxx/include/__type_traits/datasizeof.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@

#include <__config>
#include <__cstddef/size_t.h>
#include <__type_traits/is_class.h>
#include <__type_traits/is_final.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand Down
13 changes: 5 additions & 8 deletions libcxx/include/__type_traits/decay.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,8 @@
#include <__config>
#include <__type_traits/add_pointer.h>
#include <__type_traits/conditional.h>
#include <__type_traits/is_array.h>
#include <__type_traits/is_function.h>
#include <__type_traits/is_referenceable.h>
#include <__type_traits/remove_cv.h>
#include <__type_traits/remove_extent.h>
#include <__type_traits/remove_reference.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -35,25 +31,26 @@ struct decay {
};

#else
// This implementation is only used with GCC, so we can use __remove_reference and __is_array directly
template <class _Up, bool>
struct __decay {
typedef _LIBCPP_NODEBUG __remove_cv_t<_Up> type;
typedef _LIBCPP_NODEBUG __remove_cv(_Up) type;
};

template <class _Up>
struct __decay<_Up, true> {
public:
typedef _LIBCPP_NODEBUG
__conditional_t<is_array<_Up>::value,
__conditional_t<__is_array(_Up),
__add_pointer_t<__remove_extent_t<_Up> >,
__conditional_t<is_function<_Up>::value, typename add_pointer<_Up>::type, __remove_cv_t<_Up> > >
__conditional_t<__is_function(_Up), typename add_pointer<_Up>::type, __remove_cv(_Up)> >
type;
};

template <class _Tp>
struct _LIBCPP_TEMPLATE_VIS decay {
private:
typedef _LIBCPP_NODEBUG __libcpp_remove_reference_t<_Tp> _Up;
typedef _LIBCPP_NODEBUG __remove_reference(_Tp) _Up;

public:
typedef _LIBCPP_NODEBUG typename __decay<_Up, __libcpp_is_referenceable<_Up>::value>::type type;
Expand Down
12 changes: 4 additions & 8 deletions libcxx/include/__type_traits/is_always_bitcastable.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
#include <__config>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_integral.h>
#include <__type_traits/is_object.h>
#include <__type_traits/is_same.h>
#include <__type_traits/is_trivially_copyable.h>
#include <__type_traits/remove_cv.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
Expand All @@ -31,13 +27,13 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// considered bit-castable.
template <class _From, class _To>
struct __is_always_bitcastable {
using _UnqualFrom = __remove_cv_t<_From>;
using _UnqualTo = __remove_cv_t<_To>;
using _UnqualFrom = __remove_cv(_From);
using _UnqualTo = __remove_cv(_To);

// clang-format off
static const bool value =
// First, the simple case -- `From` and `To` are the same object type.
(is_same<_UnqualFrom, _UnqualTo>::value && is_trivially_copyable<_UnqualFrom>::value) ||
(__is_same(_UnqualFrom, _UnqualTo) && __is_trivially_copyable(_UnqualFrom)) ||

// Beyond the simple case, we say that one type is "always bit-castable" to another if:
// - (1) `From` and `To` have the same value representation, and in addition every possible value of `From` has
Expand Down Expand Up @@ -75,7 +71,7 @@ struct __is_always_bitcastable {
sizeof(_From) == sizeof(_To) &&
is_integral<_From>::value &&
is_integral<_To>::value &&
!is_same<_UnqualTo, bool>::value
!__is_same(_UnqualTo, bool)
);
// clang-format on
};
Expand Down
6 changes: 2 additions & 4 deletions libcxx/include/__type_traits/is_destructible.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@

#include <__config>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_function.h>
#include <__type_traits/is_reference.h>
#include <__type_traits/remove_all_extents.h>
#include <__utility/declval.h>

Expand Down Expand Up @@ -71,13 +69,13 @@ template <class _Tp, bool>
struct __destructible_false;

template <class _Tp>
struct __destructible_false<_Tp, false> : public __destructible_imp<_Tp, is_reference<_Tp>::value> {};
struct __destructible_false<_Tp, false> : public __destructible_imp<_Tp, __is_reference(_Tp)> {};

template <class _Tp>
struct __destructible_false<_Tp, true> : public false_type {};

template <class _Tp>
struct is_destructible : public __destructible_false<_Tp, is_function<_Tp>::value> {};
struct is_destructible : public __destructible_false<_Tp, __is_function(_Tp)> {};

template <class _Tp>
struct is_destructible<_Tp[]> : public false_type {};
Expand Down
Loading
Loading