Revert "[libc++][modules] Rewrite the modulemap to have fewer top-level modules (#107638)" (#110384)
This reverts 3 commits:45a09d181124bc3244d4bc6bd3bc1eThe 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:
@@ -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 "")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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__)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
193
libcxx/include/__std_clang_module
Normal file
193
libcxx/include/__std_clang_module
Normal 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>
|
||||
@@ -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
@@ -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;
|
||||
|
||||
"""
|
||||
)
|
||||
""")
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
63
libcxx/utils/generate_std_clang_module_header.py
Normal file
63
libcxx/utils/generate_std_clang_module_header.py
Normal 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")
|
||||
@@ -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",
|
||||
|
||||
Reference in New Issue
Block a user