LCOV - code coverage report
Current view: top level - v1/__algorithm - copy_move_common.h (source / functions) Coverage Total Hit
Test: vrml_testfiles.info Lines: 45.0 % 20 9
Test Date: 2024-03-08 16:12:17 Functions: 46.2 % 13 6

            Line data    Source code
       1              : //===----------------------------------------------------------------------===//
       2              : //
       3              : // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
       4              : // See https://llvm.org/LICENSE.txt for license information.
       5              : // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
       6              : //
       7              : //===----------------------------------------------------------------------===//
       8              : 
       9              : #ifndef _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H
      10              : #define _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H
      11              : 
      12              : #include <__algorithm/iterator_operations.h>
      13              : #include <__algorithm/unwrap_iter.h>
      14              : #include <__algorithm/unwrap_range.h>
      15              : #include <__config>
      16              : #include <__iterator/iterator_traits.h>
      17              : #include <__memory/pointer_traits.h>
      18              : #include <__type_traits/enable_if.h>
      19              : #include <__type_traits/is_always_bitcastable.h>
      20              : #include <__type_traits/is_constant_evaluated.h>
      21              : #include <__type_traits/is_copy_constructible.h>
      22              : #include <__type_traits/is_trivially_assignable.h>
      23              : #include <__type_traits/is_trivially_copyable.h>
      24              : #include <__type_traits/is_volatile.h>
      25              : #include <__utility/move.h>
      26              : #include <__utility/pair.h>
      27              : #include <cstddef>
      28              : 
      29              : #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
      30              : #  pragma GCC system_header
      31              : #endif
      32              : 
      33              : _LIBCPP_BEGIN_NAMESPACE_STD
      34              : 
      35              : // Type traits.
      36              : 
      37              : template <class _From, class _To>
      38              : struct __can_lower_copy_assignment_to_memmove {
      39              :   static const bool value =
      40              :     // If the types are always bitcastable, it's valid to do a bitwise copy between them.
      41              :     __is_always_bitcastable<_From, _To>::value &&
      42              :     // Reject conversions that wouldn't be performed by the regular built-in assignment (e.g. between arrays).
      43              :     is_trivially_assignable<_To&, const _From&>::value &&
      44              :     // `memmove` doesn't accept `volatile` pointers, make sure the optimization SFINAEs away in that case.
      45              :     !is_volatile<_From>::value &&
      46              :     !is_volatile<_To>::value;
      47              : };
      48              : 
      49              : template <class _From, class _To>
      50              : struct __can_lower_move_assignment_to_memmove {
      51              :   static const bool value =
      52              :     __is_always_bitcastable<_From, _To>::value &&
      53              :     is_trivially_assignable<_To&, _From&&>::value &&
      54              :     !is_volatile<_From>::value &&
      55              :     !is_volatile<_To>::value;
      56              : };
      57              : 
      58              : // `memmove` algorithms implementation.
      59              : 
      60              : template <class _In, class _Out>
      61              : _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
      62            0 : __copy_trivial_impl(_In* __first, _In* __last, _Out* __result) {
      63            0 :   const size_t __n = static_cast<size_t>(__last - __first);
      64            0 :   ::__builtin_memmove(__result, __first, __n * sizeof(_Out));
      65              : 
      66            0 :   return std::make_pair(__last, __result + __n);
      67              : }
      68              : 
      69              : template <class _In, class _Out>
      70              : _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 pair<_In*, _Out*>
      71            0 : __copy_backward_trivial_impl(_In* __first, _In* __last, _Out* __result) {
      72            0 :   const size_t __n = static_cast<size_t>(__last - __first);
      73            0 :   __result -= __n;
      74              : 
      75            0 :   ::__builtin_memmove(__result, __first, __n * sizeof(_Out));
      76              : 
      77            0 :   return std::make_pair(__last, __result);
      78              : }
      79              : 
      80              : // Iterator unwrapping and dispatching to the correct overload.
      81              : 
      82              : template <class _F1, class _F2>
      83              : struct __overload : _F1, _F2 {
      84              :   using _F1::operator();
      85              :   using _F2::operator();
      86              : };
      87              : 
      88              : template <class _InIter, class _Sent, class _OutIter, class = void>
      89              : struct __can_rewrap : false_type {};
      90              : 
      91              : template <class _InIter, class _Sent, class _OutIter>
      92              : struct __can_rewrap<_InIter,
      93              :                     _Sent,
      94              :                     _OutIter,
      95              :                     // Note that sentinels are always copy-constructible.
      96              :                     __enable_if_t< is_copy_constructible<_InIter>::value &&
      97              :                                    is_copy_constructible<_OutIter>::value > > : true_type {};
      98              : 
      99              : template <class _Algorithm,
     100              :           class _InIter,
     101              :           class _Sent,
     102              :           class _OutIter,
     103              :           __enable_if_t<__can_rewrap<_InIter, _Sent, _OutIter>::value, int> = 0>
     104              : _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter>
     105         2462 : __unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) {
     106         2462 :   auto __range  = std::__unwrap_range(__first, std::move(__last));
     107         2462 :   auto __result = _Algorithm()(std::move(__range.first), std::move(__range.second), std::__unwrap_iter(__out_first));
     108         4924 :   return std::make_pair(std::__rewrap_range<_Sent>(std::move(__first), std::move(__result.first)),
     109         2462 :                                  std::__rewrap_iter(std::move(__out_first), std::move(__result.second)));
     110              : }
     111              : 
     112              : template <class _Algorithm,
     113              :           class _InIter,
     114              :           class _Sent,
     115              :           class _OutIter,
     116              :           __enable_if_t<!__can_rewrap<_InIter, _Sent, _OutIter>::value, int> = 0>
     117              : _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter>
     118              : __unwrap_and_dispatch(_InIter __first, _Sent __last, _OutIter __out_first) {
     119              :   return _Algorithm()(std::move(__first), std::move(__last), std::move(__out_first));
     120              : }
     121              : 
     122              : template <class _IterOps, class _InValue, class _OutIter, class = void>
     123              : struct __can_copy_without_conversion : false_type {};
     124              : 
     125              : template <class _IterOps, class _InValue, class _OutIter>
     126              : struct __can_copy_without_conversion<
     127              :     _IterOps,
     128              :     _InValue,
     129              :     _OutIter,
     130              :     __enable_if_t<is_same<_InValue, typename _IterOps::template __value_type<_OutIter> >::value> > : true_type {};
     131              : 
     132              : template <class _AlgPolicy,
     133              :           class _NaiveAlgorithm,
     134              :           class _OptimizedAlgorithm,
     135              :           class _InIter,
     136              :           class _Sent,
     137              :           class _OutIter>
     138              : _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 pair<_InIter, _OutIter>
     139         2462 : __dispatch_copy_or_move(_InIter __first, _Sent __last, _OutIter __out_first) {
     140              : #ifdef _LIBCPP_COMPILER_GCC
     141              :   // GCC doesn't support `__builtin_memmove` during constant evaluation.
     142              :   if (__libcpp_is_constant_evaluated()) {
     143              :     return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first));
     144              :   }
     145              : #else
     146              :   // In Clang, `__builtin_memmove` only supports fully trivially copyable types (just having trivial copy assignment is
     147              :   // insufficient). Also, conversions are not supported.
     148         2462 :   if (__libcpp_is_constant_evaluated()) {
     149              :     using _InValue = typename _IterOps<_AlgPolicy>::template __value_type<_InIter>;
     150              :     if (!is_trivially_copyable<_InValue>::value ||
     151              :         !__can_copy_without_conversion<_IterOps<_AlgPolicy>, _InValue, _OutIter>::value) {
     152            0 :       return std::__unwrap_and_dispatch<_NaiveAlgorithm>(std::move(__first), std::move(__last), std::move(__out_first));
     153              :     }
     154            0 :   }
     155              : #endif // _LIBCPP_COMPILER_GCC
     156              : 
     157              :   using _Algorithm = __overload<_NaiveAlgorithm, _OptimizedAlgorithm>;
     158         2462 :   return std::__unwrap_and_dispatch<_Algorithm>(std::move(__first), std::move(__last), std::move(__out_first));
     159         2435 : }
     160              : 
     161              : _LIBCPP_END_NAMESPACE_STD
     162              : 
     163              : #endif // _LIBCPP___ALGORITHM_COPY_MOVE_COMMON_H
        

Generated by: LCOV version 2.0-1