On Thu, Jul 3, 2025 at 12:36 PM Luc Grosheintz <luc.groshei...@gmail.com> wrote:
> This commit implements and tests the function is_sufficiently_aligned > from P2897R7. > > 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/is_sufficiently_aligned/1.cc: New test. > * testsuite/20_util/is_sufficiently_aligned/2.cc: New test. > --- > Only one small suggestion on placement of the tests. Otherwise it looks good. > 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/is_sufficiently_aligned/1.cc | 31 +++++++++++++++++++ > .../20_util/is_sufficiently_aligned/2.cc | 7 +++++ > 7 files changed, 74 insertions(+) > create mode 100644 > libstdc++-v3/testsuite/20_util/is_sufficiently_aligned/1.cc > create mode 100644 > libstdc++-v3/testsuite/20_util/is_sufficiently_aligned/2.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? > + * > + * @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> > + 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 f4ba501c403..a2695e67716 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 dc8ac07be16..1b17a965239 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 1da03b3ea6a..ff342ff35f3 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 e692caaa5f9..6f4214ed3a7 100644 > --- a/libstdc++-v3/src/c++23/std.cc.in > +++ b/libstdc++-v3/src/c++23/std.cc.in > @@ -1864,6 +1864,7 @@ export namespace std > using std::allocator_arg_t; > using std::allocator_traits; > using std::assume_aligned; > + 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/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; > +} > diff --git a/libstdc++-v3/testsuite/20_util/is_sufficiently_aligned/2.cc > b/libstdc++-v3/testsuite/20_util/is_sufficiently_aligned/2.cc > new file mode 100644 > index 00000000000..8e0f4c07661 > --- /dev/null > +++ b/libstdc++-v3/testsuite/20_util/is_sufficiently_aligned/2.cc > @@ -0,0 +1,7 @@ > +// { dg-do compile { target c++26 } } > + > +#include <memory> > + > +#ifndef __cpp_lib_is_sufficiently_aligned > +#error "Missing FTM" > +#endif > I would integrate that into 1.cc file directly. I do not think we need a separate test. > -- > 2.49.0 > >