[libcxx-commits] [libcxx] 557e931 - [libc++] Implement P2897R7 aligned_accessor: An mdspan accessor expressing pointer over-alignment (#122603)
via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Apr 14 14:34:01 PDT 2025
Author: Damien L-G
Date: 2025-04-14T17:33:57-04:00
New Revision: 557e931d958104eb5d11b93ad3a21e4017812fcd
URL: https://github.com/llvm/llvm-project/commit/557e931d958104eb5d11b93ad3a21e4017812fcd
DIFF: https://github.com/llvm/llvm-project/commit/557e931d958104eb5d11b93ad3a21e4017812fcd.diff
LOG: [libc++] Implement P2897R7 aligned_accessor: An mdspan accessor expressing pointer over-alignment (#122603)
Closes #118372
Added:
libcxx/include/__mdspan/aligned_accessor.h
libcxx/include/__memory/is_sufficiently_aligned.h
libcxx/test/libcxx/containers/views/mdspan/aligned_accessor/byte_alignment.verify.cpp
libcxx/test/libcxx/containers/views/mdspan/aligned_accessor/element_type.verify.cpp
libcxx/test/std/containers/views/mdspan/aligned_accessor/access.pass.cpp
libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.from.default_accessor.pass.cpp
libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.conversion.pass.cpp
libcxx/test/std/containers/views/mdspan/aligned_accessor/ctor.default.pass.cpp
libcxx/test/std/containers/views/mdspan/aligned_accessor/offset.pass.cpp
libcxx/test/std/containers/views/mdspan/aligned_accessor/operator.conversion.to.default_accessor.pass.cpp
libcxx/test/std/containers/views/mdspan/aligned_accessor/types.pass.cpp
libcxx/test/std/utilities/memory/ptr.align/is_sufficiently_aligned.pass.cpp
Modified:
libcxx/docs/FeatureTestMacroTable.rst
libcxx/docs/ReleaseNotes/21.rst
libcxx/docs/Status/Cxx2cPapers.csv
libcxx/include/CMakeLists.txt
libcxx/include/__mdspan/mdspan.h
libcxx/include/mdspan
libcxx/include/memory
libcxx/include/module.modulemap
libcxx/include/version
libcxx/modules/std/mdspan.inc
libcxx/modules/std/memory.inc
libcxx/test/std/language.support/support.limits/support.limits.general/mdspan.version.compile.pass.cpp
libcxx/test/std/language.support/support.limits/support.limits.general/memory.version.compile.pass.cpp
libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
libcxx/utils/generate_feature_test_macro_components.py
Removed:
################################################################################
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 de92eeeaaa7dd..ac54922eb4c59 100644
--- a/libcxx/docs/ReleaseNotes/21.rst
+++ b/libcxx/docs/ReleaseNotes/21.rst
@@ -45,6 +45,7 @@ Implemented Papers
- P2562R1: ``constexpr`` Stable Sorting (`Github <https://github.com/llvm/llvm-project/issues/105360>`__)
- P0472R3: Put std::monostate in <utility> (`Github <https://github.com/llvm/llvm-project/issues/127874>`__)
- P1222R4: A Standard ``flat_set`` (`Github <https://github.com/llvm/llvm-project/issues/105193>`__)
+- P2897R7: ``aligned_accessor``: An mdspan accessor expressing pointer over-alignment (`Github <https://github.com/llvm/llvm-project/issues/118372>`__)
- P3247R2: Deprecate the notion of trivial types (`Github <https://github.com/llvm/llvm-project/issues/118387>`__)
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 <https://wg21.link/P3138R5>`__","``views::cache_latest``","2024-11 (Wrocław)","","",""
"`P3379R0 <https://wg21.link/P3379R0>`__","Constrain ``std::expected`` equality operators","2024-11 (Wrocław)","","",""
"`P2862R1 <https://wg21.link/P2862R1>`__","``text_encoding::name()`` should never return null values","2024-11 (Wrocław)","","",""
-"`P2897R7 <https://wg21.link/P2897R7>`__","``aligned_accessor``: An ``mdspan`` accessor expressing pointer over-alignment","2024-11 (Wrocław)","","",""
+"`P2897R7 <https://wg21.link/P2897R7>`__","``aligned_accessor``: An ``mdspan`` accessor expressing pointer over-alignment","2024-11 (Wrocław)","|Complete|","21",""
"`P3355R1 <https://wg21.link/P3355R1>`__","Fix ``submdspan`` for C++26","2024-11 (Wrocław)","","",""
"`P3222R0 <https://wg21.link/P3222R0>`__","Fix C++26 by adding transposed special cases for P2642 layouts","2024-11 (Wrocław)","","",""
"`P3050R2 <https://wg21.link/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 <class _ElementType, size_t _ByteAlignment>
+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 <class _OtherElementType, size_t _OtherByteAlignment>
+ requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]> && _OtherByteAlignment >= byte_alignment)
+ _LIBCPP_HIDE_FROM_ABI constexpr aligned_accessor(aligned_accessor<_OtherElementType, _OtherByteAlignment>) noexcept {}
+
+ template <class _OtherElementType>
+ requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]>)
+ _LIBCPP_HIDE_FROM_ABI explicit constexpr aligned_accessor(default_accessor<_OtherElementType>) noexcept {}
+
+ template <class _OtherElementType>
+ requires(is_convertible_v<element_type (*)[], _OtherElementType (*)[]>)
+ _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<byte_alignment>(__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<byte_alignment>(__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 <class _ElementType, class... _OtherIndexTypes>
requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0))
-explicit mdspan(_ElementType*,
- _OtherIndexTypes...) -> mdspan<_ElementType, extents<size_t, __maybe_static_ext<_OtherIndexTypes>...>>;
+explicit mdspan(_ElementType*, _OtherIndexTypes...)
+ -> mdspan<_ElementType, extents<size_t, __maybe_static_ext<_OtherIndexTypes>...>>;
# else
template <class _ElementType, class... _OtherIndexTypes>
requires((is_convertible_v<_OtherIndexTypes, size_t> && ...) && (sizeof...(_OtherIndexTypes) > 0))
-explicit mdspan(_ElementType*,
- _OtherIndexTypes...) -> mdspan<_ElementType, dextents<size_t, sizeof...(_OtherIndexTypes)>>;
+explicit mdspan(_ElementType*, _OtherIndexTypes...)
+ -> mdspan<_ElementType, dextents<size_t, sizeof...(_OtherIndexTypes)>>;
# endif
template <class _Pointer>
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 <cstdint>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 26
+
+template <size_t _Alignment, class _Tp>
+_LIBCPP_HIDE_FROM_ABI bool is_sufficiently_aligned(_Tp* __ptr) {
+ return reinterpret_cast<uintptr_t>(__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 ElementType>
class default_accessor;
+ // [mdspan.accessor.aligned], class template aligned_accessor
+ template<class ElementType, size_t ByteAlignment>
+ class aligned_accessor; // since C++26
+
// [mdspan.mdspan], class template mdspan
template<class ElementType, class Extents, class LayoutPolicy = layout_right,
class AccessorPolicy = default_accessor<ElementType>>
- class mdspan; // not implemented yet
+ class mdspan;
}
// extents synopsis
@@ -269,6 +273,38 @@ namespace std {
};
}
+// aligned_accessor synopsis
+
+namespace std {
+ template<class ElementType, size_t ByteAlignment>
+ struct aligned_accessor {
+ 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;
+
+ constexpr aligned_accessor() noexcept = default;
+
+ template<class OtherElementType, size_t OtherByteAlignment>
+ constexpr aligned_accessor(
+ aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept;
+
+ template<class OtherElementType>
+ explicit constexpr aligned_accessor(
+ default_accessor<OtherElementType>) noexcept;
+
+ template<class OtherElementType>
+ constexpr operator default_accessor<OtherElementType>() 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<size_t N, class T>
[[nodiscard]] constexpr T* assume_aligned(T* ptr); // since C++20
+template<size_t Alignment, class T>
+ bool is_sufficiently_aligned(T* ptr); // since C++26
+
// [out.ptr.t], class template out_ptr_t
template<class Smart, class Pointer, class... Args>
class out_ptr_t; // since c++23
@@ -945,6 +948,7 @@ template<class Pointer = void, class Smart, class... Args>
# 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 <queue> <stack>
__cpp_lib_addressof_constexpr 201603L <memory>
+__cpp_lib_aligned_accessor 202411L <mdspan>
__cpp_lib_allocate_at_least 202302L <memory>
__cpp_lib_allocator_traits_is_always_equal 201411L <deque> <forward_list> <list>
<map> <memory> <scoped_allocator>
@@ -148,6 +149,7 @@ __cpp_lib_is_nothrow_convertible 201806L <type_traits>
__cpp_lib_is_null_pointer 201309L <type_traits>
__cpp_lib_is_pointer_interconvertible 201907L <type_traits>
__cpp_lib_is_scoped_enum 202011L <type_traits>
+__cpp_lib_is_sufficiently_aligned 202411L <memory>
__cpp_lib_is_swappable 201603L <type_traits>
__cpp_lib_is_virtual_base_of 202406L <type_traits>
__cpp_lib_is_within_lifetime 202306L <type_traits>
@@ -532,6 +534,7 @@ __cpp_lib_void_t 201411L <type_traits>
#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 <type_traits>
// # 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
+
+// <mdspan>
+
+// template<class ElementType, size_t ByteAlignment>
+// class aligned_accessor;
+
+// ByteAlignement is required to be a power of two and greater or equal to alignof(ElementType).
+
+#include <mdspan>
+
+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<int, 12> acc;
+}
+
+struct alignas(8) S {};
+
+void insufficiently_aligned() {
+ // expected-error-re@*:* {{static assertion failed {{.*}}aligned_accessor: insufficient byte alignment}}
+ [[maybe_unused]] std::aligned_accessor<S, 4> 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
+
+// <mdspan>
+
+// template<class ElementType, size_t ByteAlignment>
+// class aligned_accessor;
+
+// ElementType is required to be a complete object type that is neither an abstract class type nor an array type.
+
+#include <mdspan>
+
+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<AbstractClass, 8> 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<int[5], 128> 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
+
+// <mdspan>
+
+// constexpr reference access(data_handle_type p, size_t i) const noexcept;
+//
+// Effects: Equivalent to: return assume_aligned<byte_alignment>(p)[i];
+
+#include <mdspan>
+#include <cassert>
+#include <cstddef>
+#include <concepts>
+#include <type_traits>
+
+#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 <class T, std::size_t N>
+constexpr void test_access() {
+ constexpr std::size_t Sz = 10;
+ alignas(N) T data[Sz]{};
+ T* ptr = &data[0];
+ std::aligned_accessor<T, N> acc;
+ for (std::size_t i = 0; i < Sz; ++i) {
+ std::same_as<typename std::aligned_accessor<T, N>::reference> decltype(auto) x = acc.access(ptr, i);
+ ASSERT_NOEXCEPT(acc.access(ptr, i));
+ assert(&x == ptr + i);
+ }
+}
+
+template <class T>
+constexpr void test_it() {
+ constexpr std::size_t N = alignof(T);
+ test_access<T, N>();
+ test_access<T, 2 * N>();
+ test_access<T, 4 * N>();
+ test_access<T, 8 * N>();
+ test_access<T, 16 * N>();
+}
+
+constexpr bool test() {
+ test_it<int>();
+ test_it<const int>();
+ test_it<MyMinimalElementType>();
+ test_it<const MyMinimalElementType>();
+ 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
+
+// <mdspan>
+//
+// template<class OtherElementType>
+// explicit constexpr aligned_accessor(
+// default_accessor<OtherElementType>) noexcept {}
+//
+// Constraints: is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true.
+
+#include <mdspan>
+#include <cassert>
+#include <cstddef>
+#include <type_traits>
+
+#include "test_macros.h"
+
+#include "../MinimalElementType.h"
+
+struct Base {};
+struct Derived : public Base {};
+
+template <class FromT, class ToT, std::size_t ToN>
+constexpr void test_conversion() {
+ std::default_accessor<FromT> from;
+ ASSERT_NOEXCEPT(std::aligned_accessor<ToT, ToN>(from));
+ [[maybe_unused]] std::aligned_accessor<ToT, ToN> to(from);
+ // check that the constructor is explicit
+ static_assert(std::is_nothrow_constructible_v<std::aligned_accessor<ToT, ToN>, std::default_accessor<ToT>>);
+ static_assert(!std::is_convertible_v<std::default_accessor<ToT>, std::aligned_accessor<ToT, ToN>>);
+}
+
+template <class From, class To>
+constexpr void test_it() {
+ constexpr std::size_t N = alignof(To);
+ test_conversion<From, To, N>();
+ test_conversion<From, To, 2 * N>();
+ test_conversion<From, To, 4 * N>();
+ test_conversion<From, To, 8 * N>();
+ test_conversion<From, To, 16 * N>();
+ test_conversion<From, To, 32 * N>();
+}
+
+constexpr bool test() {
+ test_it<int, int>();
+ test_it<int, const int>();
+ test_it<const int, const int>();
+ test_it<MinimalElementType, MinimalElementType>();
+ test_it<MinimalElementType, const MinimalElementType>();
+ test_it<const MinimalElementType, const MinimalElementType>();
+
+ // char is convertible to int, but accessors are not
+ static_assert(!std::is_constructible_v<std::aligned_accessor<int, 4>, std::default_accessor<char>>);
+ // don't allow conversion from const elements to non-const
+ static_assert(!std::is_constructible_v<std::aligned_accessor<int, 4>, std::default_accessor<const int>>);
+ // MinimalElementType is constructible from int, but accessors should not be convertible
+ static_assert(!std::is_constructible_v<std::aligned_accessor<MinimalElementType, 8>, std::default_accessor<int>>);
+ // don't allow conversion from const elements to non-const
+ static_assert(!std::is_constructible_v<std::aligned_accessor<MinimalElementType, 16>,
+ std::default_accessor<const MinimalElementType>>);
+ // don't allow conversion from Base to Derived
+ static_assert(!std::is_constructible_v<std::aligned_accessor<Derived, 2>, std::default_accessor<Base>>);
+ // don't allow conversion from Derived to Base
+ static_assert(!std::is_constructible_v<std::aligned_accessor<Base, 2>, std::default_accessor<Derived>>);
+
+ 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
+
+// <mdspan>
+//
+// template<class OtherElementType, size_t OtherByteAlignment>
+// constexpr aligned_accessor(aligned_accessor<OtherElementType, OtherByteAlignment>) noexcept {}
+//
+// Constraints:
+// - is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true.
+// - OtherByteAlignment >= byte_alignment is true.
+
+#include <mdspan>
+#include <cassert>
+#include <cstddef>
+#include <type_traits>
+
+#include "test_macros.h"
+
+#include "../MinimalElementType.h"
+
+struct Base {};
+struct Derived : public Base {};
+
+template <class FromT, std::size_t FromN, class ToT, std::size_t ToN>
+constexpr void test_conversion() {
+ std::aligned_accessor<FromT, FromN> acc_from;
+ ASSERT_NOEXCEPT(std::aligned_accessor<ToT, ToN>(acc_from));
+ [[maybe_unused]] std::aligned_accessor<ToT, ToN> acc_to(acc_from);
+}
+
+template <class From, class To>
+constexpr void test_it() {
+ constexpr std::size_t N = alignof(From);
+ static_assert(N == alignof(To));
+
+ test_conversion<From, N, To, N>();
+ test_conversion<From, 2 * N, To, N>();
+ test_conversion<From, 4 * N, To, N>();
+ test_conversion<From, 8 * N, To, N>();
+ test_conversion<From, 16 * N, To, N>();
+ test_conversion<From, 32 * N, To, N>();
+
+ test_conversion<From, 2 * N, To, 2 * N>();
+ test_conversion<From, 4 * N, To, 2 * N>();
+ test_conversion<From, 8 * N, To, 2 * N>();
+ test_conversion<From, 16 * N, To, 2 * N>();
+ test_conversion<From, 32 * N, To, 2 * N>();
+
+ test_conversion<From, 4 * N, To, 4 * N>();
+ test_conversion<From, 8 * N, To, 4 * N>();
+ test_conversion<From, 16 * N, To, 4 * N>();
+ test_conversion<From, 32 * N, To, 4 * N>();
+
+ test_conversion<From, 8 * N, To, 8 * N>();
+ test_conversion<From, 16 * N, To, 8 * N>();
+ test_conversion<From, 32 * N, To, 8 * N>();
+
+ test_conversion<From, 16 * N, To, 16 * N>();
+ test_conversion<From, 32 * N, To, 16 * N>();
+
+ test_conversion<From, 32 * N, To, 32 * N>();
+}
+
+constexpr bool test() {
+ test_it<int, int>();
+ test_it<int, const int>();
+ test_it<const int, const int>();
+ test_it<MinimalElementType, MinimalElementType>();
+ test_it<MinimalElementType, const MinimalElementType>();
+ test_it<const MinimalElementType, const MinimalElementType>();
+
+ // char is convertible to int, but accessors are not
+ static_assert(!std::is_constructible_v<std::aligned_accessor<int, 4>, std::aligned_accessor<char, 4>>);
+ // don't allow conversion from const elements to non-const
+ static_assert(!std::is_constructible_v<std::aligned_accessor<int, 4>, std::aligned_accessor<const int, 4>>);
+ // don't allow conversion from less to more alignment
+ static_assert(!std::is_constructible_v<std::aligned_accessor<int, 8>, std::aligned_accessor<int, 4>>);
+ static_assert(!std::is_constructible_v<std::aligned_accessor<const int, 8>, std::aligned_accessor<const int, 4>>);
+ // MinimalElementType is constructible from int, but accessors should not be convertible
+ static_assert(!std::is_constructible_v<std::aligned_accessor<MinimalElementType, 8>, std::aligned_accessor<int, 8>>);
+ // don't allow conversion from const elements to non-const
+ static_assert(!std::is_constructible_v<std::aligned_accessor<MinimalElementType, 16>,
+ std::aligned_accessor<const MinimalElementType, 16>>);
+ // don't allow conversion from Base to Derived
+ static_assert(!std::is_constructible_v<std::aligned_accessor<Derived, 1>, std::aligned_accessor<Base, 1>>);
+ // don't allow conversion from Derived to Base
+ static_assert(!std::is_constructible_v<std::aligned_accessor<Base, 1>, std::aligned_accessor<Derived, 1>>);
+
+ 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
+
+// <mdspan>
+
+// Test default construction:
+//
+// constexpr aligned_accessor() noexcept = default;
+
+#include <mdspan>
+#include <cassert>
+#include <cstddef>
+#include <type_traits>
+
+#include "test_macros.h"
+
+#include "../MinimalElementType.h"
+
+template <class T, std::size_t N>
+constexpr void test_construction() {
+ ASSERT_NOEXCEPT(std::aligned_accessor<T, N>{});
+ [[maybe_unused]] std::aligned_accessor<T, N> acc;
+ static_assert(std::is_trivially_default_constructible_v<std::aligned_accessor<T, N>>);
+}
+
+template <class T>
+constexpr void test_it() {
+ constexpr std::size_t N = alignof(T);
+ test_construction<T, N>();
+ test_construction<T, 2 * N>();
+ test_construction<T, 4 * N>();
+ test_construction<T, 8 * N>();
+ test_construction<T, 16 * N>();
+ test_construction<T, 32 * N>();
+}
+
+constexpr bool test() {
+ test_it<int>();
+ test_it<const int>();
+ test_it<MinimalElementType>();
+ test_it<const MinimalElementType>();
+ 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
+
+// <mdspan>
+
+// constexpr typename offset_policy::data_handle_type offset(data_handle_type p, size_t i) const noexcept;
+//
+// Effects: Equivalent to: return assume_aligned<byte_alignment>(p) + i;
+
+#include <mdspan>
+#include <cassert>
+#include <cstddef>
+#include <concepts>
+#include <type_traits>
+
+#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 <class T, std::size_t N>
+constexpr void test_offset() {
+ constexpr std::size_t Sz = 10;
+ alignas(N) T data[Sz]{};
+ T* ptr = &data[0];
+ std::aligned_accessor<T, N> acc;
+ for (std::size_t i = 0; i < Sz; ++i) {
+ std::same_as<typename std::default_accessor<T>::data_handle_type> decltype(auto) x = acc.offset(ptr, i);
+ ASSERT_NOEXCEPT(acc.offset(ptr, i));
+ assert(x == ptr + i);
+ }
+}
+
+template <class T>
+constexpr void test_it() {
+ constexpr std::size_t N = alignof(T);
+ test_offset<T, N>();
+ test_offset<T, 2 * N>();
+ test_offset<T, 4 * N>();
+ test_offset<T, 8 * N>();
+ test_offset<T, 16 * N>();
+}
+
+constexpr bool test() {
+ test_it<int>();
+ test_it<const int>();
+ test_it<MyMinimalElementType>();
+ test_it<const MyMinimalElementType>();
+ 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
+
+// <mdspan>
+//
+// template<class OtherElementType>
+// constexpr operator default_accessor<OtherElementType>() const noexcept;
+//
+// Constraints: is_convertible_v<element_type(*)[], OtherElementType(*)[]> is true.
+
+#include <mdspan>
+#include <cassert>
+#include <cstdint>
+#include <type_traits>
+
+#include "test_macros.h"
+
+#include "../MinimalElementType.h"
+
+struct Base {};
+struct Derived : public Base {};
+
+template <class FromT, size_t FromN, class ToT>
+constexpr void test_conversion() {
+ std::aligned_accessor<FromT, FromN> from;
+ ASSERT_NOEXCEPT(std::default_accessor<ToT>(from));
+ [[maybe_unused]] std::default_accessor<ToT> to(from);
+ // check that the conversion is implicit
+ static_assert(std::is_nothrow_convertible_v<std::aligned_accessor<FromT, FromN>, std::default_accessor<ToT>>);
+ static_assert(std::is_nothrow_constructible_v<std::default_accessor<ToT>, std::aligned_accessor<FromT, FromN>>);
+}
+
+template <class From, class To>
+constexpr void test_it() {
+ constexpr size_t N = alignof(From);
+ test_conversion<From, N, To>();
+ test_conversion<From, 2 * N, To>();
+ test_conversion<From, 4 * N, To>();
+ test_conversion<From, 8 * N, To>();
+ test_conversion<From, 16 * N, To>();
+ test_conversion<From, 32 * N, To>();
+}
+
+constexpr bool test() {
+ test_it<int, int>();
+ test_it<int, const int>();
+ test_it<const int, const int>();
+ test_it<MinimalElementType, MinimalElementType>();
+ test_it<MinimalElementType, const MinimalElementType>();
+ test_it<const MinimalElementType, const MinimalElementType>();
+
+ // char is convertible to int, but accessors are not
+ static_assert(!std::is_constructible_v<std::default_accessor<int>, std::aligned_accessor<char, 4>>);
+ // don't allow conversion from const elements to non-const
+ static_assert(!std::is_constructible_v<std::default_accessor<int>, std::aligned_accessor<const int, 8>>);
+ // MinimalElementType is constructible from int, but accessors should not be convertible
+ static_assert(!std::is_constructible_v<std::default_accessor<MinimalElementType>, std::aligned_accessor<int, 4>>);
+ // don't allow conversion from const elements to non-const
+ static_assert(!std::is_constructible_v<std::default_accessor<MinimalElementType>,
+ std::aligned_accessor<const MinimalElementType, 4>>);
+ // don't allow conversion from Base to Derived
+ static_assert(!std::is_constructible_v<std::default_accessor<Derived>, std::aligned_accessor<Base, 1>>);
+ // don't allow conversion from Derived to Base
+ static_assert(!std::is_constructible_v<std::default_accessor<Base>, std::aligned_accessor<Derived, 1>>);
+
+ 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
+
+// <mdspan>
+
+// template<class ElementType, size_t ByteAlignment>
+// struct aligned_accessor {
+// 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;
+//
+// ...
+// };
+//
+// Each specialization of aligned_accessor is a trivially copyable type that models semiregular.
+
+#include <mdspan>
+#include <cassert>
+#include <concepts>
+#include <cstddef>
+#include <type_traits>
+
+#include "test_macros.h"
+
+#include "../MinimalElementType.h"
+
+template <class T, std::size_t N>
+void test_types() {
+ using A = std::aligned_accessor<T, N>;
+ ASSERT_SAME_TYPE(typename A::offset_policy, std::default_accessor<T>);
+ 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<A>);
+ static_assert(std::is_trivially_copyable_v<A>);
+
+ LIBCPP_STATIC_ASSERT(std::is_empty_v<A>);
+}
+
+template <class T>
+void test() {
+ constexpr std::size_t N = alignof(T);
+ test_types<T, N>();
+ test_types<T, 2 * N>();
+ test_types<T, 4 * N>();
+ test_types<T, 8 * N>();
+ test_types<T, 16 * N>();
+ test_types<T, 32 * N>();
+}
+
+int main(int, char**) {
+ test<int>();
+ test<const int>();
+ test<MinimalElementType>();
+ test<const MinimalElementType>();
+ 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 <memory>
+
+// template<size_t Alignment, class T>
+// bool is_sufficiently_aligned(T* ptr);
+
+#include <cassert>
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template <typename T>
+void test_is_sufficiently_aligned() {
+ constexpr std::size_t N = alignof(T);
+
+ alignas(8 * N) std::remove_cv_t<T> buf[5];
+ constexpr std::size_t Sz = sizeof(T);
+
+ assert(std::is_sufficiently_aligned<N>(&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<N>(&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<N>(&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<N>(&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<N>(&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 <typename T>
+void check(T* p) {
+ ASSERT_SAME_TYPE(bool, decltype(std::is_sufficiently_aligned<alignof(T)>(p)));
+ test_is_sufficiently_aligned<T>();
+ test_is_sufficiently_aligned<const T>();
+}
+
+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},
More information about the libcxx-commits
mailing list