From 3f622d6c5990a7ae80eb8e52450c309a28bbec77 Mon Sep 17 00:00:00 2001
From: Abseil Team <absl-team@google.com>
Date: Mon, 9 Apr 2018 08:30:09 -0700
Subject: [PATCH]   - 51e2d3690b9065da84dbbf71fb52f87149670719 Fix
 `ABSL_HAVE_THREAD_LOCAL` on Apple 32-bit iOS simulato... by Xiaoyi Zhang
 <zhangxy@google.com>   - d38332e4d6b51542a42ff49fb0fc4f4a756fdd05 Internal
 change. by Abseil Team <absl-team@google.com>

GitOrigin-RevId: 51e2d3690b9065da84dbbf71fb52f87149670719
Change-Id: I9403fc6308a6c731f1c8e2cd70fdb382fafd960e
---
 absl/base/config.h    | 14 +++++++++-----
 absl/time/duration.cc | 19 +++++++++++--------
 2 files changed, 20 insertions(+), 13 deletions(-)

diff --git a/absl/base/config.h b/absl/base/config.h
index 87e403ad..500bc8c8 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -138,12 +138,16 @@
 // supported.
 #ifdef ABSL_HAVE_THREAD_LOCAL
 #error ABSL_HAVE_THREAD_LOCAL cannot be directly set
-#elif (!defined(__apple_build_version__) || \
-       (__apple_build_version__ >= 8000042)) && \
-      !(defined(__APPLE__) && TARGET_OS_IPHONE && \
-        __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
+#elif defined(__APPLE__)
 // Notes: Xcode's clang did not support `thread_local` until version
-// 8, and even then not for all iOS < 9.0.
+// 8, and even then not for all iOS < 9.0. Also, Xcode 9.3 started disallowing
+// `thread_local` for 32-bit iOS simulator targeting iOS 9.x.
+// `__has_feature` is only supported by Clang so it has be inside
+// `defined(__APPLE__)` check.
+#if __has_feature(cxx_thread_local)
+#define ABSL_HAVE_THREAD_LOCAL 1
+#endif
+#else  // !defined(__APPLE__)
 #define ABSL_HAVE_THREAD_LOCAL 1
 #endif
 
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index 5e4f9313..108fa490 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -62,6 +62,7 @@
 #include <limits>
 #include <string>
 
+#include "absl/base/casts.h"
 #include "absl/numeric/int128.h"
 #include "absl/time/time.h"
 
@@ -165,14 +166,16 @@ inline Duration MakeDurationFromU128(uint128 u128, bool is_neg) {
   return time_internal::MakeDuration(rep_hi, rep_lo);
 }
 
-// Convert int64_t to uint64_t in twos-complement system.
-inline uint64_t EncodeTwosComp(int64_t v) { return static_cast<uint64_t>(v); }
-
-// Convert uint64_t to int64_t in twos-complement system.
-inline int64_t DecodeTwosComp(uint64_t v) {
-  if (v <= kint64max) return static_cast<int64_t>(v);
-  return static_cast<int64_t>(v - kint64max - 1) + kint64min;
-}
+// Convert between int64_t and uint64_t, preserving representation. This
+// allows us to do arithmetic in the unsigned domain, where overflow has
+// well-defined behavior. See operator+=() and operator-=().
+//
+// C99 7.20.1.1.1, as referenced by C++11 18.4.1.2, says, "The typedef
+// name intN_t designates a signed integer type with width N, no padding
+// bits, and a two's complement representation." So, we can convert to
+// and from the corresponding uint64_t value using a bit cast.
+inline uint64_t EncodeTwosComp(int64_t v) { return bit_cast<uint64_t>(v); }
+inline int64_t DecodeTwosComp(uint64_t v) { return bit_cast<int64_t>(v); }
 
 // Note: The overflow detection in this function is done using greater/less *or
 // equal* because kint64max/min is too large to be represented exactly in a
-- 
GitLab