about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2019-06-10T08·57-0700
committerGennadiy Civil <misterg@google.com>2019-06-10T17·31-0400
commit361cb8a9db2f2130442389fd80593255be26d681 (patch)
treef38eca22b4fbf0933e06abf5d0546ec9c29721b4
parent0238ab0a831f179518c1a814f9584e99da2d75a3 (diff)
Export of internal Abseil changes.
--
4a21ad4ffa957d28b770de8717289fab7410f567 by Gennadiy Rozental <rogeeff@google.com>:

Internal cleanup

PiperOrigin-RevId: 252366381

--
b6b0f25439549c54f1537a16625be1fecd3c7d8c by Xiaoyi Zhang <zhangxy@google.com>:

Fix C4245 compiler warning of visual studio. This allows using abseil headers
in code requiring strict warning settings.
This is an import of https://github.com/abseil/abseil-cpp/pull/321.

PiperOrigin-RevId: 252101240

--
0543b7861b658a5a665298e1d868e29968ff7b27 by CJ Johnson <johnsoncj@google.com>:

Adds new benchmarks for the constructors of InlinedVector

PiperOrigin-RevId: 251905349

--
c65a08507917e9f8f6450b8beb235fe1426d7954 by CJ Johnson <johnsoncj@google.com>:

Updates the InlinedVector BatchedBenchmark abstractions to 1) provide the index of the instance back to the prepare and test functions so that callers may perform extra work on local state with a unique per-instance ID and 2) reduce the number of manually written calls to BENCHMARK_TEMPLATE.

PiperOrigin-RevId: 251895546

--
99a1ae2d786b80096172f6e018711e15c0c750b9 by Samuel Benzaquen <sbenza@google.com>:

Fix ambiguous construction problem in absl::variant<> to make in line with
std::variant.
ImaginaryFun is hiding duplicate objects instead of causing ambiguity. Add a
second unique argument to make sure all overloads exist in the final overload
set.

PiperOrigin-RevId: 251860694

--
b54d0a12673be6ebb6e77e24a556ce9b758b3a7e by Abseil Team <absl-team@google.com>:

Import of CCTZ from GitHub.

PiperOrigin-RevId: 251739183

--
f51b115e0dc3fc9a9c9c20b33a1f27027a700d48 by Abseil Team <absl-team@google.com>:

Import of CCTZ from GitHub.

PiperOrigin-RevId: 251686812

--
30e868049282dc6a6fc77d923ca7d2a5d35a1658 by Xiaoyi Zhang <zhangxy@google.com>:

Import of CCTZ from GitHub.

PiperOrigin-RevId: 251652119
GitOrigin-RevId: 4a21ad4ffa957d28b770de8717289fab7410f567
Change-Id: I7171cb613793fa90e0eb0143b65ec8264a2a84db
-rw-r--r--absl/container/inlined_vector_benchmark.cc110
-rw-r--r--absl/flags/internal/flag.h2
-rw-r--r--absl/flags/marshalling.h9
-rw-r--r--absl/time/internal/cctz/include/cctz/civil_time.h4
-rw-r--r--absl/time/internal/cctz/src/civil_time_test.cc2
-rw-r--r--absl/time/internal/cctz/src/time_zone_info.cc3
-rw-r--r--absl/time/internal/cctz/src/time_zone_libc.cc95
-rw-r--r--absl/time/internal/cctz/src/zone_info_source.cc18
-rw-r--r--absl/types/internal/variant.h12
-rw-r--r--absl/types/variant_test.cc5
10 files changed, 182 insertions, 78 deletions
diff --git a/absl/container/inlined_vector_benchmark.cc b/absl/container/inlined_vector_benchmark.cc
index b57fc1de9e3b..a8368d418c53 100644
--- a/absl/container/inlined_vector_benchmark.cc
+++ b/absl/container/inlined_vector_benchmark.cc
@@ -379,6 +379,10 @@ constexpr size_t kLargeSize = kInlinedCapacity * 2;
 constexpr size_t kSmallSize = kInlinedCapacity / 2;
 constexpr size_t kBatchSize = 100;
 
+#define ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_FunctionTemplate, T) \
+  BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize);        \
+  BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize)
+
 template <typename T>
 using InlVec = absl::InlinedVector<T, kInlinedCapacity>;
 
@@ -420,29 +424,115 @@ void BatchedBenchmark(benchmark::State& state, PrepareVecFn prepare_vec,
   while (state.KeepRunningBatch(kBatchSize)) {
     // Prepare batch
     state.PauseTiming();
-    for (auto& vec : vector_batch) {
-      prepare_vec(&vec);
+    for (size_t i = 0; i < kBatchSize; ++i) {
+      prepare_vec(vector_batch.data() + i, i);
     }
     benchmark::DoNotOptimize(vector_batch);
     state.ResumeTiming();
 
     // Test batch
-    for (auto& vec : vector_batch) {
-      test_vec(&vec);
+    for (size_t i = 0; i < kBatchSize; ++i) {
+      test_vec(vector_batch.data() + i, i);
     }
   }
 }
 
+template <typename T, size_t ToSize>
+void BM_ConstructFromSize(benchmark::State& state) {
+  using VecT = InlVec<T>;
+  auto size = ToSize;
+  BatchedBenchmark<T>(
+      state,
+      /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); },
+      /* test_vec = */
+      [&](void* ptr, size_t) {
+        benchmark::DoNotOptimize(size);
+        ::new (ptr) VecT(size);
+      });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, NontrivialType);
+
+template <typename T, size_t ToSize>
+void BM_ConstructFromSizeRef(benchmark::State& state) {
+  using VecT = InlVec<T>;
+  auto size = ToSize;
+  auto ref = T();
+  BatchedBenchmark<T>(
+      state,
+      /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); },
+      /* test_vec = */
+      [&](void* ptr, size_t) {
+        benchmark::DoNotOptimize(size);
+        benchmark::DoNotOptimize(ref);
+        ::new (ptr) VecT(size, ref);
+      });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, NontrivialType);
+
+template <typename T, size_t ToSize>
+void BM_ConstructFromRange(benchmark::State& state) {
+  using VecT = InlVec<T>;
+  std::array<T, ToSize> arr{};
+  BatchedBenchmark<T>(
+      state,
+      /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); },
+      /* test_vec = */
+      [&](void* ptr, size_t) {
+        benchmark::DoNotOptimize(arr);
+        ::new (ptr) VecT(arr.begin(), arr.end());
+      });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, NontrivialType);
+
+template <typename T, size_t ToSize>
+void BM_ConstructFromCopy(benchmark::State& state) {
+  using VecT = InlVec<T>;
+  VecT other_vec(ToSize);
+  BatchedBenchmark<T>(
+      state,
+      /* prepare_vec = */
+      [](InlVec<T>* vec, size_t) { vec->~VecT(); },
+      /* test_vec = */
+      [&](void* ptr, size_t) {
+        benchmark::DoNotOptimize(other_vec);
+        ::new (ptr) VecT(other_vec);
+      });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, NontrivialType);
+
+template <typename T, size_t ToSize>
+void BM_ConstructFromMove(benchmark::State& state) {
+  using VecT = InlVec<T>;
+  std::array<VecT, kBatchSize> vector_batch{};
+  BatchedBenchmark<T>(
+      state,
+      /* prepare_vec = */
+      [&](InlVec<T>* vec, size_t i) {
+        vector_batch[i].clear();
+        vector_batch[i].resize(ToSize);
+        vec->~VecT();
+      },
+      /* test_vec = */
+      [&](void* ptr, size_t i) {
+        benchmark::DoNotOptimize(vector_batch[i]);
+        ::new (ptr) VecT(std::move(vector_batch[i]));
+      });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, NontrivialType);
+
 template <typename T, size_t FromSize>
 void BM_Clear(benchmark::State& state) {
   BatchedBenchmark<T>(
       state,
-      /* prepare_vec = */ [](InlVec<T>* vec) { vec->resize(FromSize); },
-      /* test_vec = */ [](InlVec<T>* vec) { vec->clear(); });
+      /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); },
+      /* test_vec = */ [](InlVec<T>* vec, size_t) { vec->clear(); });
 }
-BENCHMARK_TEMPLATE(BM_Clear, TrivialType, kLargeSize);
-BENCHMARK_TEMPLATE(BM_Clear, TrivialType, kSmallSize);
-BENCHMARK_TEMPLATE(BM_Clear, NontrivialType, kLargeSize);
-BENCHMARK_TEMPLATE(BM_Clear, NontrivialType, kSmallSize);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, NontrivialType);
 
 }  // namespace
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index 6402866f2249..9b32f46735b6 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -56,7 +56,7 @@ class Flag {
   // forward declared types.
   //  auto IsCopyConstructible(const T& v) -> decltype(T(v));
   //  auto HasAbslParseFlag(absl::string_view in, T* dst, std::string* err)
-  //      -> decltype(AbslParseFlag(in, dst, GlobalStringADLGuard(err)));
+  //      -> decltype(AbslParseFlag(in, dst, err));
   //  auto HasAbslUnparseFlag(const T& v) -> decltype(AbslUnparseFlag(v));
 };
 
diff --git a/absl/flags/marshalling.h b/absl/flags/marshalling.h
index 669cf452c4b0..7eb75cde7623 100644
--- a/absl/flags/marshalling.h
+++ b/absl/flags/marshalling.h
@@ -185,18 +185,11 @@ bool AbslParseFlag(absl::string_view, double*, std::string*);
 bool AbslParseFlag(absl::string_view, std::string*, std::string*);
 bool AbslParseFlag(absl::string_view, std::vector<std::string>*, std::string*);
 
-struct GlobalStringADLGuard {
-  explicit GlobalStringADLGuard(std::string* p) : ptr(p) {}
-  operator std::string*() { return ptr; }  // NOLINT
-  std::string* ptr;
-};
-
 template <typename T>
 bool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) {
   // Comment on next line provides a good compiler error message if T
   // does not have AbslParseFlag(absl::string_view, T*, std::string*).
-  return AbslParseFlag(  // Is T missing AbslParseFlag?
-      input, dst, GlobalStringADLGuard(err));
+  return AbslParseFlag(input, dst, err);  // Is T missing AbslParseFlag?
 }
 
 // Strings and std:: containers do not have the same overload resolution
diff --git a/absl/time/internal/cctz/include/cctz/civil_time.h b/absl/time/internal/cctz/include/cctz/civil_time.h
index f844182b1c90..aa578ee3648c 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time.h
@@ -306,9 +306,9 @@ using detail::get_weekday;
 //
 //   civil_day d = ...
 //   // Gets the following Thursday if d is not already Thursday
-//   civil_day thurs1 = prev_weekday(d, weekday::thursday) + 7;
+//   civil_day thurs1 = next_weekday(d - 1, weekday::thursday);
 //   // Gets the previous Thursday if d is not already Thursday
-//   civil_day thurs2 = next_weekday(d, weekday::thursday) - 7;
+//   civil_day thurs2 = prev_weekday(d + 1, weekday::thursday);
 //
 using detail::next_weekday;
 using detail::prev_weekday;
diff --git a/absl/time/internal/cctz/src/civil_time_test.cc b/absl/time/internal/cctz/src/civil_time_test.cc
index dc7e5a1d35c6..b1f46f1284e0 100644
--- a/absl/time/internal/cctz/src/civil_time_test.cc
+++ b/absl/time/internal/cctz/src/civil_time_test.cc
@@ -1035,7 +1035,7 @@ TEST(CivilTime, LeapYears) {
 
 TEST(CivilTime, FirstThursdayInMonth) {
   const civil_day nov1(2014, 11, 1);
-  const civil_day thursday = prev_weekday(nov1, weekday::thursday) + 7;
+  const civil_day thursday = next_weekday(nov1 - 1, weekday::thursday);
   EXPECT_EQ("2014-11-06", Format(thursday));
 
   // Bonus: Date of Thanksgiving in the United States
diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc
index 50f7de54014f..184bd434c2d2 100644
--- a/absl/time/internal/cctz/src/time_zone_info.cc
+++ b/absl/time/internal/cctz/src/time_zone_info.cc
@@ -682,7 +682,6 @@ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
   // Use of the "file:" prefix is intended for testing purposes only.
   if (name.compare(0, 5, "file:") == 0) return Open(name.substr(5));
 
-#if defined(__ANDROID__)
   // See Android's libc/tzcode/bionic.cpp for additional information.
   for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata",
                              "/system/usr/share/zoneinfo/tzdata"}) {
@@ -717,7 +716,7 @@ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
       }
     }
   }
-#endif  // __ANDROID__
+
   return nullptr;
 }
 
diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc
index 3ab1623cbd17..6095e764df0d 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.cc
+++ b/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -21,7 +21,6 @@
 #include <chrono>
 #include <ctime>
 #include <limits>
-#include <tuple>
 #include <utility>
 
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
@@ -33,57 +32,75 @@ namespace cctz {
 
 namespace {
 
-// .first is seconds east of UTC; .second is the time-zone abbreviation.
-using OffsetAbbr = std::pair<int, const char*>;
-
-// Defines a function that can be called as follows:
-//
-//   std::tm tm = ...;
-//   OffsetAbbr off_abbr = get_offset_abbr(tm);
-//
 #if defined(_WIN32) || defined(_WIN64)
 // Uses the globals: '_timezone', '_dstbias' and '_tzname'.
-OffsetAbbr get_offset_abbr(const std::tm& tm) {
+auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + _dstbias) {
   const bool is_dst = tm.tm_isdst > 0;
-  const int off = _timezone + (is_dst ? _dstbias : 0);
-  const char* abbr = _tzname[is_dst];
-  return {off, abbr};
+  return _timezone + (is_dst ? _dstbias : 0);
+}
+auto tm_zone(const std::tm& tm) -> decltype(_tzname[0]) {
+  const bool is_dst = tm.tm_isdst > 0;
+  return _tzname[is_dst];
 }
 #elif defined(__sun)
 // Uses the globals: 'timezone', 'altzone' and 'tzname'.
-OffsetAbbr get_offset_abbr(const std::tm& tm) {
+auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) {
   const bool is_dst = tm.tm_isdst > 0;
-  const int off = is_dst ? altzone : timezone;
-  const char* abbr = tzname[is_dst];
-  return {off, abbr};
+  return is_dst ? altzone : timezone;
+}
+auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) {
+  const bool is_dst = tm.tm_isdst > 0;
+  return tzname[is_dst];
 }
 #elif defined(__native_client__) || defined(__myriad2__) || \
     defined(__EMSCRIPTEN__)
 // Uses the globals: 'timezone' and 'tzname'.
-OffsetAbbr get_offset_abbr(const std::tm& tm) {
+auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + 0) {
+  const bool is_dst = tm.tm_isdst > 0;
+  return _timezone + (is_dst ? 60 * 60 : 0);
+}
+auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) {
   const bool is_dst = tm.tm_isdst > 0;
-  const int off = _timezone + (is_dst ? 60 * 60 : 0);
-  const char* abbr = tzname[is_dst];
-  return {off, abbr};
+  return tzname[is_dst];
+}
+#else
+// Adapt to different spellings of the struct std::tm extension fields.
+#if defined(tm_gmtoff)
+auto tm_gmtoff(const std::tm& tm) -> decltype(tm.tm_gmtoff) {
+  return tm.tm_gmtoff;
+}
+#elif defined(__tm_gmtoff)
+auto tm_gmtoff(const std::tm& tm) -> decltype(tm.__tm_gmtoff) {
+  return tm.__tm_gmtoff;
+}
+#else
+template <typename T>
+auto tm_gmtoff(const T& tm) -> decltype(tm.tm_gmtoff) {
+  return tm.tm_gmtoff;
+}
+template <typename T>
+auto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) {
+  return tm.__tm_gmtoff;
+}
+#endif  // tm_gmtoff
+#if defined(tm_zone)
+auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) {
+  return tm.tm_zone;
+}
+#elif defined(__tm_zone)
+auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) {
+  return tm.__tm_zone;
 }
 #else
-//
-// Returns an OffsetAbbr using std::tm fields with various spellings.
-//
-#if !defined(tm_gmtoff) && !defined(tm_zone)
 template <typename T>
-OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::tm_gmtoff) = nullptr,
-                           decltype(&T::tm_zone) = nullptr) {
-  return {tm.tm_gmtoff, tm.tm_zone};
+auto tm_zone(const T& tm) -> decltype(tm.tm_zone) {
+  return tm.tm_zone;
 }
-#endif  // !defined(tm_gmtoff) && !defined(tm_zone)
-#if !defined(__tm_gmtoff) && !defined(__tm_zone)
 template <typename T>
-OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::__tm_gmtoff) = nullptr,
-                           decltype(&T::__tm_zone) = nullptr) {
-  return {tm.__tm_gmtoff, tm.__tm_zone};
+auto tm_zone(const T& tm) -> decltype(tm.__tm_zone) {
+  return tm.__tm_zone;
 }
-#endif  // !defined(__tm_gmtoff) && !defined(__tm_zone)
+#endif  // tm_zone
 #endif
 
 inline std::tm* gm_time(const std::time_t *timep, std::tm *result) {
@@ -126,7 +143,7 @@ bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) {
       return false;
     }
   }
-  *off = get_offset_abbr(tm).first;
+  *off = static_cast<int>(tm_gmtoff(tm));
   return true;
 }
 
@@ -137,7 +154,7 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) {
   while (lo + 1 != hi) {
     const std::time_t mid = lo + (hi - lo) / 2;
     if (std::tm* tmp = local_time(&mid, &tm)) {
-      if (get_offset_abbr(*tmp).first == offset) {
+      if (tm_gmtoff(*tmp) == offset) {
         hi = mid;
       } else {
         lo = mid;
@@ -147,7 +164,7 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) {
       // ignoring all failed conversions.  Slow, but never really happens.
       while (++lo != hi) {
         if (std::tm* tmp = local_time(&lo, &tm)) {
-          if (get_offset_abbr(*tmp).first == offset) break;
+          if (tm_gmtoff(*tmp) == offset) break;
         }
       }
       return lo;
@@ -193,8 +210,8 @@ time_zone::absolute_lookup TimeZoneLibC::BreakTime(
   const year_t year = tmp->tm_year + year_t{1900};
   al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday,
                        tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
-  std::tie(al.offset, al.abbr) = get_offset_abbr(*tmp);
-  if (!local_) al.abbr = "UTC";  // as expected by cctz
+  al.offset = static_cast<int>(tm_gmtoff(*tmp));
+  al.abbr = local_ ? tm_zone(*tmp) : "UTC";  // as expected by cctz
   al.is_dst = tmp->tm_isdst > 0;
   return al;
 }
diff --git a/absl/time/internal/cctz/src/zone_info_source.cc b/absl/time/internal/cctz/src/zone_info_source.cc
index 132484628cd9..42f50c5e8fb4 100644
--- a/absl/time/internal/cctz/src/zone_info_source.cc
+++ b/absl/time/internal/cctz/src/zone_info_source.cc
@@ -46,7 +46,13 @@ std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory(
 // A "weak" definition for cctz_extension::zone_info_source_factory.
 // The user may override this with their own "strong" definition (see
 // zone_info_source.h).
-#if defined(_MSC_VER)
+#if !defined(__has_attribute)
+#define __has_attribute(x) 0
+#endif
+#if __has_attribute(weak) || defined(__GNUC__)
+ZoneInfoSourceFactory zone_info_source_factory
+    __attribute__((weak)) = DefaultFactory;
+#elif defined(_MSC_VER) && !defined(_LIBCPP_VERSION)
 extern ZoneInfoSourceFactory zone_info_source_factory;
 extern ZoneInfoSourceFactory default_factory;
 ZoneInfoSourceFactory default_factory = DefaultFactory;
@@ -60,19 +66,11 @@ ZoneInfoSourceFactory default_factory = DefaultFactory;
     "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA=?default_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA")
 #else
 #error Unsupported MSVC platform
-#endif
-#else  // _MSC_VER
-#if !defined(__has_attribute)
-#define __has_attribute(x) 0
-#endif
-#if __has_attribute(weak) || defined(__GNUC__)
-ZoneInfoSourceFactory zone_info_source_factory
-    __attribute__((weak)) = DefaultFactory;
+#endif  // _M_<PLATFORM>
 #else
 // Make it a "strong" definition if we have no other choice.
 ZoneInfoSourceFactory zone_info_source_factory = DefaultFactory;
 #endif
-#endif  // _MSC_VER
 
 }  // namespace cctz_extension
 }  // namespace time_internal
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
index 5ca66e2902c6..85201b4ae1f9 100644
--- a/absl/types/internal/variant.h
+++ b/absl/types/internal/variant.h
@@ -837,8 +837,8 @@ struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> {
   // NOTE: const& and && are used instead of by-value due to lack of guaranteed
   // move elision of C++17. This may have other minor differences, but tests
   // pass.
-  static SizeT<I> Run(const H&);
-  static SizeT<I> Run(H&&);
+  static SizeT<I> Run(const H&, SizeT<I>);
+  static SizeT<I> Run(H&&, SizeT<I>);
 };
 
 // The following metafunctions are used in constructor and assignment
@@ -860,7 +860,8 @@ struct ConversionIsPossibleImpl : std::false_type {};
 
 template <class Variant, class T>
 struct ConversionIsPossibleImpl<
-    Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
+    Variant, T,
+    void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
     : std::true_type {};
 
 template <class Variant, class T>
@@ -868,8 +869,9 @@ struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {};
 
 template <class Variant, class T>
 struct IndexOfConstructedType<
-    Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
-    : decltype(ImaginaryFun<Variant>::Run(std::declval<T>())) {};
+    Variant, T,
+    void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
+    : decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {})) {};
 
 template <std::size_t... Is>
 struct ContainsVariantNPos
diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc
index b9c981181c50..d702482768a4 100644
--- a/absl/types/variant_test.cc
+++ b/absl/types/variant_test.cc
@@ -460,6 +460,11 @@ TYPED_TEST(VariantTypesTest, TestValueCtor) {
   EXPECT_EQ(value.value, mutable_valptr->value);
 }
 
+TEST(VariantTest, AmbiguousValueConstructor) {
+  EXPECT_FALSE((std::is_convertible<int, absl::variant<int, int>>::value));
+  EXPECT_FALSE((std::is_constructible<absl::variant<int, int>, int>::value));
+}
+
 TEST(VariantTest, InPlaceType) {
   using Var = variant<int, std::string, NonCopyable, std::vector<int>>;