From: Phil Willoughby Date: Wed, 12 Jul 2017 07:36:17 +0000 (-0700) Subject: Improve launder X-Git-Tag: v2017.07.17.00~20 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=fccb5ab622df7c7c572be2daf1fe5aa5f8e9604c;hp=dcb41c967151be259a189401bccf56b0c6591b1c 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 --- diff --git a/folly/Launder.h b/folly/Launder.h new file mode 100644 index 00000000..2f9c47b8 --- /dev/null +++ b/folly/Launder.h @@ -0,0 +1,64 @@ +/* + * 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 + +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 +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 +void launder(T (*)(Args...)) = delete; +} // namespace folly diff --git a/folly/Makefile.am b/folly/Makefile.am index fdd23e64..36b703fe 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -291,6 +291,7 @@ nobase_follyinclude_HEADERS = \ io/async/test/Util.h \ Iterator.h \ json.h \ + Launder.h \ Lazy.h \ LifoSem.h \ Likely.h \ diff --git a/folly/Utility.h b/folly/Utility.h index dbe552f0..a9934e8d 100644 --- a/folly/Utility.h +++ b/folly/Utility.h @@ -259,12 +259,4 @@ class MoveOnly { } // namespace moveonly_ using MoveOnly = moveonly_::MoveOnly; - -/** - * Backport from C++17 of std::launder - */ -template -constexpr T* launder(T* in) { - return (in + 1) - 1; -} } // namespace folly diff --git a/folly/test/LaunderTest.cpp b/folly/test/LaunderTest.cpp new file mode 100644 index 00000000..fb33c98a --- /dev/null +++ b/folly/test/LaunderTest.cpp @@ -0,0 +1,28 @@ +/* + * 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 +#include + +using namespace ::testing; +using namespace folly; + +TEST(LaunderTest, Basics) { + int a; + int* pa = &a; + EXPECT_EQ(pa, launder(pa)); + EXPECT_TRUE(noexcept(launder(pa))); +}