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.groshei...@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



Reply via email to