diff --git a/include/boost/archive/basic_archive.hpp b/include/boost/archive/basic_archive.hpp index fda450fcf..42e8202c5 100644 --- a/include/boost/archive/basic_archive.hpp +++ b/include/boost/archive/basic_archive.hpp @@ -46,7 +46,7 @@ class version_type { public: // should be private - but MPI fails if it's not!!! version_type(): t(0) {} - explicit version_type(const unsigned int & t_) : t(t_){ + explicit version_type(const unsigned int t_) : t(t_){ BOOST_ASSERT(t_ <= boost::integer_traits::const_max); } version_type(const version_type & t_) : @@ -119,7 +119,7 @@ class object_id_type { object_id_type(): t(0) {} // note: presumes that size_t >= unsigned int. // use explicit cast to silence useless warning - explicit object_id_type(const std::size_t & t_) : t(static_cast(t_)){ + explicit object_id_type(const std::size_t t_) : t(static_cast(t_)){ // make quadruple sure that we haven't lost any real integer // precision BOOST_ASSERT(t_ <= boost::integer_traits::const_max); diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 44e1955ed..6a773f6b2 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -116,6 +116,7 @@ test-suite "serialization" : [ test-bsl-run_files test_unique_ptr ] [ test-bsl-run_files test_valarray ] [ test-bsl-run_files test_variant : A ] + [ test-bsl-run_files test_version_value_type ] [ test-bsl-run_files test_vector : A ] [ test-bsl-run_files test_shared_ptr ] [ test-bsl-run_files test_shared_ptr_multi_base ] diff --git a/test/test_version_value_type.cpp b/test/test_version_value_type.cpp new file mode 100644 index 000000000..b621dad7b --- /dev/null +++ b/test/test_version_value_type.cpp @@ -0,0 +1,120 @@ +/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8 +// test_version_value_type.cpp + +// Copyright 2026 Gennaro Prota. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// See http://www.boost.org for updates, documentation, and revision history. + +// A version trait written by hand has to work whichever integer type it +// names for its value. The library declares the trait as an int, but +// nothing stops a user from writing unsigned int, and doing so used to +// leave the value with no definition to link against: it was passed to +// version_type through a reference, which made a definition necessary. + +// Reported by LowLevelMahn in +// https://github.com/boostorg/serialization/issues/311, together with a +// self contained example which linked with one integer type and not with +// the other. Thanks! + +// Note that this only ever failed on compilers which do not fold the +// constant away, so it links either way on some of them. + +#include +#include +#include + +#include +#if defined(BOOST_NO_STDC_NAMESPACE) +namespace std{ + using ::remove; +} +#endif + +#include +#include + +#include "test_tools.hpp" + +// the value spelled the way the library spells it +struct signed_version { + int value; +}; + +// and spelled the way the report did, which is what used to fail +template +struct unsigned_version { + int value; +}; + +namespace boost { +namespace serialization { + +template<> +struct version +{ + BOOST_STATIC_CONSTANT(int, value = 1); +}; + +// a partial specialization, as in the report +template +struct version > +{ + BOOST_STATIC_CONSTANT(unsigned int, value = 2); +}; + +template +void serialize(Archive & ar, signed_version & t, const unsigned int file_version){ + BOOST_CHECK(1 == file_version); + ar & BOOST_SERIALIZATION_NVP(t.value); +} + +template +void serialize( + Archive & ar, + unsigned_version & t, + const unsigned int file_version +){ + BOOST_CHECK(2 == file_version); + ar & BOOST_SERIALIZATION_NVP(t.value); +} + +} // namespace serialization +} // namespace boost + +typedef unsigned_version unsigned_version_type; + +int +test_main(int /* argc */, char * /* argv */ []) +{ + const char * testfile = boost::archive::tmpnam(NULL); + BOOST_REQUIRE(NULL != testfile); + + { + signed_version a; + a.value = 11; + unsigned_version_type b; + b.value = 22; + test_ostream os(testfile, TEST_STREAM_FLAGS); + test_oarchive oa(os, TEST_ARCHIVE_FLAGS); + oa << BOOST_SERIALIZATION_NVP(a); + oa << BOOST_SERIALIZATION_NVP(b); + } + { + signed_version a; + a.value = 0; + unsigned_version_type b; + b.value = 0; + test_istream is(testfile, TEST_STREAM_FLAGS); + test_iarchive ia(is, TEST_ARCHIVE_FLAGS); + ia >> BOOST_SERIALIZATION_NVP(a); + ia >> BOOST_SERIALIZATION_NVP(b); + BOOST_CHECK(11 == a.value); + BOOST_CHECK(22 == b.value); + } + + std::remove(testfile); + return EXIT_SUCCESS; +}