void-packages/srcpkgs/boost/patches/fix-boost-filesystem-285.patch

307 lines
11 KiB
Diff

From 396eef1398a87463a234e7d313d637ea67df96b5 Mon Sep 17 00:00:00 2001
From: Andrey Semashev <andrey.semashev@gmail.com>
Date: Sun, 7 May 2023 20:58:27 +0300
Subject: [PATCH] Restrict generic path comparison operators to avoid
ambiguities with std lib.
Path comparison operators that accept arbitrary path source types now require
the other argument to be exactly path. This prevents the compiler from picking
those operators when the other argument is convertible to path. This can happen
even when neither of the arguments are actually paths, e.g. when the
comparison operators are brought into the current scope by a using directive.
Fixes https://github.com/boostorg/filesystem/issues/285.
---
diff --git a/boost/filesystem/path.hpp b/boost/filesystem/path.hpp
index 61278ef74..729e18812 100644
--- a/boost/filesystem/path.hpp
+++ b/boost/filesystem/path.hpp
@@ -1287,20 +1287,26 @@ BOOST_FORCEINLINE bool operator==(path const& lhs, path const& rhs)
return lhs.compare(rhs) == 0;
}
-template< typename Source >
+template< typename Path, typename Source >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator==(path const& lhs, Source const& rhs)
+>::type operator==(Path const& lhs, Source const& rhs)
{
return lhs.compare(rhs) == 0;
}
-template< typename Source >
+template< typename Source, typename Path >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator==(Source const& lhs, path const& rhs)
+>::type operator==(Source const& lhs, Path const& rhs)
{
return rhs.compare(lhs) == 0;
}
@@ -1310,20 +1316,26 @@ BOOST_FORCEINLINE bool operator!=(path const& lhs, path const& rhs)
return lhs.compare(rhs) != 0;
}
-template< typename Source >
+template< typename Path, typename Source >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator!=(path const& lhs, Source const& rhs)
+>::type operator!=(Path const& lhs, Source const& rhs)
{
return lhs.compare(rhs) != 0;
}
-template< typename Source >
+template< typename Source, typename Path >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator!=(Source const& lhs, path const& rhs)
+>::type operator!=(Source const& lhs, Path const& rhs)
{
return rhs.compare(lhs) != 0;
}
@@ -1333,20 +1345,26 @@ BOOST_FORCEINLINE bool operator<(path const& lhs, path const& rhs)
return lhs.compare(rhs) < 0;
}
-template< typename Source >
+template< typename Path, typename Source >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator<(path const& lhs, Source const& rhs)
+>::type operator<(Path const& lhs, Source const& rhs)
{
return lhs.compare(rhs) < 0;
}
-template< typename Source >
+template< typename Source, typename Path >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator<(Source const& lhs, path const& rhs)
+>::type operator<(Source const& lhs, Path const& rhs)
{
return rhs.compare(lhs) > 0;
}
@@ -1356,20 +1374,26 @@ BOOST_FORCEINLINE bool operator<=(path const& lhs, path const& rhs)
return lhs.compare(rhs) <= 0;
}
-template< typename Source >
+template< typename Path, typename Source >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator<=(path const& lhs, Source const& rhs)
+>::type operator<=(Path const& lhs, Source const& rhs)
{
return lhs.compare(rhs) <= 0;
}
-template< typename Source >
+template< typename Source, typename Path >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator<=(Source const& lhs, path const& rhs)
+>::type operator<=(Source const& lhs, Path const& rhs)
{
return rhs.compare(lhs) >= 0;
}
@@ -1379,20 +1403,26 @@ BOOST_FORCEINLINE bool operator>(path const& lhs, path const& rhs)
return lhs.compare(rhs) > 0;
}
-template< typename Source >
+template< typename Path, typename Source >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator>(path const& lhs, Source const& rhs)
+>::type operator>(Path const& lhs, Source const& rhs)
{
return lhs.compare(rhs) > 0;
}
-template< typename Source >
+template< typename Source, typename Path >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator>(Source const& lhs, path const& rhs)
+>::type operator>(Source const& lhs, Path const& rhs)
{
return rhs.compare(lhs) < 0;
}
@@ -1402,35 +1432,41 @@ BOOST_FORCEINLINE bool operator>=(path const& lhs, path const& rhs)
return lhs.compare(rhs) >= 0;
}
-template< typename Source >
+template< typename Path, typename Source >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator>=(path const& lhs, Source const& rhs)
+>::type operator>=(Path const& lhs, Source const& rhs)
{
return lhs.compare(rhs) >= 0;
}
-template< typename Source >
+template< typename Source, typename Path >
BOOST_FORCEINLINE typename boost::enable_if_c<
- detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >::value,
+ boost::conjunction<
+ boost::is_same< Path, path >,
+ detail::path_traits::is_convertible_to_path_source< typename boost::remove_cv< Source >::type >
+ >::value,
bool
->::type operator>=(Source const& lhs, path const& rhs)
+>::type operator>=(Source const& lhs, Path const& rhs)
{
return rhs.compare(lhs) <= 0;
}
// Note: Declared as a template to delay binding to Boost.ContainerHash functions and make the dependency optional
-template< typename T >
+template< typename Path >
inline typename boost::enable_if_c<
- boost::is_same< T, path >::value,
+ boost::is_same< Path, path >::value,
std::size_t
->::type hash_value(T const& p) BOOST_NOEXCEPT
+>::type hash_value(Path const& p) BOOST_NOEXCEPT
{
#ifdef BOOST_WINDOWS_API
std::size_t seed = 0u;
- for (typename T::value_type const* it = p.c_str(); *it; ++it)
+ for (typename Path::value_type const* it = p.c_str(); *it; ++it)
hash_combine(seed, *it == L'/' ? L'\\' : *it);
return seed;
#else // BOOST_POSIX_API
diff --git a/libs/filesystem/test/Jamfile.v2 b/libs/filesystem/test/Jamfile.v2
index d1ffc2a6f..5d70b08ec 100644
--- a/libs/filesystem/test/Jamfile.v2
+++ b/libs/filesystem/test/Jamfile.v2
@@ -85,6 +85,7 @@ run operations_test.cpp : : : <link>static <define>BOOST_FILESYSTEM_VERSION=4 :
run operations_unit_test.cpp : $(HERE) : : <link>shared <define>BOOST_FILESYSTEM_VERSION=4 <test-info>always_show_run_output ;
run copy_test.cpp : : : <define>BOOST_FILESYSTEM_VERSION=4 ;
compile-fail cf_path_nullptr_test.cpp ;
+compile path_operator_ambiguity.cpp : <toolset>gcc:<warnings-as-errors>on ;
run path_test.cpp : : : <link>shared <define>BOOST_FILESYSTEM_VERSION=4 ;
run path_test.cpp : : : <link>static <define>BOOST_FILESYSTEM_VERSION=4 : path_test_static ;
run path_test.cpp : : : <link>shared <define>BOOST_FILESYSTEM_VERSION=3 : path_test_v3 ;
diff --git a/libs/filesystem/test/path_operator_ambiguity.cpp b/libs/filesystem/test/path_operator_ambiguity.cpp
new file mode 100644
index 000000000..5a43a63b6
--- /dev/null
+++ b/libs/filesystem/test/path_operator_ambiguity.cpp
@@ -0,0 +1,53 @@
+// Copyright Andrey Semashev 2023
+//
+// Use, modification, and distribution is subject to 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 library home page at http://www.boost.org/libs/filesystem
+//
+// This test verifies that a using directive does not introduce operator
+// ambiguity with the standard library.
+// https://github.com/boostorg/filesystem/issues/285
+
+#include <string>
+#include <boost/filesystem.hpp>
+
+using namespace boost::filesystem;
+
+bool test_eq(char* arg)
+{
+ return std::string("abc") == arg;
+}
+
+bool test_ne(char* arg)
+{
+ return std::string("def") != arg;
+}
+
+bool test_lt(char* arg)
+{
+ return std::string("ghi") < arg;
+}
+
+bool test_gt(char* arg)
+{
+ return std::string("jkl") > arg;
+}
+
+bool test_le(char* arg)
+{
+ return std::string("mno") <= arg;
+}
+
+bool test_ge(char* arg)
+{
+ return std::string("pqr") >= arg;
+}
+
+int main(int, char* argv[])
+{
+ return test_eq(argv[0]) + test_ne(argv[0]) +
+ test_lt(argv[0]) + test_gt(argv[0]) +
+ test_le(argv[0]) + test_ge(argv[0]);
+}