Revert "[libc++][modules] Rewrite the modulemap to have fewer top-level modules (#107638)" (#110384)

This reverts 3 commits:
45a09d1811
24bc3244d4
bc6bd3bc1e

The GitHub pre-merge CI has been broken since this PR went in. This
change reverts it to see if I can get the pre-merge CI working again.
This commit is contained in:
Chris B
2024-09-28 21:47:09 -05:00
committed by GitHub
parent bf9ab0b7c3
commit f11abac652
21 changed files with 2395 additions and 2816 deletions

View File

@@ -1,2 +1,2 @@
set(LIBCXX_HARDENING_MODE "fast" CACHE STRING "")
set(LIBCXX_ABI_DEFINES "_LIBCPP_ABI_BOUNDED_ITERATORS;_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING;_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR;_LIBCPP_ABI_BOUNDED_UNIQUE_PTR" CACHE STRING "")
set(LIBCXX_ABI_DEFINES "_LIBCPP_ABI_BOUNDED_ITERATORS;_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING;_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR" CACHE STRING "")

View File

@@ -23,6 +23,7 @@ set(files
__algorithm/find_if.h
__algorithm/find_if_not.h
__algorithm/find_segment_if.h
__algorithm/fold.h
__algorithm/for_each.h
__algorithm/for_each_n.h
__algorithm/for_each_segment.h
@@ -97,7 +98,6 @@ set(files
__algorithm/ranges_find_if.h
__algorithm/ranges_find_if_not.h
__algorithm/ranges_find_last.h
__algorithm/ranges_fold.h
__algorithm/ranges_for_each.h
__algorithm/ranges_for_each_n.h
__algorithm/ranges_generate.h
@@ -536,7 +536,6 @@ set(files
__memory/allocator_arg_t.h
__memory/allocator_destructor.h
__memory/allocator_traits.h
__memory/array_cookie.h
__memory/assume_aligned.h
__memory/auto_ptr.h
__memory/builtin_new_allocator.h
@@ -688,6 +687,7 @@ set(files
__ranges/views.h
__ranges/zip_view.h
__split_buffer
__std_clang_module
__std_mbstate_t.h
__stop_token/atomic_unique_lock.h
__stop_token/intrusive_list_view.h

View File

@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
#ifndef _LIBCPP___ALGORITHM_RANGES_FOLD_H
#define _LIBCPP___ALGORITHM_RANGES_FOLD_H
#ifndef _LIBCPP___ALGORITHM_FOLD_H
#define _LIBCPP___ALGORITHM_FOLD_H
#include <__concepts/assignable.h>
#include <__concepts/constructible.h>
@@ -126,4 +126,4 @@ _LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
#endif // _LIBCPP___ALGORITHM_RANGES_FOLD_H
#endif // _LIBCPP___ALGORITHM_FOLD_H

View File

@@ -181,13 +181,6 @@
# define _LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING
#endif
// Tracks the bounds of the array owned by std::unique_ptr<T[]>, allowing it to trap when accessed out-of-bounds.
// Note that limited bounds checking is also available outside of this ABI configuration, but only some categories
// of types can be checked.
//
// ABI impact: This causes the layout of std::unique_ptr<T[]> to change and its size to increase.
// #define _LIBCPP_ABI_BOUNDED_UNIQUE_PTR
#if defined(_LIBCPP_COMPILER_CLANG_BASED)
# if defined(__APPLE__)
# if defined(__i386__) || defined(__x86_64__)

View File

@@ -27,7 +27,6 @@
#include <__type_traits/make_unsigned.h>
#include <__utility/unreachable.h>
#include <array>
#include <cstdint>
#include <limits>
#include <string>
#include <string_view>

View File

@@ -1,55 +0,0 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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 _LIBCPP___MEMORY_ARRAY_COOKIE_H
#define _LIBCPP___MEMORY_ARRAY_COOKIE_H
#include <__config>
#include <__configuration/abi.h>
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_trivially_destructible.h>
#include <__type_traits/negation.h>
#include <cstddef>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
_LIBCPP_BEGIN_NAMESPACE_STD
// Trait representing whether a type requires an array cookie at the start of its allocation when
// allocated as `new T[n]` and deallocated as `delete array`.
//
// Under the Itanium C++ ABI [1], we know that an array cookie is available unless `T` is trivially
// destructible and the call to `operator delete[]` is not a sized operator delete. Under ABIs other
// than the Itanium ABI, we assume there are no array cookies.
//
// [1]: https://itanium-cxx-abi.github.io/cxx-abi/abi.html#array-cookies
#ifdef _LIBCPP_ABI_ITANIUM
// TODO: Use a builtin instead
// TODO: We should factor in the choice of the usual deallocation function in this determination.
template <class _Tp>
struct __has_array_cookie : _Not<is_trivially_destructible<_Tp> > {};
#else
template <class _Tp>
struct __has_array_cookie : false_type {};
#endif
template <class _Tp>
// Avoid failures when -fsanitize-address-poison-custom-array-cookie is enabled
_LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_SANITIZE("address") size_t __get_array_cookie(_Tp const* __ptr) {
static_assert(
__has_array_cookie<_Tp>::value, "Trying to access the array cookie of a type that is not guaranteed to have one");
size_t const* __cookie = reinterpret_cast<size_t const*>(__ptr) - 1; // TODO: Use a builtin instead
return *__cookie;
}
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___MEMORY_ARRAY_COOKIE_H

View File

@@ -10,7 +10,6 @@
#ifndef _LIBCPP___MEMORY_UNIQUE_PTR_H
#define _LIBCPP___MEMORY_UNIQUE_PTR_H
#include <__assert>
#include <__compare/compare_three_way.h>
#include <__compare/compare_three_way_result.h>
#include <__compare/three_way_comparable.h>
@@ -18,10 +17,8 @@
#include <__functional/hash.h>
#include <__functional/operations.h>
#include <__memory/allocator_traits.h> // __pointer
#include <__memory/array_cookie.h>
#include <__memory/auto_ptr.h>
#include <__memory/compressed_pair.h>
#include <__memory/pointer_traits.h>
#include <__type_traits/add_lvalue_reference.h>
#include <__type_traits/common_type.h>
#include <__type_traits/conditional.h>
@@ -30,7 +27,6 @@
#include <__type_traits/integral_constant.h>
#include <__type_traits/is_array.h>
#include <__type_traits/is_assignable.h>
#include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_constructible.h>
#include <__type_traits/is_convertible.h>
#include <__type_traits/is_function.h>
@@ -45,9 +41,7 @@
#include <__utility/declval.h>
#include <__utility/forward.h>
#include <__utility/move.h>
#include <__utility/private_constructor_tag.h>
#include <cstddef>
#include <cstdint>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -298,91 +292,6 @@ public:
}
};
// Bounds checking in unique_ptr<T[]>
// ==================================
//
// We provide some helper classes that allow bounds checking when accessing a unique_ptr<T[]>.
// There are a few cases where bounds checking can be implemented:
//
// 1. When an array cookie (see [1]) exists at the beginning of the array allocation, we are
// able to reuse that cookie to extract the size of the array and perform bounds checking.
// An array cookie is a size inserted at the beginning of the allocation by the compiler.
// That size is inserted implicitly when doing `new T[n]` in some cases, and its purpose
// is to allow the runtime to destroy the `n` array elements when doing `delete array`.
// When we are able to use array cookies, we reuse information already available in the
// current runtime, so bounds checking does not require changing libc++'s ABI.
//
// 2. When the "bounded unique_ptr" ABI configuration (controlled by `_LIBCPP_ABI_BOUNDED_UNIQUE_PTR`)
// is enabled, we store the size of the allocation (when it is known) so we can check it when
// indexing into the `unique_ptr`. That changes the layout of `std::unique_ptr<T[]>`, which is
// an ABI break from the default configuration.
//
// Note that even under this ABI configuration, we can't always know the size of the unique_ptr.
// Indeed, the size of the allocation can only be known when the unique_ptr is created via
// make_unique or a similar API. For example, it can't be known when constructed from an arbitrary
// pointer, in which case we are not able to check the bounds on access:
//
// unique_ptr<T[], MyDeleter> ptr(new T[3]);
//
// When we don't know the size of the allocation via the API used to create the unique_ptr, we
// try to fall back to using an array cookie when available.
//
// Finally, note that when this ABI configuration is enabled, we have no choice but to always
// make space for a size to be stored in the unique_ptr. Indeed, while we might want to avoid
// storing the size when an array cookie is available, knowing whether an array cookie is available
// requires the type stored in the unique_ptr to be complete, while unique_ptr can normally
// accommodate incomplete types.
//
// (1) Implementation where we rely on the array cookie to know the size of the allocation, if
// an array cookie exists.
struct __unique_ptr_array_bounds_stateless {
__unique_ptr_array_bounds_stateless() = default;
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __unique_ptr_array_bounds_stateless(size_t) {}
template <class _Tp, __enable_if_t<__has_array_cookie<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp* __ptr, size_t __index) const {
// In constant expressions, we can't check the array cookie so we just pretend that the index
// is in-bounds. The compiler catches invalid accesses anyway.
if (__libcpp_is_constant_evaluated())
return true;
size_t __cookie = std::__get_array_cookie(__ptr);
return __index < __cookie;
}
template <class _Tp, __enable_if_t<!__has_array_cookie<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp*, size_t) const {
return true; // If we don't have an array cookie, we assume the access is in-bounds
}
};
// (2) Implementation where we store the size in the class whenever we have it.
//
// Semantically, we'd need to store the size as an optional<size_t>. However, since that
// is really heavy weight, we instead store a size_t and use SIZE_MAX as a magic value
// meaning that we don't know the size.
struct __unique_ptr_array_bounds_stored {
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __unique_ptr_array_bounds_stored() : __size_(SIZE_MAX) {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __unique_ptr_array_bounds_stored(size_t __size) : __size_(__size) {}
// Use the array cookie if there's one
template <class _Tp, __enable_if_t<__has_array_cookie<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp* __ptr, size_t __index) const {
if (__libcpp_is_constant_evaluated())
return true;
size_t __cookie = std::__get_array_cookie(__ptr);
return __index < __cookie;
}
// Otherwise, fall back on the stored size (if any)
template <class _Tp, __enable_if_t<!__has_array_cookie<_Tp>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __in_bounds(_Tp*, size_t __index) const {
return __index < __size_;
}
private:
size_t __size_;
};
template <class _Tp, class _Dp>
class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> {
public:
@@ -391,9 +300,8 @@ public:
typedef typename __pointer<_Tp, deleter_type>::type pointer;
// A unique_ptr contains the following members which may be trivially relocatable:
// - pointer: this may be trivially relocatable, so it's checked
// - pointer : this may be trivially relocatable, so it's checked
// - deleter_type: this may be trivially relocatable, so it's checked
// - (optionally) size: this is trivially relocatable
//
// This unique_ptr implementation only contains a pointer to the unique object and a deleter, so there are no
// references to itself. This means that the entire structure is trivially relocatable if its members are.
@@ -403,16 +311,7 @@ public:
void>;
private:
template <class _Up, class _OtherDeleter>
friend class unique_ptr;
_LIBCPP_COMPRESSED_PAIR(pointer, __ptr_, deleter_type, __deleter_);
#ifdef _LIBCPP_ABI_BOUNDED_UNIQUE_PTR
using _BoundsChecker = __unique_ptr_array_bounds_stored;
#else
using _BoundsChecker = __unique_ptr_array_bounds_stateless;
#endif
_LIBCPP_NO_UNIQUE_ADDRESS _BoundsChecker __checker_;
template <class _From>
struct _CheckArrayPointerConversion : is_same<_From, pointer> {};
@@ -474,12 +373,6 @@ public:
: __ptr_(__p),
__deleter_() {}
// Private constructor used by make_unique & friends to pass the size that was allocated
template <class _Tag, class _Ptr, __enable_if_t<is_same<_Tag, __private_constructor_tag>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Tag, _Ptr __ptr, size_t __size) _NOEXCEPT
: __ptr_(__ptr),
__checker_(__size) {}
template <class _Pp,
bool _Dummy = true,
class = _EnableIfDeleterConstructible<_LValRefType<_Dummy> >,
@@ -518,13 +411,11 @@ public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT
: __ptr_(__u.release()),
__deleter_(std::forward<deleter_type>(__u.get_deleter())),
__checker_(std::move(__u.__checker_)) {}
__deleter_(std::forward<deleter_type>(__u.get_deleter())) {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT {
reset(__u.release());
__deleter_ = std::forward<deleter_type>(__u.get_deleter());
__checker_ = std::move(std::move(__u.__checker_));
return *this;
}
@@ -534,8 +425,7 @@ public:
class = _EnableIfDeleterConvertible<_Ep> >
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT
: __ptr_(__u.release()),
__deleter_(std::forward<_Ep>(__u.get_deleter())),
__checker_(std::move(__u.__checker_)) {}
__deleter_(std::forward<_Ep>(__u.get_deleter())) {}
template <class _Up,
class _Ep,
@@ -544,7 +434,6 @@ public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT {
reset(__u.release());
__deleter_ = std::forward<_Ep>(__u.get_deleter());
__checker_ = std::move(__u.__checker_);
return *this;
}
@@ -562,8 +451,6 @@ public:
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t<_Tp> operator[](size_t __i) const {
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__checker_.__in_bounds(std::__to_address(__ptr_), __i),
"unique_ptr<T[]>::operator[](index): index out of range");
return __ptr_[__i];
}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_; }
@@ -580,8 +467,6 @@ public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer release() _NOEXCEPT {
pointer __t = __ptr_;
__ptr_ = pointer();
// The deleter and the optional bounds-checker are left unchanged. The bounds-checker
// will be reinitialized appropriately when/if the unique_ptr gets assigned-to or reset.
return __t;
}
@@ -589,7 +474,6 @@ public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset(_Pp __p) _NOEXCEPT {
pointer __tmp = __ptr_;
__ptr_ = __p;
__checker_ = _BoundsChecker();
if (__tmp)
__deleter_(__tmp);
}
@@ -597,7 +481,6 @@ public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset(nullptr_t = nullptr) _NOEXCEPT {
pointer __tmp = __ptr_;
__ptr_ = nullptr;
__checker_ = _BoundsChecker();
if (__tmp)
__deleter_(__tmp);
}
@@ -606,7 +489,6 @@ public:
using std::swap;
swap(__ptr_, __u.__ptr_);
swap(__deleter_, __u.__deleter_);
swap(__checker_, __u.__checker_);
}
};
@@ -763,7 +645,7 @@ template <class _Tp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_array_unknown_bound
make_unique(size_t __n) {
typedef __remove_extent_t<_Tp> _Up;
return unique_ptr<_Tp>(__private_constructor_tag(), new _Up[__n](), __n);
return unique_ptr<_Tp>(new _Up[__n]());
}
template <class _Tp, class... _Args>
@@ -782,7 +664,7 @@ make_unique_for_overwrite() {
template <class _Tp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX23 typename __unique_if<_Tp>::__unique_array_unknown_bound
make_unique_for_overwrite(size_t __n) {
return unique_ptr<_Tp>(__private_constructor_tag(), new __remove_extent_t<_Tp>[__n], __n);
return unique_ptr<_Tp>(new __remove_extent_t<_Tp>[__n]);
}
template <class _Tp, class... _Args>

View File

@@ -0,0 +1,193 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// WARNING, this entire header is generated by
// utils/generate_std_clang_module_header.py
// DO NOT MODIFY!
// This header should not be directly included, it's exclusively to import all
// of the libc++ public clang modules for the `std` clang module to export. In
// other words, it's to facilitate `@import std;` in Objective-C++ and `import std`
// in Swift to expose all of the libc++ interfaces. This is generally not
// recommended, however there are some clients that need to import all of libc++
// without knowing what "all" is.
#if !__building_module(std)
# error "Do not include this header directly, include individual headers instead"
#endif
#include <__config>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
#include <algorithm>
#include <any>
#include <array>
#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
# include <atomic>
#endif
#include <barrier>
#include <bit>
#include <bitset>
#include <cassert>
#include <ccomplex>
#include <cctype>
#include <cerrno>
#include <cfenv>
#include <cfloat>
#include <charconv>
#include <chrono>
#include <cinttypes>
#include <ciso646>
#include <climits>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <clocale>
#endif
#include <cmath>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <codecvt>
#endif
#include <compare>
#include <complex.h>
#include <complex>
#include <concepts>
#include <condition_variable>
#include <coroutine>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstdbool>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctgmath>
#include <ctime>
#include <ctype.h>
#include <cuchar>
#include <cwchar>
#include <cwctype>
#include <deque>
#include <errno.h>
#include <exception>
#include <execution>
#include <expected>
#include <experimental/iterator>
#include <experimental/memory>
#include <experimental/propagate_const>
#include <experimental/simd>
#include <experimental/type_traits>
#include <experimental/utility>
#include <fenv.h>
#include <filesystem>
#include <float.h>
#include <format>
#include <forward_list>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <fstream>
#endif
#include <functional>
#include <future>
#include <initializer_list>
#include <inttypes.h>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <iomanip>
#endif
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <ios>
#endif
#include <iosfwd>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <iostream>
#endif
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <istream>
#endif
#include <iterator>
#include <latch>
#include <limits>
#include <list>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <locale.h>
#endif
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <locale>
#endif
#include <map>
#include <math.h>
#include <mdspan>
#include <memory>
#include <memory_resource>
#include <mutex>
#include <new>
#include <numbers>
#include <numeric>
#include <optional>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <ostream>
#endif
#include <print>
#include <queue>
#include <random>
#include <ranges>
#include <ratio>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <regex>
#endif
#include <scoped_allocator>
#include <semaphore>
#include <set>
#include <shared_mutex>
#include <source_location>
#include <span>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <sstream>
#endif
#include <stack>
#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
# include <stdatomic.h>
#endif
#include <stdbool.h>
#include <stddef.h>
#include <stdexcept>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stop_token>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <streambuf>
#endif
#include <string.h>
#include <string>
#include <string_view>
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <strstream>
#endif
#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
# include <syncstream>
#endif
#include <system_error>
#include <tgmath.h>
#include <thread>
#include <tuple>
#include <type_traits>
#include <typeindex>
#include <typeinfo>
#include <uchar.h>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <valarray>
#include <variant>
#include <vector>
#include <version>
#include <wchar.h>
#include <wctype.h>

View File

@@ -2020,10 +2020,10 @@ template <class BidirectionalIterator, class Compare>
#endif
#if _LIBCPP_STD_VER >= 23
# include <__algorithm/fold.h>
# include <__algorithm/ranges_contains_subrange.h>
# include <__algorithm/ranges_ends_with.h>
# include <__algorithm/ranges_find_last.h>
# include <__algorithm/ranges_fold.h>
# include <__algorithm/ranges_starts_with.h>
#endif // _LIBCPP_STD_VER >= 23

File diff suppressed because it is too large Load Diff

View File

@@ -37,17 +37,13 @@ for header in public_headers:
// TODO: Investigate this failure
// UNSUPPORTED: LIBCXX-FREEBSD-FIXME
// TODO: Investigate why this doesn't work on Picolibc once the locale base API is refactored
// UNSUPPORTED: LIBCXX-PICOLIBC-FIXME
{lit_header_restrictions.get(header, '')}
#include <{header}>
""")
print(
f"""\
//--- import_std.compile.pass.mm
print(f"""\
//--- __std_clang_module.compile.pass.mm
// RUN: %{{cxx}} %s %{{flags}} %{{compile_flags}} -fmodules -fcxx-modules -fmodules-cache-path=%t -fsyntax-only
// REQUIRES: clang-modules-build
@@ -65,10 +61,6 @@ print(
// TODO: Investigate this failure
// UNSUPPORTED: LIBCXX-FREEBSD-FIXME
// TODO: Investigate why this doesn't work on Picolibc once the locale base API is refactored
// UNSUPPORTED: LIBCXX-PICOLIBC-FIXME
@import std;
"""
)
""")

View File

@@ -8,10 +8,6 @@
// UNSUPPORTED: libcpp-has-abi-fix-unordered-container-size-type, libcpp-abi-no-compressed-pair-padding
// std::unique_ptr is used as an implementation detail of the unordered containers, so the layout of
// unordered containers changes when bounded unique_ptr is enabled.
// UNSUPPORTED: libcpp-has-abi-bounded-unique_ptr
#include <cstdint>
#include <unordered_map>

View File

@@ -8,10 +8,6 @@
// UNSUPPORTED: libcpp-has-abi-fix-unordered-container-size-type, libcpp-abi-no-compressed-pair-padding
// std::unique_ptr is used as an implementation detail of the unordered containers, so the layout of
// unordered containers changes when bounded unique_ptr is enabled.
// UNSUPPORTED: libcpp-has-abi-bounded-unique_ptr
#include <cstdint>
#include <unordered_set>

View File

@@ -0,0 +1,23 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <experimental/utility>
#include <experimental/utility>
#include "test_macros.h"
#ifndef _LIBCPP_UTILITY
# error "<experimental/utility> must include <utility>"
#endif
int main(int, char**)
{
return 0;
}

View File

@@ -1,93 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <memory>
// unique_ptr
// Make sure that we can form unique_ptrs to incomplete types and perform restricted
// operations on them. This requires setting up a TU where the type is complete and
// the unique_ptr is created and destroyed, and a TU where the type is incomplete and
// we check that a restricted set of operations can be performed on the unique_ptr.
// RUN: %{cxx} %s %{flags} %{compile_flags} -c -o %t.tu1.o -DCOMPLETE
// RUN: %{cxx} %s %{flags} %{compile_flags} -c -o %t.tu2.o -DINCOMPLETE
// RUN: %{cxx} %t.tu1.o %t.tu2.o %{flags} %{link_flags} -o %t.exe
// RUN: %{exec} %t.exe
#include <memory>
#include <cassert>
struct T;
extern void use(std::unique_ptr<T>& ptr);
extern void use(std::unique_ptr<T[]>& ptr);
#ifdef INCOMPLETE
void use(std::unique_ptr<T>& ptr) {
{
T* x = ptr.get();
assert(x != nullptr);
}
{
T& ref = *ptr;
assert(&ref == ptr.get());
}
{
bool engaged = static_cast<bool>(ptr);
assert(engaged);
}
{
assert(ptr == ptr);
assert(!(ptr != ptr));
assert(!(ptr < ptr));
assert(!(ptr > ptr));
assert(ptr <= ptr);
assert(ptr >= ptr);
}
}
void use(std::unique_ptr<T[]>& ptr) {
{
T* x = ptr.get();
assert(x != nullptr);
}
{
bool engaged = static_cast<bool>(ptr);
assert(engaged);
}
{
assert(ptr == ptr);
assert(!(ptr != ptr));
assert(!(ptr < ptr));
assert(!(ptr > ptr));
assert(ptr <= ptr);
assert(ptr >= ptr);
}
}
#endif // INCOMPLETE
#ifdef COMPLETE
struct T {}; // complete the type
int main(int, char**) {
{
std::unique_ptr<T> ptr(new T());
use(ptr);
}
{
std::unique_ptr<T[]> ptr(new T[3]());
use(ptr);
}
return 0;
}
#endif // COMPLETE

View File

@@ -1,166 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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: has-unix-headers
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-hardening-mode=none
// XFAIL: libcpp-hardening-mode=debug && availability-verbose_abort-missing
// <memory>
//
// unique_ptr<T[]>
//
// T& operator[](std::size_t);
// This test ensures that we catch an out-of-bounds access in std::unique_ptr<T[]>::operator[]
// when unique_ptr has the appropriate ABI configuration.
#include <memory>
#include <cstddef>
#include <string>
#include "check_assertion.h"
#include "type_algorithms.h"
struct MyDeleter {
MyDeleter() = default;
// required to exercise converting move-constructor
template <class T>
MyDeleter(std::default_delete<T> const&) {}
// required to exercise converting move-assignment
template <class T>
MyDeleter& operator=(std::default_delete<T> const&) {
return *this;
}
template <class T>
void operator()(T* ptr) const {
delete[] ptr;
}
};
template <class WithCookie, class NoCookie>
void test() {
// For types with an array cookie, we can always detect OOB accesses.
{
// Check with the default deleter
{
{
std::unique_ptr<WithCookie[]> ptr(new WithCookie[5]);
TEST_LIBCPP_ASSERT_FAILURE(ptr[6], "unique_ptr<T[]>::operator[](index): index out of range");
}
{
std::unique_ptr<WithCookie[]> ptr = std::make_unique<WithCookie[]>(5);
TEST_LIBCPP_ASSERT_FAILURE(ptr[6], "unique_ptr<T[]>::operator[](index): index out of range");
}
#if TEST_STD_VER >= 20
{
std::unique_ptr<WithCookie[]> ptr = std::make_unique_for_overwrite<WithCookie[]>(5);
TEST_LIBCPP_ASSERT_FAILURE(ptr[6] = WithCookie(), "unique_ptr<T[]>::operator[](index): index out of range");
}
#endif
}
// Check with a custom deleter
{
std::unique_ptr<WithCookie[], MyDeleter> ptr(new WithCookie[5]);
TEST_LIBCPP_ASSERT_FAILURE(ptr[6], "unique_ptr<T[]>::operator[](index): index out of range");
}
}
// For types that don't have an array cookie, things are a bit more complicated. We can detect OOB accesses
// only when the unique_ptr is created via an API where the size is passed down to the library so that we
// can store it inside the unique_ptr. That requires the appropriate ABI configuration to be enabled.
//
// Note that APIs that allow the size to be passed down to the library only support the default deleter
// as of writing this test.
#if defined(_LIBCPP_ABI_BOUNDED_UNIQUE_PTR)
{
{
std::unique_ptr<NoCookie[]> ptr = std::make_unique<NoCookie[]>(5);
TEST_LIBCPP_ASSERT_FAILURE(ptr[6], "unique_ptr<T[]>::operator[](index): index out of range");
}
# if TEST_STD_VER >= 20
{
std::unique_ptr<NoCookie[]> ptr = std::make_unique_for_overwrite<NoCookie[]>(5);
TEST_LIBCPP_ASSERT_FAILURE(ptr[6] = NoCookie(), "unique_ptr<T[]>::operator[](index): index out of range");
}
# endif
}
#endif
// Make sure that we carry the bounds information properly through conversions, assignments, etc.
// These tests are mostly relevant when the ABI setting is enabled (with a stateful bounds-checker),
// but we still run them for types with an array cookie either way.
#if defined(_LIBCPP_ABI_BOUNDED_UNIQUE_PTR)
using Types = types::type_list<NoCookie, WithCookie>;
#else
using Types = types::type_list<WithCookie>;
#endif
types::for_each(Types(), []<class T> {
// Bounds carried through move construction
{
std::unique_ptr<T[]> ptr = std::make_unique<T[]>(5);
std::unique_ptr<T[]> other(std::move(ptr));
TEST_LIBCPP_ASSERT_FAILURE(other[6], "unique_ptr<T[]>::operator[](index): index out of range");
}
// Bounds carried through move assignment
{
std::unique_ptr<T[]> ptr = std::make_unique<T[]>(5);
std::unique_ptr<T[]> other;
other = std::move(ptr);
TEST_LIBCPP_ASSERT_FAILURE(other[6], "unique_ptr<T[]>::operator[](index): index out of range");
}
// Bounds carried through converting move-constructor
{
std::unique_ptr<T[]> ptr = std::make_unique<T[]>(5);
std::unique_ptr<T[], MyDeleter> other(std::move(ptr));
TEST_LIBCPP_ASSERT_FAILURE(other[6], "unique_ptr<T[]>::operator[](index): index out of range");
}
// Bounds carried through converting move-assignment
{
std::unique_ptr<T[]> ptr = std::make_unique<T[]>(5);
std::unique_ptr<T[], MyDeleter> other;
other = std::move(ptr);
TEST_LIBCPP_ASSERT_FAILURE(other[6], "unique_ptr<T[]>::operator[](index): index out of range");
}
});
}
template <std::size_t Size>
struct NoCookie {
char padding[Size];
};
template <std::size_t Size>
struct WithCookie {
WithCookie() = default;
WithCookie(WithCookie const&) {}
WithCookie& operator=(WithCookie const&) { return *this; }
~WithCookie() {}
char padding[Size];
};
int main(int, char**) {
test<WithCookie<1>, NoCookie<1>>();
test<WithCookie<2>, NoCookie<2>>();
test<WithCookie<3>, NoCookie<3>>();
test<WithCookie<4>, NoCookie<4>>();
test<WithCookie<8>, NoCookie<8>>();
test<WithCookie<16>, NoCookie<16>>();
test<WithCookie<32>, NoCookie<32>>();
test<WithCookie<256>, NoCookie<256>>();
test<std::string, int>();
return 0;
}

View File

@@ -10,114 +10,43 @@
// unique_ptr
// pointer unique_ptr<T>::get() const noexcept;
// pointer unique_ptr<T[]>::get() const noexcept;
// test get
#include <memory>
#include <cassert>
#include <cstddef>
#include "test_macros.h"
#include "unique_ptr_test_helper.h"
template <class T>
template <bool IsArray>
TEST_CONSTEXPR_CXX23 void test_basic() {
// non-const element type
typedef typename std::conditional<IsArray, int[], int>::type VT;
typedef const VT CVT;
{
// non-const access
{
T* x = new T;
std::unique_ptr<T> ptr(x);
ASSERT_SAME_TYPE(decltype(ptr.get()), T*);
ASSERT_NOEXCEPT(ptr.get());
assert(ptr.get() == x);
}
// const access
{
T* x = new T;
std::unique_ptr<T> const ptr(x);
ASSERT_SAME_TYPE(decltype(ptr.get()), T*);
ASSERT_NOEXCEPT(ptr.get());
assert(ptr.get() == x);
}
typedef std::unique_ptr<VT> U;
int* p = newValue<VT>(1);
U s(p);
U const& sc = s;
ASSERT_SAME_TYPE(decltype(s.get()), int*);
ASSERT_SAME_TYPE(decltype(sc.get()), int*);
assert(s.get() == p);
assert(sc.get() == s.get());
}
// const element type
{
// non-const access
{
T* x = new T;
std::unique_ptr<T const> ptr(x);
ASSERT_SAME_TYPE(decltype(ptr.get()), T const*);
assert(ptr.get() == x);
}
// const access
{
T* x = new T;
std::unique_ptr<T const> const ptr(x);
ASSERT_SAME_TYPE(decltype(ptr.get()), T const*);
assert(ptr.get() == x);
}
}
// Same thing but for unique_ptr<T[]>
// non-const element type
{
// non-const access
{
T* x = new T[3];
std::unique_ptr<T[]> ptr(x);
ASSERT_SAME_TYPE(decltype(ptr.get()), T*);
ASSERT_NOEXCEPT(ptr.get());
assert(ptr.get() == x);
}
// const access
{
T* x = new T[3];
std::unique_ptr<T[]> const ptr(x);
ASSERT_SAME_TYPE(decltype(ptr.get()), T*);
ASSERT_NOEXCEPT(ptr.get());
assert(ptr.get() == x);
}
}
// const element type
{
// non-const access
{
T* x = new T[3];
std::unique_ptr<T const[]> ptr(x);
ASSERT_SAME_TYPE(decltype(ptr.get()), T const*);
assert(ptr.get() == x);
}
// const access
{
T* x = new T[3];
std::unique_ptr<T const[]> const ptr(x);
ASSERT_SAME_TYPE(decltype(ptr.get()), T const*);
assert(ptr.get() == x);
}
typedef std::unique_ptr<CVT> U;
const int* p = newValue<VT>(1);
U s(p);
U const& sc = s;
ASSERT_SAME_TYPE(decltype(s.get()), const int*);
ASSERT_SAME_TYPE(decltype(sc.get()), const int*);
assert(s.get() == p);
assert(sc.get() == s.get());
}
}
template <std::size_t Size>
struct WithSize {
char padding[Size];
};
TEST_CONSTEXPR_CXX23 bool test() {
test_basic<char>();
test_basic<int>();
test_basic<WithSize<1> >();
test_basic<WithSize<2> >();
test_basic<WithSize<3> >();
test_basic<WithSize<4> >();
test_basic<WithSize<8> >();
test_basic<WithSize<16> >();
test_basic<WithSize<256> >();
test_basic</*IsArray*/ false>();
test_basic<true>();
return true;
}

View File

@@ -10,117 +10,51 @@
// unique_ptr
// T& unique_ptr::operator[](size_t) const
// test op[](size_t)
#include <memory>
#include <cassert>
// TODO: Move TEST_IS_CONSTANT_EVALUATED into its own header
#include <type_traits>
#include <array>
#include "test_macros.h"
#include "type_algorithms.h"
static int next = 0;
struct EnumeratedDefaultCtor {
EnumeratedDefaultCtor() : value(0) { value = ++next; }
int value;
};
class A {
int state_;
static int next_;
template <std::size_t Size>
struct WithTrivialDtor {
std::array<char, Size> padding = {'x'};
TEST_CONSTEXPR_CXX23 friend bool operator==(WithTrivialDtor const& x, WithTrivialDtor const& y) {
return x.padding == y.padding;
public:
TEST_CONSTEXPR_CXX23 A() : state_(0) {
if (!TEST_IS_CONSTANT_EVALUATED)
state_ = ++next_;
}
TEST_CONSTEXPR_CXX23 int get() const { return state_; }
friend TEST_CONSTEXPR_CXX23 bool operator==(const A& x, int y) { return x.state_ == y; }
TEST_CONSTEXPR_CXX23 A& operator=(int i) {
state_ = i;
return *this;
}
};
template <std::size_t Size>
struct WithNonTrivialDtor {
std::array<char, Size> padding = {'x'};
TEST_CONSTEXPR_CXX23 friend bool operator==(WithNonTrivialDtor const& x, WithNonTrivialDtor const& y) {
return x.padding == y.padding;
}
TEST_CONSTEXPR_CXX23 ~WithNonTrivialDtor() {}
};
template <class T>
struct CustomDeleter : std::default_delete<T> {};
int A::next_ = 0;
TEST_CONSTEXPR_CXX23 bool test() {
// Basic test
{
std::unique_ptr<int[]> p(new int[3]);
{
int& result = p[0];
result = 0;
}
{
int& result = p[1];
result = 1;
}
{
int& result = p[2];
result = 2;
}
assert(p[0] == 0);
assert(p[1] == 1);
assert(p[2] == 2);
std::unique_ptr<A[]> p(new A[3]);
if (!TEST_IS_CONSTANT_EVALUATED) {
assert(p[0] == 1);
assert(p[1] == 2);
assert(p[2] == 3);
}
// Ensure that the order of access is correct after initializing a unique_ptr but
// before actually modifying any of its elements. The implementation would have to
// really try for this not to be the case, but we still check it.
//
// This requires assigning known values to the elements when they are first constructed,
// which requires global state.
{
if (!TEST_IS_CONSTANT_EVALUATED) {
std::unique_ptr<EnumeratedDefaultCtor[]> p(new EnumeratedDefaultCtor[3]);
assert(p[0].value == 1);
assert(p[1].value == 2);
assert(p[2].value == 3);
}
}
// Make sure operator[] is const-qualified
{
std::unique_ptr<int[]> const p(new int[3]);
p[0] = 42;
assert(p[0] == 42);
}
// Make sure we properly handle types with trivial and non-trivial destructors of different
// sizes. This is relevant because some implementations may want to use properties of the
// ABI like array cookies and these properties often depend on e.g. the triviality of T's
// destructor, T's size and so on.
#if TEST_STD_VER >= 20 // this test is too painful to write before C++20
{
using TrickyCookieTypes = types::type_list<
WithTrivialDtor<1>,
WithTrivialDtor<2>,
WithTrivialDtor<3>,
WithTrivialDtor<4>,
WithTrivialDtor<8>,
WithTrivialDtor<16>,
WithTrivialDtor<256>,
WithNonTrivialDtor<1>,
WithNonTrivialDtor<2>,
WithNonTrivialDtor<3>,
WithNonTrivialDtor<4>,
WithNonTrivialDtor<8>,
WithNonTrivialDtor<16>,
WithNonTrivialDtor<256>>;
types::for_each(TrickyCookieTypes(), []<class T> {
types::for_each(types::type_list<std::default_delete<T[]>, CustomDeleter<T[]>>(), []<class Deleter> {
std::unique_ptr<T[], Deleter> p(new T[3]);
assert(p[0] == T());
assert(p[1] == T());
assert(p[2] == T());
});
});
}
#endif // C++20
p[0] = 3;
p[1] = 2;
p[2] = 1;
assert(p[0] == 3);
assert(p[1] == 2);
assert(p[2] == 1);
return true;
}

View File

@@ -2,6 +2,10 @@ add_custom_target(libcxx-generate-feature-test-macros
COMMAND "${Python3_EXECUTABLE}" "${LIBCXX_SOURCE_DIR}/utils/generate_feature_test_macro_components.py"
COMMENT "Generate the <version> header and tests for feature test macros.")
add_custom_target(libcxx-generate-std-clang-module-header
COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/generate_std_clang_module_header.py"
COMMENT "Generate the <__std_clang_module> header")
add_custom_target(libcxx-generate-std-cppm-in-file
COMMAND
"${Python3_EXECUTABLE}"
@@ -53,6 +57,7 @@ add_custom_target(libcxx-indic-conjunct-break-table
add_custom_target(libcxx-generate-files
DEPENDS libcxx-generate-feature-test-macros
libcxx-generate-std-clang-module-header
libcxx-generate-std-cppm-in-file
libcxx-generate-std-compat-cppm-in-file
libcxx-generate-extended-grapheme-cluster-tables

View File

@@ -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
#
# ===----------------------------------------------------------------------===##
import os.path
import libcxx.header_information
header_restrictions = libcxx.header_information.header_restrictions
libcxx_include_directory = os.path.join(
os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "include"
)
with open(
os.path.join(libcxx_include_directory, "__std_clang_module"), "w"
) as std_clang_module_header:
std_clang_module_header.write(
"""\
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// WARNING, this entire header is generated by
// utils/generate_std_clang_module_header.py
// DO NOT MODIFY!
// This header should not be directly included, it's exclusively to import all
// of the libc++ public clang modules for the `std` clang module to export. In
// other words, it's to facilitate `@import std;` in Objective-C++ and `import std`
// in Swift to expose all of the libc++ interfaces. This is generally not
// recommended, however there are some clients that need to import all of libc++
// without knowing what "all" is.
#if !__building_module(std)
# error "Do not include this header directly, include individual headers instead"
#endif
#include <__config>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
"""
)
# Include the angle brackets in sorting so that <a.h> sorts before <a>
# like check-format wants.
for include, header in sorted([(f"<{header}>", header) for header in libcxx.header_information.public_headers]):
header_restriction = header_restrictions.get(header)
if header_restriction:
std_clang_module_header.write(f"#if {header_restriction}\n")
std_clang_module_header.write(f"# include {include}\n")
std_clang_module_header.write(f"#endif\n")
else:
std_clang_module_header.write(f"#include {include}\n")

View File

@@ -374,7 +374,6 @@ macros = {
"_LIBCPP_ABI_BOUNDED_ITERATORS": "libcpp-has-abi-bounded-iterators",
"_LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING": "libcpp-has-abi-bounded-iterators-in-string",
"_LIBCPP_ABI_BOUNDED_ITERATORS_IN_VECTOR": "libcpp-has-abi-bounded-iterators-in-vector",
"_LIBCPP_ABI_BOUNDED_UNIQUE_PTR": "libcpp-has-abi-bounded-unique_ptr",
"_LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE": "libcpp-has-abi-fix-unordered-container-size-type",
"_LIBCPP_DEPRECATED_ABI_DISABLE_PAIR_TRIVIAL_COPY_CTOR": "libcpp-deprecated-abi-disable-pair-trivial-copy-ctor",
"_LIBCPP_ABI_NO_COMPRESSED_PAIR_PADDING": "libcpp-abi-no-compressed-pair-padding",