Commit fccb5ab6 authored by Phil Willoughby's avatar Phil Willoughby Committed by Facebook Github Bot

Improve launder

Summary:
Should now work on GCC-compatible compilers, and all other compilers which don't attempt any inter-TU optimizations.

Moved out of Utility.h because it now requires a supporting .cpp file and some clients presume that Utility.h can be used header-only.

Reviewed By: ot

Differential Revision: D5381042

fbshipit-source-id: 7e954fed47de4386c85d46a61d56a8fe7fc516f4
parent dcb41c96
/*
* Copyright 2017-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <folly/Portability.h>
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`
* but that can't be done without specific support from the compiler.
*/
template <typename T>
FOLLY_NODISCARD inline T* launder(T* in) noexcept {
#ifdef __GNUC__
#ifdef FOLLY_USE_BUILTIN_LAUNDER
// Newer GCC versions have a builtin for this with no unwanted side-effects
return __builtin_launder(in);
#else
// 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.
__asm__("" : "+r"(in));
return in;
#endif
#else
static_assert(
false, "folly::launder is not implemented for this environment");
#endif
}
#ifdef FOLLY_USE_BUILTIN_LAUNDER
#undef FOLLY_USE_BUILTIN_LAUNDER
#endif
/* The standard explicitly forbids laundering these */
void launder(void*) = delete;
void launder(void const*) = delete;
void launder(void volatile*) = delete;
void launder(void const volatile*) = delete;
template <typename T, typename... Args>
void launder(T (*)(Args...)) = delete;
} // namespace folly
......@@ -291,6 +291,7 @@ nobase_follyinclude_HEADERS = \
io/async/test/Util.h \
Iterator.h \
json.h \
Launder.h \
Lazy.h \
LifoSem.h \
Likely.h \
......
......@@ -259,12 +259,4 @@ class MoveOnly {
} // namespace moveonly_
using MoveOnly = moveonly_::MoveOnly;
/**
* Backport from C++17 of std::launder
*/
template <typename T>
constexpr T* launder(T* in) {
return (in + 1) - 1;
}
} // namespace folly
/*
* Copyright 2017-present Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/Launder.h>
#include <folly/portability/GTest.h>
using namespace ::testing;
using namespace folly;
TEST(LaunderTest, Basics) {
int a;
int* pa = &a;
EXPECT_EQ(pa, launder(pa));
EXPECT_TRUE(noexcept(launder(pa)));
}
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