From 7b6dcf6ac668e24f11ec5dbc68d1fa0248d964df Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 14 Jan 2018 07:24:00 +0200 Subject: [PATCH 01/11] Make error_code, error_condition literal if C++14 constexpr is available --- include/boost/system/detail/error_code.ipp | 80 +++++----- include/boost/system/error_code.hpp | 166 ++++++++++++++------- test/Jamfile.v2 | 6 + test/constexpr_test.cpp | 40 +++++ 4 files changed, 204 insertions(+), 88 deletions(-) create mode 100644 test/constexpr_test.cpp diff --git a/include/boost/system/detail/error_code.ipp b/include/boost/system/detail/error_code.ipp index f3d67b9..3cbe1eb 100644 --- a/include/boost/system/detail/error_code.ipp +++ b/include/boost/system/detail/error_code.ipp @@ -35,31 +35,13 @@ //--------------------------------------------------------------------------------------// namespace boost { - namespace system - { + +namespace system +{ namespace detail { - // standard error categories -------------------------------------------------------// - - class generic_error_category : public error_category - { - public: - generic_error_category(){} - const char * name() const BOOST_SYSTEM_NOEXCEPT; - std::string message( int ev ) const; - }; - - class system_error_category : public error_category - { - public: - system_error_category(){} - const char * name() const BOOST_SYSTEM_NOEXCEPT; - std::string message( int ev ) const; - error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT; - }; - #ifdef BOOST_ERROR_CODE_HEADER_ONLY # define BOOST_SYSTEM_INLINE inline #else @@ -474,23 +456,47 @@ namespace detail // address for comparison purposes # endif -# ifdef BOOST_ERROR_CODE_HEADER_ONLY -# define BOOST_SYSTEM_LINKAGE inline -# else -# define BOOST_SYSTEM_LINKAGE BOOST_SYSTEM_DECL -# endif +#if defined(BOOST_ERROR_CODE_HEADER_ONLY) - BOOST_SYSTEM_LINKAGE const error_category & system_category() BOOST_SYSTEM_NOEXCEPT - { - static const detail::system_error_category system_category_const; - return system_category_const; - } +// defined in error_code.hpp - BOOST_SYSTEM_LINKAGE const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT - { - static const detail::generic_error_category generic_category_const; - return generic_category_const; - } +#elif defined(BOOST_SYSTEM_HAS_CONSTEXPR) + +#define BOOST_SYSTEM_CONST_INIT + +#if defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::require_constant_initialization) +# undef BOOST_SYSTEM_CONST_INIT +# define BOOST_SYSTEM_CONST_INIT [[clang::require_constant_initialization]] +#endif +#endif + +namespace detail +{ + +BOOST_SYSTEM_CONST_INIT const system_error_category system_category_const; +BOOST_SYSTEM_CONST_INIT const generic_error_category generic_category_const; + +} // namespace detail + +#undef BOOST_SYSTEM_CONST_INIT + +#else + +BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT +{ + static const detail::system_error_category system_category_const; + return system_category_const; +} + +BOOST_SYSTEM_DECL const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT +{ + static const detail::generic_error_category generic_category_const; + return generic_category_const; +} + +#endif + +} // namespace system - } // namespace system } // namespace boost diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index 8041d5d..c349995 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -38,6 +38,16 @@ #define BOOST_SYSTEM_NOEXCEPT BOOST_NOEXCEPT #endif +#if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_ERROR_CODE_HEADER_ONLY) +# define BOOST_SYSTEM_HAS_CONSTEXPR +#endif + +#if defined(BOOST_SYSTEM_HAS_CONSTEXPR) +# define BOOST_SYSTEM_CONSTEXPR constexpr +#else +# define BOOST_SYSTEM_CONSTEXPR +#endif + namespace boost { namespace system @@ -185,31 +195,6 @@ namespace boost // --------------------------------------------------------------------------------// - class error_category; - - // predefined error categories ---------------------------------------------------// - -#ifdef BOOST_ERROR_CODE_HEADER_ONLY - inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT; - inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT; -#else - BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT; - BOOST_SYSTEM_DECL const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT; -#endif - // deprecated synonyms ------------------------------------------------------------// - -#ifdef BOOST_SYSTEM_ENABLE_DEPRECATED - inline const error_category & get_system_category() { return system_category(); } - inline const error_category & get_generic_category() { return generic_category(); } - inline const error_category & get_posix_category() { return generic_category(); } - static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED - = generic_category(); - static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED - = generic_category(); - static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED - = system_category(); -#endif - #ifdef BOOST_MSVC #pragma warning(push) // 'this' : used in base member initializer list @@ -232,7 +217,7 @@ namespace boost public: - explicit std_category( boost::system::error_category const * pc ): pc_( pc ) + BOOST_SYSTEM_CONSTEXPR explicit std_category( boost::system::error_category const * pc ): pc_( pc ) { } @@ -258,7 +243,7 @@ namespace boost public: - error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {} + BOOST_SYSTEM_CONSTEXPR error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {} operator std::error_category const & () const BOOST_SYSTEM_NOEXCEPT { @@ -283,7 +268,7 @@ namespace boost public: - explicit std_category( boost::system::error_category const * pc ): pc_( pc ) + BOOST_SYSTEM_CONSTEXPR explicit std_category( boost::system::error_category const * pc ): pc_( pc ) { } @@ -309,7 +294,7 @@ namespace boost public: - error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {} + BOOST_SYSTEM_CONSTEXPR error_category() BOOST_SYSTEM_NOEXCEPT: std_cat_( this ) {} #endif @@ -326,9 +311,9 @@ namespace boost inline virtual bool equivalent( const error_code & code, int condition ) const BOOST_SYSTEM_NOEXCEPT; - bool operator==(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT + BOOST_SYSTEM_CONSTEXPR bool operator==(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT { return this == &rhs; } - bool operator!=(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT + BOOST_SYSTEM_CONSTEXPR bool operator!=(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT { return this != &rhs; } bool operator<( const error_category & rhs ) const BOOST_SYSTEM_NOEXCEPT { return std::less()( this, &rhs ); } @@ -338,6 +323,85 @@ namespace boost #pragma warning(pop) #endif + // predefined error categories ---------------------------------------------------// + +namespace detail +{ + + class generic_error_category : public error_category + { + public: + BOOST_SYSTEM_CONSTEXPR generic_error_category(){} + const char * name() const BOOST_SYSTEM_NOEXCEPT; + std::string message( int ev ) const; + }; + + class system_error_category : public error_category + { + public: + BOOST_SYSTEM_CONSTEXPR system_error_category(){} + const char * name() const BOOST_SYSTEM_NOEXCEPT; + std::string message( int ev ) const; + error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT; + }; + +} // namespace detail + +#if defined(BOOST_ERROR_CODE_HEADER_ONLY) + +BOOST_SYSTEM_CONSTEXPR inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT +{ + static const detail::system_error_category system_category_const; + return system_category_const; +} + +BOOST_SYSTEM_CONSTEXPR inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT +{ + static const detail::generic_error_category generic_category_const; + return generic_category_const; +} + +#elif defined(BOOST_SYSTEM_HAS_CONSTEXPR) + +namespace detail +{ + +extern const system_error_category system_category_const; +extern const generic_error_category generic_category_const; + +} // namespace detail + +constexpr const error_category & system_category() BOOST_SYSTEM_NOEXCEPT +{ + return detail::system_category_const; +} + +constexpr const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT +{ + return detail::generic_category_const; +} + +#else + + BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT; + BOOST_SYSTEM_DECL const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT; + +#endif + + // deprecated synonyms ------------------------------------------------------------// + +#ifdef BOOST_SYSTEM_ENABLE_DEPRECATED + inline const error_category & get_system_category() { return system_category(); } + inline const error_category & get_generic_category() { return generic_category(); } + inline const error_category & get_posix_category() { return generic_category(); } + static const error_category & posix_category BOOST_ATTRIBUTE_UNUSED + = generic_category(); + static const error_category & errno_ecat BOOST_ATTRIBUTE_UNUSED + = generic_category(); + static const error_category & native_ecat BOOST_ATTRIBUTE_UNUSED + = system_category(); +#endif + // class error_condition ---------------------------------------------------------// // error_conditions are portable, error_codes are system or library specific @@ -347,8 +411,8 @@ namespace boost public: // constructors: - error_condition() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&generic_category()) {} - error_condition( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT + BOOST_SYSTEM_CONSTEXPR error_condition() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&generic_category()) {} + BOOST_SYSTEM_CONSTEXPR error_condition( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT : m_val(val), m_cat(&cat) {} template @@ -361,7 +425,7 @@ namespace boost // modifiers: - void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT + BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT { m_val = val; m_cat = &cat; @@ -376,26 +440,26 @@ namespace boost return *this; } - void clear() BOOST_SYSTEM_NOEXCEPT + BOOST_SYSTEM_CONSTEXPR void clear() BOOST_SYSTEM_NOEXCEPT { m_val = 0; m_cat = &generic_category(); } // observers: - int value() const BOOST_SYSTEM_NOEXCEPT { return m_val; } - const error_category & category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; } + BOOST_SYSTEM_CONSTEXPR int value() const BOOST_SYSTEM_NOEXCEPT { return m_val; } + BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; } std::string message() const { return m_cat->message(value()); } typedef void (*unspecified_bool_type)(); static void unspecified_bool_true() {} - operator unspecified_bool_type() const BOOST_SYSTEM_NOEXCEPT // true if error + BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_SYSTEM_NOEXCEPT // true if error { return m_val == 0 ? 0 : unspecified_bool_true; } - bool operator!() const BOOST_SYSTEM_NOEXCEPT // true if no error + BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_SYSTEM_NOEXCEPT // true if no error { return m_val == 0; } @@ -403,7 +467,7 @@ namespace boost // relationals: // the more symmetrical non-member syntax allows enum // conversions work for both rhs and lhs. - inline friend bool operator==( const error_condition & lhs, + BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_condition & lhs, const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT { return lhs.m_cat == rhs.m_cat && lhs.m_val == rhs.m_val; @@ -446,8 +510,8 @@ namespace boost public: // constructors: - error_code() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&system_category()) {} - error_code( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT + BOOST_SYSTEM_CONSTEXPR error_code() BOOST_SYSTEM_NOEXCEPT : m_val(0), m_cat(&system_category()) {} + BOOST_SYSTEM_CONSTEXPR error_code( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT : m_val(val), m_cat(&cat) {} template @@ -459,7 +523,7 @@ namespace boost } // modifiers: - void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT + BOOST_SYSTEM_CONSTEXPR void assign( int val, const error_category & cat ) BOOST_SYSTEM_NOEXCEPT { m_val = val; m_cat = &cat; @@ -473,15 +537,15 @@ namespace boost return *this; } - void clear() BOOST_SYSTEM_NOEXCEPT + BOOST_SYSTEM_CONSTEXPR void clear() BOOST_SYSTEM_NOEXCEPT { m_val = 0; m_cat = &system_category(); } // observers: - int value() const BOOST_SYSTEM_NOEXCEPT { return m_val; } - const error_category & category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; } + BOOST_SYSTEM_CONSTEXPR int value() const BOOST_SYSTEM_NOEXCEPT { return m_val; } + BOOST_SYSTEM_CONSTEXPR const error_category & category() const BOOST_SYSTEM_NOEXCEPT { return *m_cat; } error_condition default_error_condition() const BOOST_SYSTEM_NOEXCEPT { return m_cat->default_error_condition(value()); } std::string message() const { return m_cat->message(value()); } @@ -489,18 +553,18 @@ namespace boost typedef void (*unspecified_bool_type)(); static void unspecified_bool_true() {} - operator unspecified_bool_type() const BOOST_SYSTEM_NOEXCEPT // true if error + BOOST_SYSTEM_CONSTEXPR operator unspecified_bool_type() const BOOST_SYSTEM_NOEXCEPT // true if error { return m_val == 0 ? 0 : unspecified_bool_true; } - bool operator!() const BOOST_SYSTEM_NOEXCEPT // true if no error + BOOST_SYSTEM_CONSTEXPR bool operator!() const BOOST_SYSTEM_NOEXCEPT // true if no error { return m_val == 0; } // relationals: - inline friend bool operator==( const error_code & lhs, + BOOST_SYSTEM_CONSTEXPR inline friend bool operator==( const error_code & lhs, const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT // the more symmetrical non-member syntax allows enum // conversions work for both rhs and lhs. @@ -569,13 +633,13 @@ namespace boost { // non-member functions ------------------------------------------------// - inline bool operator!=( const error_code & lhs, + BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_code & lhs, const error_code & rhs ) BOOST_SYSTEM_NOEXCEPT { return !(lhs == rhs); } - inline bool operator!=( const error_condition & lhs, + BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_condition & lhs, const error_condition & rhs ) BOOST_SYSTEM_NOEXCEPT { return !(lhs == rhs); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e3ca329..c08546a 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -142,6 +142,12 @@ project [ run before_main_test.cpp : : : -/boost/system//boost_system BOOST_ERROR_CODE_HEADER_ONLY : before_main_test_header ] + [ run constexpr_test.cpp + : : : static : constexpr_test_static + ] + [ run constexpr_test.cpp + : : : shared : constexpr_test_shared + ] ; # Quick (CI) test diff --git a/test/constexpr_test.cpp b/test/constexpr_test.cpp new file mode 100644 index 0000000..2c50aa5 --- /dev/null +++ b/test/constexpr_test.cpp @@ -0,0 +1,40 @@ + +// Copyright 2018 Peter Dimov. +// Distributed under the Boost Software License, Version 1.0. + +#include +#include +#include +#include + +#if !defined(BOOST_SYSTEM_HAS_CONSTEXPR) + +BOOST_PRAGMA_MESSAGE("Skipping constexpr test, BOOST_SYSTEM_HAS_CONSTEXPR isn't defined") +int main() {} + +#else + +using namespace boost::system; + +constexpr error_code e1( 1, system_category() ); + +BOOST_STATIC_ASSERT( e1.value() == 1 ); +BOOST_STATIC_ASSERT( e1.category() == system_category() ); + +constexpr error_code e2( 2, generic_category() ); + +BOOST_STATIC_ASSERT( e2.value() == 2 ); +BOOST_STATIC_ASSERT( e2.category() == generic_category() ); + +int main() +{ + error_code e1_( 1, system_category() ); + BOOST_TEST_EQ( e1, e1_ ); + + error_code e2_( 2, generic_category() ); + BOOST_TEST_EQ( e2, e2_ ); + + return boost::report_errors(); +} + +#endif From de5a0cf3ca1d9ed78764e9c429d8f7fa31a0df2e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 14 Jan 2018 07:56:11 +0200 Subject: [PATCH 02/11] Install libstdc++-4.9 for clang 4.0, 5.0 too --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 408e1ab..7cc2955 100644 --- a/.travis.yml +++ b/.travis.yml @@ -157,6 +157,7 @@ matrix: apt: packages: - clang-4.0 + - libstdc++-4.9-dev sources: - ubuntu-toolchain-r-test - llvm-toolchain-trusty-4.0 @@ -168,6 +169,7 @@ matrix: apt: packages: - clang-5.0 + - libstdc++-4.9-dev sources: - ubuntu-toolchain-r-test - llvm-toolchain-trusty-5.0 From fe55a4a963e757e1dfb0464fbb1a6f4324be46e9 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 14 Jan 2018 08:49:25 +0200 Subject: [PATCH 03/11] Make error_category::op==, !=, < nonmembers (a non-literal class can't have constexpr members acc. to g++) --- include/boost/system/error_code.hpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index c349995..ba0b04a 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -310,15 +310,20 @@ namespace boost BOOST_SYSTEM_NOEXCEPT; inline virtual bool equivalent( const error_code & code, int condition ) const BOOST_SYSTEM_NOEXCEPT; - - BOOST_SYSTEM_CONSTEXPR bool operator==(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT - { return this == &rhs; } - BOOST_SYSTEM_CONSTEXPR bool operator!=(const error_category & rhs) const BOOST_SYSTEM_NOEXCEPT - { return this != &rhs; } - bool operator<( const error_category & rhs ) const BOOST_SYSTEM_NOEXCEPT - { return std::less()( this, &rhs ); } }; + BOOST_SYSTEM_CONSTEXPR inline bool operator==( const error_category & lhs, + const error_category & rhs ) BOOST_SYSTEM_NOEXCEPT + { return &lhs == &rhs; } + + BOOST_SYSTEM_CONSTEXPR inline bool operator!=( const error_category & lhs, + const error_category & rhs ) BOOST_SYSTEM_NOEXCEPT + { return &lhs != &rhs; } + + inline bool operator<( const error_category & lhs, + const error_category & rhs ) BOOST_SYSTEM_NOEXCEPT + { return std::less()( &lhs, &rhs ); } + #ifdef BOOST_MSVC #pragma warning(pop) #endif From 83ddde6b78b92c802abf538e077c36f2913caccd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 14 Jan 2018 15:55:23 +0200 Subject: [PATCH 04/11] Disable constexpr on g++ 7/8 in C++17 mode due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83835 --- include/boost/system/error_code.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index ba0b04a..abef021 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -42,6 +42,11 @@ # define BOOST_SYSTEM_HAS_CONSTEXPR #endif +#if defined(__GNUC__) && (__GNUC__ == 7 || __GNUC__ == 8) && __cplusplus >= 201700L +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83835 +# undef BOOST_SYSTEM_HAS_CONSTEXPR +#endif + #if defined(BOOST_SYSTEM_HAS_CONSTEXPR) # define BOOST_SYSTEM_CONSTEXPR constexpr #else From 61b4d8ef24ce3e1245ba962ad6e83a8049ca6867 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Sun, 21 Jan 2018 21:42:22 +0200 Subject: [PATCH 05/11] Fix variant=release link errors --- include/boost/system/detail/error_code.ipp | 21 ++++++++++++++++++--- include/boost/system/error_code.hpp | 21 ++++++++++++++++++--- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/include/boost/system/detail/error_code.ipp b/include/boost/system/detail/error_code.ipp index 3cbe1eb..6ed777c 100644 --- a/include/boost/system/detail/error_code.ipp +++ b/include/boost/system/detail/error_code.ipp @@ -477,24 +477,39 @@ namespace detail BOOST_SYSTEM_CONST_INIT const system_error_category system_category_const; BOOST_SYSTEM_CONST_INIT const generic_error_category generic_category_const; +BOOST_SYSTEM_DECL const error_category & system_category_ncx() BOOST_SYSTEM_NOEXCEPT +{ + return system_category_const; +} + +BOOST_SYSTEM_DECL const error_category & generic_category_ncx() BOOST_SYSTEM_NOEXCEPT +{ + return generic_category_const; +} + } // namespace detail #undef BOOST_SYSTEM_CONST_INIT #else -BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT +namespace detail { - static const detail::system_error_category system_category_const; + +BOOST_SYSTEM_DECL const error_category & system_category_ncx() BOOST_SYSTEM_NOEXCEPT +{ + static const detail::system_error_category system_category_const; return system_category_const; } -BOOST_SYSTEM_DECL const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT +BOOST_SYSTEM_DECL const error_category & generic_category_ncx() BOOST_SYSTEM_NOEXCEPT { static const detail::generic_error_category generic_category_const; return generic_category_const; } +} // namespace detail + #endif } // namespace system diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index abef021..bb557f3 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -361,7 +361,7 @@ namespace detail BOOST_SYSTEM_CONSTEXPR inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT { - static const detail::system_error_category system_category_const; + static const detail::system_error_category system_category_const; return system_category_const; } @@ -393,8 +393,23 @@ constexpr const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT #else - BOOST_SYSTEM_DECL const error_category & system_category() BOOST_SYSTEM_NOEXCEPT; - BOOST_SYSTEM_DECL const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT; +namespace detail +{ + +BOOST_SYSTEM_DECL const error_category & system_category_ncx() BOOST_SYSTEM_NOEXCEPT; +BOOST_SYSTEM_DECL const error_category & generic_category_ncx() BOOST_SYSTEM_NOEXCEPT; + +} // namespace detail + +inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT +{ + return detail::system_category_ncx(); +} + +inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT +{ + return detail::generic_category_ncx(); +} #endif From 77817d88476f72f5a9857e50e817c04c8bba82db Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 22 Jan 2018 02:20:01 +0200 Subject: [PATCH 06/11] Fix MinGW link errors by properly exporting symbols --- include/boost/system/detail/error_code.ipp | 40 ++++++--------- include/boost/system/error_code.hpp | 60 ++++++++++++++-------- test/std_mismatch_test.cpp | 2 - 3 files changed, 53 insertions(+), 49 deletions(-) diff --git a/include/boost/system/detail/error_code.ipp b/include/boost/system/detail/error_code.ipp index 6ed777c..d93fb1f 100644 --- a/include/boost/system/detail/error_code.ipp +++ b/include/boost/system/detail/error_code.ipp @@ -43,19 +43,14 @@ namespace detail { #ifdef BOOST_ERROR_CODE_HEADER_ONLY -# define BOOST_SYSTEM_INLINE inline +# define BOOST_SYSTEM_DECL_ inline #else -# define BOOST_SYSTEM_INLINE +# define BOOST_SYSTEM_DECL_ BOOST_SYSTEM_DECL #endif // generic_error_category implementation ---------------------------------// - BOOST_SYSTEM_INLINE const char * generic_error_category::name() const BOOST_SYSTEM_NOEXCEPT - { - return "generic"; - } - - BOOST_SYSTEM_INLINE std::string generic_error_category::message( int ev ) const + BOOST_SYSTEM_DECL_ std::string generic_error_category::message( int ev ) const { using namespace boost::system::errc; #if defined(__PGI) @@ -148,12 +143,7 @@ namespace detail } // system_error_category implementation --------------------------------------------// - BOOST_SYSTEM_INLINE const char * system_error_category::name() const BOOST_SYSTEM_NOEXCEPT - { - return "system"; - } - - BOOST_SYSTEM_INLINE error_condition system_error_category::default_error_condition( int ev ) const + BOOST_SYSTEM_DECL_ error_condition system_error_category::default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT { using namespace boost::system::errc; @@ -358,13 +348,13 @@ namespace detail # if !defined( BOOST_WINDOWS_API ) - BOOST_SYSTEM_INLINE std::string system_error_category::message( int ev ) const + BOOST_SYSTEM_DECL_ std::string system_error_category::message( int ev ) const { return generic_category().message( ev ); } # else - BOOST_SYSTEM_INLINE std::string system_error_category::message( int ev ) const + BOOST_SYSTEM_DECL_ std::string system_error_category::message( int ev ) const { #if defined(UNDER_CE) || BOOST_PLAT_WINDOWS_RUNTIME || defined(BOOST_NO_ANSI_APIS) std::wstring buf(128, wchar_t()); @@ -443,7 +433,7 @@ namespace detail } # endif -#undef BOOST_SYSTEM_INLINE +#undef BOOST_SYSTEM_DECL_ } // namespace detail @@ -474,17 +464,17 @@ namespace detail namespace detail { -BOOST_SYSTEM_CONST_INIT const system_error_category system_category_const; -BOOST_SYSTEM_CONST_INIT const generic_error_category generic_category_const; +BOOST_SYSTEM_CONST_INIT BOOST_SYSTEM_DECL system_error_category system_category_instance; +BOOST_SYSTEM_CONST_INIT BOOST_SYSTEM_DECL generic_error_category generic_category_instance; BOOST_SYSTEM_DECL const error_category & system_category_ncx() BOOST_SYSTEM_NOEXCEPT { - return system_category_const; + return system_category_instance; } BOOST_SYSTEM_DECL const error_category & generic_category_ncx() BOOST_SYSTEM_NOEXCEPT { - return generic_category_const; + return generic_category_instance; } } // namespace detail @@ -498,14 +488,14 @@ namespace detail BOOST_SYSTEM_DECL const error_category & system_category_ncx() BOOST_SYSTEM_NOEXCEPT { - static const detail::system_error_category system_category_const; - return system_category_const; + static const detail::system_error_category system_category_instance; + return system_category_instance; } BOOST_SYSTEM_DECL const error_category & generic_category_ncx() BOOST_SYSTEM_NOEXCEPT { - static const detail::generic_error_category generic_category_const; - return generic_category_const; + static const detail::generic_error_category generic_category_instance; + return generic_category_instance; } } // namespace detail diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index bb557f3..367d485 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -338,22 +338,38 @@ namespace boost namespace detail { - class generic_error_category : public error_category - { - public: - BOOST_SYSTEM_CONSTEXPR generic_error_category(){} - const char * name() const BOOST_SYSTEM_NOEXCEPT; - std::string message( int ev ) const; - }; +#ifdef BOOST_ERROR_CODE_HEADER_ONLY +# define BOOST_SYSTEM_DECL_ +#else +# define BOOST_SYSTEM_DECL_ BOOST_SYSTEM_DECL +#endif - class system_error_category : public error_category +class generic_error_category: public error_category +{ +public: + + const char * name() const BOOST_SYSTEM_NOEXCEPT { - public: - BOOST_SYSTEM_CONSTEXPR system_error_category(){} - const char * name() const BOOST_SYSTEM_NOEXCEPT; - std::string message( int ev ) const; - error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT; - }; + return "generic"; + } + + BOOST_SYSTEM_DECL_ std::string message( int ev ) const; +}; + +class system_error_category: public error_category +{ +public: + + const char * name() const BOOST_SYSTEM_NOEXCEPT + { + return "system"; + } + + BOOST_SYSTEM_DECL_ std::string message( int ev ) const; + BOOST_SYSTEM_DECL_ error_condition default_error_condition( int ev ) const BOOST_SYSTEM_NOEXCEPT; +}; + +#undef BOOST_SYSTEM_DECL_ } // namespace detail @@ -361,14 +377,14 @@ namespace detail BOOST_SYSTEM_CONSTEXPR inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT { - static const detail::system_error_category system_category_const; - return system_category_const; + static const detail::system_error_category system_category_instance; + return system_category_instance; } BOOST_SYSTEM_CONSTEXPR inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT { - static const detail::generic_error_category generic_category_const; - return generic_category_const; + static const detail::generic_error_category generic_category_instance; + return generic_category_instance; } #elif defined(BOOST_SYSTEM_HAS_CONSTEXPR) @@ -376,19 +392,19 @@ BOOST_SYSTEM_CONSTEXPR inline const error_category & generic_category() BOOST_SY namespace detail { -extern const system_error_category system_category_const; -extern const generic_error_category generic_category_const; +extern system_error_category system_category_instance; +extern generic_error_category generic_category_instance; } // namespace detail constexpr const error_category & system_category() BOOST_SYSTEM_NOEXCEPT { - return detail::system_category_const; + return detail::system_category_instance; } constexpr const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT { - return detail::generic_category_const; + return detail::generic_category_instance; } #else diff --git a/test/std_mismatch_test.cpp b/test/std_mismatch_test.cpp index 37a606b..9c97cdd 100644 --- a/test/std_mismatch_test.cpp +++ b/test/std_mismatch_test.cpp @@ -38,7 +38,6 @@ static void test_generic_category() std::error_category const & st = bt; BOOST_TEST_CSTR_EQ( bt.name(), st.name() ); - BOOST_TEST_EQ( bt.name(), st.name() ); } static void test_system_category() @@ -47,7 +46,6 @@ static void test_system_category() std::error_category const & st = bt; BOOST_TEST_CSTR_EQ( bt.name(), st.name() ); - BOOST_TEST_EQ( bt.name(), st.name() ); } int main() From 587ceaf7393b6b9395d42ac0673aed56b4671bb0 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 22 Jan 2018 04:56:40 +0200 Subject: [PATCH 07/11] Enable constexpr in header-only mode as well --- include/boost/system/detail/error_code.ipp | 15 +------- include/boost/system/error_code.hpp | 45 ++++++++++++++++++++-- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/include/boost/system/detail/error_code.ipp b/include/boost/system/detail/error_code.ipp index d93fb1f..f9516e0 100644 --- a/include/boost/system/detail/error_code.ipp +++ b/include/boost/system/detail/error_code.ipp @@ -452,20 +452,11 @@ namespace detail #elif defined(BOOST_SYSTEM_HAS_CONSTEXPR) -#define BOOST_SYSTEM_CONST_INIT - -#if defined(__has_cpp_attribute) -#if __has_cpp_attribute(clang::require_constant_initialization) -# undef BOOST_SYSTEM_CONST_INIT -# define BOOST_SYSTEM_CONST_INIT [[clang::require_constant_initialization]] -#endif -#endif - namespace detail { -BOOST_SYSTEM_CONST_INIT BOOST_SYSTEM_DECL system_error_category system_category_instance; -BOOST_SYSTEM_CONST_INIT BOOST_SYSTEM_DECL generic_error_category generic_category_instance; +BOOST_SYSTEM_REQUIRE_CONST_INIT BOOST_SYSTEM_DECL system_error_category system_category_instance; +BOOST_SYSTEM_REQUIRE_CONST_INIT BOOST_SYSTEM_DECL generic_error_category generic_category_instance; BOOST_SYSTEM_DECL const error_category & system_category_ncx() BOOST_SYSTEM_NOEXCEPT { @@ -479,8 +470,6 @@ BOOST_SYSTEM_DECL const error_category & generic_category_ncx() BOOST_SYSTEM_NOE } // namespace detail -#undef BOOST_SYSTEM_CONST_INIT - #else namespace detail diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index 367d485..7be7005 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -38,7 +38,7 @@ #define BOOST_SYSTEM_NOEXCEPT BOOST_NOEXCEPT #endif -#if !defined(BOOST_NO_CXX14_CONSTEXPR) && !defined(BOOST_ERROR_CODE_HEADER_ONLY) +#if !defined(BOOST_NO_CXX14_CONSTEXPR) # define BOOST_SYSTEM_HAS_CONSTEXPR #endif @@ -373,20 +373,59 @@ public: } // namespace detail +#define BOOST_SYSTEM_REQUIRE_CONST_INIT + +#if defined(__has_cpp_attribute) +#if __has_cpp_attribute(clang::require_constant_initialization) +# undef BOOST_SYSTEM_REQUIRE_CONST_INIT +# define BOOST_SYSTEM_REQUIRE_CONST_INIT [[clang::require_constant_initialization]] +#endif +#endif + #if defined(BOOST_ERROR_CODE_HEADER_ONLY) -BOOST_SYSTEM_CONSTEXPR inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT +# if defined(BOOST_SYSTEM_HAS_CONSTEXPR) + +namespace detail +{ + +template struct cat_holder +{ + static system_error_category system_category_instance; + static generic_error_category generic_category_instance; +}; + +template BOOST_SYSTEM_REQUIRE_CONST_INIT system_error_category cat_holder::system_category_instance; +template BOOST_SYSTEM_REQUIRE_CONST_INIT generic_error_category cat_holder::generic_category_instance; + +} // namespace detail + +constexpr const error_category & system_category() BOOST_SYSTEM_NOEXCEPT +{ + return detail::cat_holder::system_category_instance; +} + +constexpr const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT +{ + return detail::cat_holder::generic_category_instance; +} + +# else + +inline const error_category & system_category() BOOST_SYSTEM_NOEXCEPT { static const detail::system_error_category system_category_instance; return system_category_instance; } -BOOST_SYSTEM_CONSTEXPR inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT +inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT { static const detail::generic_error_category generic_category_instance; return generic_category_instance; } +# endif + #elif defined(BOOST_SYSTEM_HAS_CONSTEXPR) namespace detail From 19d5bf5f04eb44db6fcce283de4478cb9064a8bd Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 22 Jan 2018 17:39:29 +0200 Subject: [PATCH 08/11] clang++ 3.8 and below requires a user-provided default constructor --- include/boost/system/error_code.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index 7be7005..f40a99e 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -348,6 +348,12 @@ class generic_error_category: public error_category { public: + // clang++ 3.8 and below: initialization of const object + // requires a user-provided default constructor + BOOST_SYSTEM_CONSTEXPR generic_error_category() BOOST_SYSTEM_NOEXCEPT + { + } + const char * name() const BOOST_SYSTEM_NOEXCEPT { return "generic"; @@ -360,6 +366,10 @@ class system_error_category: public error_category { public: + BOOST_SYSTEM_CONSTEXPR system_error_category() BOOST_SYSTEM_NOEXCEPT + { + } + const char * name() const BOOST_SYSTEM_NOEXCEPT { return "system"; From 9f5272fa61ce994ca933632acbf0db8d9a5f0240 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 22 Jan 2018 18:28:00 +0200 Subject: [PATCH 09/11] Install libstdc++-4.9 for clang++ 5.0 ubsan --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 109dec7..c41b380 100644 --- a/.travis.yml +++ b/.travis.yml @@ -226,6 +226,7 @@ matrix: apt: packages: - clang-5.0 + - libstdc++-4.9-dev sources: - ubuntu-toolchain-r-test - llvm-toolchain-trusty-5.0 From a413220f8dc3d51aee79eabe6c2bfec33b8bf288 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 22 Jan 2018 19:43:28 +0200 Subject: [PATCH 10/11] Add more constexpr tests --- test/constexpr_test.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/constexpr_test.cpp b/test/constexpr_test.cpp index 2c50aa5..386ce66 100644 --- a/test/constexpr_test.cpp +++ b/test/constexpr_test.cpp @@ -6,6 +6,8 @@ #include #include #include +#include +#include #if !defined(BOOST_SYSTEM_HAS_CONSTEXPR) @@ -20,11 +22,34 @@ constexpr error_code e1( 1, system_category() ); BOOST_STATIC_ASSERT( e1.value() == 1 ); BOOST_STATIC_ASSERT( e1.category() == system_category() ); +BOOST_STATIC_ASSERT( e1 ); +BOOST_STATIC_ASSERT( e1 == e1 ); constexpr error_code e2( 2, generic_category() ); BOOST_STATIC_ASSERT( e2.value() == 2 ); BOOST_STATIC_ASSERT( e2.category() == generic_category() ); +BOOST_STATIC_ASSERT( e2 ); +BOOST_STATIC_ASSERT( e2 == e2 ); + +#if !BOOST_WORKAROUND(BOOST_GCC, < 80000) + +BOOST_STATIC_ASSERT( e1 != e2 ); + +#endif + +constexpr error_code e3; + +BOOST_STATIC_ASSERT( e3.value() == 0 ); +BOOST_STATIC_ASSERT( e3.category() == system_category() ); +BOOST_STATIC_ASSERT( !e3 ); +BOOST_STATIC_ASSERT( e3 == e3 ); + +#if !BOOST_WORKAROUND(BOOST_GCC, < 80000) + +BOOST_STATIC_ASSERT( e1 != e3 ); + +#endif int main() { @@ -34,6 +59,9 @@ int main() error_code e2_( 2, generic_category() ); BOOST_TEST_EQ( e2, e2_ ); + error_code e3_; + BOOST_TEST_EQ( e3, e3_ ); + return boost::report_errors(); } From 35e3e22c7ef645fec86cec90715139626ec872bf Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 22 Jan 2018 23:39:59 +0200 Subject: [PATCH 11/11] Add BOOST_SYSTEM_CONSTEXPR to operator bool --- include/boost/system/error_code.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/system/error_code.hpp b/include/boost/system/error_code.hpp index 472a55b..57e7175 100644 --- a/include/boost/system/error_code.hpp +++ b/include/boost/system/error_code.hpp @@ -544,7 +544,7 @@ inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) - explicit operator bool() const BOOST_SYSTEM_NOEXCEPT // true if error + BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_SYSTEM_NOEXCEPT // true if error { return m_val != 0; } @@ -654,7 +654,7 @@ inline const error_category & generic_category() BOOST_SYSTEM_NOEXCEPT #if !defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) - explicit operator bool() const BOOST_SYSTEM_NOEXCEPT // true if error + BOOST_SYSTEM_CONSTEXPR explicit operator bool() const BOOST_SYSTEM_NOEXCEPT // true if error { return m_val != 0; }