From 95f0b35c36ae271e1feaf0f43a6efd43d0a75a20 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Fri, 2 Feb 2024 05:12:41 +0300 Subject: [PATCH] Move fclose_deleter and null_deleter to their own namespaces to block ADL. This prevents bringing namespace boost into ADL when the deleters are used in template parameters, e.g. in std::unique_ptr. --- doc/changes.qbk | 9 +++++++ include/boost/core/fclose_deleter.hpp | 7 ++++++ include/boost/core/null_deleter.hpp | 7 ++++++ test/Jamfile.v2 | 5 ++++ test/fclose_deleter_compile_fail_adl.cpp | 30 ++++++++++++++++++++++++ test/null_deleter_compile_fail_adl.cpp | 30 ++++++++++++++++++++++++ 6 files changed, 88 insertions(+) create mode 100644 test/fclose_deleter_compile_fail_adl.cpp create mode 100644 test/null_deleter_compile_fail_adl.cpp diff --git a/doc/changes.qbk b/doc/changes.qbk index 3c9d600..ecaeffa 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -11,6 +11,15 @@ * Added a new [link core.functor `boost/core/functor.hpp`] header with a `functor` class template for wrapping a raw function into a function object class. +* Changed [link core.null_deleter `null_deleter`] and [link core.fclose_deleter `fclose_deleter`] + definitions so that they don't bring namespace `boost` into argument-dependent lookup in cases + like this: + ``` + std::unique_ptr< std::FILE, boost::fclose_deleter > p1, p2; + swap(p1, p2); // no longer looks for boost::swap as part of ADL + ``` + Users may need to either explicitly qualify the namespace of the called function or add a + `using`-declaration. [endsect] diff --git a/include/boost/core/fclose_deleter.hpp b/include/boost/core/fclose_deleter.hpp index 8f7a7fd..7a31cb1 100644 --- a/include/boost/core/fclose_deleter.hpp +++ b/include/boost/core/fclose_deleter.hpp @@ -26,6 +26,9 @@ namespace boost { +// Block unintended ADL +namespace fclose_deleter_ns { + //! A function object that closes a file struct fclose_deleter { @@ -41,6 +44,10 @@ struct fclose_deleter } }; +} // namespace fclose_deleter_ns + +using fclose_deleter_ns::fclose_deleter; + } // namespace boost #endif // BOOST_CORE_FCLOSE_DELETER_HPP diff --git a/include/boost/core/null_deleter.hpp b/include/boost/core/null_deleter.hpp index f0af590..08b6a3d 100644 --- a/include/boost/core/null_deleter.hpp +++ b/include/boost/core/null_deleter.hpp @@ -27,6 +27,9 @@ namespace boost { +// Block unintended ADL +namespace null_deleter_ns { + //! A function object that does nothing and can be used as an empty deleter for \c shared_ptr struct null_deleter { @@ -39,6 +42,10 @@ struct null_deleter void operator() (T*) const BOOST_NOEXCEPT {} }; +} // namespace null_deleter_ns + +using null_deleter_ns::null_deleter; + } // namespace boost #endif // BOOST_CORE_NULL_DELETER_HPP diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index b64a094..c88ec4f 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -187,7 +187,12 @@ compile-fail scoped_enum_compile_fail_conv_to_int.cpp run underlying_type.cpp ; +compile-fail null_deleter_compile_fail_adl.cpp + : $(warnings-as-errors-off) ; + run fclose_deleter_test.cpp : : : windows:_CRT_SECURE_NO_WARNINGS windows:_CRT_SECURE_NO_DEPRECATE ; +compile-fail fclose_deleter_compile_fail_adl.cpp + : windows:_CRT_SECURE_NO_WARNINGS windows:_CRT_SECURE_NO_DEPRECATE $(warnings-as-errors-off) ; run functor_test.cpp ; diff --git a/test/fclose_deleter_compile_fail_adl.cpp b/test/fclose_deleter_compile_fail_adl.cpp new file mode 100644 index 0000000..135edbf --- /dev/null +++ b/test/fclose_deleter_compile_fail_adl.cpp @@ -0,0 +1,30 @@ +/* + * Copyright Andrey Semashev 2024. + * 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) + */ +/*! + * \file fclose_deleter_compile_fail_adl.cpp + * \author Andrey Semashev + * \date 02.02.2024 + * + * This file tests that \c boost::fclose_deleter doesn't bring namespace + * boost into ADL. + */ + +#include + +namespace boost { + +void check_adl(fclose_deleter const&) +{ +} + +} // namespace boost + +int main() +{ + // Must not find boost::check_adl + check_adl(boost::fclose_deleter()); +} diff --git a/test/null_deleter_compile_fail_adl.cpp b/test/null_deleter_compile_fail_adl.cpp new file mode 100644 index 0000000..4e24851 --- /dev/null +++ b/test/null_deleter_compile_fail_adl.cpp @@ -0,0 +1,30 @@ +/* + * Copyright Andrey Semashev 2024. + * 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) + */ +/*! + * \file fclose_deleter_compile_fail_adl.cpp + * \author Andrey Semashev + * \date 02.02.2024 + * + * This file tests that \c boost::null_deleter doesn't bring namespace + * boost into ADL. + */ + +#include + +namespace boost { + +void check_adl(null_deleter const&) +{ +} + +} // namespace boost + +int main() +{ + // Must not find boost::check_adl + check_adl(boost::null_deleter()); +}