[PATCH 2/2] libstdc++: Simplify std::launder definition
Jonathan Wakely
jwakely@redhat.com
Thu Sep 12 08:49:46 GMT 2024
Tested x86_64-linux.
Both GCC and Clang support the __is_function built-in, so we should get
the static_assert here. For a compiler that doesn't support it, we rely
on __builtin_launder to diagnose function pointers. That's true for
Clang, and PATCH 1/2 makes it true for G++.
We might want to consider splitting a frequently-used subset of
<type_traits> into a new <bits/...> header that we can include in <new>.
Nearly every header outside of libsupc++ includes <type_traits>, but
they don't all need all of it.
-- >8 --
A single static assert is a much simpler way to implement the
compile-time preconditions on std::launder than an overload set of
deleted functions and function templates. The only difficulty is that
<new> doesn't include <type_traits> so we can't use std::is_function and
std::is_void for the checks. That can be worked around though, by using
the __is_same and __is_function built-ins. If the __is_function built-in
isn't supported then the __builtin_launder built-in will give an error
anyway, since the commit preceding this one.
We can also remove the redundant __cplusplus >= 201703L check around the
definitions of std::launder and the interference constants, which are
already guarded by the appropriate feature test macros.
libstdc++-v3/ChangeLog:
* libsupc++/new (launder): Add static_assert and remove deleted
overloads.
* testsuite/18_support/launder/requirements_neg.cc: Adjust
expected diagnostics.
---
libstdc++-v3/libsupc++/new | 36 ++++++++-----------
.../18_support/launder/requirements_neg.cc | 15 ++++----
2 files changed, 24 insertions(+), 27 deletions(-)
diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index 2e2038e1a82..af5c7690bb9 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -198,7 +198,6 @@ inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { }
//@}
} // extern "C++"
-#if __cplusplus >= 201703L
namespace std
{
#ifdef __cpp_lib_launder // C++ >= 17 && HAVE_BUILTIN_LAUNDER
@@ -206,33 +205,28 @@ namespace std
template<typename _Tp>
[[nodiscard]] constexpr _Tp*
launder(_Tp* __p) noexcept
- { return __builtin_launder(__p); }
-
- // The program is ill-formed if T is a function type or
- // (possibly cv-qualified) void.
-
- template<typename _Ret, typename... _Args _GLIBCXX_NOEXCEPT_PARM>
- void launder(_Ret (*)(_Args...) _GLIBCXX_NOEXCEPT_QUAL) = delete;
- template<typename _Ret, typename... _Args _GLIBCXX_NOEXCEPT_PARM>
- void launder(_Ret (*)(_Args......) _GLIBCXX_NOEXCEPT_QUAL) = delete;
-
- void launder(void*) = delete;
- void launder(const void*) = delete;
- void launder(volatile void*) = delete;
- void launder(const volatile void*) = delete;
+ {
+ if constexpr (__is_same(const volatile _Tp, const volatile void))
+ static_assert(!__is_same(const volatile _Tp, const volatile void),
+ "std::launder argument must not be a void pointer");
+#if _GLIBCXX_USE_BUILTIN_TRAIT(__is_function)
+ else if constexpr (__is_function(_Tp))
+ static_assert(!__is_function(_Tp),
+ "std::launder argument must not be a function pointer");
+#endif
+ else
+ return __builtin_launder(__p);
+ return nullptr;
+ }
#endif // __cpp_lib_launder
#ifdef __cpp_lib_hardware_interference_size // C++ >= 17 && defined(gcc_dest_sz)
inline constexpr size_t hardware_destructive_interference_size = __GCC_DESTRUCTIVE_SIZE;
inline constexpr size_t hardware_constructive_interference_size = __GCC_CONSTRUCTIVE_SIZE;
#endif // __cpp_lib_hardware_interference_size
-}
-#endif // C++17
// Emitted despite the FTM potentially being undefined.
-#if __cplusplus > 201703L
-namespace std
-{
+#if __cplusplus >= 202002L
/// Tag type used to declare a class-specific operator delete that can
/// invoke the destructor before deallocating the memory.
struct destroying_delete_t
@@ -241,8 +235,8 @@ namespace std
};
/// Tag variable of type destroying_delete_t.
inline constexpr destroying_delete_t destroying_delete{};
-}
#endif // C++20
+}
#pragma GCC visibility pop
diff --git a/libstdc++-v3/testsuite/18_support/launder/requirements_neg.cc b/libstdc++-v3/testsuite/18_support/launder/requirements_neg.cc
index 2808ebf614d..82ce0b35a8c 100644
--- a/libstdc++-v3/testsuite/18_support/launder/requirements_neg.cc
+++ b/libstdc++-v3/testsuite/18_support/launder/requirements_neg.cc
@@ -25,14 +25,17 @@ int f2(const char*, ...);
void
test01()
{
- std::launder( &f1 ); // { dg-error "deleted function" }
- std::launder( &f2 ); // { dg-error "deleted function" }
+ std::launder( &f1 ); // { dg-error "here" }
+ std::launder( &f2 ); // { dg-error "here" }
void* p = nullptr;
- std::launder( p ); // { dg-error "deleted function" }
+ std::launder( p ); // { dg-error "here" }
const void* cp = nullptr;
- std::launder( cp ); // { dg-error "deleted function" }
+ std::launder( cp ); // { dg-error "here" }
volatile void* vp = nullptr;
- std::launder( vp ); // { dg-error "deleted function" }
+ std::launder( vp ); // { dg-error "here" }
const volatile void* cvp = nullptr;
- std::launder( cvp ); // { dg-error "deleted function" }
+ std::launder( cvp ); // { dg-error "here" }
}
+// { dg-error "std::launder argument must not be a void pointer" "" { target *-*-* } 0 }
+// { dg-error "std::launder argument must not be a function pointer" "" { target *-*-* } 0 }
+// { dg-warning "ignoring return value" "nodiscard" { target *-*-* } 0 }
--
2.46.0
More information about the Libstdc++
mailing list