[committed] libstdc++: Define std::is_pointer_interconvertible_base_of for C++20

Jonathan Wakely jwakely@redhat.com
Wed Aug 11 16:00:12 GMT 2021


Implement these traits using the new built-ins that Jakub added
recently.

Signed-off-by: Jonathan Wakely <jwakely@redhat.com>

libstdc++-v3/ChangeLog:

	* include/std/type_traits (__cpp_lib_is_pointer_interconvertible)
	(is_pointer_interconvertible_base_of_v)
	(is_pointer_interconvertible_base_of): Define for C++20.
	* include/std/version (__cpp_lib_is_pointer_interconvertible):
	Define.
	* testsuite/23_containers/span/layout_compat.cc: Use correct
	feature test macro for std::is_layout_compatible_v.
	* testsuite/20_util/is_pointer_interconvertible/value.cc: New test.
	* testsuite/20_util/is_pointer_interconvertible/version.cc: New test.

Tested powerpc64le-linux. Committed to trunk.

-------------- next part --------------
commit 4fa6c0ec350bb4a8dd52a7c6f9881ab427151588
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Aug 10 15:37:23 2021

    libstdc++: Define std::is_pointer_interconvertible_base_of for C++20
    
    Implement these traits using the new built-ins that Jakub added
    recently.
    
    Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
    
    libstdc++-v3/ChangeLog:
    
            * include/std/type_traits (__cpp_lib_is_pointer_interconvertible)
            (is_pointer_interconvertible_base_of_v)
            (is_pointer_interconvertible_base_of): Define for C++20.
            * include/std/version (__cpp_lib_is_pointer_interconvertible):
            Define.
            * testsuite/23_containers/span/layout_compat.cc: Use correct
            feature test macro for std::is_layout_compatible_v.
            * testsuite/20_util/is_pointer_interconvertible/value.cc: New test.
            * testsuite/20_util/is_pointer_interconvertible/version.cc: New test.

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 46edde905f8..2be4944e2a6 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -3389,6 +3389,33 @@ template<typename _Ret, typename _Fn, typename... _Args>
     inline constexpr bool is_unbounded_array_v
       = is_unbounded_array<_Tp>::value;
 
+#if __has_builtin(__is_pointer_interconvertible_base_of)
+  /// True if `_Derived` is standard-layout and has a base class of type `_Base`
+  /// @since C++20
+  template<typename _Base, typename _Derived>
+    struct is_pointer_interconvertible_base_of
+    : bool_constant<__is_pointer_interconvertible_base_of(_Base, _Derived)>
+    { };
+
+  /// @ingroup variable_templates
+  /// @since C++20
+  template<typename _Base, typename _Derived>
+    constexpr bool is_pointer_interconvertible_base_of_v
+      = __is_pointer_interconvertible_base_of(_Base, _Derived);
+
+#if __has_builtin(__builtin_is_pointer_interconvertible_with_class)
+#define __cpp_lib_is_pointer_interconvertible 201907L
+
+  /// True if `__mp` points to the first member of a standard-layout type
+  /// @returns true if `s.*__mp` is pointer-interconvertible with `s`
+  /// @since C++20
+  template<typename _Tp, typename _Mem>
+    constexpr bool
+    is_pointer_interconvertible_with_class(_Mem _Tp::*__mp) noexcept
+    { return __builtin_is_pointer_interconvertible_with_class(__mp); }
+#endif
+#endif
+
 #if __cplusplus > 202002L
 #define __cpp_lib_is_scoped_enum 202011L
 
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index d5fa38d7786..925f27704c4 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -236,6 +236,10 @@
 #ifdef _GLIBCXX_HAS_GTHREADS
 # define __cpp_lib_jthread 201911L
 #endif
+#if __has_builtin(__is_pointer_interconvertible_base_of) \
+ && __has_builtin(__builtin_is_pointer_interconvertible_with_class)
+# define __cpp_lib_is_pointer_interconvertible 201907L
+#endif
 #if __cpp_lib_atomic_wait
 # define __cpp_lib_latch 201907L
 #endif
diff --git a/libstdc++-v3/testsuite/20_util/is_pointer_interconvertible/value.cc b/libstdc++-v3/testsuite/20_util/is_pointer_interconvertible/value.cc
new file mode 100644
index 00000000000..471571cac58
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_pointer_interconvertible/value.cc
@@ -0,0 +1,51 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+#include <type_traits>
+
+#ifndef __cpp_lib_is_pointer_interconvertible
+# error "Feature test macro for is_pointer_interconvertible is missing in <type_traits>"
+#elif __cpp_lib_is_pointer_interconvertible < 201907L
+# error "Feature test macro for is_pointer_interconvertible has wrong value in <type_traits>"
+#endif
+
+static_assert( std::is_pointer_interconvertible_base_of<void, void>::value
+		== std::is_pointer_interconvertible_base_of_v<void, void> );
+
+struct B { };
+
+static_assert( std::is_pointer_interconvertible_base_of<B, B>::value
+		== std::is_pointer_interconvertible_base_of_v<B, B> );
+
+static_assert( std::is_pointer_interconvertible_base_of_v<B, B> );
+static_assert( std::is_pointer_interconvertible_base_of_v<B, const B> );
+static_assert( std::is_pointer_interconvertible_base_of_v<const B, B> );
+static_assert( std::is_pointer_interconvertible_base_of_v<const B, const B> );
+
+struct D : B { int i; };
+
+static_assert( std::is_pointer_interconvertible_base_of_v<D, D> );
+
+static_assert( std::is_pointer_interconvertible_base_of_v<B, D> );
+static_assert( std::is_pointer_interconvertible_base_of_v<const B, D> );
+static_assert( std::is_pointer_interconvertible_base_of_v<B, const D> );
+static_assert( std::is_pointer_interconvertible_base_of_v<const B, const D> );
+
+static_assert( ! std::is_pointer_interconvertible_base_of_v<D, B> );
+
+struct E : D { };
+// E is not standard-layout
+static_assert( ! std::is_pointer_interconvertible_base_of_v<E, B> );
+
+struct D1 : B { };
+struct D2 : B { };
+struct D3 : D1, D2 { };
+// B is ambiguously derived
+static_assert( ! std::is_pointer_interconvertible_base_of_v<B, D3> );
+
+union U;
+static_assert( ! std::is_pointer_interconvertible_base_of_v<U, U> );
+static_assert( ! std::is_pointer_interconvertible_base_of_v<U, D> );
+
+struct I; // incomplete
+static_assert( std::is_pointer_interconvertible_base_of_v<I, I> );
+static_assert( std::is_pointer_interconvertible_base_of_v<I, const I> );
diff --git a/libstdc++-v3/testsuite/20_util/is_pointer_interconvertible/version.cc b/libstdc++-v3/testsuite/20_util/is_pointer_interconvertible/version.cc
new file mode 100644
index 00000000000..138c4be9f93
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_pointer_interconvertible/version.cc
@@ -0,0 +1,10 @@
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
+
+#include <version>
+
+#ifndef __cpp_lib_is_pointer_interconvertible
+# error "Feature test macro for is_pointer_interconvertible is missing in <version>"
+#elif __cpp_lib_is_pointer_interconvertible < 201907L
+# error "Feature test macro for is_pointer_interconvertible has wrong value in <version>"
+#endif
diff --git a/libstdc++-v3/testsuite/23_containers/span/layout_compat.cc b/libstdc++-v3/testsuite/23_containers/span/layout_compat.cc
index 7959aa76633..04947e93dbc 100644
--- a/libstdc++-v3/testsuite/23_containers/span/layout_compat.cc
+++ b/libstdc++-v3/testsuite/23_containers/span/layout_compat.cc
@@ -27,7 +27,7 @@
 struct iovec { void* iov_base; std::size_t iov_len; };
 #endif
 
-#if __cpp_lib_is_pointer_interconvertible
+#if __cpp_lib_is_layout_compatible
 using std::is_layout_compatible_v;
 #else
 // A poor substitute for is_layout_compatible_v


More information about the Libstdc++ mailing list