diff options
Diffstat (limited to 'libcxx/test')
22 files changed, 584 insertions, 32 deletions
diff --git a/libcxx/test/benchmarks/numeric/gcd.bench.cpp b/libcxx/test/benchmarks/numeric/gcd.bench.cpp index abbc7e9..ca5fed5 100644 --- a/libcxx/test/benchmarks/numeric/gcd.bench.cpp +++ b/libcxx/test/benchmarks/numeric/gcd.bench.cpp @@ -25,7 +25,7 @@ static std::array<T, 1000> generate(std::uniform_int_distribution<T> distributio static void bm_gcd_random(benchmark::State& state) { std::array data = generate<int>(); - while (state.KeepRunningBatch(data.size())) + while (state.KeepRunningBatch(data.size() * data.size())) for (auto v0 : data) for (auto v1 : data) benchmark::DoNotOptimize(std::gcd(v0, v1)); diff --git a/libcxx/test/libcxx/clang_tidy.gen.py b/libcxx/test/libcxx/clang_tidy.gen.py index 0db9c0d..06f277e 100644 --- a/libcxx/test/libcxx/clang_tidy.gen.py +++ b/libcxx/test/libcxx/clang_tidy.gen.py @@ -33,8 +33,7 @@ for header in public_headers: {lit_header_undeprecations.get(header, '')} // TODO: run clang-tidy with modules enabled once they are supported -// RUN: %{{clang-tidy}} %s --warnings-as-errors=* -header-filter=.* --checks='-*,libcpp-*' --load=%{{test-tools-dir}}/clang_tidy_checks/libcxx-tidy.plugin -- %{{compile_flags}} -fno-modules -// RUN: %{{clang-tidy}} %s --warnings-as-errors=* -header-filter=.* --config-file=%{{libcxx-dir}}/.clang-tidy -- -Wweak-vtables %{{compile_flags}} -fno-modules +// RUN: %{{clang-tidy}} %s --warnings-as-errors=* -header-filter=.* --config-file=%{{libcxx-dir}}/.clang-tidy --load=%{{test-tools-dir}}/clang_tidy_checks/libcxx-tidy.plugin -- -Wweak-vtables %{{compile_flags}} -fno-modules #include <{header}> """) diff --git a/libcxx/test/libcxx/containers/sequences/forwardlist/assert.pass.cpp b/libcxx/test/libcxx/containers/sequences/forwardlist/assert.pass.cpp new file mode 100644 index 0000000..6d1748e --- /dev/null +++ b/libcxx/test/libcxx/containers/sequences/forwardlist/assert.pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// <forward_list> + +// Test hardening assertions for std::forward_list. + +// REQUIRES: has-unix-headers +// REQUIRES: libcpp-hardening-mode={{extensive|debug}} +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include <forward_list> + +#include "check_assertion.h" + +int main(int, char**) { + { // Default-constructed list. + std::forward_list<int> c; + const auto& const_c = c; + TEST_LIBCPP_ASSERT_FAILURE(c.front(), "forward_list::front called on an empty list"); + TEST_LIBCPP_ASSERT_FAILURE(const_c.front(), "forward_list::front called on an empty list"); + TEST_LIBCPP_ASSERT_FAILURE(c.pop_front(), "forward_list::pop_front called on an empty list"); + } + + { // Non-empty list becomes empty. + std::forward_list<int> c; + const auto& const_c = c; + c.push_front(1); + + // Check that there's no assertion on valid access. + (void)c.front(); + (void)const_c.front(); + + c.pop_front(); + TEST_LIBCPP_ASSERT_FAILURE(c.pop_front(), "forward_list::pop_front called on an empty list"); + TEST_LIBCPP_ASSERT_FAILURE(c.front(), "forward_list::front called on an empty list"); + TEST_LIBCPP_ASSERT_FAILURE(const_c.front(), "forward_list::front called on an empty list"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/sequences/vector.bool/assert.pass.cpp b/libcxx/test/libcxx/containers/sequences/vector.bool/assert.pass.cpp new file mode 100644 index 0000000..41badad --- /dev/null +++ b/libcxx/test/libcxx/containers/sequences/vector.bool/assert.pass.cpp @@ -0,0 +1,63 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// <vector> + +// Test hardening assertions for std::vector<bool>. + +// REQUIRES: has-unix-headers +// UNSUPPORTED: libcpp-hardening-mode=none +// UNSUPPORTED: c++03 +// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing + +#include <vector> + +#include "check_assertion.h" +#include "min_allocator.h" + +template <class Allocator> +void test() { + std::vector<bool, Allocator> c; + TEST_LIBCPP_ASSERT_FAILURE(c.front(), "vector<bool>::front() called on an empty vector"); + TEST_LIBCPP_ASSERT_FAILURE(c.back(), "vector<bool>::back() called on an empty vector"); + TEST_LIBCPP_ASSERT_FAILURE(c[0], "vector<bool>::operator[] index out of bounds"); + TEST_LIBCPP_ASSERT_FAILURE(c.pop_back(), "vector<bool>::pop_back called on an empty vector"); + + // Repeat the test with a const reference to test the const overloads. + { + const std::vector<bool, Allocator>& cc = c; + TEST_LIBCPP_ASSERT_FAILURE(cc.front(), "vector<bool>::front() called on an empty vector"); + TEST_LIBCPP_ASSERT_FAILURE(cc.back(), "vector<bool>::back() called on an empty vector"); + TEST_LIBCPP_ASSERT_FAILURE(cc[0], "vector<bool>::operator[] index out of bounds"); + } + + c.push_back(true); + c.push_back(false); + c.push_back(true); + TEST_LIBCPP_ASSERT_FAILURE(c[3], "vector<bool>::operator[] index out of bounds"); + TEST_LIBCPP_ASSERT_FAILURE(c[100], "vector<bool>::operator[] index out of bounds"); + + // Repeat the test with a const reference to test the const overloads. + { + const std::vector<bool, Allocator>& cc = c; + TEST_LIBCPP_ASSERT_FAILURE(cc[3], "vector<bool>::operator[] index out of bounds"); + TEST_LIBCPP_ASSERT_FAILURE(cc[100], "vector<bool>::operator[] index out of bounds"); + } + + TEST_LIBCPP_ASSERT_FAILURE( + c.erase(c.end()), "vector<bool>::erase(iterator) called with a non-dereferenceable iterator"); + TEST_LIBCPP_ASSERT_FAILURE( + c.erase(c.begin() + 1, c.begin()), "vector<bool>::erase(iterator, iterator) called with an invalid range"); +} + +int main(int, char**) { + test<std::allocator<bool>>(); + test<min_allocator<bool>>(); + + return 0; +} diff --git a/libcxx/test/libcxx/diagnostics/system_error_win_codes.pass.cpp b/libcxx/test/libcxx/diagnostics/system_error_win_codes.pass.cpp new file mode 100644 index 0000000..799a5b5 --- /dev/null +++ b/libcxx/test/libcxx/diagnostics/system_error_win_codes.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: windows + +// Validate that system_error on windows accepts Windows' System Error Codes (as +// used by win32 APIs and reported by GetLastError), and that they are properly +// translated to generic conditions. + +#include <windows.h> +#include <system_error> +#include <cassert> + +#include "test_macros.h" + +int main(int, char**) { + LIBCPP_ASSERT(std::error_code(ERROR_ACCESS_DENIED, std::system_category()) == std::errc::permission_denied); + LIBCPP_ASSERT(std::error_code(ERROR_PATH_NOT_FOUND, std::system_category()) == std::errc::no_such_file_or_directory); + return 0; +} diff --git a/libcxx/test/std/atomics/atomics.ref/exchange.pass.cpp b/libcxx/test/std/atomics/atomics.ref/exchange.pass.cpp index cd998d4..c2afa6b 100644 --- a/libcxx/test/std/atomics/atomics.ref/exchange.pass.cpp +++ b/libcxx/test/std/atomics/atomics.ref/exchange.pass.cpp @@ -17,24 +17,47 @@ #include <type_traits> #include "atomic_helpers.h" +#include "test_helper.h" #include "test_macros.h" template <typename T> struct TestExchange { void operator()() const { - T x(T(1)); - std::atomic_ref<T> const a(x); + { + T x(T(1)); + std::atomic_ref<T> const a(x); + + { + std::same_as<T> decltype(auto) y = a.exchange(T(2)); + assert(y == T(1)); + ASSERT_NOEXCEPT(a.exchange(T(2))); + } + + { + std::same_as<T> decltype(auto) y = a.exchange(T(3), std::memory_order_seq_cst); + assert(y == T(2)); + ASSERT_NOEXCEPT(a.exchange(T(3), std::memory_order_seq_cst)); + } + } + // memory_order::release { - std::same_as<T> decltype(auto) y = a.exchange(T(2)); - assert(y == T(1)); - ASSERT_NOEXCEPT(a.exchange(T(2))); + auto exchange = [](std::atomic_ref<T> const& x, T, T new_val) { + x.exchange(new_val, std::memory_order::release); + }; + auto load = [](std::atomic_ref<T> const& x) { return x.load(std::memory_order::acquire); }; + test_acquire_release<T>(exchange, load); } + // memory_order::seq_cst { - std::same_as<T> decltype(auto) y = a.exchange(T(3), std::memory_order_seq_cst); - assert(y == T(2)); - ASSERT_NOEXCEPT(a.exchange(T(3), std::memory_order_seq_cst)); + auto exchange_no_arg = [](std::atomic_ref<T> const& x, T, T new_val) { x.exchange(new_val); }; + auto exchange_with_order = [](std::atomic_ref<T> const& x, T, T new_val) { + x.exchange(new_val, std::memory_order::seq_cst); + }; + auto load = [](std::atomic_ref<T> const& x) { return x.load(); }; + test_seq_cst<T>(exchange_no_arg, load); + test_seq_cst<T>(exchange_with_order, load); } } }; diff --git a/libcxx/test/std/containers/sequences/vector.bool/at.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/at.pass.cpp new file mode 100644 index 0000000..16832dd --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector.bool/at.pass.cpp @@ -0,0 +1,125 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// <vector> + +// reference at(size_type n); // constexpr since C++20 + +#include <cassert> +#include <memory> +#include <vector> + +#include "min_allocator.h" +#include "test_allocator.h" +#include "test_macros.h" + +#ifndef TEST_HAS_NO_EXCEPTIONS +# include <stdexcept> +#endif + +template <typename Allocator> +TEST_CONSTEXPR_CXX20 void test() { + using C = std::vector<bool, Allocator>; + using reference = typename C::reference; + bool a[] = {1, 0, 1, 0, 1}; + C v(a, a + sizeof(a) / sizeof(a[0])); + ASSERT_SAME_TYPE(reference, decltype(v.at(0))); + assert(v.at(0) == true); + assert(v.at(1) == false); + assert(v.at(2) == true); + assert(v.at(3) == false); + assert(v.at(4) == true); + v.at(1) = 1; + assert(v.at(1) == true); + v.at(3) = 1; + assert(v.at(3) == true); +} + +template <typename Allocator> +void test_exception() { +#ifndef TEST_HAS_NO_EXCEPTIONS + { + bool a[] = {1, 0, 1, 1}; + using C = std::vector<bool, Allocator>; + C v(a, a + sizeof(a) / sizeof(a[0])); + + try { + TEST_IGNORE_NODISCARD v.at(4); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + + try { + TEST_IGNORE_NODISCARD v.at(5); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + + try { + TEST_IGNORE_NODISCARD v.at(6); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + + try { + using size_type = typename C::size_type; + TEST_IGNORE_NODISCARD v.at(static_cast<size_type>(-1)); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } + + { + std::vector<bool, Allocator> v; + try { + TEST_IGNORE_NODISCARD v.at(0); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } +#endif +} + +TEST_CONSTEXPR_CXX20 bool tests() { + test<std::allocator<bool> >(); + test<min_allocator<bool> >(); + test<test_allocator<bool> >(); + return true; +} + +void test_exceptions() { + test_exception<std::allocator<bool> >(); + test_exception<min_allocator<bool> >(); + test_exception<test_allocator<bool> >(); +} + +int main(int, char**) { + tests(); + test_exceptions(); + +#if TEST_STD_VER >= 20 + static_assert(tests()); +#endif + + return 0; +} diff --git a/libcxx/test/std/containers/sequences/vector.bool/at_const.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/at_const.pass.cpp new file mode 100644 index 0000000..5ed794d --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector.bool/at_const.pass.cpp @@ -0,0 +1,121 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// <vector> + +// const_reference at(size_type n) const; // constexpr since C++20 + +#include <cassert> +#include <memory> +#include <vector> + +#include "min_allocator.h" +#include "test_allocator.h" +#include "test_macros.h" + +#ifndef TEST_HAS_NO_EXCEPTIONS +# include <stdexcept> +#endif + +template <typename Allocator> +TEST_CONSTEXPR_CXX20 void test() { + using C = const std::vector<bool, Allocator>; + using const_reference = typename C::const_reference; + bool a[] = {1, 0, 1, 0, 1}; + C v(a, a + sizeof(a) / sizeof(a[0])); + ASSERT_SAME_TYPE(const_reference, decltype(v.at(0))); + assert(v.at(0) == true); + assert(v.at(1) == false); + assert(v.at(2) == true); + assert(v.at(3) == false); + assert(v.at(4) == true); +} + +template <typename Allocator> +void test_exception() { +#ifndef TEST_HAS_NO_EXCEPTIONS + { + bool a[] = {1, 0, 1, 1}; + using C = const std::vector<bool, Allocator>; + C v(a, a + sizeof(a) / sizeof(a[0])); + + try { + TEST_IGNORE_NODISCARD v.at(4); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + + try { + TEST_IGNORE_NODISCARD v.at(5); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + + try { + TEST_IGNORE_NODISCARD v.at(6); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + + try { + using size_type = typename C::size_type; + TEST_IGNORE_NODISCARD v.at(static_cast<size_type>(-1)); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } + + { + std::vector<bool, Allocator> v; + try { + TEST_IGNORE_NODISCARD v.at(0); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } +#endif +} + +TEST_CONSTEXPR_CXX20 bool tests() { + test<std::allocator<bool> >(); + test<min_allocator<bool> >(); + test<test_allocator<bool> >(); + return true; +} + +void test_exceptions() { + test_exception<std::allocator<bool> >(); + test_exception<min_allocator<bool> >(); + test_exception<test_allocator<bool> >(); +} + +int main(int, char**) { + tests(); + test_exceptions(); + +#if TEST_STD_VER >= 20 + static_assert(tests()); +#endif + + return 0; +} diff --git a/libcxx/test/std/diagnostics/syserr/syserr.compare/eq_error_code_error_code.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.compare/eq_error_code_error_code.pass.cpp index f1f4973..a8b565b 100644 --- a/libcxx/test/std/diagnostics/syserr/syserr.compare/eq_error_code_error_code.pass.cpp +++ b/libcxx/test/std/diagnostics/syserr/syserr.compare/eq_error_code_error_code.pass.cpp @@ -22,6 +22,10 @@ #include "test_macros.h" +#ifndef _WIN32 +# define TEST_SYSTEM_CATEGORY_IS_GENERIC_CATEGORY +#endif + int main(int, char**) { std::error_code e_code1(5, std::generic_category()); std::error_code e_code2(5, std::system_category()); @@ -45,7 +49,9 @@ int main(int, char**) { assert(e_code2 == e_code2); assert(e_code2 != e_code3); assert(e_code2 != e_code4); +#ifdef TEST_SYSTEM_CATEGORY_IS_GENERIC_CATEGORY LIBCPP_ASSERT(e_code2 == e_condition1); +#endif assert(e_code2 == e_condition2); LIBCPP_ASSERT(e_code2 != e_condition3); assert(e_code2 != e_condition4); @@ -65,11 +71,15 @@ int main(int, char**) { assert(e_code4 == e_code4); LIBCPP_ASSERT(e_code4 != e_condition1); assert(e_code4 != e_condition2); +#ifdef TEST_SYSTEM_CATEGORY_IS_GENERIC_CATEGORY LIBCPP_ASSERT(e_code4 == e_condition3); +#endif assert(e_code4 == e_condition4); assert(e_condition1 == e_code1); +#ifdef TEST_SYSTEM_CATEGORY_IS_GENERIC_CATEGORY LIBCPP_ASSERT(e_condition1 == e_code2); +#endif assert(e_condition1 != e_code3); LIBCPP_ASSERT(e_condition1 != e_code4); assert(e_condition1 == e_condition1); @@ -89,7 +99,9 @@ int main(int, char**) { assert(e_condition3 != e_code1); LIBCPP_ASSERT(e_condition3 != e_code2); assert(e_condition3 == e_code3); +#ifdef TEST_SYSTEM_CATEGORY_IS_GENERIC_CATEGORY LIBCPP_ASSERT(e_condition3 == e_code4); +#endif assert(e_condition3 != e_condition1); assert(e_condition3 != e_condition2); assert(e_condition3 == e_condition3); diff --git a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.derived/message.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.derived/message.pass.cpp index 9f7eb42..f7f4313 100644 --- a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.derived/message.pass.cpp +++ b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.derived/message.pass.cpp @@ -29,8 +29,11 @@ int main(int, char**) { assert(!m1.empty()); assert(!m2.empty()); assert(!m3.empty()); +#ifndef _WIN32 + // On windows, system_category is distinct. LIBCPP_ASSERT(m1 == m2); - assert(m1 != m3); +#endif + assert(m2 != m3); return 0; } diff --git a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp index 6ba33ba..255cbe7 100644 --- a/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp +++ b/libcxx/test/std/diagnostics/syserr/syserr.errcat/syserr.errcat.objects/system_category.pass.cpp @@ -33,7 +33,12 @@ int main(int, char**) { { const std::error_category& e_cat1 = std::system_category(); std::error_condition e_cond = e_cat1.default_error_condition(5); +#ifdef _WIN32 + // Windows' system error 5 is ERROR_ACCESS_DENIED, which maps to generic code permission_denied. + LIBCPP_ASSERT(e_cond.value() == static_cast<int>(std::errc::permission_denied)); +#else LIBCPP_ASSERT(e_cond.value() == 5); +#endif LIBCPP_ASSERT(e_cond.category() == std::generic_category()); assert(e_cat1.equivalent(5, e_cond)); diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp index 303a95a..071ee7f 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/file_type_obs.pass.cpp @@ -172,8 +172,13 @@ static void test_with_ec_dne() { file_status st = status(p, status_ec); file_status sym_st = symlink_status(p, sym_status_ec); std::error_code ec = GetTestEC(2); - auto CheckEC = [&](std::error_code const& other_ec) { - bool res = ec == other_ec; + auto CheckEC = [&](std::error_code const& other_ec) { + // Note: we're comparing equality of the _canonicalized_ error_condition + // here (unlike in other tests where we expect exactly the same + // error_code). This is because directory_entry can construct its own + // generic_category error when a file doesn't exist, instead of passing + // through an underlying system_category error. + bool res = ec.default_error_condition() == other_ec.default_error_condition(); ec = GetTestEC(2); return res; }; diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/status.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/status.pass.cpp index dd72232..dec04df 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/status.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/status.pass.cpp @@ -44,7 +44,7 @@ static void test_basic() { file_status es = e.status(eec); assert(ps.type() == es.type()); assert(ps.permissions() == es.permissions()); - assert(pec == eec); + assert(pec.default_error_condition() == eec.default_error_condition()); } for (const auto& p : TestCases) { const directory_entry e(p); diff --git a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp index 24e8069..77da936 100644 --- a/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp +++ b/libcxx/test/std/input.output/filesystems/class.directory_entry/directory_entry.obs/symlink_status.pass.cpp @@ -44,7 +44,7 @@ static void test_signature() { file_status es = e.symlink_status(eec); assert(ps.type() == es.type()); assert(ps.permissions() == es.permissions()); - assert(pec == eec); + assert(pec.default_error_condition() == eec.default_error_condition()); } for (const auto& p : TestCases) { const directory_entry e(p); diff --git a/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_procfs.pass.cpp b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_procfs.pass.cpp new file mode 100644 index 0000000..29bc8e4 --- /dev/null +++ b/libcxx/test/std/input.output/filesystems/fs.op.funcs/fs.op.copy_file/copy_file_procfs.pass.cpp @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 +// REQUIRES: linux +// UNSUPPORTED: no-filesystem +// XFAIL: no-localization +// UNSUPPORTED: availability-filesystem-missing + +// <filesystem> + +// bool copy_file(const path& from, const path& to); +// bool copy_file(const path& from, const path& to, error_code& ec) noexcept; +// bool copy_file(const path& from, const path& to, copy_options options); +// bool copy_file(const path& from, const path& to, copy_options options, +// error_code& ec) noexcept; + +#include <cassert> +#include <filesystem> +#include <system_error> + +#include "test_macros.h" +#include "filesystem_test_helper.h" + +namespace fs = std::filesystem; + +// Linux has various virtual filesystems such as /proc and /sys +// where files may have no length (st_size == 0), but still contain data. +// This is because the to-be-read data is usually generated ad-hoc by the reading syscall +// These files can not be copied with kernel-side copies like copy_file_range or sendfile, +// and must instead be copied via a traditional userspace read + write loop. +int main(int, char** argv) { + const fs::path procfile{"/proc/self/comm"}; + assert(file_size(procfile) == 0); + + scoped_test_env env; + std::error_code ec = GetTestEC(); + + const fs::path dest = env.make_env_path("dest"); + + assert(copy_file(procfile, dest, ec)); + assert(!ec); + + // /proc/self/comm contains the filename of the executable, plus a null terminator + assert(file_size(dest) == fs::path(argv[0]).filename().string().size() + 1); + + return 0; +} diff --git a/libcxx/test/support/filesystem_test_helper.h b/libcxx/test/support/filesystem_test_helper.h index a63d645..2ad9efb 100644 --- a/libcxx/test/support/filesystem_test_helper.h +++ b/libcxx/test/support/filesystem_test_helper.h @@ -583,7 +583,11 @@ struct ExceptionChecker { assert(ErrorIsImp(Err.code(), {expected_err})); assert(Err.path1() == expected_path1); assert(Err.path2() == expected_path2); +#ifndef _WIN32 + // On Windows, the error strings are windows error code strings, and don't + // match textually with the strings generated for generic std::errc::*. LIBCPP_ONLY(check_libcxx_string(Err)); +#endif } void check_libcxx_string(fs::filesystem_error const& Err) { diff --git a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt index 05c44e4..0f8f0e88 100644 --- a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt +++ b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt @@ -92,6 +92,7 @@ set(SOURCES header_exportable_declarations.cpp hide_from_abi.cpp internal_ftm_use.cpp + nodebug_on_aliases.cpp proper_version_checks.cpp qualify_declval.cpp robust_against_adl.cpp diff --git a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp index 54beed5..bc7c8ce 100644 --- a/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp +++ b/libcxx/test/tools/clang_tidy_checks/libcpp_module.cpp @@ -13,6 +13,7 @@ #include "header_exportable_declarations.hpp" #include "hide_from_abi.hpp" #include "internal_ftm_use.hpp" +#include "nodebug_on_aliases.hpp" #include "proper_version_checks.hpp" #include "qualify_declval.hpp" #include "robust_against_adl.hpp" @@ -26,6 +27,7 @@ public: check_factories.registerCheck<libcpp::header_exportable_declarations>("libcpp-header-exportable-declarations"); check_factories.registerCheck<libcpp::hide_from_abi>("libcpp-hide-from-abi"); check_factories.registerCheck<libcpp::internal_ftm_use>("libcpp-internal-ftms"); + check_factories.registerCheck<libcpp::nodebug_on_aliases>("libcpp-nodebug-on-aliases"); check_factories.registerCheck<libcpp::proper_version_checks>("libcpp-cpp-version-check"); check_factories.registerCheck<libcpp::robust_against_adl_check>("libcpp-robust-against-adl"); check_factories.registerCheck<libcpp::uglify_attributes>("libcpp-uglify-attributes"); diff --git a/libcxx/test/tools/clang_tidy_checks/nodebug_on_aliases.cpp b/libcxx/test/tools/clang_tidy_checks/nodebug_on_aliases.cpp new file mode 100644 index 0000000..9b96269 --- /dev/null +++ b/libcxx/test/tools/clang_tidy_checks/nodebug_on_aliases.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang-tidy/ClangTidyCheck.h" + +#include "nodebug_on_aliases.hpp" +#include "utilities.hpp" + +namespace libcpp { +namespace { +AST_MATCHER(clang::NamedDecl, isPretty) { return !is_ugly_name(Node.getName()); } +} // namespace + +nodebug_on_aliases::nodebug_on_aliases(llvm::StringRef name, clang::tidy::ClangTidyContext* context) + : clang::tidy::ClangTidyCheck(name, context) {} + +void nodebug_on_aliases::registerMatchers(clang::ast_matchers::MatchFinder* finder) { + using namespace clang::ast_matchers; + finder->addMatcher( + typeAliasDecl(unless(anyOf(isPretty(), hasAttr(clang::attr::NoDebug), hasAncestor(functionDecl())))) + .bind("nodebug_on_internal_aliases"), + this); +} + +void nodebug_on_aliases::check(const clang::ast_matchers::MatchFinder::MatchResult& result) { + if (const auto* alias = result.Nodes.getNodeAs<clang::TypeAliasDecl>("nodebug_on_internal_aliases")) { + diag(alias->getBeginLoc(), "Internal aliases should always be marked _LIBCPP_NODEBUG"); + } +} +} // namespace libcpp diff --git a/libcxx/test/tools/clang_tidy_checks/nodebug_on_aliases.hpp b/libcxx/test/tools/clang_tidy_checks/nodebug_on_aliases.hpp new file mode 100644 index 0000000..1097e89 --- /dev/null +++ b/libcxx/test/tools/clang_tidy_checks/nodebug_on_aliases.hpp @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang-tidy/ClangTidyCheck.h" + +namespace libcpp { +class nodebug_on_aliases : public clang::tidy::ClangTidyCheck { +public: + nodebug_on_aliases(llvm::StringRef, clang::tidy::ClangTidyContext*); + void registerMatchers(clang::ast_matchers::MatchFinder*) override; + void check(const clang::ast_matchers::MatchFinder::MatchResult&) override; +}; +} // namespace libcpp diff --git a/libcxx/test/tools/clang_tidy_checks/uglify_attributes.cpp b/libcxx/test/tools/clang_tidy_checks/uglify_attributes.cpp index 7812b23..24bacde 100644 --- a/libcxx/test/tools/clang_tidy_checks/uglify_attributes.cpp +++ b/libcxx/test/tools/clang_tidy_checks/uglify_attributes.cpp @@ -10,20 +10,11 @@ #include "clang-tidy/ClangTidyModuleRegistry.h" #include "uglify_attributes.hpp" +#include "utilities.hpp" -#include <algorithm> -#include <array> -#include <span> -#include <string_view> +#include <optional> namespace { -bool isUgly(std::string_view str) { - if (str.size() < 2) - return false; - if (str[0] == '_' && str[1] >= 'A' && str[1] <= 'Z') - return true; - return str.find("__") != std::string_view::npos; -} // Starting with Clang 17 ToT C++23 support is provided by CPlusPlus23 instead // of C++23 support is provided by CPlusPlus2b. To allow a smooth transition for @@ -77,17 +68,15 @@ AST_MATCHER(clang::Attr, isPretty) { if (Node.isKeywordAttribute() || !Node.getAttrName()) return false; if (Node.isCXX11Attribute() && !Node.hasScope()) { - if (isUgly(Node.getAttrName()->getName())) + if (is_ugly_name(Node.getAttrName()->getName())) return false; return !llvm::is_contained( get_standard_attributes(Finder->getASTContext().getLangOpts()), Node.getAttrName()->getName()); } if (Node.hasScope()) - if (!isUgly(Node.getScopeName()->getName())) + if (!is_ugly_name(Node.getScopeName()->getName())) return true; - return !isUgly(Node.getAttrName()->getName()); - - return false; + return !is_ugly_name(Node.getAttrName()->getName()); } std::optional<std::string> getUglyfiedCXX11Attr(const clang::Attr& attr) { diff --git a/libcxx/test/tools/clang_tidy_checks/utilities.hpp b/libcxx/test/tools/clang_tidy_checks/utilities.hpp new file mode 100644 index 0000000..b780efe --- /dev/null +++ b/libcxx/test/tools/clang_tidy_checks/utilities.hpp @@ -0,0 +1,22 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LIBCXX_TEST_TOOLS_CLANG_TIDY_CHECKS_UTILITIES_HPP +#define LIBCXX_TEST_TOOLS_CLANG_TIDY_CHECKS_UTILITIES_HPP + +#include <string_view> + +inline bool is_ugly_name(std::string_view str) { + if (str.size() < 2) + return false; + if (str[0] == '_' && str[1] >= 'A' && str[1] <= 'Z') + return true; + return str.find("__") != std::string_view::npos; +} + +#endif // LIBCXX_TEST_TOOLS_CLANG_TIDY_CHECKS_UTILITIES_HPP |