From a7f33f5d6fe4d4c62f5e0364595131a591a7d4ac Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Tue, 31 Oct 2017 02:47:13 +0100 Subject: [PATCH] more defensive checking for trivial types -- avoiding bugs --- .../boost/optional/detail/optional_config.hpp | 29 ++++++++++++++++++- include/boost/optional/optional.hpp | 12 ++++++-- test/optional_test_static_properties.cpp | 25 ++++++++-------- 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/include/boost/optional/detail/optional_config.hpp b/include/boost/optional/detail/optional_config.hpp index d5d3514..6bb411c 100644 --- a/include/boost/optional/detail/optional_config.hpp +++ b/include/boost/optional/detail/optional_config.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. -// Copyright (C) 2015 Andrzej Krzemienski. +// Copyright (C) 2015 - 2017 Andrzej Krzemienski. // // Use, modification, and distribution is subject to the Boost Software // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -15,6 +15,7 @@ #include #include +#include #if (defined BOOST_NO_CXX11_RVALUE_REFERENCES) || (defined BOOST_OPTIONAL_CONFIG_NO_RVALUE_REFERENCES) # define BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES @@ -124,4 +125,30 @@ # define BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_FUNCTIONS #endif + +// The condition to use POD implementation + +#ifdef BOOST_OPTIONAL_CONFIG_NO_POD_SPEC +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif defined BOOST_OPTIONAL_CONFIG_NO_SPEC_FOR_TRIVIAL_TYPES +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_CONSTRUCTOR +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_MOVE_ASSIGN +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_COPY +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_ASSIGN +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#elif !defined BOOST_HAS_TRIVIAL_DESTRUCTOR +# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES +#endif + +#ifdef BOOST_OPTIONAL_CONFIG_NO_POD_SPEC +# define BOOST_OPTIONAL_DETAIL_NO_POD_SPEC +#endif + + #endif // header guard diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 6d5a5a7..4a237a1 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -806,6 +806,7 @@ struct is_optional_val_init_candidate {}; +#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES template struct is_type_trivially_copyable : boost::conditional<(boost::has_trivial_copy_constructor::value && @@ -815,6 +816,13 @@ struct is_type_trivially_copyable boost::has_trivial_assign::value), boost::true_type, boost::false_type>::type {}; +#else +template +struct is_type_trivially_copyable +: boost::conditional<(boost::is_scalar::value && !boost::is_const::value && !boost::is_volatile::value), + boost::true_type, boost::false_type>::type +{}; +#endif } // namespace optional_detail @@ -822,7 +830,7 @@ namespace optional_config { template struct is_type_trivial - : boost::conditional< (optional_detail::is_type_trivially_copyable::value && boost::has_trivial_default_constructor::value) || + : boost::conditional< (optional_detail::is_type_trivially_copyable::value && BOOST_HAS_TRIVIAL_CONSTRUCTOR(T)) || (boost::is_scalar::value && !boost::is_const::value && !boost::is_volatile::value) , boost::true_type, boost::false_type>::type {}; @@ -830,7 +838,7 @@ struct is_type_trivial } // namespace optional_config -#ifndef BOOST_OPTIONAL_CONFIG_NO_SPEC_FOR_TRIVIAL_TYPES +#ifndef BOOST_OPTIONAL_DETAIL_NO_POD_SPEC # define BOOST_OPTIONAL_BASE_TYPE(T) boost::conditional< optional_config::is_type_trivial::value, \ optional_detail::tc_optional_base, \ optional_detail::optional_base \ diff --git a/test/optional_test_static_properties.cpp b/test/optional_test_static_properties.cpp index 02c1af6..d9a0b69 100644 --- a/test/optional_test_static_properties.cpp +++ b/test/optional_test_static_properties.cpp @@ -19,12 +19,7 @@ #include "boost/core/lightweight_test_trait.hpp" #include "boost/type_traits/is_base_of.hpp" -#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS - -#if (defined BOOST_HAS_TRIVIAL_MOVE_ASSIGN) && (defined BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR) && (defined BOOST_HAS_TRIVIAL_CONSTRUCTOR) && (defined BOOST_HAS_TRIVIAL_COPY) && (defined BOOST_HAS_TRIVIAL_ASSIGN) && (defined BOOST_HAS_TRIVIAL_DESTRUCTOR) -#else -# define BOOST_OPTIONAL_NO_TRIVIALITY_DETECTION -#endif +#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_FUNCTIONS struct PrivDefault { @@ -77,9 +72,7 @@ void test_type_traits() // this only tests if type traits are implemented correctly BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial )); BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial > )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial, double> > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial )); @@ -95,11 +88,17 @@ void test_type_traits() BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + + +#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::is_type_trivial, double> > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable, double> > )); - -#ifndef BOOST_OPTIONAL_NO_TRIVIALITY_DETECTION + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); @@ -118,7 +117,7 @@ void test_trivial_copyability() BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); -#ifndef BOOST_OPTIONAL_NO_TRIVIALITY_DETECTION +#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); @@ -132,7 +131,7 @@ void test_trivial_copyability() int main() { -#ifndef BOOST_NO_CXX11_DEFAULTED_FUNCTIONS +#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_FUNCTIONS test_type_traits(); test_trivial_copyability(); #endif