diff --git a/.drone.jsonnet b/.drone.jsonnet index 26999e6..a0bb441 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -106,7 +106,7 @@ local windows_pipeline(name, image, environment, arch = "amd64") = linux_pipeline( "Linux 16.04 GCC 4.8 32/64", "cppalliance/droneubuntu1604:1", - { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11', ADDRMD: '32,64' }, + { TOOLSET: 'gcc', COMPILER: 'g++-4.8', CXXSTD: '11', ADDRMD: '32,64' }, "g++-4.8-multilib", ), @@ -150,16 +150,23 @@ local windows_pipeline(name, image, environment, arch = "amd64") = ), linux_pipeline( - "Linux 20.04 GCC 9* ARM64", + "Linux 20.04 GCC 9* ARM64 ASAN", "cppalliance/droneubuntu2004:multiarch", - { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' }, + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' } + asan, arch="arm64", ), linux_pipeline( - "Linux 20.04 GCC 9* S390x", + "Linux 20.04 GCC 9* ARM64 UBSAN", "cppalliance/droneubuntu2004:multiarch", - { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' }, + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' } + ubsan, + arch="arm64", + ), + + linux_pipeline( + "Linux 20.04 GCC 9* S390x UBSAN", + "cppalliance/droneubuntu2004:multiarch", + { TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' } + ubsan, arch="s390x", ), @@ -184,31 +191,24 @@ local windows_pipeline(name, image, environment, arch = "amd64") = ), linux_pipeline( - "Linux 23.04 GCC 13 32 ASAN", + "Linux 23.04 GCC 13 32/64 ASAN", "cppalliance/droneubuntu2304:1", - { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + asan, + { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32,64' } + asan, "g++-13-multilib", ), linux_pipeline( - "Linux 23.04 GCC 13 64 ASAN", + "Linux 23.04 GCC 13 32/64 UBSAN", "cppalliance/droneubuntu2304:1", - { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '64' } + asan, + { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32,64' } + ubsan, "g++-13-multilib", ), linux_pipeline( - "Linux 23.04 GCC 13 32 UBSAN", - "cppalliance/droneubuntu2304:1", - { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + ubsan, - "g++-13-multilib", - ), - - linux_pipeline( - "Linux 23.04 GCC 13 64 UBSAN", - "cppalliance/droneubuntu2304:1", - { TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '64' } + ubsan, - "g++-13-multilib", + "Linux 24.04 GCC 14 32/64", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '11,14,17,20,2b', ADDRMD: '32,64' }, + "g++-14-multilib", ), linux_pipeline( @@ -351,6 +351,20 @@ local windows_pipeline(name, image, environment, arch = "amd64") = "clang-17", ), + linux_pipeline( + "Linux 24.04 Clang 18 UBSAN", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' } + ubsan, + "clang-18", + ), + + linux_pipeline( + "Linux 24.04 Clang 18 ASAN", + "cppalliance/droneubuntu2404:1", + { TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' } + asan, + "clang-18", + ), + macos_pipeline( "MacOS 10.15 Xcode 12.2 UBSAN", { TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,2a' } + ubsan, diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 424af4f..e557003 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -83,6 +83,12 @@ jobs: os: ubuntu-latest install: g++-13-multilib address-model: 32,64 + - toolset: gcc-14 + cxxstd: "11,14,17,20,2b" + container: ubuntu:24.04 + os: ubuntu-latest + install: g++-14-multilib + address-model: 32,64 - toolset: clang compiler: clang++-3.9 cxxstd: "11,14" @@ -163,6 +169,12 @@ jobs: container: ubuntu:23.10 os: ubuntu-latest install: clang-17 + - toolset: clang + compiler: clang++-18 + cxxstd: "11,14,17,20,2b" + container: ubuntu:24.04 + os: ubuntu-latest + install: clang-18 - toolset: clang cxxstd: "11,14,17,2a" os: macos-11 @@ -172,6 +184,9 @@ jobs: - toolset: clang cxxstd: "11,14,17,20,2b" os: macos-13 + - toolset: clang + cxxstd: "11,14,17,20,2b" + os: macos-14 runs-on: ${{matrix.os}} container: ${{matrix.container}} diff --git a/include/boost/function/function_base.hpp b/include/boost/function/function_base.hpp index 7f78e36..ca15b7b 100644 --- a/include/boost/function/function_base.hpp +++ b/include/boost/function/function_base.hpp @@ -15,17 +15,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -33,6 +22,7 @@ #include #include #include +#include #if defined(BOOST_MSVC) # pragma warning( push ) @@ -43,10 +33,8 @@ // retained because used in a test #define BOOST_FUNCTION_TARGET_FIX(x) -# define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ - typename ::boost::enable_if_< \ - !(::boost::is_integral::value), \ - Type>::type +#define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ + typename std::enable_if< !std::is_integral::value, Type>::type namespace boost { namespace detail { @@ -131,15 +119,15 @@ namespace boost { template class get_function_tag { - typedef typename conditional<(is_pointer::value), + typedef typename std::conditional::value, function_ptr_tag, function_obj_tag>::type ptr_or_obj_tag; - typedef typename conditional<(is_member_pointer::value), + typedef typename std::conditional::value, member_ptr_tag, ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag; - typedef typename conditional<(is_reference_wrapper::value), + typedef typename std::conditional::value, function_obj_ref_tag, ptr_or_obj_or_mem_tag>::type or_ref_tag; @@ -204,8 +192,8 @@ namespace boost { BOOST_STATIC_CONSTANT (bool, value = ((sizeof(F) <= sizeof(function_buffer) && - (alignment_of::value - % alignment_of::value == 0)))); + (std::alignment_of::value + % std::alignment_of::value == 0)))); }; template @@ -306,7 +294,7 @@ namespace boost { // Function objects that fit in the small-object buffer. static inline void manager(const function_buffer& in_buffer, function_buffer& out_buffer, - functor_manager_operation_type op, true_type) + functor_manager_operation_type op, std::true_type) { functor_manager_common::manage_small(in_buffer,out_buffer,op); } @@ -314,7 +302,7 @@ namespace boost { // Function objects that require heap allocation static inline void manager(const function_buffer& in_buffer, function_buffer& out_buffer, - functor_manager_operation_type op, false_type) + functor_manager_operation_type op, std::false_type) { if (op == clone_functor_tag) { // Clone the functor @@ -355,7 +343,7 @@ namespace boost { functor_manager_operation_type op, function_obj_tag) { manager(in_buffer, out_buffer, op, - integral_constant::value)>()); + std::integral_constant::value)>()); } // For member pointers, we use the small-object optimization buffer. @@ -363,7 +351,7 @@ namespace boost { manager(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op, member_ptr_tag) { - manager(in_buffer, out_buffer, op, true_type()); + manager(in_buffer, out_buffer, op, std::true_type()); } public: @@ -401,7 +389,7 @@ namespace boost { // Function objects that fit in the small-object buffer. static inline void manager(const function_buffer& in_buffer, function_buffer& out_buffer, - functor_manager_operation_type op, true_type) + functor_manager_operation_type op, std::true_type) { functor_manager_common::manage_small(in_buffer,out_buffer,op); } @@ -409,7 +397,7 @@ namespace boost { // Function objects that require heap allocation static inline void manager(const function_buffer& in_buffer, function_buffer& out_buffer, - functor_manager_operation_type op, false_type) + functor_manager_operation_type op, std::false_type) { typedef functor_wrapper functor_wrapper_type; @@ -460,7 +448,7 @@ namespace boost { functor_manager_operation_type op, function_obj_tag) { manager(in_buffer, out_buffer, op, - integral_constant::value)>()); + std::integral_constant::value)>()); } public: @@ -529,8 +517,8 @@ public: detail::function::function_buffer type_result; type_result.members.type.type = &BOOST_CORE_TYPEID(Functor); - type_result.members.type.const_qualified = is_const::value; - type_result.members.type.volatile_qualified = is_volatile::value; + type_result.members.type.const_qualified = std::is_const::value; + type_result.members.type.volatile_qualified = std::is_volatile::value; get_vtable()->manager(functor, type_result, detail::function::check_functor_type_tag); return static_cast(type_result.members.obj_ptr); @@ -544,7 +532,7 @@ public: detail::function::function_buffer type_result; type_result.members.type.type = &BOOST_CORE_TYPEID(Functor); type_result.members.type.const_qualified = true; - type_result.members.type.volatile_qualified = is_volatile::value; + type_result.members.type.volatile_qualified = std::is_volatile::value; get_vtable()->manager(functor, type_result, detail::function::check_functor_type_tag); // GCC 2.95.3 gets the CV qualifiers wrong here, so we @@ -553,8 +541,8 @@ public: } template - typename boost::enable_if_< !boost::is_function::value, bool >::type - contains(const F& f) const + typename std::enable_if< !std::is_function::value, bool >::type + contains(const F& f) const { if (const F* fp = this->template target()) { @@ -565,8 +553,8 @@ public: } template - typename boost::enable_if_< boost::is_function::value, bool >::type - contains(Fn& f) const + typename std::enable_if< std::is_function::value, bool >::type + contains(Fn& f) const { typedef Fn* F; if (const F* fp = this->template target()) diff --git a/include/boost/function/function_template.hpp b/include/boost/function/function_template.hpp index ee3fc7a..48329c2 100644 --- a/include/boost/function/function_template.hpp +++ b/include/boost/function/function_template.hpp @@ -15,11 +15,10 @@ #include #include #include -#include -#include #include #include #include +#include #if defined(BOOST_MSVC) # pragma warning( push ) @@ -180,7 +179,7 @@ namespace boost { > struct get_function_invoker { - typedef typename conditional<(is_void::value), + typedef typename std::conditional::value, void_function_invoker< FunctionPtr, R, @@ -201,7 +200,7 @@ namespace boost { > struct get_function_obj_invoker { - typedef typename conditional<(is_void::value), + typedef typename std::conditional::value, void_function_obj_invoker< FunctionObj, R, @@ -222,7 +221,7 @@ namespace boost { > struct get_function_ref_invoker { - typedef typename conditional<(is_void::value), + typedef typename std::conditional::value, void_function_ref_invoker< FunctionObj, R, @@ -244,7 +243,7 @@ namespace boost { > struct get_member_invoker { - typedef typename conditional<(is_void::value), + typedef typename std::conditional::value, void_member_invoker< MemberPtr, R, @@ -499,27 +498,27 @@ namespace boost { // Assign to a function object using the small object optimization template void - assign_functor(FunctionObj f, function_buffer& functor, true_type) const + assign_functor(FunctionObj f, function_buffer& functor, std::true_type) const { new (reinterpret_cast(functor.data)) FunctionObj(std::move(f)); } template void - assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, true_type) const + assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, std::true_type) const { - assign_functor(std::move(f),functor,true_type()); + assign_functor(std::move(f),functor,std::true_type()); } // Assign to a function object allocated on the heap. template void - assign_functor(FunctionObj f, function_buffer& functor, false_type) const + assign_functor(FunctionObj f, function_buffer& functor, std::false_type) const { functor.members.obj_ptr = new FunctionObj(std::move(f)); } template void - assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, false_type) const + assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, std::false_type) const { typedef functor_wrapper functor_wrapper_type; @@ -540,7 +539,7 @@ namespace boost { { if (!boost::detail::function::has_empty_target(boost::addressof(f))) { assign_functor(std::move(f), functor, - integral_constant::value)>()); + std::integral_constant::value)>()); return true; } else { return false; @@ -552,7 +551,7 @@ namespace boost { { if (!boost::detail::function::has_empty_target(boost::addressof(f))) { assign_functor_a(std::move(f), functor, a, - integral_constant::value)>()); + std::integral_constant::value)>()); return true; } else { return false; @@ -566,8 +565,8 @@ namespace boost { function_buffer& functor, function_obj_ref_tag) const { functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer()); - functor.members.obj_ref.is_const_qualified = is_const::value; - functor.members.obj_ref.is_volatile_qualified = is_volatile::value; + functor.members.obj_ref.is_const_qualified = std::is_const::value; + functor.members.obj_ref.is_volatile_qualified = std::is_volatile::value; return true; } template @@ -600,6 +599,17 @@ namespace boost { typedef T1 second_argument_type; }; +#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 50000 + + template struct is_trivially_copyable: std::integral_constant {}; + +#else + + using std::is_trivially_copyable; + +#endif + } // end namespace function } // end namespace detail @@ -643,8 +653,8 @@ namespace boost { // one with a default parameter. template function_n(Functor f - ,typename boost::enable_if_< - !(is_integral::value), + ,typename std::enable_if< + !std::is_integral::value, int>::type = 0 ) : function_base() @@ -653,8 +663,8 @@ namespace boost { } template function_n(Functor f, Allocator a - ,typename boost::enable_if_< - !(is_integral::value), + ,typename std::enable_if< + !std::is_integral::value, int>::type = 0 ) : function_base() @@ -691,8 +701,8 @@ namespace boost { // handle function_n as the type of the temporary to // construct. template - typename boost::enable_if_< - !(is_integral::value), + typename std::enable_if< + !std::is_integral::value, function_n&>::type operator=(Functor f) { @@ -835,8 +845,7 @@ namespace boost { if (stored_vtable.assign_to(std::move(f), functor)) { std::size_t value = reinterpret_cast(&stored_vtable.base); // coverity[pointless_expression]: suppress coverity warnings on apparant if(const). - if (boost::has_trivial_copy_constructor::value && - boost::has_trivial_destructor::value && + if (boost::detail::function::is_trivially_copyable::value && boost::detail::function::function_allows_small_object_optimization::value) value |= static_cast(0x01); vtable = reinterpret_cast(value); @@ -869,8 +878,7 @@ namespace boost { if (stored_vtable.assign_to_a(std::move(f), functor, a)) { std::size_t value = reinterpret_cast(&stored_vtable.base); // coverity[pointless_expression]: suppress coverity warnings on apparant if(const). - if (boost::has_trivial_copy_constructor::value && - boost::has_trivial_destructor::value && + if (boost::detail::function::is_trivially_copyable::value && boost::detail::function::function_allows_small_object_optimization::value) value |= static_cast(0x01); vtable = reinterpret_cast(value); @@ -974,8 +982,8 @@ public: template function(Functor f - ,typename boost::enable_if_< - !(is_integral::value), + ,typename std::enable_if< + !std::is_integral::value, int>::type = 0 ) : base_type(std::move(f)) @@ -983,8 +991,8 @@ public: } template function(Functor f, Allocator a - ,typename boost::enable_if_< - !(is_integral::value), + ,typename std::enable_if< + !std::is_integral::value, int>::type = 0 ) : base_type(std::move(f),a) @@ -1014,8 +1022,8 @@ public: } template - typename boost::enable_if_< - !(is_integral::value), + typename std::enable_if< + !std::is_integral::value, self_type&>::type operator=(Functor f) {