Export of internal Abseil changes.

--
00d42e3d5433aaf29c2ed293520b2ba178ae8bdb by Greg Falcon <gfalcon@google.com>:

Import of CCTZ from GitHub.

PiperOrigin-RevId: 238061818

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

Added a IWYU export pragma when including a standard header for the purpose of aliasing its symbols.

PiperOrigin-RevId: 238022277

--
17047745058f2f151cd986ea9f649512542d3876 by Matt Armstrong <marmstrong@google.com>:

Clarify the comment discouraging WrapUnique<T>(x) calls.

PiperOrigin-RevId: 237873803

--
3dcb2e4968243d33ca0ce53280c445df50f4a7ec by Samuel Benzaquen <sbenza@google.com>:

Workaround clang bug https://bugs.llvm.org/show_bug.cgi?id=38289

PiperOrigin-RevId: 237873551

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

Reduce minimum capacity to 1.
This reduces memory usage for small tables.
A flat_hash_set<int> of 1 element goes from 92 bytes to 24.
A flat_hash_set<string> of 1 element goes from 512 bytes to 56.

PiperOrigin-RevId: 237859811

--
9c8125be5e4e5d22a7bb62bdec8c323338385c1b by Jon Cohen <cohenjon@google.com>:

Bump to CMake 3.5. This is the oldest modern cmake being included by default in most popular OS distributions according to https://repology.org/project/cmake/versions.  Specifically, Ubuntu LTS 16.04 uses cmake 3.5 (https://packages.ubuntu.com/xenial/cmake)

PiperOrigin-RevId: 237859345

--
07638d672e0a4dced986a62750cfd8318ed36ffa by Derek Mauro <dmauro@google.com>:

Import of CCTZ from GitHub.

PiperOrigin-RevId: 237714597
GitOrigin-RevId: 00d42e3d5433aaf29c2ed293520b2ba178ae8bdb
Change-Id: I5faecc45add4a5a774d4f9baf06e5519091f2ccc
This commit is contained in:
Abseil Team 2019-03-12 11:39:15 -07:00 committed by vslashg
parent 88a152ae74
commit 256be56344
37 changed files with 180 additions and 128 deletions

View file

@ -14,9 +14,12 @@
# limitations under the License. # limitations under the License.
# #
# We require 3.0 for modern, target-based CMake. We require 3.1 for the use of # Most widely used distributions have cmake 3.5 or greater available as of March
# CXX_STANDARD in our targets. # 2019. A notable exception is RHEL-7 (CentOS7). You can install a current
cmake_minimum_required(VERSION 3.1) # version of CMake by first installing Extra Packages for Enterprise Linux
# (https://fedoraproject.org/wiki/EPEL#Extra_Packages_for_Enterprise_Linux_.28EPEL.29)
# and then issuing `yum install cmake3` on the command line.
cmake_minimum_required(VERSION 3.5)
# Compiler id for Apple Clang is now AppleClang. # Compiler id for Apple Clang is now AppleClang.
if (POLICY CMP0025) if (POLICY CMP0025)

View file

@ -141,6 +141,7 @@ TEST(FlatHashMap, LazyKeyPattern) {
int conversions = 0; int conversions = 0;
int hashes = 0; int hashes = 0;
flat_hash_map<size_t, size_t, Hash, Eq> m(0, Hash{&hashes}); flat_hash_map<size_t, size_t, Hash, Eq> m(0, Hash{&hashes});
m.reserve(3);
m[LazyInt(1, &conversions)] = 1; m[LazyInt(1, &conversions)] = 1;
EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 1))); EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 1)));

View file

@ -446,9 +446,7 @@ using Group = GroupPortableImpl;
template <class Policy, class Hash, class Eq, class Alloc> template <class Policy, class Hash, class Eq, class Alloc>
class raw_hash_set; class raw_hash_set;
inline bool IsValidCapacity(size_t n) { inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
return ((n + 1) & n) == 0 && n >= Group::kWidth - 1;
}
// PRECONDITION: // PRECONDITION:
// IsValidCapacity(capacity) // IsValidCapacity(capacity)
@ -470,13 +468,9 @@ inline void ConvertDeletedToEmptyAndFullToDeleted(
ctrl[capacity] = kSentinel; ctrl[capacity] = kSentinel;
} }
// Rounds up the capacity to the next power of 2 minus 1 and ensures it is // Rounds up the capacity to the next power of 2 minus 1, with a minimum of 1.
// greater or equal to Group::kWidth - 1.
inline size_t NormalizeCapacity(size_t n) { inline size_t NormalizeCapacity(size_t n) {
constexpr size_t kMinCapacity = Group::kWidth - 1; return n ? ~size_t{} >> LeadingZeros(n) : 1;
return n <= kMinCapacity
? kMinCapacity
: (std::numeric_limits<size_t>::max)() >> LeadingZeros(n);
} }
// We use 7/8th as maximum load factor. // We use 7/8th as maximum load factor.
@ -1507,6 +1501,7 @@ class raw_hash_set {
void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE { void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE {
assert(IsValidCapacity(capacity_)); assert(IsValidCapacity(capacity_));
assert(!is_small());
// Algorithm: // Algorithm:
// - mark all DELETED slots as EMPTY // - mark all DELETED slots as EMPTY
// - mark all FULL slots as DELETED // - mark all FULL slots as DELETED
@ -1572,7 +1567,7 @@ class raw_hash_set {
void rehash_and_grow_if_necessary() { void rehash_and_grow_if_necessary() {
if (capacity_ == 0) { if (capacity_ == 0) {
resize(Group::kWidth - 1); resize(1);
} else if (size() <= CapacityToGrowth(capacity()) / 2) { } else if (size() <= CapacityToGrowth(capacity()) / 2) {
// Squash DELETED without growing if there is enough capacity. // Squash DELETED without growing if there is enough capacity.
drop_deletes_without_resize(); drop_deletes_without_resize();
@ -1619,17 +1614,15 @@ class raw_hash_set {
auto mask = g.MatchEmptyOrDeleted(); auto mask = g.MatchEmptyOrDeleted();
if (mask) { if (mask) {
#if !defined(NDEBUG) #if !defined(NDEBUG)
// We want to force small tables to have random entries too, so // We want to add entropy even when ASLR is not enabled.
// in debug build we will randomly insert in either the front or back of // In debug build we will randomly insert in either the front or back of
// the group. // the group.
// TODO(kfm,sbenza): revisit after we do unconditional mixing // TODO(kfm,sbenza): revisit after we do unconditional mixing
if (ShouldInsertBackwards(hash, ctrl_)) if (!is_small() && ShouldInsertBackwards(hash, ctrl_)) {
return {seq.offset(mask.HighestBitSet()), seq.index()}; return {seq.offset(mask.HighestBitSet()), seq.index()};
else }
return {seq.offset(mask.LowestBitSet()), seq.index()};
#else
return {seq.offset(mask.LowestBitSet()), seq.index()};
#endif #endif
return {seq.offset(mask.LowestBitSet()), seq.index()};
} }
assert(seq.index() < capacity_ && "full table!"); assert(seq.index() < capacity_ && "full table!");
seq.next(); seq.next();
@ -1732,11 +1725,28 @@ class raw_hash_set {
} }
ctrl_[i] = h; ctrl_[i] = h;
ctrl_[((i - Group::kWidth) & capacity_) + Group::kWidth] = h; ctrl_[((i - Group::kWidth) & capacity_) + 1 +
((Group::kWidth - 1) & capacity_)] = h;
} }
size_t& growth_left() { return settings_.template get<0>(); } size_t& growth_left() { return settings_.template get<0>(); }
// The representation of the object has two modes:
// - small: For capacities < kWidth-1
// - large: For the rest.
//
// Differences:
// - In small mode we are able to use the whole capacity. The extra control
// bytes give us at least one "empty" control byte to stop the iteration.
// This is important to make 1 a valid capacity.
//
// - In small mode only the first `capacity()` control bytes after the
// sentinel are valid. The rest contain dummy kEmpty values that do not
// represent a real slot. This is important to take into account on
// find_first_non_full(), where we never try ShouldInsertBackwards() for
// small tables.
bool is_small() const { return capacity_ < Group::kWidth - 1; }
hasher& hash_ref() { return settings_.template get<1>(); } hasher& hash_ref() { return settings_.template get<1>(); }
const hasher& hash_ref() const { return settings_.template get<1>(); } const hasher& hash_ref() const { return settings_.template get<1>(); }
key_equal& eq_ref() { return settings_.template get<2>(); } key_equal& eq_ref() { return settings_.template get<2>(); }

View file

@ -55,13 +55,16 @@ using ::testing::Pair;
using ::testing::UnorderedElementsAre; using ::testing::UnorderedElementsAre;
TEST(Util, NormalizeCapacity) { TEST(Util, NormalizeCapacity) {
constexpr size_t kMinCapacity = Group::kWidth - 1; EXPECT_EQ(1, NormalizeCapacity(0));
EXPECT_EQ(kMinCapacity, NormalizeCapacity(0)); EXPECT_EQ(1, NormalizeCapacity(1));
EXPECT_EQ(kMinCapacity, NormalizeCapacity(1)); EXPECT_EQ(3, NormalizeCapacity(2));
EXPECT_EQ(kMinCapacity, NormalizeCapacity(2)); EXPECT_EQ(3, NormalizeCapacity(3));
EXPECT_EQ(kMinCapacity, NormalizeCapacity(kMinCapacity)); EXPECT_EQ(7, NormalizeCapacity(4));
EXPECT_EQ(kMinCapacity * 2 + 1, NormalizeCapacity(kMinCapacity + 1)); EXPECT_EQ(7, NormalizeCapacity(7));
EXPECT_EQ(kMinCapacity * 2 + 1, NormalizeCapacity(kMinCapacity + 2)); EXPECT_EQ(15, NormalizeCapacity(8));
EXPECT_EQ(15, NormalizeCapacity(15));
EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 1));
EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 2));
} }
TEST(Util, GrowthAndCapacity) { TEST(Util, GrowthAndCapacity) {
@ -72,10 +75,7 @@ TEST(Util, GrowthAndCapacity) {
size_t capacity = NormalizeCapacity(GrowthToLowerboundCapacity(growth)); size_t capacity = NormalizeCapacity(GrowthToLowerboundCapacity(growth));
// The capacity is large enough for `growth` // The capacity is large enough for `growth`
EXPECT_THAT(CapacityToGrowth(capacity), Ge(growth)); EXPECT_THAT(CapacityToGrowth(capacity), Ge(growth));
if (growth < Group::kWidth - 1) { if (growth != 0 && capacity > 1) {
// Fits in one group, that is the minimum capacity.
EXPECT_EQ(capacity, Group::kWidth - 1);
} else {
// There is no smaller capacity that works. // There is no smaller capacity that works.
EXPECT_THAT(CapacityToGrowth(capacity / 2), Lt(growth)); EXPECT_THAT(CapacityToGrowth(capacity / 2), Lt(growth));
} }
@ -814,7 +814,7 @@ TEST(Table, EnsureNonQuadraticAsInRust) {
TEST(Table, ClearBug) { TEST(Table, ClearBug) {
IntTable t; IntTable t;
constexpr size_t capacity = container_internal::Group::kWidth - 1; constexpr size_t capacity = container_internal::Group::kWidth - 1;
constexpr size_t max_size = capacity / 2; constexpr size_t max_size = capacity / 2 + 1;
for (size_t i = 0; i < max_size; ++i) { for (size_t i = 0; i < max_size; ++i) {
t.insert(i); t.insert(i);
} }
@ -1741,73 +1741,49 @@ TEST(Nodes, ExtractInsert) {
EXPECT_FALSE(node); EXPECT_FALSE(node);
} }
StringTable MakeSimpleTable(size_t size) { IntTable MakeSimpleTable(size_t size) {
StringTable t; IntTable t;
for (size_t i = 0; i < size; ++i) t.emplace(std::string(1, 'A' + i), ""); while (t.size() < size) t.insert(t.size());
return t; return t;
} }
std::string OrderOfIteration(const StringTable& t) { std::vector<int> OrderOfIteration(const IntTable& t) {
std::string order; return {t.begin(), t.end()};
for (auto& p : t) order += p.first;
return order;
} }
// These IterationOrderChanges tests depend on non-deterministic behavior.
// We are injecting non-determinism from the pointer of the table, but do so in
// a way that only the page matters. We have to retry enough times to make sure
// we are touching different memory pages to cause the ordering to change.
// We also need to keep the old tables around to avoid getting the same memory
// blocks over and over.
TEST(Table, IterationOrderChangesByInstance) { TEST(Table, IterationOrderChangesByInstance) {
// Needs to be more than kWidth elements to be able to affect order. for (size_t size : {2, 6, 12, 20}) {
const StringTable reference = MakeSimpleTable(20); const auto reference_table = MakeSimpleTable(size);
const auto reference = OrderOfIteration(reference_table);
// Since order is non-deterministic we can't just try once and verify. std::vector<IntTable> tables;
// We'll try until we find that order changed. It should not take many tries bool found_difference = false;
// for that. for (int i = 0; !found_difference && i < 500; ++i) {
// Important: we have to keep the old tables around. Otherwise tcmalloc will tables.push_back(MakeSimpleTable(size));
// just give us the same blocks and we would be doing the same order again. found_difference = OrderOfIteration(tables.back()) != reference;
std::vector<StringTable> garbage; }
for (int i = 0; i < 10; ++i) { if (!found_difference) {
auto trial = MakeSimpleTable(20); FAIL()
if (OrderOfIteration(trial) != OrderOfIteration(reference)) { << "Iteration order remained the same across many attempts with size "
// We are done. << size;
return;
} }
garbage.push_back(std::move(trial));
} }
FAIL();
} }
TEST(Table, IterationOrderChangesOnRehash) { TEST(Table, IterationOrderChangesOnRehash) {
// Since order is non-deterministic we can't just try once and verify. std::vector<IntTable> garbage;
// We'll try until we find that order changed. It should not take many tries for (int i = 0; i < 500; ++i) {
// for that. auto t = MakeSimpleTable(20);
// Important: we have to keep the old tables around. Otherwise tcmalloc will const auto reference = OrderOfIteration(t);
// just give us the same blocks and we would be doing the same order again.
std::vector<StringTable> garbage;
for (int i = 0; i < 10; ++i) {
// Needs to be more than kWidth elements to be able to affect order.
StringTable t = MakeSimpleTable(20);
const std::string reference = OrderOfIteration(t);
// Force rehash to the same size. // Force rehash to the same size.
t.rehash(0); t.rehash(0);
std::string trial = OrderOfIteration(t); auto trial = OrderOfIteration(t);
if (trial != reference) {
// We are done.
return;
}
garbage.push_back(std::move(t));
}
FAIL();
}
TEST(Table, IterationOrderChangesForSmallTables) {
// Since order is non-deterministic we can't just try once and verify.
// We'll try until we find that order changed.
// Important: we have to keep the old tables around. Otherwise tcmalloc will
// just give us the same blocks and we would be doing the same order again.
StringTable reference_table = MakeSimpleTable(5);
const std::string reference = OrderOfIteration(reference_table);
std::vector<StringTable> garbage;
for (int i = 0; i < 50; ++i) {
StringTable t = MakeSimpleTable(5);
std::string trial = OrderOfIteration(t);
if (trial != reference) { if (trial != reference) {
// We are done. // We are done.
return; return;
@ -1817,6 +1793,24 @@ TEST(Table, IterationOrderChangesForSmallTables) {
FAIL() << "Iteration order remained the same across many attempts."; FAIL() << "Iteration order remained the same across many attempts.";
} }
// Verify that pointers are invalidated as soon as a second element is inserted.
// This prevents dependency on pointer stability on small tables.
TEST(Table, UnstablePointers) {
IntTable table;
const auto addr = [&](int i) {
return reinterpret_cast<uintptr_t>(&*table.find(i));
};
table.insert(0);
const uintptr_t old_ptr = addr(0);
// This causes a rehash.
table.insert(1);
EXPECT_NE(old_ptr, addr(0));
}
// Confirm that we assert if we try to erase() end(). // Confirm that we assert if we try to erase() end().
TEST(TableDeathTest, EraseOfEndAsserts) { TEST(TableDeathTest, EraseOfEndAsserts) {
// Use an assert with side-effects to figure out if they are actually enabled. // Use an assert with side-effects to figure out if they are actually enabled.
@ -1857,6 +1851,7 @@ TEST(RawHashSamplerTest, Sample) {
#ifdef ADDRESS_SANITIZER #ifdef ADDRESS_SANITIZER
TEST(Sanitizer, PoisoningUnused) { TEST(Sanitizer, PoisoningUnused) {
IntTable t; IntTable t;
t.reserve(5);
// Insert something to force an allocation. // Insert something to force an allocation.
int64_t& v1 = *t.insert(0).first; int64_t& v1 = *t.insert(0).first;

View file

@ -47,19 +47,14 @@ namespace absl {
// X* NewX(int, int); // X* NewX(int, int);
// auto x = WrapUnique(NewX(1, 2)); // 'x' is std::unique_ptr<X>. // auto x = WrapUnique(NewX(1, 2)); // 'x' is std::unique_ptr<X>.
// //
// The purpose of WrapUnique is to automatically deduce the pointer type. If you // Do not call WrapUnique with an explicit type, as in
// wish to make the type explicit, for readability reasons or because you prefer // `WrapUnique<X>(NewX(1, 2))`. The purpose of WrapUnique is to automatically
// to use a base-class pointer rather than a derived one, just use // deduce the pointer type. If you wish to make the type explicit, just use
// `std::unique_ptr` directly. // `std::unique_ptr` directly.
// //
// Example: // auto x = std::unique_ptr<X>(NewX(1, 2));
// X* Factory(int, int);
// auto x = std::unique_ptr<X>(Factory(1, 2));
// - or - // - or -
// std::unique_ptr<X> x(Factory(1, 2)); // std::unique_ptr<X> x(NewX(1, 2));
//
// This has the added advantage of working whether Factory returns a raw
// pointer or a `std::unique_ptr`.
// //
// While `absl::WrapUnique` is useful for capturing the output of a raw // While `absl::WrapUnique` is useful for capturing the output of a raw
// pointer factory, prefer 'absl::make_unique<T>(args...)' over // pointer factory, prefer 'absl::make_unique<T>(args...)' over

View file

@ -123,6 +123,28 @@ uint128 MakeUint128FromFloat(T v) {
return MakeUint128(0, static_cast<uint64_t>(v)); return MakeUint128(0, static_cast<uint64_t>(v));
} }
#if defined(__clang__) && !defined(__SSE3__)
// Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289
// Casting from long double to uint64_t is miscompiled and drops bits.
// It is more work, so only use when we need the workaround.
uint128 MakeUint128FromFloat(long double v) {
// Go 50 bits at a time, that fits in a double
static_assert(std::numeric_limits<double>::digits >= 50, "");
static_assert(std::numeric_limits<long double>::digits <= 150, "");
// Undefined behavior if v is not finite or cannot fit into uint128.
assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128));
v = std::ldexp(v, -100);
uint64_t w0 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
v = std::ldexp(v - static_cast<double>(w0), 50);
uint64_t w1 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
v = std::ldexp(v - static_cast<double>(w1), 50);
uint64_t w2 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
return (static_cast<uint128>(w0) << 100) | (static_cast<uint128>(w1) << 50) |
static_cast<uint128>(w2);
}
#endif // __clang__ && !__SSE3__
} // namespace } // namespace
uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {} uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {}

View file

@ -271,6 +271,20 @@ TEST(Uint128, ConversionTests) {
EXPECT_EQ(static_cast<absl::uint128>(round_to_zero), 0); EXPECT_EQ(static_cast<absl::uint128>(round_to_zero), 0);
EXPECT_EQ(static_cast<absl::uint128>(round_to_five), 5); EXPECT_EQ(static_cast<absl::uint128>(round_to_five), 5);
EXPECT_EQ(static_cast<absl::uint128>(round_to_nine), 9); EXPECT_EQ(static_cast<absl::uint128>(round_to_nine), 9);
absl::uint128 highest_precision_in_long_double =
~absl::uint128{} >> (128 - std::numeric_limits<long double>::digits);
EXPECT_EQ(highest_precision_in_long_double,
static_cast<absl::uint128>(
static_cast<long double>(highest_precision_in_long_double)));
// Apply a mask just to make sure all the bits are the right place.
const absl::uint128 arbitrary_mask =
absl::MakeUint128(0xa29f622677ded751, 0xf8ca66add076f468);
EXPECT_EQ(highest_precision_in_long_double & arbitrary_mask,
static_cast<absl::uint128>(static_cast<long double>(
highest_precision_in_long_double & arbitrary_mask)));
EXPECT_EQ(static_cast<absl::uint128>(-0.1L), 0);
} }
TEST(Uint128, OperatorAssignReturnRef) { TEST(Uint128, OperatorAssignReturnRef) {

View file

@ -32,7 +32,7 @@
#ifdef ABSL_HAVE_STD_STRING_VIEW #ifdef ABSL_HAVE_STD_STRING_VIEW
#include <string_view> #include <string_view> // IWYU pragma: export
namespace absl { namespace absl {
using std::string_view; using std::string_view;

View file

@ -4,7 +4,7 @@
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
# You may obtain a copy of the License at # You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # https://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, software # Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, # distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@ -72,7 +72,7 @@ split_seconds(const time_point<seconds>& tp) {
// //
// See also: // See also:
// - http://www.iana.org/time-zones // - http://www.iana.org/time-zones
// - http://en.wikipedia.org/wiki/Zoneinfo // - https://en.wikipedia.org/wiki/Zoneinfo
class time_zone { class time_zone {
public: public:
time_zone() : time_zone(nullptr) {} // Equivalent to UTC time_zone() : time_zone(nullptr) {} // Equivalent to UTC

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@ -25,7 +25,7 @@
// a grain of salt. // a grain of salt.
// //
// For more information see tzfile(5), http://www.iana.org/time-zones, or // For more information see tzfile(5), http://www.iana.org/time-zones, or
// http://en.wikipedia.org/wiki/Zoneinfo. // https://en.wikipedia.org/wiki/Zoneinfo.
// //
// Note that we assume the proleptic Gregorian calendar and 60-second // Note that we assume the proleptic Gregorian calendar and 60-second
// minutes throughout. // minutes throughout.

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,
@ -20,6 +20,11 @@
#include <dlfcn.h> #include <dlfcn.h>
#endif #endif
#endif #endif
#if defined(__APPLE__)
#include <CoreFoundation/CFTimeZone.h>
#endif
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <string> #include <string>
@ -121,6 +126,11 @@ time_zone local_time_zone() {
char* tz_env = nullptr; char* tz_env = nullptr;
#if defined(_MSC_VER) #if defined(_MSC_VER)
_dupenv_s(&tz_env, nullptr, "TZ"); _dupenv_s(&tz_env, nullptr, "TZ");
#elif defined(__APPLE__)
CFTimeZoneRef system_time_zone = CFTimeZoneCopySystem();
CFStringRef tz_name = CFTimeZoneGetName(system_time_zone);
tz_env = strdup(CFStringGetCStringPtr(tz_name, CFStringGetSystemEncoding()));
CFRelease(system_time_zone);
#else #else
tz_env = std::getenv("TZ"); tz_env = std::getenv("TZ");
#endif #endif
@ -153,6 +163,8 @@ time_zone local_time_zone() {
#if defined(_MSC_VER) #if defined(_MSC_VER)
free(localtime_env); free(localtime_env);
free(tz_env); free(tz_env);
#elif defined(__APPLE__)
free(tz_env);
#endif #endif
time_zone tz; time_zone tz;

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
// You may obtain a copy of the License at // You may obtain a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, // distributed under the License is distributed on an "AS IS" BASIS,

View file

@ -10,7 +10,7 @@
# #
# 1. ISO 3166-1 alpha-2 country code, current as of # 1. ISO 3166-1 alpha-2 country code, current as of
# ISO 3166-1 N905 (2016-11-15). See: Updates on ISO 3166-1 # ISO 3166-1 N905 (2016-11-15). See: Updates on ISO 3166-1
# http://isotc.iso.org/livelink/livelink/Open/16944257 # https://isotc.iso.org/livelink/livelink/Open/16944257
# 2. The usual English name for the coded region, # 2. The usual English name for the coded region,
# chosen so that alphabetic sorting of subsets produces helpful lists. # chosen so that alphabetic sorting of subsets produces helpful lists.
# This is not the same as the English name in the ISO 3166 tables. # This is not the same as the English name in the ISO 3166 tables.

View file

@ -58,7 +58,7 @@
#ifdef ABSL_HAVE_STD_ANY #ifdef ABSL_HAVE_STD_ANY
#include <any> #include <any> // IWYU pragma: export
namespace absl { namespace absl {
using std::any; using std::any;

View file

@ -40,7 +40,7 @@
#ifdef ABSL_HAVE_STD_OPTIONAL #ifdef ABSL_HAVE_STD_OPTIONAL
#include <optional> #include <optional> // IWYU pragma: export
namespace absl { namespace absl {
using std::bad_optional_access; using std::bad_optional_access;

View file

@ -47,7 +47,7 @@
#ifdef ABSL_HAVE_STD_VARIANT #ifdef ABSL_HAVE_STD_VARIANT
#include <variant> #include <variant> // IWYU pragma: export
namespace absl { namespace absl {
using std::bad_variant_access; using std::bad_variant_access;