On Thu, 17 Jul 2025 at 10:05, Luc Grosheintz <luc.groshei...@gmail.com> wrote: > > > > On 7/8/25 16:56, Tomasz Kaminski wrote: > > 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. > > Now I know they're called version.cc it's easier to find others. There's > > testsuite/20_util/headers/memory/version.cc > > which checks: > > __cpp_lib_allocator_traits_is_always_equal > __cpp_lib_addressof_constexpr > > That feels like the place to also put this one.
Yes, that makes sense. > It's use of dejagnu is > neat too: > > // { dg-do preprocess { target c++17 } } The 'preprocess' does what you'd expect, it stops after preprocessing (so doesn't bother doing any of compiling and assembling and linking and running): https://gcc.gnu.org/onlinedocs/gccint/Directives.html#Specify-how-to-build-the-test By default this test will only be tested with -std=gnu++17 but people who run the testsuite with additional/different -std options can test it for -std=c++26: https://gcc.gnu.org/onlinedocs/libstdc++/manual/test.html#test.run.permutations If we really want to be sure the new macro is *always* tested by everybody running the tests, it needs to be a separate file with { target c++26 } so that the testsuite chooses -std=gnu++26 for it. So that's an argument against checking the new macro in the existing headers/memory/version.cc file. I don't feel strongly about it though, because I test everything with every -std option several times a day, and as long as *somebody* is doing that, we'll know it works. And one day in the future -std=gnu++26 will be the default for all tests anyway (but that's years away). > // { dg-add-options no_pch } This prevents the test harness from adding an implicit -include bits/stdc++.h which includes every libstdc++ header at the very start of the file. If the test just wants to check that the macro is defined by <memory> then including every other header first would not test what you want to test! The definition of no_pch is in testsuite/lib/dg-options.exp > > Now I'm tempted to adjust mdspan/version.cc accordingly. > > > > >> -- > >> 2.49.0 > >> > >> > > >