[PATCH v4 1/2] libstdc++: Implement is_sufficiently_aligned [PR120994]

Jonathan Wakely jwakely@redhat.com
Wed Aug 20 17:18:58 GMT 2025


On 04/08/25 12:59 +0200, Luc Grosheintz wrote:
>This commit implements and tests the function is_sufficiently_aligned
>from P2897R7.
>
>	PR libstdc++/120994
>
>libstdc++-v3/ChangeLog:
>
>	* include/bits/align.h (is_sufficiently_aligned): New function.
>	* include/bits/version.def (is_sufficiently_aligned): Add.
>	* include/bits/version.h: Regenerate.
>	* include/std/memory: Add __glibcxx_want_is_sufficiently_aligned.
>	* src/c++23/std.cc.in (is_sufficiently_aligned): Add.
>	* testsuite/20_util/headers/memory/version.cc: Add test for
>	__cpp_lib_is_sufficiently_aligned.
>	* testsuite/20_util/is_sufficiently_aligned/1.cc: New test.
>
>Signed-off-by: Luc Grosheintz <luc.grosheintz@gmail.com>
>---
> libstdc++-v3/include/bits/align.h             | 16 ++++++++++
> libstdc++-v3/include/bits/version.def         |  8 +++++
> libstdc++-v3/include/bits/version.h           | 10 ++++++
> libstdc++-v3/include/std/memory               |  1 +
> libstdc++-v3/src/c++23/std.cc.in              |  1 +
> .../20_util/headers/memory/version.cc         |  4 +++
> .../20_util/is_sufficiently_aligned/1.cc      | 31 +++++++++++++++++++
> 7 files changed, 71 insertions(+)
> create mode 100644 libstdc++-v3/testsuite/20_util/is_sufficiently_aligned/1.cc
>
>diff --git a/libstdc++-v3/include/bits/align.h b/libstdc++-v3/include/bits/align.h
>index 2b40c37e033..fbbe9cb1f9c 100644
>--- a/libstdc++-v3/include/bits/align.h
>+++ b/libstdc++-v3/include/bits/align.h
>@@ -102,6 +102,22 @@ align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept
>     }
> #endif // __glibcxx_assume_aligned
>
>+#ifdef __glibcxx_is_sufficiently_aligned // C++ >= 26
>+  /** @brief Is @a __ptr aligned to an _Align byte boundary?

I would prefer if this used Markdown instead of @a, i.e. `__ptr` 

That's easier to read in the source, and has the same result in the
generated HTML docs.

>+   *
>+   *  @tparam _Align An alignment value
>+   *  @tparam _Tp    An object type
>+   *
>+   *  C++26 20.2.5 [ptr.align]
>+   *
>+   *  @ingroup memory
>+   */
>+  template<size_t _Align, class _Tp>

I think we want `[[nodiscard]]` and `inline` here.

>+    bool
>+    is_sufficiently_aligned(_Tp* __ptr)
>+    { return reinterpret_cast<__UINTPTR_TYPE__>(__ptr) % _Align == 0; }
>+#endif // __glibcxx_is_sufficiently_aligned
>+
> _GLIBCXX_END_NAMESPACE_VERSION
> } // namespace
>
>diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
>index e9830d9d685..56ad9ee9d4b 100644
>--- a/libstdc++-v3/include/bits/version.def
>+++ b/libstdc++-v3/include/bits/version.def
>@@ -732,6 +732,14 @@ ftms = {
>   };
> };
>
>+ftms = {
>+  name = is_sufficiently_aligned;
>+  values = {
>+    v = 202411;
>+    cxxmin = 26;
>+  };
>+};
>+
> ftms = {
>   name = atomic_flag_test;
>   values = {
>diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
>index 59b0cfa1f92..51805d292f0 100644
>--- a/libstdc++-v3/include/bits/version.h
>+++ b/libstdc++-v3/include/bits/version.h
>@@ -815,6 +815,16 @@
> #endif /* !defined(__cpp_lib_assume_aligned) && defined(__glibcxx_want_assume_aligned) */
> #undef __glibcxx_want_assume_aligned
>
>+#if !defined(__cpp_lib_is_sufficiently_aligned)
>+# if (__cplusplus >  202302L)
>+#  define __glibcxx_is_sufficiently_aligned 202411L
>+#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_sufficiently_aligned)
>+#   define __cpp_lib_is_sufficiently_aligned 202411L
>+#  endif
>+# endif
>+#endif /* !defined(__cpp_lib_is_sufficiently_aligned) && defined(__glibcxx_want_is_sufficiently_aligned) */
>+#undef __glibcxx_want_is_sufficiently_aligned
>+
> #if !defined(__cpp_lib_atomic_flag_test)
> # if (__cplusplus >= 202002L)
> #  define __glibcxx_atomic_flag_test 201907L
>diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory
>index 763a57ee998..bc59622dba8 100644
>--- a/libstdc++-v3/include/std/memory
>+++ b/libstdc++-v3/include/std/memory
>@@ -110,6 +110,7 @@
> #define __glibcxx_want_constexpr_memory
> #define __glibcxx_want_enable_shared_from_this
> #define __glibcxx_want_indirect
>+#define __glibcxx_want_is_sufficiently_aligned
> #define __glibcxx_want_make_unique
> #define __glibcxx_want_out_ptr
> #define __glibcxx_want_parallel_algorithm
>diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
>index 6d7f3fda060..24411476ba0 100644
>--- a/libstdc++-v3/src/c++23/std.cc.in
>+++ b/libstdc++-v3/src/c++23/std.cc.in
>@@ -1874,6 +1874,7 @@ export namespace std
>   using std::allocator_arg_t;
>   using std::allocator_traits;
>   using std::assume_aligned;

This should be guarded with:

#ifdef __glibcxx_is_sufficiently_aligned

so that the std.cc.in file can be compiled as C++20 and C++23.

>+  using std::is_sufficiently_aligned;
>   using std::make_obj_using_allocator;
>   using std::pointer_traits;
>   using std::to_address;
>diff --git a/libstdc++-v3/testsuite/20_util/headers/memory/version.cc b/libstdc++-v3/testsuite/20_util/headers/memory/version.cc
>index 946955dd212..5366a5dce8a 100644
>--- a/libstdc++-v3/testsuite/20_util/headers/memory/version.cc
>+++ b/libstdc++-v3/testsuite/20_util/headers/memory/version.cc
>@@ -10,3 +10,7 @@
> #if __cpp_lib_addressof_constexpr != 201603L
> # error "Feature-test macro __cpp_lib_addressof_constexpr has wrong value in <version>"
> #endif
>+
>+#if __cplusplus > 202302L && __cpp_lib_is_sufficiently_aligned != 202411L
>+# error "Feature-test macro __cpp_lib_is_sufficiently_aligned has wrong value in <version>"
>+#endif
>diff --git a/libstdc++-v3/testsuite/20_util/is_sufficiently_aligned/1.cc b/libstdc++-v3/testsuite/20_util/is_sufficiently_aligned/1.cc
>new file mode 100644
>index 00000000000..4c2738b57db
>--- /dev/null
>+++ b/libstdc++-v3/testsuite/20_util/is_sufficiently_aligned/1.cc
>@@ -0,0 +1,31 @@
>+// { dg-do run { target c++26 } }
>+
>+#include <memory>
>+#include <array>
>+#include <testsuite_hooks.h>
>+
>+void
>+test01()
>+{
>+  constexpr size_t N = 4;
>+  constexpr size_t M = 2*N + 1;
>+  alignas(N) std::array<char, M> buffer{};
>+
>+  auto* ptr = buffer.data();
>+  VERIFY(std::is_sufficiently_aligned<1>(ptr+0));
>+  VERIFY(std::is_sufficiently_aligned<1>(ptr+1));
>+
>+  VERIFY(std::is_sufficiently_aligned<2>(ptr+0));
>+  VERIFY(!std::is_sufficiently_aligned<2>(ptr+1));
>+  VERIFY(std::is_sufficiently_aligned<2>(ptr+2));
>+
>+  for (size_t i = 0; i < M; ++i)
>+    VERIFY(std::is_sufficiently_aligned<N>(ptr + i) == (i % N == 0));
>+}
>+
>+int
>+main()
>+{
>+  test01();
>+  return 0;
>+}
>-- 
>2.50.0
>
>



More information about the Libstdc++ mailing list