summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--absl/base/config.h7
-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/strings/str_cat.h3
-rw-r--r--absl/strings/str_format.h11
-rw-r--r--absl/strings/substitute.h7
-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_fixed.cc16
-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.cc7
15 files changed, 214 insertions, 92 deletions
diff --git a/absl/base/config.h b/absl/base/config.h
index 2a14fe74..f12f84fd 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -181,6 +181,13 @@
#endif
#endif // defined(__ANDROID__) && defined(__clang__)
+// Emscripten doesn't yet support `thread_local` or `__thread`.
+// https://github.com/emscripten-core/emscripten/issues/3502
+#if defined(__EMSCRIPTEN__)
+#undef ABSL_HAVE_TLS
+#undef ABSL_HAVE_THREAD_LOCAL
+#endif // defined(__EMSCRIPTEN__)
+
// ABSL_HAVE_INTRINSIC_INT128
//
// Checks whether the __int128 compiler extension for a 128-bit integral type is
diff --git a/absl/container/inlined_vector_benchmark.cc b/absl/container/inlined_vector_benchmark.cc
index b57fc1de..a8368d41 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 6402866f..9b32f467 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 669cf452..7eb75cde 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/strings/str_cat.h b/absl/strings/str_cat.h
index 559ee0aa..a99aac01 100644
--- a/absl/strings/str_cat.h
+++ b/absl/strings/str_cat.h
@@ -37,7 +37,8 @@
// attempt to pass ':' instead of ":" might result in a 58 ending up in your
// result.
//
-// Bools convert to "0" or "1".
+// Bools convert to "0" or "1". Pointers to types other than `char *` are not
+// valid inputs. No output is generated for null `char *` pointers.
//
// Floating point numbers are formatted with six-digit precision, which is
// the default for "std::cout <<" or printf "%g" (the same as "%.6g").
diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h
index da3208e1..0b93c288 100644
--- a/absl/strings/str_format.h
+++ b/absl/strings/str_format.h
@@ -20,7 +20,8 @@
// The `str_format` library is a typesafe replacement for the family of
// `printf()` string formatting routines within the `<cstdio>` standard library
// header. Like the `printf` family, the `str_format` uses a "format string" to
-// perform argument substitutions based on types.
+// perform argument substitutions based on types. See the `FormatSpec` section
+// below for format string documentation.
//
// Example:
//
@@ -67,6 +68,7 @@
// In addition, the `str_format` library provides extension points for
// augmenting formatting to new types. These extensions are fully documented
// within the `str_format_extension.h` header file.
+
#ifndef ABSL_STRINGS_STR_FORMAT_H_
#define ABSL_STRINGS_STR_FORMAT_H_
@@ -211,6 +213,11 @@ class FormatCountCapture {
// written to this point. The resulting value must be captured within an
// `absl::FormatCountCapture` type.
//
+// Implementation-defined behavior:
+// * A null pointer provided to "%s" or "%p" is output as "(nil)".
+// * A non-null pointer provided to "%p" is output in hex as if by %#x or
+// %#lx.
+//
// NOTE: `o`, `x\X` and `u` will convert signed values to their unsigned
// counterpart before formatting.
//
@@ -226,7 +233,7 @@ class FormatCountCapture {
// "%e", .01 -> "1.00000e-2"
// "%a", -3.0 -> "-0x1.8p+1"
// "%g", .01 -> "1e-2"
-// "%p", *int -> "0x7ffdeb6ad2a4"
+// "%p", (void*)&value -> "0x7ffdeb6ad2a4"
//
// int n = 0;
// std::string s = absl::StrFormat(
diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h
index 32dec30b..233e9dcf 100644
--- a/absl/strings/substitute.h
+++ b/absl/strings/substitute.h
@@ -35,10 +35,13 @@
// and single digit positional ids to indicate which substitution arguments to
// use at that location within the format string.
//
+// A '$$' sequence in the format string causes a literal '$' character to be
+// output.
+//
// Example 1:
-// std::string s = Substitute("$1 purchased $0 $2. Thanks $1!",
+// std::string s = Substitute("$1 purchased $0 $2 for $$10. Thanks $1!",
// 5, "Bob", "Apples");
-// EXPECT_EQ("Bob purchased 5 Apples. Thanks Bob!", s);
+// EXPECT_EQ("Bob purchased 5 Apples for $10. Thanks Bob!", s);
//
// Example 2:
// std::string s = "Hi. ";
diff --git a/absl/time/internal/cctz/include/cctz/civil_time.h b/absl/time/internal/cctz/include/cctz/civil_time.h
index f844182b..aa578ee3 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 dc7e5a1d..b1f46f12 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_fixed.cc b/absl/time/internal/cctz/src/time_zone_fixed.cc
index 81ece72b..b0d159a2 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.cc
+++ b/absl/time/internal/cctz/src/time_zone_fixed.cc
@@ -27,7 +27,7 @@ namespace cctz {
namespace {
// The prefix used for the internal names of fixed-offset zones.
-const char kFixedOffsetPrefix[] = "Fixed/UTC";
+const char kFixedZonePrefix[] = "Fixed/UTC";
const char kDigits[] = "0123456789";
@@ -55,11 +55,11 @@ bool FixedOffsetFromName(const std::string& name, seconds* offset) {
return true;
}
- const std::size_t prefix_len = sizeof(kFixedOffsetPrefix) - 1;
- const char* const ep = kFixedOffsetPrefix + prefix_len;
+ const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
+ const char* const ep = kFixedZonePrefix + prefix_len;
if (name.size() != prefix_len + 9) // <prefix>+99:99:99
return false;
- if (!std::equal(kFixedOffsetPrefix, ep, name.begin()))
+ if (!std::equal(kFixedZonePrefix, ep, name.begin()))
return false;
const char* np = name.data() + prefix_len;
if (np[0] != '+' && np[0] != '-')
@@ -102,9 +102,9 @@ std::string FixedOffsetToName(const seconds& offset) {
}
int hours = minutes / 60;
minutes %= 60;
- char buf[sizeof(kFixedOffsetPrefix) - 1 + sizeof("-24:00:00")];
- std::strcpy(buf, kFixedOffsetPrefix);
- char* ep = buf + sizeof(kFixedOffsetPrefix) - 1;
+ const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
+ char buf[prefix_len + sizeof("-24:00:00")];
+ char* ep = std::copy(kFixedZonePrefix, kFixedZonePrefix + prefix_len, buf);
*ep++ = sign;
ep = Format02d(ep, hours);
*ep++ = ':';
@@ -118,7 +118,7 @@ std::string FixedOffsetToName(const seconds& offset) {
std::string FixedOffsetToAbbr(const seconds& offset) {
std::string abbr = FixedOffsetToName(offset);
- const std::size_t prefix_len = sizeof(kFixedOffsetPrefix) - 1;
+ const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
if (abbr.size() == prefix_len + 9) { // <prefix>+99:99:99
abbr.erase(0, prefix_len); // +99:99:99
abbr.erase(6, 1); // +99:9999
diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc
index 50f7de54..184bd434 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 3ab1623c..6095e764 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 13248462..42f50c5e 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 5ca66e29..85201b4a 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 b9c98118..2efaf21e 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>>;
@@ -1788,8 +1793,8 @@ TEST(VariantTest, VisitSimple) {
EXPECT_EQ("B", piece);
struct StrLen {
- int operator()(const std::string& s) const { return s.size(); }
int operator()(const char* s) const { return strlen(s); }
+ int operator()(const std::string& s) const { return s.size(); }
};
v = "SomeStr";