diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index bf25b34ba9159..9b57b7c8eeb52 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -408,6 +408,8 @@ Status ---------------------------------------------------------- ----------------- **C++26** ---------------------------------------------------------------------------- + ``__cpp_lib_aligned_accessor`` ``202411L`` + ---------------------------------------------------------- ----------------- ``__cpp_lib_associative_heterogeneous_insertion`` *unimplemented* ---------------------------------------------------------- ----------------- ``__cpp_lib_atomic_min_max`` *unimplemented* @@ -456,6 +458,8 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_inplace_vector`` *unimplemented* ---------------------------------------------------------- ----------------- + ``__cpp_lib_is_sufficiently_aligned`` ``202411L`` + ---------------------------------------------------------- ----------------- ``__cpp_lib_is_virtual_base_of`` ``202406L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_is_within_lifetime`` *unimplemented* diff --git a/libcxx/docs/ReleaseNotes/21.rst b/libcxx/docs/ReleaseNotes/21.rst index a8f20ed0abaf0..4f5de6393bf00 100644 --- a/libcxx/docs/ReleaseNotes/21.rst +++ b/libcxx/docs/ReleaseNotes/21.rst @@ -45,6 +45,7 @@ Implemented Papers - P2562R1: ``constexpr`` Stable Sorting (`Github `__) - P0472R3: Put std::monostate in (`Github `__) - P1222R4: A Standard ``flat_set`` (`Github `__) +- P2897R7: ``aligned_accessor``: An mdspan accessor expressing pointer over-alignment (`Github `__) - P3247R2: Deprecate the notion of trivial types (`Github `__) Improvements and New Features diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index b40d9eb58c24e..63e19f097e301 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -80,7 +80,7 @@ "`P3138R5 `__","``views::cache_latest``","2024-11 (Wrocław)","","","" "`P3379R0 `__","Constrain ``std::expected`` equality operators","2024-11 (Wrocław)","","","" "`P2862R1 `__","``text_encoding::name()`` should never return null values","2024-11 (Wrocław)","","","" -"`P2897R7 `__","``aligned_accessor``: An ``mdspan`` accessor expressing pointer over-alignment","2024-11 (Wrocław)","","","" +"`P2897R7 `__","``aligned_accessor``: An ``mdspan`` accessor expressing pointer over-alignment","2024-11 (Wrocław)","|Complete|","21","" "`P3355R1 `__","Fix ``submdspan`` for C++26","2024-11 (Wrocław)","","","" "`P3222R0 `__","Fix C++26 by adding transposed special cases for P2642 layouts","2024-11 (Wrocław)","","","" "`P3050R2 `__","Fix C++26 by optimizing ``linalg::conjugated`` for noncomplex value types","2024-11 (Wrocław)","","","" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index c225131101ce2..4431582cc33ca 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -545,6 +545,7 @@ set(files __math/traits.h __math/trigonometric_functions.h __mbstate_t.h + __mdspan/aligned_accessor.h __mdspan/default_accessor.h __mdspan/extents.h __mdspan/layout_left.h @@ -569,6 +570,7 @@ set(files __memory/destroy.h __memory/destruct_n.h __memory/inout_ptr.h + __memory/is_sufficiently_aligned.h __memory/noexcept_move_assign_container.h __memory/out_ptr.h __memory/pointer_traits.h diff --git a/libcxx/include/__mdspan/aligned_accessor.h b/libcxx/include/__mdspan/aligned_accessor.h new file mode 100644 index 0000000000000..2b8d4c52d8737 --- /dev/null +++ b/libcxx/include/__mdspan/aligned_accessor.h @@ -0,0 +1,87 @@ +// -*- 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 +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H +#define _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H + +#include <__config> +#include <__cstddef/size_t.h> +#include <__mdspan/default_accessor.h> +#include <__memory/assume_aligned.h> +#include <__type_traits/is_abstract.h> +#include <__type_traits/is_array.h> +#include <__type_traits/is_convertible.h> +#include <__type_traits/remove_const.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 26 + +template +struct aligned_accessor { + static_assert(_ByteAlignment != 0 && (_ByteAlignment & (_ByteAlignment - 1)) == 0, + "aligned_accessor: byte alignment must be a power of two"); + static_assert(_ByteAlignment >= alignof(_ElementType), "aligned_accessor: insufficient byte alignment"); + static_assert(!is_array_v<_ElementType>, "aligned_accessor: template argument may not be an array type"); + static_assert(!is_abstract_v<_ElementType>, "aligned_accessor: template argument may not be an abstract class"); + + using offset_policy = default_accessor<_ElementType>; + using element_type = _ElementType; + using reference = _ElementType&; + using data_handle_type = _ElementType*; + + static constexpr size_t byte_alignment = _ByteAlignment; + + _LIBCPP_HIDE_FROM_ABI constexpr aligned_accessor() noexcept = default; + + template + requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]> && _OtherByteAlignment >= byte_alignment) + _LIBCPP_HIDE_FROM_ABI constexpr aligned_accessor(aligned_accessor<_OtherElementType, _OtherByteAlignment>) noexcept {} + + template + requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]>) + _LIBCPP_HIDE_FROM_ABI explicit constexpr aligned_accessor(default_accessor<_OtherElementType>) noexcept {} + + template + requires(is_convertible_v) + _LIBCPP_HIDE_FROM_ABI constexpr operator default_accessor<_OtherElementType>() const noexcept { + return {}; + } + + _LIBCPP_HIDE_FROM_ABI constexpr reference access(data_handle_type __p, size_t __i) const noexcept { + return std::assume_aligned(__p)[__i]; + } + + _LIBCPP_HIDE_FROM_ABI constexpr typename offset_policy::data_handle_type + offset(data_handle_type __p, size_t __i) const noexcept { + return std::assume_aligned(__p) + __i; + } +}; + +#endif // _LIBCPP_STD_VER >= 26 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___MDSPAN_ALIGNED_ACCESSOR_H diff --git a/libcxx/include/__mdspan/mdspan.h b/libcxx/include/__mdspan/mdspan.h index 59ab9aca582c7..c0f27678197ce 100644 --- a/libcxx/include/__mdspan/mdspan.h +++ b/libcxx/include/__mdspan/mdspan.h @@ -20,6 +20,7 @@ #include <__assert> #include <__config> #include <__fwd/mdspan.h> +#include <__mdspan/aligned_accessor.h> #include <__mdspan/default_accessor.h> #include <__mdspan/extents.h> #include <__memory/addressof.h> @@ -267,13 +268,13 @@ class mdspan { # if _LIBCPP_STD_VER >= 26 template requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0)) -explicit mdspan(_ElementType*, - _OtherIndexTypes...) -> mdspan<_ElementType, extents...>>; +explicit mdspan(_ElementType*, _OtherIndexTypes...) + -> mdspan<_ElementType, extents...>>; # else template requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0)) -explicit mdspan(_ElementType*, - _OtherIndexTypes...) -> mdspan<_ElementType, dextents>; +explicit mdspan(_ElementType*, _OtherIndexTypes...) + -> mdspan<_ElementType, dextents>; # endif template diff --git a/libcxx/include/__memory/is_sufficiently_aligned.h b/libcxx/include/__memory/is_sufficiently_aligned.h new file mode 100644 index 0000000000000..4280920cabb4b --- /dev/null +++ b/libcxx/include/__memory/is_sufficiently_aligned.h @@ -0,0 +1,34 @@ +// -*- 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_IS_SUFFICIENTLY_ALIGNED_H +#define _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H + +#include <__config> +#include <__cstddef/size_t.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER >= 26 + +template +_LIBCPP_HIDE_FROM_ABI bool is_sufficiently_aligned(_Tp* __ptr) { + return reinterpret_cast(__ptr) % _Alignment == 0; +} + +#endif // _LIBCPP_STD_VER >= 26 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H diff --git a/libcxx/include/mdspan b/libcxx/include/mdspan index 2c7ef4f733f74..43982e0f339b8 100644 --- a/libcxx/include/mdspan +++ b/libcxx/include/mdspan @@ -33,10 +33,14 @@ namespace std { template class default_accessor; + // [mdspan.accessor.aligned], class template aligned_accessor + template + class aligned_accessor; // since C++26 + // [mdspan.mdspan], class template mdspan template> - class mdspan; // not implemented yet + class mdspan; } // extents synopsis @@ -269,6 +273,38 @@ namespace std { }; } +// aligned_accessor synopsis + +namespace std { + template + struct aligned_accessor { + using offset_policy = default_accessor; + using element_type = ElementType; + using reference = ElementType&; + using data_handle_type = ElementType*; + + static constexpr size_t byte_alignment = ByteAlignment; + + constexpr aligned_accessor() noexcept = default; + + template + constexpr aligned_accessor( + aligned_accessor) noexcept; + + template + explicit constexpr aligned_accessor( + default_accessor) noexcept; + + template + constexpr operator default_accessor() const noexcept; + + constexpr reference access(data_handle_type p, size_t i) const noexcept; + + constexpr typename offset_policy::data_handle_type + offset(data_handle_type p, size_t i) const noexcept; + }; +} + // mdspan synopsis namespace std { diff --git a/libcxx/include/memory b/libcxx/include/memory index 6661bc4f43756..ca880c83a544d 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -912,6 +912,9 @@ void* align(size_t alignment, size_t size, void*& ptr, size_t& space); template [[nodiscard]] constexpr T* assume_aligned(T* ptr); // since C++20 +template + bool is_sufficiently_aligned(T* ptr); // since C++26 + // [out.ptr.t], class template out_ptr_t template class out_ptr_t; // since c++23 @@ -945,6 +948,7 @@ template # include <__memory/allocator_traits.h> # include <__memory/auto_ptr.h> # include <__memory/inout_ptr.h> +# include <__memory/is_sufficiently_aligned.h> # include <__memory/out_ptr.h> # include <__memory/pointer_traits.h> # include <__memory/raw_storage_iterator.h> diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 65123eb268150..353d9651093ef 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -1593,6 +1593,7 @@ module std [system] { } module mdspan { + module aligned_accessor { header "__mdspan/aligned_accessor.h" } module default_accessor { header "__mdspan/default_accessor.h" } module extents { header "__mdspan/extents.h" } module fwd { header "__fwd/mdspan.h" } @@ -1631,6 +1632,7 @@ module std [system] { module destruct_n { header "__memory/destruct_n.h" } module fwd { header "__fwd/memory.h" } module inout_ptr { header "__memory/inout_ptr.h" } + module is_sufficiently_aligned { header "__memory/is_sufficiently_aligned.h" } module noexcept_move_assign_container { header "__memory/noexcept_move_assign_container.h" } module out_ptr { header "__memory/out_ptr.h" } module pointer_traits { header "__memory/pointer_traits.h" } diff --git a/libcxx/include/version b/libcxx/include/version index 0a19ff9ad8187..77d97b93adc6c 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -16,6 +16,7 @@ Macro name Value Headers __cpp_lib_adaptor_iterator_pair_constructor 202106L __cpp_lib_addressof_constexpr 201603L +__cpp_lib_aligned_accessor 202411L __cpp_lib_allocate_at_least 202302L __cpp_lib_allocator_traits_is_always_equal 201411L @@ -148,6 +149,7 @@ __cpp_lib_is_nothrow_convertible 201806L __cpp_lib_is_null_pointer 201309L __cpp_lib_is_pointer_interconvertible 201907L __cpp_lib_is_scoped_enum 202011L +__cpp_lib_is_sufficiently_aligned 202411L __cpp_lib_is_swappable 201603L __cpp_lib_is_virtual_base_of 202406L __cpp_lib_is_within_lifetime 202306L @@ -532,6 +534,7 @@ __cpp_lib_void_t 201411L #endif #if _LIBCPP_STD_VER >= 26 +# define __cpp_lib_aligned_accessor 202411L // # define __cpp_lib_associative_heterogeneous_insertion 202306L // # define __cpp_lib_atomic_min_max 202403L # undef __cpp_lib_bind_front @@ -562,6 +565,7 @@ __cpp_lib_void_t 201411L // # define __cpp_lib_generate_random 202403L // # define __cpp_lib_hazard_pointer 202306L // # define __cpp_lib_inplace_vector 202406L +# define __cpp_lib_is_sufficiently_aligned 202411L # if __has_builtin(__builtin_is_virtual_base_of) # define __cpp_lib_is_virtual_base_of 202406L # endif diff --git a/libcxx/modules/std/mdspan.inc b/libcxx/modules/std/mdspan.inc index 5e65993383cdc..c8cc78badb7d5 100644 --- a/libcxx/modules/std/mdspan.inc +++ b/libcxx/modules/std/mdspan.inc @@ -28,6 +28,11 @@ export namespace std { // [mdspan.accessor.default], class template default_accessor using std::default_accessor; +# if _LIBCPP_STD_VER >= 26 + // [mdspan.accessor.aligned], class template aligned_accessor + using std::aligned_accessor; +# endif // _LIBCPP_STD_VER >= 26 + // [mdspan.mdspan], class template mdspan using std::mdspan; #endif // _LIBCPP_STD_VER >= 23 diff --git a/libcxx/modules/std/memory.inc b/libcxx/modules/std/memory.inc index 82056e426d06c..c25e9e3443e9c 100644 --- a/libcxx/modules/std/memory.inc +++ b/libcxx/modules/std/memory.inc @@ -17,6 +17,9 @@ export namespace std { // [ptr.align], pointer alignment using std::align; using std::assume_aligned; +#if _LIBCPP_STD_VER >= 26 + using std::is_sufficiently_aligned; +#endif // [obj.lifetime], explicit lifetime management // using std::start_lifetime_as; diff --git a/libcxx/test/libcxx/containers/views/mdspan/aligned_accessor/byte_alignment.verify.cpp b/libcxx/test/libcxx/containers/views/mdspan/aligned_accessor/byte_alignment.verify.cpp new file mode 100644 index 0000000000000..fbc8386a72ded --- /dev/null +++ b/libcxx/test/libcxx/containers/views/mdspan/aligned_accessor/byte_alignment.verify.cpp @@ -0,0 +1,29 @@ +// +// 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, c++17, c++20, c++23 + +// + +// template +// class aligned_accessor; + +// ByteAlignement is required to be a power of two and greater or equal to alignof(ElementType). + +#include + +void not_power_of_two() { + // expected-error-re@*:* {{static assertion failed {{.*}}aligned_accessor: byte alignment must be a power of two}} + [[maybe_unused]] std::aligned_accessor acc; +} + +struct alignas(8) S {}; + +void insufficiently_aligned() { + // expected-error-re@*:* {{static assertion failed {{.*}}aligned_accessor: insufficient byte alignment}} + [[maybe_unused]] std::aligned_accessor acc; +} diff --git a/libcxx/test/libcxx/containers/views/mdspan/aligned_accessor/element_type.verify.cpp b/libcxx/test/libcxx/containers/views/mdspan/aligned_accessor/element_type.verify.cpp new file mode 100644 index 0000000000000..91510a99aeec9 --- /dev/null +++ b/libcxx/test/libcxx/containers/views/mdspan/aligned_accessor/element_type.verify.cpp @@ -0,0 +1,32 @@ +// +// 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, c++17, c++20, c++23 + +// + +// template +// class aligned_accessor; + +// ElementType is required to be a complete object type that is neither an abstract class type nor an array type. + +#include + +class AbstractClass { +public: + virtual void method() = 0; +}; + +void not_abstract_class() { + // expected-error-re@*:* {{static assertion failed {{.*}}aligned_accessor: template argument may not be an abstract class}} + [[maybe_unused]] std::aligned_accessor acc; +} + +void not_array_type() { + // expected-error-re@*:* {{static assertion failed {{.*}}aligned_accessor: template argument may not be an array type}} + [[maybe_unused]] std::aligned_accessor acc; +} diff --git a/libcxx/test/std/containers/views/mdspan/aligned_accessor/access.pass.cpp b/libcxx/test/std/containers/views/mdspan/aligned_accessor/access.pass.cpp new file mode 100644 index 0000000000000..deca1226e47ca --- /dev/null +++ b/libcxx/test/std/containers/views/mdspan/aligned_accessor/access.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++17, c++20, c++23 + +// + +// constexpr reference access(data_handle_type p, size_t i) const noexcept; +// +// Effects: Equivalent to: return assume_aligned(p)[i]; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// We are not using MinimalElementType.h because MinimalElementType is not +// default consructible and uninitialized storage does not work in constexpr. + +// Same as MinimalElementType but with a defaulted default constructor +struct MyMinimalElementType { + int val; + constexpr MyMinimalElementType() = default; + constexpr MyMinimalElementType(const MyMinimalElementType&) = delete; + constexpr explicit MyMinimalElementType(int v) noexcept : val(v) {} + constexpr MyMinimalElementType& operator=(const MyMinimalElementType&) = delete; +}; + +template +constexpr void test_access() { + constexpr std::size_t Sz = 10; + alignas(N) T data[Sz]{}; + T* ptr = &data[0]; + std::aligned_accessor acc; + for (std::size_t i = 0; i < Sz; ++i) { + std::same_as::reference> decltype(auto) x = acc.access(ptr, i); + ASSERT_NOEXCEPT(acc.access(ptr, i)); + assert(&x == ptr + i); + } +} + +template +constexpr void test_it() { + constexpr std::size_t N = alignof(T); + test_access(); + test_access(); + test_access(); + test_access(); + test_access(); +} + +constexpr bool test() { + test_it(); + test_it(); + test_it(); + test_it(); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.from.default_accessor.pass.cpp b/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.from.default_accessor.pass.cpp new file mode 100644 index 0000000000000..3c465e89b77b9 --- /dev/null +++ b/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.from.default_accessor.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++17, c++20, c++23 + +// +// +// template +// explicit constexpr aligned_accessor( +// default_accessor) noexcept {} +// +// Constraints: is_convertible_v is true. + +#include +#include +#include +#include + +#include "test_macros.h" + +#include "../MinimalElementType.h" + +struct Base {}; +struct Derived : public Base {}; + +template +constexpr void test_conversion() { + std::default_accessor from; + ASSERT_NOEXCEPT(std::aligned_accessor(from)); + [[maybe_unused]] std::aligned_accessor to(from); + // check that the constructor is explicit + static_assert(std::is_nothrow_constructible_v, std::default_accessor>); + static_assert(!std::is_convertible_v, std::aligned_accessor>); +} + +template +constexpr void test_it() { + constexpr std::size_t N = alignof(To); + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); +} + +constexpr bool test() { + test_it(); + test_it(); + test_it(); + test_it(); + test_it(); + test_it(); + + // char is convertible to int, but accessors are not + static_assert(!std::is_constructible_v, std::default_accessor>); + // don't allow conversion from const elements to non-const + static_assert(!std::is_constructible_v, std::default_accessor>); + // MinimalElementType is constructible from int, but accessors should not be convertible + static_assert(!std::is_constructible_v, std::default_accessor>); + // don't allow conversion from const elements to non-const + static_assert(!std::is_constructible_v, + std::default_accessor>); + // don't allow conversion from Base to Derived + static_assert(!std::is_constructible_v, std::default_accessor>); + // don't allow conversion from Derived to Base + static_assert(!std::is_constructible_v, std::default_accessor>); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.pass.cpp b/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.pass.cpp new file mode 100644 index 0000000000000..0263e7c1d2e3a --- /dev/null +++ b/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.pass.cpp @@ -0,0 +1,104 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++17, c++20, c++23 + +// +// +// template +// constexpr aligned_accessor(aligned_accessor) noexcept {} +// +// Constraints: +// - is_convertible_v is true. +// - OtherByteAlignment >= byte_alignment is true. + +#include +#include +#include +#include + +#include "test_macros.h" + +#include "../MinimalElementType.h" + +struct Base {}; +struct Derived : public Base {}; + +template +constexpr void test_conversion() { + std::aligned_accessor acc_from; + ASSERT_NOEXCEPT(std::aligned_accessor(acc_from)); + [[maybe_unused]] std::aligned_accessor acc_to(acc_from); +} + +template +constexpr void test_it() { + constexpr std::size_t N = alignof(From); + static_assert(N == alignof(To)); + + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); + + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); + + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); + + test_conversion(); + test_conversion(); + test_conversion(); + + test_conversion(); + test_conversion(); + + test_conversion(); +} + +constexpr bool test() { + test_it(); + test_it(); + test_it(); + test_it(); + test_it(); + test_it(); + + // char is convertible to int, but accessors are not + static_assert(!std::is_constructible_v, std::aligned_accessor>); + // don't allow conversion from const elements to non-const + static_assert(!std::is_constructible_v, std::aligned_accessor>); + // don't allow conversion from less to more alignment + static_assert(!std::is_constructible_v, std::aligned_accessor>); + static_assert(!std::is_constructible_v, std::aligned_accessor>); + // MinimalElementType is constructible from int, but accessors should not be convertible + static_assert(!std::is_constructible_v, std::aligned_accessor>); + // don't allow conversion from const elements to non-const + static_assert(!std::is_constructible_v, + std::aligned_accessor>); + // don't allow conversion from Base to Derived + static_assert(!std::is_constructible_v, std::aligned_accessor>); + // don't allow conversion from Derived to Base + static_assert(!std::is_constructible_v, std::aligned_accessor>); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.default.pass.cpp b/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.default.pass.cpp new file mode 100644 index 0000000000000..a1a2449bd4c67 --- /dev/null +++ b/libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.default.pass.cpp @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++17, c++20, c++23 + +// + +// Test default construction: +// +// constexpr aligned_accessor() noexcept = default; + +#include +#include +#include +#include + +#include "test_macros.h" + +#include "../MinimalElementType.h" + +template +constexpr void test_construction() { + ASSERT_NOEXCEPT(std::aligned_accessor{}); + [[maybe_unused]] std::aligned_accessor acc; + static_assert(std::is_trivially_default_constructible_v>); +} + +template +constexpr void test_it() { + constexpr std::size_t N = alignof(T); + test_construction(); + test_construction(); + test_construction(); + test_construction(); + test_construction(); + test_construction(); +} + +constexpr bool test() { + test_it(); + test_it(); + test_it(); + test_it(); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/containers/views/mdspan/aligned_accessor/offset.pass.cpp b/libcxx/test/std/containers/views/mdspan/aligned_accessor/offset.pass.cpp new file mode 100644 index 0000000000000..66c30da787a8d --- /dev/null +++ b/libcxx/test/std/containers/views/mdspan/aligned_accessor/offset.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++17, c++20, c++23 + +// + +// constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const noexcept; +// +// Effects: Equivalent to: return assume_aligned(p) + i; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +// We are not using MinimalElementType.h because MinimalElementType is not +// default consructible and uninitialized storage does not work in constexpr. + +// Same as MinimalElementType but with a defaulted default constructor +struct MyMinimalElementType { + int val; + constexpr MyMinimalElementType() = default; + constexpr MyMinimalElementType(const MyMinimalElementType&) = delete; + constexpr explicit MyMinimalElementType(int v) noexcept : val(v) {} + constexpr MyMinimalElementType& operator=(const MyMinimalElementType&) = delete; +}; + +template +constexpr void test_offset() { + constexpr std::size_t Sz = 10; + alignas(N) T data[Sz]{}; + T* ptr = &data[0]; + std::aligned_accessor acc; + for (std::size_t i = 0; i < Sz; ++i) { + std::same_as::data_handle_type> decltype(auto) x = acc.offset(ptr, i); + ASSERT_NOEXCEPT(acc.offset(ptr, i)); + assert(x == ptr + i); + } +} + +template +constexpr void test_it() { + constexpr std::size_t N = alignof(T); + test_offset(); + test_offset(); + test_offset(); + test_offset(); + test_offset(); +} + +constexpr bool test() { + test_it(); + test_it(); + test_it(); + test_it(); + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/containers/views/mdspan/aligned_accessor/operator.conversion.to.default_accessor.pass.cpp b/libcxx/test/std/containers/views/mdspan/aligned_accessor/operator.conversion.to.default_accessor.pass.cpp new file mode 100644 index 0000000000000..5b72718c89ec2 --- /dev/null +++ b/libcxx/test/std/containers/views/mdspan/aligned_accessor/operator.conversion.to.default_accessor.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++17, c++20, c++23 + +// +// +// template +// constexpr operator default_accessor() const noexcept; +// +// Constraints: is_convertible_v is true. + +#include +#include +#include +#include + +#include "test_macros.h" + +#include "../MinimalElementType.h" + +struct Base {}; +struct Derived : public Base {}; + +template +constexpr void test_conversion() { + std::aligned_accessor from; + ASSERT_NOEXCEPT(std::default_accessor(from)); + [[maybe_unused]] std::default_accessor to(from); + // check that the conversion is implicit + static_assert(std::is_nothrow_convertible_v, std::default_accessor>); + static_assert(std::is_nothrow_constructible_v, std::aligned_accessor>); +} + +template +constexpr void test_it() { + constexpr size_t N = alignof(From); + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); + test_conversion(); +} + +constexpr bool test() { + test_it(); + test_it(); + test_it(); + test_it(); + test_it(); + test_it(); + + // char is convertible to int, but accessors are not + static_assert(!std::is_constructible_v, std::aligned_accessor>); + // don't allow conversion from const elements to non-const + static_assert(!std::is_constructible_v, std::aligned_accessor>); + // MinimalElementType is constructible from int, but accessors should not be convertible + static_assert(!std::is_constructible_v, std::aligned_accessor>); + // don't allow conversion from const elements to non-const + static_assert(!std::is_constructible_v, + std::aligned_accessor>); + // don't allow conversion from Base to Derived + static_assert(!std::is_constructible_v, std::aligned_accessor>); + // don't allow conversion from Derived to Base + static_assert(!std::is_constructible_v, std::aligned_accessor>); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcxx/test/std/containers/views/mdspan/aligned_accessor/types.pass.cpp b/libcxx/test/std/containers/views/mdspan/aligned_accessor/types.pass.cpp new file mode 100644 index 0000000000000..1fed971f3bb13 --- /dev/null +++ b/libcxx/test/std/containers/views/mdspan/aligned_accessor/types.pass.cpp @@ -0,0 +1,71 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++17, c++20, c++23 + +// + +// template +// struct aligned_accessor { +// using offset_policy = default_accessor; +// using element_type = ElementType; +// using reference = ElementType&; +// using data_handle_type = ElementType*; +// +// static constexpr size_t byte_alignment = ByteAlignment; +// +// ... +// }; +// +// Each specialization of aligned_accessor is a trivially copyable type that models semiregular. + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +#include "../MinimalElementType.h" + +template +void test_types() { + using A = std::aligned_accessor; + ASSERT_SAME_TYPE(typename A::offset_policy, std::default_accessor); + ASSERT_SAME_TYPE(typename A::element_type, T); + ASSERT_SAME_TYPE(typename A::reference, T&); + ASSERT_SAME_TYPE(typename A::data_handle_type, T*); + + ASSERT_SAME_TYPE(decltype(A::byte_alignment), const std::size_t); + static_assert(A::byte_alignment == N); + + static_assert(std::semiregular); + static_assert(std::is_trivially_copyable_v); + + LIBCPP_STATIC_ASSERT(std::is_empty_v); +} + +template +void test() { + constexpr std::size_t N = alignof(T); + test_types(); + test_types(); + test_types(); + test_types(); + test_types(); + test_types(); +} + +int main(int, char**) { + test(); + test(); + test(); + test(); + return 0; +} diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/mdspan.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/mdspan.version.compile.pass.cpp index 28524438f644b..e6b4adac20efb 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/mdspan.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/mdspan.version.compile.pass.cpp @@ -20,6 +20,10 @@ #if TEST_STD_VER < 14 +# ifdef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should not be defined before c++26" +# endif + # ifdef __cpp_lib_freestanding_mdspan # error "__cpp_lib_freestanding_mdspan should not be defined before c++26" # endif @@ -34,6 +38,10 @@ #elif TEST_STD_VER == 14 +# ifdef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should not be defined before c++26" +# endif + # ifdef __cpp_lib_freestanding_mdspan # error "__cpp_lib_freestanding_mdspan should not be defined before c++26" # endif @@ -48,6 +56,10 @@ #elif TEST_STD_VER == 17 +# ifdef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should not be defined before c++26" +# endif + # ifdef __cpp_lib_freestanding_mdspan # error "__cpp_lib_freestanding_mdspan should not be defined before c++26" # endif @@ -62,6 +74,10 @@ #elif TEST_STD_VER == 20 +# ifdef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should not be defined before c++26" +# endif + # ifdef __cpp_lib_freestanding_mdspan # error "__cpp_lib_freestanding_mdspan should not be defined before c++26" # endif @@ -76,6 +92,10 @@ #elif TEST_STD_VER == 23 +# ifdef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should not be defined before c++26" +# endif + # ifdef __cpp_lib_freestanding_mdspan # error "__cpp_lib_freestanding_mdspan should not be defined before c++26" # endif @@ -93,6 +113,13 @@ #elif TEST_STD_VER > 23 +# ifndef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should be defined in c++26" +# endif +# if __cpp_lib_aligned_accessor != 202411L +# error "__cpp_lib_aligned_accessor should have the value 202411L in c++26" +# endif + # if !defined(_LIBCPP_VERSION) # ifndef __cpp_lib_freestanding_mdspan # error "__cpp_lib_freestanding_mdspan should be defined in c++26" diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp index fc70df3ae2ef9..bf02dba0da773 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp @@ -52,6 +52,10 @@ # error "__cpp_lib_enable_shared_from_this should not be defined before c++17" # endif +# ifdef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should not be defined before c++26" +# endif + # ifdef __cpp_lib_make_unique # error "__cpp_lib_make_unique should not be defined before c++14" # endif @@ -126,6 +130,10 @@ # error "__cpp_lib_enable_shared_from_this should not be defined before c++17" # endif +# ifdef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should not be defined before c++26" +# endif + # ifndef __cpp_lib_make_unique # error "__cpp_lib_make_unique should be defined in c++14" # endif @@ -215,6 +223,10 @@ # error "__cpp_lib_enable_shared_from_this should have the value 201603L in c++17" # endif +# ifdef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should not be defined before c++26" +# endif + # ifndef __cpp_lib_make_unique # error "__cpp_lib_make_unique should be defined in c++17" # endif @@ -325,6 +337,10 @@ # error "__cpp_lib_enable_shared_from_this should have the value 201603L in c++20" # endif +# ifdef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should not be defined before c++26" +# endif + # ifndef __cpp_lib_make_unique # error "__cpp_lib_make_unique should be defined in c++20" # endif @@ -447,6 +463,10 @@ # error "__cpp_lib_enable_shared_from_this should have the value 201603L in c++23" # endif +# ifdef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should not be defined before c++26" +# endif + # ifndef __cpp_lib_make_unique # error "__cpp_lib_make_unique should be defined in c++23" # endif @@ -572,6 +592,13 @@ # error "__cpp_lib_enable_shared_from_this should have the value 201603L in c++26" # endif +# ifndef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should be defined in c++26" +# endif +# if __cpp_lib_is_sufficiently_aligned != 202411L +# error "__cpp_lib_is_sufficiently_aligned should have the value 202411L in c++26" +# endif + # ifndef __cpp_lib_make_unique # error "__cpp_lib_make_unique should be defined in c++26" # endif diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index 7b2041be4dc86..aa33a2788f1eb 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -28,6 +28,10 @@ # error "__cpp_lib_addressof_constexpr should not be defined before c++17" # endif +# ifdef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should not be defined before c++26" +# endif + # ifdef __cpp_lib_allocate_at_least # error "__cpp_lib_allocate_at_least should not be defined before c++23" # endif @@ -476,6 +480,10 @@ # error "__cpp_lib_is_scoped_enum should not be defined before c++23" # endif +# ifdef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should not be defined before c++26" +# endif + # ifdef __cpp_lib_is_swappable # error "__cpp_lib_is_swappable should not be defined before c++17" # endif @@ -898,6 +906,10 @@ # error "__cpp_lib_addressof_constexpr should not be defined before c++17" # endif +# ifdef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should not be defined before c++26" +# endif + # ifdef __cpp_lib_allocate_at_least # error "__cpp_lib_allocate_at_least should not be defined before c++23" # endif @@ -1370,6 +1382,10 @@ # error "__cpp_lib_is_scoped_enum should not be defined before c++23" # endif +# ifdef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should not be defined before c++26" +# endif + # ifdef __cpp_lib_is_swappable # error "__cpp_lib_is_swappable should not be defined before c++17" # endif @@ -1843,6 +1859,10 @@ # error "__cpp_lib_addressof_constexpr should have the value 201603L in c++17" # endif +# ifdef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should not be defined before c++26" +# endif + # ifdef __cpp_lib_allocate_at_least # error "__cpp_lib_allocate_at_least should not be defined before c++23" # endif @@ -2399,6 +2419,10 @@ # error "__cpp_lib_is_scoped_enum should not be defined before c++23" # endif +# ifdef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should not be defined before c++26" +# endif + # ifndef __cpp_lib_is_swappable # error "__cpp_lib_is_swappable should be defined in c++17" # endif @@ -2983,6 +3007,10 @@ # error "__cpp_lib_addressof_constexpr should have the value 201603L in c++20" # endif +# ifdef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should not be defined before c++26" +# endif + # ifdef __cpp_lib_allocate_at_least # error "__cpp_lib_allocate_at_least should not be defined before c++23" # endif @@ -3710,6 +3738,10 @@ # error "__cpp_lib_is_scoped_enum should not be defined before c++23" # endif +# ifdef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should not be defined before c++26" +# endif + # ifndef __cpp_lib_is_swappable # error "__cpp_lib_is_swappable should be defined in c++20" # endif @@ -4390,6 +4422,10 @@ # error "__cpp_lib_addressof_constexpr should have the value 201603L in c++23" # endif +# ifdef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should not be defined before c++26" +# endif + # ifndef __cpp_lib_allocate_at_least # error "__cpp_lib_allocate_at_least should be defined in c++23" # endif @@ -5198,6 +5234,10 @@ # error "__cpp_lib_is_scoped_enum should have the value 202011L in c++23" # endif +# ifdef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should not be defined before c++26" +# endif + # ifndef __cpp_lib_is_swappable # error "__cpp_lib_is_swappable should be defined in c++23" # endif @@ -6025,6 +6065,13 @@ # error "__cpp_lib_addressof_constexpr should have the value 201603L in c++26" # endif +# ifndef __cpp_lib_aligned_accessor +# error "__cpp_lib_aligned_accessor should be defined in c++26" +# endif +# if __cpp_lib_aligned_accessor != 202411L +# error "__cpp_lib_aligned_accessor should have the value 202411L in c++26" +# endif + # ifndef __cpp_lib_allocate_at_least # error "__cpp_lib_allocate_at_least should be defined in c++26" # endif @@ -7025,6 +7072,13 @@ # error "__cpp_lib_is_scoped_enum should have the value 202011L in c++26" # endif +# ifndef __cpp_lib_is_sufficiently_aligned +# error "__cpp_lib_is_sufficiently_aligned should be defined in c++26" +# endif +# if __cpp_lib_is_sufficiently_aligned != 202411L +# error "__cpp_lib_is_sufficiently_aligned should have the value 202411L in c++26" +# endif + # ifndef __cpp_lib_is_swappable # error "__cpp_lib_is_swappable should be defined in c++26" # endif diff --git a/libcxx/test/std/utilities/memory/ptr.align/is_sufficiently_aligned.pass.cpp b/libcxx/test/std/utilities/memory/ptr.align/is_sufficiently_aligned.pass.cpp new file mode 100644 index 0000000000000..fb40459cfe470 --- /dev/null +++ b/libcxx/test/std/utilities/memory/ptr.align/is_sufficiently_aligned.pass.cpp @@ -0,0 +1,113 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++17, c++20, c++23 + +// #include + +// template +// bool is_sufficiently_aligned(T* ptr); + +#include +#include +#include +#include + +#include "test_macros.h" + +template +void test_is_sufficiently_aligned() { + constexpr std::size_t N = alignof(T); + + alignas(8 * N) std::remove_cv_t buf[5]; + constexpr std::size_t Sz = sizeof(T); + + assert(std::is_sufficiently_aligned(&buf[0])); + assert(std::is_sufficiently_aligned<2 * N>(&buf[0])); + assert(std::is_sufficiently_aligned<4 * N>(&buf[0])); + assert(std::is_sufficiently_aligned<8 * N>(&buf[0])); + + assert(std::is_sufficiently_aligned(&buf[1])); + assert(std::is_sufficiently_aligned<2 * N>(&buf[1]) == (((1 * Sz) % (2 * N)) == 0)); + assert(std::is_sufficiently_aligned<4 * N>(&buf[1]) == (((1 * Sz) % (4 * N)) == 0)); + assert(std::is_sufficiently_aligned<8 * N>(&buf[1]) == (((1 * Sz) % (8 * N)) == 0)); + + assert(std::is_sufficiently_aligned(&buf[2])); + assert(std::is_sufficiently_aligned<2 * N>(&buf[2]) == (((2 * Sz) % (2 * N)) == 0)); + assert(std::is_sufficiently_aligned<4 * N>(&buf[2]) == (((2 * Sz) % (4 * N)) == 0)); + assert(std::is_sufficiently_aligned<8 * N>(&buf[2]) == (((2 * Sz) % (8 * N)) == 0)); + + assert(std::is_sufficiently_aligned(&buf[3])); + assert(std::is_sufficiently_aligned<2 * N>(&buf[3]) == (((3 * Sz) % (2 * N)) == 0)); + assert(std::is_sufficiently_aligned<4 * N>(&buf[3]) == (((3 * Sz) % (4 * N)) == 0)); + assert(std::is_sufficiently_aligned<8 * N>(&buf[3]) == (((3 * Sz) % (8 * N)) == 0)); + + assert(std::is_sufficiently_aligned(&buf[4])); + assert(std::is_sufficiently_aligned<2 * N>(&buf[4]) == (((4 * Sz) % (2 * N)) == 0)); + assert(std::is_sufficiently_aligned<4 * N>(&buf[4]) == (((4 * Sz) % (4 * N)) == 0)); + assert(std::is_sufficiently_aligned<8 * N>(&buf[4]) == (((4 * Sz) % (8 * N)) == 0)); +} + +template +void check(T* p) { + ASSERT_SAME_TYPE(bool, decltype(std::is_sufficiently_aligned(p))); + test_is_sufficiently_aligned(); + test_is_sufficiently_aligned(); +} + +struct S {}; +struct alignas(4) S4 {}; +struct alignas(8) S8 {}; +struct alignas(16) S16 {}; +struct alignas(32) S32 {}; +struct alignas(64) S64 {}; +struct alignas(128) S128 {}; + +struct alignas(1) X { + unsigned char d[2]; +}; +static_assert(sizeof(X) == 2 * alignof(X)); + +bool tests() { + char c; + int i; + long l; + double d; + long double ld; + check(&c); + check(&i); + check(&l); + check(&d); + check(&ld); + + S s; + S4 s4; + S8 s8; + S16 s16; + S32 s32; + S64 s64; + S128 s128; + check(&s); + check(&s4); + check(&s8); + check(&s16); + check(&s32); + check(&s64); + check(&s128); + + X x; + check(&x); + + return true; +} + +int main(int, char**) { + tests(); + + return 0; +} diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index baca05f5e0772..cb92dc17ba707 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -97,6 +97,11 @@ def add_version_header(tc): "values": {"c++17": 201603}, "headers": ["memory"], }, + { + "name": "__cpp_lib_aligned_accessor", + "values": {"c++26": 202411}, + "headers": ["mdspan"], + }, { "name": "__cpp_lib_allocate_at_least", "values": { @@ -803,6 +808,11 @@ def add_version_header(tc): "values": {"c++23": 202011}, "headers": ["type_traits"], }, + { + "name": "__cpp_lib_is_sufficiently_aligned", + "values": {"c++26": 202411}, + "headers": ["memory"], + }, { "name": "__cpp_lib_is_swappable", "values": {"c++17": 201603},