From 49b183a9ecf62bc1b37e53bdddf42e6ea4ce4cd7 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Fri, 21 Dec 2018 04:09:01 +0000 Subject: [PATCH] Implement LWG 3065: Make path operators friends. This prevents things like: using namespace std::filesystem; auto x = L"a/b" == std::string("a/b"); llvm-svn: 349884 --- libcxx/include/filesystem | 62 ++++++++----------- .../path.nonmember/append_op.fail.cpp | 27 ++++++++ .../path.nonmember/append_op.pass.cpp | 4 +- .../path.nonmember/comparison_ops.fail.cpp | 33 ++++++++++ libcxx/www/cxx2a_status.html | 2 +- 5 files changed, 89 insertions(+), 39 deletions(-) create mode 100644 libcxx/test/std/input.output/filesystems/class.path/path.nonmember/append_op.fail.cpp create mode 100644 libcxx/test/std/input.output/filesystems/class.path/path.nonmember/comparison_ops.fail.cpp diff --git a/libcxx/include/filesystem b/libcxx/include/filesystem index 06a0eb33c4e5..af713a063587 100644 --- a/libcxx/include/filesystem +++ b/libcxx/include/filesystem @@ -1151,6 +1151,31 @@ public: return __is; } + friend _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, const path& __rhs) noexcept { + return __lhs.compare(__rhs) == 0; + } + friend _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.compare(__rhs) != 0; + } + friend _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, const path& __rhs) noexcept { + return __lhs.compare(__rhs) < 0; + } + friend _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.compare(__rhs) <= 0; + } + friend _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, const path& __rhs) noexcept { + return __lhs.compare(__rhs) > 0; + } + friend _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, const path& __rhs) noexcept { + return __lhs.compare(__rhs) >= 0; + } + + friend _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs, + const path& __rhs) { + path __result(__lhs); + __result /= __rhs; + return __result; + } private: inline _LIBCPP_INLINE_VISIBILITY path& __assign_view(__string_view const& __s) noexcept { @@ -1167,43 +1192,6 @@ inline _LIBCPP_INLINE_VISIBILITY void swap(path& __lhs, path& __rhs) noexcept { _LIBCPP_FUNC_VIS size_t hash_value(const path& __p) noexcept; -inline _LIBCPP_INLINE_VISIBILITY bool operator==(const path& __lhs, - const path& __rhs) noexcept { - return __lhs.compare(__rhs) == 0; -} - -inline _LIBCPP_INLINE_VISIBILITY bool operator!=(const path& __lhs, - const path& __rhs) noexcept { - return __lhs.compare(__rhs) != 0; -} - -inline _LIBCPP_INLINE_VISIBILITY bool operator<(const path& __lhs, - const path& __rhs) noexcept { - return __lhs.compare(__rhs) < 0; -} - -inline _LIBCPP_INLINE_VISIBILITY bool operator<=(const path& __lhs, - const path& __rhs) noexcept { - return __lhs.compare(__rhs) <= 0; -} - -inline _LIBCPP_INLINE_VISIBILITY bool operator>(const path& __lhs, - const path& __rhs) noexcept { - return __lhs.compare(__rhs) > 0; -} - -inline _LIBCPP_INLINE_VISIBILITY bool operator>=(const path& __lhs, - const path& __rhs) noexcept { - return __lhs.compare(__rhs) >= 0; -} - -inline _LIBCPP_INLINE_VISIBILITY path operator/(const path& __lhs, - const path& __rhs) { - path __result(__lhs); - __result /= __rhs; - return __result; -} - template _LIBCPP_INLINE_VISIBILITY typename enable_if<__is_pathable<_Source>::value, path>::type diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/append_op.fail.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/append_op.fail.cpp new file mode 100644 index 000000000000..e0b3a959c29f --- /dev/null +++ b/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/append_op.fail.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +#include "filesystem_include.hpp" + +using namespace fs; + +struct ConvToPath { + operator fs::path() const { + return ""; + } +}; + +int main() { + ConvToPath LHS, RHS; + (void)(LHS / RHS); // expected-error {{invalid operands to binary expression}} +} \ No newline at end of file diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/append_op.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/append_op.pass.cpp index 09498bf2135a..2a291d61da7c 100644 --- a/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/append_op.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/append_op.pass.cpp @@ -20,7 +20,6 @@ #include "test_macros.h" #include "filesystem_test_helper.hpp" - // This is mainly tested via the member append functions. int main() { @@ -29,4 +28,7 @@ int main() path p2("def"); path p3 = p1 / p2; assert(p3 == "abc/def"); + + path p4 = p1 / "def"; + assert(p4 == "abc/def"); } diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/comparison_ops.fail.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/comparison_ops.fail.cpp new file mode 100644 index 000000000000..00eafe532d08 --- /dev/null +++ b/libcxx/test/std/input.output/filesystems/class.path/path.nonmember/comparison_ops.fail.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + + +#include "filesystem_include.hpp" + +using namespace fs; + +struct ConvToPath { + operator fs::path() const { + return ""; + } +}; + +int main() { + ConvToPath LHS, RHS; + (void)(LHS == RHS); // expected-error {{invalid operands to binary expression}} + (void)(LHS != RHS); // expected-error {{invalid operands to binary expression}} + (void)(LHS < RHS); // expected-error {{invalid operands to binary expression}} + (void)(LHS <= RHS); // expected-error {{invalid operands to binary expression}} + (void)(LHS > RHS); // expected-error {{invalid operands to binary expression}} + (void)(LHS >= RHS); // expected-error {{invalid operands to binary expression}} +} \ No newline at end of file diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html index 88aa56e38a85..1a072c9b0540 100644 --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -270,7 +270,7 @@ 3037polymorphic_allocator and incomplete typesSan Diego 3038polymorphic_allocator::allocate should not allow integer overflow to create vulnerabilitiesSan Diego 3054uninitialized_copy appears to not be able to meet its exception-safety guaranteeSan Diego - 3065LWG 2989 missed that all path's other operators should be hidden friends as wellSan Diego + 3065LWG 2989 missed that all path's other operators should be hidden friends as wellSan DiegoComplete 3096path::lexically_relative is confused by trailing slashesSan Diego 3116OUTERMOST_ALLOC_TRAITS needs remove_reference_tSan Diego 3122__cpp_lib_chrono_udls was accidentally droppedSan DiegoWe've already made the update; but we don't support all the test macros. When we do, this will be closed