memcpy.hpp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // Copyright 2023 Matt Borland
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // https://www.boost.org/LICENSE_1_0.txt
  4. #ifndef BOOST_CHARCONV_DETAIL_MEMCPY_HPP
  5. #define BOOST_CHARCONV_DETAIL_MEMCPY_HPP
  6. #include <boost/charconv/detail/config.hpp>
  7. #include <cstring>
  8. #include <cstdint>
  9. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89689
  10. // GCC 10 added checks for length of memcpy which yields the following warning (converted to error with -Werror)
  11. // /usr/include/x86_64-linux-gnu/bits/string_fortified.h:34:33: error:
  12. // ‘void* __builtin___memcpy_chk(void*, const void*, long unsigned int, long unsigned int)’ specified size between
  13. // 18446744071562067968 and 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Werror=stringop-overflow=]
  14. //
  15. // memcpy is defined as taking a size_t for the count and the largest count this will recieve is the number of digits
  16. // in a 128-bit int (39) so we can safely ignore
  17. #if defined(__GNUC__) && __GNUC__ >= 10
  18. # pragma GCC diagnostic push
  19. # pragma GCC diagnostic ignored "-Wstringop-overflow"
  20. # define BOOST_CHARCONV_STRINGOP_OVERFLOW_DISABLED
  21. #endif
  22. namespace boost { namespace charconv { namespace detail {
  23. #if !defined(BOOST_CHARCONV_NO_CONSTEXPR_DETECTION) && defined(BOOST_CXX14_CONSTEXPR)
  24. #define BOOST_CHARCONV_CONSTEXPR constexpr
  25. constexpr char* memcpy(char* dest, const char* src, std::size_t count)
  26. {
  27. if (BOOST_CHARCONV_IS_CONSTANT_EVALUATED(count))
  28. {
  29. for (std::size_t i = 0; i < count; ++i)
  30. {
  31. *(dest + i) = *(src + i);
  32. }
  33. return dest;
  34. }
  35. else
  36. {
  37. // Workaround for GCC-11 because it does not honor GCC diagnostic ignored
  38. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431
  39. // Hopefully the optimizer turns this into memcpy
  40. #if defined(__GNUC__) && __GNUC__ == 11
  41. for (std::size_t i = 0; i < count; ++i)
  42. {
  43. *(dest + i) = *(src + i);
  44. }
  45. return dest;
  46. #else
  47. return static_cast<char*>(std::memcpy(dest, src, count));
  48. #endif
  49. }
  50. }
  51. #else // Either not C++14 or no way of telling if we are in a constexpr context
  52. #define BOOST_CHARCONV_CONSTEXPR inline
  53. inline void* memcpy(void* dest, const void* src, std::size_t count)
  54. {
  55. return std::memcpy(dest, src, count);
  56. }
  57. #endif
  58. }}} // Namespace boost::charconv::detail
  59. #ifdef BOOST_CHARCONV_STRINGOP_OVERFLOW_DISABLED
  60. # pragma GCC diagnostic pop
  61. #endif
  62. #endif // BOOST_CHARCONV_DETAIL_MEMCPY_HPP