[libcxx-commits] [libcxx] [libc++] Implement LWG4290: Missing Mandates clauses on is_sufficiently_aligned (PR #229765)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Oct 8 08:04:47 PDT 2026


https://github.com/KaroliShp updated https://github.com/llvm/llvm-project/pull/229765

>From accffea988f6fc4f9a23e585f89225d1738ddd17 Mon Sep 17 00:00:00 2001
From: Karolis <karolis.spukas at gmail.com>
Date: Wed, 7 Oct 2026 13:17:10 +0100
Subject: [PATCH 1/3] [libc++] Implement LWG4290: Missing Mandates clauses on
 is_sufficiently_aligned

---
 libcxx/docs/Status/Cxx26Issues.csv            |  2 +-
 .../__memory/is_sufficiently_aligned.h        |  3 ++
 .../is_sufficiently_aligned.power2.verify.cpp | 28 +++++++++++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)
 create mode 100644 libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp

diff --git a/libcxx/docs/Status/Cxx26Issues.csv b/libcxx/docs/Status/Cxx26Issues.csv
index 7cb257a49c30f..9f2a8edbde8c9 100644
--- a/libcxx/docs/Status/Cxx26Issues.csv
+++ b/libcxx/docs/Status/Cxx26Issues.csv
@@ -278,7 +278,7 @@
 "`LWG4151 <https://wg21.link/LWG4151>`__","Precondition of ``inplace_vector::swap``","2026-03 (Croydon)","","","`#189820 <https://github.com/llvm/llvm-project/issues/189820>`__",""
 "`LWG4223 <https://wg21.link/LWG4223>`__","Deduction guides for maps are mishandling tuples and references","2026-03 (Croydon)","","","`#189821 <https://github.com/llvm/llvm-project/issues/189821>`__",""
 "`LWG4259 <https://wg21.link/LWG4259>`__","P1148R0 changed the return values of searching functions of ``std::basic_string`` on some platforms","2026-03 (Croydon)","","","`#189822 <https://github.com/llvm/llvm-project/issues/189822>`__",""
-"`LWG4290 <https://wg21.link/LWG4290>`__","Missing *Mandates* clauses on ``is_sufficiently_aligned``","2026-03 (Croydon)","","","`#189823 <https://github.com/llvm/llvm-project/issues/189823>`__",""
+"`LWG4290 <https://wg21.link/LWG4290>`__","Missing *Mandates* clauses on ``is_sufficiently_aligned``","2026-03 (Croydon)","|Complete|","24","`#189823 <https://github.com/llvm/llvm-project/issues/189823>`__",""
 "`LWG4314 <https://wg21.link/LWG4314>`__","Missing move in ``mdspan`` layout ``mapping::operator()``","2026-03 (Croydon)","","","`#189824 <https://github.com/llvm/llvm-project/issues/189824>`__",""
 "`LWG4324 <https://wg21.link/LWG4324>`__","``unique_ptr<void>::operator*`` is not SFINAE-friendly","2026-03 (Croydon)","|Complete|","23","`#189825 <https://github.com/llvm/llvm-project/issues/189825>`__",""
 "`LWG4325 <https://wg21.link/LWG4325>`__","``std::indirect``'s ``operator==`` still does not support incomplete types","2026-03 (Croydon)","","","`#189826 <https://github.com/llvm/llvm-project/issues/189826>`__",""
diff --git a/libcxx/include/__memory/is_sufficiently_aligned.h b/libcxx/include/__memory/is_sufficiently_aligned.h
index b8725880028db..923c502008835 100644
--- a/libcxx/include/__memory/is_sufficiently_aligned.h
+++ b/libcxx/include/__memory/is_sufficiently_aligned.h
@@ -22,6 +22,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <size_t _Alignment, class _Tp>
 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __is_sufficiently_aligned(_Tp* __ptr) {
+  static_assert(_Alignment != 0 && (_Alignment & (_Alignment - 1)) == 0,
+                "std::is_sufficiently_aligned<Alignment>(p) requires Alignment to be a power of two");
+
   return reinterpret_cast<uintptr_t>(__ptr) % _Alignment == 0;
 }
 
diff --git a/libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp b/libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp
new file mode 100644
index 0000000000000..76c015052babf
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+// #include <memory>
+
+// template<size_t Alignment, class T>
+//   bool is_sufficiently_aligned(T* ptr);
+
+#include <memory>
+
+void f() {
+  int* p = nullptr;
+  (void)std::is_sufficiently_aligned<0>(
+      p); // expected-error@*:* {{std::is_sufficiently_aligned<Alignment>(p) requires Alignment to be a power of two}}
+  (void)std::is_sufficiently_aligned<3>(
+      p); // expected-error@*:* {{std::is_sufficiently_aligned<Alignment>(p) requires Alignment to be a power of two}}
+  (void)std::is_sufficiently_aligned<5>(
+      p); // expected-error@*:* {{std::is_sufficiently_aligned<Alignment>(p) requires Alignment to be a power of two}}
+  (void)std::is_sufficiently_aligned<33>(
+      p); // expected-error@*:* {{std::is_sufficiently_aligned<Alignment>(p) requires Alignment to be a power of two}}
+}

>From 8a3c5cbc844a9885232e7040572696f242946043 Mon Sep 17 00:00:00 2001
From: Karolis <karolis.spukas at gmail.com>
Date: Thu, 8 Oct 2026 09:57:21 +0100
Subject: [PATCH 2/3] Address review comments: shorten static_assert message

---
 libcxx/include/__memory/is_sufficiently_aligned.h    |  3 +--
 .../is_sufficiently_aligned.power2.verify.cpp        | 12 ++++--------
 2 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/libcxx/include/__memory/is_sufficiently_aligned.h b/libcxx/include/__memory/is_sufficiently_aligned.h
index 923c502008835..61b77ae7b027f 100644
--- a/libcxx/include/__memory/is_sufficiently_aligned.h
+++ b/libcxx/include/__memory/is_sufficiently_aligned.h
@@ -22,8 +22,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <size_t _Alignment, class _Tp>
 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __is_sufficiently_aligned(_Tp* __ptr) {
-  static_assert(_Alignment != 0 && (_Alignment & (_Alignment - 1)) == 0,
-                "std::is_sufficiently_aligned<Alignment>(p) requires Alignment to be a power of two");
+  static_assert(_Alignment != 0 && (_Alignment & (_Alignment - 1)) == 0, "_Alignment should be a power of two.");
 
   return reinterpret_cast<uintptr_t>(__ptr) % _Alignment == 0;
 }
diff --git a/libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp b/libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp
index 76c015052babf..54bbde0500811 100644
--- a/libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp
+++ b/libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp
@@ -17,12 +17,8 @@
 
 void f() {
   int* p = nullptr;
-  (void)std::is_sufficiently_aligned<0>(
-      p); // expected-error@*:* {{std::is_sufficiently_aligned<Alignment>(p) requires Alignment to be a power of two}}
-  (void)std::is_sufficiently_aligned<3>(
-      p); // expected-error@*:* {{std::is_sufficiently_aligned<Alignment>(p) requires Alignment to be a power of two}}
-  (void)std::is_sufficiently_aligned<5>(
-      p); // expected-error@*:* {{std::is_sufficiently_aligned<Alignment>(p) requires Alignment to be a power of two}}
-  (void)std::is_sufficiently_aligned<33>(
-      p); // expected-error@*:* {{std::is_sufficiently_aligned<Alignment>(p) requires Alignment to be a power of two}}
+  (void)std::is_sufficiently_aligned<0>(p);  // expected-error@*:* {{_Alignment should be a power of two.}}
+  (void)std::is_sufficiently_aligned<3>(p);  // expected-error@*:* {{_Alignment should be a power of two.}}
+  (void)std::is_sufficiently_aligned<5>(p);  // expected-error@*:* {{_Alignment should be a power of two.}}
+  (void)std::is_sufficiently_aligned<33>(p); // expected-error@*:* {{_Alignment should be a power of two.}}
 }

>From a2a6cff34927a7c4a79eb5108c15a30f932d9520 Mon Sep 17 00:00:00 2001
From: Karolis <karolis.spukas at gmail.com>
Date: Thu, 8 Oct 2026 16:04:31 +0100
Subject: [PATCH 3/3] Address review comments: restrict to C++20 and use std
 has_single_bit

---
 libcxx/include/__memory/is_sufficiently_aligned.h     | 11 ++++++++---
 .../is_sufficiently_aligned.power2.verify.cpp         |  8 ++++----
 2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/libcxx/include/__memory/is_sufficiently_aligned.h b/libcxx/include/__memory/is_sufficiently_aligned.h
index 61b77ae7b027f..587710d7e3526 100644
--- a/libcxx/include/__memory/is_sufficiently_aligned.h
+++ b/libcxx/include/__memory/is_sufficiently_aligned.h
@@ -10,6 +10,7 @@
 #ifndef _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H
 #define _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H
 
+#include <__bit/has_single_bit.h>
 #include <__config>
 #include <__cstddef/size_t.h>
 #include <cstdint>
@@ -18,24 +19,28 @@
 #  pragma GCC system_header
 #endif
 
+#if _LIBCPP_STD_VER >= 20
+
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <size_t _Alignment, class _Tp>
 [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI bool __is_sufficiently_aligned(_Tp* __ptr) {
-  static_assert(_Alignment != 0 && (_Alignment & (_Alignment - 1)) == 0, "_Alignment should be a power of two.");
+  static_assert(std::has_single_bit(_Alignment), "alignment must be a power of two.");
 
   return reinterpret_cast<uintptr_t>(__ptr) % _Alignment == 0;
 }
 
-#if _LIBCPP_STD_VER >= 26
+#  if _LIBCPP_STD_VER >= 26
 
 template <size_t _Alignment, class _Tp>
 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool is_sufficiently_aligned(_Tp* __ptr) {
   return std::__is_sufficiently_aligned<_Alignment>(__ptr);
 }
 
-#endif // _LIBCPP_STD_VER >= 26
+#  endif // _LIBCPP_STD_VER >= 26
 
 _LIBCPP_END_NAMESPACE_STD
 
+#endif // _LIBCPP_STD_VER >= 20
+
 #endif // _LIBCPP___MEMORY_IS_SUFFICIENTLY_ALIGNED_H
diff --git a/libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp b/libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp
index 54bbde0500811..cde7aa38deb74 100644
--- a/libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp
+++ b/libcxx/test/libcxx/utilities/memory/ptr.align/is_sufficiently_aligned.power2.verify.cpp
@@ -17,8 +17,8 @@
 
 void f() {
   int* p = nullptr;
-  (void)std::is_sufficiently_aligned<0>(p);  // expected-error@*:* {{_Alignment should be a power of two.}}
-  (void)std::is_sufficiently_aligned<3>(p);  // expected-error@*:* {{_Alignment should be a power of two.}}
-  (void)std::is_sufficiently_aligned<5>(p);  // expected-error@*:* {{_Alignment should be a power of two.}}
-  (void)std::is_sufficiently_aligned<33>(p); // expected-error@*:* {{_Alignment should be a power of two.}}
+  (void)std::is_sufficiently_aligned<0>(p);  // expected-error@*:* {{alignment must be a power of two.}}
+  (void)std::is_sufficiently_aligned<3>(p);  // expected-error@*:* {{alignment must be a power of two.}}
+  (void)std::is_sufficiently_aligned<5>(p);  // expected-error@*:* {{alignment must be a power of two.}}
+  (void)std::is_sufficiently_aligned<33>(p); // expected-error@*:* {{alignment must be a power of two.}}
 }



More information about the libcxx-commits mailing list