Commit ccb206fc authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Add FOLLY_HAS_BUILTIN and use it

Summary:
[Folly] Add `FOLLY_HAS_BUILTIN` and use it.

Use it in the definition of `folly::launder`. Of course, since GCC does not have `__has_builtin`, we still have to check its version.

Reviewed By: WillerZ

Differential Revision: D5496748

fbshipit-source-id: 3bd6e89424dfd2c9cb9795ee4d88f66c4294cc4c
parent c815830f
...@@ -45,6 +45,12 @@ ...@@ -45,6 +45,12 @@
# endif # endif
#endif #endif
#if defined(__has_builtin)
#define FOLLY_HAS_BUILTIN(...) __has_builtin(__VA_ARGS__)
#else
#define FOLLY_HAS_BUILTIN(...) 0
#endif
/* Define a convenience macro to test when address sanitizer is being used /* Define a convenience macro to test when address sanitizer is being used
* across the different compilers (e.g. clang, gcc) */ * across the different compilers (e.g. clang, gcc) */
#if defined(__clang__) #if defined(__clang__)
......
...@@ -16,44 +16,31 @@ ...@@ -16,44 +16,31 @@
#pragma once #pragma once
#include <folly/CPortability.h>
#include <folly/Portability.h> #include <folly/Portability.h>
namespace folly { namespace folly {
#ifdef __GNUC__
#ifdef __has_builtin
#if __has_builtin(__builtin_launder)
#define FOLLY_USE_BUILTIN_LAUNDER 1
#endif
#endif
#endif
/** /**
* Approximate backport from C++17 of std::launder. It should be `constexpr` * Approximate backport from C++17 of std::launder. It should be `constexpr`
* but that can't be done without specific support from the compiler. * but that can't be done without specific support from the compiler.
*/ */
template <typename T> template <typename T>
FOLLY_NODISCARD inline T* launder(T* in) noexcept { FOLLY_NODISCARD inline T* launder(T* in) noexcept {
#ifdef __GNUC__ #if FOLLY_HAS_BUILTIN(__builtin_launder) || __GNUC__ >= 7
#ifdef FOLLY_USE_BUILTIN_LAUNDER // The builtin has no unwanted side-effects.
// Newer GCC versions have a builtin for this with no unwanted side-effects
return __builtin_launder(in); return __builtin_launder(in);
#else #elif __GNUC__
// This inline assembler block declares that `in` is an input and an output, // This inline assembler block declares that `in` is an input and an output,
// so the compiler has to assume that it has been changed inside the block. // so the compiler has to assume that it has been changed inside the block.
__asm__("" : "+r"(in)); __asm__("" : "+r"(in));
return in; return in;
#endif
#else #else
static_assert( static_assert(
false, "folly::launder is not implemented for this environment"); false, "folly::launder is not implemented for this environment");
#endif #endif
} }
#ifdef FOLLY_USE_BUILTIN_LAUNDER
#undef FOLLY_USE_BUILTIN_LAUNDER
#endif
/* The standard explicitly forbids laundering these */ /* The standard explicitly forbids laundering these */
void launder(void*) = delete; void launder(void*) = delete;
void launder(void const*) = delete; void launder(void const*) = delete;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment