Improve launder
authorPhil Willoughby <philwill@fb.com>
Wed, 12 Jul 2017 07:36:17 +0000 (00:36 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Wed, 12 Jul 2017 07:53:49 +0000 (00:53 -0700)
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

folly/Launder.h [new file with mode: 0644]
folly/Makefile.am
folly/Utility.h
folly/test/LaunderTest.cpp [new file with mode: 0644]

diff --git a/folly/Launder.h b/folly/Launder.h
new file mode 100644 (file)
index 0000000..2f9c47b
--- /dev/null
@@ -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 <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
index fdd23e640dc90cb941dc64a2434ccef309c761b6..36b703feaba46f9cf1311b5f86b12dd1c119037b 100644 (file)
@@ -291,6 +291,7 @@ nobase_follyinclude_HEADERS = \
        io/async/test/Util.h \
        Iterator.h \
        json.h \
        io/async/test/Util.h \
        Iterator.h \
        json.h \
+       Launder.h \
        Lazy.h \
        LifoSem.h \
        Likely.h \
        Lazy.h \
        LifoSem.h \
        Likely.h \
index dbe552f02aac940b79c34b2708ae18e4c4201d75..a9934e8d499a53f872f491821fcf1174d1822753 100644 (file)
@@ -259,12 +259,4 @@ class MoveOnly {
 } // namespace moveonly_
 
 using MoveOnly = moveonly_::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
 } // namespace folly
diff --git a/folly/test/LaunderTest.cpp b/folly/test/LaunderTest.cpp
new file mode 100644 (file)
index 0000000..fb33c98
--- /dev/null
@@ -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 <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)));
+}