diff --git a/absl/base/config.h b/absl/base/config.h index 87e403ad8..500bc8c81 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 5e4f93136..108fa4906 100644 --- a/absl/time/duration.cc +++ b/absl/time/duration.cc @@ -62,6 +62,7 @@ #include #include +#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(v); } - -// Convert uint64_t to int64_t in twos-complement system. -inline int64_t DecodeTwosComp(uint64_t v) { - if (v <= kint64max) return static_cast(v); - return static_cast(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(v); } +inline int64_t DecodeTwosComp(uint64_t v) { return bit_cast(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