mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
libstdc++: Simplify std::launder definition
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.
This commit is contained in:
committed by
Jonathan Wakely
parent
9fe57e4879
commit
27c985b774
@@ -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
|
||||
|
||||
|
||||
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user