[PATCH v1 1/3] libstdc++: Implement is_sufficiently_aligned.

Luc Grosheintz luc.grosheintz@gmail.com
Thu Jul 17 09:04:41 GMT 2025



On 7/8/25 16:56, Tomasz Kaminski wrote:
> On Thu, Jul 3, 2025 at 12:36 PM Luc Grosheintz <luc.grosheintz@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. It's use of dejagnu is
neat too:

// { dg-do preprocess { target c++17 } }
// { dg-add-options no_pch }

Now I'm tempted to adjust mdspan/version.cc accordingly.

> 
>> --
>> 2.49.0
>>
>>
> 



More information about the Libstdc++ mailing list