Fix folly::max_align_v for Clang on ARMv7
authorYedidya Feldblum <yfeldblum@fb.com>
Fri, 15 Dec 2017 07:26:47 +0000 (23:26 -0800)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Fri, 15 Dec 2017 07:35:09 +0000 (23:35 -0800)
Summary:
[Folly] Fix `folly::max_align_v` for Clang on ARMv7.

There is some problem with computing the correct result of `alignof` for a compound `union` POD type, because why wouldn't there be. The result *should* just be the max of the `alignof` of the type of each field if each field is default aligned - but not on some platforms! So we must compute the max directly.

Reviewed By: mzlee, Orvid

Differential Revision: D6573548

fbshipit-source-id: 512a255fda64795104d71fde14372befa3bf41e4

folly/lang/Align.h

index 8b878d401659723a88e685ff24c3b04ddab7c0fc..4f0564dccd62fbd7d821efcdb95079468f697b4d 100644 (file)
@@ -22,22 +22,34 @@ namespace folly {
 
 namespace detail {
 
-union max_align_ {
-  std::max_align_t mat;
-  long double ld;
-  double d;
-  float f;
-  long long int lli;
-  long int li;
-  int i;
-  short int si;
-  bool b;
-  char c;
-  char16_t c16;
-  char32_t c32;
-  wchar_t wc;
-  std::nullptr_t n;
+// Implemented this way because of a bug in Clang for ARMv7, which gives the
+// wrong result for `alignof` a `union` with a field of each scalar type.
+constexpr size_t max_align_(std::size_t a) {
+  return a;
+}
+template <typename... Es>
+constexpr std::size_t max_align_(std::size_t a, std::size_t e, Es... es) {
+  return !(a < e) ? a : max_align_(e, es...);
+}
+template <typename... Ts>
+struct max_align_t_ {
+  static constexpr std::size_t value = max_align_(0u, alignof(Ts)...);
 };
+using max_align_v_ = max_align_t_<
+    long double,
+    double,
+    float,
+    long long int,
+    long int,
+    int,
+    short int,
+    bool,
+    char,
+    char16_t,
+    char32_t,
+    wchar_t,
+    void*,
+    std::max_align_t>;
 
 } // namespace detail
 
@@ -73,7 +85,7 @@ union max_align_ {
 // crashes on 32-bit iOS apps that use `double`.
 //
 // Apple's allocation reference: http://bit.ly/malloc-small
-constexpr std::size_t max_align_v = alignof(detail::max_align_);
+constexpr std::size_t max_align_v = detail::max_align_v_::value;
 struct alignas(max_align_v) max_align_t {};
 
 } // namespace folly