diff options
Diffstat (limited to 'boost/endian')
-rw-r--r-- | boost/endian/arithmetic.hpp | 18 | ||||
-rw-r--r-- | boost/endian/buffers.hpp | 58 | ||||
-rw-r--r-- | boost/endian/conversion.hpp | 37 | ||||
-rw-r--r-- | boost/endian/detail/config.hpp | 6 | ||||
-rw-r--r-- | boost/endian/detail/cover_operators.hpp | 24 | ||||
-rw-r--r-- | boost/endian/detail/intrinsic.hpp | 2 | ||||
-rw-r--r-- | boost/endian/detail/lightweight_test.hpp | 2 |
7 files changed, 85 insertions, 62 deletions
diff --git a/boost/endian/arithmetic.hpp b/boost/endian/arithmetic.hpp index d8bcbe62b4..e20d25b3b4 100644 --- a/boost/endian/arithmetic.hpp +++ b/boost/endian/arithmetic.hpp @@ -21,8 +21,8 @@ #ifndef BOOST_ENDIAN_ARITHMETIC_HPP #define BOOST_ENDIAN_ARITHMETIC_HPP -#if defined(_MSC_VER) -# pragma warning(push) +#if defined(_MSC_VER) +# pragma warning(push) # pragma warning(disable:4365) // conversion ... signed/unsigned mismatch #endif @@ -300,7 +300,7 @@ namespace endian # ifndef BOOST_ENDIAN_NO_CTORS endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT - { + { # ifdef BOOST_ENDIAN_LOG if ( endian_log ) std::cout << "big, unaligned, " << n_bits << "-bits, construct(" << val << ")\n"; @@ -325,7 +325,7 @@ namespace endian # ifndef BOOST_ENDIAN_NO_CTORS endian_arithmetic() BOOST_ENDIAN_DEFAULT_CONSTRUCT BOOST_ENDIAN_EXPLICIT_OPT endian_arithmetic(T val) BOOST_NOEXCEPT - { + { # ifdef BOOST_ENDIAN_LOG if ( endian_log ) std::cout << "little, unaligned, " << n_bits << "-bits, construct(" << val << ")\n"; @@ -361,7 +361,7 @@ namespace endian this->m_value = ::boost::endian::native_to_big(val); } -# endif +# endif endian_arithmetic& operator=(T val) BOOST_NOEXCEPT { this->m_value = ::boost::endian::native_to_big(val); @@ -390,7 +390,7 @@ namespace endian # endif this->m_value = ::boost::endian::native_to_little(val); } -# endif +# endif endian_arithmetic& operator=(T val) BOOST_NOEXCEPT { this->m_value = ::boost::endian::native_to_little(val); @@ -406,8 +406,8 @@ namespace endian # pragma pack(pop) #endif -#if defined(_MSC_VER) -# pragma warning(pop) -#endif +#if defined(_MSC_VER) +# pragma warning(pop) +#endif #endif // BOOST_ENDIAN_ARITHMETIC_HPP diff --git a/boost/endian/buffers.hpp b/boost/endian/buffers.hpp index b48b8de7d4..258bbecb54 100644 --- a/boost/endian/buffers.hpp +++ b/boost/endian/buffers.hpp @@ -21,8 +21,8 @@ #ifndef BOOST_ENDIAN_BUFFERS_HPP #define BOOST_ENDIAN_BUFFERS_HPP -#if defined(_MSC_VER) -# pragma warning(push) +#if defined(_MSC_VER) +# pragma warning(push) # pragma warning(disable:4365) // conversion ... signed/unsigned mismatch #endif @@ -38,11 +38,16 @@ #include <boost/predef/detail/endian_compat.h> #include <boost/endian/conversion.hpp> #include <boost/type_traits/is_signed.hpp> +#include <boost/type_traits/make_unsigned.hpp> +#include <boost/type_traits/conditional.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/type_traits/type_identity.hpp> #include <boost/cstdint.hpp> #include <boost/static_assert.hpp> #include <boost/core/scoped_enum.hpp> #include <iosfwd> #include <climits> +#include <cstring> # if CHAR_BIT != 8 # error Platforms with CHAR_BIT != 8 are not supported @@ -195,7 +200,7 @@ namespace endian return os << x.value(); } - // Stream extractor + // Stream extractor template <class charT, class traits, BOOST_SCOPED_ENUM(order) Order, class T, std::size_t n_bits, BOOST_SCOPED_ENUM(align) A> std::basic_istream<charT, traits>& @@ -221,20 +226,27 @@ namespace endian { typedef unrolled_byte_loops<T, n_bytes - 1, sign> next; + // shifting a negative number is flagged by -fsanitize=undefined + // so use the corresponding unsigned type for the shifts + + typedef typename boost::conditional< + boost::is_integral<T>::value, + boost::make_unsigned<T>, boost::type_identity<T> >::type::type U; + static T load_big(const unsigned char* bytes) BOOST_NOEXCEPT - { return static_cast<T>(*(bytes - 1) | (next::load_big(bytes - 1) << 8)); } + { return static_cast<T>(*(bytes - 1) | (static_cast<U>(next::load_big(bytes - 1)) << 8)); } static T load_little(const unsigned char* bytes) BOOST_NOEXCEPT - { return static_cast<T>(*bytes | (next::load_little(bytes + 1) << 8)); } + { return static_cast<T>(*bytes | (static_cast<U>(next::load_little(bytes + 1)) << 8)); } static void store_big(char* bytes, T value) BOOST_NOEXCEPT { *(bytes - 1) = static_cast<char>(value); - next::store_big(bytes - 1, static_cast<T>(value >> 8)); + next::store_big(bytes - 1, static_cast<T>(static_cast<U>(value) >> 8)); } static void store_little(char* bytes, T value) BOOST_NOEXCEPT { *bytes = static_cast<char>(value); - next::store_little(bytes + 1, static_cast<T>(value >> 8)); + next::store_little(bytes + 1, static_cast<T>(static_cast<U>(value) >> 8)); } }; @@ -284,7 +296,12 @@ namespace endian // case since sizeof(T) and n_bytes are known at compile // time. { - return *reinterpret_cast<T const *>(bytes); + // Avoids -fsanitize=undefined violations due to unaligned loads + // All major x86 compilers optimize a short-sized memcpy into a single instruction + + T t; + std::memcpy( &t, bytes, sizeof(T) ); + return t; } # endif return unrolled_byte_loops<T, n_bytes>::load_little @@ -310,7 +327,10 @@ namespace endian // case since sizeof(T) and n_bytes are known at compile // time. { - *reinterpret_cast<T *>(bytes) = value; + // Avoids -fsanitize=undefined violations due to unaligned stores + // All major x86 compilers optimize a short-sized memcpy into a single instruction + + std::memcpy( bytes, &value, sizeof(T) ); return; } # endif @@ -346,7 +366,7 @@ namespace endian # ifndef BOOST_ENDIAN_NO_CTORS endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT explicit endian_buffer(T val) BOOST_NOEXCEPT - { + { # ifdef BOOST_ENDIAN_LOG if ( endian_log ) std::cout << "big, unaligned, " @@ -365,7 +385,7 @@ namespace endian return *this; } value_type value() const BOOST_NOEXCEPT - { + { # ifdef BOOST_ENDIAN_LOG if ( endian_log ) std::cout << "big, unaligned, " << n_bits << "-bits, convert(" @@ -388,7 +408,7 @@ namespace endian # ifndef BOOST_ENDIAN_NO_CTORS endian_buffer() BOOST_ENDIAN_DEFAULT_CONSTRUCT explicit endian_buffer(T val) BOOST_NOEXCEPT - { + { # ifdef BOOST_ENDIAN_LOG if ( endian_log ) std::cout << "little, unaligned, " << n_bits << "-bits, construct(" @@ -400,7 +420,7 @@ namespace endian endian_buffer & operator=(T val) BOOST_NOEXCEPT { detail::store_little_endian<T, n_bits/8>(m_value, val); return *this; } value_type value() const BOOST_NOEXCEPT - { + { # ifdef BOOST_ENDIAN_LOG if ( endian_log ) std::cout << "little, unaligned, " << n_bits << "-bits, convert(" @@ -435,14 +455,14 @@ namespace endian m_value = ::boost::endian::native_to_big(val); } -# endif +# endif endian_buffer& operator=(T val) BOOST_NOEXCEPT { m_value = ::boost::endian::native_to_big(val); return *this; } //operator value_type() const BOOST_NOEXCEPT - //{ + //{ // return ::boost::endian::big_to_native(m_value); //} value_type value() const BOOST_NOEXCEPT @@ -480,7 +500,7 @@ namespace endian m_value = ::boost::endian::native_to_little(val); } -# endif +# endif endian_buffer& operator=(T val) BOOST_NOEXCEPT { m_value = ::boost::endian::native_to_little(val); @@ -508,8 +528,8 @@ namespace endian # pragma pack(pop) #endif -#if defined(_MSC_VER) -# pragma warning(pop) -#endif +#if defined(_MSC_VER) +# pragma warning(pop) +#endif #endif // BOOST_ENDIAN_BUFFERS_HPP diff --git a/boost/endian/conversion.hpp b/boost/endian/conversion.hpp index fc0e1a2360..9dc40231d4 100644 --- a/boost/endian/conversion.hpp +++ b/boost/endian/conversion.hpp @@ -48,12 +48,12 @@ namespace endian // by argument dependent lookup (ADL). // // // //--------------------------------------------------------------------------------------// - + // customization for exact-length arithmetic types. See doc/conversion.html/#FAQ. // Note: The omission of a overloads for the arithmetic type (typically long, or // long long) not assigned to one of the exact length typedefs is a deliberate // design decision. Such overloads would be non-portable and thus error prone. - + inline int8_t endian_reverse(int8_t x) BOOST_NOEXCEPT; inline int16_t endian_reverse(int16_t x) BOOST_NOEXCEPT; inline int32_t endian_reverse(int32_t x) BOOST_NOEXCEPT; @@ -112,7 +112,7 @@ namespace endian // // // user-defined types (UDTs) // // // - // All reverse in place function templates are required to be implemented in terms // + // All reverse in place function templates are required to be implemented in terms // // of an unqualified call to "endian_reverse_inplace(x)", a function reversing // // the endianness of x, which is a non-const reference. This provides a // // customization point for any UDT that provides a "reverse_inplace" free-function // @@ -146,7 +146,7 @@ namespace endian // generic conditional reverse in place template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To, class EndianReversibleInplace> - inline void conditional_reverse_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT; + inline void conditional_reverse_inplace(EndianReversibleInplace& x) BOOST_NOEXCEPT; // runtime reverse in place template <class EndianReversibleInplace> @@ -199,33 +199,35 @@ namespace endian { return x; } - + inline int16_t endian_reverse(int16_t x) BOOST_NOEXCEPT { -# ifdef BOOST_ENDIAN_NO_INTRINSICS +# ifdef BOOST_ENDIAN_NO_INTRINSICS return (static_cast<uint16_t>(x) << 8) | (static_cast<uint16_t>(x) >> 8); # else - return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(static_cast<uint16_t>(x)); + return static_cast<int16_t>( + BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_2(static_cast<uint16_t>(x))); # endif } inline int32_t endian_reverse(int32_t x) BOOST_NOEXCEPT { -# ifdef BOOST_ENDIAN_NO_INTRINSICS +# ifdef BOOST_ENDIAN_NO_INTRINSICS uint32_t step16; step16 = static_cast<uint32_t>(x) << 16 | static_cast<uint32_t>(x) >> 16; return ((static_cast<uint32_t>(step16) << 8) & 0xff00ff00) | ((static_cast<uint32_t>(step16) >> 8) & 0x00ff00ff); # else - return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(static_cast<uint32_t>(x)); + return static_cast<int32_t>( + BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(static_cast<uint32_t>(x))); # endif } inline int64_t endian_reverse(int64_t x) BOOST_NOEXCEPT { -# ifdef BOOST_ENDIAN_NO_INTRINSICS +# ifdef BOOST_ENDIAN_NO_INTRINSICS uint64_t step32, step16; step32 = static_cast<uint64_t>(x) << 32 | static_cast<uint64_t>(x) >> 32; step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 @@ -233,10 +235,11 @@ namespace endian return static_cast<int64_t>((step16 & 0x00FF00FF00FF00FFULL) << 8 | (step16 & 0xFF00FF00FF00FF00ULL) >> 8); # else - return BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(static_cast<uint64_t>(x)); + return static_cast<int64_t>( + BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(static_cast<uint64_t>(x))); # endif } - + inline uint8_t endian_reverse(uint8_t x) BOOST_NOEXCEPT { return x; @@ -244,7 +247,7 @@ namespace endian inline uint16_t endian_reverse(uint16_t x) BOOST_NOEXCEPT { -# ifdef BOOST_ENDIAN_NO_INTRINSICS +# ifdef BOOST_ENDIAN_NO_INTRINSICS return (x << 8) | (x >> 8); # else @@ -252,9 +255,9 @@ namespace endian # endif } - inline uint32_t endian_reverse(uint32_t x) BOOST_NOEXCEPT + inline uint32_t endian_reverse(uint32_t x) BOOST_NOEXCEPT { -# ifdef BOOST_ENDIAN_NO_INTRINSICS +# ifdef BOOST_ENDIAN_NO_INTRINSICS uint32_t step16; step16 = x << 16 | x >> 16; return @@ -267,7 +270,7 @@ namespace endian inline uint64_t endian_reverse(uint64_t x) BOOST_NOEXCEPT { -# ifdef BOOST_ENDIAN_NO_INTRINSICS +# ifdef BOOST_ENDIAN_NO_INTRINSICS uint64_t step32, step16; step32 = x << 32 | x >> 32; step16 = (step32 & 0x0000FFFF0000FFFFULL) << 16 @@ -402,7 +405,7 @@ namespace endian namespace detail { - // Primary template and specializations support generic + // Primary template and specializations support generic // endian_reverse_inplace(). // See rationale in endian_reverse_inplace() below. template <BOOST_SCOPED_ENUM(order) From, BOOST_SCOPED_ENUM(order) To, diff --git a/boost/endian/detail/config.hpp b/boost/endian/detail/config.hpp index 8ece0a1e9f..6d446fa5d5 100644 --- a/boost/endian/detail/config.hpp +++ b/boost/endian/detail/config.hpp @@ -5,7 +5,7 @@ // Distributed under the Boost Software License, Version 1.0. // See http://www.boost.org/LICENSE_1_0.txt -//--------------------------------------------------------------------------------------// +//--------------------------------------------------------------------------------------// #ifndef BOOST_ENDIAN_CONFIG_HPP #define BOOST_ENDIAN_CONFIG_HPP @@ -31,14 +31,14 @@ #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_ENDIAN_DYN_LINK) # if defined(BOOST_ENDIAN_SOURCE) # define BOOST_ENDIAN_DECL BOOST_SYMBOL_EXPORT -# else +# else # define BOOST_ENDIAN_DECL BOOST_SYMBOL_IMPORT # endif #else # define BOOST_ENDIAN_DECL #endif -// enable automatic library variant selection ----------------------------------------// +// enable automatic library variant selection ----------------------------------------// #if !defined(BOOST_ENDIAN_SOURCE) && !defined(BOOST_ALL_NO_LIB) \ && !defined(BOOST_ENDIAN_NO_LIB) diff --git a/boost/endian/detail/cover_operators.hpp b/boost/endian/detail/cover_operators.hpp index f4fd052803..a16545e498 100644 --- a/boost/endian/detail/cover_operators.hpp +++ b/boost/endian/detail/cover_operators.hpp @@ -9,8 +9,8 @@ #ifndef BOOST_ENDIAN_COVER_OPERATORS_HPP #define BOOST_ENDIAN_COVER_OPERATORS_HPP -#if defined(_MSC_VER) -# pragma warning(push) +#if defined(_MSC_VER) +# pragma warning(push) # pragma warning(disable:4365) // conversion ... signed/unsigned mismatch #endif @@ -61,7 +61,7 @@ namespace boost friend bool operator==(const D& x, ArithmeticT y) BOOST_NOEXCEPT { return +x == y; } friend bool operator<(const D& x, ArithmeticT y) BOOST_NOEXCEPT { return +x < y; } # endif - + // The basic arithmetic operations. friend D& operator+=(D& x, ArithmeticT y) BOOST_NOEXCEPT { return x = static_cast<ArithmeticT>(+x + y); } @@ -83,13 +83,13 @@ namespace boost { return x = static_cast<ArithmeticT>(+x << y); } friend D& operator>>=(D& x, ArithmeticT y) BOOST_NOEXCEPT { return x = static_cast<ArithmeticT>(+x >> y); } - + // A few binary arithmetic operations not covered by operators base class. friend ArithmeticT operator<<(const D& x, ArithmeticT y) BOOST_NOEXCEPT { return static_cast<ArithmeticT>(+x << y); } friend ArithmeticT operator>>(const D& x, ArithmeticT y) BOOST_NOEXCEPT { return static_cast<ArithmeticT>(+x >> y); } - + // Auto-increment and auto-decrement can be defined in terms of the // arithmetic operations. friend D& operator++(D& x) BOOST_NOEXCEPT { return x += 1; } @@ -97,13 +97,13 @@ namespace boost # ifdef BOOST_ENDIAN_MINIMAL_COVER_OPERATORS friend D operator++(D& x, int) BOOST_NOEXCEPT - { + { D tmp(x); x += 1; return tmp; } friend D operator--(D& x, int) BOOST_NOEXCEPT - { + { D tmp(x); x -= 1; return tmp; @@ -117,10 +117,10 @@ namespace boost friend std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const D& x) { - return os << +x; + return os << +x; } - // Stream extractor + // Stream extractor template <class charT, class traits> friend std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, D& x) @@ -135,8 +135,8 @@ namespace boost } // namespace endian } // namespace boost -#if defined(_MSC_VER) -# pragma warning(pop) -#endif +#if defined(_MSC_VER) +# pragma warning(pop) +#endif #endif // BOOST_ENDIAN_COVER_OPERATORS_HPP diff --git a/boost/endian/detail/intrinsic.hpp b/boost/endian/detail/intrinsic.hpp index 0abd0ad435..f110276b10 100644 --- a/boost/endian/detail/intrinsic.hpp +++ b/boost/endian/detail/intrinsic.hpp @@ -46,7 +46,7 @@ # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_4(x) __builtin_bswap32(x) # define BOOST_ENDIAN_INTRINSIC_BYTE_SWAP_8(x) __builtin_bswap64(x) -// Linux systems provide the byteswap.h header, with +// Linux systems provide the byteswap.h header, with #elif defined(__linux__) // don't check for obsolete forms defined(linux) and defined(__linux) on the theory that // compilers that predefine only these are so old that byteswap.h probably isn't present. diff --git a/boost/endian/detail/lightweight_test.hpp b/boost/endian/detail/lightweight_test.hpp index eba315c954..ba0eee2f7c 100644 --- a/boost/endian/detail/lightweight_test.hpp +++ b/boost/endian/detail/lightweight_test.hpp @@ -45,7 +45,7 @@ struct report_errors_reminder ~report_errors_reminder() { - BOOST_ASSERT(called_report_errors_function); // verify report_errors() was called + BOOST_ASSERT(called_report_errors_function); // verify report_errors() was called } }; |