Squashed 'third_party/abseil/' changes from ddf8e52a2..384af0e91

384af0e91 Export of internal Abseil changes
e7ca23aca Export of internal Abseil changes
4611a601a Export of internal Abseil changes
8a9ef3c5d Export of internal Abseil changes
9f8b87b71 Add missing word 'library' in the 'status' description (#868)
e2b1bab19 Export of internal Abseil changes
1bae23e32 Export of internal Abseil changes
6df644c56 Include the status library into the main README. (#863)
68f1ad932 Export of internal Abseil changes
52acfe6fc Export of internal Abseil changes
1918ad2ae Export of internal Abseil changes
938fd0f4e Export of internal Abseil changes
fbdff6f3a Export of internal Abseil changes
acf3390ca Export of internal Abseil changes
592924480 Export of internal Abseil changes
e80c0b353 Export of internal Abseil changes
5d8fc9192 Export of internal Abseil changes
e19260fd7 Export of internal Abseil changes
4fd9a1ec5 Export of internal Abseil changes
4ae673067 Export of internal Abseil changes
1b465af3b Export of internal Abseil changes
6b03bf543 fix build dll (#797)
0bbebc85c Export of internal Abseil changes
0453e1653 Export of internal Abseil changes
a4798817e Export of internal Abseil changes
e96d49687 Export of internal Abseil changes
731852f10 Fix stacktrace on aarch64 architecture. Fixes #805 (#827)
2e5f2bcfd moved deleted functions to public for better compiler errors. (#828)
e9e9b9fc7 Export of internal Abseil changes
b8e890f95 Export of internal Abseil changes
c9894d1dc Export of internal Abseil changes
e9b9e38f6 Export of internal Abseil changes
962b06754 Export of internal Abseil changes
5bf048b84 Export of internal Abseil changes
1e3d25b26 Export of internal Abseil changes
eb317a701 Export of internal Abseil changes
4b915e709 Export of internal Abseil changes
8f1c34a77 Export of internal Abseil changes
60d00a582 Export of internal Abseil changes
f3f785ab5 Export of internal Abseil changes
4b2fbb4ad Export of internal Abseil changes
e493d6acb fix compile fails with asan and -Wredundant-decls (#801)
e63a5a610 Export of internal Abseil changes
c678d6c6b Export of internal Abseil changes
4b4f9aae7 Export of internal Abseil changes
887d0eee6 Export of internal Abseil changes
b978fc02f Export of internal Abseil changes
093cc2760 Export of internal Abseil changes
40fdb59d3 btree: fix sign-compare warnings (#800)
1fd58b69c Export of internal Abseil changes
d1de75bf5 Export of internal Abseil changes
cad3f30b4 Export of internal Abseil changes
9927a0989 Export of internal Abseil changes
7680a5f8e Added missing asserts for seq.index() < capacity_ and unified their usage based on has_element(). (#781)
d3614de61 Export of internal Abseil changes
20feb1cdb Export of internal Abseil changes
c1ae0a497 Export of internal Abseil changes
6af91b351 Export of internal Abseil changes
f2c9c663d Export of internal Abseil changes
3c8b5d758 Export of internal Abseil changes
7ba8cdb56 Export of internal Abseil changes
930fbec75 Export of internal Abseil changes
0e9921b75 Export of internal Abseil changes
a4cbb5f69 Export of internal Abseil changes
4d2ff381a Export of internal Abseil changes
c03c18e7f Export of internal Abseil changes
b321ad86c Export of internal Abseil changes
fbf0fdab6 Export of internal Abseil changes
dc969f34a Export of internal Abseil changes
d0c433455 Export of internal Abseil changes
c6b3f2cf5 Export of internal Abseil changes
1beb3191c Export of internal Abseil changes
1b7e751e5 Export of internal Abseil changes
ce4bc9277 Export of internal Abseil changes
f72cc3516 Export of internal Abseil changes
f66bc7492 Export of internal Abseil changes
1995c6a3c Export of internal Abseil changes
184cf2524 Export of internal Abseil changes
82302f1e0 Export of internal Abseil changes
dea76486c Export of internal Abseil changes
d39fe6cd6 Export of internal Abseil changes
2c8a5b0d8 Export of internal Abseil changes
41a6263fd Export of internal Abseil changes
3c2bed2e7 Export of internal Abseil changes
ea8a689cf fix build on P9 (#739)
672d9e0ae Export of internal Abseil changes
f624790b7 Export of internal Abseil changes
55c04eb92 Export of internal Abseil changes
302b250e1 Disable pthread for standalone wasm build support (#721)
61d8bc057 Merge branch 'master' of https://github.com/abseil/abseil-cpp into master
4b5b25a28 cmake: remove unneeded enable_testing() cmd (#736)
63f2c695e cmake: flag conformance_testing as TESTONLY (#737)
d5269a8b6 Export of internal Abseil changes
23f1f9cf6 Typo in comment (#733)
259301a52 Fix CMake path for INSTALL_INCLUDEDIR (#723)
dc464c1dc Allow overriding Abseil IDE folder (#724)
bf655de09 Export of internal Abseil changes
38db52adb Export of internal Abseil changes
81f34df83 Export of internal Abseil changes
b86fff162 Export of internal Abseil changes
10cb35e45 Export of internal Abseil changes
4ccc0fce0 Export of internal Abseil changes
4a851046a Export of internal Abseil changes
ccdbb5941 Export of internal Abseil changes
01f5f81f9 Export of internal Abseil changes
2c92bdc7c Export of internal Abseil changes
e7ebf9803 Export of internal Abseil changes
2eba343b5 Export of internal Abseil changes
a8b03d90e Export of internal Abseil changes
1d31b5c36 Export of internal Abseil changes
da3a87690 Export of internal Abseil changes
8faf20461 Exclude empty directories (#697)
2069dc796 Export of internal Abseil changes
4832bf6bf Added a BUILD file in root to expose license. (#695)
af8f994af Export of internal Abseil changes
33caf1097 Export of internal Abseil changes
cf1a02e2d Export of internal Abseil changes
768eb2ca2 Export of internal Abseil changes
3f347c462 Fix build on riscv32 (#675)
62cf6a704 Export of internal Abseil changes
d118d4bb1 Export of internal Abseil changes
f2bc9d11e Fix public target name of the random library (#684)
0fecf0e63 Export of internal Abseil changes
cbfd0f0fe Export of internal Abseil changes
c45d1c09d Export of internal Abseil changes
a35ef8a62 Export of internal Abseil changes
bd317cae3 Export of internal Abseil changes
b11574465 fix MSVC warning 4245: conversion signed => unsigned during initialization (#678)
d85783fd0 Export of internal Abseil changes
a1d668990 Export of internal Abseil changes
ca9856cab Export of internal Abseil changes
6e18c7115 Export of internal Abseil changes
3f48ce1c4 init (#673)
cde2e2410 Export of internal Abseil changes
68494aae9 Fix CMake Threads dependency issue
902909a43 Export of internal Abseil changes
cb52b05ea Export of internal Abseil changes
1a02b7a20 Use "-lrt" instead of the resolved find_library result when linking librt (#665)
df60c82df Export of internal Abseil changes
b35973e3e Export of internal Abseil changes
db5773a72 Export of internal Abseil changes
71079e42c Export of internal Abseil changes
2946ac0de Use base_internal::AtomicHook instead of std::atomic (#661)
567bee2f7 Fix ABSL_RANDOM_RANDEN_COPTS setting on FreeBSD (#664)
bf6166a63 Export of internal Abseil changes
111260963 Export of internal Abseil changes
73ea9a957 Export of internal Abseil changes
c01b9916e  Add option to use an externally provided GoogleTest target (for usage of abseil as add_subdirectory target) (#647)
d43b7997c Export of internal Abseil changes
62f05b1f5 Export of internal Abseil changes
fba8a316c Export of internal Abseil changes
79e0dc115 Export of internal Abseil changes
132d791b4 bazel: Add missing load statements for cc_binary (#645)
518f17501 Export of internal Abseil changes
092ed9793 Export of internal Abseil changes
2d2a8aea2 Export of internal Abseil changes
7853a7586 Export of internal Abseil changes
c6954897f Export of internal Abseil changes
b92f35f65 Fix CompressedTuple move constructor on MSVC (#637)
a877af1f2 Export of internal Abseil changes
d936052d3 Export of internal Abseil changes
238b9a59c Skip the .exe suffix in the helpshort filter on Windows (#629)
417ea99cb UWP doesn't allow reading regkeys (#594)
40a0e58eb Export of internal Abseil changes
cf3a1998e Export of internal Abseil changes
b19ba9676 Export of internal Abseil changes
06f0e767d BuildBreak: UWP apps can't call GetModuleHandle (#596)
bcefbdcdf Export of internal Abseil changes
0033c9ea9 Fix build on FreeBSD/powerpc (#616)
0d5ce2797 Export of internal Abseil changes
b69c7d880 Export of internal Abseil changes
2a5633fc0 Merge "Export of internal Abseil changes"
f9b3d6e49 Add RISCV support to GetProgramCounter() (#621)
914ff4451 Export of internal Abseil changes
0232c87f2 Add missing ABSL_HAVE_VDSO_SUPPORT conditional (#622)
3c8141051 Export of internal Abseil changes
c44657f55 Export of internal Abseil changes
98eb410c9 Export of internal Abseil changes
bf78e9773 Export of internal Abseil changes
d95d15671 Export of internal Abseil changes
24713a703 Export of internal Abseil changes
72382c21f Export of internal Abseil changes
08a7e7bf9 Export of internal Abseil changes
36bcd9599 Fix pointer format specifier in documentation (#614)
0f86336b6 Export of internal Abseil changes
c512f118d Export of internal Abseil changes
37dd2562e Export of internal Abseil changes
444277026 fix: Add support for more ARM processors detection (#608)
159bf2bf6 Export of internal Abseil changes
a2e6adecc Use https links. (#586)
564001ae5 Export of internal Abseil changes
b3aaac8a3 Export of internal Abseil changes
63ee2f887 Export of internal Abseil changes
a048203a8 Export of internal Abseil changes
1de016636 Export of internal Abseil changes
ad904b6cd Export of internal Abseil changes
7bd1935dc cmake: Fix x86_64 check on Windows for random copts (#518)
292351391 Export of internal Abseil changes
bf86cfe16 Export of internal Abseil changes
12bc53e03 Export of internal Abseil changes
1e39f8626 Export of internal Abseil changes
77f87009a Export of internal Abseil changes
d659fe54b Export of internal Abseil changes
a4b757b5d Export of internal Abseil changes
0514227d2 Export of internal Abseil changes
7f4fe64af Export of internal Abseil changes
16d9fd58a Export of internal Abseil changes
bcaae6009 Export of internal Abseil changes
8ba96a824 Export of internal Abseil changes
2103fd9ac Export of internal Abseil changes
3df7b52a6 Export of internal Abseil changes
fa8c75182 Export of internal Abseil changes
85092b4b6 Fix Conan builds (#400)
e96ae2203 Export of internal Abseil changes
20de2db74 Export of internal Abseil changes
846e5dbed Export of internal Abseil changes
83880e3d8 Merge branch 'master' of https://github.com/abseil/abseil-cpp
8207907f4 Export of internal Abseil changes
39d68a422 docs: fix typo (#397)
078b89b3c Export of internal Abseil changes
19b021cb3 Export of internal Abseil changes
ecc0033b5 Always enable proper symbolize implementation on Windows (#257)
2796d500a Export of internal Abseil changes
e4c8d0eb8 Export of internal Abseil changes
a15364ce4 Export of internal Abseil changes
ab3552a18 Export of internal Abseil changes
e9f9000c7 Fix ABSL_WAITER_MODE detection for mingw (#342)
abea769b5 Fix ABSL_HAVE_ALARM check on mingw (#341)
25597bdfc Export of internal Abseil changes
aad33fefa Export of internal Abseil changes
8fe7214fe Export of internal Abseil changes
debac94cf Export of internal Abseil changes
882b3501a Fix spelling errors (#384)
502efe6d7 Export of internal Abseil changes
ccdd1d57b Export of internal Abseil changes

Change-Id: I59864a0053f6e03d88cc9d5e2a92757039a05484
git-subtree-dir: third_party/abseil
git-subtree-split: 384af0e9141283172e2bff3210dae79fb7130d9c
diff --git a/.github/ISSUE_TEMPLATE/00-bug_report.md b/.github/ISSUE_TEMPLATE/00-bug_report.md
new file mode 100644
index 0000000..1edf3de
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/00-bug_report.md
@@ -0,0 +1,41 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: 'bug'
+assignees: ''
+---
+
+**Describe the bug**
+
+Include a clear and concise description of what the problem is, including what
+you expected to happen, and what actually happened.
+
+**Steps to reproduce the bug**
+
+It's important that we are able to reproduce the problem that you are
+experiencing. Please provide all code and relevant steps to reproduce the
+problem, including your `BUILD`/`CMakeLists.txt` file and build commands. Links
+to a GitHub branch or [godbolt.org](https://godbolt.org/) that demonstrate the
+problem are also helpful.
+
+**What version of Abseil are you using?**
+
+**What operating system and version are you using**
+
+If you are using a Linux distribution please include the name and version of the
+distribution as well.
+
+**What compiler and version are you using?**
+
+Please include the output of `gcc -v` or `clang -v`, or the equivalent for your
+compiler.
+
+**What build system are you using?**
+
+Please include the output of `bazel --version` or `cmake --version`, or the
+equivalent for your build system.
+
+**Additional context**
+
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/90-question.md b/.github/ISSUE_TEMPLATE/90-question.md
new file mode 100644
index 0000000..84cf349
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/90-question.md
@@ -0,0 +1,7 @@
+---
+name: Question
+about: Have a question? Ask us anything! :-)
+title: ''
+labels: 'question'
+assignees: ''
+---
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000..9794ae1
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1 @@
+blank_issues_enables: true
diff --git a/BUILD.bazel b/BUILD.bazel
new file mode 100644
index 0000000..79fb0ec
--- /dev/null
+++ b/BUILD.bazel
@@ -0,0 +1,25 @@
+#
+# Copyright 2020 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])  # Apache 2.0
+
+# Expose license for external usage through bazel.
+exports_files([
+    "AUTHORS",
+    "LICENSE",
+])
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
new file mode 100644
index 0000000..7c98b21
--- /dev/null
+++ b/CMake/AbseilDll.cmake
@@ -0,0 +1,519 @@
+include(CMakeParseArguments)
+
+set(ABSL_INTERNAL_DLL_FILES
+  "algorithm/algorithm.h"
+  "algorithm/container.h"
+  "base/attributes.h"
+  "base/call_once.h"
+  "base/casts.h"
+  "base/config.h"
+  "base/const_init.h"
+  "base/dynamic_annotations.h"
+  "base/internal/atomic_hook.h"
+  "base/internal/cycleclock.cc"
+  "base/internal/cycleclock.h"
+  "base/internal/direct_mmap.h"
+  "base/internal/dynamic_annotations.h"
+  "base/internal/endian.h"
+  "base/internal/errno_saver.h"
+  "base/internal/exponential_biased.cc"
+  "base/internal/exponential_biased.h"
+  "base/internal/fast_type_id.h"
+  "base/internal/hide_ptr.h"
+  "base/internal/identity.h"
+  "base/internal/invoke.h"
+  "base/internal/inline_variable.h"
+  "base/internal/low_level_alloc.cc"
+  "base/internal/low_level_alloc.h"
+  "base/internal/low_level_scheduling.h"
+  "base/internal/per_thread_tls.h"
+  "base/internal/periodic_sampler.cc"
+  "base/internal/periodic_sampler.h"
+  "base/internal/pretty_function.h"
+  "base/internal/raw_logging.cc"
+  "base/internal/raw_logging.h"
+  "base/internal/scheduling_mode.h"
+  "base/internal/scoped_set_env.cc"
+  "base/internal/scoped_set_env.h"
+  "base/internal/strerror.h"
+  "base/internal/strerror.cc"
+  "base/internal/spinlock.cc"
+  "base/internal/spinlock.h"
+  "base/internal/spinlock_wait.cc"
+  "base/internal/spinlock_wait.h"
+  "base/internal/sysinfo.cc"
+  "base/internal/sysinfo.h"
+  "base/internal/thread_annotations.h"
+  "base/internal/thread_identity.cc"
+  "base/internal/thread_identity.h"
+  "base/internal/throw_delegate.cc"
+  "base/internal/throw_delegate.h"
+  "base/internal/tsan_mutex_interface.h"
+  "base/internal/unaligned_access.h"
+  "base/internal/unscaledcycleclock.cc"
+  "base/internal/unscaledcycleclock.h"
+  "base/log_severity.cc"
+  "base/log_severity.h"
+  "base/macros.h"
+  "base/optimization.h"
+  "base/options.h"
+  "base/policy_checks.h"
+  "base/port.h"
+  "base/thread_annotations.h"
+  "container/btree_map.h"
+  "container/btree_set.h"
+  "container/fixed_array.h"
+  "container/flat_hash_map.h"
+  "container/flat_hash_set.h"
+  "container/inlined_vector.h"
+  "container/internal/btree.h"
+  "container/internal/btree_container.h"
+  "container/internal/common.h"
+  "container/internal/compressed_tuple.h"
+  "container/internal/container_memory.h"
+  "container/internal/counting_allocator.h"
+  "container/internal/hash_function_defaults.h"
+  "container/internal/hash_policy_traits.h"
+  "container/internal/hashtable_debug.h"
+  "container/internal/hashtable_debug_hooks.h"
+  "container/internal/hashtablez_sampler.cc"
+  "container/internal/hashtablez_sampler.h"
+  "container/internal/hashtablez_sampler_force_weak_definition.cc"
+  "container/internal/have_sse.h"
+  "container/internal/inlined_vector.h"
+  "container/internal/layout.h"
+  "container/internal/node_hash_policy.h"
+  "container/internal/raw_hash_map.h"
+  "container/internal/raw_hash_set.cc"
+  "container/internal/raw_hash_set.h"
+  "container/internal/tracked.h"
+  "container/node_hash_map.h"
+  "container/node_hash_set.h"
+  "debugging/failure_signal_handler.cc"
+  "debugging/failure_signal_handler.h"
+  "debugging/leak_check.h"
+  "debugging/leak_check_disable.cc"
+  "debugging/stacktrace.cc"
+  "debugging/stacktrace.h"
+  "debugging/symbolize.cc"
+  "debugging/symbolize.h"
+  "debugging/internal/address_is_readable.cc"
+  "debugging/internal/address_is_readable.h"
+  "debugging/internal/demangle.cc"
+  "debugging/internal/demangle.h"
+  "debugging/internal/elf_mem_image.cc"
+  "debugging/internal/elf_mem_image.h"
+  "debugging/internal/examine_stack.cc"
+  "debugging/internal/examine_stack.h"
+  "debugging/internal/stack_consumption.cc"
+  "debugging/internal/stack_consumption.h"
+  "debugging/internal/stacktrace_config.h"
+  "debugging/internal/symbolize.h"
+  "debugging/internal/vdso_support.cc"
+  "debugging/internal/vdso_support.h"
+  "functional/internal/front_binder.h"
+  "functional/bind_front.h"
+  "functional/function_ref.h"
+  "functional/internal/function_ref.h"
+  "hash/hash.h"
+  "hash/internal/city.h"
+  "hash/internal/city.cc"
+  "hash/internal/hash.h"
+  "hash/internal/hash.cc"
+  "hash/internal/spy_hash_state.h"
+  "hash/internal/wyhash.h"
+  "hash/internal/wyhash.cc"
+  "memory/memory.h"
+  "meta/type_traits.h"
+  "numeric/bits.h"
+  "numeric/int128.cc"
+  "numeric/int128.h"
+  "numeric/internal/bits.h"
+  "random/bernoulli_distribution.h"
+  "random/beta_distribution.h"
+  "random/bit_gen_ref.h"
+  "random/discrete_distribution.cc"
+  "random/discrete_distribution.h"
+  "random/distributions.h"
+  "random/exponential_distribution.h"
+  "random/gaussian_distribution.cc"
+  "random/gaussian_distribution.h"
+  "random/internal/distribution_caller.h"
+  "random/internal/fastmath.h"
+  "random/internal/fast_uniform_bits.h"
+  "random/internal/generate_real.h"
+  "random/internal/iostream_state_saver.h"
+  "random/internal/mock_helpers.h"
+  "random/internal/nonsecure_base.h"
+  "random/internal/pcg_engine.h"
+  "random/internal/platform.h"
+  "random/internal/pool_urbg.cc"
+  "random/internal/pool_urbg.h"
+  "random/internal/randen.cc"
+  "random/internal/randen.h"
+  "random/internal/randen_detect.cc"
+  "random/internal/randen_detect.h"
+  "random/internal/randen_engine.h"
+  "random/internal/randen_hwaes.cc"
+  "random/internal/randen_hwaes.h"
+  "random/internal/randen_round_keys.cc"
+  "random/internal/randen_slow.cc"
+  "random/internal/randen_slow.h"
+  "random/internal/randen_traits.h"
+  "random/internal/salted_seed_seq.h"
+  "random/internal/seed_material.cc"
+  "random/internal/seed_material.h"
+  "random/internal/sequence_urbg.h"
+  "random/internal/traits.h"
+  "random/internal/uniform_helper.h"
+  "random/internal/wide_multiply.h"
+  "random/log_uniform_int_distribution.h"
+  "random/poisson_distribution.h"
+  "random/random.h"
+  "random/seed_gen_exception.cc"
+  "random/seed_gen_exception.h"
+  "random/seed_sequences.cc"
+  "random/seed_sequences.h"
+  "random/uniform_int_distribution.h"
+  "random/uniform_real_distribution.h"
+  "random/zipf_distribution.h"
+  "status/internal/status_internal.h"
+  "status/internal/statusor_internal.h"
+  "status/status.h"
+  "status/status.cc"
+  "status/statusor.h"
+  "status/statusor.cc"
+  "status/status_payload_printer.h"
+  "status/status_payload_printer.cc"
+  "strings/ascii.cc"
+  "strings/ascii.h"
+  "strings/charconv.cc"
+  "strings/charconv.h"
+  "strings/cord.cc"
+  "strings/cord.h"
+  "strings/escaping.cc"
+  "strings/escaping.h"
+  "strings/internal/cord_internal.cc"
+  "strings/internal/cord_internal.h"
+  "strings/internal/cord_rep_flat.h"
+  "strings/internal/charconv_bigint.cc"
+  "strings/internal/charconv_bigint.h"
+  "strings/internal/charconv_parse.cc"
+  "strings/internal/charconv_parse.h"
+  "strings/internal/stl_type_traits.h"
+  "strings/internal/string_constant.h"
+  "strings/match.cc"
+  "strings/match.h"
+  "strings/numbers.cc"
+  "strings/numbers.h"
+  "strings/str_format.h"
+  "strings/str_cat.cc"
+  "strings/str_cat.h"
+  "strings/str_join.h"
+  "strings/str_replace.cc"
+  "strings/str_replace.h"
+  "strings/str_split.cc"
+  "strings/str_split.h"
+  "strings/string_view.cc"
+  "strings/string_view.h"
+  "strings/strip.h"
+  "strings/substitute.cc"
+  "strings/substitute.h"
+  "strings/internal/char_map.h"
+  "strings/internal/escaping.h"
+  "strings/internal/escaping.cc"
+  "strings/internal/memutil.cc"
+  "strings/internal/memutil.h"
+  "strings/internal/ostringstream.cc"
+  "strings/internal/ostringstream.h"
+  "strings/internal/pow10_helper.cc"
+  "strings/internal/pow10_helper.h"
+  "strings/internal/resize_uninitialized.h"
+  "strings/internal/str_format/arg.cc"
+  "strings/internal/str_format/arg.h"
+  "strings/internal/str_format/bind.cc"
+  "strings/internal/str_format/bind.h"
+  "strings/internal/str_format/checker.h"
+  "strings/internal/str_format/extension.cc"
+  "strings/internal/str_format/extension.h"
+  "strings/internal/str_format/float_conversion.cc"
+  "strings/internal/str_format/float_conversion.h"
+  "strings/internal/str_format/output.cc"
+  "strings/internal/str_format/output.h"
+  "strings/internal/str_format/parser.cc"
+  "strings/internal/str_format/parser.h"
+  "strings/internal/str_join_internal.h"
+  "strings/internal/str_split_internal.h"
+  "strings/internal/utf8.cc"
+  "strings/internal/utf8.h"
+  "synchronization/barrier.cc"
+  "synchronization/barrier.h"
+  "synchronization/blocking_counter.cc"
+  "synchronization/blocking_counter.h"
+  "synchronization/mutex.cc"
+  "synchronization/mutex.h"
+  "synchronization/notification.cc"
+  "synchronization/notification.h"
+  "synchronization/internal/create_thread_identity.cc"
+  "synchronization/internal/create_thread_identity.h"
+  "synchronization/internal/futex.h"
+  "synchronization/internal/graphcycles.cc"
+  "synchronization/internal/graphcycles.h"
+  "synchronization/internal/kernel_timeout.h"
+  "synchronization/internal/per_thread_sem.cc"
+  "synchronization/internal/per_thread_sem.h"
+  "synchronization/internal/thread_pool.h"
+  "synchronization/internal/waiter.cc"
+  "synchronization/internal/waiter.h"
+  "time/civil_time.cc"
+  "time/civil_time.h"
+  "time/clock.cc"
+  "time/clock.h"
+  "time/duration.cc"
+  "time/format.cc"
+  "time/time.cc"
+  "time/time.h"
+  "time/internal/cctz/include/cctz/civil_time.h"
+  "time/internal/cctz/include/cctz/civil_time_detail.h"
+  "time/internal/cctz/include/cctz/time_zone.h"
+  "time/internal/cctz/include/cctz/zone_info_source.h"
+  "time/internal/cctz/src/civil_time_detail.cc"
+  "time/internal/cctz/src/time_zone_fixed.cc"
+  "time/internal/cctz/src/time_zone_fixed.h"
+  "time/internal/cctz/src/time_zone_format.cc"
+  "time/internal/cctz/src/time_zone_if.cc"
+  "time/internal/cctz/src/time_zone_if.h"
+  "time/internal/cctz/src/time_zone_impl.cc"
+  "time/internal/cctz/src/time_zone_impl.h"
+  "time/internal/cctz/src/time_zone_info.cc"
+  "time/internal/cctz/src/time_zone_info.h"
+  "time/internal/cctz/src/time_zone_libc.cc"
+  "time/internal/cctz/src/time_zone_libc.h"
+  "time/internal/cctz/src/time_zone_lookup.cc"
+  "time/internal/cctz/src/time_zone_posix.cc"
+  "time/internal/cctz/src/time_zone_posix.h"
+  "time/internal/cctz/src/tzfile.h"
+  "time/internal/cctz/src/zone_info_source.cc"
+  "types/any.h"
+  "types/bad_any_cast.cc"
+  "types/bad_any_cast.h"
+  "types/bad_optional_access.cc"
+  "types/bad_optional_access.h"
+  "types/bad_variant_access.cc"
+  "types/bad_variant_access.h"
+  "types/compare.h"
+  "types/internal/conformance_aliases.h"
+  "types/internal/conformance_archetype.h"
+  "types/internal/conformance_profile.h"
+  "types/internal/parentheses.h"
+  "types/internal/transform_args.h"
+  "types/internal/variant.h"
+  "types/optional.h"
+  "types/internal/optional.h"
+  "types/span.h"
+  "types/internal/span.h"
+  "types/variant.h"
+  "utility/utility.h"
+)
+
+set(ABSL_INTERNAL_DLL_TARGETS
+  "stacktrace"
+  "symbolize"
+  "examine_stack"
+  "failure_signal_handler"
+  "debugging_internal"
+  "demangle_internal"
+  "leak_check"
+  "leak_check_disable"
+  "stack_consumption"
+  "debugging"
+  "hash"
+  "spy_hash_state"
+  "city"
+  "memory"
+  "strings"
+  "strings_internal"
+  "cord"
+  "str_format"
+  "str_format_internal"
+  "pow10_helper"
+  "int128"
+  "numeric"
+  "utility"
+  "any"
+  "bad_any_cast"
+  "bad_any_cast_impl"
+  "span"
+  "optional"
+  "bad_optional_access"
+  "bad_variant_access"
+  "variant"
+  "compare"
+  "algorithm"
+  "algorithm_container"
+  "graphcycles_internal"
+  "kernel_timeout_internal"
+  "synchronization"
+  "thread_pool"
+  "bind_front"
+  "function_ref"
+  "atomic_hook"
+  "log_severity"
+  "raw_logging_internal"
+  "spinlock_wait"
+  "config"
+  "dynamic_annotations"
+  "core_headers"
+  "malloc_internal"
+  "base_internal"
+  "base"
+  "throw_delegate"
+  "pretty_function"
+  "endian"
+  "bits"
+  "exponential_biased"
+  "periodic_sampler"
+  "scoped_set_env"
+  "type_traits"
+  "meta"
+  "random_random"
+  "random_bit_gen_ref"
+  "random_distributions"
+  "random_seed_gen_exception"
+  "random_seed_sequences"
+  "random_internal_traits"
+  "random_internal_distribution_caller"
+  "random_internal_distributions"
+  "random_internal_fast_uniform_bits"
+  "random_internal_seed_material"
+  "random_internal_pool_urbg"
+  "random_internal_explicit_seed_seq"
+  "random_internal_sequence_urbg"
+  "random_internal_salted_seed_seq"
+  "random_internal_iostream_state_saver"
+  "random_internal_generate_real"
+  "random_internal_wide_multiply"
+  "random_internal_fastmath"
+  "random_internal_nonsecure_base"
+  "random_internal_pcg_engine"
+  "random_internal_randen_engine"
+  "random_internal_platform"
+  "random_internal_randen"
+  "random_internal_randen_slow"
+  "random_internal_randen_hwaes"
+  "random_internal_randen_hwaes_impl"
+  "random_internal_uniform_helper"
+  "status"
+  "time"
+  "civil_time"
+  "time_zone"
+  "container"
+  "btree"
+  "compressed_tuple"
+  "fixed_array"
+  "inlined_vector_internal"
+  "inlined_vector"
+  "counting_allocator"
+  "flat_hash_map"
+  "flat_hash_set"
+  "node_hash_map"
+  "node_hash_set"
+  "container_memory"
+  "hash_function_defaults"
+  "hash_policy_traits"
+  "hashtablez_sampler"
+  "hashtable_debug"
+  "hashtable_debug_hooks"
+  "have_sse"
+  "node_hash_policy"
+  "raw_hash_map"
+  "container_common"
+  "raw_hash_set"
+  "layout"
+  "tracked"
+)
+
+function(absl_internal_dll_contains)
+  cmake_parse_arguments(ABSL_INTERNAL_DLL
+    ""
+    "OUTPUT;TARGET"
+    ""
+    ${ARGN}
+  )
+
+  STRING(REGEX REPLACE "^absl::" "" _target ${ABSL_INTERNAL_DLL_TARGET})
+
+  list(FIND
+    ABSL_INTERNAL_DLL_TARGETS
+    "${_target}"
+    _index)
+
+  if (${_index} GREATER -1)
+    set(${ABSL_INTERNAL_DLL_OUTPUT} 1 PARENT_SCOPE)
+  else()
+    set(${ABSL_INTERNAL_DLL_OUTPUT} 0 PARENT_SCOPE)
+  endif()
+endfunction()
+
+function(absl_internal_dll_targets)
+  cmake_parse_arguments(ABSL_INTERNAL_DLL
+  ""
+  "OUTPUT"
+  "DEPS"
+  ${ARGN}
+  )
+
+  set(_deps "")
+  foreach(dep IN LISTS ABSL_INTERNAL_DLL_DEPS)
+    absl_internal_dll_contains(TARGET ${dep} OUTPUT _contains)
+    if (_contains)
+      list(APPEND _deps abseil_dll)
+    else()
+      list(APPEND _deps ${dep})
+    endif()
+  endforeach()
+
+  # Because we may have added the DLL multiple times
+  list(REMOVE_DUPLICATES _deps)
+  set(${ABSL_INTERNAL_DLL_OUTPUT} "${_deps}" PARENT_SCOPE)
+endfunction()
+
+function(absl_make_dll)
+  add_library(
+    abseil_dll
+    SHARED
+      "${ABSL_INTERNAL_DLL_FILES}"
+  )
+  target_link_libraries(
+    abseil_dll
+    PRIVATE
+      ${ABSL_DEFAULT_LINKOPTS}
+  )
+  set_property(TARGET abseil_dll PROPERTY LINKER_LANGUAGE "CXX")
+  target_include_directories(
+    abseil_dll
+    PUBLIC
+      "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
+      $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
+  )
+
+  target_compile_options(
+    abseil_dll
+    PRIVATE
+      ${ABSL_DEFAULT_COPTS}
+  )
+
+  target_compile_definitions(
+    abseil_dll
+    PRIVATE
+      ABSL_BUILD_DLL
+      NOMINMAX
+    INTERFACE
+      ${ABSL_CC_LIB_DEFINES}
+  )
+  install(TARGETS abseil_dll EXPORT ${PROJECT_NAME}Targets
+        RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR}
+        LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR}
+        ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR}
+  )
+endfunction()
diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake
index 67b97fe..e88507d 100644
--- a/CMake/AbseilHelpers.cmake
+++ b/CMake/AbseilHelpers.cmake
@@ -16,13 +16,16 @@
 
 include(CMakeParseArguments)
 include(AbseilConfigureCopts)
+include(AbseilDll)
 include(AbseilInstallDirs)
 
 # The IDE folder for Abseil that will be used if Abseil is included in a CMake
 # project that sets
 #    set_property(GLOBAL PROPERTY USE_FOLDERS ON)
 # For example, Visual Studio supports folders.
-set(ABSL_IDE_FOLDER Abseil)
+if(NOT DEFINED ABSL_IDE_FOLDER)
+  set(ABSL_IDE_FOLDER Abseil)
+endif()
 
 # absl_cc_library()
 #
@@ -80,95 +83,220 @@
     ${ARGN}
   )
 
-  if(NOT ABSL_CC_LIB_TESTONLY OR ABSL_RUN_TESTS)
-    if(ABSL_ENABLE_INSTALL)
-      set(_NAME "${ABSL_CC_LIB_NAME}")
-    else()
-      set(_NAME "absl_${ABSL_CC_LIB_NAME}")
-    endif()
+  if(ABSL_CC_LIB_TESTONLY AND NOT ABSL_RUN_TESTS)
+    return()
+  endif()
 
-    # Check if this is a header-only library
-    # Note that as of February 2019, many popular OS's (for example, Ubuntu
-    # 16.04 LTS) only come with cmake 3.5 by default.  For this reason, we can't
-    # use list(FILTER...)
-    set(ABSL_CC_SRCS "${ABSL_CC_LIB_SRCS}")
-    foreach(src_file IN LISTS ABSL_CC_SRCS)
-      if(${src_file} MATCHES ".*\\.(h|inc)")
-        list(REMOVE_ITEM ABSL_CC_SRCS "${src_file}")
-      endif()
-    endforeach()
-    if("${ABSL_CC_SRCS}" STREQUAL "")
+  if(ABSL_ENABLE_INSTALL)
+    set(_NAME "${ABSL_CC_LIB_NAME}")
+  else()
+    set(_NAME "absl_${ABSL_CC_LIB_NAME}")
+  endif()
+
+  # Check if this is a header-only library
+  # Note that as of February 2019, many popular OS's (for example, Ubuntu
+  # 16.04 LTS) only come with cmake 3.5 by default.  For this reason, we can't
+  # use list(FILTER...)
+  set(ABSL_CC_SRCS "${ABSL_CC_LIB_SRCS}")
+  foreach(src_file IN LISTS ABSL_CC_SRCS)
+    if(${src_file} MATCHES ".*\\.(h|inc)")
+      list(REMOVE_ITEM ABSL_CC_SRCS "${src_file}")
+    endif()
+  endforeach()
+
+  if("${ABSL_CC_SRCS}" STREQUAL "")
+    set(ABSL_CC_LIB_IS_INTERFACE 1)
+  else()
+    set(ABSL_CC_LIB_IS_INTERFACE 0)
+  endif()
+
+  # Determine this build target's relationship to the DLL. It's one of four things:
+  # 1. "dll"     -- This target is part of the DLL
+  # 2. "dll_dep" -- This target is not part of the DLL, but depends on the DLL.
+  #                 Note that we assume any target not in the DLL depends on the
+  #                 DLL. This is not a technical necessity but a convenience
+  #                 which happens to be true, because nearly every target is
+  #                 part of the DLL.
+  # 3. "shared"  -- This is a shared library, perhaps on a non-windows platform
+  #                 where DLL doesn't make sense.
+  # 4. "static"  -- This target does not depend on the DLL and should be built
+  #                 statically.
+  if (${ABSL_BUILD_DLL})
+    if(ABSL_ENABLE_INSTALL)
+      absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll)
+    else()
+      absl_internal_dll_contains(TARGET ${ABSL_CC_LIB_NAME} OUTPUT _in_dll)
+    endif()
+    if (${_in_dll})
+      # This target should be replaced by the DLL
+      set(_build_type "dll")
       set(ABSL_CC_LIB_IS_INTERFACE 1)
     else()
-      set(ABSL_CC_LIB_IS_INTERFACE 0)
+      # Building a DLL, but this target is not part of the DLL
+      set(_build_type "dll_dep")
     endif()
+  elseif(BUILD_SHARED_LIBS)
+    set(_build_type "shared")
+  else()
+    set(_build_type "static")
+  endif()
 
-    if(NOT ABSL_CC_LIB_IS_INTERFACE)
+  # Generate a pkg-config file for every library:
+  if(${_build_type} STREQUAL "static" OR ${_build_type} STREQUAL "shared")
+    if(NOT ABSL_CC_LIB_TESTONLY)
+      if(absl_VERSION)
+        set(PC_VERSION "${absl_VERSION}")
+      else()
+        set(PC_VERSION "head")
+      endif()
+      foreach(dep ${ABSL_CC_LIB_DEPS})
+        if(${dep} MATCHES "^absl::(.*)")
+          set(PC_DEPS "${PC_DEPS} absl_${CMAKE_MATCH_1} = ${PC_VERSION}")
+        endif()
+      endforeach()
+      foreach(cflag ${ABSL_CC_LIB_COPTS})
+        if(${cflag} MATCHES "^(-Wno|/wd)")
+          # These flags are needed to suppress warnings that might fire in our headers.
+          set(PC_CFLAGS "${PC_CFLAGS} ${cflag}")
+        elseif(${cflag} MATCHES "^(-W|/w[1234eo])")
+          # Don't impose our warnings on others.
+        else()
+          set(PC_CFLAGS "${PC_CFLAGS} ${cflag}")
+        endif()
+      endforeach()
+      FILE(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" CONTENT "\
+prefix=${CMAKE_INSTALL_PREFIX}\n\
+exec_prefix=\${prefix}\n\
+libdir=\${prefix}/lib\n\
+includedir=\${prefix}/include\n\
+\n\
+Name: absl_${_NAME}\n\
+Description: Abseil ${_NAME} library\n\
+URL: https://abseil.io/\n\
+Version: ${PC_VERSION}\n\
+Requires.private:${PC_DEPS}\n\
+Libs: -L\${libdir} $<JOIN:${ABSL_CC_LIB_LINKOPTS}, > $<$<NOT:$<BOOL:${ABSL_CC_LIB_IS_INTERFACE}>>:-labsl_${_NAME}>\n\
+Cflags: -I\${includedir}${PC_CFLAGS}\n")
+      INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc"
+              DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
+    endif()
+  endif()
+
+  if(NOT ABSL_CC_LIB_IS_INTERFACE)
+    if(${_build_type} STREQUAL "dll_dep")
+      # This target depends on the DLL. When adding dependencies to this target,
+      # any depended-on-target which is contained inside the DLL is replaced
+      # with a dependency on the DLL.
       add_library(${_NAME} STATIC "")
       target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
-      target_include_directories(${_NAME}
-        PUBLIC
-          "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
-          $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
+      absl_internal_dll_targets(
+        DEPS ${ABSL_CC_LIB_DEPS}
+        OUTPUT _dll_deps
       )
-      target_compile_options(${_NAME}
-        PRIVATE ${ABSL_CC_LIB_COPTS})
       target_link_libraries(${_NAME}
-        PUBLIC ${ABSL_CC_LIB_DEPS}
+        PUBLIC ${_dll_deps}
         PRIVATE
           ${ABSL_CC_LIB_LINKOPTS}
           ${ABSL_DEFAULT_LINKOPTS}
       )
-      target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_LIB_DEFINES})
 
-      # Add all Abseil targets to a a folder in the IDE for organization.
-      if(ABSL_CC_LIB_PUBLIC)
-        set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
-      elseif(ABSL_CC_LIB_TESTONLY)
-        set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
+      if (ABSL_CC_LIB_TESTONLY)
+        set(_gtest_link_define "GTEST_LINKED_AS_SHARED_LIBRARY=1")
       else()
-        set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal)
+        set(_gtest_link_define)
       endif()
 
-      # INTERFACE libraries can't have the CXX_STANDARD property set
-      set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
-      set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
+      target_compile_definitions(${_NAME}
+        PUBLIC
+          ABSL_CONSUME_DLL
+          "${_gtest_link_define}"
+      )
 
-      # When being installed, we lose the absl_ prefix.  We want to put it back
-      # to have properly named lib files.  This is a no-op when we are not being
-      # installed.
-      set_target_properties(${_NAME} PROPERTIES
-        OUTPUT_NAME "absl_${_NAME}"
+    elseif(${_build_type} STREQUAL "static" OR ${_build_type} STREQUAL "shared")
+      add_library(${_NAME} "")
+      target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
+      target_link_libraries(${_NAME}
+      PUBLIC ${ABSL_CC_LIB_DEPS}
+      PRIVATE
+        ${ABSL_CC_LIB_LINKOPTS}
+        ${ABSL_DEFAULT_LINKOPTS}
       )
     else()
-      # Generating header-only library
-      add_library(${_NAME} INTERFACE)
-      target_include_directories(${_NAME}
-        INTERFACE
-          "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
-          $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
-        )
-      target_link_libraries(${_NAME}
-        INTERFACE
-          ${ABSL_CC_LIB_DEPS}
-          ${ABSL_CC_LIB_LINKOPTS}
-          ${ABSL_DEFAULT_LINKOPTS}
-      )
-      target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
+      message(FATAL_ERROR "Invalid build type: ${_build_type}")
     endif()
 
-    # TODO currently we don't install googletest alongside abseil sources, so
-    # installed abseil can't be tested.
-    if(NOT ABSL_CC_LIB_TESTONLY AND ABSL_ENABLE_INSTALL)
-      install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets
-            RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR}
-            LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR}
-            ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR}
+    # Linker language can be inferred from sources, but in the case of DLLs we
+    # don't have any .cc files so it would be ambiguous. We could set it
+    # explicitly only in the case of DLLs but, because "CXX" is always the
+    # correct linker language for static or for shared libraries, we set it
+    # unconditionally.
+    set_property(TARGET ${_NAME} PROPERTY LINKER_LANGUAGE "CXX")
+
+    target_include_directories(${_NAME}
+      PUBLIC
+        "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
+        $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
+    )
+    target_compile_options(${_NAME}
+      PRIVATE ${ABSL_CC_LIB_COPTS})
+    target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_LIB_DEFINES})
+
+    # Add all Abseil targets to a a folder in the IDE for organization.
+    if(ABSL_CC_LIB_PUBLIC)
+      set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
+    elseif(ABSL_CC_LIB_TESTONLY)
+      set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
+    else()
+      set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal)
+    endif()
+
+    # INTERFACE libraries can't have the CXX_STANDARD property set
+    set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
+    set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
+
+    # When being installed, we lose the absl_ prefix.  We want to put it back
+    # to have properly named lib files.  This is a no-op when we are not being
+    # installed.
+    if(ABSL_ENABLE_INSTALL)
+      set_target_properties(${_NAME} PROPERTIES
+        OUTPUT_NAME "absl_${_NAME}"
+        # TODO(b/173696973): Figure out how to set SOVERSION for LTS releases.
+        SOVERSION 0
       )
     endif()
+  else()
+    # Generating header-only library
+    add_library(${_NAME} INTERFACE)
+    target_include_directories(${_NAME}
+      INTERFACE
+        "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
+        $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
+      )
+
+    if (${_build_type} STREQUAL "dll")
+        set(ABSL_CC_LIB_DEPS abseil_dll)
+    endif()
+
+    target_link_libraries(${_NAME}
+      INTERFACE
+        ${ABSL_CC_LIB_DEPS}
+        ${ABSL_CC_LIB_LINKOPTS}
+        ${ABSL_DEFAULT_LINKOPTS}
+    )
+    target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
+  endif()
+
+  # TODO currently we don't install googletest alongside abseil sources, so
+  # installed abseil can't be tested.
+  if(NOT ABSL_CC_LIB_TESTONLY AND ABSL_ENABLE_INSTALL)
+    install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets
+          RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR}
+          LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR}
+          ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR}
+    )
+  endif()
 
     add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME})
-  endif()
 endfunction()
 
 # absl_cc_test()
@@ -221,23 +349,42 @@
   )
 
   set(_NAME "absl_${ABSL_CC_TEST_NAME}")
+
   add_executable(${_NAME} "")
   target_sources(${_NAME} PRIVATE ${ABSL_CC_TEST_SRCS})
   target_include_directories(${_NAME}
     PUBLIC ${ABSL_COMMON_INCLUDE_DIRS}
     PRIVATE ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
   )
-  target_compile_definitions(${_NAME}
-    PUBLIC ${ABSL_CC_TEST_DEFINES}
-  )
+
+  if (${ABSL_BUILD_DLL})
+    target_compile_definitions(${_NAME}
+      PUBLIC
+        ${ABSL_CC_TEST_DEFINES}
+        ABSL_CONSUME_DLL
+        GTEST_LINKED_AS_SHARED_LIBRARY=1
+    )
+
+    # Replace dependencies on targets inside the DLL with abseil_dll itself.
+    absl_internal_dll_targets(
+      DEPS ${ABSL_CC_TEST_DEPS}
+      OUTPUT ABSL_CC_TEST_DEPS
+    )
+  else()
+    target_compile_definitions(${_NAME}
+      PUBLIC
+        ${ABSL_CC_TEST_DEFINES}
+    )
+  endif()
   target_compile_options(${_NAME}
     PRIVATE ${ABSL_CC_TEST_COPTS}
   )
+
   target_link_libraries(${_NAME}
     PUBLIC ${ABSL_CC_TEST_DEPS}
     PRIVATE ${ABSL_CC_TEST_LINKOPTS}
   )
-  # Add all Abseil targets to a a folder in the IDE for organization.
+  # Add all Abseil targets to a folder in the IDE for organization.
   set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
 
   set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
diff --git a/CMake/AbseilInstallDirs.cmake b/CMake/AbseilInstallDirs.cmake
index b67272f..6fc914b 100644
--- a/CMake/AbseilInstallDirs.cmake
+++ b/CMake/AbseilInstallDirs.cmake
@@ -10,11 +10,11 @@
   set(ABSL_SUBDIR "${PROJECT_NAME}_${PROJECT_VERSION}")
   set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}/${ABSL_SUBDIR}")
   set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${ABSL_SUBDIR}")
-  set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/{ABSL_SUBDIR}")
+  set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/${ABSL_SUBDIR}")
   set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}/${ABSL_SUBDIR}")
 else()
   set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}")
   set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
   set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
   set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
-endif()
\ No newline at end of file
+endif()
diff --git a/CMake/Googletest/CMakeLists.txt.in b/CMake/Googletest/CMakeLists.txt.in
index d60a33e..5769e3a 100644
--- a/CMake/Googletest/CMakeLists.txt.in
+++ b/CMake/Googletest/CMakeLists.txt.in
@@ -1,15 +1,14 @@
 cmake_minimum_required(VERSION 2.8.2)
 
-project(googletest-download NONE)
+project(googletest-external NONE)
 
 include(ExternalProject)
 ExternalProject_Add(googletest
-  GIT_REPOSITORY    https://github.com/google/googletest.git
-  GIT_TAG           master
-  SOURCE_DIR        "${CMAKE_BINARY_DIR}/googletest-src"
-  BINARY_DIR        "${CMAKE_BINARY_DIR}/googletest-build"
+  URL               "${absl_gtest_download_url}"  # May be empty
+  SOURCE_DIR        "${absl_gtest_src_dir}"
+  BINARY_DIR        "${absl_gtest_build_dir}"
   CONFIGURE_COMMAND ""
   BUILD_COMMAND     ""
   INSTALL_COMMAND   ""
   TEST_COMMAND      ""
-)
\ No newline at end of file
+)
diff --git a/CMake/Googletest/DownloadGTest.cmake b/CMake/Googletest/DownloadGTest.cmake
index 3c682ae..9d071c9 100644
--- a/CMake/Googletest/DownloadGTest.cmake
+++ b/CMake/Googletest/DownloadGTest.cmake
@@ -1,32 +1,41 @@
-# Downloads and unpacks googletest at configure time.  Based on the instructions
-# at https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project
+# Integrates googletest at configure time.  Based on the instructions at
+# https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project
 
-# Download the latest googletest from Github master
+# Set up the external googletest project, downloading the latest from Github
+# master if requested.
 configure_file(
   ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in
-  ${CMAKE_BINARY_DIR}/googletest-download/CMakeLists.txt
+  ${CMAKE_BINARY_DIR}/googletest-external/CMakeLists.txt
 )
 
-# Configure and build the downloaded googletest source
+set(ABSL_SAVE_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+set(ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+if (BUILD_SHARED_LIBS)
+  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_CREATE_SHARED_LIBRARY=1")
+endif()
+
+# Configure and build the googletest source.
 execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
   RESULT_VARIABLE result
-  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
+  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external )
 if(result)
   message(FATAL_ERROR "CMake step for googletest failed: ${result}")
 endif()
 
 execute_process(COMMAND ${CMAKE_COMMAND} --build .
   RESULT_VARIABLE result
-  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
+  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external)
 if(result)
   message(FATAL_ERROR "Build step for googletest failed: ${result}")
 endif()
 
+set(CMAKE_CXX_FLAGS ${ABSL_SAVE_CMAKE_CXX_FLAGS})
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+
 # Prevent overriding the parent project's compiler/linker settings on Windows
 set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
 
 # Add googletest directly to our build. This defines the gtest and gtest_main
 # targets.
-add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
-                 ${CMAKE_BINARY_DIR}/googletest-build
-                 EXCLUDE_FROM_ALL)
+add_subdirectory(${absl_gtest_src_dir} ${absl_gtest_build_dir} EXCLUDE_FROM_ALL)
diff --git a/CMake/README.md b/CMake/README.md
index 04d5df3..8f73475 100644
--- a/CMake/README.md
+++ b/CMake/README.md
@@ -93,7 +93,7 @@
 absl::memory
 absl::meta
 absl::numeric
-absl::random
+absl::random_random
 absl::strings
 absl::synchronization
 absl::time
diff --git a/CMake/abslConfig.cmake.in b/CMake/abslConfig.cmake.in
index 60847fa..62d246d 100644
--- a/CMake/abslConfig.cmake.in
+++ b/CMake/abslConfig.cmake.in
@@ -1,7 +1,8 @@
 # absl CMake configuration file.
 
-include(FindThreads)
+include(CMakeFindDependencyMacro)
+find_dependency(Threads)
 
 @PACKAGE_INIT@
 
-include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
\ No newline at end of file
+include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
diff --git a/CMake/install_test_project/test.sh b/CMake/install_test_project/test.sh
index 99989b0..ddc7726 100755
--- a/CMake/install_test_project/test.sh
+++ b/CMake/install_test_project/test.sh
@@ -118,6 +118,24 @@
   exit 1
 fi
 
+pushd "${HOME}"
+cat > hello-abseil.cc << EOF
+#include <cstdlib>
+
+#include "absl/strings/str_format.h"
+
+int main(int argc, char **argv) {
+  absl::PrintF("Hello Abseil!\n");
+  return EXIT_SUCCESS;
+}
+EOF
+export PKG_CONFIG_PATH="${install_dir}/${libdir}/pkgconfig"
+pc_args=($(pkg-config --cflags --libs --static absl_str_format))
+g++ -static -o hello-abseil hello-abseil.cc "${pc_args[@]}"
+hello="$(./hello-abseil)"
+[[ "${hello}" == "Hello Abseil!" ]]
+popd
+
 uninstall_absl
 popd
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 86f5634..c1ae8d5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,22 +22,39 @@
 cmake_minimum_required(VERSION 3.5)
 
 # Compiler id for Apple Clang is now AppleClang.
-cmake_policy(SET CMP0025 NEW)
+if (POLICY CMP0025)
+  cmake_policy(SET CMP0025 NEW)
+endif (POLICY CMP0025)
 
 # if command can use IN_LIST
-cmake_policy(SET CMP0057 NEW)
+if (POLICY CMP0057)
+  cmake_policy(SET CMP0057 NEW)
+endif (POLICY CMP0057)
 
-# Project version variables are the empty std::string if version is unspecified
-cmake_policy(SET CMP0048 NEW)
+# Project version variables are the empty string if version is unspecified
+if (POLICY CMP0048)
+  cmake_policy(SET CMP0048 NEW)
+endif (POLICY CMP0048)
+
+# option() honor variables
+if (POLICY CMP0077)
+  cmake_policy(SET CMP0077 NEW)
+endif (POLICY CMP0077)
 
 project(absl CXX)
 
+# Output directory is correct by default for most build setups. However, when
+# building Abseil as a DLL, it is important to have the DLL in the same
+# directory as the executable using it. Thus, we put all executables in a single
+# /bin directory.
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+
 # when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp))
 # in the source tree of a project that uses it, install rules are disabled.
 if(NOT "^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$")
-  set(ABSL_ENABLE_INSTALL FALSE)
+  option(ABSL_ENABLE_INSTALL "Enable install rule" OFF)
 else()
-  set(ABSL_ENABLE_INSTALL TRUE)
+  option(ABSL_ENABLE_INSTALL "Enable install rule" ON)
 endif()
 
 list(APPEND CMAKE_MODULE_PATH
@@ -47,6 +64,7 @@
 
 include(AbseilInstallDirs)
 include(CMakePackageConfigHelpers)
+include(AbseilDll)
 include(AbseilHelpers)
 
 
@@ -74,8 +92,17 @@
 ## pthread
 find_package(Threads REQUIRED)
 
+option(ABSL_USE_EXTERNAL_GOOGLETEST
+  "If ON, Abseil will assume that the targets for GoogleTest are already provided by the including project. This makes sense when Abseil is used with add_subproject." OFF)
+
 option(ABSL_USE_GOOGLETEST_HEAD
-  "If ON, abseil will download HEAD from googletest at config time." OFF)
+  "If ON, abseil will download HEAD from GoogleTest at config time." OFF)
+
+set(ABSL_GOOGLETEST_DOWNLOAD_URL "" CACHE STRING "If set, download GoogleTest from this URL")
+
+set(ABSL_LOCAL_GOOGLETEST_DIR "/usr/src/googletest" CACHE PATH
+  "If ABSL_USE_GOOGLETEST_HEAD is OFF and ABSL_GOOGLETEST_URL is not set, specifies the directory of a local GoogleTest checkout."
+  )
 
 option(ABSL_RUN_TESTS "If ON, Abseil tests will be run." OFF)
 
@@ -83,16 +110,24 @@
   # enable CTest.  This will set BUILD_TESTING to ON unless otherwise specified
   # on the command line
   include(CTest)
-  enable_testing()
-endif()
 
-## check targets
-if(BUILD_TESTING)
-
-  if(${ABSL_USE_GOOGLETEST_HEAD})
-    include(CMake/Googletest/DownloadGTest.cmake)
-    set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src)
+  ## check targets
+  if (NOT ABSL_USE_EXTERNAL_GOOGLETEST)
     set(absl_gtest_build_dir ${CMAKE_BINARY_DIR}/googletest-build)
+    if(ABSL_USE_GOOGLETEST_HEAD AND ABSL_GOOGLETEST_DOWNLOAD_URL)
+      message(FATAL_ERROR "Do not set both ABSL_USE_GOOGLETEST_HEAD and ABSL_GOOGLETEST_DOWNLOAD_URL")
+    endif()
+    if(ABSL_USE_GOOGLETEST_HEAD)
+      set(absl_gtest_download_url "https://github.com/google/googletest/archive/master.zip")
+    elseif(ABSL_GOOGLETEST_DOWNLOAD_URL)
+      set(absl_gtest_download_url ${ABSL_GOOGLETEST_DOWNLOAD_URL})
+    endif()
+    if(absl_gtest_download_url)
+      set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src)
+    else()
+      set(absl_gtest_src_dir ${ABSL_LOCAL_GOOGLETEST_DIR})
+    endif()
+    include(CMake/Googletest/DownloadGTest.cmake)
   endif()
 
   check_target(gtest)
@@ -156,5 +191,7 @@
     FILES_MATCHING
       PATTERN "*.inc"
       PATTERN "*.h"
-  )
+      PATTERN "copts" EXCLUDE
+      PATTERN "testdata" EXCLUDE
+    )
 endif()  # ABSL_ENABLE_INSTALL
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index f4cb4a2..9dadae9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -123,10 +123,13 @@
 
 ## Running Tests
 
-Use "bazel test <>" functionality to run the unit tests.
+If you have [Bazel](https://bazel.build/) installed, use `bazel test
+--test_tag_filters="-benchmark" ...` to run the unit tests.
 
-Prerequisites for building and running tests are listed in
-[README.md](README.md)
+If you are running the Linux operating system and have
+[Docker](https://www.docker.com/) installed, you can also run the `linux_*.sh`
+scripts under the `ci/`(https://github.com/abseil/abseil-cpp/tree/master/ci)
+directory to test Abseil under a variety of conditions.
 
 ## Abseil Committers
 
diff --git a/FAQ.md b/FAQ.md
new file mode 100644
index 0000000..78028fc
--- /dev/null
+++ b/FAQ.md
@@ -0,0 +1,164 @@
+# Abseil FAQ
+
+## Is Abseil the right home for my utility library?
+
+Most often the answer to the question is "no." As both the [About
+Abseil](https://abseil.io/about/) page and our [contributing
+guidelines](https://github.com/abseil/abseil-cpp/blob/master/CONTRIBUTING.md#contribution-guidelines)
+explain, Abseil contains a variety of core C++ library code that is widely used
+at [Google](https://www.google.com/). As such, Abseil's primary purpose is to be
+used as a dependency by Google's open source C++ projects. While we do hope that
+Abseil is also useful to the C++ community at large, this added constraint also
+means that we are unlikely to accept a contribution of utility code that isn't
+already widely used by Google.
+
+## How to I set the C++ dialect used to build Abseil?
+
+The short answer is that whatever mechanism you choose, you need to make sure
+that you set this option consistently at the global level for your entire
+project. If, for example, you want to set the C++ dialect to C++17, with
+[Bazel](https://bazel/build/) as the build system and `gcc` or `clang` as the
+compiler, there several ways to do this:
+* Pass `--cxxopt=-std=c++17` on the command line (for example, `bazel build
+  --cxxopt=-std=c++17 ...`)
+* Set the environment variable `BAZEL_CXXOPTS` (for example,
+  `BAZEL_CXXOPTS=-std=c++17`)
+* Add `build --cxxopt=-std=c++17` to your [`.bazelrc`
+  file](https://docs.bazel.build/versions/master/guide.html#bazelrc)
+
+If you are using CMake as the build system, you'll need to add a line like
+`set(CMAKE_CXX_STANDARD 17)` to your top level `CMakeLists.txt` file. See the
+[CMake build
+instructions](https://github.com/abseil/abseil-cpp/blob/master/CMake/README.md)
+for more information.
+
+For a longer answer to this question and to understand why some other approaches
+don't work, see the answer to ["What is ABI and why don't you recommend using a
+pre-compiled version of
+Abseil?"](#what-is-abi-and-why-dont-you-recommend-using-a-pre-compiled-version-of-abseil)
+
+## What is ABI and why don't you recommend using a pre-compiled version of Abseil?
+
+For the purposes of this discussion, you can think of
+[ABI](https://en.wikipedia.org/wiki/Application_binary_interface) as the
+compiled representation of the interfaces in code. This is in contrast to
+[API](https://en.wikipedia.org/wiki/Application_programming_interface), which
+you can think of as the interfaces as defined by the code itself. [Abseil has a
+strong promise of API compatibility, but does not make any promise of ABI
+compatibility](https://abseil.io/about/compatibility). Let's take a look at what
+this means in practice.
+
+You might be tempted to do something like this in a
+[Bazel](https://bazel.build/) `BUILD` file:
+
+```
+# DON'T DO THIS!!!
+cc_library(
+    name = "my_library",
+    srcs = ["my_library.cc"],
+    copts = ["-std=c++17"],  # May create a mixed-mode compile!
+    deps = ["@com_google_absl//absl/strings"],
+)
+```
+
+Applying `-std=c++17` to an individual target in your `BUILD` file is going to
+compile that specific target in C++17 mode, but it isn't going to ensure the
+Abseil library is built in C++17 mode, since the Abseil library itself is a
+different build target. If your code includes an Abseil header, then your
+program may contain conflicting definitions of the same
+class/function/variable/enum, etc. As a rule, all compile options that affect
+the ABI of a program need to be applied to the entire build on a global basis.
+
+C++ has something called the [One Definition
+Rule](https://en.wikipedia.org/wiki/One_Definition_Rule) (ODR). C++ doesn't
+allow multiple definitions of the same class/function/variable/enum, etc. ODR
+violations sometimes result in linker errors, but linkers do not always catch
+violations. Uncaught ODR violations can result in strange runtime behaviors or
+crashes that can be hard to debug.
+
+If you build the Abseil library and your code using different compile options
+that affect ABI, there is a good chance you will run afoul of the One Definition
+Rule. Examples of GCC compile options that affect ABI include (but aren't
+limited to) language dialect (e.g. `-std=`), optimization level (e.g. `-O2`),
+code generation flags (e.g. `-fexceptions`), and preprocessor defines
+(e.g. `-DNDEBUG`).
+
+If you use a pre-compiled version of Abseil, (for example, from your Linux
+distribution package manager or from something like
+[vcpkg](https://github.com/microsoft/vcpkg)) you have to be very careful to
+ensure ABI compatibility across the components of your program. The only way you
+can be sure your program is going to be correct regarding ABI is to ensure
+you've used the exact same compile options as were used to build the
+pre-compiled library. This does not mean that Abseil cannot work as part of a
+Linux distribution since a knowledgeable binary packager will have ensured that
+all packages have been built with consistent compile options. This is one of the
+reasons we warn against - though do not outright reject - using Abseil as a
+pre-compiled library.
+
+Another possible way that you might afoul of ABI issues is if you accidentally
+include two versions of Abseil in your program. Multiple versions of Abseil can
+end up within the same binary if your program uses the Abseil library and
+another library also transitively depends on Abseil (resulting in what is
+sometimes called the diamond dependency problem). In cases such as this you must
+structure your build so that all libraries use the same version of Abseil.
+[Abseil's strong promise of API compatibility between
+releases](https://abseil.io/about/compatibility) means the latest "HEAD" release
+of Abseil is almost certainly the right choice if you are doing as we recommend
+and building all of your code from source.
+
+For these reasons we recommend you avoid pre-compiled code and build the Abseil
+library yourself in a consistent manner with the rest of your code.
+
+## What is "live at head" and how do I do it?
+
+From Abseil's point-of-view, "live at head" means that every Abseil source
+release (which happens on an almost daily basis) is either API compatible with
+the previous release, or comes with an automated tool that you can run over code
+to make it compatible. In practice, the need to use an automated tool is
+extremely rare. This means that upgrading from one source release to another
+should be a routine practice that can and should be performed often.
+
+We recommend you update to the [latest commit in the `master` branch of
+Abseil](https://github.com/abseil/abseil-cpp/commits/master) as often as
+possible. Not only will you pick up bug fixes more quickly, but if you have good
+automated testing, you will catch and be able to fix any [Hyrum's
+Law](https://www.hyrumslaw.com/) dependency problems on an incremental basis
+instead of being overwhelmed by them and having difficulty isolating them if you
+wait longer between updates.
+
+If you are using the [Bazel](https://bazel.build/) build system and its
+[external dependencies](https://docs.bazel.build/versions/master/external.html)
+feature, updating the
+[`http_archive`](https://docs.bazel.build/versions/master/repo/http.html#http_archive)
+rule in your
+[`WORKSPACE`](https://docs.bazel.build/versions/master/be/workspace.html) for
+`com_google_abseil` to point to the [latest commit in the `master` branch of
+Abseil](https://github.com/abseil/abseil-cpp/commits/master) is all you need to
+do. For example, on February 11, 2020, the latest commit to the master branch
+was `98eb410c93ad059f9bba1bf43f5bb916fc92a5ea`. To update to this commit, you
+would add the following snippet to your `WORKSPACE` file:
+
+```
+http_archive(
+  name = "com_google_absl",
+  urls = ["https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip"],  # 2020-02-11T18:50:53Z
+  strip_prefix = "abseil-cpp-98eb410c93ad059f9bba1bf43f5bb916fc92a5ea",
+  sha256 = "aabf6c57e3834f8dc3873a927f37eaf69975d4b28117fc7427dfb1c661542a87",
+)
+```
+
+To get the `sha256` of this URL, run `curl -sL --output -
+https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip
+| sha256sum -`.
+
+You can commit the updated `WORKSPACE` file to your source control every time
+you update, and if you have good automated testing, you might even consider
+automating this.
+
+One thing we don't recommend is using GitHub's `master.zip` files (for example
+[https://github.com/abseil/abseil-cpp/archive/master.zip](https://github.com/abseil/abseil-cpp/archive/master.zip)),
+which are always the latest commit in the `master` branch, to implement live at
+head. Since these `master.zip` URLs are not versioned, you will lose build
+reproducibility. In addition, some build systems, including Bazel, will simply
+cache this file, which means you won't actually be updating to the latest
+release until your cache is cleared or invalidated.
diff --git a/LTS.md b/LTS.md
index 94363b6..ade8b17 100644
--- a/LTS.md
+++ b/LTS.md
@@ -13,3 +13,4 @@
 * [LTS Branch December 18, 2018](https://github.com/abseil/abseil-cpp/tree/lts_2018_12_18/)
 * [LTS Branch June 20, 2018](https://github.com/abseil/abseil-cpp/tree/lts_2018_06_20/)
 * [LTS Branch August 8, 2019](https://github.com/abseil/abseil-cpp/tree/lts_2019_08_08/)
+* [LTS Branch February 25, 2020](https://github.com/abseil/abseil-cpp/tree/lts_2020_02_25/)
diff --git a/README.md b/README.md
index 85de569..76f1d1e 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,9 @@
 - [About Abseil](#about)
 - [Quickstart](#quickstart)
 - [Building Abseil](#build)
+- [Support](#support)
 - [Codemap](#codemap)
+- [Releases](#releases)
 - [License](#license)
 - [Links](#links)
 
@@ -42,14 +44,22 @@
 <a name="build"></a>
 ## Building Abseil
 
-[Bazel](https://bazel.build) is the official build system for Abseil,
-which is supported on most major platforms (Linux, Windows, macOS, for example)
-and compilers. See the [quickstart](https://abseil.io/docs/cpp/quickstart) for
-more information on building Abseil using the Bazel build system.
+[Bazel](https://bazel.build) and [CMake](https://cmake.org/) are the official
+build systems for Abseil.
 
-<a name="cmake"></a>
-If you require CMake support, please check the
-[CMake build instructions](CMake/README.md).
+See the [quickstart](https://abseil.io/docs/cpp/quickstart) for more information
+on building Abseil using the Bazel build system.
+
+If you require CMake support, please check the [CMake build
+instructions](CMake/README.md) and [CMake
+Quickstart](https://abseil.io/docs/cpp/quickstart-cmake).
+
+## Support
+
+Abseil is officially supported on many platforms. See the [Abseil
+platform support
+guide](https://abseil.io/docs/cpp/platforms/platforms) for details on
+supported operating systems, compilers, CPUs, etc.
 
 ## Codemap
 
@@ -79,6 +89,9 @@
   available within C++14 and C++17 versions of the C++ `<type_traits>` library.
 * [`numeric`](absl/numeric/)
   <br /> The `numeric` library contains C++11-compatible 128-bit integers.
+* [`status`](absl/status/)
+  <br /> The `status` contains abstractions for error handling, specifically
+  `absl::Status` and `absl::StatusOr<T>`.
 * [`strings`](absl/strings/)
   <br /> The `strings` library contains a variety of strings routines and
   utilities, including a C++11-compatible version of the C++17
@@ -97,6 +110,15 @@
 * [`utility`](absl/utility/)
   <br /> The `utility` library contains utility and helper code.
 
+## Releases
+
+Abseil recommends users "live-at-head" (update to the latest commit from the
+master branch as often as possible). However, we realize this philosophy doesn't
+work for every project, so we also provide [Long Term Support
+Releases](https://github.com/abseil/abseil-cpp/releases) to which we backport
+fixes for severe bugs. See our [release
+management](https://abseil.io/about/releases) document for more details.
+
 ## License
 
 The Abseil C++ library is licensed under the terms of the Apache
diff --git a/WORKSPACE b/WORKSPACE
index 572f5b1..258d23b 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -19,27 +19,27 @@
 
 # GoogleTest/GoogleMock framework. Used by most unit-tests.
 http_archive(
-     name = "com_google_googletest",
-     urls = ["https://github.com/google/googletest/archive/b6cd405286ed8635ece71c72f118e659f4ade3fb.zip"],  # 2019-01-07
-     strip_prefix = "googletest-b6cd405286ed8635ece71c72f118e659f4ade3fb",
-     sha256 = "ff7a82736e158c077e76188232eac77913a15dac0b22508c390ab3f88e6d6d86",
+    name = "com_google_googletest",
+    # Keep this URL in sync with ABSL_GOOGLETEST_COMMIT in ci/cmake_common.sh.
+    urls = ["https://github.com/google/googletest/archive/8567b09290fe402cf01923e2131c5635b8ed851b.zip"],  # 2020-06-12T22:24:28Z
+    strip_prefix = "googletest-8567b09290fe402cf01923e2131c5635b8ed851b",
+    sha256 = "9a8a166eb6a56c7b3d7b19dc2c946fe4778fd6f21c7a12368ad3b836d8f1be48",
 )
 
 # Google benchmark.
 http_archive(
     name = "com_github_google_benchmark",
-    urls = ["https://github.com/google/benchmark/archive/16703ff83c1ae6d53e5155df3bb3ab0bc96083be.zip"],
-    strip_prefix = "benchmark-16703ff83c1ae6d53e5155df3bb3ab0bc96083be",
-    sha256 = "59f918c8ccd4d74b6ac43484467b500f1d64b40cc1010daa055375b322a43ba3",
+    urls = ["https://github.com/google/benchmark/archive/bf585a2789e30585b4e3ce6baf11ef2750b54677.zip"],  # 2020-11-26T11:14:03Z
+    strip_prefix = "benchmark-bf585a2789e30585b4e3ce6baf11ef2750b54677",
+    sha256 = "2a778d821997df7d8646c9c59b8edb9a573a6e04c534c01892a40aa524a7b68c",
 )
 
 # C++ rules for Bazel.
 http_archive(
     name = "rules_cc",
-    sha256 = "67412176974bfce3f4cf8bdaff39784a72ed709fc58def599d1f68710b58d68b",
-    strip_prefix = "rules_cc-b7fe9697c0c76ab2fd431a891dbb9a6a32ed7c3e",
+    sha256 = "9a446e9dd9c1bb180c86977a8dc1e9e659550ae732ae58bd2e8fd51e15b2c91d",
+    strip_prefix = "rules_cc-262ebec3c2296296526740db4aefce68c80de7fa",
     urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/rules_cc/archive/b7fe9697c0c76ab2fd431a891dbb9a6a32ed7c3e.zip",
-        "https://github.com/bazelbuild/rules_cc/archive/b7fe9697c0c76ab2fd431a891dbb9a6a32ed7c3e.zip",
+        "https://github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip",
     ],
 )
diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel
index 853330d..6da20c4 100644
--- a/absl/BUILD.bazel
+++ b/absl/BUILD.bazel
@@ -12,16 +12,16 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
-load(":compiler_config_setting.bzl", "create_llvm_config")
-
-create_llvm_config(
-    name = "llvm_compiler",
+config_setting(
+    name = "clang_compiler",
+    flag_values = {
+        "@bazel_tools//tools/cpp:compiler": "clang",
+    },
     visibility = [":__subpackages__"],
 )
 
@@ -41,9 +41,10 @@
 
 config_setting(
     name = "windows",
-    values = {
-        "cpu": "x64_windows",
-    },
+    constraint_values = [
+        "@bazel_tools//platforms:x86_64",
+        "@bazel_tools//platforms:windows",
+    ],
     visibility = [":__subpackages__"],
 )
 
@@ -54,3 +55,11 @@
     },
     visibility = [":__subpackages__"],
 )
+
+config_setting(
+    name = "wasm",
+    values = {
+        "cpu": "wasm32",
+    },
+    visibility = [":__subpackages__"],
+)
diff --git a/absl/CMakeLists.txt b/absl/CMakeLists.txt
index 3e78397..fbfa782 100644
--- a/absl/CMakeLists.txt
+++ b/absl/CMakeLists.txt
@@ -14,20 +14,24 @@
 # limitations under the License.
 #
 
-
-
 add_subdirectory(base)
 add_subdirectory(algorithm)
 add_subdirectory(container)
 add_subdirectory(debugging)
 add_subdirectory(flags)
+add_subdirectory(functional)
 add_subdirectory(hash)
 add_subdirectory(memory)
 add_subdirectory(meta)
 add_subdirectory(numeric)
 add_subdirectory(random)
+add_subdirectory(status)
 add_subdirectory(strings)
 add_subdirectory(synchronization)
 add_subdirectory(time)
 add_subdirectory(types)
 add_subdirectory(utility)
+
+if (${ABSL_BUILD_DLL})
+  absl_make_dll()
+endif()
diff --git a/absl/abseil.podspec.gen.py b/absl/abseil.podspec.gen.py
new file mode 100755
index 0000000..6375298
--- /dev/null
+++ b/absl/abseil.podspec.gen.py
@@ -0,0 +1,229 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""This script generates abseil.podspec from all BUILD.bazel files.
+
+This is expected to run on abseil git repository with Bazel 1.0 on Linux.
+It recursively analyzes BUILD.bazel files using query command of Bazel to
+dump its build rules in XML format. From these rules, it constructs podspec
+structure.
+"""
+
+import argparse
+import collections
+import os
+import re
+import subprocess
+import xml.etree.ElementTree
+
+# Template of root podspec.
+SPEC_TEMPLATE = """
+# This file has been automatically generated from a script.
+# Please make modifications to `abseil.podspec.gen.py` instead.
+Pod::Spec.new do |s|
+  s.name     = 'abseil'
+  s.version  = '${version}'
+  s.summary  = 'Abseil Common Libraries (C++) from Google'
+  s.homepage = 'https://abseil.io'
+  s.license  = 'Apache License, Version 2.0'
+  s.authors  = { 'Abseil Team' => 'abseil-io@googlegroups.com' }
+  s.source = {
+    :git => 'https://github.com/abseil/abseil-cpp.git',
+    :tag => '${tag}',
+  }
+  s.module_name = 'absl'
+  s.header_mappings_dir = 'absl'
+  s.header_dir = 'absl'
+  s.libraries = 'c++'
+  s.compiler_flags = '-Wno-everything'
+  s.pod_target_xcconfig = {
+    'USER_HEADER_SEARCH_PATHS' => '$(inherited) "$(PODS_TARGET_SRCROOT)"',
+    'USE_HEADERMAP' => 'NO',
+    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
+  }
+  s.ios.deployment_target = '9.0'
+  s.osx.deployment_target = '10.10'
+  s.tvos.deployment_target = '9.0'
+  s.watchos.deployment_target = '2.0'
+"""
+
+# Rule object representing the rule of Bazel BUILD.
+Rule = collections.namedtuple(
+    "Rule", "type name package srcs hdrs textual_hdrs deps visibility testonly")
+
+
+def get_elem_value(elem, name):
+  """Returns the value of XML element with the given name."""
+  for child in elem:
+    if child.attrib.get("name") != name:
+      continue
+    if child.tag == "string":
+      return child.attrib.get("value")
+    if child.tag == "boolean":
+      return child.attrib.get("value") == "true"
+    if child.tag == "list":
+      return [nested_child.attrib.get("value") for nested_child in child]
+    raise "Cannot recognize tag: " + child.tag
+  return None
+
+
+def normalize_paths(paths):
+  """Returns the list of normalized path."""
+  # e.g. ["//absl/strings:dir/header.h"] -> ["absl/strings/dir/header.h"]
+  return [path.lstrip("/").replace(":", "/") for path in paths]
+
+
+def parse_rule(elem, package):
+  """Returns a rule from bazel XML rule."""
+  return Rule(
+      type=elem.attrib["class"],
+      name=get_elem_value(elem, "name"),
+      package=package,
+      srcs=normalize_paths(get_elem_value(elem, "srcs") or []),
+      hdrs=normalize_paths(get_elem_value(elem, "hdrs") or []),
+      textual_hdrs=normalize_paths(get_elem_value(elem, "textual_hdrs") or []),
+      deps=get_elem_value(elem, "deps") or [],
+      visibility=get_elem_value(elem, "visibility") or [],
+      testonly=get_elem_value(elem, "testonly") or False)
+
+
+def read_build(package):
+  """Runs bazel query on given package file and returns all cc rules."""
+  result = subprocess.check_output(
+      ["bazel", "query", package + ":all", "--output", "xml"])
+  root = xml.etree.ElementTree.fromstring(result)
+  return [
+      parse_rule(elem, package)
+      for elem in root
+      if elem.tag == "rule" and elem.attrib["class"].startswith("cc_")
+  ]
+
+
+def collect_rules(root_path):
+  """Collects and returns all rules from root path recursively."""
+  rules = []
+  for cur, _, _ in os.walk(root_path):
+    build_path = os.path.join(cur, "BUILD.bazel")
+    if os.path.exists(build_path):
+      rules.extend(read_build("//" + cur))
+  return rules
+
+
+def relevant_rule(rule):
+  """Returns true if a given rule is relevant when generating a podspec."""
+  return (
+      # cc_library only (ignore cc_test, cc_binary)
+      rule.type == "cc_library" and
+      # ignore empty rule
+      (rule.hdrs + rule.textual_hdrs + rule.srcs) and
+      # ignore test-only rule
+      not rule.testonly)
+
+
+def get_spec_var(depth):
+  """Returns the name of variable for spec with given depth."""
+  return "s" if depth == 0 else "s{}".format(depth)
+
+
+def get_spec_name(label):
+  """Converts the label of bazel rule to the name of podspec."""
+  assert label.startswith("//absl/"), "{} doesn't start with //absl/".format(
+      label)
+  # e.g. //absl/apple/banana -> abseil/apple/banana
+  return "abseil/" + label[7:]
+
+
+def write_podspec(f, rules, args):
+  """Writes a podspec from given rules and args."""
+  rule_dir = build_rule_directory(rules)["abseil"]
+  # Write root part with given arguments
+  spec = re.sub(r"\$\{(\w+)\}", lambda x: args[x.group(1)],
+                SPEC_TEMPLATE).lstrip()
+  f.write(spec)
+  # Write all target rules
+  write_podspec_map(f, rule_dir, 0)
+  f.write("end\n")
+
+
+def build_rule_directory(rules):
+  """Builds a tree-style rule directory from given rules."""
+  rule_dir = {}
+  for rule in rules:
+    cur = rule_dir
+    for frag in get_spec_name(rule.package).split("/"):
+      cur = cur.setdefault(frag, {})
+    cur[rule.name] = rule
+  return rule_dir
+
+
+def write_podspec_map(f, cur_map, depth):
+  """Writes podspec from rule map recursively."""
+  for key, value in sorted(cur_map.items()):
+    indent = "  " * (depth + 1)
+    f.write("{indent}{var0}.subspec '{key}' do |{var1}|\n".format(
+        indent=indent,
+        key=key,
+        var0=get_spec_var(depth),
+        var1=get_spec_var(depth + 1)))
+    if isinstance(value, dict):
+      write_podspec_map(f, value, depth + 1)
+    else:
+      write_podspec_rule(f, value, depth + 1)
+    f.write("{indent}end\n".format(indent=indent))
+
+
+def write_podspec_rule(f, rule, depth):
+  """Writes podspec from given rule."""
+  indent = "  " * (depth + 1)
+  spec_var = get_spec_var(depth)
+  # Puts all files in hdrs, textual_hdrs, and srcs into source_files.
+  # Since CocoaPods treats header_files a bit differently from bazel,
+  # this won't generate a header_files field so that all source_files
+  # are considered as header files.
+  srcs = sorted(set(rule.hdrs + rule.textual_hdrs + rule.srcs))
+  write_indented_list(
+      f, "{indent}{var}.source_files = ".format(indent=indent, var=spec_var),
+      srcs)
+  # Writes dependencies of this rule.
+  for dep in sorted(rule.deps):
+    name = get_spec_name(dep.replace(":", "/"))
+    f.write("{indent}{var}.dependency '{dep}'\n".format(
+        indent=indent, var=spec_var, dep=name))
+
+
+def write_indented_list(f, leading, values):
+  """Writes leading values in an indented style."""
+  f.write(leading)
+  f.write((",\n" + " " * len(leading)).join("'{}'".format(v) for v in values))
+  f.write("\n")
+
+
+def generate(args):
+  """Generates a podspec file from all BUILD files under absl directory."""
+  rules = filter(relevant_rule, collect_rules("absl"))
+  with open(args.output, "wt") as f:
+    write_podspec(f, rules, vars(args))
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      description="Generates abseil.podspec from BUILD.bazel")
+  parser.add_argument(
+      "-v", "--version", help="The version of podspec", required=True)
+  parser.add_argument(
+      "-t",
+      "--tag",
+      default=None,
+      help="The name of git tag (default: version)")
+  parser.add_argument(
+      "-o",
+      "--output",
+      default="abseil.podspec",
+      help="The name of output file (default: abseil.podspec)")
+  args = parser.parse_args()
+  if args.tag is None:
+    args.tag = args.version
+  generate(args)
+
+
+if __name__ == "__main__":
+  main()
diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel
index 2ee8c09..a3002b7 100644
--- a/absl/algorithm/BUILD.bazel
+++ b/absl/algorithm/BUILD.bazel
@@ -24,13 +24,16 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "algorithm",
     hdrs = ["algorithm.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+    ],
 )
 
 cc_test(
diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt
index 9fbe36f..56cd0fb 100644
--- a/absl/algorithm/CMakeLists.txt
+++ b/absl/algorithm/CMakeLists.txt
@@ -21,6 +21,8 @@
     "algorithm.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
   PUBLIC
 )
 
diff --git a/absl/algorithm/algorithm.h b/absl/algorithm/algorithm.h
index bb90215..e9b4733 100644
--- a/absl/algorithm/algorithm.h
+++ b/absl/algorithm/algorithm.h
@@ -26,7 +26,10 @@
 #include <iterator>
 #include <type_traits>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace algorithm_internal {
 
@@ -84,6 +87,8 @@
 
 }  // namespace algorithm_internal
 
+// equal()
+//
 // Compares the equality of two ranges specified by pairs of iterators, using
 // the given predicate, returning true iff for each corresponding iterator i1
 // and i2 in the first and second range respectively, pred(*i1, *i2) == true
@@ -104,8 +109,8 @@
       typename std::iterator_traits<InputIter2>::iterator_category{});
 }
 
-// Performs comparison of two ranges specified by pairs of iterators using
-// operator==.
+// Overload of equal() that performs comparison of two ranges specified by pairs
+// of iterators using operator==.
 template <typename InputIter1, typename InputIter2>
 bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
            InputIter2 last2) {
@@ -113,6 +118,8 @@
                      algorithm_internal::EqualTo{});
 }
 
+// linear_search()
+//
 // Performs a linear search for `value` using the iterator `first` up to
 // but not including `last`, returning true if [`first`, `last`) contains an
 // element equal to `value`.
@@ -126,6 +133,8 @@
   return std::find(first, last, value) != last;
 }
 
+// rotate()
+//
 // Performs a left rotation on a range of elements (`first`, `last`) such that
 // `middle` is now the first element. `rotate()` returns an iterator pointing to
 // the first element before rotation. This function is exactly the same as
@@ -135,7 +144,6 @@
 // The complexity of this algorithm is the same as that of `std::rotate`, but if
 // `ForwardIterator` is not a random-access iterator, then `absl::rotate`
 // performs an additional pass over the range to construct the return value.
-
 template <typename ForwardIterator>
 ForwardIterator rotate(ForwardIterator first, ForwardIterator middle,
                        ForwardIterator last) {
@@ -145,6 +153,7 @@
                    ForwardIterator>());
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_ALGORITHM_ALGORITHM_H_
diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h
index c84de46..6398438 100644
--- a/absl/algorithm/container.h
+++ b/absl/algorithm/container.h
@@ -55,6 +55,7 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_algorithm_internal {
 
 // NOTE: it is important to defer to ADL lookup for building with C++ modules,
@@ -89,10 +90,10 @@
 // lookup of std::begin and std::end, i.e.
 //   using std::begin;
 //   using std::end;
-//   std::foo(begin(c), end(c);
+//   std::foo(begin(c), end(c));
 // becomes
 //   std::foo(container_algorithm_internal::begin(c),
-//   container_algorithm_internal::end(c));
+//            container_algorithm_internal::end(c));
 // These are meant for internal use only.
 
 template <typename C>
@@ -112,6 +113,18 @@
 struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
     : std::true_type {};
 
+// container_algorithm_internal::c_size. It is meant for internal use only.
+
+template <class C>
+auto c_size(C& c) -> decltype(c.size()) {
+  return c.size();
+}
+
+template <class T, std::size_t N>
+constexpr std::size_t c_size(T (&)[N]) {
+  return N;
+}
+
 }  // namespace container_algorithm_internal
 
 // PUBLIC API
@@ -175,7 +188,7 @@
 // c_none_of()
 //
 // Container-based version of the <algorithm> `std::none_of()` function to
-// test if no elements in a container fulfil a condition.
+// test if no elements in a container fulfill a condition.
 template <typename C, typename Pred>
 bool c_none_of(const C& c, Pred&& pred) {
   return std::none_of(container_algorithm_internal::c_begin(c),
@@ -256,7 +269,8 @@
 // c_find_first_of()
 //
 // Container-based version of the <algorithm> `std::find_first_of()` function to
-// find the first elements in an ordered set within a container.
+// find the first element within the container that is also within the options
+// container.
 template <typename C1, typename C2>
 container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container,
                                                                 C2& options) {
@@ -326,24 +340,45 @@
 // c_mismatch()
 //
 // Container-based version of the <algorithm> `std::mismatch()` function to
-// return the first element where two ordered containers differ.
+// return the first element where two ordered containers differ. Applies `==` to
+// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
 template <typename C1, typename C2>
 container_algorithm_internal::ContainerIterPairType<C1, C2>
 c_mismatch(C1& c1, C2& c2) {
-  return std::mismatch(container_algorithm_internal::c_begin(c1),
-                       container_algorithm_internal::c_end(c1),
-                       container_algorithm_internal::c_begin(c2));
+  auto first1 = container_algorithm_internal::c_begin(c1);
+  auto last1 = container_algorithm_internal::c_end(c1);
+  auto first2 = container_algorithm_internal::c_begin(c2);
+  auto last2 = container_algorithm_internal::c_end(c2);
+
+  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+    // Negates equality because Cpp17EqualityComparable doesn't require clients
+    // to overload both `operator==` and `operator!=`.
+    if (!(*first1 == *first2)) {
+      break;
+    }
+  }
+
+  return std::make_pair(first1, first2);
 }
 
 // Overload of c_mismatch() for using a predicate evaluation other than `==` as
-// the function's test condition.
+// the function's test condition. Applies `pred`to the first N elements of `c1`
+// and `c2`, where N = min(size(c1), size(c2)).
 template <typename C1, typename C2, typename BinaryPredicate>
 container_algorithm_internal::ContainerIterPairType<C1, C2>
-c_mismatch(C1& c1, C2& c2, BinaryPredicate&& pred) {
-  return std::mismatch(container_algorithm_internal::c_begin(c1),
-                       container_algorithm_internal::c_end(c1),
-                       container_algorithm_internal::c_begin(c2),
-                       std::forward<BinaryPredicate>(pred));
+c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
+  auto first1 = container_algorithm_internal::c_begin(c1);
+  auto last1 = container_algorithm_internal::c_end(c1);
+  auto first2 = container_algorithm_internal::c_begin(c2);
+  auto last2 = container_algorithm_internal::c_end(c2);
+
+  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+    if (!pred(*first1, *first2)) {
+      break;
+    }
+  }
+
+  return std::make_pair(first1, first2);
 }
 
 // c_equal()
@@ -365,7 +400,8 @@
 
 template <typename C1, typename C2>
 bool c_equal(const C1& c1, const C2& c2) {
-  return ((c1.size() == c2.size()) &&
+  return ((container_algorithm_internal::c_size(c1) ==
+           container_algorithm_internal::c_size(c2)) &&
           std::equal(container_algorithm_internal::c_begin(c1),
                      container_algorithm_internal::c_end(c1),
                      container_algorithm_internal::c_begin(c2)));
@@ -375,7 +411,8 @@
 // the function's test condition.
 template <typename C1, typename C2, typename BinaryPredicate>
 bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
-  return ((c1.size() == c2.size()) &&
+  return ((container_algorithm_internal::c_size(c1) ==
+           container_algorithm_internal::c_size(c2)) &&
           std::equal(container_algorithm_internal::c_begin(c1),
                      container_algorithm_internal::c_end(c1),
                      container_algorithm_internal::c_begin(c2),
@@ -523,12 +560,20 @@
 // c_swap_ranges()
 //
 // Container-based version of the <algorithm> `std::swap_ranges()` function to
-// swap a container's elements with another container's elements.
+// swap a container's elements with another container's elements. Swaps the
+// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
 template <typename C1, typename C2>
 container_algorithm_internal::ContainerIter<C2> c_swap_ranges(C1& c1, C2& c2) {
-  return std::swap_ranges(container_algorithm_internal::c_begin(c1),
-                          container_algorithm_internal::c_end(c1),
-                          container_algorithm_internal::c_begin(c2));
+  auto first1 = container_algorithm_internal::c_begin(c1);
+  auto last1 = container_algorithm_internal::c_end(c1);
+  auto first2 = container_algorithm_internal::c_begin(c2);
+  auto last2 = container_algorithm_internal::c_end(c2);
+
+  using std::swap;
+  for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+    swap(*first1, *first2);
+  }
+  return first2;
 }
 
 // c_transform()
@@ -546,16 +591,23 @@
 }
 
 // Overload of c_transform() for performing a transformation using a binary
-// predicate.
+// predicate. Applies `binary_op` to the first N elements of `c1` and `c2`,
+// where N = min(size(c1), size(c2)).
 template <typename InputSequence1, typename InputSequence2,
           typename OutputIterator, typename BinaryOp>
 OutputIterator c_transform(const InputSequence1& input1,
                            const InputSequence2& input2, OutputIterator output,
                            BinaryOp&& binary_op) {
-  return std::transform(container_algorithm_internal::c_begin(input1),
-                        container_algorithm_internal::c_end(input1),
-                        container_algorithm_internal::c_begin(input2), output,
-                        std::forward<BinaryOp>(binary_op));
+  auto first1 = container_algorithm_internal::c_begin(input1);
+  auto last1 = container_algorithm_internal::c_end(input1);
+  auto first2 = container_algorithm_internal::c_begin(input2);
+  auto last2 = container_algorithm_internal::c_end(input2);
+  for (; first1 != last1 && first2 != last2;
+       ++first1, (void)++first2, ++output) {
+    *output = binary_op(*first1, *first2);
+  }
+
+  return output;
 }
 
 // c_replace()
@@ -927,9 +979,10 @@
 // c_partial_sort_copy()
 //
 // Container-based version of the <algorithm> `std::partial_sort_copy()`
-// function to sort elements within a container such that elements before
-// `middle` are sorted in ascending order, and return the result within an
-// iterator.
+// function to sort the elements in the given range `result` within the larger
+// `sequence` in ascending order (and using `result` as the output parameter).
+// At most min(result.last - result.first, sequence.last - sequence.first)
+// elements from the sequence will be stored in the result.
 template <typename C, typename RandomAccessContainer>
 container_algorithm_internal::ContainerIter<RandomAccessContainer>
 c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) {
@@ -1705,6 +1758,7 @@
                           output_first, std::forward<BinaryOp>(op));
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_ALGORITHM_CONTAINER_H_
diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc
index 86bf9d3..605afc8 100644
--- a/absl/algorithm/container_test.cc
+++ b/absl/algorithm/container_test.cc
@@ -57,9 +57,7 @@
 };
 
 struct AccumulateCalls {
-  void operator()(int value) {
-    calls.push_back(value);
-  }
+  void operator()(int value) { calls.push_back(value); }
   std::vector<int> calls;
 };
 
@@ -68,7 +66,6 @@
 bool Equals(int v1, int v2) { return v1 == v2; }
 bool IsOdd(int x) { return x % 2 != 0; }
 
-
 TEST_F(NonMutatingTest, Distance) {
   EXPECT_EQ(container_.size(), absl::c_distance(container_));
   EXPECT_EQ(sequence_.size(), absl::c_distance(sequence_));
@@ -151,35 +148,118 @@
 }
 
 TEST_F(NonMutatingTest, Mismatch) {
-  absl::c_mismatch(container_, sequence_);
-  absl::c_mismatch(sequence_, container_);
+  // Testing necessary as absl::c_mismatch executes logic.
+  {
+    auto result = absl::c_mismatch(vector_, sequence_);
+    EXPECT_EQ(result.first, vector_.end());
+    EXPECT_EQ(result.second, sequence_.end());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_);
+    EXPECT_EQ(result.first, sequence_.end());
+    EXPECT_EQ(result.second, vector_.end());
+  }
+
+  sequence_.back() = 5;
+  {
+    auto result = absl::c_mismatch(vector_, sequence_);
+    EXPECT_EQ(result.first, std::prev(vector_.end()));
+    EXPECT_EQ(result.second, std::prev(sequence_.end()));
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_);
+    EXPECT_EQ(result.first, std::prev(sequence_.end()));
+    EXPECT_EQ(result.second, std::prev(vector_.end()));
+  }
+
+  sequence_.pop_back();
+  {
+    auto result = absl::c_mismatch(vector_, sequence_);
+    EXPECT_EQ(result.first, std::prev(vector_.end()));
+    EXPECT_EQ(result.second, sequence_.end());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_);
+    EXPECT_EQ(result.first, sequence_.end());
+    EXPECT_EQ(result.second, std::prev(vector_.end()));
+  }
+  {
+    struct NoNotEquals {
+      constexpr bool operator==(NoNotEquals) const { return true; }
+      constexpr bool operator!=(NoNotEquals) const = delete;
+    };
+    std::vector<NoNotEquals> first;
+    std::list<NoNotEquals> second;
+
+    // Check this still compiles.
+    absl::c_mismatch(first, second);
+  }
 }
 
 TEST_F(NonMutatingTest, MismatchWithPredicate) {
-  absl::c_mismatch(container_, sequence_, BinPredicate);
-  absl::c_mismatch(sequence_, container_, BinPredicate);
+  // Testing necessary as absl::c_mismatch executes logic.
+  {
+    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+    EXPECT_EQ(result.first, vector_.begin());
+    EXPECT_EQ(result.second, sequence_.begin());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+    EXPECT_EQ(result.first, sequence_.begin());
+    EXPECT_EQ(result.second, vector_.begin());
+  }
+
+  sequence_.front() = 0;
+  {
+    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+    EXPECT_EQ(result.first, vector_.begin());
+    EXPECT_EQ(result.second, sequence_.begin());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+    EXPECT_EQ(result.first, std::next(sequence_.begin()));
+    EXPECT_EQ(result.second, std::next(vector_.begin()));
+  }
+
+  sequence_.clear();
+  {
+    auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+    EXPECT_EQ(result.first, vector_.begin());
+    EXPECT_EQ(result.second, sequence_.end());
+  }
+  {
+    auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+    EXPECT_EQ(result.first, sequence_.end());
+    EXPECT_EQ(result.second, vector_.begin());
+  }
 }
 
 TEST_F(NonMutatingTest, Equal) {
   EXPECT_TRUE(absl::c_equal(vector_, sequence_));
   EXPECT_TRUE(absl::c_equal(sequence_, vector_));
+  EXPECT_TRUE(absl::c_equal(sequence_, array_));
+  EXPECT_TRUE(absl::c_equal(array_, vector_));
 
   // Test that behavior appropriately differs from that of equal().
   std::vector<int> vector_plus = {1, 2, 3};
   vector_plus.push_back(4);
   EXPECT_FALSE(absl::c_equal(vector_plus, sequence_));
   EXPECT_FALSE(absl::c_equal(sequence_, vector_plus));
+  EXPECT_FALSE(absl::c_equal(array_, vector_plus));
 }
 
 TEST_F(NonMutatingTest, EqualWithPredicate) {
   EXPECT_TRUE(absl::c_equal(vector_, sequence_, Equals));
   EXPECT_TRUE(absl::c_equal(sequence_, vector_, Equals));
+  EXPECT_TRUE(absl::c_equal(array_, sequence_, Equals));
+  EXPECT_TRUE(absl::c_equal(vector_, array_, Equals));
 
   // Test that behavior appropriately differs from that of equal().
   std::vector<int> vector_plus = {1, 2, 3};
   vector_plus.push_back(4);
   EXPECT_FALSE(absl::c_equal(vector_plus, sequence_, Equals));
   EXPECT_FALSE(absl::c_equal(sequence_, vector_plus, Equals));
+  EXPECT_FALSE(absl::c_equal(vector_plus, array_, Equals));
 }
 
 TEST_F(NonMutatingTest, IsPermutation) {
@@ -513,11 +593,9 @@
 TEST_F(SortingTest, NthElement) {
   std::vector<int> unsorted = {2, 4, 1, 3};
   absl::c_nth_element(unsorted, unsorted.begin() + 2);
-  EXPECT_THAT(unsorted,
-              ElementsAre(Lt(3), Lt(3), 3, Gt(3)));
+  EXPECT_THAT(unsorted, ElementsAre(Lt(3), Lt(3), 3, Gt(3)));
   absl::c_nth_element(unsorted, unsorted.begin() + 2, std::greater<int>());
-  EXPECT_THAT(unsorted,
-              ElementsAre(Gt(2), Gt(2), 2, Lt(2)));
+  EXPECT_THAT(unsorted, ElementsAre(Gt(2), Gt(2), 2, Lt(2)));
 }
 
 TEST(MutatingTest, IsPartitioned) {
@@ -670,6 +748,15 @@
   absl::c_swap_ranges(odds, evens);
   EXPECT_THAT(odds, ElementsAre(1, 3, 5));
   EXPECT_THAT(evens, ElementsAre(2, 4, 6));
+
+  odds.pop_back();
+  absl::c_swap_ranges(odds, evens);
+  EXPECT_THAT(odds, ElementsAre(2, 4));
+  EXPECT_THAT(evens, ElementsAre(1, 3, 6));
+
+  absl::c_swap_ranges(evens, odds);
+  EXPECT_THAT(odds, ElementsAre(1, 3));
+  EXPECT_THAT(evens, ElementsAre(2, 4, 6));
 }
 
 TEST_F(NonMutatingTest, Transform) {
@@ -684,6 +771,20 @@
   EXPECT_EQ(std::vector<int>({1, 5, 4}), z);
   *end = 7;
   EXPECT_EQ(std::vector<int>({1, 5, 4, 7}), z);
+
+  z.clear();
+  y.pop_back();
+  end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
+  EXPECT_EQ(std::vector<int>({1, 5}), z);
+  *end = 7;
+  EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
+
+  z.clear();
+  std::swap(x, y);
+  end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
+  EXPECT_EQ(std::vector<int>({1, 5}), z);
+  *end = 7;
+  EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
 }
 
 TEST(MutatingTest, Replace) {
@@ -749,10 +850,9 @@
 TEST(MutatingTest, StableSort) {
   std::vector<Element> test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}};
   absl::c_stable_sort(test_vector);
-  EXPECT_THAT(
-      test_vector,
-      ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1),
-                  IsElement(2, 0), IsElement(2, 2)));
+  EXPECT_THAT(test_vector,
+              ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1),
+                          IsElement(2, 0), IsElement(2, 2)));
 }
 
 TEST(MutatingTest, StableSortWithPredicate) {
@@ -760,10 +860,9 @@
   absl::c_stable_sort(test_vector, [](const Element& e1, const Element& e2) {
     return e2 < e1;
   });
-  EXPECT_THAT(
-      test_vector,
-      ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2),
-                  IsElement(1, 1), IsElement(1, 0)));
+  EXPECT_THAT(test_vector,
+              ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2),
+                          IsElement(1, 1), IsElement(1, 0)));
 }
 
 TEST(MutatingTest, ReplaceCopyIf) {
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 57caa06..5d67a50 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "atomic_hook",
@@ -34,6 +34,21 @@
     visibility = [
         "//absl:__subpackages__",
     ],
+    deps = [
+        ":config",
+        ":core_headers",
+    ],
+)
+
+cc_library(
+    name = "errno_saver",
+    hdrs = ["internal/errno_saver.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl:__subpackages__",
+    ],
+    deps = [":config"],
 )
 
 cc_library(
@@ -42,7 +57,10 @@
     hdrs = ["log_severity.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [":core_headers"],
+    deps = [
+        ":config",
+        ":core_headers",
+    ],
 )
 
 cc_library(
@@ -71,22 +89,24 @@
         "internal/spinlock_wait.cc",
         "internal/spinlock_win32.inc",
     ],
-    hdrs = [
-        "internal/scheduling_mode.h",
-        "internal/spinlock_wait.h",
-    ],
+    hdrs = ["internal/spinlock_wait.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     visibility = [
         "//absl/base:__pkg__",
     ],
-    deps = [":core_headers"],
+    deps = [
+        ":base_internal",
+        ":core_headers",
+        ":errno_saver",
+    ],
 )
 
 cc_library(
     name = "config",
     hdrs = [
         "config.h",
+        "options.h",
         "policy_checks.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
@@ -95,11 +115,18 @@
 
 cc_library(
     name = "dynamic_annotations",
-    srcs = ["dynamic_annotations.cc"],
-    hdrs = ["dynamic_annotations.h"],
+    srcs = [
+        "internal/dynamic_annotations.h",
+    ],
+    hdrs = [
+        "dynamic_annotations.h",
+    ],
     copts = ABSL_DEFAULT_COPTS,
-    defines = ["__CLANG_SUPPORT_DYN_ANNOTATION__"],
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        ":core_headers",
+    ],
 )
 
 cc_library(
@@ -134,18 +161,19 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = select({
         "//absl:windows": [],
+        "//absl:wasm": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     visibility = [
-        "//absl:__subpackages__",
+        "//visibility:public",
     ],
     deps = [
         ":base",
+        ":base_internal",
         ":config",
         ":core_headers",
         ":dynamic_annotations",
         ":raw_logging_internal",
-        ":spinlock_wait",
     ],
 )
 
@@ -164,6 +192,7 @@
         "//absl:__subpackages__",
     ],
     deps = [
+        ":config",
         "//absl/meta:type_traits",
     ],
 )
@@ -191,7 +220,10 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = select({
-        "//absl:windows": [],
+        "//absl:windows": [
+            "-DEFAULTLIB:advapi32.lib",
+        ],
+        "//absl:wasm": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
@@ -207,6 +239,19 @@
     ],
 )
 
+cc_library(
+    name = "atomic_hook_test_helper",
+    testonly = 1,
+    srcs = ["internal/atomic_hook_test_helper.cc"],
+    hdrs = ["internal/atomic_hook_test_helper.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":atomic_hook",
+        ":core_headers",
+    ],
+)
+
 cc_test(
     name = "atomic_hook_test",
     size = "small",
@@ -215,6 +260,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":atomic_hook",
+        ":atomic_hook_test_helper",
         ":core_headers",
         "@com_google_googletest//:gtest_main",
     ],
@@ -262,6 +308,19 @@
     ],
 )
 
+cc_test(
+    name = "errno_saver_test",
+    size = "small",
+    srcs = ["internal/errno_saver_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":errno_saver",
+        ":strerror",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
 cc_library(
     name = "exception_testing",
     testonly = 1,
@@ -355,8 +414,9 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":base",
+        ":base_internal",
+        ":config",
         ":core_headers",
-        ":spinlock_wait",
         "//absl/synchronization",
         "@com_google_googletest//:gtest",
     ],
@@ -371,8 +431,9 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":base",
+        ":base_internal",
+        ":config",
         ":core_headers",
-        ":spinlock_wait",
         "//absl/synchronization",
         "@com_google_googletest//:gtest_main",
     ],
@@ -402,6 +463,7 @@
     testonly = 1,
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = ["benchmark"],
     visibility = ["//visibility:private"],
     deps = [
         ":spinlock_benchmark_common",
@@ -489,8 +551,13 @@
     srcs = ["internal/low_level_alloc_test.cc"],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    tags = ["no_test_ios_x86_64"],
-    deps = [":malloc_internal"],
+    tags = [
+        "no_test_ios_x86_64",
+    ],
+    deps = [
+        ":malloc_internal",
+        "//absl/container:node_hash_map",
+    ],
 )
 
 cc_test(
@@ -522,28 +589,75 @@
 )
 
 cc_library(
-    name = "bits",
-    hdrs = ["internal/bits.h"],
+    name = "exponential_biased",
+    srcs = ["internal/exponential_biased.cc"],
+    hdrs = ["internal/exponential_biased.h"],
     linkopts = ABSL_DEFAULT_LINKOPTS,
     visibility = [
         "//absl:__subpackages__",
     ],
-    deps = [":core_headers"],
+    deps = [
+        ":config",
+        ":core_headers",
+    ],
 )
 
 cc_test(
-    name = "bits_test",
+    name = "exponential_biased_test",
     size = "small",
-    srcs = ["internal/bits_test.cc"],
+    srcs = ["internal/exponential_biased_test.cc"],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = ["//visibility:private"],
     deps = [
-        ":bits",
+        ":exponential_biased",
+        "//absl/strings",
         "@com_google_googletest//:gtest_main",
     ],
 )
 
 cc_library(
+    name = "periodic_sampler",
+    srcs = ["internal/periodic_sampler.cc"],
+    hdrs = ["internal/periodic_sampler.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":core_headers",
+        ":exponential_biased",
+    ],
+)
+
+cc_test(
+    name = "periodic_sampler_test",
+    size = "small",
+    srcs = ["internal/periodic_sampler_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":core_headers",
+        ":periodic_sampler",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_binary(
+    name = "periodic_sampler_benchmark",
+    testonly = 1,
+    srcs = ["internal/periodic_sampler_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":core_headers",
+        ":periodic_sampler",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
+
+cc_library(
     name = "scoped_set_env",
     testonly = 1,
     srcs = ["internal/scoped_set_env.cc"],
@@ -552,7 +666,10 @@
     visibility = [
         "//absl:__subpackages__",
     ],
-    deps = [":raw_logging_internal"],
+    deps = [
+        ":config",
+        ":raw_logging_internal",
+    ],
 )
 
 cc_test(
@@ -575,8 +692,104 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":log_severity",
+        "//absl/flags:flag_internal",
         "//absl/flags:marshalling",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_library(
+    name = "strerror",
+    srcs = ["internal/strerror.cc"],
+    hdrs = ["internal/strerror.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl:__subpackages__",
+    ],
+    deps = [
+        ":config",
+        ":core_headers",
+        ":errno_saver",
+    ],
+)
+
+cc_test(
+    name = "strerror_test",
+    size = "small",
+    srcs = ["internal/strerror_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":strerror",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_binary(
+    name = "strerror_benchmark",
+    testonly = 1,
+    srcs = ["internal/strerror_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":strerror",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
+
+cc_library(
+    name = "fast_type_id",
+    hdrs = ["internal/fast_type_id.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl:__subpackages__",
+    ],
+    deps = [
+        ":config",
+    ],
+)
+
+cc_test(
+    name = "fast_type_id_test",
+    size = "small",
+    srcs = ["internal/fast_type_id_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":fast_type_id",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "unique_small_name_test",
+    size = "small",
+    srcs = ["internal/unique_small_name_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    linkstatic = 1,
+    deps = [
+        ":core_headers",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "optimization_test",
+    size = "small",
+    srcs = ["optimization_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":core_headers",
+        "//absl/types:optional",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 2f11ef8..3d930b8 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -14,11 +14,27 @@
 # limitations under the License.
 #
 
+find_library(LIBRT rt)
+
 absl_cc_library(
   NAME
     atomic_hook
   HDRS
     "internal/atomic_hook.h"
+  DEPS
+    absl::config
+    absl::core_headers
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+)
+
+absl_cc_library(
+  NAME
+    errno_saver
+  HDRS
+    "internal/errno_saver.h"
+  DEPS
+    absl::config
   COPTS
     ${ABSL_DEFAULT_COPTS}
 )
@@ -56,7 +72,6 @@
   NAME
     spinlock_wait
   HDRS
-    "internal/scheduling_mode.h"
     "internal/spinlock_wait.h"
   SRCS
     "internal/spinlock_akaros.inc"
@@ -67,7 +82,9 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
+    absl::base_internal
     absl::core_headers
+    absl::errno_saver
 )
 
 absl_cc_library(
@@ -75,6 +92,7 @@
     config
   HDRS
     "config.h"
+    "options.h"
     "policy_checks.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
@@ -87,11 +105,11 @@
   HDRS
     "dynamic_annotations.h"
   SRCS
-    "dynamic_annotations.cc"
+    "internal/dynamic_annotations.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
-  DEFINES
-    "__CLANG_SUPPORT_DYN_ANNOTATION__"
+  DEPS
+    absl::config
   PUBLIC
 )
 
@@ -125,11 +143,11 @@
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::base
+    absl::base_internal
     absl::config
     absl::core_headers
     absl::dynamic_annotations
     absl::raw_logging_internal
-    absl::spinlock_wait
     Threads::Threads
 )
 
@@ -141,9 +159,11 @@
     "internal/identity.h"
     "internal/inline_variable.h"
     "internal/invoke.h"
+    "internal/scheduling_mode.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
+    absl::config
     absl::type_traits
 )
 
@@ -161,16 +181,18 @@
     "internal/thread_identity.h"
     "internal/tsan_mutex_interface.h"
     "internal/unscaledcycleclock.h"
-    "log_severity.h"
   SRCS
     "internal/cycleclock.cc"
     "internal/spinlock.cc"
     "internal/sysinfo.cc"
     "internal/thread_identity.cc"
     "internal/unscaledcycleclock.cc"
-    "log_severity.cc"
   COPTS
     ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+    $<$<BOOL:${LIBRT}>:-lrt>
+    $<$<BOOL:${MINGW}>:"advapi32">
   DEPS
     absl::atomic_hook
     absl::base_internal
@@ -254,6 +276,19 @@
     gtest_main
 )
 
+absl_cc_library(
+  NAME
+    atomic_hook_test_helper
+  SRCS
+    "internal/atomic_hook_test_helper.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::atomic_hook
+    absl::core_headers
+  TESTONLY
+)
+
 absl_cc_test(
   NAME
     atomic_hook_test
@@ -262,8 +297,10 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::atomic_hook_test_helper
     absl::atomic_hook
     absl::core_headers
+    gmock
     gtest_main
 )
 
@@ -282,6 +319,20 @@
 
 absl_cc_test(
   NAME
+    errno_saver_test
+  SRCS
+    "internal/errno_saver_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::errno_saver
+    absl::strerror
+    gmock
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
     throw_delegate_test
   SRCS
     "throw_delegate_test.cc"
@@ -333,8 +384,9 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::base
+    absl::config
+    absl::base_internal
     absl::core_headers
-    absl::spinlock_wait
     absl::synchronization
     gtest
   TESTONLY
@@ -350,8 +402,9 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::base
+    absl::base_internal
+    absl::config
     absl::core_headers
-    absl::spinlock_wait
     absl::synchronization
     gtest_main
 )
@@ -446,6 +499,7 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::malloc_internal
+    absl::node_hash_map
     Threads::Threads
 )
 
@@ -466,25 +520,56 @@
 
 absl_cc_library(
   NAME
-    bits
+    exponential_biased
+  SRCS
+    "internal/exponential_biased.cc"
   HDRS
-    "internal/bits.h"
+    "internal/exponential_biased.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
+    absl::config
     absl::core_headers
 )
 
 absl_cc_test(
   NAME
-    bits_test
+    exponential_biased_test
   SRCS
-    "internal/bits_test.cc"
+    "internal/exponential_biased_test.cc"
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
-    absl::bits
-    gtest_main
+    absl::exponential_biased
+    absl::strings
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    periodic_sampler
+  SRCS
+    "internal/periodic_sampler.cc"
+  HDRS
+    "internal/periodic_sampler.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+    absl::exponential_biased
+)
+
+absl_cc_test(
+  NAME
+    periodic_sampler_test
+  SRCS
+    "internal/periodic_sampler_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::core_headers
+    absl::periodic_sampler
+    gmock_main
 )
 
 absl_cc_library(
@@ -497,6 +582,7 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
+    absl::config
     absl::raw_logging_internal
 )
 
@@ -529,9 +615,79 @@
   SRCS
     "log_severity_test.cc"
   DEPS
+    absl::flags_internal
     absl::flags_marshalling
     absl::log_severity
     absl::strings
     gmock
     gtest_main
 )
+
+absl_cc_library(
+  NAME
+    strerror
+  SRCS
+    "internal/strerror.cc"
+  HDRS
+    "internal/strerror.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::core_headers
+    absl::errno_saver
+)
+
+absl_cc_test(
+  NAME
+    strerror_test
+  SRCS
+    "internal/strerror_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strerror
+    absl::strings
+    gmock
+    gtest_main
+)
+
+absl_cc_library(
+  NAME
+    fast_type_id
+  HDRS
+    "internal/fast_type_id.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+)
+
+absl_cc_test(
+  NAME
+    fast_type_id_test
+  SRCS
+    "internal/fast_type_id_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::fast_type_id
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    optimization_test
+  SRCS
+    "optimization_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::core_headers
+    absl::optional
+    gtest_main
+)
diff --git a/absl/base/attributes.h b/absl/base/attributes.h
index a7da62a..0ba1e7d 100644
--- a/absl/base/attributes.h
+++ b/absl/base/attributes.h
@@ -32,34 +32,12 @@
 // of them are not supported in older version of Clang. Thus, we check
 // `__has_attribute()` first. If the check fails, we check if we are on GCC and
 // assume the attribute exists on GCC (which is verified on GCC 4.7).
-//
-// -----------------------------------------------------------------------------
-// Sanitizer Attributes
-// -----------------------------------------------------------------------------
-//
-// Sanitizer-related attributes are not "defined" in this file (and indeed
-// are not defined as such in any file). To utilize the following
-// sanitizer-related attributes within your builds, define the following macros
-// within your build using a `-D` flag, along with the given value for
-// `-fsanitize`:
-//
-//   * `ADDRESS_SANITIZER` + `-fsanitize=address` (Clang, GCC 4.8)
-//   * `MEMORY_SANITIZER` + `-fsanitize=memory` (Clang-only)
-//   * `THREAD_SANITIZER + `-fsanitize=thread` (Clang, GCC 4.8+)
-//   * `UNDEFINED_BEHAVIOR_SANITIZER` + `-fsanitize=undefined` (Clang, GCC 4.9+)
-//   * `CONTROL_FLOW_INTEGRITY` + -fsanitize=cfi (Clang-only)
-//
-// Example:
-//
-//   // Enable branches in the Abseil code that are tagged for ASan:
-//   $ bazel build --copt=-DADDRESS_SANITIZER --copt=-fsanitize=address
-//     --linkopt=-fsanitize=address *target*
-//
-// Since these macro names are only supported by GCC and Clang, we only check
-// for `__GNUC__` (GCC or Clang) and the above macros.
+
 #ifndef ABSL_BASE_ATTRIBUTES_H_
 #define ABSL_BASE_ATTRIBUTES_H_
 
+#include "absl/base/config.h"
+
 // ABSL_HAVE_ATTRIBUTE
 //
 // A function-like feature checking macro that is a wrapper around
@@ -157,10 +135,12 @@
 // Tags a function as weak for the purposes of compilation and linking.
 // Weak attributes currently do not work properly in LLVM's Windows backend,
 // so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
-// for futher information.
-#if (ABSL_HAVE_ATTRIBUTE(weak) || \
+// for further information.
+// The MinGW compiler doesn't complain about the weak attribute until the link
+// step, presumably because Windows doesn't use ELF binaries.
+#if (ABSL_HAVE_ATTRIBUTE(weak) ||                   \
      (defined(__GNUC__) && !defined(__clang__))) && \
-    !(defined(__llvm__) && defined(_WIN32))
+    !(defined(__llvm__) && defined(_WIN32)) && !defined(__MINGW32__)
 #undef ABSL_ATTRIBUTE_WEAK
 #define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
 #define ABSL_HAVE_ATTRIBUTE_WEAK 1
@@ -232,7 +212,7 @@
 // out of bounds or does other scary things with memory.
 // NOTE: GCC supports AddressSanitizer(asan) since 4.8.
 // https://gcc.gnu.org/gcc-4.8/changes.html
-#if defined(__GNUC__)
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize_address)
 #define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
 #else
 #define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
@@ -240,13 +220,13 @@
 
 // ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
 //
-// Tells the  MemorySanitizer to relax the handling of a given function. All
-// "Use of uninitialized value" warnings from such functions will be suppressed,
-// and all values loaded from memory will be considered fully initialized.
-// This attribute is similar to the ADDRESS_SANITIZER attribute above, but deals
-// with initialized-ness rather than addressability issues.
+// Tells the MemorySanitizer to relax the handling of a given function. All "Use
+// of uninitialized value" warnings from such functions will be suppressed, and
+// all values loaded from memory will be considered fully initialized.  This
+// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute
+// above, but deals with initialized-ness rather than addressability issues.
 // NOTE: MemorySanitizer(msan) is supported by Clang but not GCC.
-#if defined(__clang__)
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory)
 #define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
 #else
 #define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
@@ -257,7 +237,7 @@
 // Tells the ThreadSanitizer to not instrument a given function.
 // NOTE: GCC supports ThreadSanitizer(tsan) since 4.8.
 // https://gcc.gnu.org/gcc-4.8/changes.html
-#if defined(__GNUC__)
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread)
 #define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
 #else
 #define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD
@@ -269,8 +249,10 @@
 // where certain behavior (eg. division by zero) is being used intentionally.
 // NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9.
 // https://gcc.gnu.org/gcc-4.9/changes.html
-#if defined(__GNUC__) && \
-    (defined(UNDEFINED_BEHAVIOR_SANITIZER) || defined(ADDRESS_SANITIZER))
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined)
+#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
+  __attribute__((no_sanitize_undefined))
+#elif ABSL_HAVE_ATTRIBUTE(no_sanitize)
 #define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
   __attribute__((no_sanitize("undefined")))
 #else
@@ -281,7 +263,7 @@
 //
 // Tells the ControlFlowIntegrity sanitizer to not instrument a given function.
 // See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details.
-#if defined(__GNUC__) && defined(CONTROL_FLOW_INTEGRITY)
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize)
 #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi")))
 #else
 #define ABSL_ATTRIBUTE_NO_SANITIZE_CFI
@@ -291,7 +273,7 @@
 //
 // Tells the SafeStack to not instrument a given function.
 // See https://clang.llvm.org/docs/SafeStack.html for details.
-#if defined(__GNUC__) && defined(SAFESTACK_SANITIZER)
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize)
 #define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \
   __attribute__((no_sanitize("safe-stack")))
 #else
@@ -505,8 +487,10 @@
 // packages/targets, as this may lead to conflicting definitions of functions at
 // link-time.
 //
+// XRay isn't currently supported on Android:
+// https://github.com/android/ndk/issues/368
 #if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \
-    !defined(ABSL_NO_XRAY_ATTRIBUTES)
+    !defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__)
 #define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]]
 #define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]]
 #if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args)
@@ -561,7 +545,19 @@
 
 // ABSL_ATTRIBUTE_PACKED
 //
-// Prevents the compiler from padding a structure to natural alignment
+// Instructs the compiler not to use natural alignment for a tagged data
+// structure, but instead to reduce its alignment to 1. This attribute can
+// either be applied to members of a structure or to a structure in its
+// entirety. Applying this attribute (judiciously) to a structure in its
+// entirety to optimize the memory footprint of very commonly-used structs is
+// fine. Do not apply this attribute to a structure in its entirety if the
+// purpose is to control the offsets of the members in the structure. Instead,
+// apply this attribute only to structure members that need it.
+//
+// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the
+// natural alignment of structure members not annotated is preserved. Aligned
+// member accesses are faster than non-aligned member accesses even if the
+// targeted microprocessor supports non-aligned accesses.
 #if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__))
 #define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__))
 #else
@@ -578,6 +574,86 @@
 #define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes)
 #endif
 
+// ABSL_FALLTHROUGH_INTENDED
+//
+// Annotates implicit fall-through between switch labels, allowing a case to
+// indicate intentional fallthrough and turn off warnings about any lack of a
+// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by
+// a semicolon and can be used in most places where `break` can, provided that
+// no statements exist between it and the next switch label.
+//
+// Example:
+//
+//  switch (x) {
+//    case 40:
+//    case 41:
+//      if (truth_is_out_there) {
+//        ++x;
+//        ABSL_FALLTHROUGH_INTENDED;  // Use instead of/along with annotations
+//                                    // in comments
+//      } else {
+//        return x;
+//      }
+//    case 42:
+//      ...
+//
+// Notes: when compiled with clang in C++11 mode, the ABSL_FALLTHROUGH_INTENDED
+// macro is expanded to the [[clang::fallthrough]] attribute, which is analysed
+// when  performing switch labels fall-through diagnostic
+// (`-Wimplicit-fallthrough`). See clang documentation on language extensions
+// for details:
+// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough
+//
+// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro
+// has no effect on diagnostics. In any case this macro has no effect on runtime
+// behavior and performance of code.
+
+#ifdef ABSL_FALLTHROUGH_INTENDED
+#error "ABSL_FALLTHROUGH_INTENDED should not be defined."
+#endif
+
+// TODO(zhangxy): Use c++17 standard [[fallthrough]] macro, when supported.
+#if defined(__clang__) && defined(__has_warning)
+#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
+#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]]
+#endif
+#elif defined(__GNUC__) && __GNUC__ >= 7
+#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
+#endif
+
+#ifndef ABSL_FALLTHROUGH_INTENDED
+#define ABSL_FALLTHROUGH_INTENDED \
+  do {                            \
+  } while (0)
+#endif
+
+// ABSL_DEPRECATED()
+//
+// Marks a deprecated class, struct, enum, function, method and variable
+// declarations. The macro argument is used as a custom diagnostic message (e.g.
+// suggestion of a better alternative).
+//
+// Examples:
+//
+//   class ABSL_DEPRECATED("Use Bar instead") Foo {...};
+//
+//   ABSL_DEPRECATED("Use Baz() instead") void Bar() {...}
+//
+//   template <typename T>
+//   ABSL_DEPRECATED("Use DoThat() instead")
+//   void DoThis();
+//
+// Every usage of a deprecated entity will trigger a warning when compiled with
+// clang's `-Wdeprecated-declarations` option. This option is turned off by
+// default, but the warnings will be reported by clang-tidy.
+#if defined(__clang__) && defined(__cplusplus) && __cplusplus >= 201103L
+#define ABSL_DEPRECATED(message) __attribute__((deprecated(message)))
+#endif
+
+#ifndef ABSL_DEPRECATED
+#define ABSL_DEPRECATED(message)
+#endif
+
 // ABSL_CONST_INIT
 //
 // A variable declaration annotated with the `ABSL_CONST_INIT` attribute will
@@ -599,7 +675,6 @@
 //
 // Note that this attribute is redundant if the variable is declared constexpr.
 #if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
-// NOLINTNEXTLINE(whitespace/braces)
 #define ABSL_CONST_INIT [[clang::require_constant_initialization]]
 #else
 #define ABSL_CONST_INIT
diff --git a/absl/base/bit_cast_test.cc b/absl/base/bit_cast_test.cc
index 4846add..8a3a41e 100644
--- a/absl/base/bit_cast_test.cc
+++ b/absl/base/bit_cast_test.cc
@@ -22,6 +22,7 @@
 #include "absl/base/macros.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 template <int N>
@@ -104,4 +105,5 @@
 }
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/call_once.h b/absl/base/call_once.h
index 4aa6360..96109f5 100644
--- a/absl/base/call_once.h
+++ b/absl/base/call_once.h
@@ -41,6 +41,7 @@
 #include "absl/base/port.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 class once_flag;
 
@@ -148,7 +149,7 @@
                   Args&&... args) {
 #ifndef NDEBUG
   {
-    uint32_t old_control = control->load(std::memory_order_acquire);
+    uint32_t old_control = control->load(std::memory_order_relaxed);
     if (old_control != kOnceInit &&
         old_control != kOnceRunning &&
         old_control != kOnceWaiter &&
@@ -166,16 +167,18 @@
   // Must do this before potentially modifying control word's state.
   base_internal::SchedulingHelper maybe_disable_scheduling(scheduling_mode);
   // Short circuit the simplest case to avoid procedure call overhead.
+  // The base_internal::SpinLockWait() call returns either kOnceInit or
+  // kOnceDone. If it returns kOnceDone, it must have loaded the control word
+  // with std::memory_order_acquire and seen a value of kOnceDone.
   uint32_t old_control = kOnceInit;
   if (control->compare_exchange_strong(old_control, kOnceRunning,
-                                       std::memory_order_acquire,
                                        std::memory_order_relaxed) ||
       base_internal::SpinLockWait(control, ABSL_ARRAYSIZE(trans), trans,
                                   scheduling_mode) == kOnceInit) {
-    base_internal::Invoke(std::forward<Callable>(fn),
+    base_internal::invoke(std::forward<Callable>(fn),
                           std::forward<Args>(args)...);
-    old_control = control->load(std::memory_order_relaxed);
-    control->store(base_internal::kOnceDone, std::memory_order_release);
+    old_control =
+        control->exchange(base_internal::kOnceDone, std::memory_order_release);
     if (old_control == base_internal::kOnceWaiter) {
       base_internal::SpinLockWake(control, true);
     }
@@ -210,6 +213,7 @@
   }
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_CALL_ONCE_H_
diff --git a/absl/base/call_once_test.cc b/absl/base/call_once_test.cc
index 9a5a5c1..11d26c4 100644
--- a/absl/base/call_once_test.cc
+++ b/absl/base/call_once_test.cc
@@ -24,6 +24,7 @@
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 absl::once_flag once;
@@ -102,4 +103,5 @@
 }
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/casts.h b/absl/base/casts.h
index aba0178..83c6912 100644
--- a/absl/base/casts.h
+++ b/absl/base/casts.h
@@ -34,6 +34,7 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace internal_casts {
 
@@ -158,16 +159,19 @@
   return dest;
 }
 
-// NOTE: This overload is only picked if the requirements of bit_cast are not
-// met. It is therefore UB, but is provided temporarily as previous versions of
-// this function template were unchecked. Do not use this in new code.
+// NOTE: This overload is only picked if the requirements of bit_cast are
+// not met. It is therefore UB, but is provided temporarily as previous
+// versions of this function template were unchecked. Do not use this in
+// new code.
 template <
     typename Dest, typename Source,
     typename std::enable_if<
-        !internal_casts::is_bitcastable<Dest, Source>::value, int>::type = 0>
+        !internal_casts::is_bitcastable<Dest, Source>::value,
+        int>::type = 0>
 ABSL_DEPRECATED(
-    "absl::bit_cast type requirements were violated. Update the types being "
-    "used such that they are the same size and are both TriviallyCopyable.")
+    "absl::bit_cast type requirements were violated. Update the types "
+    "being used such that they are the same size and are both "
+    "TriviallyCopyable.")
 inline Dest bit_cast(const Source& source) {
   static_assert(sizeof(Dest) == sizeof(Source),
                 "Source and destination types should have equal sizes.");
@@ -177,6 +181,7 @@
   return dest;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_CASTS_H_
diff --git a/absl/base/config.h b/absl/base/config.h
index 1cb69b0..3f7f32b 100644
--- a/absl/base/config.h
+++ b/absl/base/config.h
@@ -63,8 +63,72 @@
 #include <TargetConditionals.h>
 #endif
 
+#include "absl/base/options.h"
 #include "absl/base/policy_checks.h"
 
+// Helper macro to convert a CPP variable to a string literal.
+#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
+#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x)
+
+// -----------------------------------------------------------------------------
+// Abseil namespace annotations
+// -----------------------------------------------------------------------------
+
+// ABSL_NAMESPACE_BEGIN/ABSL_NAMESPACE_END
+//
+// An annotation placed at the beginning/end of each `namespace absl` scope.
+// This is used to inject an inline namespace.
+//
+// The proper way to write Abseil code in the `absl` namespace is:
+//
+// namespace absl {
+// ABSL_NAMESPACE_BEGIN
+//
+// void Foo();  // absl::Foo().
+//
+// ABSL_NAMESPACE_END
+// }  // namespace absl
+//
+// Users of Abseil should not use these macros, because users of Abseil should
+// not write `namespace absl {` in their own code for any reason.  (Abseil does
+// not support forward declarations of its own types, nor does it support
+// user-provided specialization of Abseil templates.  Code that violates these
+// rules may be broken without warning.)
+#if !defined(ABSL_OPTION_USE_INLINE_NAMESPACE) || \
+    !defined(ABSL_OPTION_INLINE_NAMESPACE_NAME)
+#error options.h is misconfigured.
+#endif
+
+// Check that ABSL_OPTION_INLINE_NAMESPACE_NAME is neither "head" nor ""
+#if defined(__cplusplus) && ABSL_OPTION_USE_INLINE_NAMESPACE == 1
+
+#define ABSL_INTERNAL_INLINE_NAMESPACE_STR \
+  ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME)
+
+static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != '\0',
+              "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must "
+              "not be empty.");
+static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
+                  ABSL_INTERNAL_INLINE_NAMESPACE_STR[1] != 'e' ||
+                  ABSL_INTERNAL_INLINE_NAMESPACE_STR[2] != 'a' ||
+                  ABSL_INTERNAL_INLINE_NAMESPACE_STR[3] != 'd' ||
+                  ABSL_INTERNAL_INLINE_NAMESPACE_STR[4] != '\0',
+              "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must "
+              "be changed to a new, unique identifier name.");
+
+#endif
+
+#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0
+#define ABSL_NAMESPACE_BEGIN
+#define ABSL_NAMESPACE_END
+#elif ABSL_OPTION_USE_INLINE_NAMESPACE == 1
+#define ABSL_NAMESPACE_BEGIN \
+  inline namespace ABSL_OPTION_INLINE_NAMESPACE_NAME {
+#define ABSL_NAMESPACE_END }
+#else
+#error options.h is misconfigured.
+#endif
+
 // -----------------------------------------------------------------------------
 // Compiler Feature Checks
 // -----------------------------------------------------------------------------
@@ -84,6 +148,18 @@
 #define ABSL_HAVE_BUILTIN(x) 0
 #endif
 
+#if defined(__is_identifier)
+#define ABSL_INTERNAL_HAS_KEYWORD(x) !(__is_identifier(x))
+#else
+#define ABSL_INTERNAL_HAS_KEYWORD(x) 0
+#endif
+
+#ifdef __has_feature
+#define ABSL_HAVE_FEATURE(f) __has_feature(f)
+#else
+#define ABSL_HAVE_FEATURE(f) 0
+#endif
+
 // ABSL_HAVE_TLS is defined to 1 when __thread should be supported.
 // We assume __thread is supported on Linux when compiled with Clang or compiled
 // against libstdc++ with _GLIBCXX_HAVE_TLS defined.
@@ -132,6 +208,17 @@
 #define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
 #endif
 
+// ABSL_HAVE_SOURCE_LOCATION_CURRENT
+//
+// Indicates whether `absl::SourceLocation::current()` will return useful
+// information in some contexts.
+#ifndef ABSL_HAVE_SOURCE_LOCATION_CURRENT
+#if ABSL_INTERNAL_HAS_KEYWORD(__builtin_LINE) && \
+    ABSL_INTERNAL_HAS_KEYWORD(__builtin_FILE)
+#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1
+#endif
+#endif
+
 // ABSL_HAVE_THREAD_LOCAL
 //
 // Checks whether C++11's `thread_local` storage duration specifier is
@@ -145,11 +232,9 @@
 // * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator
 //   targeting iOS 9.x.
 // * Xcode 10 moves the deployment target check for iOS < 9.0 to link time
-//   making __has_feature unreliable there.
+//   making ABSL_HAVE_FEATURE unreliable there.
 //
-// Otherwise, `__has_feature` is only supported by Clang so it has be inside
-// `defined(__APPLE__)` check.
-#if __has_feature(cxx_thread_local) && \
+#if ABSL_HAVE_FEATURE(cxx_thread_local) && \
     !(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
 #define ABSL_HAVE_THREAD_LOCAL 1
 #endif
@@ -181,13 +266,6 @@
 #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
@@ -235,13 +313,19 @@
 #error ABSL_HAVE_EXCEPTIONS cannot be directly set.
 
 #elif defined(__clang__)
-// TODO(calabrese)
-// Switch to using __cpp_exceptions when we no longer support versions < 3.6.
-// For details on this check, see:
-//   http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
-#if defined(__EXCEPTIONS) && __has_feature(cxx_exceptions)
+
+#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
+// Clang >= 3.6
+#if ABSL_HAVE_FEATURE(cxx_exceptions)
 #define ABSL_HAVE_EXCEPTIONS 1
-#endif  // defined(__EXCEPTIONS) && __has_feature(cxx_exceptions)
+#endif  // ABSL_HAVE_FEATURE(cxx_exceptions)
+#else
+// Clang < 3.6
+// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
+#if defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
+#define ABSL_HAVE_EXCEPTIONS 1
+#endif  // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
+#endif  // __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
 
 // Handle remaining special cases and default to exceptions being supported.
 #elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) &&    \
@@ -280,7 +364,7 @@
 #elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) ||   \
     defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
     defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
-    defined(__ASYLO__)
+    defined(__ASYLO__) || defined(__myriad2__)
 #define ABSL_HAVE_MMAP 1
 #endif
 
@@ -307,7 +391,7 @@
 
 // ABSL_HAVE_SEMAPHORE_H
 //
-// Checks whether the platform supports the <semaphore.h> header and sem_open(3)
+// Checks whether the platform supports the <semaphore.h> header and sem_init(3)
 // family of functions as standardized in POSIX.1-2001.
 //
 // Note: While Apple provides <semaphore.h> for both iOS and macOS, it is
@@ -334,6 +418,11 @@
 #define ABSL_HAVE_ALARM 1
 #elif defined(_MSC_VER)
 // feature tests for Microsoft's library
+#elif defined(__MINGW32__)
+// mingw32 doesn't provide alarm(2):
+// https://osdn.net/projects/mingw/scm/git/mingw-org-wsl/blobs/5.2-trunk/mingwrt/include/unistd.h
+// mingw-w64 provides a no-op implementation:
+// https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c
 #elif defined(__EMSCRIPTEN__)
 // emscripten doesn't support signals
 #elif defined(__Fuchsia__)
@@ -385,9 +474,9 @@
   (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
    __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \
   (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
-   __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 120000) || \
+   __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \
   (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
-   __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 50000))
+   __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000))
 #define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1
 #else
 #define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
@@ -463,6 +552,68 @@
 #define ABSL_HAVE_STD_STRING_VIEW 1
 #endif
 
+// ABSL_USES_STD_ANY
+//
+// Indicates whether absl::any is an alias for std::any.
+#if !defined(ABSL_OPTION_USE_STD_ANY)
+#error options.h is misconfigured.
+#elif ABSL_OPTION_USE_STD_ANY == 0 || \
+    (ABSL_OPTION_USE_STD_ANY == 2 && !defined(ABSL_HAVE_STD_ANY))
+#undef ABSL_USES_STD_ANY
+#elif ABSL_OPTION_USE_STD_ANY == 1 || \
+    (ABSL_OPTION_USE_STD_ANY == 2 && defined(ABSL_HAVE_STD_ANY))
+#define ABSL_USES_STD_ANY 1
+#else
+#error options.h is misconfigured.
+#endif
+
+// ABSL_USES_STD_OPTIONAL
+//
+// Indicates whether absl::optional is an alias for std::optional.
+#if !defined(ABSL_OPTION_USE_STD_OPTIONAL)
+#error options.h is misconfigured.
+#elif ABSL_OPTION_USE_STD_OPTIONAL == 0 || \
+    (ABSL_OPTION_USE_STD_OPTIONAL == 2 && !defined(ABSL_HAVE_STD_OPTIONAL))
+#undef ABSL_USES_STD_OPTIONAL
+#elif ABSL_OPTION_USE_STD_OPTIONAL == 1 || \
+    (ABSL_OPTION_USE_STD_OPTIONAL == 2 && defined(ABSL_HAVE_STD_OPTIONAL))
+#define ABSL_USES_STD_OPTIONAL 1
+#else
+#error options.h is misconfigured.
+#endif
+
+// ABSL_USES_STD_VARIANT
+//
+// Indicates whether absl::variant is an alias for std::variant.
+#if !defined(ABSL_OPTION_USE_STD_VARIANT)
+#error options.h is misconfigured.
+#elif ABSL_OPTION_USE_STD_VARIANT == 0 || \
+    (ABSL_OPTION_USE_STD_VARIANT == 2 && !defined(ABSL_HAVE_STD_VARIANT))
+#undef ABSL_USES_STD_VARIANT
+#elif ABSL_OPTION_USE_STD_VARIANT == 1 || \
+    (ABSL_OPTION_USE_STD_VARIANT == 2 && defined(ABSL_HAVE_STD_VARIANT))
+#define ABSL_USES_STD_VARIANT 1
+#else
+#error options.h is misconfigured.
+#endif
+
+// ABSL_USES_STD_STRING_VIEW
+//
+// Indicates whether absl::string_view is an alias for std::string_view.
+#if !defined(ABSL_OPTION_USE_STD_STRING_VIEW)
+#error options.h is misconfigured.
+#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0 || \
+    (ABSL_OPTION_USE_STD_STRING_VIEW == 2 &&  \
+     !defined(ABSL_HAVE_STD_STRING_VIEW))
+#undef ABSL_USES_STD_STRING_VIEW
+#elif ABSL_OPTION_USE_STD_STRING_VIEW == 1 || \
+    (ABSL_OPTION_USE_STD_STRING_VIEW == 2 &&  \
+     defined(ABSL_HAVE_STD_STRING_VIEW))
+#define ABSL_USES_STD_STRING_VIEW 1
+#else
+#error options.h is misconfigured.
+#endif
+
 // In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION
 // SEH exception from emplace for variant<SomeStruct> when constructing the
 // struct can throw. This defeats some of variant_test and
@@ -471,4 +622,93 @@
 #define ABSL_INTERNAL_MSVC_2017_DBG_MODE
 #endif
 
+// ABSL_INTERNAL_MANGLED_NS
+// ABSL_INTERNAL_MANGLED_BACKREFERENCE
+//
+// Internal macros for building up mangled names in our internal fork of CCTZ.
+// This implementation detail is only needed and provided for the MSVC build.
+//
+// These macros both expand to string literals.  ABSL_INTERNAL_MANGLED_NS is
+// the mangled spelling of the `absl` namespace, and
+// ABSL_INTERNAL_MANGLED_BACKREFERENCE is a back-reference integer representing
+// the proper count to skip past the CCTZ fork namespace names.  (This number
+// is one larger when there is an inline namespace name to skip.)
+#if defined(_MSC_VER)
+#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0
+#define ABSL_INTERNAL_MANGLED_NS "absl"
+#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "5"
+#else
+#define ABSL_INTERNAL_MANGLED_NS \
+  ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) "@absl"
+#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "6"
+#endif
+#endif
+
+#undef ABSL_INTERNAL_HAS_KEYWORD
+
+// ABSL_DLL
+//
+// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)`
+// so we can annotate symbols appropriately as being exported. When used in
+// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so
+// that consumers know the symbol is defined inside the DLL. In all other cases,
+// the macro expands to nothing.
+#if defined(_MSC_VER)
+#if defined(ABSL_BUILD_DLL)
+#define ABSL_DLL __declspec(dllexport)
+#elif defined(ABSL_CONSUME_DLL)
+#define ABSL_DLL __declspec(dllimport)
+#else
+#define ABSL_DLL
+#endif
+#else
+#define ABSL_DLL
+#endif  // defined(_MSC_VER)
+
+// ABSL_HAVE_MEMORY_SANITIZER
+//
+// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of
+// a compiler instrumentation module and a run-time library.
+#ifdef ABSL_HAVE_MEMORY_SANITIZER
+#error "ABSL_HAVE_MEMORY_SANITIZER cannot be directly set."
+#elif defined(MEMORY_SANITIZER)
+// The MEMORY_SANITIZER macro is deprecated but we will continue to honor it
+// for now.
+#define ABSL_HAVE_MEMORY_SANITIZER 1
+#elif defined(__SANITIZE_MEMORY__)
+#define ABSL_HAVE_MEMORY_SANITIZER 1
+#elif !defined(__native_client__) && ABSL_HAVE_FEATURE(memory_sanitizer)
+#define ABSL_HAVE_MEMORY_SANITIZER 1
+#endif
+
+// ABSL_HAVE_THREAD_SANITIZER
+//
+// ThreadSanitizer (TSan) is a fast data race detector.
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+#error "ABSL_HAVE_THREAD_SANITIZER cannot be directly set."
+#elif defined(THREAD_SANITIZER)
+// The THREAD_SANITIZER macro is deprecated but we will continue to honor it
+// for now.
+#define ABSL_HAVE_THREAD_SANITIZER 1
+#elif defined(__SANITIZE_THREAD__)
+#define ABSL_HAVE_THREAD_SANITIZER 1
+#elif ABSL_HAVE_FEATURE(thread_sanitizer)
+#define ABSL_HAVE_THREAD_SANITIZER 1
+#endif
+
+// ABSL_HAVE_ADDRESS_SANITIZER
+//
+// AddressSanitizer (ASan) is a fast memory error detector.
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#error "ABSL_HAVE_ADDRESS_SANITIZER cannot be directly set."
+#elif defined(ADDRESS_SANITIZER)
+// The ADDRESS_SANITIZER macro is deprecated but we will continue to honor it
+// for now.
+#define ABSL_HAVE_ADDRESS_SANITIZER 1
+#elif defined(__SANITIZE_ADDRESS__)
+#define ABSL_HAVE_ADDRESS_SANITIZER 1
+#elif ABSL_HAVE_FEATURE(address_sanitizer)
+#define ABSL_HAVE_ADDRESS_SANITIZER 1
+#endif
+
 #endif  // ABSL_BASE_CONFIG_H_
diff --git a/absl/base/const_init.h b/absl/base/const_init.h
index 17858a7..16520b6 100644
--- a/absl/base/const_init.h
+++ b/absl/base/const_init.h
@@ -22,6 +22,8 @@
 #ifndef ABSL_BASE_CONST_INIT_H_
 #define ABSL_BASE_CONST_INIT_H_
 
+#include "absl/base/config.h"
+
 // In general, objects with static storage duration (such as global variables)
 // can trigger tricky object lifetime situations.  Attempting to access them
 // from the constructors or destructors of other global objects can result in
@@ -62,11 +64,13 @@
 // or thread_local storage duration.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 enum ConstInitType {
   kConstInit,
 };
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_CONST_INIT_H_
diff --git a/absl/base/dynamic_annotations.cc b/absl/base/dynamic_annotations.cc
deleted file mode 100644
index 21e822e..0000000
--- a/absl/base/dynamic_annotations.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "absl/base/dynamic_annotations.h"
-
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-
-/* Compiler-based ThreadSanitizer defines
-   DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1
-   and provides its own definitions of the functions. */
-
-#ifndef DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL
-# define DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL 0
-#endif
-
-/* Each function is empty and called (via a macro) only in debug mode.
-   The arguments are captured by dynamic tools at runtime. */
-
-#if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 && !defined(__native_client__)
-
-#if __has_feature(memory_sanitizer)
-#include <sanitizer/msan_interface.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void AnnotateRWLockCreate(const char *, int,
-                          const volatile void *){}
-void AnnotateRWLockDestroy(const char *, int,
-                           const volatile void *){}
-void AnnotateRWLockAcquired(const char *, int,
-                            const volatile void *, long){}
-void AnnotateRWLockReleased(const char *, int,
-                            const volatile void *, long){}
-void AnnotateBenignRace(const char *, int,
-                        const volatile void *,
-                        const char *){}
-void AnnotateBenignRaceSized(const char *, int,
-                             const volatile void *,
-                             size_t,
-                             const char *) {}
-void AnnotateThreadName(const char *, int,
-                        const char *){}
-void AnnotateIgnoreReadsBegin(const char *, int){}
-void AnnotateIgnoreReadsEnd(const char *, int){}
-void AnnotateIgnoreWritesBegin(const char *, int){}
-void AnnotateIgnoreWritesEnd(const char *, int){}
-void AnnotateEnableRaceDetection(const char *, int, int){}
-void AnnotateMemoryIsInitialized(const char *, int,
-                                 const volatile void *mem, size_t size) {
-#if __has_feature(memory_sanitizer)
-  __msan_unpoison(mem, size);
-#else
-  (void)mem;
-  (void)size;
-#endif
-}
-
-void AnnotateMemoryIsUninitialized(const char *, int,
-                                   const volatile void *mem, size_t size) {
-#if __has_feature(memory_sanitizer)
-  __msan_allocated_memory(mem, size);
-#else
-  (void)mem;
-  (void)size;
-#endif
-}
-
-static int GetRunningOnValgrind(void) {
-#ifdef RUNNING_ON_VALGRIND
-  if (RUNNING_ON_VALGRIND) return 1;
-#endif
-  char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND");
-  if (running_on_valgrind_str) {
-    return strcmp(running_on_valgrind_str, "0") != 0;
-  }
-  return 0;
-}
-
-/* See the comments in dynamic_annotations.h */
-int RunningOnValgrind(void) {
-  static volatile int running_on_valgrind = -1;
-  int local_running_on_valgrind = running_on_valgrind;
-  /* C doesn't have thread-safe initialization of statics, and we
-     don't want to depend on pthread_once here, so hack it. */
-  ANNOTATE_BENIGN_RACE(&running_on_valgrind, "safe hack");
-  if (local_running_on_valgrind == -1)
-    running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
-  return local_running_on_valgrind;
-}
-
-/* See the comments in dynamic_annotations.h */
-double ValgrindSlowdown(void) {
-  /* Same initialization hack as in RunningOnValgrind(). */
-  static volatile double slowdown = 0.0;
-  double local_slowdown = slowdown;
-  ANNOTATE_BENIGN_RACE(&slowdown, "safe hack");
-  if (RunningOnValgrind() == 0) {
-    return 1.0;
-  }
-  if (local_slowdown == 0.0) {
-    char *env = getenv("VALGRIND_SLOWDOWN");
-    slowdown = local_slowdown = env ? atof(env) : 50.0;
-  }
-  return local_slowdown;
-}
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-#endif  /* DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h
index 65a54b4..545f8cb 100644
--- a/absl/base/dynamic_annotations.h
+++ b/absl/base/dynamic_annotations.h
@@ -1,389 +1,482 @@
-/*
- *  Copyright 2017 The Abseil Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/* This file defines dynamic annotations for use with dynamic analysis
-   tool such as valgrind, PIN, etc.
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 
-   Dynamic annotation is a source code annotation that affects
-   the generated code (that is, the annotation is not a comment).
-   Each such annotation is attached to a particular
-   instruction and/or to a particular object (address) in the program.
-
-   The annotations that should be used by users are macros in all upper-case
-   (e.g., ANNOTATE_THREAD_NAME).
-
-   Actual implementation of these macros may differ depending on the
-   dynamic analysis tool being used.
-
-   This file supports the following configurations:
-   - Dynamic Annotations enabled (with static thread-safety warnings disabled).
-     In this case, macros expand to functions implemented by Thread Sanitizer,
-     when building with TSan. When not provided an external implementation,
-     dynamic_annotations.cc provides no-op implementations.
-
-   - Static Clang thread-safety warnings enabled.
-     When building with a Clang compiler that supports thread-safety warnings,
-     a subset of annotations can be statically-checked at compile-time. We
-     expand these macros to static-inline functions that can be analyzed for
-     thread-safety, but afterwards elided when building the final binary.
-
-   - All annotations are disabled.
-     If neither Dynamic Annotations nor Clang thread-safety warnings are
-     enabled, then all annotation-macros expand to empty. */
+// This file defines dynamic annotations for use with dynamic analysis tool
+// such as valgrind, PIN, etc.
+//
+// Dynamic annotation is a source code annotation that affects the generated
+// code (that is, the annotation is not a comment). Each such annotation is
+// attached to a particular instruction and/or to a particular object (address)
+// in the program.
+//
+// The annotations that should be used by users are macros in all upper-case
+// (e.g., ABSL_ANNOTATE_THREAD_NAME).
+//
+// Actual implementation of these macros may differ depending on the dynamic
+// analysis tool being used.
+//
+// This file supports the following configurations:
+// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
+//   In this case, macros expand to functions implemented by Thread Sanitizer,
+//   when building with TSan. When not provided an external implementation,
+//   dynamic_annotations.cc provides no-op implementations.
+//
+// - Static Clang thread-safety warnings enabled.
+//   When building with a Clang compiler that supports thread-safety warnings,
+//   a subset of annotations can be statically-checked at compile-time. We
+//   expand these macros to static-inline functions that can be analyzed for
+//   thread-safety, but afterwards elided when building the final binary.
+//
+// - All annotations are disabled.
+//   If neither Dynamic Annotations nor Clang thread-safety warnings are
+//   enabled, then all annotation-macros expand to empty.
 
 #ifndef ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
 #define ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
 
-#ifndef DYNAMIC_ANNOTATIONS_ENABLED
-# define DYNAMIC_ANNOTATIONS_ENABLED 0
-#endif
-
-#if DYNAMIC_ANNOTATIONS_ENABLED != 0
-
-  /* -------------------------------------------------------------
-     Annotations that suppress errors.  It is usually better to express the
-     program's synchronization using the other annotations, but these can
-     be used when all else fails. */
-
-  /* Report that we may have a benign race at "pointer", with size
-     "sizeof(*(pointer))". "pointer" must be a non-void* pointer.  Insert at the
-     point where "pointer" has been allocated, preferably close to the point
-     where the race happens.  See also ANNOTATE_BENIGN_RACE_STATIC. */
-  #define ANNOTATE_BENIGN_RACE(pointer, description) \
-    AnnotateBenignRaceSized(__FILE__, __LINE__, pointer, \
-                            sizeof(*(pointer)), description)
-
-  /* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
-     the memory range [address, address+size). */
-  #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
-    AnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description)
-
-  /* Enable (enable!=0) or disable (enable==0) race detection for all threads.
-     This annotation could be useful if you want to skip expensive race analysis
-     during some period of program execution, e.g. during initialization. */
-  #define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
-    AnnotateEnableRaceDetection(__FILE__, __LINE__, enable)
-
-  /* -------------------------------------------------------------
-     Annotations useful for debugging. */
-
-  /* Report the current thread name to a race detector. */
-  #define ANNOTATE_THREAD_NAME(name) \
-    AnnotateThreadName(__FILE__, __LINE__, name)
-
-  /* -------------------------------------------------------------
-     Annotations useful when implementing locks.  They are not
-     normally needed by modules that merely use locks.
-     The "lock" argument is a pointer to the lock object. */
-
-  /* Report that a lock has been created at address "lock". */
-  #define ANNOTATE_RWLOCK_CREATE(lock) \
-    AnnotateRWLockCreate(__FILE__, __LINE__, lock)
-
-  /* Report that a linker initialized lock has been created at address "lock".
-   */
-#ifdef THREAD_SANITIZER
-  #define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
-    AnnotateRWLockCreateStatic(__FILE__, __LINE__, lock)
-#else
-  #define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)
-#endif
-
-  /* Report that the lock at address "lock" is about to be destroyed. */
-  #define ANNOTATE_RWLOCK_DESTROY(lock) \
-    AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
-
-  /* Report that the lock at address "lock" has been acquired.
-     is_w=1 for writer lock, is_w=0 for reader lock. */
-  #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
-    AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w)
-
-  /* Report that the lock at address "lock" is about to be released. */
-  #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
-    AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w)
-
-#else  /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
-
-  #define ANNOTATE_RWLOCK_CREATE(lock) /* empty */
-  #define ANNOTATE_RWLOCK_CREATE_STATIC(lock) /* empty */
-  #define ANNOTATE_RWLOCK_DESTROY(lock) /* empty */
-  #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */
-  #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */
-  #define ANNOTATE_BENIGN_RACE(address, description) /* empty */
-  #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */
-  #define ANNOTATE_THREAD_NAME(name) /* empty */
-  #define ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */
-
-#endif  /* DYNAMIC_ANNOTATIONS_ENABLED */
-
-/* These annotations are also made available to LLVM's Memory Sanitizer */
-#if DYNAMIC_ANNOTATIONS_ENABLED == 1 || defined(MEMORY_SANITIZER)
-  #define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
-    AnnotateMemoryIsInitialized(__FILE__, __LINE__, address, size)
-
-  #define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
-    AnnotateMemoryIsUninitialized(__FILE__, __LINE__, address, size)
-#else
-  #define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) /* empty */
-  #define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) /* empty */
-#endif  /* DYNAMIC_ANNOTATIONS_ENABLED || MEMORY_SANITIZER */
-
-/* TODO(delesley) -- Replace __CLANG_SUPPORT_DYN_ANNOTATION__ with the
-   appropriate feature ID. */
-#if defined(__clang__) && (!defined(SWIG)) \
-    && defined(__CLANG_SUPPORT_DYN_ANNOTATION__)
-
-  #if DYNAMIC_ANNOTATIONS_ENABLED == 0
-    #define ANNOTALYSIS_ENABLED
-  #endif
-
-  /* When running in opt-mode, GCC will issue a warning, if these attributes are
-     compiled. Only include them when compiling using Clang. */
-  #define ATTRIBUTE_IGNORE_READS_BEGIN \
-      __attribute((exclusive_lock_function("*")))
-  #define ATTRIBUTE_IGNORE_READS_END \
-      __attribute((unlock_function("*")))
-#else
-  #define ATTRIBUTE_IGNORE_READS_BEGIN  /* empty */
-  #define ATTRIBUTE_IGNORE_READS_END  /* empty */
-#endif  /* defined(__clang__) && ... */
-
-#if (DYNAMIC_ANNOTATIONS_ENABLED != 0) || defined(ANNOTALYSIS_ENABLED)
-  #define ANNOTATIONS_ENABLED
-#endif
-
-#if (DYNAMIC_ANNOTATIONS_ENABLED != 0)
-
-  /* Request the analysis tool to ignore all reads in the current thread
-     until ANNOTATE_IGNORE_READS_END is called.
-     Useful to ignore intentional racey reads, while still checking
-     other reads and all writes.
-     See also ANNOTATE_UNPROTECTED_READ. */
-  #define ANNOTATE_IGNORE_READS_BEGIN() \
-    AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
-
-  /* Stop ignoring reads. */
-  #define ANNOTATE_IGNORE_READS_END() \
-    AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
-
-  /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead. */
-  #define ANNOTATE_IGNORE_WRITES_BEGIN() \
-    AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
-
-  /* Stop ignoring writes. */
-  #define ANNOTATE_IGNORE_WRITES_END() \
-    AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
-
-/* Clang provides limited support for static thread-safety analysis
-   through a feature called Annotalysis. We configure macro-definitions
-   according to whether Annotalysis support is available. */
-#elif defined(ANNOTALYSIS_ENABLED)
-
-  #define ANNOTATE_IGNORE_READS_BEGIN() \
-    StaticAnnotateIgnoreReadsBegin(__FILE__, __LINE__)
-
-  #define ANNOTATE_IGNORE_READS_END() \
-    StaticAnnotateIgnoreReadsEnd(__FILE__, __LINE__)
-
-  #define ANNOTATE_IGNORE_WRITES_BEGIN() \
-    StaticAnnotateIgnoreWritesBegin(__FILE__, __LINE__)
-
-  #define ANNOTATE_IGNORE_WRITES_END() \
-    StaticAnnotateIgnoreWritesEnd(__FILE__, __LINE__)
-
-#else
-  #define ANNOTATE_IGNORE_READS_BEGIN()  /* empty */
-  #define ANNOTATE_IGNORE_READS_END()  /* empty */
-  #define ANNOTATE_IGNORE_WRITES_BEGIN()  /* empty */
-  #define ANNOTATE_IGNORE_WRITES_END()  /* empty */
-#endif
-
-/* Implement the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
-   primitive annotations defined above. */
-#if defined(ANNOTATIONS_ENABLED)
-
-  /* Start ignoring all memory accesses (both reads and writes). */
-  #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
-    do {                                           \
-      ANNOTATE_IGNORE_READS_BEGIN();               \
-      ANNOTATE_IGNORE_WRITES_BEGIN();              \
-    }while (0)
-
-  /* Stop ignoring both reads and writes. */
-  #define ANNOTATE_IGNORE_READS_AND_WRITES_END()   \
-    do {                                           \
-      ANNOTATE_IGNORE_WRITES_END();                \
-      ANNOTATE_IGNORE_READS_END();                 \
-    }while (0)
-
-#else
-  #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN()  /* empty */
-  #define ANNOTATE_IGNORE_READS_AND_WRITES_END()  /* empty */
-#endif
-
-/* Use the macros above rather than using these functions directly. */
 #include <stddef.h>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #ifdef __cplusplus
-extern "C" {
-#endif
-void AnnotateRWLockCreate(const char *file, int line,
-                          const volatile void *lock);
-void AnnotateRWLockCreateStatic(const char *file, int line,
-                          const volatile void *lock);
-void AnnotateRWLockDestroy(const char *file, int line,
-                           const volatile void *lock);
-void AnnotateRWLockAcquired(const char *file, int line,
-                            const volatile void *lock, long is_w);  /* NOLINT */
-void AnnotateRWLockReleased(const char *file, int line,
-                            const volatile void *lock, long is_w);  /* NOLINT */
-void AnnotateBenignRace(const char *file, int line,
-                        const volatile void *address,
-                        const char *description);
-void AnnotateBenignRaceSized(const char *file, int line,
-                        const volatile void *address,
-                        size_t size,
-                        const char *description);
-void AnnotateThreadName(const char *file, int line,
-                        const char *name);
-void AnnotateEnableRaceDetection(const char *file, int line, int enable);
-void AnnotateMemoryIsInitialized(const char *file, int line,
-                                 const volatile void *mem, size_t size);
-void AnnotateMemoryIsUninitialized(const char *file, int line,
-                                   const volatile void *mem, size_t size);
-
-/* Annotations expand to these functions, when Dynamic Annotations are enabled.
-   These functions are either implemented as no-op calls, if no Sanitizer is
-   attached, or provided with externally-linked implementations by a library
-   like ThreadSanitizer. */
-void AnnotateIgnoreReadsBegin(const char *file, int line)
-    ATTRIBUTE_IGNORE_READS_BEGIN;
-void AnnotateIgnoreReadsEnd(const char *file, int line)
-    ATTRIBUTE_IGNORE_READS_END;
-void AnnotateIgnoreWritesBegin(const char *file, int line);
-void AnnotateIgnoreWritesEnd(const char *file, int line);
-
-#if defined(ANNOTALYSIS_ENABLED)
-/* When Annotalysis is enabled without Dynamic Annotations, the use of
-   static-inline functions allows the annotations to be read at compile-time,
-   while still letting the compiler elide the functions from the final build.
-
-   TODO(delesley) -- The exclusive lock here ignores writes as well, but
-   allows IGNORE_READS_AND_WRITES to work properly. */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-static inline void StaticAnnotateIgnoreReadsBegin(const char *file, int line)
-    ATTRIBUTE_IGNORE_READS_BEGIN { (void)file; (void)line; }
-static inline void StaticAnnotateIgnoreReadsEnd(const char *file, int line)
-    ATTRIBUTE_IGNORE_READS_END { (void)file; (void)line; }
-static inline void StaticAnnotateIgnoreWritesBegin(
-    const char *file, int line) { (void)file; (void)line; }
-static inline void StaticAnnotateIgnoreWritesEnd(
-    const char *file, int line) { (void)file; (void)line; }
-#pragma GCC diagnostic pop
+#include "absl/base/macros.h"
 #endif
 
-/* Return non-zero value if running under valgrind.
+// TODO(rogeeff): Remove after the backward compatibility period.
+#include "absl/base/internal/dynamic_annotations.h"  // IWYU pragma: export
 
-  If "valgrind.h" is included into dynamic_annotations.cc,
-  the regular valgrind mechanism will be used.
-  See http://valgrind.org/docs/manual/manual-core-adv.html about
-  RUNNING_ON_VALGRIND and other valgrind "client requests".
-  The file "valgrind.h" may be obtained by doing
-     svn co svn://svn.valgrind.org/valgrind/trunk/include
+// -------------------------------------------------------------------------
+// Decide which features are enabled.
 
-  If for some reason you can't use "valgrind.h" or want to fake valgrind,
-  there are two ways to make this function return non-zero:
-    - Use environment variable: export RUNNING_ON_VALGRIND=1
-    - Make your tool intercept the function RunningOnValgrind() and
-      change its return value.
- */
-int RunningOnValgrind(void);
+#ifdef ABSL_HAVE_THREAD_SANITIZER
 
-/* ValgrindSlowdown returns:
-    * 1.0, if (RunningOnValgrind() == 0)
-    * 50.0, if (RunningOnValgrind() != 0 && getenv("VALGRIND_SLOWDOWN") == NULL)
-    * atof(getenv("VALGRIND_SLOWDOWN")) otherwise
-   This function can be used to scale timeout values:
-   EXAMPLE:
-   for (;;) {
-     DoExpensiveBackgroundTask();
-     SleepForSeconds(5 * ValgrindSlowdown());
-   }
- */
-double ValgrindSlowdown(void);
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
+
+#else
+
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
+
+// Clang provides limited support for static thread-safety analysis through a
+// feature called Annotalysis. We configure macro-definitions according to
+// whether Annotalysis support is available. When running in opt-mode, GCC
+// will issue a warning, if these attributes are compiled. Only include them
+// when compiling using Clang.
+
+#if defined(__clang__)
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 1
+#if !defined(SWIG)
+#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
+#endif
+#else
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
+#endif
+
+// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
+  ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+
+#endif  // ABSL_HAVE_THREAD_SANITIZER
 
 #ifdef __cplusplus
-}
+#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
+#define ABSL_INTERNAL_END_EXTERN_C }  // extern "C"
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
+#define ABSL_INTERNAL_STATIC_INLINE inline
+#else
+#define ABSL_INTERNAL_BEGIN_EXTERN_C  // empty
+#define ABSL_INTERNAL_END_EXTERN_C    // empty
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
+#define ABSL_INTERNAL_STATIC_INLINE static inline
 #endif
 
-/* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+// -------------------------------------------------------------------------
+// Define race annotations.
 
-     Instead of doing
-        ANNOTATE_IGNORE_READS_BEGIN();
-        ... = x;
-        ANNOTATE_IGNORE_READS_END();
-     one can use
-        ... = ANNOTATE_UNPROTECTED_READ(x); */
-#if defined(__cplusplus) && defined(ANNOTATIONS_ENABLED)
+#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
+
+// -------------------------------------------------------------
+// Annotations that suppress errors. It is usually better to express the
+// program's synchronization using the other annotations, but these can be used
+// when all else fails.
+
+// Report that we may have a benign race at `pointer`, with size
+// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
+// point where `pointer` has been allocated, preferably close to the point
+// where the race happens. See also ABSL_ANNOTATE_BENIGN_RACE_STATIC.
+#define ABSL_ANNOTATE_BENIGN_RACE(pointer, description) \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized)  \
+  (__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
+
+// Same as ABSL_ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
+// the memory range [`address`, `address`+`size`).
+#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized)              \
+  (__FILE__, __LINE__, address, size, description)
+
+// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
+// This annotation could be useful if you want to skip expensive race analysis
+// during some period of program execution, e.g. during initialization.
+#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable)        \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
+  (__FILE__, __LINE__, enable)
+
+// -------------------------------------------------------------
+// Annotations useful for debugging.
+
+// Report the current thread `name` to a race detector.
+#define ABSL_ANNOTATE_THREAD_NAME(name) \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
+
+// -------------------------------------------------------------
+// Annotations useful when implementing locks. They are not normally needed by
+// modules that merely use locks. The `lock` argument is a pointer to the lock
+// object.
+
+// Report that a lock has been created at address `lock`.
+#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
+
+// Report that a linker initialized lock has been created at address `lock`.
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock)          \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
+  (__FILE__, __LINE__, lock)
+#else
+#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
+  ABSL_ANNOTATE_RWLOCK_CREATE(lock)
+#endif
+
+// Report that the lock at address `lock` is about to be destroyed.
+#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
+
+// Report that the lock at address `lock` has been acquired.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w)     \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
+  (__FILE__, __LINE__, lock, is_w)
+
+// Report that the lock at address `lock` is about to be released.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w)     \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
+  (__FILE__, __LINE__, lock, is_w)
+
+// Apply ABSL_ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
+#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description)      \
+  namespace {                                                          \
+  class static_var##_annotator {                                       \
+   public:                                                             \
+    static_var##_annotator() {                                         \
+      ABSL_ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
+                                      #static_var ": " description);   \
+    }                                                                  \
+  };                                                                   \
+  static static_var##_annotator the##static_var##_annotator;           \
+  }  // namespace
+
+// Function prototypes of annotations provided by the compiler-based sanitizer
+// implementation.
+ABSL_INTERNAL_BEGIN_EXTERN_C
+void AnnotateRWLockCreate(const char* file, int line,
+                          const volatile void* lock);
+void AnnotateRWLockCreateStatic(const char* file, int line,
+                                const volatile void* lock);
+void AnnotateRWLockDestroy(const char* file, int line,
+                           const volatile void* lock);
+void AnnotateRWLockAcquired(const char* file, int line,
+                            const volatile void* lock, long is_w);  // NOLINT
+void AnnotateRWLockReleased(const char* file, int line,
+                            const volatile void* lock, long is_w);  // NOLINT
+void AnnotateBenignRace(const char* file, int line,
+                        const volatile void* address, const char* description);
+void AnnotateBenignRaceSized(const char* file, int line,
+                             const volatile void* address, size_t size,
+                             const char* description);
+void AnnotateThreadName(const char* file, int line, const char* name);
+void AnnotateEnableRaceDetection(const char* file, int line, int enable);
+ABSL_INTERNAL_END_EXTERN_C
+
+#else  // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
+
+#define ABSL_ANNOTATE_RWLOCK_CREATE(lock)                            // empty
+#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock)                     // empty
+#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock)                           // empty
+#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w)                    // empty
+#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w)                    // empty
+#define ABSL_ANNOTATE_BENIGN_RACE(address, description)              // empty
+#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description)  // empty
+#define ABSL_ANNOTATE_THREAD_NAME(name)                              // empty
+#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable)                  // empty
+#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description)    // empty
+
+#endif  // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+
+// -------------------------------------------------------------------------
+// Define memory annotations.
+
+#ifdef ABSL_HAVE_MEMORY_SANITIZER
+
+#include <sanitizer/msan_interface.h>
+
+#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+  __msan_unpoison(address, size)
+
+#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+  __msan_allocated_memory(address, size)
+
+#else  // !defined(ABSL_HAVE_MEMORY_SANITIZER)
+
+// TODO(rogeeff): remove this branch
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+  do {                                                     \
+    (void)(address);                                       \
+    (void)(size);                                          \
+  } while (0)
+#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+  do {                                                       \
+    (void)(address);                                         \
+    (void)(size);                                            \
+  } while (0)
+#else
+
+#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size)    // empty
+#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size)  // empty
+
+#endif
+
+#endif  // ABSL_HAVE_MEMORY_SANITIZER
+
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END attributes.
+
+#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
+  __attribute((exclusive_lock_function("*")))
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
+  __attribute((unlock_function("*")))
+
+#else  // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE  // empty
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE    // empty
+
+#endif  // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END annotations.
+
+#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
+
+// Request the analysis tool to ignore all reads in the current thread until
+// ABSL_ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
+// reads, while still checking other reads and all writes.
+// See also ABSL_ANNOTATE_UNPROTECTED_READ.
+#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
+
+// Stop ignoring reads.
+#define ABSL_ANNOTATE_IGNORE_READS_END() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
+
+// Function prototypes of annotations provided by the compiler-based sanitizer
+// implementation.
+ABSL_INTERNAL_BEGIN_EXTERN_C
+void AnnotateIgnoreReadsBegin(const char* file, int line)
+    ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE;
+void AnnotateIgnoreReadsEnd(const char* file,
+                            int line) ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE;
+ABSL_INTERNAL_END_EXTERN_C
+
+#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
+
+// When Annotalysis is enabled without Dynamic Annotations, the use of
+// static-inline functions allows the annotations to be read at compile-time,
+// while still letting the compiler elide the functions from the final build.
+//
+// TODO(delesley) -- The exclusive lock here ignores writes as well, but
+// allows IGNORE_READS_AND_WRITES to work properly.
+
+#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)()
+
+#define ABSL_ANNOTATE_IGNORE_READS_END() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)()
+
+ABSL_INTERNAL_STATIC_INLINE void AbslInternalAnnotateIgnoreReadsBegin()
+    ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE {}
+
+ABSL_INTERNAL_STATIC_INLINE void AbslInternalAnnotateIgnoreReadsEnd()
+    ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE {}
+
+#else
+
+#define ABSL_ANNOTATE_IGNORE_READS_BEGIN()  // empty
+#define ABSL_ANNOTATE_IGNORE_READS_END()    // empty
+
+#endif
+
+// -------------------------------------------------------------------------
+// Define IGNORE_WRITES_BEGIN/_END annotations.
+
+#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
+
+// Similar to ABSL_ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
+#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
+
+// Stop ignoring writes.
+#define ABSL_ANNOTATE_IGNORE_WRITES_END() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
+
+// Function prototypes of annotations provided by the compiler-based sanitizer
+// implementation.
+ABSL_INTERNAL_BEGIN_EXTERN_C
+void AnnotateIgnoreWritesBegin(const char* file, int line);
+void AnnotateIgnoreWritesEnd(const char* file, int line);
+ABSL_INTERNAL_END_EXTERN_C
+
+#else
+
+#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN()  // empty
+#define ABSL_ANNOTATE_IGNORE_WRITES_END()    // empty
+
+#endif
+
+// -------------------------------------------------------------------------
+// Define the ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
+// primitive annotations defined above.
+//
+//     Instead of doing
+//        ABSL_ANNOTATE_IGNORE_READS_BEGIN();
+//        ... = x;
+//        ABSL_ANNOTATE_IGNORE_READS_END();
+//     one can use
+//        ... = ABSL_ANNOTATE_UNPROTECTED_READ(x);
+
+#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
+
+// Start ignoring all memory accesses (both reads and writes).
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+  do {                                                \
+    ABSL_ANNOTATE_IGNORE_READS_BEGIN();               \
+    ABSL_ANNOTATE_IGNORE_WRITES_BEGIN();              \
+  } while (0)
+
+// Stop ignoring both reads and writes.
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+  do {                                              \
+    ABSL_ANNOTATE_IGNORE_WRITES_END();              \
+    ABSL_ANNOTATE_IGNORE_READS_END();               \
+  } while (0)
+
+#ifdef __cplusplus
+// ABSL_ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+#define ABSL_ANNOTATE_UNPROTECTED_READ(x) \
+  absl::base_internal::AnnotateUnprotectedRead(x)
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
 template <typename T>
-inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) { /* NOLINT */
-  ANNOTATE_IGNORE_READS_BEGIN();
+inline T AnnotateUnprotectedRead(const volatile T& x) {  // NOLINT
+  ABSL_ANNOTATE_IGNORE_READS_BEGIN();
   T res = x;
-  ANNOTATE_IGNORE_READS_END();
+  ABSL_ANNOTATE_IGNORE_READS_END();
   return res;
-  }
-#else
-  #define ANNOTATE_UNPROTECTED_READ(x) (x)
+}
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
 #endif
 
-#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus)
-  /* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
-  #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description)        \
-    namespace {                                                       \
-      class static_var ## _annotator {                                \
-       public:                                                        \
-        static_var ## _annotator() {                                  \
-          ANNOTATE_BENIGN_RACE_SIZED(&static_var,                     \
-                                      sizeof(static_var),             \
-            # static_var ": " description);                           \
-        }                                                             \
-      };                                                              \
-      static static_var ## _annotator the ## static_var ## _annotator;\
-    }  // namespace
-#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
-  #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description)  /* empty */
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
-
-#ifdef ADDRESS_SANITIZER
-/* Describe the current state of a contiguous container such as e.g.
- * std::vector or std::string. For more details see
- * sanitizer/common_interface_defs.h, which is provided by the compiler. */
-#include <sanitizer/common_interface_defs.h>
-#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
-  __sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
-#define ADDRESS_SANITIZER_REDZONE(name)         \
-  struct { char x[8] __attribute__ ((aligned (8))); } name
 #else
-#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
-#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
-#endif  // ADDRESS_SANITIZER
 
-/* Undefine the macros intended only in this file. */
-#undef ANNOTALYSIS_ENABLED
-#undef ANNOTATIONS_ENABLED
-#undef ATTRIBUTE_IGNORE_READS_BEGIN
-#undef ATTRIBUTE_IGNORE_READS_END
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN()  // empty
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END()    // empty
+#define ABSL_ANNOTATE_UNPROTECTED_READ(x) (x)
 
-#endif  /* ABSL_BASE_DYNAMIC_ANNOTATIONS_H_ */
+#endif
+
+#ifdef __cplusplus
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+ABSL_INTERNAL_BEGIN_EXTERN_C
+int RunningOnValgrind();
+double ValgrindSlowdown();
+ABSL_INTERNAL_END_EXTERN_C
+#else
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+ABSL_DEPRECATED(
+    "Don't use this interface. It is misleading and is being deleted.")
+ABSL_ATTRIBUTE_ALWAYS_INLINE inline int RunningOnValgrind() { return 0; }
+ABSL_DEPRECATED(
+    "Don't use this interface. It is misleading and is being deleted.")
+ABSL_ATTRIBUTE_ALWAYS_INLINE inline double ValgrindSlowdown() { return 1.0; }
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+using absl::base_internal::RunningOnValgrind;
+using absl::base_internal::ValgrindSlowdown;
+#endif
+#endif
+
+// -------------------------------------------------------------------------
+// Address sanitizer annotations
+
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+// Describe the current state of a contiguous container such as e.g.
+// std::vector or std::string. For more details see
+// sanitizer/common_interface_defs.h, which is provided by the compiler.
+#include <sanitizer/common_interface_defs.h>
+
+#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
+  __sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
+#define ABSL_ADDRESS_SANITIZER_REDZONE(name) \
+  struct {                                   \
+    char x[8] __attribute__((aligned(8)));   \
+  } name
+
+#else
+
+#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)  // empty
+#define ABSL_ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
+
+#endif  // ABSL_HAVE_ADDRESS_SANITIZER
+
+// -------------------------------------------------------------------------
+// Undefine the macros intended only for this file.
+
+#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_BEGIN_EXTERN_C
+#undef ABSL_INTERNAL_END_EXTERN_C
+#undef ABSL_INTERNAL_STATIC_INLINE
+
+#endif  // ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
diff --git a/absl/base/exception_safety_testing_test.cc b/absl/base/exception_safety_testing_test.cc
index 575b535..a59be29 100644
--- a/absl/base/exception_safety_testing_test.cc
+++ b/absl/base/exception_safety_testing_test.cc
@@ -328,17 +328,15 @@
   UnsetCountdown();
 }
 
-using Storage =
-    absl::aligned_storage_t<sizeof(ThrowingValue<>), alignof(ThrowingValue<>)>;
-
 TEST(ThrowingValueTest, NonThrowingPlacementDelete) {
   constexpr int kArrayLen = 2;
   // We intentionally create extra space to store the tag allocated by placement
   // new[].
   constexpr int kStorageLen = 4;
 
-  Storage buf;
-  Storage array_buf[kStorageLen];
+  alignas(ThrowingValue<>) unsigned char buf[sizeof(ThrowingValue<>)];
+  alignas(ThrowingValue<>) unsigned char
+      array_buf[sizeof(ThrowingValue<>[kStorageLen])];
   auto* placed = new (&buf) ThrowingValue<>(1);
   auto placed_array = new (&array_buf) ThrowingValue<>[kArrayLen];
 
@@ -902,12 +900,12 @@
 }
 
 TEST(ConstructorTrackerTest, NotDestroyedAfter) {
-  absl::aligned_storage_t<sizeof(Tracked), alignof(Tracked)> storage;
+  alignas(Tracked) unsigned char storage[sizeof(Tracked)];
   EXPECT_NONFATAL_FAILURE(
       {
         exceptions_internal::ConstructorTracker ct(
             exceptions_internal::countdown);
-        new (&storage) Tracked;
+        new (&storage) Tracked();
       },
       "not destroyed");
 }
@@ -924,11 +922,11 @@
 
 TEST(ConstructorTrackerTest, ConstructedTwice) {
   exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
-  absl::aligned_storage_t<sizeof(Tracked), alignof(Tracked)> storage;
+  alignas(Tracked) unsigned char storage[sizeof(Tracked)];
   EXPECT_NONFATAL_FAILURE(
       {
-        new (&storage) Tracked;
-        new (&storage) Tracked;
+        new (&storage) Tracked();
+        new (&storage) Tracked();
         reinterpret_cast<Tracked*>(&storage)->~Tracked();
       },
       "re-constructed");
diff --git a/absl/base/inline_variable_test.cc b/absl/base/inline_variable_test.cc
index 471f706..37a40e1 100644
--- a/absl/base/inline_variable_test.cc
+++ b/absl/base/inline_variable_test.cc
@@ -20,6 +20,7 @@
 #include "gtest/gtest.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace inline_variable_testing_internal {
 namespace {
 
@@ -59,4 +60,5 @@
 
 }  // namespace
 }  // namespace inline_variable_testing_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/inline_variable_test_a.cc b/absl/base/inline_variable_test_a.cc
index d0b8e7d..f96a58d 100644
--- a/absl/base/inline_variable_test_a.cc
+++ b/absl/base/inline_variable_test_a.cc
@@ -15,6 +15,7 @@
 #include "absl/base/internal/inline_variable_testing.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace inline_variable_testing_internal {
 
 const Foo& get_foo_a() { return inline_variable_foo; }
@@ -22,4 +23,5 @@
 const int& get_int_a() { return inline_variable_int; }
 
 }  // namespace inline_variable_testing_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/inline_variable_test_b.cc b/absl/base/inline_variable_test_b.cc
index 931d56d..038adc3 100644
--- a/absl/base/inline_variable_test_b.cc
+++ b/absl/base/inline_variable_test_b.cc
@@ -15,6 +15,7 @@
 #include "absl/base/internal/inline_variable_testing.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace inline_variable_testing_internal {
 
 const Foo& get_foo_b() { return inline_variable_foo; }
@@ -22,4 +23,5 @@
 const int& get_int_b() { return inline_variable_int; }
 
 }  // namespace inline_variable_testing_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/atomic_hook.h b/absl/base/internal/atomic_hook.h
index 803e905..ae21cd7 100644
--- a/absl/base/internal/atomic_hook.h
+++ b/absl/base/internal/atomic_hook.h
@@ -11,7 +11,6 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
-//
 
 #ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
 #define ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
@@ -21,28 +20,51 @@
 #include <cstdint>
 #include <utility>
 
-#ifdef _MSC_FULL_VER
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+
+#if defined(_MSC_VER) && !defined(__clang__)
+#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 0
+#else
+#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 1
+#endif
+
+#if defined(_MSC_VER)
 #define ABSL_HAVE_WORKING_ATOMIC_POINTER 0
 #else
 #define ABSL_HAVE_WORKING_ATOMIC_POINTER 1
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 template <typename T>
 class AtomicHook;
 
-// AtomicHook is a helper class, templatized on a raw function pointer type, for
-// implementing Abseil customization hooks.  It is a callable object that
-// dispatches to the registered hook.
+// To workaround AtomicHook not being constant-initializable on some platforms,
+// prefer to annotate instances with `ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES`
+// instead of `ABSL_CONST_INIT`.
+#if ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
+#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_CONST_INIT
+#else
+#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+#endif
+
+// `AtomicHook` is a helper class, templatized on a raw function pointer type,
+// for implementing Abseil customization hooks.  It is a callable object that
+// dispatches to the registered hook.  Objects of type `AtomicHook` must have
+// static or thread storage duration.
 //
 // A default constructed object performs a no-op (and returns a default
 // constructed object) if no hook has been registered.
 //
-// Hooks can be pre-registered via constant initialization, for example,
-// ABSL_CONST_INIT static AtomicHook<void(*)()> my_hook(DefaultAction);
-// and then changed at runtime via a call to Store().
+// Hooks can be pre-registered via constant initialization, for example:
+//
+// ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static AtomicHook<void(*)()>
+//     my_hook(DefaultAction);
+//
+// and then changed at runtime via a call to `Store()`.
 //
 // Reads and writes guarantee memory_order_acquire/memory_order_release
 // semantics.
@@ -57,12 +79,23 @@
 
   // Constructs an object that by default dispatches to/returns the
   // pre-registered default_fn when no hook has been registered at runtime.
-#if ABSL_HAVE_WORKING_ATOMIC_POINTER
+#if ABSL_HAVE_WORKING_ATOMIC_POINTER && ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
   explicit constexpr AtomicHook(FnPtr default_fn)
       : hook_(default_fn), default_fn_(default_fn) {}
-#else
+#elif ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
   explicit constexpr AtomicHook(FnPtr default_fn)
       : hook_(kUninitialized), default_fn_(default_fn) {}
+#else
+  // As of January 2020, on all known versions of MSVC this constructor runs in
+  // the global constructor sequence.  If `Store()` is called by a dynamic
+  // initializer, we want to preserve the value, even if this constructor runs
+  // after the call to `Store()`.  If not, `hook_` will be
+  // zero-initialized by the linker and we have no need to set it.
+  // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html
+  explicit constexpr AtomicHook(FnPtr default_fn)
+      : /* hook_(deliberately omitted), */ default_fn_(default_fn) {
+    static_assert(kUninitialized == 0, "here we rely on zero-initialization");
+  }
 #endif
 
   // Stores the provided function pointer as the value for this hook.
@@ -158,8 +191,10 @@
 };
 
 #undef ABSL_HAVE_WORKING_ATOMIC_POINTER
+#undef ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
diff --git a/absl/base/internal/atomic_hook_test.cc b/absl/base/internal/atomic_hook_test.cc
index ecc8040..e577a8f 100644
--- a/absl/base/internal/atomic_hook_test.cc
+++ b/absl/base/internal/atomic_hook_test.cc
@@ -14,16 +14,22 @@
 
 #include "absl/base/internal/atomic_hook.h"
 
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/base/attributes.h"
+#include "absl/base/internal/atomic_hook_test_helper.h"
 
 namespace {
 
+using ::testing::Eq;
+
 int value = 0;
 void TestHook(int x) { value = x; }
 
 TEST(AtomicHookTest, NoDefaultFunction) {
-  ABSL_CONST_INIT static absl::base_internal::AtomicHook<void(*)(int)> hook;
+  ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
+      void (*)(int)>
+      hook;
   value = 0;
 
   // Test the default DummyFunction.
@@ -49,8 +55,9 @@
 
 TEST(AtomicHookTest, WithDefaultFunction) {
   // Set the default value to TestHook at compile-time.
-  ABSL_CONST_INIT static absl::base_internal::AtomicHook<void (*)(int)> hook(
-      TestHook);
+  ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
+      void (*)(int)>
+      hook(TestHook);
   value = 0;
 
   // Test the default value is TestHook.
@@ -67,4 +74,24 @@
   EXPECT_EQ(value, 2);
 }
 
+ABSL_CONST_INIT int override_func_calls = 0;
+void OverrideFunc() { override_func_calls++; }
+static struct OverrideInstaller {
+  OverrideInstaller() { absl::atomic_hook_internal::func.Store(OverrideFunc); }
+} override_installer;
+
+TEST(AtomicHookTest, DynamicInitFromAnotherTU) {
+  // MSVC 14.2 doesn't do constexpr static init correctly; in particular it
+  // tends to sequence static init (i.e. defaults) of `AtomicHook` objects
+  // after their dynamic init (i.e. overrides), overwriting whatever value was
+  // written during dynamic init.  This regression test validates the fix.
+  // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html
+  EXPECT_THAT(absl::atomic_hook_internal::default_func_calls, Eq(0));
+  EXPECT_THAT(override_func_calls, Eq(0));
+  absl::atomic_hook_internal::func();
+  EXPECT_THAT(absl::atomic_hook_internal::default_func_calls, Eq(0));
+  EXPECT_THAT(override_func_calls, Eq(1));
+  EXPECT_THAT(absl::atomic_hook_internal::func.Load(), Eq(OverrideFunc));
+}
+
 }  // namespace
diff --git a/absl/base/internal/atomic_hook_test_helper.cc b/absl/base/internal/atomic_hook_test_helper.cc
new file mode 100644
index 0000000..537d47c
--- /dev/null
+++ b/absl/base/internal/atomic_hook_test_helper.cc
@@ -0,0 +1,32 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/atomic_hook_test_helper.h"
+
+#include "absl/base/attributes.h"
+#include "absl/base/internal/atomic_hook.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace atomic_hook_internal {
+
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<VoidF>
+    func(DefaultFunc);
+ABSL_CONST_INIT int default_func_calls = 0;
+void DefaultFunc() { default_func_calls++; }
+void RegisterFunc(VoidF f) { func.Store(f); }
+
+}  // namespace atomic_hook_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/base/internal/atomic_hook_test_helper.h b/absl/base/internal/atomic_hook_test_helper.h
new file mode 100644
index 0000000..3e72b49
--- /dev/null
+++ b/absl/base/internal/atomic_hook_test_helper.h
@@ -0,0 +1,34 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_
+#define ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_
+
+#include "absl/base/internal/atomic_hook.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace atomic_hook_internal {
+
+using VoidF = void (*)();
+extern absl::base_internal::AtomicHook<VoidF> func;
+extern int default_func_calls;
+void DefaultFunc();
+void RegisterFunc(VoidF func);
+
+}  // namespace atomic_hook_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_BASE_ATOMIC_HOOK_TEST_HELPER_H_
diff --git a/absl/base/internal/bits.h b/absl/base/internal/bits.h
deleted file mode 100644
index b0780f2..0000000
--- a/absl/base/internal/bits.h
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_BASE_INTERNAL_BITS_H_
-#define ABSL_BASE_INTERNAL_BITS_H_
-
-// This file contains bitwise ops which are implementation details of various
-// absl libraries.
-
-#include <cstdint>
-
-// Clang on Windows has __builtin_clzll; otherwise we need to use the
-// windows intrinsic functions.
-#if defined(_MSC_VER)
-#include <intrin.h>
-#if defined(_M_X64)
-#pragma intrinsic(_BitScanReverse64)
-#pragma intrinsic(_BitScanForward64)
-#endif
-#pragma intrinsic(_BitScanReverse)
-#pragma intrinsic(_BitScanForward)
-#endif
-
-#include "absl/base/attributes.h"
-
-#if defined(_MSC_VER)
-// We can achieve something similar to attribute((always_inline)) with MSVC by
-// using the __forceinline keyword, however this is not perfect. MSVC is
-// much less aggressive about inlining, and even with the __forceinline keyword.
-#define ABSL_BASE_INTERNAL_FORCEINLINE __forceinline
-#else
-// Use default attribute inline.
-#define ABSL_BASE_INTERNAL_FORCEINLINE inline ABSL_ATTRIBUTE_ALWAYS_INLINE
-#endif
-
-
-namespace absl {
-namespace base_internal {
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64Slow(uint64_t n) {
-  int zeroes = 60;
-  if (n >> 32) zeroes -= 32, n >>= 32;
-  if (n >> 16) zeroes -= 16, n >>= 16;
-  if (n >> 8) zeroes -= 8, n >>= 8;
-  if (n >> 4) zeroes -= 4, n >>= 4;
-  return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64(uint64_t n) {
-#if defined(_MSC_VER) && defined(_M_X64)
-  // MSVC does not have __buitin_clzll. Use _BitScanReverse64.
-  unsigned long result = 0;  // NOLINT(runtime/int)
-  if (_BitScanReverse64(&result, n)) {
-    return 63 - result;
-  }
-  return 64;
-#elif defined(_MSC_VER)
-  // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse
-  unsigned long result = 0;  // NOLINT(runtime/int)
-  if ((n >> 32) && _BitScanReverse(&result, n >> 32)) {
-    return 31 - result;
-  }
-  if (_BitScanReverse(&result, n)) {
-    return 63 - result;
-  }
-  return 64;
-#elif defined(__GNUC__)
-  // Use __builtin_clzll, which uses the following instructions:
-  //  x86: bsr
-  //  ARM64: clz
-  //  PPC: cntlzd
-  static_assert(sizeof(unsigned long long) == sizeof(n),  // NOLINT(runtime/int)
-                "__builtin_clzll does not take 64-bit arg");
-
-  // Handle 0 as a special case because __builtin_clzll(0) is undefined.
-  if (n == 0) {
-    return 64;
-  }
-  return __builtin_clzll(n);
-#else
-  return CountLeadingZeros64Slow(n);
-#endif
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32Slow(uint64_t n) {
-  int zeroes = 28;
-  if (n >> 16) zeroes -= 16, n >>= 16;
-  if (n >> 8) zeroes -= 8, n >>= 8;
-  if (n >> 4) zeroes -= 4, n >>= 4;
-  return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32(uint32_t n) {
-#if defined(_MSC_VER)
-  unsigned long result = 0;  // NOLINT(runtime/int)
-  if (_BitScanReverse(&result, n)) {
-    return 31 - result;
-  }
-  return 32;
-#elif defined(__GNUC__)
-  // Use __builtin_clz, which uses the following instructions:
-  //  x86: bsr
-  //  ARM64: clz
-  //  PPC: cntlzd
-  static_assert(sizeof(int) == sizeof(n),
-                "__builtin_clz does not take 32-bit arg");
-
-  // Handle 0 as a special case because __builtin_clz(0) is undefined.
-  if (n == 0) {
-    return 32;
-  }
-  return __builtin_clz(n);
-#else
-  return CountLeadingZeros32Slow(n);
-#endif
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64Slow(uint64_t n) {
-  int c = 63;
-  n &= ~n + 1;
-  if (n & 0x00000000FFFFFFFF) c -= 32;
-  if (n & 0x0000FFFF0000FFFF) c -= 16;
-  if (n & 0x00FF00FF00FF00FF) c -= 8;
-  if (n & 0x0F0F0F0F0F0F0F0F) c -= 4;
-  if (n & 0x3333333333333333) c -= 2;
-  if (n & 0x5555555555555555) c -= 1;
-  return c;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64(uint64_t n) {
-#if defined(_MSC_VER) && defined(_M_X64)
-  unsigned long result = 0;  // NOLINT(runtime/int)
-  _BitScanForward64(&result, n);
-  return result;
-#elif defined(_MSC_VER)
-  unsigned long result = 0;  // NOLINT(runtime/int)
-  if (static_cast<uint32_t>(n) == 0) {
-    _BitScanForward(&result, n >> 32);
-    return result + 32;
-  }
-  _BitScanForward(&result, n);
-  return result;
-#elif defined(__GNUC__)
-  static_assert(sizeof(unsigned long long) == sizeof(n),  // NOLINT(runtime/int)
-                "__builtin_ctzll does not take 64-bit arg");
-  return __builtin_ctzll(n);
-#else
-  return CountTrailingZerosNonZero64Slow(n);
-#endif
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32Slow(uint32_t n) {
-  int c = 31;
-  n &= ~n + 1;
-  if (n & 0x0000FFFF) c -= 16;
-  if (n & 0x00FF00FF) c -= 8;
-  if (n & 0x0F0F0F0F) c -= 4;
-  if (n & 0x33333333) c -= 2;
-  if (n & 0x55555555) c -= 1;
-  return c;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32(uint32_t n) {
-#if defined(_MSC_VER)
-  unsigned long result = 0;  // NOLINT(runtime/int)
-  _BitScanForward(&result, n);
-  return result;
-#elif defined(__GNUC__)
-  static_assert(sizeof(int) == sizeof(n),
-                "__builtin_ctz does not take 32-bit arg");
-  return __builtin_ctz(n);
-#else
-  return CountTrailingZerosNonZero32Slow(n);
-#endif
-}
-
-#undef ABSL_BASE_INTERNAL_FORCEINLINE
-
-}  // namespace base_internal
-}  // namespace absl
-
-#endif  // ABSL_BASE_INTERNAL_BITS_H_
diff --git a/absl/base/internal/bits_test.cc b/absl/base/internal/bits_test.cc
deleted file mode 100644
index 7855fa6..0000000
--- a/absl/base/internal/bits_test.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/base/internal/bits.h"
-
-#include "gtest/gtest.h"
-
-namespace {
-
-int CLZ64(uint64_t n) {
-  int fast = absl::base_internal::CountLeadingZeros64(n);
-  int slow = absl::base_internal::CountLeadingZeros64Slow(n);
-  EXPECT_EQ(fast, slow) << n;
-  return fast;
-}
-
-TEST(BitsTest, CountLeadingZeros64) {
-  EXPECT_EQ(64, CLZ64(uint64_t{}));
-  EXPECT_EQ(0, CLZ64(~uint64_t{}));
-
-  for (int index = 0; index < 64; index++) {
-    uint64_t x = static_cast<uint64_t>(1) << index;
-    const auto cnt = 63 - index;
-    ASSERT_EQ(cnt, CLZ64(x)) << index;
-    ASSERT_EQ(cnt, CLZ64(x + x - 1)) << index;
-  }
-}
-
-int CLZ32(uint32_t n) {
-  int fast = absl::base_internal::CountLeadingZeros32(n);
-  int slow = absl::base_internal::CountLeadingZeros32Slow(n);
-  EXPECT_EQ(fast, slow) << n;
-  return fast;
-}
-
-TEST(BitsTest, CountLeadingZeros32) {
-  EXPECT_EQ(32, CLZ32(uint32_t{}));
-  EXPECT_EQ(0, CLZ32(~uint32_t{}));
-
-  for (int index = 0; index < 32; index++) {
-    uint32_t x = static_cast<uint32_t>(1) << index;
-    const auto cnt = 31 - index;
-    ASSERT_EQ(cnt, CLZ32(x)) << index;
-    ASSERT_EQ(cnt, CLZ32(x + x - 1)) << index;
-    ASSERT_EQ(CLZ64(x), CLZ32(x) + 32);
-  }
-}
-
-int CTZ64(uint64_t n) {
-  int fast = absl::base_internal::CountTrailingZerosNonZero64(n);
-  int slow = absl::base_internal::CountTrailingZerosNonZero64Slow(n);
-  EXPECT_EQ(fast, slow) << n;
-  return fast;
-}
-
-TEST(BitsTest, CountTrailingZerosNonZero64) {
-  EXPECT_EQ(0, CTZ64(~uint64_t{}));
-
-  for (int index = 0; index < 64; index++) {
-    uint64_t x = static_cast<uint64_t>(1) << index;
-    const auto cnt = index;
-    ASSERT_EQ(cnt, CTZ64(x)) << index;
-    ASSERT_EQ(cnt, CTZ64(~(x - 1))) << index;
-  }
-}
-
-int CTZ32(uint32_t n) {
-  int fast = absl::base_internal::CountTrailingZerosNonZero32(n);
-  int slow = absl::base_internal::CountTrailingZerosNonZero32Slow(n);
-  EXPECT_EQ(fast, slow) << n;
-  return fast;
-}
-
-TEST(BitsTest, CountTrailingZerosNonZero32) {
-  EXPECT_EQ(0, CTZ32(~uint32_t{}));
-
-  for (int index = 0; index < 32; index++) {
-    uint32_t x = static_cast<uint32_t>(1) << index;
-    const auto cnt = index;
-    ASSERT_EQ(cnt, CTZ32(x)) << index;
-    ASSERT_EQ(cnt, CTZ32(~(x - 1))) << index;
-  }
-}
-
-
-}  // namespace
diff --git a/absl/base/internal/cycleclock.cc b/absl/base/internal/cycleclock.cc
index e9844b7..0e65005 100644
--- a/absl/base/internal/cycleclock.cc
+++ b/absl/base/internal/cycleclock.cc
@@ -28,6 +28,7 @@
 #include "absl/base/internal/unscaledcycleclock.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 #if ABSL_USE_UNSCALED_CYCLECLOCK
@@ -102,4 +103,5 @@
 #endif
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/cycleclock.h b/absl/base/internal/cycleclock.h
index 794564e..a18b584 100644
--- a/absl/base/internal/cycleclock.h
+++ b/absl/base/internal/cycleclock.h
@@ -44,7 +44,10 @@
 
 #include <cstdint>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // -----------------------------------------------------------------------------
@@ -85,6 +88,7 @@
 };
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_CYCLECLOCK_H_
diff --git a/absl/base/internal/direct_mmap.h b/absl/base/internal/direct_mmap.h
index 0401ddf..16accf0 100644
--- a/absl/base/internal/direct_mmap.h
+++ b/absl/base/internal/direct_mmap.h
@@ -61,7 +61,12 @@
 #endif
 #endif  // __BIONIC__
 
+#if defined(__NR_mmap2) && !defined(SYS_mmap2)
+#define SYS_mmap2 __NR_mmap2
+#endif
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // Platform specific logic extracted from
@@ -71,6 +76,7 @@
 #if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \
     (defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) ||                   \
     (defined(__PPC__) && !defined(__PPC64__)) ||                             \
+    (defined(__riscv) && __riscv_xlen == 32) ||                              \
     (defined(__s390__) && !defined(__s390x__))
   // On these architectures, implement mmap with mmap2.
   static int pagesize = 0;
@@ -128,6 +134,7 @@
 }
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #else  // !__linux__
@@ -136,6 +143,7 @@
 // actual mmap()/munmap() methods.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
@@ -148,6 +156,7 @@
 }
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // __linux__
diff --git a/absl/base/internal/dynamic_annotations.h b/absl/base/internal/dynamic_annotations.h
new file mode 100644
index 0000000..b23c5ec
--- /dev/null
+++ b/absl/base/internal/dynamic_annotations.h
@@ -0,0 +1,398 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file defines dynamic annotations for use with dynamic analysis tool
+// such as valgrind, PIN, etc.
+//
+// Dynamic annotation is a source code annotation that affects the generated
+// code (that is, the annotation is not a comment). Each such annotation is
+// attached to a particular instruction and/or to a particular object (address)
+// in the program.
+//
+// The annotations that should be used by users are macros in all upper-case
+// (e.g., ANNOTATE_THREAD_NAME).
+//
+// Actual implementation of these macros may differ depending on the dynamic
+// analysis tool being used.
+//
+// This file supports the following configurations:
+// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
+//   In this case, macros expand to functions implemented by Thread Sanitizer,
+//   when building with TSan. When not provided an external implementation,
+//   dynamic_annotations.cc provides no-op implementations.
+//
+// - Static Clang thread-safety warnings enabled.
+//   When building with a Clang compiler that supports thread-safety warnings,
+//   a subset of annotations can be statically-checked at compile-time. We
+//   expand these macros to static-inline functions that can be analyzed for
+//   thread-safety, but afterwards elided when building the final binary.
+//
+// - All annotations are disabled.
+//   If neither Dynamic Annotations nor Clang thread-safety warnings are
+//   enabled, then all annotation-macros expand to empty.
+
+#ifndef ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
+#define ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
+
+#include <stddef.h>
+
+#include "absl/base/config.h"
+
+// -------------------------------------------------------------------------
+// Decide which features are enabled
+
+#ifndef DYNAMIC_ANNOTATIONS_ENABLED
+#define DYNAMIC_ANNOTATIONS_ENABLED 0
+#endif
+
+#if defined(__clang__) && !defined(SWIG)
+#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
+#endif
+
+#if DYNAMIC_ANNOTATIONS_ENABLED != 0
+
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
+
+#else
+
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
+
+// Clang provides limited support for static thread-safety analysis through a
+// feature called Annotalysis. We configure macro-definitions according to
+// whether Annotalysis support is available. When running in opt-mode, GCC
+// will issue a warning, if these attributes are compiled. Only include them
+// when compiling using Clang.
+
+// ANNOTALYSIS_ENABLED == 1 when IGNORE_READ_ATTRIBUTE_ENABLED == 1
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED \
+  defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
+  ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+#endif
+
+// Memory annotations are also made available to LLVM's Memory Sanitizer
+#if defined(ABSL_HAVE_MEMORY_SANITIZER) && !defined(__native_client__)
+#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1
+#endif
+
+#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
+#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0
+#endif
+
+#ifdef __cplusplus
+#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
+#define ABSL_INTERNAL_END_EXTERN_C }  // extern "C"
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
+#define ABSL_INTERNAL_STATIC_INLINE inline
+#else
+#define ABSL_INTERNAL_BEGIN_EXTERN_C  // empty
+#define ABSL_INTERNAL_END_EXTERN_C    // empty
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
+#define ABSL_INTERNAL_STATIC_INLINE static inline
+#endif
+
+// -------------------------------------------------------------------------
+// Define race annotations.
+
+#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
+
+// -------------------------------------------------------------
+// Annotations that suppress errors. It is usually better to express the
+// program's synchronization using the other annotations, but these can be used
+// when all else fails.
+
+// Report that we may have a benign race at `pointer`, with size
+// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
+// point where `pointer` has been allocated, preferably close to the point
+// where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC.
+#define ANNOTATE_BENIGN_RACE(pointer, description)     \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
+  (__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
+
+// Same as ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
+// the memory range [`address`, `address`+`size`).
+#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized)         \
+  (__FILE__, __LINE__, address, size, description)
+
+// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
+// This annotation could be useful if you want to skip expensive race analysis
+// during some period of program execution, e.g. during initialization.
+#define ANNOTATE_ENABLE_RACE_DETECTION(enable)             \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
+  (__FILE__, __LINE__, enable)
+
+// -------------------------------------------------------------
+// Annotations useful for debugging.
+
+// Report the current thread `name` to a race detector.
+#define ANNOTATE_THREAD_NAME(name) \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
+
+// -------------------------------------------------------------
+// Annotations useful when implementing locks. They are not normally needed by
+// modules that merely use locks. The `lock` argument is a pointer to the lock
+// object.
+
+// Report that a lock has been created at address `lock`.
+#define ANNOTATE_RWLOCK_CREATE(lock) \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
+
+// Report that a linker initialized lock has been created at address `lock`.
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+#define ANNOTATE_RWLOCK_CREATE_STATIC(lock)               \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
+  (__FILE__, __LINE__, lock)
+#else
+#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)
+#endif
+
+// Report that the lock at address `lock` is about to be destroyed.
+#define ANNOTATE_RWLOCK_DESTROY(lock) \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
+
+// Report that the lock at address `lock` has been acquired.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w)          \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
+  (__FILE__, __LINE__, lock, is_w)
+
+// Report that the lock at address `lock` is about to be released.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ANNOTATE_RWLOCK_RELEASED(lock, is_w)          \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
+  (__FILE__, __LINE__, lock, is_w)
+
+// Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
+#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description)      \
+  namespace {                                                     \
+  class static_var##_annotator {                                  \
+   public:                                                        \
+    static_var##_annotator() {                                    \
+      ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
+                                 #static_var ": " description);   \
+    }                                                             \
+  };                                                              \
+  static static_var##_annotator the##static_var##_annotator;      \
+  }  // namespace
+
+#else  // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
+
+#define ANNOTATE_RWLOCK_CREATE(lock)                            // empty
+#define ANNOTATE_RWLOCK_CREATE_STATIC(lock)                     // empty
+#define ANNOTATE_RWLOCK_DESTROY(lock)                           // empty
+#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w)                    // empty
+#define ANNOTATE_RWLOCK_RELEASED(lock, is_w)                    // empty
+#define ANNOTATE_BENIGN_RACE(address, description)              // empty
+#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description)  // empty
+#define ANNOTATE_THREAD_NAME(name)                              // empty
+#define ANNOTATE_ENABLE_RACE_DETECTION(enable)                  // empty
+#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description)    // empty
+
+#endif  // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+
+// -------------------------------------------------------------------------
+// Define memory annotations.
+
+#if ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 1
+
+#include <sanitizer/msan_interface.h>
+
+#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+  __msan_unpoison(address, size)
+
+#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+  __msan_allocated_memory(address, size)
+
+#else  // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 0
+
+#if DYNAMIC_ANNOTATIONS_ENABLED == 1
+#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+  do {                                                \
+    (void)(address);                                  \
+    (void)(size);                                     \
+  } while (0)
+#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+  do {                                                  \
+    (void)(address);                                    \
+    (void)(size);                                       \
+  } while (0)
+#else
+#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size)    // empty
+#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size)  // empty
+#endif
+
+#endif  // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
+
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END attributes.
+
+#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
+  __attribute((exclusive_lock_function("*")))
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
+  __attribute((unlock_function("*")))
+
+#else  // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE  // empty
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE    // empty
+
+#endif  // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END annotations.
+
+#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
+
+// Request the analysis tool to ignore all reads in the current thread until
+// ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
+// reads, while still checking other reads and all writes.
+// See also ANNOTATE_UNPROTECTED_READ.
+#define ANNOTATE_IGNORE_READS_BEGIN() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
+
+// Stop ignoring reads.
+#define ANNOTATE_IGNORE_READS_END() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
+
+#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
+
+// When Annotalysis is enabled without Dynamic Annotations, the use of
+// static-inline functions allows the annotations to be read at compile-time,
+// while still letting the compiler elide the functions from the final build.
+//
+// TODO(delesley) -- The exclusive lock here ignores writes as well, but
+// allows IGNORE_READS_AND_WRITES to work properly.
+
+#define ANNOTATE_IGNORE_READS_BEGIN() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)()
+
+#define ANNOTATE_IGNORE_READS_END() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)()
+
+#else
+
+#define ANNOTATE_IGNORE_READS_BEGIN()  // empty
+#define ANNOTATE_IGNORE_READS_END()    // empty
+
+#endif
+
+// -------------------------------------------------------------------------
+// Define IGNORE_WRITES_BEGIN/_END annotations.
+
+#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
+
+// Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
+#define ANNOTATE_IGNORE_WRITES_BEGIN() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
+
+// Stop ignoring writes.
+#define ANNOTATE_IGNORE_WRITES_END() \
+  ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
+
+#else
+
+#define ANNOTATE_IGNORE_WRITES_BEGIN()  // empty
+#define ANNOTATE_IGNORE_WRITES_END()    // empty
+
+#endif
+
+// -------------------------------------------------------------------------
+// Define the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
+// primitive annotations defined above.
+//
+//     Instead of doing
+//        ANNOTATE_IGNORE_READS_BEGIN();
+//        ... = x;
+//        ANNOTATE_IGNORE_READS_END();
+//     one can use
+//        ... = ANNOTATE_UNPROTECTED_READ(x);
+
+#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
+
+// Start ignoring all memory accesses (both reads and writes).
+#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+  do {                                           \
+    ANNOTATE_IGNORE_READS_BEGIN();               \
+    ANNOTATE_IGNORE_WRITES_BEGIN();              \
+  } while (0)
+
+// Stop ignoring both reads and writes.
+#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+  do {                                         \
+    ANNOTATE_IGNORE_WRITES_END();              \
+    ANNOTATE_IGNORE_READS_END();               \
+  } while (0)
+
+#ifdef __cplusplus
+// ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+#define ANNOTATE_UNPROTECTED_READ(x) \
+  absl::base_internal::AnnotateUnprotectedRead(x)
+
+#endif
+
+#else
+
+#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN()  // empty
+#define ANNOTATE_IGNORE_READS_AND_WRITES_END()    // empty
+#define ANNOTATE_UNPROTECTED_READ(x) (x)
+
+#endif
+
+// -------------------------------------------------------------------------
+// Address sanitizer annotations
+
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+// Describe the current state of a contiguous container such as e.g.
+// std::vector or std::string. For more details see
+// sanitizer/common_interface_defs.h, which is provided by the compiler.
+#include <sanitizer/common_interface_defs.h>
+
+#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
+  __sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
+#define ADDRESS_SANITIZER_REDZONE(name)    \
+  struct {                                 \
+    char x[8] __attribute__((aligned(8))); \
+  } name
+
+#else
+
+#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
+#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
+
+#endif  // ABSL_HAVE_ADDRESS_SANITIZER
+
+// -------------------------------------------------------------------------
+// Undefine the macros intended only for this file.
+
+#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_BEGIN_EXTERN_C
+#undef ABSL_INTERNAL_END_EXTERN_C
+#undef ABSL_INTERNAL_STATIC_INLINE
+
+#endif  // ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
diff --git a/absl/base/internal/endian.h b/absl/base/internal/endian.h
index 296e92d..9677530 100644
--- a/absl/base/internal/endian.h
+++ b/absl/base/internal/endian.h
@@ -19,9 +19,6 @@
 // The following guarantees declaration of the byte swap functions
 #ifdef _MSC_VER
 #include <stdlib.h>  // NOLINT(build/include)
-#elif defined(__APPLE__)
-// macOS / Darwin features
-#include <libkern/OSByteOrder.h>
 #elif defined(__FreeBSD__)
 #include <sys/endian.h>
 #elif defined(__GLIBC__)
@@ -34,6 +31,7 @@
 #include "absl/base/port.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // Use compiler byte-swapping intrinsics if they are available.  32-bit
 // and 64-bit versions are available in Clang and GCC as of GCC 4.3.0.
@@ -63,11 +61,6 @@
   return _byteswap_ushort(host_int);
 }
 
-#elif defined(__APPLE__)
-inline uint64_t gbswap_64(uint64_t host_int) { return OSSwapInt16(host_int); }
-inline uint32_t gbswap_32(uint32_t host_int) { return OSSwapInt32(host_int); }
-inline uint16_t gbswap_16(uint16_t host_int) { return OSSwapInt64(host_int); }
-
 #else
 inline uint64_t gbswap_64(uint64_t host_int) {
 #if defined(__GNUC__) && defined(__x86_64__) && !defined(__APPLE__)
@@ -113,7 +106,7 @@
 #endif
 }
 
-#endif  // intrinics available
+#endif  // intrinsics available
 
 #ifdef ABSL_IS_LITTLE_ENDIAN
 
@@ -267,6 +260,7 @@
 
 }  // namespace big_endian
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_ENDIAN_H_
diff --git a/absl/base/internal/endian_test.cc b/absl/base/internal/endian_test.cc
index 98a099e..a1691b1 100644
--- a/absl/base/internal/endian_test.cc
+++ b/absl/base/internal/endian_test.cc
@@ -24,6 +24,7 @@
 #include "absl/base/config.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 const uint64_t kInitialNumber{0x0123456789abcdef};
@@ -53,24 +54,22 @@
 const uint16_t k16ValueBE{0x2301};
 #endif
 
-template<typename T>
-std::vector<T> GenerateAllValuesForType() {
-  std::vector<T> result;
-  T next = std::numeric_limits<T>::min();
-  while (true) {
-    result.push_back(next);
-    if (next == std::numeric_limits<T>::max()) {
-      return result;
-    }
-    ++next;
+std::vector<uint16_t> GenerateAllUint16Values() {
+  std::vector<uint16_t> result;
+  result.reserve(size_t{1} << (sizeof(uint16_t) * 8));
+  for (uint32_t i = std::numeric_limits<uint16_t>::min();
+       i <= std::numeric_limits<uint16_t>::max(); ++i) {
+    result.push_back(static_cast<uint16_t>(i));
   }
+  return result;
 }
 
 template<typename T>
-std::vector<T> GenerateRandomIntegers(size_t numValuesToTest) {
+std::vector<T> GenerateRandomIntegers(size_t num_values_to_test) {
   std::vector<T> result;
+  result.reserve(num_values_to_test);
   std::mt19937_64 rng(kRandomSeed);
-  for (size_t i = 0; i < numValuesToTest; ++i) {
+  for (size_t i = 0; i < num_values_to_test; ++i) {
     result.push_back(rng());
   }
   return result;
@@ -147,7 +146,7 @@
 }
 
 TEST(EndianessTest, Uint16) {
-  GBSwapHelper(GenerateAllValuesForType<uint16_t>(), &Swap16);
+  GBSwapHelper(GenerateAllUint16Values(), &Swap16);
 }
 
 TEST(EndianessTest, Uint32) {
@@ -260,4 +259,5 @@
 }
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/errno_saver.h b/absl/base/internal/errno_saver.h
new file mode 100644
index 0000000..251de51
--- /dev/null
+++ b/absl/base/internal/errno_saver.h
@@ -0,0 +1,43 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
+#define ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
+
+#include <cerrno>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// `ErrnoSaver` captures the value of `errno` upon construction and restores it
+// upon deletion.  It is used in low-level code and must be super fast.  Do not
+// add instrumentation, even in debug modes.
+class ErrnoSaver {
+ public:
+  ErrnoSaver() : saved_errno_(errno) {}
+  ~ErrnoSaver() { errno = saved_errno_; }
+  int operator()() const { return saved_errno_; }
+
+ private:
+  const int saved_errno_;
+};
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
diff --git a/absl/base/internal/errno_saver_test.cc b/absl/base/internal/errno_saver_test.cc
new file mode 100644
index 0000000..e9b742c
--- /dev/null
+++ b/absl/base/internal/errno_saver_test.cc
@@ -0,0 +1,45 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/errno_saver.h"
+
+#include <cerrno>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/strerror.h"
+
+namespace {
+using ::testing::Eq;
+
+struct ErrnoPrinter {
+  int no;
+};
+std::ostream &operator<<(std::ostream &os, ErrnoPrinter ep) {
+  return os << absl::base_internal::StrError(ep.no) << " [" << ep.no << "]";
+}
+bool operator==(ErrnoPrinter one, ErrnoPrinter two) { return one.no == two.no; }
+
+TEST(ErrnoSaverTest, Works) {
+  errno = EDOM;
+  {
+    absl::base_internal::ErrnoSaver errno_saver;
+    EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{EDOM}));
+    errno = ERANGE;
+    EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{ERANGE}));
+    EXPECT_THAT(ErrnoPrinter{errno_saver()}, Eq(ErrnoPrinter{EDOM}));
+  }
+  EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{EDOM}));
+}
+}  // namespace
diff --git a/absl/base/internal/exponential_biased.cc b/absl/base/internal/exponential_biased.cc
new file mode 100644
index 0000000..1b30c06
--- /dev/null
+++ b/absl/base/internal/exponential_biased.cc
@@ -0,0 +1,93 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/exponential_biased.h"
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <atomic>
+#include <cmath>
+#include <limits>
+
+#include "absl/base/attributes.h"
+#include "absl/base/optimization.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// The algorithm generates a random number between 0 and 1 and applies the
+// inverse cumulative distribution function for an exponential. Specifically:
+// Let m be the inverse of the sample period, then the probability
+// distribution function is m*exp(-mx) so the CDF is
+// p = 1 - exp(-mx), so
+// q = 1 - p = exp(-mx)
+// log_e(q) = -mx
+// -log_e(q)/m = x
+// log_2(q) * (-log_e(2) * 1/m) = x
+// In the code, q is actually in the range 1 to 2**26, hence the -26 below
+int64_t ExponentialBiased::GetSkipCount(int64_t mean) {
+  if (ABSL_PREDICT_FALSE(!initialized_)) {
+    Initialize();
+  }
+
+  uint64_t rng = NextRandom(rng_);
+  rng_ = rng;
+
+  // Take the top 26 bits as the random number
+  // (This plus the 1<<58 sampling bound give a max possible step of
+  // 5194297183973780480 bytes.)
+  // The uint32_t cast is to prevent a (hard-to-reproduce) NAN
+  // under piii debug for some binaries.
+  double q = static_cast<uint32_t>(rng >> (kPrngNumBits - 26)) + 1.0;
+  // Put the computed p-value through the CDF of a geometric.
+  double interval = bias_ + (std::log2(q) - 26) * (-std::log(2.0) * mean);
+  // Very large values of interval overflow int64_t. To avoid that, we will
+  // cheat and clamp any huge values to (int64_t max)/2. This is a potential
+  // source of bias, but the mean would need to be such a large value that it's
+  // not likely to come up. For example, with a mean of 1e18, the probability of
+  // hitting this condition is about 1/1000. For a mean of 1e17, standard
+  // calculators claim that this event won't happen.
+  if (interval > static_cast<double>(std::numeric_limits<int64_t>::max() / 2)) {
+    // Assume huge values are bias neutral, retain bias for next call.
+    return std::numeric_limits<int64_t>::max() / 2;
+  }
+  double value = std::round(interval);
+  bias_ = interval - value;
+  return value;
+}
+
+int64_t ExponentialBiased::GetStride(int64_t mean) {
+  return GetSkipCount(mean - 1) + 1;
+}
+
+void ExponentialBiased::Initialize() {
+  // We don't get well distributed numbers from `this` so we call NextRandom() a
+  // bunch to mush the bits around. We use a global_rand to handle the case
+  // where the same thread (by memory address) gets created and destroyed
+  // repeatedly.
+  ABSL_CONST_INIT static std::atomic<uint32_t> global_rand(0);
+  uint64_t r = reinterpret_cast<uint64_t>(this) +
+               global_rand.fetch_add(1, std::memory_order_relaxed);
+  for (int i = 0; i < 20; ++i) {
+    r = NextRandom(r);
+  }
+  rng_ = r;
+  initialized_ = true;
+}
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/base/internal/exponential_biased.h b/absl/base/internal/exponential_biased.h
new file mode 100644
index 0000000..94f79a3
--- /dev/null
+++ b/absl/base/internal/exponential_biased.h
@@ -0,0 +1,130 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
+#define ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
+
+#include <stdint.h>
+
+#include "absl/base/config.h"
+#include "absl/base/macros.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// ExponentialBiased provides a small and fast random number generator for a
+// rounded exponential distribution. This generator manages very little state,
+// and imposes no synchronization overhead. This makes it useful in specialized
+// scenarios requiring minimum overhead, such as stride based periodic sampling.
+//
+// ExponentialBiased provides two closely related functions, GetSkipCount() and
+// GetStride(), both returning a rounded integer defining a number of events
+// required before some event with a given mean probability occurs.
+//
+// The distribution is useful to generate a random wait time or some periodic
+// event with a given mean probability. For example, if an action is supposed to
+// happen on average once every 'N' events, then we can get a random 'stride'
+// counting down how long before the event to happen. For example, if we'd want
+// to sample one in every 1000 'Frobber' calls, our code could look like this:
+//
+//   Frobber::Frobber() {
+//     stride_ = exponential_biased_.GetStride(1000);
+//   }
+//
+//   void Frobber::Frob(int arg) {
+//     if (--stride == 0) {
+//       SampleFrob(arg);
+//       stride_ = exponential_biased_.GetStride(1000);
+//     }
+//     ...
+//   }
+//
+// The rounding of the return value creates a bias, especially for smaller means
+// where the distribution of the fraction is not evenly distributed. We correct
+// this bias by tracking the fraction we rounded up or down on each iteration,
+// effectively tracking the distance between the cumulative value, and the
+// rounded cumulative value. For example, given a mean of 2:
+//
+//   raw = 1.63076, cumulative = 1.63076, rounded = 2, bias = -0.36923
+//   raw = 0.14624, cumulative = 1.77701, rounded = 2, bias =  0.14624
+//   raw = 4.93194, cumulative = 6.70895, rounded = 7, bias = -0.06805
+//   raw = 0.24206, cumulative = 6.95101, rounded = 7, bias =  0.24206
+//   etc...
+//
+// Adjusting with rounding bias is relatively trivial:
+//
+//    double value = bias_ + exponential_distribution(mean)();
+//    double rounded_value = std::round(value);
+//    bias_ = value - rounded_value;
+//    return rounded_value;
+//
+// This class is thread-compatible.
+class ExponentialBiased {
+ public:
+  // The number of bits set by NextRandom.
+  static constexpr int kPrngNumBits = 48;
+
+  // `GetSkipCount()` returns the number of events to skip before some chosen
+  // event happens. For example, randomly tossing a coin, we will on average
+  // throw heads once before we get tails. We can simulate random coin tosses
+  // using GetSkipCount() as:
+  //
+  //   ExponentialBiased eb;
+  //   for (...) {
+  //     int number_of_heads_before_tail = eb.GetSkipCount(1);
+  //     for (int flips = 0; flips < number_of_heads_before_tail; ++flips) {
+  //       printf("head...");
+  //     }
+  //     printf("tail\n");
+  //   }
+  //
+  int64_t GetSkipCount(int64_t mean);
+
+  // GetStride() returns the number of events required for a specific event to
+  // happen. See the class comments for a usage example. `GetStride()` is
+  // equivalent to `GetSkipCount(mean - 1) + 1`. When to use `GetStride()` or
+  // `GetSkipCount()` depends mostly on what best fits the use case.
+  int64_t GetStride(int64_t mean);
+
+  // Computes a random number in the range [0, 1<<(kPrngNumBits+1) - 1]
+  //
+  // This is public to enable testing.
+  static uint64_t NextRandom(uint64_t rnd);
+
+ private:
+  void Initialize();
+
+  uint64_t rng_{0};
+  double bias_{0};
+  bool initialized_{false};
+};
+
+// Returns the next prng value.
+// pRNG is: aX+b mod c with a = 0x5DEECE66D, b =  0xB, c = 1<<48
+// This is the lrand64 generator.
+inline uint64_t ExponentialBiased::NextRandom(uint64_t rnd) {
+  const uint64_t prng_mult = uint64_t{0x5DEECE66D};
+  const uint64_t prng_add = 0xB;
+  const uint64_t prng_mod_power = 48;
+  const uint64_t prng_mod_mask =
+      ~((~static_cast<uint64_t>(0)) << prng_mod_power);
+  return (prng_mult * rnd + prng_add) & prng_mod_mask;
+}
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
diff --git a/absl/base/internal/exponential_biased_test.cc b/absl/base/internal/exponential_biased_test.cc
new file mode 100644
index 0000000..075583c
--- /dev/null
+++ b/absl/base/internal/exponential_biased_test.cc
@@ -0,0 +1,199 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/exponential_biased.h"
+
+#include <stddef.h>
+
+#include <cmath>
+#include <cstdint>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/strings/str_cat.h"
+
+using ::testing::Ge;
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+MATCHER_P2(IsBetween, a, b,
+           absl::StrCat(std::string(negation ? "isn't" : "is"), " between ", a,
+                        " and ", b)) {
+  return a <= arg && arg <= b;
+}
+
+// Tests of the quality of the random numbers generated
+// This uses the Anderson Darling test for uniformity.
+// See "Evaluating the Anderson-Darling Distribution" by Marsaglia
+// for details.
+
+// Short cut version of ADinf(z), z>0 (from Marsaglia)
+// This returns the p-value for Anderson Darling statistic in
+// the limit as n-> infinity. For finite n, apply the error fix below.
+double AndersonDarlingInf(double z) {
+  if (z < 2) {
+    return exp(-1.2337141 / z) / sqrt(z) *
+           (2.00012 +
+            (0.247105 -
+             (0.0649821 - (0.0347962 - (0.011672 - 0.00168691 * z) * z) * z) *
+                 z) *
+                z);
+  }
+  return exp(
+      -exp(1.0776 -
+           (2.30695 -
+            (0.43424 - (0.082433 - (0.008056 - 0.0003146 * z) * z) * z) * z) *
+               z));
+}
+
+// Corrects the approximation error in AndersonDarlingInf for small values of n
+// Add this to AndersonDarlingInf to get a better approximation
+// (from Marsaglia)
+double AndersonDarlingErrFix(int n, double x) {
+  if (x > 0.8) {
+    return (-130.2137 +
+            (745.2337 -
+             (1705.091 - (1950.646 - (1116.360 - 255.7844 * x) * x) * x) * x) *
+                x) /
+           n;
+  }
+  double cutoff = 0.01265 + 0.1757 / n;
+  if (x < cutoff) {
+    double t = x / cutoff;
+    t = sqrt(t) * (1 - t) * (49 * t - 102);
+    return t * (0.0037 / (n * n) + 0.00078 / n + 0.00006) / n;
+  } else {
+    double t = (x - cutoff) / (0.8 - cutoff);
+    t = -0.00022633 +
+        (6.54034 - (14.6538 - (14.458 - (8.259 - 1.91864 * t) * t) * t) * t) *
+            t;
+    return t * (0.04213 + 0.01365 / n) / n;
+  }
+}
+
+// Returns the AndersonDarling p-value given n and the value of the statistic
+double AndersonDarlingPValue(int n, double z) {
+  double ad = AndersonDarlingInf(z);
+  double errfix = AndersonDarlingErrFix(n, ad);
+  return ad + errfix;
+}
+
+double AndersonDarlingStatistic(const std::vector<double>& random_sample) {
+  int n = random_sample.size();
+  double ad_sum = 0;
+  for (int i = 0; i < n; i++) {
+    ad_sum += (2 * i + 1) *
+              std::log(random_sample[i] * (1 - random_sample[n - 1 - i]));
+  }
+  double ad_statistic = -n - 1 / static_cast<double>(n) * ad_sum;
+  return ad_statistic;
+}
+
+// Tests if the array of doubles is uniformly distributed.
+// Returns the p-value of the Anderson Darling Statistic
+// for the given set of sorted random doubles
+// See "Evaluating the Anderson-Darling Distribution" by
+// Marsaglia and Marsaglia for details.
+double AndersonDarlingTest(const std::vector<double>& random_sample) {
+  double ad_statistic = AndersonDarlingStatistic(random_sample);
+  double p = AndersonDarlingPValue(random_sample.size(), ad_statistic);
+  return p;
+}
+
+TEST(ExponentialBiasedTest, CoinTossDemoWithGetSkipCount) {
+  ExponentialBiased eb;
+  for (int runs = 0; runs < 10; ++runs) {
+    for (int flips = eb.GetSkipCount(1); flips > 0; --flips) {
+      printf("head...");
+    }
+    printf("tail\n");
+  }
+  int heads = 0;
+  for (int i = 0; i < 10000000; i += 1 + eb.GetSkipCount(1)) {
+    ++heads;
+  }
+  printf("Heads = %d (%f%%)\n", heads, 100.0 * heads / 10000000);
+}
+
+TEST(ExponentialBiasedTest, SampleDemoWithStride) {
+  ExponentialBiased eb;
+  int stride = eb.GetStride(10);
+  int samples = 0;
+  for (int i = 0; i < 10000000; ++i) {
+    if (--stride == 0) {
+      ++samples;
+      stride = eb.GetStride(10);
+    }
+  }
+  printf("Samples = %d (%f%%)\n", samples, 100.0 * samples / 10000000);
+}
+
+
+// Testing that NextRandom generates uniform random numbers. Applies the
+// Anderson-Darling test for uniformity
+TEST(ExponentialBiasedTest, TestNextRandom) {
+  for (auto n : std::vector<int>({
+           10,  // Check short-range correlation
+           100, 1000,
+           10000  // Make sure there's no systemic error
+       })) {
+    uint64_t x = 1;
+    // This assumes that the prng returns 48 bit numbers
+    uint64_t max_prng_value = static_cast<uint64_t>(1) << 48;
+    // Initialize.
+    for (int i = 1; i <= 20; i++) {
+      x = ExponentialBiased::NextRandom(x);
+    }
+    std::vector<uint64_t> int_random_sample(n);
+    // Collect samples
+    for (int i = 0; i < n; i++) {
+      int_random_sample[i] = x;
+      x = ExponentialBiased::NextRandom(x);
+    }
+    // First sort them...
+    std::sort(int_random_sample.begin(), int_random_sample.end());
+    std::vector<double> random_sample(n);
+    // Convert them to uniform randoms (in the range [0,1])
+    for (int i = 0; i < n; i++) {
+      random_sample[i] =
+          static_cast<double>(int_random_sample[i]) / max_prng_value;
+    }
+    // Now compute the Anderson-Darling statistic
+    double ad_pvalue = AndersonDarlingTest(random_sample);
+    EXPECT_GT(std::min(ad_pvalue, 1 - ad_pvalue), 0.0001)
+        << "prng is not uniform: n = " << n << " p = " << ad_pvalue;
+  }
+}
+
+// The generator needs to be available as a thread_local and as a static
+// variable.
+TEST(ExponentialBiasedTest, InitializationModes) {
+  ABSL_CONST_INIT static ExponentialBiased eb_static;
+  EXPECT_THAT(eb_static.GetSkipCount(2), Ge(0));
+
+#ifdef ABSL_HAVE_THREAD_LOCAL
+  thread_local ExponentialBiased eb_thread;
+  EXPECT_THAT(eb_thread.GetSkipCount(2), Ge(0));
+#endif
+
+  ExponentialBiased eb_stack;
+  EXPECT_THAT(eb_stack.GetSkipCount(2), Ge(0));
+}
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/base/internal/fast_type_id.h b/absl/base/internal/fast_type_id.h
new file mode 100644
index 0000000..3db59e8
--- /dev/null
+++ b/absl/base/internal/fast_type_id.h
@@ -0,0 +1,48 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
+#define ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+template <typename Type>
+struct FastTypeTag {
+  constexpr static char dummy_var = 0;
+};
+
+template <typename Type>
+constexpr char FastTypeTag<Type>::dummy_var;
+
+// FastTypeId<Type>() evaluates at compile/link-time to a unique pointer for the
+// passed-in type. These are meant to be good match for keys into maps or
+// straight up comparisons.
+using FastTypeIdType = const void*;
+
+template <typename Type>
+constexpr inline FastTypeIdType FastTypeId() {
+  return &FastTypeTag<Type>::dummy_var;
+}
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
diff --git a/absl/base/internal/fast_type_id_test.cc b/absl/base/internal/fast_type_id_test.cc
new file mode 100644
index 0000000..16f3c14
--- /dev/null
+++ b/absl/base/internal/fast_type_id_test.cc
@@ -0,0 +1,123 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/fast_type_id.h"
+
+#include <cstdint>
+#include <map>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+namespace {
+namespace bi = absl::base_internal;
+
+// NOLINTNEXTLINE
+#define PRIM_TYPES(A)   \
+  A(bool)               \
+  A(short)              \
+  A(unsigned short)     \
+  A(int)                \
+  A(unsigned int)       \
+  A(long)               \
+  A(unsigned long)      \
+  A(long long)          \
+  A(unsigned long long) \
+  A(float)              \
+  A(double)             \
+  A(long double)
+
+TEST(FastTypeIdTest, PrimitiveTypes) {
+  bi::FastTypeIdType type_ids[] = {
+#define A(T) bi::FastTypeId<T>(),
+    PRIM_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<const T>(),
+    PRIM_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<volatile T>(),
+    PRIM_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<const volatile T>(),
+    PRIM_TYPES(A)
+#undef A
+  };
+  size_t total_type_ids = sizeof(type_ids) / sizeof(bi::FastTypeIdType);
+
+  for (int i = 0; i < total_type_ids; ++i) {
+    EXPECT_EQ(type_ids[i], type_ids[i]);
+    for (int j = 0; j < i; ++j) {
+      EXPECT_NE(type_ids[i], type_ids[j]);
+    }
+  }
+}
+
+#define FIXED_WIDTH_TYPES(A) \
+  A(int8_t)                  \
+  A(uint8_t)                 \
+  A(int16_t)                 \
+  A(uint16_t)                \
+  A(int32_t)                 \
+  A(uint32_t)                \
+  A(int64_t)                 \
+  A(uint64_t)
+
+TEST(FastTypeIdTest, FixedWidthTypes) {
+  bi::FastTypeIdType type_ids[] = {
+#define A(T) bi::FastTypeId<T>(),
+    FIXED_WIDTH_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<const T>(),
+    FIXED_WIDTH_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<volatile T>(),
+    FIXED_WIDTH_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<const volatile T>(),
+    FIXED_WIDTH_TYPES(A)
+#undef A
+  };
+  size_t total_type_ids = sizeof(type_ids) / sizeof(bi::FastTypeIdType);
+
+  for (int i = 0; i < total_type_ids; ++i) {
+    EXPECT_EQ(type_ids[i], type_ids[i]);
+    for (int j = 0; j < i; ++j) {
+      EXPECT_NE(type_ids[i], type_ids[j]);
+    }
+  }
+}
+
+TEST(FastTypeIdTest, AliasTypes) {
+  using int_alias = int;
+  EXPECT_EQ(bi::FastTypeId<int_alias>(), bi::FastTypeId<int>());
+}
+
+TEST(FastTypeIdTest, TemplateSpecializations) {
+  EXPECT_NE(bi::FastTypeId<std::vector<int>>(),
+            bi::FastTypeId<std::vector<long>>());
+
+  EXPECT_NE((bi::FastTypeId<std::map<int, float>>()),
+            (bi::FastTypeId<std::map<int, double>>()));
+}
+
+struct Base {};
+struct Derived : Base {};
+struct PDerived : private Base {};
+
+TEST(FastTypeIdTest, Inheritance) {
+  EXPECT_NE(bi::FastTypeId<Base>(), bi::FastTypeId<Derived>());
+  EXPECT_NE(bi::FastTypeId<Base>(), bi::FastTypeId<PDerived>());
+}
+
+}  // namespace
diff --git a/absl/base/internal/hide_ptr.h b/absl/base/internal/hide_ptr.h
index cf8f408..1dba809 100644
--- a/absl/base/internal/hide_ptr.h
+++ b/absl/base/internal/hide_ptr.h
@@ -17,7 +17,10 @@
 
 #include <cstdint>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // Arbitrary value with high bits set. Xor'ing with it is unlikely
@@ -42,6 +45,7 @@
 }
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_HIDE_PTR_H_
diff --git a/absl/base/internal/identity.h b/absl/base/internal/identity.h
index 086447c..a3154ed 100644
--- a/absl/base/internal/identity.h
+++ b/absl/base/internal/identity.h
@@ -16,7 +16,10 @@
 #ifndef ABSL_BASE_INTERNAL_IDENTITY_H_
 #define ABSL_BASE_INTERNAL_IDENTITY_H_
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace internal {
 
 template <typename T>
@@ -28,6 +31,7 @@
 using identity_t = typename identity<T>::type;
 
 }  // namespace internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_IDENTITY_H_
diff --git a/absl/base/internal/inline_variable_testing.h b/absl/base/internal/inline_variable_testing.h
index 15dc481..3856b9f 100644
--- a/absl/base/internal/inline_variable_testing.h
+++ b/absl/base/internal/inline_variable_testing.h
@@ -18,6 +18,7 @@
 #include "absl/base/internal/inline_variable.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace inline_variable_testing_internal {
 
 struct Foo {
@@ -39,6 +40,7 @@
 const int& get_int_b();
 
 }  // namespace inline_variable_testing_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INLINE_VARIABLE_TESTING_H_
diff --git a/absl/base/internal/invoke.h b/absl/base/internal/invoke.h
index 44f1330..5c71f32 100644
--- a/absl/base/internal/invoke.h
+++ b/absl/base/internal/invoke.h
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
-// absl::base_internal::Invoke(f, args...) is an implementation of
+// absl::base_internal::invoke(f, args...) is an implementation of
 // INVOKE(f, args...) from section [func.require] of the C++ standard.
 //
 // [func.require]
@@ -29,7 +29,7 @@
 //    is not one of the types described in the previous item;
 // 5. f(t1, t2, ..., tN) in all other cases.
 //
-// The implementation is SFINAE-friendly: substitution failure within Invoke()
+// The implementation is SFINAE-friendly: substitution failure within invoke()
 // isn't an error.
 
 #ifndef ABSL_BASE_INTERNAL_INVOKE_H_
@@ -45,6 +45,7 @@
 // top of this file for the API documentation.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // The five classes below each implement one of the clauses from the definition
@@ -169,17 +170,18 @@
 
 // The result type of Invoke<F, Args...>.
 template <typename F, typename... Args>
-using InvokeT = decltype(Invoker<F, Args...>::type::Invoke(
+using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke(
     std::declval<F>(), std::declval<Args>()...));
 
 // Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
 // [func.require] of the C++ standard.
 template <typename F, typename... Args>
-InvokeT<F, Args...> Invoke(F&& f, Args&&... args) {
+invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) {
   return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
                                            std::forward<Args>(args)...);
 }
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_INVOKE_H_
diff --git a/absl/base/internal/low_level_alloc.cc b/absl/base/internal/low_level_alloc.cc
index 64d7aa8..229ab91 100644
--- a/absl/base/internal/low_level_alloc.cc
+++ b/absl/base/internal/low_level_alloc.cc
@@ -63,6 +63,7 @@
 #endif  // __APPLE__
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // A first-fit allocator with amortized logarithmic free() time.
@@ -211,7 +212,7 @@
   // Result of sysconf(_SC_PAGESIZE)
   const size_t pagesize;
   // Lowest power of two >= max(16, sizeof(AllocList))
-  const size_t roundup;
+  const size_t round_up;
   // Smallest allocation block size
   const size_t min_size;
   // PRNG state
@@ -219,16 +220,17 @@
 };
 
 namespace {
-using ArenaStorage = std::aligned_storage<sizeof(LowLevelAlloc::Arena),
-                                          alignof(LowLevelAlloc::Arena)>::type;
-
 // Static storage space for the lazily-constructed, default global arena
 // instances.  We require this space because the whole point of LowLevelAlloc
 // is to avoid relying on malloc/new.
-ArenaStorage default_arena_storage;
-ArenaStorage unhooked_arena_storage;
+alignas(LowLevelAlloc::Arena) unsigned char default_arena_storage[sizeof(
+    LowLevelAlloc::Arena)];
+alignas(LowLevelAlloc::Arena) unsigned char unhooked_arena_storage[sizeof(
+    LowLevelAlloc::Arena)];
 #ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
-ArenaStorage unhooked_async_sig_safe_arena_storage;
+alignas(
+    LowLevelAlloc::Arena) unsigned char unhooked_async_sig_safe_arena_storage
+    [sizeof(LowLevelAlloc::Arena)];
 #endif
 
 // We must use LowLevelCallOnce here to construct the global arenas, rather than
@@ -336,11 +338,11 @@
 
 size_t RoundedUpBlockSize() {
   // Round up block sizes to a power of two close to the header size.
-  size_t roundup = 16;
-  while (roundup < sizeof(AllocList::Header)) {
-    roundup += roundup;
+  size_t round_up = 16;
+  while (round_up < sizeof(AllocList::Header)) {
+    round_up += round_up;
   }
-  return roundup;
+  return round_up;
 }
 
 }  // namespace
@@ -350,8 +352,8 @@
       allocation_count(0),
       flags(flags_value),
       pagesize(GetPageSize()),
-      roundup(RoundedUpBlockSize()),
-      min_size(2 * roundup),
+      round_up(RoundedUpBlockSize()),
+      min_size(2 * round_up),
       random(0) {
   freelist.header.size = 0;
   freelist.header.magic =
@@ -447,7 +449,7 @@
 // that the freelist is in the correct order, that it
 // consists of regions marked "unallocated", and that no two regions
 // are adjacent in memory (they should have been coalesced).
-// L < arena->mu
+// L >= arena->mu
 static AllocList *Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena) {
   ABSL_RAW_CHECK(i < prev->levels, "too few levels in Next()");
   AllocList *next = prev->next[i];
@@ -508,8 +510,6 @@
   if (v != nullptr) {
     AllocList *f = reinterpret_cast<AllocList *>(
                         reinterpret_cast<char *>(v) - sizeof (f->header));
-    ABSL_RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header),
-                   "bad magic number in Free()");
     LowLevelAlloc::Arena *arena = f->header.arena;
     ArenaLock section(arena);
     AddToFreelist(v, arena);
@@ -528,7 +528,7 @@
     ArenaLock section(arena);
     // round up with header
     size_t req_rnd = RoundUp(CheckedAdd(request, sizeof (s->header)),
-                             arena->roundup);
+                             arena->round_up);
     for (;;) {      // loop until we find a suitable region
       // find the minimum levels that a block of this size must have
       int i = LLA_SkiplistLevels(req_rnd, arena->min_size, nullptr) - 1;
@@ -598,7 +598,7 @@
     section.Leave();
     result = &s->levels;
   }
-  ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request);
+  ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request);
   return result;
 }
 
@@ -614,6 +614,7 @@
 }
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_LOW_LEVEL_ALLOC_MISSING
diff --git a/absl/base/internal/low_level_alloc.h b/absl/base/internal/low_level_alloc.h
index c98cdb3..db91951 100644
--- a/absl/base/internal/low_level_alloc.h
+++ b/absl/base/internal/low_level_alloc.h
@@ -55,6 +55,7 @@
 #include "absl/base/port.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 class LowLevelAlloc {
@@ -119,6 +120,7 @@
 };
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_
diff --git a/absl/base/internal/low_level_alloc_test.cc b/absl/base/internal/low_level_alloc_test.cc
index 34a080c..31abb88 100644
--- a/absl/base/internal/low_level_alloc_test.cc
+++ b/absl/base/internal/low_level_alloc_test.cc
@@ -21,7 +21,14 @@
 #include <unordered_map>
 #include <utility>
 
+#ifdef __EMSCRIPTEN__
+#include <emscripten.h>
+#endif
+
+#include "absl/container/node_hash_map.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 namespace {
 
@@ -74,7 +81,7 @@
 // allocations and deallocations are reported via the MallocHook
 // interface.
 static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
-  typedef std::unordered_map<int, BlockDesc> AllocMap;
+  typedef absl::node_hash_map<int, BlockDesc> AllocMap;
   AllocMap allocated;
   AllocMap::iterator it;
   BlockDesc block_desc;
@@ -149,10 +156,26 @@
 
 }  // namespace
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 int main(int argc, char *argv[]) {
   // The actual test runs in the global constructor of `before_main`.
   printf("PASS\n");
+#ifdef __EMSCRIPTEN__
+  // clang-format off
+// This is JS here. Don't try to format it.
+    MAIN_THREAD_EM_ASM({
+      if (ENVIRONMENT_IS_WEB) {
+        if (typeof TEST_FINISH === 'function') {
+          TEST_FINISH($0);
+        } else {
+          console.error('Attempted to exit with status ' + $0);
+          console.error('But TEST_FINSIHED is not a function.');
+        }
+      }
+    }, 0);
+// clang-format on
+#endif
   return 0;
 }
diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h
index 0fcc8d3..9baccc0 100644
--- a/absl/base/internal/low_level_scheduling.h
+++ b/absl/base/internal/low_level_scheduling.h
@@ -18,6 +18,7 @@
 #ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
 #define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
 
+#include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/scheduling_mode.h"
 #include "absl/base/macros.h"
 
@@ -28,6 +29,14 @@
 extern "C" void __google_enable_rescheduling(bool disable_result);
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
+class CondVar;
+class Mutex;
+
+namespace synchronization_internal {
+int MutexDelay(int32_t c, int mode);
+}  // namespace synchronization_internal
+
 namespace base_internal {
 
 class SchedulingHelper;  // To allow use of SchedulingGuard.
@@ -52,6 +61,8 @@
  public:
   // Returns true iff the calling thread may be cooperatively rescheduled.
   static bool ReschedulingIsAllowed();
+  SchedulingGuard(const SchedulingGuard&) = delete;
+  SchedulingGuard& operator=(const SchedulingGuard&) = delete;
 
  private:
   // Disable cooperative rescheduling of the calling thread.  It may still
@@ -75,12 +86,23 @@
     bool disabled;
   };
 
-  // Access to SchedulingGuard is explicitly white-listed.
+  // A scoped helper to enable rescheduling temporarily.
+  // REQUIRES: destructor must run in same thread as constructor.
+  class ScopedEnable {
+   public:
+    ScopedEnable();
+    ~ScopedEnable();
+
+   private:
+    int scheduling_disabled_depth_;
+  };
+
+  // Access to SchedulingGuard is explicitly permitted.
+  friend class absl::CondVar;
+  friend class absl::Mutex;
   friend class SchedulingHelper;
   friend class SpinLock;
-
-  SchedulingGuard(const SchedulingGuard&) = delete;
-  SchedulingGuard& operator=(const SchedulingGuard&) = delete;
+  friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode);
 };
 
 //------------------------------------------------------------------------------
@@ -99,7 +121,14 @@
   return;
 }
 
+inline SchedulingGuard::ScopedEnable::ScopedEnable()
+    : scheduling_disabled_depth_(0) {}
+inline SchedulingGuard::ScopedEnable::~ScopedEnable() {
+  ABSL_RAW_CHECK(scheduling_disabled_depth_ == 0, "disable unused warning");
+}
+
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
diff --git a/absl/base/internal/periodic_sampler.cc b/absl/base/internal/periodic_sampler.cc
new file mode 100644
index 0000000..520dabb
--- /dev/null
+++ b/absl/base/internal/periodic_sampler.cc
@@ -0,0 +1,53 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/periodic_sampler.h"
+
+#include <atomic>
+
+#include "absl/base/internal/exponential_biased.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+int64_t PeriodicSamplerBase::GetExponentialBiased(int period) noexcept {
+  return rng_.GetStride(period);
+}
+
+bool PeriodicSamplerBase::SubtleConfirmSample() noexcept {
+  int current_period = period();
+
+  // Deal with period case 0 (always off) and 1 (always on)
+  if (ABSL_PREDICT_FALSE(current_period < 2)) {
+    stride_ = 0;
+    return current_period == 1;
+  }
+
+  // Check if this is the first call to Sample()
+  if (ABSL_PREDICT_FALSE(stride_ == 1)) {
+    stride_ = static_cast<uint64_t>(-GetExponentialBiased(current_period));
+    if (static_cast<int64_t>(stride_) < -1) {
+      ++stride_;
+      return false;
+    }
+  }
+
+  stride_ = static_cast<uint64_t>(-GetExponentialBiased(current_period));
+  return true;
+}
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/base/internal/periodic_sampler.h b/absl/base/internal/periodic_sampler.h
new file mode 100644
index 0000000..f8a8679
--- /dev/null
+++ b/absl/base/internal/periodic_sampler.h
@@ -0,0 +1,211 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_BASE_INTERNAL_PERIODIC_SAMPLER_H_
+#define ABSL_BASE_INTERNAL_PERIODIC_SAMPLER_H_
+
+#include <stdint.h>
+
+#include <atomic>
+
+#include "absl/base/internal/exponential_biased.h"
+#include "absl/base/optimization.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// PeriodicSamplerBase provides the basic period sampler implementation.
+//
+// This is the base class for the templated PeriodicSampler class, which holds
+// a global std::atomic value identified by a user defined tag, such that
+// each specific PeriodSampler implementation holds its own global period.
+//
+// PeriodicSamplerBase is thread-compatible except where stated otherwise.
+class PeriodicSamplerBase {
+ public:
+  // PeriodicSamplerBase is trivial / copyable / movable / destructible.
+  PeriodicSamplerBase() = default;
+  PeriodicSamplerBase(PeriodicSamplerBase&&) = default;
+  PeriodicSamplerBase(const PeriodicSamplerBase&) = default;
+
+  // Returns true roughly once every `period` calls. This is established by a
+  // randomly picked `stride` that is counted down on each call to `Sample`.
+  // This stride is picked such that the probability of `Sample()` returning
+  // true is 1 in `period`.
+  inline bool Sample() noexcept;
+
+  // The below methods are intended for optimized use cases where the
+  // size of the inlined fast path code is highly important. Applications
+  // should use the `Sample()` method unless they have proof that their
+  // specific use case requires the optimizations offered by these methods.
+  //
+  // An example of such a use case is SwissTable sampling. All sampling checks
+  // are in inlined SwissTable methods, and the number of call sites is huge.
+  // In this case, the inlined code size added to each translation unit calling
+  // SwissTable methods is non-trivial.
+  //
+  // The `SubtleMaybeSample()` function spuriously returns true even if the
+  // function should not be sampled, applications MUST match each call to
+  // 'SubtleMaybeSample()' returning true with a `SubtleConfirmSample()` call,
+  // and use the result of the latter as the sampling decision.
+  // In other words: the code should logically be equivalent to:
+  //
+  //    if (SubtleMaybeSample() && SubtleConfirmSample()) {
+  //      // Sample this call
+  //    }
+  //
+  // In the 'inline-size' optimized case, the `SubtleConfirmSample()` call can
+  // be placed out of line, for example, the typical use case looks as follows:
+  //
+  //   // --- frobber.h -----------
+  //   void FrobberSampled();
+  //
+  //   inline void FrobberImpl() {
+  //     // ...
+  //   }
+  //
+  //   inline void Frobber() {
+  //     if (ABSL_PREDICT_FALSE(sampler.SubtleMaybeSample())) {
+  //       FrobberSampled();
+  //     } else {
+  //       FrobberImpl();
+  //     }
+  //   }
+  //
+  //   // --- frobber.cc -----------
+  //   void FrobberSampled() {
+  //     if (!sampler.SubtleConfirmSample())) {
+  //       // Spurious false positive
+  //       FrobberImpl();
+  //       return;
+  //     }
+  //
+  //     // Sampled execution
+  //     // ...
+  //   }
+  inline bool SubtleMaybeSample() noexcept;
+  bool SubtleConfirmSample() noexcept;
+
+ protected:
+  // We explicitly don't use a virtual destructor as this class is never
+  // virtually destroyed, and it keeps the class trivial, which avoids TLS
+  // prologue and epilogue code for our TLS instances.
+  ~PeriodicSamplerBase() = default;
+
+  // Returns the next stride for our sampler.
+  // This function is virtual for testing purposes only.
+  virtual int64_t GetExponentialBiased(int period) noexcept;
+
+ private:
+  // Returns the current period of this sampler. Thread-safe.
+  virtual int period() const noexcept = 0;
+
+  // Keep and decrement stride_ as an unsigned integer, but compare the value
+  // to zero casted as a signed int. clang and msvc do not create optimum code
+  // if we use signed for the combined decrement and sign comparison.
+  //
+  // Below 3 alternative options, all compiles generate the best code
+  // using the unsigned increment <---> signed int comparison option.
+  //
+  // Option 1:
+  //   int64_t stride_;
+  //   if (ABSL_PREDICT_TRUE(++stride_ < 0)) { ... }
+  //
+  //   GCC   x64 (OK) : https://gcc.godbolt.org/z/R5MzzA
+  //   GCC   ppc (OK) : https://gcc.godbolt.org/z/z7NZAt
+  //   Clang x64 (BAD): https://gcc.godbolt.org/z/t4gPsd
+  //   ICC   x64 (OK) : https://gcc.godbolt.org/z/rE6s8W
+  //   MSVC  x64 (OK) : https://gcc.godbolt.org/z/ARMXqS
+  //
+  // Option 2:
+  //   int64_t stride_ = 0;
+  //   if (ABSL_PREDICT_TRUE(--stride_ >= 0)) { ... }
+  //
+  //   GCC   x64 (OK) : https://gcc.godbolt.org/z/jSQxYK
+  //   GCC   ppc (OK) : https://gcc.godbolt.org/z/VJdYaA
+  //   Clang x64 (BAD): https://gcc.godbolt.org/z/Xm4NjX
+  //   ICC   x64 (OK) : https://gcc.godbolt.org/z/4snaFd
+  //   MSVC  x64 (BAD): https://gcc.godbolt.org/z/BgnEKE
+  //
+  // Option 3:
+  //   uint64_t stride_;
+  //   if (ABSL_PREDICT_TRUE(static_cast<int64_t>(++stride_) < 0)) { ... }
+  //
+  //   GCC   x64 (OK) : https://gcc.godbolt.org/z/bFbfPy
+  //   GCC   ppc (OK) : https://gcc.godbolt.org/z/S9KkUE
+  //   Clang x64 (OK) : https://gcc.godbolt.org/z/UYzRb4
+  //   ICC   x64 (OK) : https://gcc.godbolt.org/z/ptTNfD
+  //   MSVC  x64 (OK) : https://gcc.godbolt.org/z/76j4-5
+  uint64_t stride_ = 0;
+  ExponentialBiased rng_;
+};
+
+inline bool PeriodicSamplerBase::SubtleMaybeSample() noexcept {
+  // See comments on `stride_` for the unsigned increment / signed compare.
+  if (ABSL_PREDICT_TRUE(static_cast<int64_t>(++stride_) < 0)) {
+    return false;
+  }
+  return true;
+}
+
+inline bool PeriodicSamplerBase::Sample() noexcept {
+  return ABSL_PREDICT_FALSE(SubtleMaybeSample()) ? SubtleConfirmSample()
+                                                 : false;
+}
+
+// PeriodicSampler is a concreted periodic sampler implementation.
+// The user provided Tag identifies the implementation, and is required to
+// isolate the global state of this instance from other instances.
+//
+// Typical use case:
+//
+//   struct HashTablezTag {};
+//   thread_local PeriodicSampler sampler;
+//
+//   void HashTableSamplingLogic(...) {
+//     if (sampler.Sample()) {
+//       HashTableSlowSamplePath(...);
+//     }
+//   }
+//
+template <typename Tag, int default_period = 0>
+class PeriodicSampler final : public PeriodicSamplerBase {
+ public:
+  ~PeriodicSampler() = default;
+
+  int period() const noexcept final {
+    return period_.load(std::memory_order_relaxed);
+  }
+
+  // Sets the global period for this sampler. Thread-safe.
+  // Setting a period of 0 disables the sampler, i.e., every call to Sample()
+  // will return false. Setting a period of 1 puts the sampler in 'always on'
+  // mode, i.e., every call to Sample() returns true.
+  static void SetGlobalPeriod(int period) {
+    period_.store(period, std::memory_order_relaxed);
+  }
+
+ private:
+  static std::atomic<int> period_;
+};
+
+template <typename Tag, int default_period>
+std::atomic<int> PeriodicSampler<Tag, default_period>::period_(default_period);
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_BASE_INTERNAL_PERIODIC_SAMPLER_H_
diff --git a/absl/base/internal/periodic_sampler_benchmark.cc b/absl/base/internal/periodic_sampler_benchmark.cc
new file mode 100644
index 0000000..5ad469c
--- /dev/null
+++ b/absl/base/internal/periodic_sampler_benchmark.cc
@@ -0,0 +1,79 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "benchmark/benchmark.h"
+#include "absl/base/internal/periodic_sampler.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+namespace {
+
+template <typename Sampler>
+void BM_Sample(Sampler* sampler, benchmark::State& state) {
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(sampler);
+    benchmark::DoNotOptimize(sampler->Sample());
+  }
+}
+
+template <typename Sampler>
+void BM_SampleMinunumInlined(Sampler* sampler, benchmark::State& state) {
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(sampler);
+    if (ABSL_PREDICT_FALSE(sampler->SubtleMaybeSample())) {
+      benchmark::DoNotOptimize(sampler->SubtleConfirmSample());
+    }
+  }
+}
+
+void BM_PeriodicSampler_TinySample(benchmark::State& state) {
+  struct Tag {};
+  PeriodicSampler<Tag, 10> sampler;
+  BM_Sample(&sampler, state);
+}
+BENCHMARK(BM_PeriodicSampler_TinySample);
+
+void BM_PeriodicSampler_ShortSample(benchmark::State& state) {
+  struct Tag {};
+  PeriodicSampler<Tag, 1024> sampler;
+  BM_Sample(&sampler, state);
+}
+BENCHMARK(BM_PeriodicSampler_ShortSample);
+
+void BM_PeriodicSampler_LongSample(benchmark::State& state) {
+  struct Tag {};
+  PeriodicSampler<Tag, 1024 * 1024> sampler;
+  BM_Sample(&sampler, state);
+}
+BENCHMARK(BM_PeriodicSampler_LongSample);
+
+void BM_PeriodicSampler_LongSampleMinunumInlined(benchmark::State& state) {
+  struct Tag {};
+  PeriodicSampler<Tag, 1024 * 1024> sampler;
+  BM_SampleMinunumInlined(&sampler, state);
+}
+BENCHMARK(BM_PeriodicSampler_LongSampleMinunumInlined);
+
+void BM_PeriodicSampler_Disabled(benchmark::State& state) {
+  struct Tag {};
+  PeriodicSampler<Tag, 0> sampler;
+  BM_Sample(&sampler, state);
+}
+BENCHMARK(BM_PeriodicSampler_Disabled);
+
+}  // namespace
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/base/internal/periodic_sampler_test.cc b/absl/base/internal/periodic_sampler_test.cc
new file mode 100644
index 0000000..3b301e3
--- /dev/null
+++ b/absl/base/internal/periodic_sampler_test.cc
@@ -0,0 +1,177 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/periodic_sampler.h"
+
+#include <thread>  // NOLINT(build/c++11)
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/macros.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+namespace {
+
+using testing::Eq;
+using testing::Return;
+using testing::StrictMock;
+
+class MockPeriodicSampler : public PeriodicSamplerBase {
+ public:
+  virtual ~MockPeriodicSampler() = default;
+
+  MOCK_METHOD(int, period, (), (const, noexcept));
+  MOCK_METHOD(int64_t, GetExponentialBiased, (int), (noexcept));
+};
+
+TEST(PeriodicSamplerBaseTest, Sample) {
+  StrictMock<MockPeriodicSampler> sampler;
+
+  EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(16));
+  EXPECT_CALL(sampler, GetExponentialBiased(16))
+      .WillOnce(Return(2))
+      .WillOnce(Return(3))
+      .WillOnce(Return(4));
+
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_TRUE(sampler.Sample());
+
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_TRUE(sampler.Sample());
+
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_FALSE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerBaseTest, ImmediatelySample) {
+  StrictMock<MockPeriodicSampler> sampler;
+
+  EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(16));
+  EXPECT_CALL(sampler, GetExponentialBiased(16))
+      .WillOnce(Return(1))
+      .WillOnce(Return(2))
+      .WillOnce(Return(3));
+
+  EXPECT_TRUE(sampler.Sample());
+
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_TRUE(sampler.Sample());
+
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_FALSE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerBaseTest, Disabled) {
+  StrictMock<MockPeriodicSampler> sampler;
+
+  EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(0));
+
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_FALSE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerBaseTest, AlwaysOn) {
+  StrictMock<MockPeriodicSampler> sampler;
+
+  EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(1));
+
+  EXPECT_TRUE(sampler.Sample());
+  EXPECT_TRUE(sampler.Sample());
+  EXPECT_TRUE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerBaseTest, Disable) {
+  StrictMock<MockPeriodicSampler> sampler;
+
+  EXPECT_CALL(sampler, period()).WillOnce(Return(16));
+  EXPECT_CALL(sampler, GetExponentialBiased(16)).WillOnce(Return(3));
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_FALSE(sampler.Sample());
+
+  EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(0));
+
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_FALSE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerBaseTest, Enable) {
+  StrictMock<MockPeriodicSampler> sampler;
+
+  EXPECT_CALL(sampler, period()).WillOnce(Return(0));
+  EXPECT_FALSE(sampler.Sample());
+
+  EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(16));
+  EXPECT_CALL(sampler, GetExponentialBiased(16))
+      .Times(2)
+      .WillRepeatedly(Return(3));
+
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_TRUE(sampler.Sample());
+
+  EXPECT_FALSE(sampler.Sample());
+  EXPECT_FALSE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerTest, ConstructConstInit) {
+  struct Tag {};
+  ABSL_CONST_INIT static PeriodicSampler<Tag> sampler;
+  (void)sampler;
+}
+
+TEST(PeriodicSamplerTest, DefaultPeriod0) {
+  struct Tag {};
+  PeriodicSampler<Tag> sampler;
+  EXPECT_THAT(sampler.period(), Eq(0));
+}
+
+TEST(PeriodicSamplerTest, DefaultPeriod) {
+  struct Tag {};
+  PeriodicSampler<Tag, 100> sampler;
+  EXPECT_THAT(sampler.period(), Eq(100));
+}
+
+TEST(PeriodicSamplerTest, SetGlobalPeriod) {
+  struct Tag1 {};
+  struct Tag2 {};
+  PeriodicSampler<Tag1, 25> sampler1;
+  PeriodicSampler<Tag2, 50> sampler2;
+
+  EXPECT_THAT(sampler1.period(), Eq(25));
+  EXPECT_THAT(sampler2.period(), Eq(50));
+
+  std::thread thread([] {
+    PeriodicSampler<Tag1, 25> sampler1;
+    PeriodicSampler<Tag2, 50> sampler2;
+    EXPECT_THAT(sampler1.period(), Eq(25));
+    EXPECT_THAT(sampler2.period(), Eq(50));
+    sampler1.SetGlobalPeriod(10);
+    sampler2.SetGlobalPeriod(20);
+  });
+  thread.join();
+
+  EXPECT_THAT(sampler1.period(), Eq(10));
+  EXPECT_THAT(sampler2.period(), Eq(20));
+}
+
+}  // namespace
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc
index 878fe6c..074e026 100644
--- a/absl/base/internal/raw_logging.cc
+++ b/absl/base/internal/raw_logging.cc
@@ -37,9 +37,9 @@
 // this, consider moving both to config.h instead.
 #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
     defined(__Fuchsia__) || defined(__native_client__) || \
-    defined(__EMSCRIPTEN__)
-#include <unistd.h>
+    defined(__EMSCRIPTEN__) || defined(__ASYLO__)
 
+#include <unistd.h>
 
 #define ABSL_HAVE_POSIX_WRITE 1
 #define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
@@ -67,26 +67,32 @@
 #undef ABSL_HAVE_RAW_IO
 #endif
 
-// TODO(gfalcon): We want raw-logging to work on as many platforms as possible.
-// Explicitly #error out when not ABSL_LOW_LEVEL_WRITE_SUPPORTED, except for a
-// whitelisted set of platforms for which we expect not to be able to raw log.
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace raw_logging_internal {
+namespace {
 
-ABSL_CONST_INIT static absl::base_internal::AtomicHook<
-    absl::raw_logging_internal::LogPrefixHook> log_prefix_hook;
-ABSL_CONST_INIT static absl::base_internal::AtomicHook<
-    absl::raw_logging_internal::AbortHook> abort_hook;
+// TODO(gfalcon): We want raw-logging to work on as many platforms as possible.
+// Explicitly `#error` out when not `ABSL_LOW_LEVEL_WRITE_SUPPORTED`, except for
+// a selected set of platforms for which we expect not to be able to raw log.
+
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+    absl::base_internal::AtomicHook<LogPrefixHook>
+        log_prefix_hook;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+    absl::base_internal::AtomicHook<AbortHook>
+        abort_hook;
 
 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
-static const char kTruncated[] = " ... (message truncated)\n";
+constexpr char kTruncated[] = " ... (message truncated)\n";
 
 // sprintf the format to the buffer, adjusting *buf and *size to reflect the
 // consumed bytes, and return whether the message fit without truncation.  If
 // truncation occurred, if possible leave room in the buffer for the message
 // kTruncated[].
-inline static bool VADoRawLog(char** buf, int* size, const char* format,
-                              va_list ap) ABSL_PRINTF_ATTRIBUTE(3, 0);
-inline static bool VADoRawLog(char** buf, int* size,
-                              const char* format, va_list ap) {
+bool VADoRawLog(char** buf, int* size, const char* format, va_list ap)
+    ABSL_PRINTF_ATTRIBUTE(3, 0);
+bool VADoRawLog(char** buf, int* size, const char* format, va_list ap) {
   int n = vsnprintf(*buf, *size, format, ap);
   bool result = true;
   if (n < 0 || n > *size) {
@@ -94,7 +100,7 @@
     if (static_cast<size_t>(*size) > sizeof(kTruncated)) {
       n = *size - sizeof(kTruncated);  // room for truncation message
     } else {
-      n = 0;                           // no room for truncation message
+      n = 0;  // no room for truncation message
     }
   }
   *size -= n;
@@ -103,9 +109,7 @@
 }
 #endif  // ABSL_LOW_LEVEL_WRITE_SUPPORTED
 
-static constexpr int kLogBufSize = 3000;
-
-namespace {
+constexpr int kLogBufSize = 3000;
 
 // CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
 // that invoke malloc() and getenv() that might acquire some locks.
@@ -164,7 +168,7 @@
     } else {
       DoRawLog(&buf, &size, "%s", kTruncated);
     }
-    absl::raw_logging_internal::SafeWriteToStderr(buffer, strlen(buffer));
+    SafeWriteToStderr(buffer, strlen(buffer));
   }
 #else
   static_cast<void>(format);
@@ -179,10 +183,18 @@
   }
 }
 
+// Non-formatting version of RawLog().
+//
+// TODO(gfalcon): When string_view no longer depends on base, change this
+// interface to take its message as a string_view instead.
+void DefaultInternalLog(absl::LogSeverity severity, const char* file, int line,
+                        const std::string& message) {
+  RawLog(severity, file, line, "%.*s", static_cast<int>(message.size()),
+         message.data());
+}
+
 }  // namespace
 
-namespace absl {
-namespace raw_logging_internal {
 void SafeWriteToStderr(const char *s, size_t len) {
 #if defined(ABSL_HAVE_SYSCALL_WRITE)
   syscall(SYS_write, STDERR_FILENO, s, len);
@@ -198,8 +210,6 @@
 }
 
 void RawLog(absl::LogSeverity severity, const char* file, int line,
-            const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);
-void RawLog(absl::LogSeverity severity, const char* file, int line,
             const char* format, ...) {
   va_list ap;
   va_start(ap, format);
@@ -207,15 +217,6 @@
   va_end(ap);
 }
 
-// Non-formatting version of RawLog().
-//
-// TODO(gfalcon): When string_view no longer depends on base, change this
-// interface to take its message as a string_view instead.
-static void DefaultInternalLog(absl::LogSeverity severity, const char* file,
-                               int line, const std::string& message) {
-  RawLog(severity, file, line, "%s", message.c_str());
-}
-
 bool RawLoggingFullySupported() {
 #ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
   return true;
@@ -224,12 +225,18 @@
 #endif  // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
 }
 
-ABSL_CONST_INIT absl::base_internal::AtomicHook<InternalLogFunction>
-    internal_log_function(DefaultInternalLog);
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL
+    absl::base_internal::AtomicHook<InternalLogFunction>
+        internal_log_function(DefaultInternalLog);
+
+void RegisterLogPrefixHook(LogPrefixHook func) { log_prefix_hook.Store(func); }
+
+void RegisterAbortHook(AbortHook func) { abort_hook.Store(func); }
 
 void RegisterInternalLogFunction(InternalLogFunction func) {
   internal_log_function.Store(func);
 }
 
 }  // namespace raw_logging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h
index 6a4c093..2bf7aab 100644
--- a/absl/base/internal/raw_logging.h
+++ b/absl/base/internal/raw_logging.h
@@ -22,9 +22,11 @@
 #include <string>
 
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/atomic_hook.h"
 #include "absl/base/log_severity.h"
 #include "absl/base/macros.h"
+#include "absl/base/optimization.h"
 #include "absl/base/port.h"
 
 // This is similar to LOG(severity) << format..., but
@@ -70,14 +72,14 @@
 //
 // The API is a subset of the above: each macro only takes two arguments.  Use
 // StrCat if you need to build a richer message.
-#define ABSL_INTERNAL_LOG(severity, message)                          \
-  do {                                                                \
-    constexpr const char* absl_raw_logging_internal_basename =        \
-        ::absl::raw_logging_internal::Basename(__FILE__,              \
-                                               sizeof(__FILE__) - 1); \
-    ::absl::raw_logging_internal::internal_log_function(              \
-        ABSL_RAW_LOGGING_INTERNAL_##severity,                         \
-        absl_raw_logging_internal_basename, __LINE__, message);       \
+#define ABSL_INTERNAL_LOG(severity, message)                                 \
+  do {                                                                       \
+    constexpr const char* absl_raw_logging_internal_filename = __FILE__;     \
+    ::absl::raw_logging_internal::internal_log_function(                     \
+        ABSL_RAW_LOGGING_INTERNAL_##severity,                                \
+        absl_raw_logging_internal_filename, __LINE__, message);              \
+    if (ABSL_RAW_LOGGING_INTERNAL_##severity == ::absl::LogSeverity::kFatal) \
+      ABSL_INTERNAL_UNREACHABLE;                                             \
   } while (0)
 
 #define ABSL_INTERNAL_CHECK(condition, message)                    \
@@ -97,6 +99,7 @@
   ::absl::NormalizeLogSeverity(severity)
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace raw_logging_internal {
 
 // Helper function to implement ABSL_RAW_LOG
@@ -157,7 +160,7 @@
 //
 // 'file' and 'line' are the file and line number where the ABSL_RAW_LOG macro
 // was located.
-// The null-terminated logged message lives in the buffer between 'buf_start'
+// The NUL-terminated logged message lives in the buffer between 'buf_start'
 // and 'buf_end'.  'prefix_end' points to the first non-prefix character of the
 // buffer (as written by the LogPrefixHook.)
 using AbortHook = void (*)(const char* file, int line, const char* buf_start,
@@ -171,11 +174,22 @@
                                      const char* file, int line,
                                      const std::string& message);
 
-extern base_internal::AtomicHook<InternalLogFunction> internal_log_function;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL extern base_internal::AtomicHook<
+    InternalLogFunction>
+    internal_log_function;
 
+// Registers hooks of the above types.  Only a single hook of each type may be
+// registered.  It is an error to call these functions multiple times with
+// different input arguments.
+//
+// These functions are safe to call at any point during initialization; they do
+// not block or malloc, and are async-signal safe.
+void RegisterLogPrefixHook(LogPrefixHook func);
+void RegisterAbortHook(AbortHook func);
 void RegisterInternalLogFunction(InternalLogFunction func);
 
 }  // namespace raw_logging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_RAW_LOGGING_H_
diff --git a/absl/base/internal/scheduling_mode.h b/absl/base/internal/scheduling_mode.h
index d5b4b7f..8be5ab6 100644
--- a/absl/base/internal/scheduling_mode.h
+++ b/absl/base/internal/scheduling_mode.h
@@ -18,7 +18,10 @@
 #ifndef ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_
 #define ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // Used to describe how a thread may be scheduled.  Typically associated with
@@ -49,6 +52,7 @@
 };
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_
diff --git a/absl/base/internal/scoped_set_env.cc b/absl/base/internal/scoped_set_env.cc
index 3ac3f68..8a934cb 100644
--- a/absl/base/internal/scoped_set_env.cc
+++ b/absl/base/internal/scoped_set_env.cc
@@ -23,6 +23,7 @@
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 namespace {
@@ -76,4 +77,5 @@
 }
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/scoped_set_env.h b/absl/base/internal/scoped_set_env.h
index 855b22f..19ec7b5 100644
--- a/absl/base/internal/scoped_set_env.h
+++ b/absl/base/internal/scoped_set_env.h
@@ -19,7 +19,10 @@
 
 #include <string>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 class ScopedSetEnv {
@@ -36,6 +39,7 @@
 };
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_
diff --git a/absl/base/internal/spinlock.cc b/absl/base/internal/spinlock.cc
index 7354438..a7d44f3 100644
--- a/absl/base/internal/spinlock.cc
+++ b/absl/base/internal/spinlock.cc
@@ -54,10 +54,11 @@
 //          holder to acquire the lock.  There may be outstanding waiter(s).
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
-ABSL_CONST_INIT static base_internal::AtomicHook<void (*)(const void *lock,
-                                                          int64_t wait_cycles)>
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static base_internal::AtomicHook<void (*)(
+    const void *lock, int64_t wait_cycles)>
     submit_profile_data;
 
 void RegisterSpinLockProfiler(void (*fn)(const void *contendedlock,
@@ -65,35 +66,19 @@
   submit_profile_data.Store(fn);
 }
 
+// Static member variable definitions.
+constexpr uint32_t SpinLock::kSpinLockHeld;
+constexpr uint32_t SpinLock::kSpinLockCooperative;
+constexpr uint32_t SpinLock::kSpinLockDisabledScheduling;
+constexpr uint32_t SpinLock::kSpinLockSleeper;
+constexpr uint32_t SpinLock::kWaitTimeMask;
+
 // Uncommon constructors.
 SpinLock::SpinLock(base_internal::SchedulingMode mode)
     : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {
   ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
 }
 
-SpinLock::SpinLock(base_internal::LinkerInitialized,
-                   base_internal::SchedulingMode mode) {
-  ABSL_TSAN_MUTEX_CREATE(this, 0);
-  if (IsCooperative(mode)) {
-    InitLinkerInitializedAndCooperative();
-  }
-  // Otherwise, lockword_ is already initialized.
-}
-
-// Static (linker initialized) spinlocks always start life as functional
-// non-cooperative locks.  When their static constructor does run, it will call
-// this initializer to augment the lockword with the cooperative bit.  By
-// actually taking the lock when we do this we avoid the need for an atomic
-// operation in the regular unlock path.
-//
-// SlowLock() must be careful to re-test for this bit so that any outstanding
-// waiters may be upgraded to cooperative status.
-void SpinLock::InitLinkerInitializedAndCooperative() {
-  Lock();
-  lockword_.fetch_or(kSpinLockCooperative, std::memory_order_relaxed);
-  Unlock();
-}
-
 // Monitor the lock to see if its value changes within some time period
 // (adaptive_spin_count loop iterations). The last value read from the lock
 // is returned from the method.
@@ -120,6 +105,14 @@
   if ((lock_value & kSpinLockHeld) == 0) {
     return;
   }
+
+  base_internal::SchedulingMode scheduling_mode;
+  if ((lock_value & kSpinLockCooperative) != 0) {
+    scheduling_mode = base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL;
+  } else {
+    scheduling_mode = base_internal::SCHEDULE_KERNEL_ONLY;
+  }
+
   // The lock was not obtained initially, so this thread needs to wait for
   // it.  Record the current timestamp in the local variable wait_start_time
   // so the total wait time can be stored in the lockword once this thread
@@ -150,12 +143,6 @@
       }
     }
 
-    base_internal::SchedulingMode scheduling_mode;
-    if ((lock_value & kSpinLockCooperative) != 0) {
-      scheduling_mode = base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL;
-    } else {
-      scheduling_mode = base_internal::SCHEDULE_KERNEL_ONLY;
-    }
     // SpinLockDelay() calls into fiber scheduler, we need to see
     // synchronization there to avoid false positives.
     ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
@@ -189,30 +176,32 @@
 // We use the upper 29 bits of the lock word to store the time spent waiting to
 // acquire this lock.  This is reported by contentionz profiling.  Since the
 // lower bits of the cycle counter wrap very quickly on high-frequency
-// processors we divide to reduce the granularity to 2^PROFILE_TIMESTAMP_SHIFT
+// processors we divide to reduce the granularity to 2^kProfileTimestampShift
 // sized units.  On a 4Ghz machine this will lose track of wait times greater
 // than (2^29/4 Ghz)*128 =~ 17.2 seconds.  Such waits should be extremely rare.
-enum { PROFILE_TIMESTAMP_SHIFT = 7 };
-enum { LOCKWORD_RESERVED_SHIFT = 3 };  // We currently reserve the lower 3 bits.
+static constexpr int kProfileTimestampShift = 7;
+
+// We currently reserve the lower 3 bits.
+static constexpr int kLockwordReservedShift = 3;
 
 uint32_t SpinLock::EncodeWaitCycles(int64_t wait_start_time,
                                     int64_t wait_end_time) {
   static const int64_t kMaxWaitTime =
-      std::numeric_limits<uint32_t>::max() >> LOCKWORD_RESERVED_SHIFT;
+      std::numeric_limits<uint32_t>::max() >> kLockwordReservedShift;
   int64_t scaled_wait_time =
-      (wait_end_time - wait_start_time) >> PROFILE_TIMESTAMP_SHIFT;
+      (wait_end_time - wait_start_time) >> kProfileTimestampShift;
 
   // Return a representation of the time spent waiting that can be stored in
   // the lock word's upper bits.
   uint32_t clamped = static_cast<uint32_t>(
-      std::min(scaled_wait_time, kMaxWaitTime) << LOCKWORD_RESERVED_SHIFT);
+      std::min(scaled_wait_time, kMaxWaitTime) << kLockwordReservedShift);
 
   if (clamped == 0) {
     return kSpinLockSleeper;  // Just wake waiters, but don't record contention.
   }
   // Bump up value if necessary to avoid returning kSpinLockSleeper.
   const uint32_t kMinWaitTime =
-      kSpinLockSleeper + (1 << LOCKWORD_RESERVED_SHIFT);
+      kSpinLockSleeper + (1 << kLockwordReservedShift);
   if (clamped == kSpinLockSleeper) {
     return kMinWaitTime;
   }
@@ -223,9 +212,9 @@
   // Cast to uint32_t first to ensure bits [63:32] are cleared.
   const uint64_t scaled_wait_time =
       static_cast<uint32_t>(lock_value & kWaitTimeMask);
-  return scaled_wait_time
-      << (PROFILE_TIMESTAMP_SHIFT - LOCKWORD_RESERVED_SHIFT);
+  return scaled_wait_time << (kProfileTimestampShift - kLockwordReservedShift);
 }
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h
index 1d1bd6c..dce1c85 100644
--- a/absl/base/internal/spinlock.h
+++ b/absl/base/internal/spinlock.h
@@ -15,11 +15,8 @@
 //
 
 //  Most users requiring mutual exclusion should use Mutex.
-//  SpinLock is provided for use in three situations:
+//  SpinLock is provided for use in two situations:
 //   - for use in code that Mutex itself depends on
-//   - to get a faster fast-path release under low contention (without an
-//     atomic read-modify-write) In return, SpinLock has worse behaviour under
-//     contention, which is why Mutex is preferred in most situations.
 //   - for async signal safety (see below)
 
 // SpinLock is async signal safe.  If a spinlock is used within a signal
@@ -36,6 +33,7 @@
 #include <atomic>
 
 #include "absl/base/attributes.h"
+#include "absl/base/const_init.h"
 #include "absl/base/dynamic_annotations.h"
 #include "absl/base/internal/low_level_scheduling.h"
 #include "absl/base/internal/raw_logging.h"
@@ -46,6 +44,7 @@
 #include "absl/base/thread_annotations.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 class ABSL_LOCKABLE SpinLock {
@@ -54,29 +53,22 @@
     ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
   }
 
-  // Special constructor for use with static SpinLock objects.  E.g.,
-  //
-  //    static SpinLock lock(base_internal::kLinkerInitialized);
-  //
-  // When initialized using this constructor, we depend on the fact
-  // that the linker has already initialized the memory appropriately. The lock
-  // is initialized in non-cooperative mode.
-  //
-  // A SpinLock constructed like this can be freely used from global
-  // initializers without worrying about the order in which global
-  // initializers run.
-  explicit SpinLock(base_internal::LinkerInitialized) {
-    // Does nothing; lockword_ is already initialized
-    ABSL_TSAN_MUTEX_CREATE(this, 0);
-  }
-
   // Constructors that allow non-cooperative spinlocks to be created for use
   // inside thread schedulers.  Normal clients should not use these.
   explicit SpinLock(base_internal::SchedulingMode mode);
-  SpinLock(base_internal::LinkerInitialized,
-           base_internal::SchedulingMode mode);
 
+  // Constructor for global SpinLock instances.  See absl/base/const_init.h.
+  constexpr SpinLock(absl::ConstInitType, base_internal::SchedulingMode mode)
+      : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {}
+
+  // For global SpinLock instances prefer trivial destructor when possible.
+  // Default but non-trivial destructor in some build configurations causes an
+  // extra static initializer.
+#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
   ~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }
+#else
+  ~SpinLock() = default;
+#endif
 
   // Acquire this SpinLock.
   inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
@@ -147,12 +139,13 @@
   // bit[1] encodes whether a lock uses cooperative scheduling.
   // bit[2] encodes whether a lock disables scheduling.
   // bit[3:31] encodes time a lock spent on waiting as a 29-bit unsigned int.
-  enum { kSpinLockHeld = 1 };
-  enum { kSpinLockCooperative = 2 };
-  enum { kSpinLockDisabledScheduling = 4 };
-  enum { kSpinLockSleeper = 8 };
-  enum { kWaitTimeMask =                      // Includes kSpinLockSleeper.
-    ~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling) };
+  static constexpr uint32_t kSpinLockHeld = 1;
+  static constexpr uint32_t kSpinLockCooperative = 2;
+  static constexpr uint32_t kSpinLockDisabledScheduling = 4;
+  static constexpr uint32_t kSpinLockSleeper = 8;
+  // Includes kSpinLockSleeper.
+  static constexpr uint32_t kWaitTimeMask =
+      ~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling);
 
   // Returns true if the provided scheduling mode is cooperative.
   static constexpr bool IsCooperative(
@@ -161,7 +154,6 @@
   }
 
   uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles);
-  void InitLinkerInitializedAndCooperative();
   void SlowLock() ABSL_ATTRIBUTE_COLD;
   void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD;
   uint32_t SpinLoop();
@@ -236,6 +228,7 @@
 }
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_SPINLOCK_H_
diff --git a/absl/base/internal/spinlock_linux.inc b/absl/base/internal/spinlock_linux.inc
index 28e29d1..e31c6ed 100644
--- a/absl/base/internal/spinlock_linux.inc
+++ b/absl/base/internal/spinlock_linux.inc
@@ -19,12 +19,12 @@
 #include <unistd.h>
 
 #include <atomic>
-#include <cerrno>
 #include <climits>
 #include <cstdint>
 #include <ctime>
 
 #include "absl/base/attributes.h"
+#include "absl/base/internal/errno_saver.h"
 
 // The SpinLock lockword is `std::atomic<uint32_t>`. Here we assert that
 // `std::atomic<uint32_t>` is bitwise equivalent of the `int` expected
@@ -46,17 +46,24 @@
 #endif
 #endif
 
+#if defined(__NR_futex_time64) && !defined(SYS_futex_time64)
+#define SYS_futex_time64 __NR_futex_time64
+#endif
+
+#if defined(SYS_futex_time64) && !defined(SYS_futex)
+#define SYS_futex SYS_futex_time64
+#endif
+
 extern "C" {
 
 ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
     std::atomic<uint32_t> *w, uint32_t value, int loop,
     absl::base_internal::SchedulingMode) {
-  int save_errno = errno;
+  absl::base_internal::ErrnoSaver errno_saver;
   struct timespec tm;
   tm.tv_sec = 0;
   tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);
   syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
-  errno = save_errno;
 }
 
 ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(std::atomic<uint32_t> *w,
diff --git a/absl/base/internal/spinlock_posix.inc b/absl/base/internal/spinlock_posix.inc
index f025b5f..fcd21b1 100644
--- a/absl/base/internal/spinlock_posix.inc
+++ b/absl/base/internal/spinlock_posix.inc
@@ -15,10 +15,11 @@
 // This file is a Posix-specific part of spinlock_wait.cc
 
 #include <sched.h>
+
 #include <atomic>
 #include <ctime>
-#include <cerrno>
 
+#include "absl/base/internal/errno_saver.h"
 #include "absl/base/internal/scheduling_mode.h"
 #include "absl/base/port.h"
 
@@ -27,7 +28,7 @@
 ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
     std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop,
     absl::base_internal::SchedulingMode /* mode */) {
-  int save_errno = errno;
+  absl::base_internal::ErrnoSaver errno_saver;
   if (loop == 0) {
   } else if (loop == 1) {
     sched_yield();
@@ -37,7 +38,6 @@
     tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);
     nanosleep(&tm, nullptr);
   }
-  errno = save_errno;
 }
 
 ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(
diff --git a/absl/base/internal/spinlock_wait.cc b/absl/base/internal/spinlock_wait.cc
index fac8a21..fa824be 100644
--- a/absl/base/internal/spinlock_wait.cc
+++ b/absl/base/internal/spinlock_wait.cc
@@ -32,6 +32,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // See spinlock_wait.h for spec.
@@ -76,4 +77,5 @@
 }
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/spinlock_wait.h b/absl/base/internal/spinlock_wait.h
index 6642ce1..c34ce41 100644
--- a/absl/base/internal/spinlock_wait.h
+++ b/absl/base/internal/spinlock_wait.h
@@ -24,6 +24,7 @@
 #include "absl/base/internal/scheduling_mode.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // SpinLockWait() waits until it can perform one of several transitions from
@@ -42,18 +43,16 @@
                       const SpinLockWaitTransition trans[],
                       SchedulingMode scheduling_mode);
 
-// If possible, wake some thread that has called SpinLockDelay(w, ...). If
-// "all" is true, wake all such threads.  This call is a hint, and on some
-// systems it may be a no-op; threads calling SpinLockDelay() will always wake
-// eventually even if SpinLockWake() is never called.
+// If possible, wake some thread that has called SpinLockDelay(w, ...). If `all`
+// is true, wake all such threads. On some systems, this may be a no-op; on
+// those systems, threads calling SpinLockDelay() will always wake eventually
+// even if SpinLockWake() is never called.
 void SpinLockWake(std::atomic<uint32_t> *w, bool all);
 
 // Wait for an appropriate spin delay on iteration "loop" of a
 // spin loop on location *w, whose previously observed value was "value".
 // SpinLockDelay() may do nothing, may yield the CPU, may sleep a clock tick,
-// or may wait for a delay that can be truncated by a call to SpinLockWake(w).
-// In all cases, it must return in bounded time even if SpinLockWake() is not
-// called.
+// or may wait for a call to SpinLockWake(w).
 void SpinLockDelay(std::atomic<uint32_t> *w, uint32_t value, int loop,
                    base_internal::SchedulingMode scheduling_mode);
 
@@ -62,6 +61,7 @@
 int SpinLockSuggestedDelayNS(int loop);
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 // In some build configurations we pass --detect-odr-violations to the
diff --git a/absl/base/internal/strerror.cc b/absl/base/internal/strerror.cc
new file mode 100644
index 0000000..0d6226f
--- /dev/null
+++ b/absl/base/internal/strerror.cc
@@ -0,0 +1,88 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/strerror.h"
+
+#include <array>
+#include <cerrno>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include <type_traits>
+
+#include "absl/base/internal/errno_saver.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+namespace {
+
+const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
+#if defined(_WIN32)
+  int rc = strerror_s(buf, buflen, errnum);
+  buf[buflen - 1] = '\0';  // guarantee NUL termination
+  if (rc == 0 && strncmp(buf, "Unknown error", buflen) == 0) *buf = '\0';
+  return buf;
+#else
+  // The type of `ret` is platform-specific; both of these branches must compile
+  // either way but only one will execute on any given platform:
+  auto ret = strerror_r(errnum, buf, buflen);
+  if (std::is_same<decltype(ret), int>::value) {
+    // XSI `strerror_r`; `ret` is `int`:
+    if (ret) *buf = '\0';
+    return buf;
+  } else {
+    // GNU `strerror_r`; `ret` is `char *`:
+    return reinterpret_cast<const char*>(ret);
+  }
+#endif
+}
+
+std::string StrErrorInternal(int errnum) {
+  char buf[100];
+  const char* str = StrErrorAdaptor(errnum, buf, sizeof buf);
+  if (*str == '\0') {
+    snprintf(buf, sizeof buf, "Unknown error %d", errnum);
+    str = buf;
+  }
+  return str;
+}
+
+// kSysNerr is the number of errors from a recent glibc. `StrError()` falls back
+// to `StrErrorAdaptor()` if the value is larger than this.
+constexpr int kSysNerr = 135;
+
+std::array<std::string, kSysNerr>* NewStrErrorTable() {
+  auto* table = new std::array<std::string, kSysNerr>;
+  for (int i = 0; i < static_cast<int>(table->size()); ++i) {
+    (*table)[i] = StrErrorInternal(i);
+  }
+  return table;
+}
+
+}  // namespace
+
+std::string StrError(int errnum) {
+  absl::base_internal::ErrnoSaver errno_saver;
+  static const auto* table = NewStrErrorTable();
+  if (errnum >= 0 && errnum < static_cast<int>(table->size())) {
+    return (*table)[errnum];
+  }
+  return StrErrorInternal(errnum);
+}
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/base/internal/strerror.h b/absl/base/internal/strerror.h
new file mode 100644
index 0000000..3500973
--- /dev/null
+++ b/absl/base/internal/strerror.h
@@ -0,0 +1,39 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_BASE_INTERNAL_STRERROR_H_
+#define ABSL_BASE_INTERNAL_STRERROR_H_
+
+#include <string>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// A portable and thread-safe alternative to C89's `strerror`.
+//
+// The C89 specification of `strerror` is not suitable for use in a
+// multi-threaded application as the returned string may be changed by calls to
+// `strerror` from another thread.  The many non-stdlib alternatives differ
+// enough in their names, availability, and semantics to justify this wrapper
+// around them.  `errno` will not be modified by a call to `absl::StrError`.
+std::string StrError(int errnum);
+
+}  // namespace base_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_BASE_INTERNAL_STRERROR_H_
diff --git a/absl/random/internal/seed_salting_sequence_generator_empty_sequence.cc b/absl/base/internal/strerror_benchmark.cc
similarity index 60%
rename from absl/random/internal/seed_salting_sequence_generator_empty_sequence.cc
rename to absl/base/internal/strerror_benchmark.cc
index 8797e2e..c9ab14a 100644
--- a/absl/random/internal/seed_salting_sequence_generator_empty_sequence.cc
+++ b/absl/base/internal/strerror_benchmark.cc
@@ -1,4 +1,4 @@
-// Copyright 2017 The Abseil Authors.
+// Copyright 2020 The Abseil Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,19 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include <iostream>
-#include <random>
+#include <cerrno>
+#include <cstdio>
+#include <string>
 
-#include "absl/random/random.h"
+#include "absl/base/internal/strerror.h"
+#include "benchmark/benchmark.h"
 
-// This program is used in integration tests.
-
-int main() {
-  std::seed_seq seed_seq{};
-  absl::BitGen rng(seed_seq);
-  constexpr size_t kSequenceLength = 8;
-  for (size_t i = 0; i < kSequenceLength; i++) {
-    std::cout << rng() << "\n";
+namespace {
+void BM_AbslStrError(benchmark::State& state) {
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(absl::base_internal::StrError(ERANGE));
   }
-  return 0;
 }
+BENCHMARK(BM_AbslStrError);
+}  // namespace
diff --git a/absl/base/internal/strerror_test.cc b/absl/base/internal/strerror_test.cc
new file mode 100644
index 0000000..e32d5b5
--- /dev/null
+++ b/absl/base/internal/strerror_test.cc
@@ -0,0 +1,88 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/strerror.h"
+
+#include <atomic>
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include <thread>  // NOLINT(build/c++11)
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/strings/match.h"
+
+namespace {
+using ::testing::AnyOf;
+using ::testing::Eq;
+
+TEST(StrErrorTest, ValidErrorCode) {
+  errno = ERANGE;
+  EXPECT_THAT(absl::base_internal::StrError(EDOM), Eq(strerror(EDOM)));
+  EXPECT_THAT(errno, Eq(ERANGE));
+}
+
+TEST(StrErrorTest, InvalidErrorCode) {
+  errno = ERANGE;
+  EXPECT_THAT(absl::base_internal::StrError(-1),
+              AnyOf(Eq("No error information"), Eq("Unknown error -1")));
+  EXPECT_THAT(errno, Eq(ERANGE));
+}
+
+TEST(StrErrorTest, MultipleThreads) {
+  // In this test, we will start up 2 threads and have each one call
+  // StrError 1000 times, each time with a different errnum.  We
+  // expect that StrError(errnum) will return a string equal to the
+  // one returned by strerror(errnum), if the code is known.  Since
+  // strerror is known to be thread-hostile, collect all the expected
+  // strings up front.
+  const int kNumCodes = 1000;
+  std::vector<std::string> expected_strings(kNumCodes);
+  for (int i = 0; i < kNumCodes; ++i) {
+    expected_strings[i] = strerror(i);
+  }
+
+  std::atomic_int counter(0);
+  auto thread_fun = [&]() {
+    for (int i = 0; i < kNumCodes; ++i) {
+      ++counter;
+      errno = ERANGE;
+      const std::string value = absl::base_internal::StrError(i);
+      // EXPECT_* could change errno. Stash it first.
+      int check_err = errno;
+      EXPECT_THAT(check_err, Eq(ERANGE));
+      // Only the GNU implementation is guaranteed to provide the
+      // string "Unknown error nnn". POSIX doesn't say anything.
+      if (!absl::StartsWith(value, "Unknown error ")) {
+        EXPECT_THAT(value, Eq(expected_strings[i]));
+      }
+    }
+  };
+
+  const int kNumThreads = 100;
+  std::vector<std::thread> threads;
+  for (int i = 0; i < kNumThreads; ++i) {
+    threads.push_back(std::thread(thread_fun));
+  }
+  for (auto& thread : threads) {
+    thread.join();
+  }
+
+  EXPECT_THAT(counter, Eq(kNumThreads * kNumCodes));
+}
+
+}  // namespace
diff --git a/absl/base/internal/sysinfo.cc b/absl/base/internal/sysinfo.cc
index 4dd3add..4a3b205 100644
--- a/absl/base/internal/sysinfo.cc
+++ b/absl/base/internal/sysinfo.cc
@@ -17,7 +17,6 @@
 #include "absl/base/attributes.h"
 
 #ifdef _WIN32
-#include <shlwapi.h>
 #include <windows.h>
 #else
 #include <fcntl.h>
@@ -40,6 +39,7 @@
 #endif
 
 #include <string.h>
+
 #include <cassert>
 #include <cstdint>
 #include <cstdio>
@@ -51,17 +51,16 @@
 #include <vector>
 
 #include "absl/base/call_once.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/spinlock.h"
 #include "absl/base/internal/unscaledcycleclock.h"
+#include "absl/base/thread_annotations.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
-static once_flag init_system_info_once;
-static int num_cpus = 0;
-static double nominal_cpu_frequency = 1.0;  // 0.0 might be dangerous.
-
 static int GetNumCPUs() {
 #if defined(__myriad2__)
   return 1;
@@ -76,16 +75,32 @@
 #if defined(_WIN32)
 
 static double GetNominalCPUFrequency() {
-  DWORD data;
-  DWORD data_size = sizeof(data);
-  #pragma comment(lib, "shlwapi.lib")  // For SHGetValue().
-  if (SUCCEEDED(
-          SHGetValueA(HKEY_LOCAL_MACHINE,
-                      "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
-                      "~MHz", nullptr, &data, &data_size))) {
-    return data * 1e6;  // Value is MHz.
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
+    !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+  // UWP apps don't have access to the registry and currently don't provide an
+  // API informing about CPU nominal frequency.
+  return 1.0;
+#else
+#pragma comment(lib, "advapi32.lib")  // For Reg* functions.
+  HKEY key;
+  // Use the Reg* functions rather than the SH functions because shlwapi.dll
+  // pulls in gdi32.dll which makes process destruction much more costly.
+  if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+                    "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
+                    KEY_READ, &key) == ERROR_SUCCESS) {
+    DWORD type = 0;
+    DWORD data = 0;
+    DWORD data_size = sizeof(data);
+    auto result = RegQueryValueExA(key, "~MHz", 0, &type,
+                                   reinterpret_cast<LPBYTE>(&data), &data_size);
+    RegCloseKey(key);
+    if (result == ERROR_SUCCESS && type == REG_DWORD &&
+        data_size == sizeof(data)) {
+      return data * 1e6;  // Value is MHz.
+    }
   }
   return 1.0;
+#endif  // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
 }
 
 #elif defined(CTL_HW) && defined(HW_CPU_FREQ)
@@ -256,28 +271,34 @@
 
 #endif
 
-// InitializeSystemInfo() may be called before main() and before
-// malloc is properly initialized, therefore this must not allocate
-// memory.
-static void InitializeSystemInfo() {
-  num_cpus = GetNumCPUs();
-  nominal_cpu_frequency = GetNominalCPUFrequency();
-}
+ABSL_CONST_INIT static once_flag init_num_cpus_once;
+ABSL_CONST_INIT static int num_cpus = 0;
 
+// NumCPUs() may be called before main() and before malloc is properly
+// initialized, therefore this must not allocate memory.
 int NumCPUs() {
-  base_internal::LowLevelCallOnce(&init_system_info_once, InitializeSystemInfo);
+  base_internal::LowLevelCallOnce(
+      &init_num_cpus_once, []() { num_cpus = GetNumCPUs(); });
   return num_cpus;
 }
 
+// A default frequency of 0.0 might be dangerous if it is used in division.
+ABSL_CONST_INIT static once_flag init_nominal_cpu_frequency_once;
+ABSL_CONST_INIT static double nominal_cpu_frequency = 1.0;
+
+// NominalCPUFrequency() may be called before main() and before malloc is
+// properly initialized, therefore this must not allocate memory.
 double NominalCPUFrequency() {
-  base_internal::LowLevelCallOnce(&init_system_info_once, InitializeSystemInfo);
+  base_internal::LowLevelCallOnce(
+      &init_nominal_cpu_frequency_once,
+      []() { nominal_cpu_frequency = GetNominalCPUFrequency(); });
   return nominal_cpu_frequency;
 }
 
 #if defined(_WIN32)
 
 pid_t GetTID() {
-  return GetCurrentThreadId();
+  return pid_t{GetCurrentThreadId()};
 }
 
 #elif defined(__linux__)
@@ -325,15 +346,16 @@
 #else
 
 // Fallback implementation of GetTID using pthread_getspecific.
-static once_flag tid_once;
-static pthread_key_t tid_key;
-static absl::base_internal::SpinLock tid_lock(
-    absl::base_internal::kLinkerInitialized);
+ABSL_CONST_INIT static once_flag tid_once;
+ABSL_CONST_INIT static pthread_key_t tid_key;
+ABSL_CONST_INIT static absl::base_internal::SpinLock tid_lock(
+    absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
 
 // We set a bit per thread in this array to indicate that an ID is in
 // use. ID 0 is unused because it is the default value returned by
 // pthread_getspecific().
-static std::vector<uint32_t>* tid_array GUARDED_BY(tid_lock) = nullptr;
+ABSL_CONST_INIT static std::vector<uint32_t> *tid_array
+    ABSL_GUARDED_BY(tid_lock) = nullptr;
 static constexpr int kBitsPerWord = 32;  // tid_array is uint32_t.
 
 // Returns the TID to tid_array.
@@ -400,5 +422,18 @@
 
 #endif
 
+// GetCachedTID() caches the thread ID in thread-local storage (which is a
+// userspace construct) to avoid unnecessary system calls. Without this caching,
+// it can take roughly 98ns, while it takes roughly 1ns with this caching.
+pid_t GetCachedTID() {
+#ifdef ABSL_HAVE_THREAD_LOCAL
+  static thread_local pid_t thread_id = GetTID();
+  return thread_id;
+#else
+  return GetTID();
+#endif  // ABSL_HAVE_THREAD_LOCAL
+}
+
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/sysinfo.h b/absl/base/internal/sysinfo.h
index b864a59..119cf1f 100644
--- a/absl/base/internal/sysinfo.h
+++ b/absl/base/internal/sysinfo.h
@@ -26,13 +26,15 @@
 
 #ifndef _WIN32
 #include <sys/types.h>
-#else
-#include <intsafe.h>
 #endif
 
+#include <cstdint>
+
+#include "absl/base/config.h"
 #include "absl/base/port.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // Nominal core processor cycles per second of each processor.   This is _not_
@@ -51,13 +53,22 @@
 // On Linux, you may send a signal to the resulting ID with kill().  However,
 // it is recommended for portability that you use pthread_kill() instead.
 #ifdef _WIN32
-// On Windows, process id and thread id are of the same type according to
-// the return types of GetProcessId() and GetThreadId() are both DWORD.
-using pid_t = DWORD;
+// On Windows, process id and thread id are of the same type according to the
+// return types of GetProcessId() and GetThreadId() are both DWORD, an unsigned
+// 32-bit type.
+using pid_t = uint32_t;
 #endif
 pid_t GetTID();
 
+// Like GetTID(), but caches the result in thread-local storage in order
+// to avoid unnecessary system calls. Note that there are some cases where
+// one must call through to GetTID directly, which is why this exists as a
+// separate function. For example, GetCachedTID() is not safe to call in
+// an asynchronous signal-handling context nor right after a call to fork().
+pid_t GetCachedTID();
+
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_SYSINFO_H_
diff --git a/absl/base/internal/sysinfo_test.cc b/absl/base/internal/sysinfo_test.cc
index 82bbcc2..5f9e45f 100644
--- a/absl/base/internal/sysinfo_test.cc
+++ b/absl/base/internal/sysinfo_test.cc
@@ -28,6 +28,7 @@
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 namespace {
 
@@ -36,17 +37,28 @@
       << "NumCPUs() should not have the default value of 0";
 }
 
+// Ensure that NominalCPUFrequency returns a reasonable value, or 1.00 on
+// platforms where the CPU frequency is not available through sysfs.
+//
+// POWER is particularly problematic here; some Linux kernels expose the CPU
+// frequency, while others do not. Since we can't predict a priori what a given
+// machine is going to do, just disable this test on POWER on Linux.
+#if !(defined(__linux) && (defined(__ppc64__) || defined(__PPC64__)))
 TEST(SysinfoTest, NominalCPUFrequency) {
-#if !(defined(__aarch64__) && defined(__linux__)) && !defined(__EMSCRIPTEN__)
-  EXPECT_GE(NominalCPUFrequency(), 1000.0)
-      << "NominalCPUFrequency() did not return a reasonable value";
-#else
-  // Aarch64 cannot read the CPU frequency from sysfs, so we get back 1.0.
-  // Emscripten does not have a sysfs to read from at all.
+  // Linux only exposes the CPU frequency on certain architectures, and
+  // Emscripten doesn't expose it at all.
+#if defined(__linux__) &&                                                  \
+        (defined(__aarch64__) || defined(__hppa__) || defined(__mips__) || \
+         defined(__riscv) || defined(__s390x__)) ||                        \
+    defined(__EMSCRIPTEN__)
   EXPECT_EQ(NominalCPUFrequency(), 1.0)
       << "CPU frequency detection was fixed! Please update unittest.";
+#else
+  EXPECT_GE(NominalCPUFrequency(), 1000.0)
+      << "NominalCPUFrequency() did not return a reasonable value";
 #endif
 }
+#endif
 
 TEST(SysinfoTest, GetTID) {
   EXPECT_EQ(GetTID(), GetTID());  // Basic compile and equality test.
@@ -58,8 +70,8 @@
 #endif
   // Test that TIDs are unique to each thread.
   // Uses a few loops to exercise implementations that reallocate IDs.
-  for (int i = 0; i < 32; ++i) {
-    constexpr int kNumThreads = 64;
+  for (int i = 0; i < 10; ++i) {
+    constexpr int kNumThreads = 10;
     Barrier all_threads_done(kNumThreads);
     std::vector<std::thread> threads;
 
@@ -95,4 +107,5 @@
 
 }  // namespace
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/thread_identity.cc b/absl/base/internal/thread_identity.cc
index 91273a6..6ea010e 100644
--- a/absl/base/internal/thread_identity.cc
+++ b/absl/base/internal/thread_identity.cc
@@ -23,11 +23,13 @@
 #include <cassert>
 #include <memory>
 
+#include "absl/base/attributes.h"
 #include "absl/base/call_once.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/spinlock.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 #if ABSL_THREAD_IDENTITY_MODE != ABSL_THREAD_IDENTITY_MODE_USE_CPP11
@@ -52,10 +54,17 @@
 // exist within a process (via dlopen() or similar), references to
 // thread_identity_ptr from each instance of the code will refer to
 // *different* instances of this ptr.
-#ifdef __GNUC__
+// Apple platforms have the visibility attribute, but issue a compile warning
+// that protected visibility is unsupported.
+#if ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
 __attribute__((visibility("protected")))
-#endif  // __GNUC__
-  ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr;
+#endif  // ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
+#if ABSL_PER_THREAD_TLS
+// Prefer __thread to thread_local as benchmarks indicate it is a bit faster.
+ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr = nullptr;
+#elif defined(ABSL_HAVE_THREAD_LOCAL)
+thread_local ThreadIdentity* thread_identity_ptr = nullptr;
+#endif  // ABSL_PER_THREAD_TLS
 #endif  // TLS or CPP11
 
 void SetCurrentThreadIdentity(
@@ -69,8 +78,8 @@
   absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey,
                   reclaimer);
 
-#ifdef __EMSCRIPTEN__
-  // Emscripten PThread implementation does not support signals.
+#if defined(__EMSCRIPTEN__) || defined(__MINGW32__)
+  // Emscripten and MinGW pthread implementations does not support signals.
   // See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html
   // for more information.
   pthread_setspecific(thread_identity_pthread_key,
@@ -89,7 +98,7 @@
   pthread_setspecific(thread_identity_pthread_key,
                       reinterpret_cast<void*>(identity));
   pthread_sigmask(SIG_SETMASK, &curr_signals, nullptr);
-#endif  // !__EMSCRIPTEN__
+#endif  // !__EMSCRIPTEN__ && !__MINGW32__
 
 #elif ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS
   // NOTE: Not async-safe.  But can be open-coded.
@@ -107,6 +116,18 @@
 #endif
 }
 
+#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
+    ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
+
+// Please see the comment on `CurrentThreadIdentityIfPresent` in
+// thread_identity.h. Because DLLs cannot expose thread_local variables in
+// headers, we opt for the correct-but-slower option of placing the definition
+// of this function only in a translation unit inside DLL.
+#if defined(ABSL_BUILD_DLL) || defined(ABSL_CONSUME_DLL)
+ThreadIdentity* CurrentThreadIdentityIfPresent() { return thread_identity_ptr; }
+#endif
+#endif
+
 void ClearCurrentThreadIdentity() {
 #if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
     ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
@@ -130,4 +151,5 @@
 #endif
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h
index b34674a..d2a65fd 100644
--- a/absl/base/internal/thread_identity.h
+++ b/absl/base/internal/thread_identity.h
@@ -30,9 +30,12 @@
 #include <atomic>
 #include <cstdint>
 
+#include "absl/base/config.h"
 #include "absl/base/internal/per_thread_tls.h"
+#include "absl/base/optimization.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 struct SynchLocksHeld;
 struct SynchWaitParams;
@@ -67,30 +70,28 @@
                          // is using this PerThreadSynch as a terminator.  Its
                          // skip field must not be filled in because the loop
                          // might then skip over the terminator.
-
-  // The wait parameters of the current wait.  waitp is null if the
-  // thread is not waiting. Transitions from null to non-null must
-  // occur before the enqueue commit point (state = kQueued in
-  // Enqueue() and CondVarEnqueue()). Transitions from non-null to
-  // null must occur after the wait is finished (state = kAvailable in
-  // Mutex::Block() and CondVar::WaitCommon()). This field may be
-  // changed only by the thread that describes this PerThreadSynch.  A
-  // special case is Fer(), which calls Enqueue() on another thread,
-  // but with an identical SynchWaitParams pointer, thus leaving the
-  // pointer unchanged.
-  SynchWaitParams *waitp;
-
-  bool suppress_fatal_errors;  // If true, try to proceed even in the face of
-                               // broken invariants.  This is used within fatal
-                               // signal handlers to improve the chances of
-                               // debug logging information being output
-                               // successfully.
-
-  intptr_t readers;     // Number of readers in mutex.
-  int priority;         // Priority of thread (updated every so often).
-
-  // When priority will next be read (cycles).
-  int64_t next_priority_read_cycles;
+  bool wake;             // This thread is to be woken from a Mutex.
+  // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
+  // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
+  //
+  // The value of "x->cond_waiter" is meaningless if "x" is not on a
+  // Mutex waiter list.
+  bool cond_waiter;
+  bool maybe_unlocking;  // Valid at head of Mutex waiter queue;
+                         // true if UnlockSlow could be searching
+                         // for a waiter to wake.  Used for an optimization
+                         // in Enqueue().  true is always a valid value.
+                         // Can be reset to false when the unlocker or any
+                         // writer releases the lock, or a reader fully
+                         // releases the lock.  It may not be set to false
+                         // by a reader that decrements the count to
+                         // non-zero. protected by mutex spinlock
+  bool suppress_fatal_errors;  // If true, try to proceed even in the face
+                               // of broken invariants.  This is used within
+                               // fatal signal handlers to improve the
+                               // chances of debug logging information being
+                               // output successfully.
+  int priority;                // Priority of thread (updated every so often).
 
   // State values:
   //   kAvailable: This PerThreadSynch is available.
@@ -109,30 +110,30 @@
   };
   std::atomic<State> state;
 
-  bool maybe_unlocking;  // Valid at head of Mutex waiter queue;
-                         // true if UnlockSlow could be searching
-                         // for a waiter to wake.  Used for an optimization
-                         // in Enqueue().  true is always a valid value.
-                         // Can be reset to false when the unlocker or any
-                         // writer releases the lock, or a reader fully releases
-                         // the lock.  It may not be set to false by a reader
-                         // that decrements the count to non-zero.
-                         // protected by mutex spinlock
+  // The wait parameters of the current wait.  waitp is null if the
+  // thread is not waiting. Transitions from null to non-null must
+  // occur before the enqueue commit point (state = kQueued in
+  // Enqueue() and CondVarEnqueue()). Transitions from non-null to
+  // null must occur after the wait is finished (state = kAvailable in
+  // Mutex::Block() and CondVar::WaitCommon()). This field may be
+  // changed only by the thread that describes this PerThreadSynch.  A
+  // special case is Fer(), which calls Enqueue() on another thread,
+  // but with an identical SynchWaitParams pointer, thus leaving the
+  // pointer unchanged.
+  SynchWaitParams* waitp;
 
-  bool wake;  // This thread is to be woken from a Mutex.
+  intptr_t readers;     // Number of readers in mutex.
 
-  // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
-  // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
-  //
-  // The value of "x->cond_waiter" is meaningless if "x" is not on a
-  // Mutex waiter list.
-  bool cond_waiter;
+  // When priority will next be read (cycles).
+  int64_t next_priority_read_cycles;
 
   // Locks held; used during deadlock detection.
   // Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().
   SynchLocksHeld *all_locks;
 };
 
+// The instances of this class are allocated in NewThreadIdentity() with an
+// alignment of PerThreadSynch::kAlignment.
 struct ThreadIdentity {
   // Must be the first member.  The Mutex implementation requires that
   // the PerThreadSynch object associated with each thread is
@@ -208,9 +209,11 @@
 #error ABSL_THREAD_IDENTITY_MODE cannot be direcly set
 #elif defined(ABSL_FORCE_THREAD_IDENTITY_MODE)
 #define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE
-#elif defined(_WIN32)
+#elif defined(_WIN32) && !defined(__MINGW32__)
 #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
-#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
+#elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)
+#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
+#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) &&        \
     (__GOOGLE_GRTE_VERSION__ >= 20140228L)
 // Support for async-safe TLS was specifically added in GRTEv4.  It's not
 // present in the upstream eglibc.
@@ -224,11 +227,26 @@
 #if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
     ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
 
-extern ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr;
+#if ABSL_PER_THREAD_TLS
+ABSL_CONST_INIT extern ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity*
+    thread_identity_ptr;
+#elif defined(ABSL_HAVE_THREAD_LOCAL)
+ABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr;
+#else
+#error Thread-local storage not detected on this platform
+#endif
 
+// thread_local variables cannot be in headers exposed by DLLs. However, it is
+// important for performance reasons in general that
+// `CurrentThreadIdentityIfPresent` be inlined. This is not possible across a
+// DLL boundary so, with DLLs, we opt to have the function not be inlined. Note
+// that `CurrentThreadIdentityIfPresent` is declared above so we can exclude
+// this entire inline definition when compiling as a DLL.
+#if !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL)
 inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
   return thread_identity_ptr;
 }
+#endif
 
 #elif ABSL_THREAD_IDENTITY_MODE != \
     ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
@@ -236,6 +254,7 @@
 #endif
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
diff --git a/absl/base/internal/thread_identity_test.cc b/absl/base/internal/thread_identity_test.cc
index 13bfbe3..46a6f74 100644
--- a/absl/base/internal/thread_identity_test.cc
+++ b/absl/base/internal/thread_identity_test.cc
@@ -21,17 +21,18 @@
 #include "absl/base/attributes.h"
 #include "absl/base/internal/spinlock.h"
 #include "absl/base/macros.h"
+#include "absl/base/thread_annotations.h"
 #include "absl/synchronization/internal/per_thread_sem.h"
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 namespace {
 
-// protects num_identities_reused
-static absl::base_internal::SpinLock map_lock(
-    absl::base_internal::kLinkerInitialized);
-static int num_identities_reused;
+ABSL_CONST_INIT static absl::base_internal::SpinLock map_lock(
+    absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
+ABSL_CONST_INIT static int num_identities_reused ABSL_GUARDED_BY(map_lock);
 
 static const void* const kCheckNoIdentity = reinterpret_cast<void*>(1);
 
@@ -74,7 +75,7 @@
   // - If a thread implementation chooses to recycle threads, that
   //   correct re-initialization occurs.
   static const int kNumLoops = 3;
-  static const int kNumThreads = 400;
+  static const int kNumThreads = 32;
   for (int iter = 0; iter < kNumLoops; iter++) {
     std::vector<std::thread> threads;
     for (int i = 0; i < kNumThreads; ++i) {
@@ -89,6 +90,7 @@
   // We should have recycled ThreadIdentity objects above; while (external)
   // library threads allocating their own identities may preclude some
   // reuse, we should have sufficient repetitions to exclude this.
+  absl::base_internal::SpinLockHolder l(&map_lock);
   EXPECT_LT(kNumThreads, num_identities_reused);
 }
 
@@ -123,4 +125,5 @@
 
 }  // namespace
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/throw_delegate.cc b/absl/base/internal/throw_delegate.cc
index 8e928b8..c260ff1 100644
--- a/absl/base/internal/throw_delegate.cc
+++ b/absl/base/internal/throw_delegate.cc
@@ -18,89 +18,195 @@
 #include <functional>
 #include <new>
 #include <stdexcept>
+
 #include "absl/base/config.h"
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
+// NOTE: The various STL exception throwing functions are placed within the
+// #ifdef blocks so the symbols aren't exposed on platforms that don't support
+// them, such as the Android NDK. For example, ANGLE fails to link when building
+// within AOSP without them, since the STL functions don't exist.
 namespace {
+#ifdef ABSL_HAVE_EXCEPTIONS
 template <typename T>
 [[noreturn]] void Throw(const T& error) {
-#ifdef ABSL_HAVE_EXCEPTIONS
   throw error;
-#else
-  ABSL_RAW_LOG(FATAL, "%s", error.what());
-  std::abort();
-#endif
 }
+#endif
 }  // namespace
 
 void ThrowStdLogicError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::logic_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdLogicError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::logic_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 void ThrowStdInvalidArgument(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::invalid_argument(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdInvalidArgument(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::invalid_argument(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdDomainError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::domain_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdDomainError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::domain_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdLengthError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::length_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdLengthError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::length_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdOutOfRange(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::out_of_range(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdOutOfRange(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::out_of_range(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdRuntimeError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::runtime_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdRuntimeError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::runtime_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdRangeError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::range_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdRangeError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::range_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdOverflowError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::overflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdOverflowError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::overflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
 void ThrowStdUnderflowError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::underflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+  std::abort();
+#endif
 }
 void ThrowStdUnderflowError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
   Throw(std::underflow_error(what_arg));
+#else
+  ABSL_RAW_LOG(FATAL, "%s", what_arg);
+  std::abort();
+#endif
 }
 
-void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); }
+void ThrowStdBadFunctionCall() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+  Throw(std::bad_function_call());
+#else
+  std::abort();
+#endif
+}
 
-void ThrowStdBadAlloc() { Throw(std::bad_alloc()); }
+void ThrowStdBadAlloc() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+  Throw(std::bad_alloc());
+#else
+  std::abort();
+#endif
+}
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/internal/throw_delegate.h b/absl/base/internal/throw_delegate.h
index 03c700b..075f527 100644
--- a/absl/base/internal/throw_delegate.h
+++ b/absl/base/internal/throw_delegate.h
@@ -19,7 +19,10 @@
 
 #include <string>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // Helper functions that allow throwing exceptions consistently from anywhere.
@@ -66,6 +69,7 @@
 // [[noreturn]] void ThrowStdBadArrayNewLength();
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_INTERNAL_THROW_DELEGATE_H_
diff --git a/absl/base/internal/tsan_mutex_interface.h b/absl/base/internal/tsan_mutex_interface.h
index 2a51060..39207d8 100644
--- a/absl/base/internal/tsan_mutex_interface.h
+++ b/absl/base/internal/tsan_mutex_interface.h
@@ -19,6 +19,8 @@
 #ifndef ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_
 #define ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_
 
+#include "absl/base/config.h"
+
 // ABSL_INTERNAL_HAVE_TSAN_INTERFACE
 // Macro intended only for internal use.
 //
@@ -28,7 +30,7 @@
 #error "ABSL_INTERNAL_HAVE_TSAN_INTERFACE cannot be directly set."
 #endif
 
-#if defined(THREAD_SANITIZER) && defined(__has_include)
+#if defined(ABSL_HAVE_THREAD_SANITIZER) && defined(__has_include)
 #if __has_include(<sanitizer/tsan_interface.h>)
 #define ABSL_INTERNAL_HAVE_TSAN_INTERFACE 1
 #endif
diff --git a/absl/base/internal/unaligned_access.h b/absl/base/internal/unaligned_access.h
index 2cf7c1d..093dd9b 100644
--- a/absl/base/internal/unaligned_access.h
+++ b/absl/base/internal/unaligned_access.h
@@ -18,9 +18,11 @@
 #define ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_
 
 #include <string.h>
+
 #include <cstdint>
 
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
 
 // unaligned APIs
 
@@ -29,79 +31,8 @@
 // The unaligned API is C++ only.  The declarations use C++ features
 // (namespaces, inline) which are absent or incompatible in C.
 #if defined(__cplusplus)
-
-#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\
-    defined(MEMORY_SANITIZER)
-// Consider we have an unaligned load/store of 4 bytes from address 0x...05.
-// AddressSanitizer will treat it as a 3-byte access to the range 05:07 and
-// will miss a bug if 08 is the first unaddressable byte.
-// ThreadSanitizer will also treat this as a 3-byte access to 05:07 and will
-// miss a race between this access and some other accesses to 08.
-// MemorySanitizer will correctly propagate the shadow on unaligned stores
-// and correctly report bugs on unaligned loads, but it may not properly
-// update and report the origin of the uninitialized memory.
-// For all three tools, replacing an unaligned access with a tool-specific
-// callback solves the problem.
-
-// Make sure uint16_t/uint32_t/uint64_t are defined.
-#include <stdint.h>
-
-extern "C" {
-uint16_t __sanitizer_unaligned_load16(const void *p);
-uint32_t __sanitizer_unaligned_load32(const void *p);
-uint64_t __sanitizer_unaligned_load64(const void *p);
-void __sanitizer_unaligned_store16(void *p, uint16_t v);
-void __sanitizer_unaligned_store32(void *p, uint32_t v);
-void __sanitizer_unaligned_store64(void *p, uint64_t v);
-}  // extern "C"
-
 namespace absl {
-namespace base_internal {
-
-inline uint16_t UnalignedLoad16(const void *p) {
-  return __sanitizer_unaligned_load16(p);
-}
-
-inline uint32_t UnalignedLoad32(const void *p) {
-  return __sanitizer_unaligned_load32(p);
-}
-
-inline uint64_t UnalignedLoad64(const void *p) {
-  return __sanitizer_unaligned_load64(p);
-}
-
-inline void UnalignedStore16(void *p, uint16_t v) {
-  __sanitizer_unaligned_store16(p, v);
-}
-
-inline void UnalignedStore32(void *p, uint32_t v) {
-  __sanitizer_unaligned_store32(p, v);
-}
-
-inline void UnalignedStore64(void *p, uint64_t v) {
-  __sanitizer_unaligned_store64(p, v);
-}
-
-}  // namespace base_internal
-}  // namespace absl
-
-#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
-  (absl::base_internal::UnalignedLoad16(_p))
-#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
-  (absl::base_internal::UnalignedLoad32(_p))
-#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
-  (absl::base_internal::UnalignedLoad64(_p))
-
-#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
-  (absl::base_internal::UnalignedStore16(_p, _val))
-#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
-  (absl::base_internal::UnalignedStore32(_p, _val))
-#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
-  (absl::base_internal::UnalignedStore64(_p, _val))
-
-#else
-
-namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 inline uint16_t UnalignedLoad16(const void *p) {
@@ -129,6 +60,7 @@
 inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
@@ -145,8 +77,6 @@
 #define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
   (absl::base_internal::UnalignedStore64(_p, _val))
 
-#endif
-
 #endif  // defined(__cplusplus), end of unaligned API
 
 #endif  // ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_
diff --git a/absl/base/internal/unique_small_name_test.cc b/absl/base/internal/unique_small_name_test.cc
new file mode 100644
index 0000000..ff8c2b3
--- /dev/null
+++ b/absl/base/internal/unique_small_name_test.cc
@@ -0,0 +1,77 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gtest/gtest.h"
+#include "absl/base/optimization.h"
+#include "absl/strings/string_view.h"
+
+// This test by itself does not do anything fancy, but it serves as binary I can
+// query in shell test.
+
+namespace {
+
+template <class T>
+void DoNotOptimize(const T& var) {
+#ifdef __GNUC__
+  asm volatile("" : "+m"(const_cast<T&>(var)));
+#else
+  std::cout << (void*)&var;
+#endif
+}
+
+int very_long_int_variable_name ABSL_INTERNAL_UNIQUE_SMALL_NAME() = 0;
+char very_long_str_variable_name[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = "abc";
+
+TEST(UniqueSmallName, NonAutomaticVar) {
+  EXPECT_EQ(very_long_int_variable_name, 0);
+  EXPECT_EQ(absl::string_view(very_long_str_variable_name), "abc");
+}
+
+int VeryLongFreeFunctionName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
+
+TEST(UniqueSmallName, FreeFunction) {
+  DoNotOptimize(&VeryLongFreeFunctionName);
+
+  EXPECT_EQ(VeryLongFreeFunctionName(), 456);
+}
+
+int VeryLongFreeFunctionName() { return 456; }
+
+struct VeryLongStructName {
+  explicit VeryLongStructName(int i);
+
+  int VeryLongMethodName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
+
+  static int VeryLongStaticMethodName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
+
+ private:
+  int fld;
+};
+
+TEST(UniqueSmallName, Struct) {
+  VeryLongStructName var(10);
+
+  DoNotOptimize(var);
+  DoNotOptimize(&VeryLongStructName::VeryLongMethodName);
+  DoNotOptimize(&VeryLongStructName::VeryLongStaticMethodName);
+
+  EXPECT_EQ(var.VeryLongMethodName(), 10);
+  EXPECT_EQ(VeryLongStructName::VeryLongStaticMethodName(), 123);
+}
+
+VeryLongStructName::VeryLongStructName(int i) : fld(i) {}
+int VeryLongStructName::VeryLongMethodName() { return fld; }
+int VeryLongStructName::VeryLongStaticMethodName() { return 123; }
+
+}  // namespace
diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc
index 593762b..1545288 100644
--- a/absl/base/internal/unscaledcycleclock.cc
+++ b/absl/base/internal/unscaledcycleclock.cc
@@ -21,12 +21,18 @@
 #endif
 
 #if defined(__powerpc__) || defined(__ppc__)
+#ifdef __GLIBC__
 #include <sys/platform/ppc.h>
+#elif defined(__FreeBSD__)
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#endif
 #endif
 
 #include "absl/base/internal/sysinfo.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 #if defined(__i386__)
@@ -56,11 +62,43 @@
 #elif defined(__powerpc__) || defined(__ppc__)
 
 int64_t UnscaledCycleClock::Now() {
+#ifdef __GLIBC__
   return __ppc_get_timebase();
+#else
+#ifdef __powerpc64__
+  int64_t tbr;
+  asm volatile("mfspr %0, 268" : "=r"(tbr));
+  return tbr;
+#else
+  int32_t tbu, tbl, tmp;
+  asm volatile(
+      "0:\n"
+      "mftbu %[hi32]\n"
+      "mftb %[lo32]\n"
+      "mftbu %[tmp]\n"
+      "cmpw %[tmp],%[hi32]\n"
+      "bne 0b\n"
+      : [ hi32 ] "=r"(tbu), [ lo32 ] "=r"(tbl), [ tmp ] "=r"(tmp));
+  return (static_cast<int64_t>(tbu) << 32) | tbl;
+#endif
+#endif
 }
 
 double UnscaledCycleClock::Frequency() {
+#ifdef __GLIBC__
   return __ppc_get_timebase_freq();
+#elif defined(__FreeBSD__)
+  static once_flag init_timebase_frequency_once;
+  static double timebase_frequency = 0.0;
+  base_internal::LowLevelCallOnce(&init_timebase_frequency_once, [&]() {
+    size_t length = sizeof(timebase_frequency);
+    sysctlbyname("kern.timecounter.tc.timebase.frequency", &timebase_frequency,
+                 &length, nullptr, 0);
+  });
+  return timebase_frequency;
+#else
+#error Must implement UnscaledCycleClock::Frequency()
+#endif
 }
 
 #elif defined(__aarch64__)
@@ -85,9 +123,7 @@
 
 #pragma intrinsic(__rdtsc)
 
-int64_t UnscaledCycleClock::Now() {
-  return __rdtsc();
-}
+int64_t UnscaledCycleClock::Now() { return __rdtsc(); }
 
 double UnscaledCycleClock::Frequency() {
   return base_internal::NominalCPUFrequency();
@@ -96,6 +132,7 @@
 #endif
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_USE_UNSCALED_CYCLECLOCK
diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h
index 2d361e9..82f2c87 100644
--- a/absl/base/internal/unscaledcycleclock.h
+++ b/absl/base/internal/unscaledcycleclock.h
@@ -15,8 +15,8 @@
 // UnscaledCycleClock
 //    An UnscaledCycleClock yields the value and frequency of a cycle counter
 //    that increments at a rate that is approximately constant.
-//    This class is for internal / whitelisted use only, you should consider
-//    using CycleClock instead.
+//    This class is for internal use only, you should consider using CycleClock
+//    instead.
 //
 // Notes:
 // The cycle counter frequency is not necessarily the core clock frequency.
@@ -86,6 +86,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 class UnscaledCycleClockWrapperForGetCurrentTime;
 }  // namespace time_internal
@@ -108,13 +109,14 @@
   // value.
   static double Frequency();
 
-  // Whitelisted friends.
+  // Allowed users
   friend class base_internal::CycleClock;
   friend class time_internal::UnscaledCycleClockWrapperForGetCurrentTime;
   friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency;
 };
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_USE_UNSCALED_CYCLECLOCK
diff --git a/absl/base/invoke_test.cc b/absl/base/invoke_test.cc
index 9074443..bcdef36 100644
--- a/absl/base/invoke_test.cc
+++ b/absl/base/invoke_test.cc
@@ -25,6 +25,7 @@
 #include "absl/strings/str_cat.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 namespace {
 
@@ -85,71 +86,73 @@
   int member;
 };
 
-// CallMaybeWithArg(f) resolves either to Invoke(f) or Invoke(f, 42), depending
+// CallMaybeWithArg(f) resolves either to invoke(f) or invoke(f, 42), depending
 // on which one is valid.
 template <typename F>
-decltype(Invoke(std::declval<const F&>())) CallMaybeWithArg(const F& f) {
-  return Invoke(f);
+decltype(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
+    const F& f) {
+  return base_internal::invoke(f);
 }
 
 template <typename F>
-decltype(Invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(const F& f) {
-  return Invoke(f, 42);
+decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
+    const F& f) {
+  return base_internal::invoke(f, 42);
 }
 
 TEST(InvokeTest, Function) {
-  EXPECT_EQ(1, Invoke(Function, 3, 2));
-  EXPECT_EQ(1, Invoke(&Function, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
 }
 
 TEST(InvokeTest, NonCopyableArgument) {
-  EXPECT_EQ(42, Invoke(Sink, make_unique<int>(42)));
+  EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
 }
 
 TEST(InvokeTest, NonCopyableResult) {
-  EXPECT_THAT(Invoke(Factory, 42), ::testing::Pointee(42));
+  EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
 }
 
-TEST(InvokeTest, VoidResult) {
-  Invoke(NoOp);
-}
+TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
 
 TEST(InvokeTest, ConstFunctor) {
-  EXPECT_EQ(1, Invoke(ConstFunctor(), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
 }
 
 TEST(InvokeTest, MutableFunctor) {
   MutableFunctor f;
-  EXPECT_EQ(1, Invoke(f, 3, 2));
-  EXPECT_EQ(1, Invoke(MutableFunctor(), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
 }
 
 TEST(InvokeTest, EphemeralFunctor) {
   EphemeralFunctor f;
-  EXPECT_EQ(1, Invoke(std::move(f), 3, 2));
-  EXPECT_EQ(1, Invoke(EphemeralFunctor(), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
 }
 
 TEST(InvokeTest, OverloadedFunctor) {
   OverloadedFunctor f;
   const OverloadedFunctor& cf = f;
 
-  EXPECT_EQ("&", Invoke(f));
-  EXPECT_EQ("& 42", Invoke(f, " 42"));
+  EXPECT_EQ("&", base_internal::invoke(f));
+  EXPECT_EQ("& 42", base_internal::invoke(f, " 42"));
 
-  EXPECT_EQ("const&", Invoke(cf));
-  EXPECT_EQ("const& 42", Invoke(cf, " 42"));
+  EXPECT_EQ("const&", base_internal::invoke(cf));
+  EXPECT_EQ("const& 42", base_internal::invoke(cf, " 42"));
 
-  EXPECT_EQ("&&", Invoke(std::move(f)));
-  EXPECT_EQ("&& 42", Invoke(std::move(f), " 42"));
+  EXPECT_EQ("&&", base_internal::invoke(std::move(f)));
+
+  OverloadedFunctor f2;
+  EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
 }
 
 TEST(InvokeTest, ReferenceWrapper) {
   ConstFunctor cf;
   MutableFunctor mf;
-  EXPECT_EQ(1, Invoke(std::cref(cf), 3, 2));
-  EXPECT_EQ(1, Invoke(std::ref(cf), 3, 2));
-  EXPECT_EQ(1, Invoke(std::ref(mf), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(std::cref(cf), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(std::ref(cf), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(std::ref(mf), 3, 2));
 }
 
 TEST(InvokeTest, MemberFunction) {
@@ -157,58 +160,62 @@
   std::unique_ptr<const Class> cp(new Class);
   std::unique_ptr<volatile Class> vp(new Class);
 
-  EXPECT_EQ(1, Invoke(&Class::Method, p, 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::Method, p.get(), 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::Method, *p, 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::RefMethod, p, 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::RefMethod, p.get(), 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::RefMethod, *p, 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::RefRefMethod, std::move(*p), 3, 2));  // NOLINT
-  EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, p, 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, p.get(), 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, *p, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::Method, p, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::Method, p.get(), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::Method, *p, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p.get(), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, *p, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::RefRefMethod, std::move(*p), 3,
+                                     2));  // NOLINT
+  EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p.get(), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, *p, 3, 2));
 
-  EXPECT_EQ(1, Invoke(&Class::ConstMethod, p, 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::ConstMethod, p.get(), 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::ConstMethod, *p, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p.get(), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *p, 3, 2));
 
-  EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp, 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp.get(), 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::ConstMethod, *cp, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp.get(), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *cp, 3, 2));
 
-  EXPECT_EQ(1, Invoke(&Class::VolatileMethod, p, 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::VolatileMethod, p.get(), 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::VolatileMethod, *p, 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::VolatileMethod, vp, 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::VolatileMethod, vp.get(), 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::VolatileMethod, *vp, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p.get(), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *p, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp, 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp.get(), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *vp, 3, 2));
 
-  EXPECT_EQ(1, Invoke(&Class::Method, make_unique<Class>(), 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<Class>(), 3, 2));
-  EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<const Class>(), 3, 2));
+  EXPECT_EQ(1,
+            base_internal::invoke(&Class::Method, make_unique<Class>(), 3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, make_unique<Class>(),
+                                     3, 2));
+  EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod,
+                                     make_unique<const Class>(), 3, 2));
 }
 
 TEST(InvokeTest, DataMember) {
   std::unique_ptr<Class> p(new Class{42});
   std::unique_ptr<const Class> cp(new Class{42});
-  EXPECT_EQ(42, Invoke(&Class::member, p));
-  EXPECT_EQ(42, Invoke(&Class::member, *p));
-  EXPECT_EQ(42, Invoke(&Class::member, p.get()));
+  EXPECT_EQ(42, base_internal::invoke(&Class::member, p));
+  EXPECT_EQ(42, base_internal::invoke(&Class::member, *p));
+  EXPECT_EQ(42, base_internal::invoke(&Class::member, p.get()));
 
-  Invoke(&Class::member, p) = 42;
-  Invoke(&Class::member, p.get()) = 42;
+  base_internal::invoke(&Class::member, p) = 42;
+  base_internal::invoke(&Class::member, p.get()) = 42;
 
-  EXPECT_EQ(42, Invoke(&Class::member, cp));
-  EXPECT_EQ(42, Invoke(&Class::member, *cp));
-  EXPECT_EQ(42, Invoke(&Class::member, cp.get()));
+  EXPECT_EQ(42, base_internal::invoke(&Class::member, cp));
+  EXPECT_EQ(42, base_internal::invoke(&Class::member, *cp));
+  EXPECT_EQ(42, base_internal::invoke(&Class::member, cp.get()));
 }
 
 TEST(InvokeTest, FlipFlop) {
   FlipFlop obj = {42};
   // This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
   // ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
-  EXPECT_EQ(42, Invoke(&FlipFlop::ConstMethod, obj));
-  EXPECT_EQ(42, Invoke(&FlipFlop::member, obj));
+  EXPECT_EQ(42, base_internal::invoke(&FlipFlop::ConstMethod, obj));
+  EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
 }
 
 TEST(InvokeTest, SfinaeFriendly) {
@@ -218,4 +225,5 @@
 
 }  // namespace
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/log_severity.cc b/absl/base/log_severity.cc
index 02a2a48..72312af 100644
--- a/absl/base/log_severity.cc
+++ b/absl/base/log_severity.cc
@@ -17,9 +17,11 @@
 #include <ostream>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 std::ostream& operator<<(std::ostream& os, absl::LogSeverity s) {
   if (s == absl::NormalizeLogSeverity(s)) return os << absl::LogSeverityName(s);
   return os << "absl::LogSeverity(" << static_cast<int>(s) << ")";
 }
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h
index f5dc7d2..045f17f 100644
--- a/absl/base/log_severity.h
+++ b/absl/base/log_severity.h
@@ -12,29 +12,57 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
-#define ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
+#ifndef ABSL_BASE_LOG_SEVERITY_H_
+#define ABSL_BASE_LOG_SEVERITY_H_
 
 #include <array>
 #include <ostream>
 
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
-// Four severity levels are defined.  Logging APIs should terminate the program
+// absl::LogSeverity
+//
+// Four severity levels are defined. Logging APIs should terminate the program
 // when a message is logged at severity `kFatal`; the other levels have no
 // special semantics.
 //
-// Abseil flags may be defined with type `LogSeverity`.  Dependency layering
-// constraints require that the `AbslParseFlag` overload be declared and defined
-// in the flags module rather than here.  The `AbslUnparseFlag` overload is
-// defined there too for consistency.
+// Values other than the four defined levels (e.g. produced by `static_cast`)
+// are valid, but their semantics when passed to a function, macro, or flag
+// depend on the function, macro, or flag. The usual behavior is to normalize
+// such values to a defined severity level, however in some cases values other
+// than the defined levels are useful for comparison.
 //
-// The parser accepts arbitrary integers (as if the type were `int`).  It also
-// accepts each named enumerator, without regard for case, with or without the
-// leading 'k'.  For example: "kInfo", "INFO", and "info" all parse to the value
-// `absl::LogSeverity::kInfo`.
+// Exmaple:
+//
+//   // Effectively disables all logging:
+//   SetMinLogLevel(static_cast<absl::LogSeverity>(100));
+//
+// Abseil flags may be defined with type `LogSeverity`. Dependency layering
+// constraints require that the `AbslParseFlag()` overload be declared and
+// defined in the flags library itself rather than here. The `AbslUnparseFlag()`
+// overload is defined there as well for consistency.
+//
+// absl::LogSeverity Flag String Representation
+//
+// An `absl::LogSeverity` has a string representation used for parsing
+// command-line flags based on the enumerator name (e.g. `kFatal`) or
+// its unprefixed name (without the `k`) in any case-insensitive form. (E.g.
+// "FATAL", "fatal" or "Fatal" are all valid.) Unparsing such flags produces an
+// unprefixed string representation in all caps (e.g. "FATAL") or an integer.
+//
+// Additionally, the parser accepts arbitrary integers (as if the type were
+// `int`).
+//
+// Examples:
+//
+//   --my_log_level=kInfo
+//   --my_log_level=INFO
+//   --my_log_level=info
+//   --my_log_level=0
 //
 // Unparsing a flag produces the same result as `absl::LogSeverityName()` for
 // the standard levels and a base-ten integer otherwise.
@@ -45,6 +73,8 @@
   kFatal = 3,
 };
 
+// LogSeverities()
+//
 // Returns an iterable of all standard `absl::LogSeverity` values, ordered from
 // least to most severe.
 constexpr std::array<absl::LogSeverity, 4> LogSeverities() {
@@ -52,6 +82,8 @@
            absl::LogSeverity::kError, absl::LogSeverity::kFatal}};
 }
 
+// LogSeverityName()
+//
 // Returns the all-caps string representation (e.g. "INFO") of the specified
 // severity level if it is one of the standard levels and "UNKNOWN" otherwise.
 constexpr const char* LogSeverityName(absl::LogSeverity s) {
@@ -64,6 +96,8 @@
                          : s == absl::LogSeverity::kFatal ? "FATAL" : "UNKNOWN";
 }
 
+// NormalizeLogSeverity()
+//
 // Values less than `kInfo` normalize to `kInfo`; values greater than `kFatal`
 // normalize to `kError` (**NOT** `kFatal`).
 constexpr absl::LogSeverity NormalizeLogSeverity(absl::LogSeverity s) {
@@ -75,10 +109,13 @@
   return absl::NormalizeLogSeverity(static_cast<absl::LogSeverity>(s));
 }
 
+// operator<<
+//
 // The exact representation of a streamed `absl::LogSeverity` is deliberately
 // unspecified; do not rely on it.
 std::ostream& operator<<(std::ostream& os, absl::LogSeverity s);
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
+#endif  // ABSL_BASE_LOG_SEVERITY_H_
diff --git a/absl/base/log_severity_test.cc b/absl/base/log_severity_test.cc
index 1e3aafa..2c6872b 100644
--- a/absl/base/log_severity_test.cc
+++ b/absl/base/log_severity_test.cc
@@ -24,6 +24,7 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/flags/internal/flag.h"
 #include "absl/flags/marshalling.h"
 #include "absl/strings/str_cat.h"
 
@@ -51,6 +52,10 @@
               Eq("absl::LogSeverity(4)"));
 }
 
+static_assert(
+    absl::flags_internal::FlagUseOneWordStorage<absl::LogSeverity>::value,
+    "Flags of type absl::LogSeverity ought to be lock-free.");
+
 using ParseFlagFromOutOfRangeIntegerTest = TestWithParam<int64_t>;
 INSTANTIATE_TEST_SUITE_P(
     Instantiation, ParseFlagFromOutOfRangeIntegerTest,
diff --git a/absl/base/macros.h b/absl/base/macros.h
index d481288..3e085a9 100644
--- a/absl/base/macros.h
+++ b/absl/base/macros.h
@@ -31,6 +31,8 @@
 #include <cassert>
 #include <cstddef>
 
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/base/optimization.h"
 #include "absl/base/port.h"
 
@@ -43,127 +45,22 @@
   (sizeof(::absl::macros_internal::ArraySizeHelper(array)))
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace macros_internal {
 // Note: this internal template function declaration is used by ABSL_ARRAYSIZE.
 // The function doesn't need a definition, as we only use its type.
 template <typename T, size_t N>
 auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
 }  // namespace macros_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-// kLinkerInitialized
-//
-// An enum used only as a constructor argument to indicate that a variable has
-// static storage duration, and that the constructor should do nothing to its
-// state. Use of this macro indicates to the reader that it is legal to
-// declare a static instance of the class, provided the constructor is given
-// the absl::base_internal::kLinkerInitialized argument.
-//
-// Normally, it is unsafe to declare a static variable that has a constructor or
-// a destructor because invocation order is undefined. However, if the type can
-// be zero-initialized (which the loader does for static variables) into a valid
-// state and the type's destructor does not affect storage, then a constructor
-// for static initialization can be declared.
-//
-// Example:
-//       // Declaration
-//       explicit MyClass(absl::base_internal:LinkerInitialized x) {}
-//
-//       // Invocation
-//       static MyClass my_global(absl::base_internal::kLinkerInitialized);
-namespace absl {
-namespace base_internal {
-enum LinkerInitialized {
-  kLinkerInitialized = 0,
-};
-}  // namespace base_internal
-}  // namespace absl
-
-// ABSL_FALLTHROUGH_INTENDED
-//
-// Annotates implicit fall-through between switch labels, allowing a case to
-// indicate intentional fallthrough and turn off warnings about any lack of a
-// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by
-// a semicolon and can be used in most places where `break` can, provided that
-// no statements exist between it and the next switch label.
-//
-// Example:
-//
-//  switch (x) {
-//    case 40:
-//    case 41:
-//      if (truth_is_out_there) {
-//        ++x;
-//        ABSL_FALLTHROUGH_INTENDED;  // Use instead of/along with annotations
-//                                    // in comments
-//      } else {
-//        return x;
-//      }
-//    case 42:
-//      ...
-//
-// Notes: when compiled with clang in C++11 mode, the ABSL_FALLTHROUGH_INTENDED
-// macro is expanded to the [[clang::fallthrough]] attribute, which is analysed
-// when  performing switch labels fall-through diagnostic
-// (`-Wimplicit-fallthrough`). See clang documentation on language extensions
-// for details:
-// http://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough
-//
-// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro
-// has no effect on diagnostics. In any case this macro has no effect on runtime
-// behavior and performance of code.
-#ifdef ABSL_FALLTHROUGH_INTENDED
-#error "ABSL_FALLTHROUGH_INTENDED should not be defined."
-#endif
-
-// TODO(zhangxy): Use c++17 standard [[fallthrough]] macro, when supported.
-#if defined(__clang__) && defined(__has_warning)
-#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
-#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]]
-#endif
-#elif defined(__GNUC__) && __GNUC__ >= 7
-#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
-#endif
-
-#ifndef ABSL_FALLTHROUGH_INTENDED
-#define ABSL_FALLTHROUGH_INTENDED \
-  do {                            \
-  } while (0)
-#endif
-
-// ABSL_DEPRECATED()
-//
-// Marks a deprecated class, struct, enum, function, method and variable
-// declarations. The macro argument is used as a custom diagnostic message (e.g.
-// suggestion of a better alternative).
-//
-// Examples:
-//
-//   class ABSL_DEPRECATED("Use Bar instead") Foo {...};
-//
-//   ABSL_DEPRECATED("Use Baz() instead") void Bar() {...}
-//
-//   template <typename T>
-//   ABSL_DEPRECATED("Use DoThat() instead")
-//   void DoThis();
-//
-// Every usage of a deprecated entity will trigger a warning when compiled with
-// clang's `-Wdeprecated-declarations` option. This option is turned off by
-// default, but the warnings will be reported by clang-tidy.
-#if defined(__clang__) && __cplusplus >= 201103L
-#define ABSL_DEPRECATED(message) __attribute__((deprecated(message)))
-#endif
-
-#ifndef ABSL_DEPRECATED
-#define ABSL_DEPRECATED(message)
-#endif
-
 // ABSL_BAD_CALL_IF()
 //
 // Used on a function overload to trap bad calls: any call that matches the
 // overload will cause a compile-time error. This macro uses a clang-specific
 // "enable_if" attribute, as described at
-// http://clang.llvm.org/docs/AttributeReference.html#enable-if
+// https://clang.llvm.org/docs/AttributeReference.html#enable-if
 //
 // Overloads which use this macro should be bracketed by
 // `#ifdef ABSL_BAD_CALL_IF`.
@@ -176,12 +73,9 @@
 //     ABSL_BAD_CALL_IF(c <= -1 || c > 255,
 //                       "'c' must have the value of an unsigned char or EOF");
 //   #endif // ABSL_BAD_CALL_IF
-
-#if defined(__clang__)
-# if __has_attribute(enable_if)
-#  define ABSL_BAD_CALL_IF(expr, msg) \
-    __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg)))
-# endif
+#if ABSL_HAVE_ATTRIBUTE(enable_if)
+#define ABSL_BAD_CALL_IF(expr, msg) \
+  __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg)))
 #endif
 
 // ABSL_ASSERT()
@@ -205,6 +99,41 @@
                              : [] { assert(false && #expr); }())  // NOLINT
 #endif
 
+// `ABSL_INTERNAL_HARDENING_ABORT()` controls how `ABSL_HARDENING_ASSERT()`
+// aborts the program in release mode (when NDEBUG is defined). The
+// implementation should abort the program as quickly as possible and ideally it
+// should not be possible to ignore the abort request.
+#if (ABSL_HAVE_BUILTIN(__builtin_trap) &&         \
+     ABSL_HAVE_BUILTIN(__builtin_unreachable)) || \
+    (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_INTERNAL_HARDENING_ABORT() \
+  do {                                  \
+    __builtin_trap();                   \
+    __builtin_unreachable();            \
+  } while (false)
+#else
+#define ABSL_INTERNAL_HARDENING_ABORT() abort()
+#endif
+
+// ABSL_HARDENING_ASSERT()
+//
+// `ABSL_HARDENING_ASSERT()` is like `ABSL_ASSERT()`, but used to implement
+// runtime assertions that should be enabled in hardened builds even when
+// `NDEBUG` is defined.
+//
+// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT()` is identical to
+// `ABSL_ASSERT()`.
+//
+// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on
+// hardened mode.
+#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
+#define ABSL_HARDENING_ASSERT(expr)                 \
+  (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
+                             : [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
+#else
+#define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr)
+#endif
+
 #ifdef ABSL_HAVE_EXCEPTIONS
 #define ABSL_INTERNAL_TRY try
 #define ABSL_INTERNAL_CATCH_ANY catch (...)
@@ -215,4 +144,15 @@
 #define ABSL_INTERNAL_RETHROW do {} while (false)
 #endif  // ABSL_HAVE_EXCEPTIONS
 
+// `ABSL_INTERNAL_UNREACHABLE` is an unreachable statement.  A program which
+// reaches one has undefined behavior, and the compiler may optimize
+// accordingly.
+#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
+#define ABSL_INTERNAL_UNREACHABLE __builtin_unreachable()
+#elif defined(_MSC_VER)
+#define ABSL_INTERNAL_UNREACHABLE __assume(0)
+#else
+#define ABSL_INTERNAL_UNREACHABLE
+#endif
+
 #endif  // ABSL_BASE_MACROS_H_
diff --git a/absl/base/optimization.h b/absl/base/optimization.h
index 0dcbef3..6332b62 100644
--- a/absl/base/optimization.h
+++ b/absl/base/optimization.h
@@ -22,13 +22,15 @@
 #ifndef ABSL_BASE_OPTIMIZATION_H_
 #define ABSL_BASE_OPTIMIZATION_H_
 
+#include <assert.h>
+
 #include "absl/base/config.h"
 
 // ABSL_BLOCK_TAIL_CALL_OPTIMIZATION
 //
-// Instructs the compiler to avoid optimizing tail-call recursion. Use of this
-// macro is useful when you wish to preserve the existing function order within
-// a stack trace for logging, debugging, or profiling purposes.
+// Instructs the compiler to avoid optimizing tail-call recursion. This macro is
+// useful when you wish to preserve the existing function order within a stack
+// trace for logging, debugging, or profiling purposes.
 //
 // Example:
 //
@@ -171,11 +173,71 @@
 // to yield performance improvements.
 #if ABSL_HAVE_BUILTIN(__builtin_expect) || \
     (defined(__GNUC__) && !defined(__clang__))
-#define ABSL_PREDICT_FALSE(x) (__builtin_expect(x, 0))
-#define ABSL_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+#define ABSL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false))
+#define ABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true))
 #else
 #define ABSL_PREDICT_FALSE(x) (x)
 #define ABSL_PREDICT_TRUE(x) (x)
 #endif
 
+// ABSL_INTERNAL_ASSUME(cond)
+// Informs the compiler that a condition is always true and that it can assume
+// it to be true for optimization purposes. The call has undefined behavior if
+// the condition is false.
+// In !NDEBUG mode, the condition is checked with an assert().
+// NOTE: The expression must not have side effects, as it will only be evaluated
+// in some compilation modes and not others.
+//
+// Example:
+//
+//   int x = ...;
+//   ABSL_INTERNAL_ASSUME(x >= 0);
+//   // The compiler can optimize the division to a simple right shift using the
+//   // assumption specified above.
+//   int y = x / 16;
+//
+#if !defined(NDEBUG)
+#define ABSL_INTERNAL_ASSUME(cond) assert(cond)
+#elif ABSL_HAVE_BUILTIN(__builtin_assume)
+#define ABSL_INTERNAL_ASSUME(cond) __builtin_assume(cond)
+#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
+#define ABSL_INTERNAL_ASSUME(cond)        \
+  do {                                    \
+    if (!(cond)) __builtin_unreachable(); \
+  } while (0)
+#elif defined(_MSC_VER)
+#define ABSL_INTERNAL_ASSUME(cond) __assume(cond)
+#else
+#define ABSL_INTERNAL_ASSUME(cond)      \
+  do {                                  \
+    static_cast<void>(false && (cond)); \
+  } while (0)
+#endif
+
+// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)
+// This macro forces small unique name on a static file level symbols like
+// static local variables or static functions. This is intended to be used in
+// macro definitions to optimize the cost of generated code. Do NOT use it on
+// symbols exported from translation unit since it may cause a link time
+// conflict.
+//
+// Example:
+//
+// #define MY_MACRO(txt)
+// namespace {
+//  char VeryVeryLongVarName[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = txt;
+//  const char* VeryVeryLongFuncName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
+//  const char* VeryVeryLongFuncName() { return txt; }
+// }
+//
+
+#if defined(__GNUC__)
+#define ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) #x
+#define ABSL_INTERNAL_UNIQUE_SMALL_NAME1(x) ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x)
+#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
+  asm(ABSL_INTERNAL_UNIQUE_SMALL_NAME1(.absl.__COUNTER__))
+#else
+#define ABSL_INTERNAL_UNIQUE_SMALL_NAME()
+#endif
+
 #endif  // ABSL_BASE_OPTIMIZATION_H_
diff --git a/absl/base/optimization_test.cc b/absl/base/optimization_test.cc
new file mode 100644
index 0000000..e83369f
--- /dev/null
+++ b/absl/base/optimization_test.cc
@@ -0,0 +1,129 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/optimization.h"
+
+#include "gtest/gtest.h"
+#include "absl/types/optional.h"
+
+namespace {
+
+// Tests for the ABSL_PREDICT_TRUE and ABSL_PREDICT_FALSE macros.
+// The tests only verify that the macros are functionally correct - i.e. code
+// behaves as if they weren't used. They don't try to check their impact on
+// optimization.
+
+TEST(PredictTest, PredictTrue) {
+  EXPECT_TRUE(ABSL_PREDICT_TRUE(true));
+  EXPECT_FALSE(ABSL_PREDICT_TRUE(false));
+  EXPECT_TRUE(ABSL_PREDICT_TRUE(1 == 1));
+  EXPECT_FALSE(ABSL_PREDICT_TRUE(1 == 2));
+
+  if (ABSL_PREDICT_TRUE(false)) ADD_FAILURE();
+  if (!ABSL_PREDICT_TRUE(true)) ADD_FAILURE();
+
+  EXPECT_TRUE(ABSL_PREDICT_TRUE(true) && true);
+  EXPECT_TRUE(ABSL_PREDICT_TRUE(true) || false);
+}
+
+TEST(PredictTest, PredictFalse) {
+  EXPECT_TRUE(ABSL_PREDICT_FALSE(true));
+  EXPECT_FALSE(ABSL_PREDICT_FALSE(false));
+  EXPECT_TRUE(ABSL_PREDICT_FALSE(1 == 1));
+  EXPECT_FALSE(ABSL_PREDICT_FALSE(1 == 2));
+
+  if (ABSL_PREDICT_FALSE(false)) ADD_FAILURE();
+  if (!ABSL_PREDICT_FALSE(true)) ADD_FAILURE();
+
+  EXPECT_TRUE(ABSL_PREDICT_FALSE(true) && true);
+  EXPECT_TRUE(ABSL_PREDICT_FALSE(true) || false);
+}
+
+TEST(PredictTest, OneEvaluation) {
+  // Verify that the expression is only evaluated once.
+  int x = 0;
+  if (ABSL_PREDICT_TRUE((++x) == 0)) ADD_FAILURE();
+  EXPECT_EQ(x, 1);
+  if (ABSL_PREDICT_FALSE((++x) == 0)) ADD_FAILURE();
+  EXPECT_EQ(x, 2);
+}
+
+TEST(PredictTest, OperatorOrder) {
+  // Verify that operator order inside and outside the macro behaves well.
+  // These would fail for a naive '#define ABSL_PREDICT_TRUE(x) x'
+  EXPECT_TRUE(ABSL_PREDICT_TRUE(1 && 2) == true);
+  EXPECT_TRUE(ABSL_PREDICT_FALSE(1 && 2) == true);
+  EXPECT_TRUE(!ABSL_PREDICT_TRUE(1 == 2));
+  EXPECT_TRUE(!ABSL_PREDICT_FALSE(1 == 2));
+}
+
+TEST(PredictTest, Pointer) {
+  const int x = 3;
+  const int *good_intptr = &x;
+  const int *null_intptr = nullptr;
+  EXPECT_TRUE(ABSL_PREDICT_TRUE(good_intptr));
+  EXPECT_FALSE(ABSL_PREDICT_TRUE(null_intptr));
+  EXPECT_TRUE(ABSL_PREDICT_FALSE(good_intptr));
+  EXPECT_FALSE(ABSL_PREDICT_FALSE(null_intptr));
+}
+
+TEST(PredictTest, Optional) {
+  // Note: An optional's truth value is the value's existence, not its truth.
+  absl::optional<bool> has_value(false);
+  absl::optional<bool> no_value;
+  EXPECT_TRUE(ABSL_PREDICT_TRUE(has_value));
+  EXPECT_FALSE(ABSL_PREDICT_TRUE(no_value));
+  EXPECT_TRUE(ABSL_PREDICT_FALSE(has_value));
+  EXPECT_FALSE(ABSL_PREDICT_FALSE(no_value));
+}
+
+class ImplictlyConvertibleToBool {
+ public:
+  explicit ImplictlyConvertibleToBool(bool value) : value_(value) {}
+  operator bool() const {  // NOLINT(google-explicit-constructor)
+    return value_;
+  }
+
+ private:
+  bool value_;
+};
+
+TEST(PredictTest, ImplicitBoolConversion) {
+  const ImplictlyConvertibleToBool is_true(true);
+  const ImplictlyConvertibleToBool is_false(false);
+  if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
+  if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
+  if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
+  if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
+}
+
+class ExplictlyConvertibleToBool {
+ public:
+  explicit ExplictlyConvertibleToBool(bool value) : value_(value) {}
+  explicit operator bool() const { return value_; }
+
+ private:
+  bool value_;
+};
+
+TEST(PredictTest, ExplicitBoolConversion) {
+  const ExplictlyConvertibleToBool is_true(true);
+  const ExplictlyConvertibleToBool is_false(false);
+  if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
+  if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
+  if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
+  if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
+}
+
+}  // namespace
diff --git a/absl/base/options.h b/absl/base/options.h
new file mode 100644
index 0000000..230bf1e
--- /dev/null
+++ b/absl/base/options.h
@@ -0,0 +1,238 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: options.h
+// -----------------------------------------------------------------------------
+//
+// This file contains Abseil configuration options for setting specific
+// implementations instead of letting Abseil determine which implementation to
+// use at compile-time. Setting these options may be useful for package or build
+// managers who wish to guarantee ABI stability within binary builds (which are
+// otherwise difficult to enforce).
+//
+// *** IMPORTANT NOTICE FOR PACKAGE MANAGERS:  It is important that
+// maintainers of package managers who wish to package Abseil read and
+// understand this file! ***
+//
+// Abseil contains a number of possible configuration endpoints, based on
+// parameters such as the detected platform, language version, or command-line
+// flags used to invoke the underlying binary. As is the case with all
+// libraries, binaries which contain Abseil code must ensure that separate
+// packages use the same compiled copy of Abseil to avoid a diamond dependency
+// problem, which can occur if two packages built with different Abseil
+// configuration settings are linked together. Diamond dependency problems in
+// C++ may manifest as violations to the One Definition Rule (ODR) (resulting in
+// linker errors), or undefined behavior (resulting in crashes).
+//
+// Diamond dependency problems can be avoided if all packages utilize the same
+// exact version of Abseil. Building from source code with the same compilation
+// parameters is the easiest way to avoid such dependency problems. However, for
+// package managers who cannot control such compilation parameters, we are
+// providing the file to allow you to inject ABI (Application Binary Interface)
+// stability across builds. Settings options in this file will neither change
+// API nor ABI, providing a stable copy of Abseil between packages.
+//
+// Care must be taken to keep options within these configurations isolated
+// from any other dynamic settings, such as command-line flags which could alter
+// these options. This file is provided specifically to help build and package
+// managers provide a stable copy of Abseil within their libraries and binaries;
+// other developers should not have need to alter the contents of this file.
+//
+// -----------------------------------------------------------------------------
+// Usage
+// -----------------------------------------------------------------------------
+//
+// For any particular package release, set the appropriate definitions within
+// this file to whatever value makes the most sense for your package(s). Note
+// that, by default, most of these options, at the moment, affect the
+// implementation of types; future options may affect other implementation
+// details.
+//
+// NOTE: the defaults within this file all assume that Abseil can select the
+// proper Abseil implementation at compile-time, which will not be sufficient
+// to guarantee ABI stability to package managers.
+
+#ifndef ABSL_BASE_OPTIONS_H_
+#define ABSL_BASE_OPTIONS_H_
+
+// Include a standard library header to allow configuration based on the
+// standard library in use.
+#ifdef __cplusplus
+#include <ciso646>
+#endif
+
+// -----------------------------------------------------------------------------
+// Type Compatibility Options
+// -----------------------------------------------------------------------------
+//
+// ABSL_OPTION_USE_STD_ANY
+//
+// This option controls whether absl::any is implemented as an alias to
+// std::any, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation.  This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::any.  This requires that all code
+// using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::any is available.  This option is
+// useful when you are building your entire program, including all of its
+// dependencies, from source.  It should not be used otherwise -- for example,
+// if you are distributing Abseil in a binary package manager -- since in
+// mode 2, absl::any will name a different type, with a different mangled name
+// and binary layout, depending on the compiler flags passed by the end user.
+// For more info, see https://abseil.io/about/design/dropin-types.
+//
+// User code should not inspect this macro.  To check in the preprocessor if
+// absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY.
+
+#define ABSL_OPTION_USE_STD_ANY 2
+
+
+// ABSL_OPTION_USE_STD_OPTIONAL
+//
+// This option controls whether absl::optional is implemented as an alias to
+// std::optional, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation.  This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::optional.  This requires that all
+// code using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::optional is available.  This option
+// is useful when you are building your program from source.  It should not be
+// used otherwise -- for example, if you are distributing Abseil in a binary
+// package manager -- since in mode 2, absl::optional will name a different
+// type, with a different mangled name and binary layout, depending on the
+// compiler flags passed by the end user.  For more info, see
+// https://abseil.io/about/design/dropin-types.
+
+// User code should not inspect this macro.  To check in the preprocessor if
+// absl::optional is a typedef of std::optional, use the feature macro
+// ABSL_USES_STD_OPTIONAL.
+
+#define ABSL_OPTION_USE_STD_OPTIONAL 2
+
+
+// ABSL_OPTION_USE_STD_STRING_VIEW
+//
+// This option controls whether absl::string_view is implemented as an alias to
+// std::string_view, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation.  This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::string_view.  This requires that
+// all code using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::string_view is available.  This
+// option is useful when you are building your program from source.  It should
+// not be used otherwise -- for example, if you are distributing Abseil in a
+// binary package manager -- since in mode 2, absl::string_view will name a
+// different type, with a different mangled name and binary layout, depending on
+// the compiler flags passed by the end user.  For more info, see
+// https://abseil.io/about/design/dropin-types.
+//
+// User code should not inspect this macro.  To check in the preprocessor if
+// absl::string_view is a typedef of std::string_view, use the feature macro
+// ABSL_USES_STD_STRING_VIEW.
+
+#define ABSL_OPTION_USE_STD_STRING_VIEW 2
+
+// ABSL_OPTION_USE_STD_VARIANT
+//
+// This option controls whether absl::variant is implemented as an alias to
+// std::variant, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation.  This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::variant.  This requires that all
+// code using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::variant is available.  This option
+// is useful when you are building your program from source.  It should not be
+// used otherwise -- for example, if you are distributing Abseil in a binary
+// package manager -- since in mode 2, absl::variant will name a different
+// type, with a different mangled name and binary layout, depending on the
+// compiler flags passed by the end user.  For more info, see
+// https://abseil.io/about/design/dropin-types.
+//
+// User code should not inspect this macro.  To check in the preprocessor if
+// absl::variant is a typedef of std::variant, use the feature macro
+// ABSL_USES_STD_VARIANT.
+
+#define ABSL_OPTION_USE_STD_VARIANT 2
+
+
+// ABSL_OPTION_USE_INLINE_NAMESPACE
+// ABSL_OPTION_INLINE_NAMESPACE_NAME
+//
+// These options controls whether all entities in the absl namespace are
+// contained within an inner inline namespace.  This does not affect the
+// user-visible API of Abseil, but it changes the mangled names of all symbols.
+//
+// This can be useful as a version tag if you are distributing Abseil in
+// precompiled form.  This will prevent a binary library build of Abseil with
+// one inline namespace being used with headers configured with a different
+// inline namespace name.  Binary packagers are reminded that Abseil does not
+// guarantee any ABI stability in Abseil, so any update of Abseil or
+// configuration change in such a binary package should be combined with a
+// new, unique value for the inline namespace name.
+//
+// A value of 0 means not to use inline namespaces.
+//
+// A value of 1 means to use an inline namespace with the given name inside
+// namespace absl.  If this is set, ABSL_OPTION_INLINE_NAMESPACE_NAME must also
+// be changed to a new, unique identifier name.  In particular "head" is not
+// allowed.
+
+#define ABSL_OPTION_USE_INLINE_NAMESPACE 0
+#define ABSL_OPTION_INLINE_NAMESPACE_NAME head
+
+// ABSL_OPTION_HARDENED
+//
+// This option enables a "hardened" build in release mode (in this context,
+// release mode is defined as a build where the `NDEBUG` macro is defined).
+//
+// A value of 0 means that "hardened" mode is not enabled.
+//
+// A value of 1 means that "hardened" mode is enabled.
+//
+// Hardened builds have additional security checks enabled when `NDEBUG` is
+// defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a
+// no-op, as well as disabling other bespoke program consistency checks. By
+// defining ABSL_OPTION_HARDENED to 1, a select set of checks remain enabled in
+// release mode. These checks guard against programming errors that may lead to
+// security vulnerabilities. In release mode, when one of these programming
+// errors is encountered, the program will immediately abort, possibly without
+// any attempt at logging.
+//
+// The checks enabled by this option are not free; they do incur runtime cost.
+//
+// The checks enabled by this option are always active when `NDEBUG` is not
+// defined, even in the case when ABSL_OPTION_HARDENED is defined to 0. The
+// checks enabled by this option may abort the program in a different way and
+// log additional information when `NDEBUG` is not defined.
+
+#define ABSL_OPTION_HARDENED 0
+
+#endif  // ABSL_BASE_OPTIONS_H_
diff --git a/absl/base/policy_checks.h b/absl/base/policy_checks.h
index 699fb1a..06b3243 100644
--- a/absl/base/policy_checks.h
+++ b/absl/base/policy_checks.h
@@ -41,7 +41,7 @@
 #endif
 
 // -----------------------------------------------------------------------------
-// Compiler Check
+// Toolchain Check
 // -----------------------------------------------------------------------------
 
 // We support MSVC++ 14.0 update 2 and later.
@@ -82,16 +82,6 @@
 // Standard Library Check
 // -----------------------------------------------------------------------------
 
-// We have chosen glibc 2.12 as the minimum as it was tagged for release
-// in May, 2010 and includes some functionality used in Google software
-// (for instance pthread_setname_np):
-// https://sourceware.org/ml/libc-alpha/2010-05/msg00000.html
-#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
-#if !__GLIBC_PREREQ(2, 12)
-#error "Minimum required version of glibc is 2.12."
-#endif
-#endif
-
 #if defined(_STLPORT_VERSION)
 #error "STLPort is not supported."
 #endif
diff --git a/absl/base/spinlock_test_common.cc b/absl/base/spinlock_test_common.cc
index 84fc4da..dee266e 100644
--- a/absl/base/spinlock_test_common.cc
+++ b/absl/base/spinlock_test_common.cc
@@ -20,10 +20,12 @@
 #include <limits>
 #include <random>
 #include <thread>  // NOLINT(build/c++11)
+#include <type_traits>
 #include <vector>
 
 #include "gtest/gtest.h"
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/low_level_scheduling.h"
 #include "absl/base/internal/scheduling_mode.h"
 #include "absl/base/internal/spinlock.h"
@@ -36,6 +38,7 @@
 constexpr int32_t kIters = 1000;
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // This is defined outside of anonymous namespace so that it can be
@@ -55,12 +58,10 @@
 static constexpr int kArrayLength = 10;
 static uint32_t values[kArrayLength];
 
-static SpinLock static_spinlock(base_internal::kLinkerInitialized);
-static SpinLock static_cooperative_spinlock(
-    base_internal::kLinkerInitialized,
-    base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL);
-static SpinLock static_noncooperative_spinlock(
-    base_internal::kLinkerInitialized, base_internal::SCHEDULE_KERNEL_ONLY);
+ABSL_CONST_INIT static SpinLock static_cooperative_spinlock(
+    absl::kConstInit, base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL);
+ABSL_CONST_INIT static SpinLock static_noncooperative_spinlock(
+    absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
 
 // Simple integer hash function based on the public domain lookup2 hash.
 // http://burtleburtle.net/bob/c/lookup2.c
@@ -104,6 +105,10 @@
   }
 }
 
+#ifndef ABSL_HAVE_THREAD_SANITIZER
+static_assert(std::is_trivially_destructible<SpinLock>(), "");
+#endif
+
 TEST(SpinLock, StackNonCooperativeDisablesScheduling) {
   SpinLock spinlock(base_internal::SCHEDULE_KERNEL_ONLY);
   spinlock.Lock();
@@ -190,10 +195,6 @@
   EXPECT_GT(expected_max_value_decoded, before_max_value_decoded);
 }
 
-TEST(SpinLockWithThreads, StaticSpinLock) {
-  ThreadedTest(&static_spinlock);
-}
-
 TEST(SpinLockWithThreads, StackSpinLock) {
   SpinLock spinlock;
   ThreadedTest(&spinlock);
@@ -266,4 +267,5 @@
 
 }  // namespace
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h
index f98af9f..e23fff1 100644
--- a/absl/base/thread_annotations.h
+++ b/absl/base/thread_annotations.h
@@ -34,15 +34,11 @@
 #ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_
 #define ABSL_BASE_THREAD_ANNOTATIONS_H_
 
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
 // TODO(mbonadei): Remove after the backward compatibility period.
 #include "absl/base/internal/thread_annotations.h"  // IWYU pragma: export
 
-#if defined(__clang__)
-#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) __attribute__((x))
-#else
-#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x)  // no-op
-#endif
-
 // ABSL_GUARDED_BY()
 //
 // Documents if a shared field or global variable needs to be protected by a
@@ -60,8 +56,11 @@
 //     int p1_ ABSL_GUARDED_BY(mu_);
 //     ...
 //   };
-#define ABSL_GUARDED_BY(x) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(guarded_by(x))
+#if ABSL_HAVE_ATTRIBUTE(guarded_by)
+#define ABSL_GUARDED_BY(x) __attribute__((guarded_by(x)))
+#else
+#define ABSL_GUARDED_BY(x)
+#endif
 
 // ABSL_PT_GUARDED_BY()
 //
@@ -83,8 +82,11 @@
 //   // `q_`, guarded by `mu1_`, points to a shared memory location that is
 //   // guarded by `mu2_`:
 //   int *q_ ABSL_GUARDED_BY(mu1_) ABSL_PT_GUARDED_BY(mu2_);
-#define ABSL_PT_GUARDED_BY(x) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(pt_guarded_by(x))
+#if ABSL_HAVE_ATTRIBUTE(pt_guarded_by)
+#define ABSL_PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x)))
+#else
+#define ABSL_PT_GUARDED_BY(x)
+#endif
 
 // ABSL_ACQUIRED_AFTER() / ABSL_ACQUIRED_BEFORE()
 //
@@ -101,11 +103,17 @@
 //
 //   Mutex m1_;
 //   Mutex m2_ ABSL_ACQUIRED_AFTER(m1_);
-#define ABSL_ACQUIRED_AFTER(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_after(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(acquired_after)
+#define ABSL_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
+#else
+#define ABSL_ACQUIRED_AFTER(...)
+#endif
 
-#define ABSL_ACQUIRED_BEFORE(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_before(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(acquired_before)
+#define ABSL_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
+#else
+#define ABSL_ACQUIRED_BEFORE(...)
+#endif
 
 // ABSL_EXCLUSIVE_LOCKS_REQUIRED() / ABSL_SHARED_LOCKS_REQUIRED()
 //
@@ -130,33 +138,50 @@
 //
 //   void foo() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
 //   void bar() const ABSL_SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
-#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...)   \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
-      exclusive_locks_required(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(exclusive_locks_required)
+#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \
+  __attribute__((exclusive_locks_required(__VA_ARGS__)))
+#else
+#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...)
+#endif
 
+#if ABSL_HAVE_ATTRIBUTE(shared_locks_required)
 #define ABSL_SHARED_LOCKS_REQUIRED(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_locks_required(__VA_ARGS__))
+  __attribute__((shared_locks_required(__VA_ARGS__)))
+#else
+#define ABSL_SHARED_LOCKS_REQUIRED(...)
+#endif
 
 // ABSL_LOCKS_EXCLUDED()
 //
 // Documents the locks acquired in the body of the function. These locks
 // cannot be held when calling this function (as Abseil's `Mutex` locks are
 // non-reentrant).
-#define ABSL_LOCKS_EXCLUDED(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(locks_excluded(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(locks_excluded)
+#define ABSL_LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
+#else
+#define ABSL_LOCKS_EXCLUDED(...)
+#endif
 
 // ABSL_LOCK_RETURNED()
 //
 // Documents a function that returns a mutex without acquiring it.  For example,
 // a public getter method that returns a pointer to a private mutex should
 // be annotated with ABSL_LOCK_RETURNED.
-#define ABSL_LOCK_RETURNED(x) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lock_returned(x))
+#if ABSL_HAVE_ATTRIBUTE(lock_returned)
+#define ABSL_LOCK_RETURNED(x) __attribute__((lock_returned(x)))
+#else
+#define ABSL_LOCK_RETURNED(x)
+#endif
 
 // ABSL_LOCKABLE
 //
 // Documents if a class/type is a lockable type (such as the `Mutex` class).
-#define ABSL_LOCKABLE ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lockable)
+#if ABSL_HAVE_ATTRIBUTE(lockable)
+#define ABSL_LOCKABLE __attribute__((lockable))
+#else
+#define ABSL_LOCKABLE
+#endif
 
 // ABSL_SCOPED_LOCKABLE
 //
@@ -165,30 +190,43 @@
 // acquired, and the destructor should use `UNLOCK_FUNCTION()` with no
 // arguments; the analysis will assume that the destructor unlocks whatever the
 // constructor locked.
-#define ABSL_SCOPED_LOCKABLE \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(scoped_lockable)
+#if ABSL_HAVE_ATTRIBUTE(scoped_lockable)
+#define ABSL_SCOPED_LOCKABLE __attribute__((scoped_lockable))
+#else
+#define ABSL_SCOPED_LOCKABLE
+#endif
 
 // ABSL_EXCLUSIVE_LOCK_FUNCTION()
 //
 // Documents functions that acquire a lock in the body of a function, and do
 // not release it.
-#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...)    \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
-      exclusive_lock_function(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(exclusive_lock_function)
+#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \
+  __attribute__((exclusive_lock_function(__VA_ARGS__)))
+#else
+#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...)
+#endif
 
 // ABSL_SHARED_LOCK_FUNCTION()
 //
 // Documents functions that acquire a shared (reader) lock in the body of a
 // function, and do not release it.
+#if ABSL_HAVE_ATTRIBUTE(shared_lock_function)
 #define ABSL_SHARED_LOCK_FUNCTION(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_lock_function(__VA_ARGS__))
+  __attribute__((shared_lock_function(__VA_ARGS__)))
+#else
+#define ABSL_SHARED_LOCK_FUNCTION(...)
+#endif
 
 // ABSL_UNLOCK_FUNCTION()
 //
 // Documents functions that expect a lock to be held on entry to the function,
 // and release it in the body of the function.
-#define ABSL_UNLOCK_FUNCTION(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(unlock_function(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(unlock_function)
+#define ABSL_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
+#else
+#define ABSL_UNLOCK_FUNCTION(...)
+#endif
 
 // ABSL_EXCLUSIVE_TRYLOCK_FUNCTION() / ABSL_SHARED_TRYLOCK_FUNCTION()
 //
@@ -198,31 +236,49 @@
 // success, or `false` for functions that return `false` on success. The second
 // argument specifies the mutex that is locked on success. If unspecified, this
 // mutex is assumed to be `this`.
+#if ABSL_HAVE_ATTRIBUTE(exclusive_trylock_function)
 #define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
-      exclusive_trylock_function(__VA_ARGS__))
+  __attribute__((exclusive_trylock_function(__VA_ARGS__)))
+#else
+#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...)
+#endif
 
-#define ABSL_SHARED_TRYLOCK_FUNCTION(...)    \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
-      shared_trylock_function(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(shared_trylock_function)
+#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \
+  __attribute__((shared_trylock_function(__VA_ARGS__)))
+#else
+#define ABSL_SHARED_TRYLOCK_FUNCTION(...)
+#endif
 
 // ABSL_ASSERT_EXCLUSIVE_LOCK() / ABSL_ASSERT_SHARED_LOCK()
 //
 // Documents functions that dynamically check to see if a lock is held, and fail
 // if it is not held.
+#if ABSL_HAVE_ATTRIBUTE(assert_exclusive_lock)
 #define ABSL_ASSERT_EXCLUSIVE_LOCK(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_exclusive_lock(__VA_ARGS__))
+  __attribute__((assert_exclusive_lock(__VA_ARGS__)))
+#else
+#define ABSL_ASSERT_EXCLUSIVE_LOCK(...)
+#endif
 
+#if ABSL_HAVE_ATTRIBUTE(assert_shared_lock)
 #define ABSL_ASSERT_SHARED_LOCK(...) \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_shared_lock(__VA_ARGS__))
+  __attribute__((assert_shared_lock(__VA_ARGS__)))
+#else
+#define ABSL_ASSERT_SHARED_LOCK(...)
+#endif
 
 // ABSL_NO_THREAD_SAFETY_ANALYSIS
 //
 // Turns off thread safety checking within the body of a particular function.
 // This annotation is used to mark functions that are known to be correct, but
 // the locking behavior is more complicated than the analyzer can handle.
+#if ABSL_HAVE_ATTRIBUTE(no_thread_safety_analysis)
 #define ABSL_NO_THREAD_SAFETY_ANALYSIS \
-  ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(no_thread_safety_analysis)
+  __attribute__((no_thread_safety_analysis))
+#else
+#define ABSL_NO_THREAD_SAFETY_ANALYSIS
+#endif
 
 //------------------------------------------------------------------------------
 // Tool-Supplied Annotations
@@ -256,6 +312,7 @@
 #define ABSL_TS_UNCHECKED_READ(x) absl::base_internal::ts_unchecked_read(x)
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace base_internal {
 
 // Takes a reference to a guarded data member, and returns an unguarded
@@ -272,6 +329,7 @@
 }
 
 }  // namespace base_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_BASE_THREAD_ANNOTATIONS_H_
diff --git a/absl/compiler_config_setting.bzl b/absl/compiler_config_setting.bzl
deleted file mode 100644
index 6696229..0000000
--- a/absl/compiler_config_setting.bzl
+++ /dev/null
@@ -1,38 +0,0 @@
-#
-# Copyright 2018 The Abseil Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Creates config_setting that allows selecting based on 'compiler' value."""
-
-def create_llvm_config(name, visibility):
-    # The "do_not_use_tools_cpp_compiler_present" attribute exists to
-    # distinguish between older versions of Bazel that do not support
-    # "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do.
-    # In the future, the only way to select on the compiler will be through
-    # flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can
-    # be removed.
-    if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"):
-        native.config_setting(
-            name = name,
-            flag_values = {
-                "@bazel_tools//tools/cpp:compiler": "llvm",
-            },
-            visibility = visibility,
-        )
-    else:
-        native.config_setting(
-            name = name,
-            values = {"compiler": "llvm"},
-            visibility = visibility,
-        )
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index 0894bb2..f22fdc6 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
 load(
     "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "compressed_tuple",
@@ -60,6 +60,7 @@
     deps = [
         ":compressed_tuple",
         "//absl/algorithm",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
         "//absl/base:throw_delegate",
@@ -73,7 +74,9 @@
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":counting_allocator",
         ":fixed_array",
+        "//absl/base:config",
         "//absl/base:exception_testing",
         "//absl/hash:hash_testing",
         "//absl/memory",
@@ -141,6 +144,7 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     visibility = ["//visibility:private"],
+    deps = ["//absl/base:config"],
 )
 
 cc_test(
@@ -152,6 +156,7 @@
         ":counting_allocator",
         ":inlined_vector",
         ":test_instance_tracker",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:exception_testing",
         "//absl/base:raw_logging_internal",
@@ -254,6 +259,7 @@
         ":unordered_map_lookup_test",
         ":unordered_map_members_test",
         ":unordered_map_modifiers_test",
+        "//absl/base:raw_logging_internal",
         "//absl/types:any",
         "@com_google_googletest//:gtest_main",
     ],
@@ -287,6 +293,7 @@
         ":unordered_set_lookup_test",
         ":unordered_set_members_test",
         ":unordered_set_modifiers_test",
+        "//absl/base:raw_logging_internal",
         "//absl/memory",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
@@ -362,7 +369,9 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        "//absl/base:config",
         "//absl/memory",
+        "//absl/meta:type_traits",
         "//absl/utility",
     ],
 )
@@ -375,6 +384,7 @@
     tags = NOTEST_TAGS_NONMOBILE,
     deps = [
         ":container_memory",
+        ":test_instance_tracker",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
     ],
@@ -389,6 +399,7 @@
         "//absl/base:config",
         "//absl/hash",
         "//absl/strings",
+        "//absl/strings:cord",
     ],
 )
 
@@ -401,7 +412,10 @@
     deps = [
         ":hash_function_defaults",
         "//absl/hash",
+        "//absl/random",
         "//absl/strings",
+        "//absl/strings:cord",
+        "//absl/strings:cord_test_helpers",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -478,6 +492,9 @@
     hdrs = ["internal/hashtable_debug_hooks.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+    ],
 )
 
 cc_library(
@@ -493,6 +510,7 @@
         ":have_sse",
         "//absl/base",
         "//absl/base:core_headers",
+        "//absl/base:exponential_biased",
         "//absl/debugging:stacktrace",
         "//absl/memory",
         "//absl/synchronization",
@@ -520,6 +538,7 @@
     hdrs = ["internal/node_hash_policy.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = ["//absl/base:config"],
 )
 
 cc_test(
@@ -580,12 +599,12 @@
         ":hashtablez_sampler",
         ":have_sse",
         ":layout",
-        "//absl/base:bits",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:endian",
         "//absl/memory",
         "//absl/meta:type_traits",
+        "//absl/numeric:bits",
         "//absl/utility",
     ],
 )
@@ -603,6 +622,7 @@
         ":hashtable_debug",
         ":raw_hash_set",
         "//absl/base",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
         "//absl/strings",
@@ -610,6 +630,45 @@
     ],
 )
 
+cc_binary(
+    name = "raw_hash_set_benchmark",
+    testonly = 1,
+    srcs = ["internal/raw_hash_set_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":hash_function_defaults",
+        ":raw_hash_set",
+        "//absl/base:raw_logging_internal",
+        "//absl/strings:str_format",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
+
+cc_binary(
+    name = "raw_hash_set_probe_benchmark",
+    testonly = 1,
+    srcs = ["internal/raw_hash_set_probe_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = select({
+        "//conditions:default": [],
+    }) + ABSL_DEFAULT_LINKOPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":flat_hash_map",
+        ":hash_function_defaults",
+        ":hashtable_debug",
+        ":raw_hash_set",
+        "//absl/random",
+        "//absl/random:distributions",
+        "//absl/strings",
+        "//absl/strings:str_format",
+    ],
+)
+
 cc_test(
     name = "raw_hash_set_allocator_test",
     size = "small",
@@ -630,6 +689,7 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/meta:type_traits",
         "//absl/strings",
@@ -648,6 +708,7 @@
     visibility = ["//visibility:private"],
     deps = [
         ":layout",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
         "//absl/types:span",
@@ -655,12 +716,31 @@
     ],
 )
 
+cc_binary(
+    name = "layout_benchmark",
+    testonly = 1,
+    srcs = ["internal/layout_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":layout",
+        "//absl/base:core_headers",
+        "//absl/base:raw_logging_internal",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
+
 cc_library(
     name = "tracked",
     testonly = 1,
     hdrs = ["internal/tracked.h"],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+    ],
 )
 
 cc_library(
@@ -819,6 +899,7 @@
         "//absl/memory",
         "//absl/meta:type_traits",
         "//absl/strings",
+        "//absl/strings:cord",
         "//absl/types:compare",
         "//absl/utility",
     ],
@@ -835,6 +916,7 @@
         ":btree",
         ":flat_hash_set",
         "//absl/strings",
+        "//absl/strings:cord",
         "//absl/time",
     ],
 )
@@ -865,3 +947,30 @@
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_binary(
+    name = "btree_benchmark",
+    testonly = 1,
+    srcs = [
+        "btree_benchmark.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":btree",
+        ":btree_test_common",
+        ":flat_hash_map",
+        ":flat_hash_set",
+        ":hashtable_debug",
+        "//absl/base:raw_logging_internal",
+        "//absl/flags:flag",
+        "//absl/hash",
+        "//absl/memory",
+        "//absl/strings:cord",
+        "//absl/strings:str_format",
+        "//absl/time",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 933c7a8..eb202c4 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -40,6 +40,7 @@
     absl::compare
     absl::compressed_tuple
     absl::container_memory
+    absl::cord
     absl::core_headers
     absl::layout
     absl::memory
@@ -60,6 +61,7 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::btree
+    absl::cord
     absl::flat_hash_set
     absl::strings
     absl::time
@@ -129,6 +131,7 @@
   DEPS
     absl::compressed_tuple
     absl::algorithm
+    absl::config
     absl::core_headers
     absl::dynamic_annotations
     absl::throw_delegate
@@ -145,6 +148,8 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::fixed_array
+    absl::counting_allocator
+    absl::config
     absl::exception_testing
     absl::hash_testing
     absl::memory
@@ -204,6 +209,8 @@
     "internal/counting_allocator.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
 )
 
 absl_cc_test(
@@ -217,6 +224,7 @@
     absl::counting_allocator
     absl::inlined_vector
     absl::test_instance_tracker
+    absl::config
     absl::core_headers
     absl::exception_testing
     absl::hash_testing
@@ -297,6 +305,7 @@
     absl::unordered_map_members_test
     absl::unordered_map_modifiers_test
     absl::any
+    absl::raw_logging_internal
     gmock_main
 )
 
@@ -333,6 +342,7 @@
     absl::unordered_set_members_test
     absl::unordered_set_modifiers_test
     absl::memory
+    absl::raw_logging_internal
     absl::strings
     gmock_main
 )
@@ -414,7 +424,9 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
+    absl::config
     absl::memory
+    absl::type_traits
     absl::utility
   PUBLIC
 )
@@ -429,6 +441,7 @@
   DEPS
     absl::container_memory
     absl::strings
+    absl::test_instance_tracker
     gmock_main
 )
 
@@ -441,6 +454,7 @@
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::config
+    absl::cord
     absl::hash
     absl::strings
   PUBLIC
@@ -454,8 +468,11 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::cord
+    absl::cord_test_helpers
     absl::hash_function_defaults
     absl::hash
+    absl::random_random
     absl::strings
     gmock_main
 )
@@ -538,6 +555,7 @@
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::base
+    absl::exponential_biased
     absl::have_sse
     absl::synchronization
 )
@@ -573,6 +591,8 @@
     "internal/hashtable_debug_hooks.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
   PUBLIC
 )
 
@@ -592,6 +612,8 @@
     "internal/node_hash_policy.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
   PUBLIC
 )
 
@@ -626,7 +648,7 @@
   NAME
     container_common
   HDRS
-    "internal/commom.h"
+    "internal/common.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
@@ -676,6 +698,7 @@
     absl::hashtable_debug
     absl::raw_hash_set
     absl::base
+    absl::config
     absl::core_headers
     absl::raw_logging_internal
     absl::strings
@@ -704,6 +727,7 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
+    absl::config
     absl::core_headers
     absl::meta
     absl::strings
@@ -721,6 +745,7 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::layout
+    absl::config
     absl::core_headers
     absl::raw_logging_internal
     absl::span
@@ -734,6 +759,8 @@
     "internal/tracked.h"
   COPTS
     ${ABSL_TEST_COPTS}
+  DEPS
+    absl::config
   TESTONLY
 )
 
diff --git a/absl/container/btree_benchmark.cc b/absl/container/btree_benchmark.cc
new file mode 100644
index 0000000..4679867
--- /dev/null
+++ b/absl/container/btree_benchmark.cc
@@ -0,0 +1,735 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <functional>
+#include <map>
+#include <numeric>
+#include <random>
+#include <set>
+#include <string>
+#include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/container/btree_map.h"
+#include "absl/container/btree_set.h"
+#include "absl/container/btree_test.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/container/internal/hashtable_debug.h"
+#include "absl/flags/flag.h"
+#include "absl/hash/hash.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/str_format.h"
+#include "absl/time/time.h"
+#include "benchmark/benchmark.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+namespace {
+
+constexpr size_t kBenchmarkValues = 1 << 20;
+
+// How many times we add and remove sub-batches in one batch of *AddRem
+// benchmarks.
+constexpr size_t kAddRemBatchSize = 1 << 2;
+
+// Generates n values in the range [0, 4 * n].
+template <typename V>
+std::vector<V> GenerateValues(int n) {
+  constexpr int kSeed = 23;
+  return GenerateValuesWithSeed<V>(n, 4 * n, kSeed);
+}
+
+// Benchmark insertion of values into a container.
+template <typename T>
+void BM_InsertImpl(benchmark::State& state, bool sorted) {
+  using V = typename remove_pair_const<typename T::value_type>::type;
+  typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+
+  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+  if (sorted) {
+    std::sort(values.begin(), values.end());
+  }
+  T container(values.begin(), values.end());
+
+  // Remove and re-insert 10% of the keys per batch.
+  const int batch_size = (kBenchmarkValues + 9) / 10;
+  while (state.KeepRunningBatch(batch_size)) {
+    state.PauseTiming();
+    const auto i = static_cast<int>(state.iterations());
+
+    for (int j = i; j < i + batch_size; j++) {
+      int x = j % kBenchmarkValues;
+      container.erase(key_of_value(values[x]));
+    }
+
+    state.ResumeTiming();
+
+    for (int j = i; j < i + batch_size; j++) {
+      int x = j % kBenchmarkValues;
+      container.insert(values[x]);
+    }
+  }
+}
+
+template <typename T>
+void BM_Insert(benchmark::State& state) {
+  BM_InsertImpl<T>(state, false);
+}
+
+template <typename T>
+void BM_InsertSorted(benchmark::State& state) {
+  BM_InsertImpl<T>(state, true);
+}
+
+// container::insert sometimes returns a pair<iterator, bool> and sometimes
+// returns an iterator (for multi- containers).
+template <typename Iter>
+Iter GetIterFromInsert(const std::pair<Iter, bool>& pair) {
+  return pair.first;
+}
+template <typename Iter>
+Iter GetIterFromInsert(const Iter iter) {
+  return iter;
+}
+
+// Benchmark insertion of values into a container at the end.
+template <typename T>
+void BM_InsertEnd(benchmark::State& state) {
+  using V = typename remove_pair_const<typename T::value_type>::type;
+  typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+
+  T container;
+  const int kSize = 10000;
+  for (int i = 0; i < kSize; ++i) {
+    container.insert(Generator<V>(kSize)(i));
+  }
+  V v = Generator<V>(kSize)(kSize - 1);
+  typename T::key_type k = key_of_value(v);
+
+  auto it = container.find(k);
+  while (state.KeepRunning()) {
+    // Repeatedly removing then adding v.
+    container.erase(it);
+    it = GetIterFromInsert(container.insert(v));
+  }
+}
+
+// Benchmark inserting the first few elements in a container. In b-tree, this is
+// when the root node grows.
+template <typename T>
+void BM_InsertSmall(benchmark::State& state) {
+  using V = typename remove_pair_const<typename T::value_type>::type;
+
+  const int kSize = 8;
+  std::vector<V> values = GenerateValues<V>(kSize);
+  T container;
+
+  while (state.KeepRunningBatch(kSize)) {
+    for (int i = 0; i < kSize; ++i) {
+      benchmark::DoNotOptimize(container.insert(values[i]));
+    }
+    state.PauseTiming();
+    // Do not measure the time it takes to clear the container.
+    container.clear();
+    state.ResumeTiming();
+  }
+}
+
+template <typename T>
+void BM_LookupImpl(benchmark::State& state, bool sorted) {
+  using V = typename remove_pair_const<typename T::value_type>::type;
+  typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+
+  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+  if (sorted) {
+    std::sort(values.begin(), values.end());
+  }
+  T container(values.begin(), values.end());
+
+  while (state.KeepRunning()) {
+    int idx = state.iterations() % kBenchmarkValues;
+    benchmark::DoNotOptimize(container.find(key_of_value(values[idx])));
+  }
+}
+
+// Benchmark lookup of values in a container.
+template <typename T>
+void BM_Lookup(benchmark::State& state) {
+  BM_LookupImpl<T>(state, false);
+}
+
+// Benchmark lookup of values in a full container, meaning that values
+// are inserted in-order to take advantage of biased insertion, which
+// yields a full tree.
+template <typename T>
+void BM_FullLookup(benchmark::State& state) {
+  BM_LookupImpl<T>(state, true);
+}
+
+// Benchmark deletion of values from a container.
+template <typename T>
+void BM_Delete(benchmark::State& state) {
+  using V = typename remove_pair_const<typename T::value_type>::type;
+  typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+  T container(values.begin(), values.end());
+
+  // Remove and re-insert 10% of the keys per batch.
+  const int batch_size = (kBenchmarkValues + 9) / 10;
+  while (state.KeepRunningBatch(batch_size)) {
+    const int i = state.iterations();
+
+    for (int j = i; j < i + batch_size; j++) {
+      int x = j % kBenchmarkValues;
+      container.erase(key_of_value(values[x]));
+    }
+
+    state.PauseTiming();
+    for (int j = i; j < i + batch_size; j++) {
+      int x = j % kBenchmarkValues;
+      container.insert(values[x]);
+    }
+    state.ResumeTiming();
+  }
+}
+
+// Benchmark deletion of multiple values from a container.
+template <typename T>
+void BM_DeleteRange(benchmark::State& state) {
+  using V = typename remove_pair_const<typename T::value_type>::type;
+  typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+  T container(values.begin(), values.end());
+
+  // Remove and re-insert 10% of the keys per batch.
+  const int batch_size = (kBenchmarkValues + 9) / 10;
+  while (state.KeepRunningBatch(batch_size)) {
+    const int i = state.iterations();
+
+    const int start_index = i % kBenchmarkValues;
+
+    state.PauseTiming();
+    {
+      std::vector<V> removed;
+      removed.reserve(batch_size);
+      auto itr = container.find(key_of_value(values[start_index]));
+      auto start = itr;
+      for (int j = 0; j < batch_size; j++) {
+        if (itr == container.end()) {
+          state.ResumeTiming();
+          container.erase(start, itr);
+          state.PauseTiming();
+          itr = container.begin();
+          start = itr;
+        }
+        removed.push_back(*itr++);
+      }
+
+      state.ResumeTiming();
+      container.erase(start, itr);
+      state.PauseTiming();
+
+      container.insert(removed.begin(), removed.end());
+    }
+    state.ResumeTiming();
+  }
+}
+
+// Benchmark steady-state insert (into first half of range) and remove (from
+// second half of range), treating the container approximately like a queue with
+// log-time access for all elements. This benchmark does not test the case where
+// insertion and removal happen in the same region of the tree.  This benchmark
+// counts two value constructors.
+template <typename T>
+void BM_QueueAddRem(benchmark::State& state) {
+  using V = typename remove_pair_const<typename T::value_type>::type;
+  typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+
+  ABSL_RAW_CHECK(kBenchmarkValues % 2 == 0, "for performance");
+
+  T container;
+
+  const size_t half = kBenchmarkValues / 2;
+  std::vector<int> remove_keys(half);
+  std::vector<int> add_keys(half);
+
+  // We want to do the exact same work repeatedly, and the benchmark can end
+  // after a different number of iterations depending on the speed of the
+  // individual run so we use a large batch size here and ensure that we do
+  // deterministic work every batch.
+  while (state.KeepRunningBatch(half * kAddRemBatchSize)) {
+    state.PauseTiming();
+
+    container.clear();
+
+    for (size_t i = 0; i < half; ++i) {
+      remove_keys[i] = i;
+      add_keys[i] = i;
+    }
+    constexpr int kSeed = 5;
+    std::mt19937_64 rand(kSeed);
+    std::shuffle(remove_keys.begin(), remove_keys.end(), rand);
+    std::shuffle(add_keys.begin(), add_keys.end(), rand);
+
+    // Note needs lazy generation of values.
+    Generator<V> g(kBenchmarkValues * kAddRemBatchSize);
+
+    for (size_t i = 0; i < half; ++i) {
+      container.insert(g(add_keys[i]));
+      container.insert(g(half + remove_keys[i]));
+    }
+
+    // There are three parts each of size "half":
+    // 1 is being deleted from  [offset - half, offset)
+    // 2 is standing            [offset, offset + half)
+    // 3 is being inserted into [offset + half, offset + 2 * half)
+    size_t offset = 0;
+
+    for (size_t i = 0; i < kAddRemBatchSize; ++i) {
+      std::shuffle(remove_keys.begin(), remove_keys.end(), rand);
+      std::shuffle(add_keys.begin(), add_keys.end(), rand);
+      offset += half;
+
+      state.ResumeTiming();
+      for (size_t idx = 0; idx < half; ++idx) {
+        container.erase(key_of_value(g(offset - half + remove_keys[idx])));
+        container.insert(g(offset + half + add_keys[idx]));
+      }
+      state.PauseTiming();
+    }
+    state.ResumeTiming();
+  }
+}
+
+// Mixed insertion and deletion in the same range using pre-constructed values.
+template <typename T>
+void BM_MixedAddRem(benchmark::State& state) {
+  using V = typename remove_pair_const<typename T::value_type>::type;
+  typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+
+  ABSL_RAW_CHECK(kBenchmarkValues % 2 == 0, "for performance");
+
+  T container;
+
+  // Create two random shuffles
+  std::vector<int> remove_keys(kBenchmarkValues);
+  std::vector<int> add_keys(kBenchmarkValues);
+
+  // We want to do the exact same work repeatedly, and the benchmark can end
+  // after a different number of iterations depending on the speed of the
+  // individual run so we use a large batch size here and ensure that we do
+  // deterministic work every batch.
+  while (state.KeepRunningBatch(kBenchmarkValues * kAddRemBatchSize)) {
+    state.PauseTiming();
+
+    container.clear();
+
+    constexpr int kSeed = 7;
+    std::mt19937_64 rand(kSeed);
+
+    std::vector<V> values = GenerateValues<V>(kBenchmarkValues * 2);
+
+    // Insert the first half of the values (already in random order)
+    container.insert(values.begin(), values.begin() + kBenchmarkValues);
+
+    // Insert the first half of the values (already in random order)
+    for (size_t i = 0; i < kBenchmarkValues; ++i) {
+      // remove_keys and add_keys will be swapped before each round,
+      // therefore fill add_keys here w/ the keys being inserted, so
+      // they'll be the first to be removed.
+      remove_keys[i] = i + kBenchmarkValues;
+      add_keys[i] = i;
+    }
+
+    for (size_t i = 0; i < kAddRemBatchSize; ++i) {
+      remove_keys.swap(add_keys);
+      std::shuffle(remove_keys.begin(), remove_keys.end(), rand);
+      std::shuffle(add_keys.begin(), add_keys.end(), rand);
+
+      state.ResumeTiming();
+      for (size_t idx = 0; idx < kBenchmarkValues; ++idx) {
+        container.erase(key_of_value(values[remove_keys[idx]]));
+        container.insert(values[add_keys[idx]]);
+      }
+      state.PauseTiming();
+    }
+    state.ResumeTiming();
+  }
+}
+
+// Insertion at end, removal from the beginning.  This benchmark
+// counts two value constructors.
+// TODO(ezb): we could add a GenerateNext version of generator that could reduce
+// noise for string-like types.
+template <typename T>
+void BM_Fifo(benchmark::State& state) {
+  using V = typename remove_pair_const<typename T::value_type>::type;
+
+  T container;
+  // Need lazy generation of values as state.max_iterations is large.
+  Generator<V> g(kBenchmarkValues + state.max_iterations);
+
+  for (int i = 0; i < kBenchmarkValues; i++) {
+    container.insert(g(i));
+  }
+
+  while (state.KeepRunning()) {
+    container.erase(container.begin());
+    container.insert(container.end(), g(state.iterations() + kBenchmarkValues));
+  }
+}
+
+// Iteration (forward) through the tree
+template <typename T>
+void BM_FwdIter(benchmark::State& state) {
+  using V = typename remove_pair_const<typename T::value_type>::type;
+  using R = typename T::value_type const*;
+
+  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+  T container(values.begin(), values.end());
+
+  auto iter = container.end();
+
+  R r = nullptr;
+
+  while (state.KeepRunning()) {
+    if (iter == container.end()) iter = container.begin();
+    r = &(*iter);
+    ++iter;
+  }
+
+  benchmark::DoNotOptimize(r);
+}
+
+// Benchmark random range-construction of a container.
+template <typename T>
+void BM_RangeConstructionImpl(benchmark::State& state, bool sorted) {
+  using V = typename remove_pair_const<typename T::value_type>::type;
+
+  std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+  if (sorted) {
+    std::sort(values.begin(), values.end());
+  }
+  {
+    T container(values.begin(), values.end());
+  }
+
+  while (state.KeepRunning()) {
+    T container(values.begin(), values.end());
+    benchmark::DoNotOptimize(container);
+  }
+}
+
+template <typename T>
+void BM_InsertRangeRandom(benchmark::State& state) {
+  BM_RangeConstructionImpl<T>(state, false);
+}
+
+template <typename T>
+void BM_InsertRangeSorted(benchmark::State& state) {
+  BM_RangeConstructionImpl<T>(state, true);
+}
+
+#define STL_ORDERED_TYPES(value)                     \
+  using stl_set_##value = std::set<value>;           \
+  using stl_map_##value = std::map<value, intptr_t>; \
+  using stl_multiset_##value = std::multiset<value>; \
+  using stl_multimap_##value = std::multimap<value, intptr_t>
+
+using StdString = std::string;
+STL_ORDERED_TYPES(int32_t);
+STL_ORDERED_TYPES(int64_t);
+STL_ORDERED_TYPES(StdString);
+STL_ORDERED_TYPES(Cord);
+STL_ORDERED_TYPES(Time);
+
+#define STL_UNORDERED_TYPES(value)                                       \
+  using stl_unordered_set_##value = std::unordered_set<value>;           \
+  using stl_unordered_map_##value = std::unordered_map<value, intptr_t>; \
+  using flat_hash_set_##value = flat_hash_set<value>;                    \
+  using flat_hash_map_##value = flat_hash_map<value, intptr_t>;          \
+  using stl_unordered_multiset_##value = std::unordered_multiset<value>; \
+  using stl_unordered_multimap_##value =                                 \
+      std::unordered_multimap<value, intptr_t>
+
+#define STL_UNORDERED_TYPES_CUSTOM_HASH(value, hash)                           \
+  using stl_unordered_set_##value = std::unordered_set<value, hash>;           \
+  using stl_unordered_map_##value = std::unordered_map<value, intptr_t, hash>; \
+  using flat_hash_set_##value = flat_hash_set<value, hash>;                    \
+  using flat_hash_map_##value = flat_hash_map<value, intptr_t, hash>;          \
+  using stl_unordered_multiset_##value = std::unordered_multiset<value, hash>; \
+  using stl_unordered_multimap_##value =                                       \
+      std::unordered_multimap<value, intptr_t, hash>
+
+STL_UNORDERED_TYPES_CUSTOM_HASH(Cord, absl::Hash<absl::Cord>);
+
+STL_UNORDERED_TYPES(int32_t);
+STL_UNORDERED_TYPES(int64_t);
+STL_UNORDERED_TYPES(StdString);
+STL_UNORDERED_TYPES_CUSTOM_HASH(Time, absl::Hash<absl::Time>);
+
+#define BTREE_TYPES(value)                                            \
+  using btree_256_set_##value =                                       \
+      btree_set<value, std::less<value>, std::allocator<value>>;      \
+  using btree_256_map_##value =                                       \
+      btree_map<value, intptr_t, std::less<value>,                    \
+                std::allocator<std::pair<const value, intptr_t>>>;    \
+  using btree_256_multiset_##value =                                  \
+      btree_multiset<value, std::less<value>, std::allocator<value>>; \
+  using btree_256_multimap_##value =                                  \
+      btree_multimap<value, intptr_t, std::less<value>,               \
+                     std::allocator<std::pair<const value, intptr_t>>>
+
+BTREE_TYPES(int32_t);
+BTREE_TYPES(int64_t);
+BTREE_TYPES(StdString);
+BTREE_TYPES(Cord);
+BTREE_TYPES(Time);
+
+#define MY_BENCHMARK4(type, func)                                              \
+  void BM_##type##_##func(benchmark::State& state) { BM_##func<type>(state); } \
+  BENCHMARK(BM_##type##_##func)
+
+#define MY_BENCHMARK3(type)               \
+  MY_BENCHMARK4(type, Insert);            \
+  MY_BENCHMARK4(type, InsertSorted);      \
+  MY_BENCHMARK4(type, InsertEnd);         \
+  MY_BENCHMARK4(type, InsertSmall);       \
+  MY_BENCHMARK4(type, Lookup);            \
+  MY_BENCHMARK4(type, FullLookup);        \
+  MY_BENCHMARK4(type, Delete);            \
+  MY_BENCHMARK4(type, DeleteRange);       \
+  MY_BENCHMARK4(type, QueueAddRem);       \
+  MY_BENCHMARK4(type, MixedAddRem);       \
+  MY_BENCHMARK4(type, Fifo);              \
+  MY_BENCHMARK4(type, FwdIter);           \
+  MY_BENCHMARK4(type, InsertRangeRandom); \
+  MY_BENCHMARK4(type, InsertRangeSorted)
+
+#define MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(type) \
+  MY_BENCHMARK3(stl_##type);                    \
+  MY_BENCHMARK3(stl_unordered_##type);          \
+  MY_BENCHMARK3(btree_256_##type)
+
+#define MY_BENCHMARK2(type)                \
+  MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(type); \
+  MY_BENCHMARK3(flat_hash_##type)
+
+// Define MULTI_TESTING to see benchmarks for multi-containers also.
+//
+// You can use --copt=-DMULTI_TESTING.
+#ifdef MULTI_TESTING
+#define MY_BENCHMARK(type)                            \
+  MY_BENCHMARK2(set_##type);                          \
+  MY_BENCHMARK2(map_##type);                          \
+  MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(multiset_##type); \
+  MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(multimap_##type)
+#else
+#define MY_BENCHMARK(type)   \
+  MY_BENCHMARK2(set_##type); \
+  MY_BENCHMARK2(map_##type)
+#endif
+
+MY_BENCHMARK(int32_t);
+MY_BENCHMARK(int64_t);
+MY_BENCHMARK(StdString);
+MY_BENCHMARK(Cord);
+MY_BENCHMARK(Time);
+
+// Define a type whose size and cost of moving are independently customizable.
+// When sizeof(value_type) increases, we expect btree to no longer have as much
+// cache-locality advantage over STL. When cost of moving increases, we expect
+// btree to actually do more work than STL because it has to move values around
+// and STL doesn't have to.
+template <int Size, int Copies>
+struct BigType {
+  BigType() : BigType(0) {}
+  explicit BigType(int x) { std::iota(values.begin(), values.end(), x); }
+
+  void Copy(const BigType& other) {
+    for (int i = 0; i < Size && i < Copies; ++i) values[i] = other.values[i];
+    // If Copies > Size, do extra copies.
+    for (int i = Size, idx = 0; i < Copies; ++i) {
+      int64_t tmp = other.values[idx];
+      benchmark::DoNotOptimize(tmp);
+      idx = idx + 1 == Size ? 0 : idx + 1;
+    }
+  }
+
+  BigType(const BigType& other) { Copy(other); }
+  BigType& operator=(const BigType& other) {
+    Copy(other);
+    return *this;
+  }
+
+  // Compare only the first Copies elements if Copies is less than Size.
+  bool operator<(const BigType& other) const {
+    return std::lexicographical_compare(
+        values.begin(), values.begin() + std::min(Size, Copies),
+        other.values.begin(), other.values.begin() + std::min(Size, Copies));
+  }
+  bool operator==(const BigType& other) const {
+    return std::equal(values.begin(), values.begin() + std::min(Size, Copies),
+                      other.values.begin());
+  }
+
+  // Support absl::Hash.
+  template <typename State>
+  friend State AbslHashValue(State h, const BigType& b) {
+    for (int i = 0; i < Size && i < Copies; ++i)
+      h = State::combine(std::move(h), b.values[i]);
+    return h;
+  }
+
+  std::array<int64_t, Size> values;
+};
+
+#define BIG_TYPE_BENCHMARKS(SIZE, COPIES)                                     \
+  using stl_set_size##SIZE##copies##COPIES = std::set<BigType<SIZE, COPIES>>; \
+  using stl_map_size##SIZE##copies##COPIES =                                  \
+      std::map<BigType<SIZE, COPIES>, intptr_t>;                              \
+  using stl_multiset_size##SIZE##copies##COPIES =                             \
+      std::multiset<BigType<SIZE, COPIES>>;                                   \
+  using stl_multimap_size##SIZE##copies##COPIES =                             \
+      std::multimap<BigType<SIZE, COPIES>, intptr_t>;                         \
+  using stl_unordered_set_size##SIZE##copies##COPIES =                        \
+      std::unordered_set<BigType<SIZE, COPIES>,                               \
+                         absl::Hash<BigType<SIZE, COPIES>>>;                  \
+  using stl_unordered_map_size##SIZE##copies##COPIES =                        \
+      std::unordered_map<BigType<SIZE, COPIES>, intptr_t,                     \
+                         absl::Hash<BigType<SIZE, COPIES>>>;                  \
+  using flat_hash_set_size##SIZE##copies##COPIES =                            \
+      flat_hash_set<BigType<SIZE, COPIES>>;                                   \
+  using flat_hash_map_size##SIZE##copies##COPIES =                            \
+      flat_hash_map<BigType<SIZE, COPIES>, intptr_t>;                         \
+  using stl_unordered_multiset_size##SIZE##copies##COPIES =                   \
+      std::unordered_multiset<BigType<SIZE, COPIES>,                          \
+                              absl::Hash<BigType<SIZE, COPIES>>>;             \
+  using stl_unordered_multimap_size##SIZE##copies##COPIES =                   \
+      std::unordered_multimap<BigType<SIZE, COPIES>, intptr_t,                \
+                              absl::Hash<BigType<SIZE, COPIES>>>;             \
+  using btree_256_set_size##SIZE##copies##COPIES =                            \
+      btree_set<BigType<SIZE, COPIES>>;                                       \
+  using btree_256_map_size##SIZE##copies##COPIES =                            \
+      btree_map<BigType<SIZE, COPIES>, intptr_t>;                             \
+  using btree_256_multiset_size##SIZE##copies##COPIES =                       \
+      btree_multiset<BigType<SIZE, COPIES>>;                                  \
+  using btree_256_multimap_size##SIZE##copies##COPIES =                       \
+      btree_multimap<BigType<SIZE, COPIES>, intptr_t>;                        \
+  MY_BENCHMARK(size##SIZE##copies##COPIES)
+
+// Define BIG_TYPE_TESTING to see benchmarks for more big types.
+//
+// You can use --copt=-DBIG_TYPE_TESTING.
+#ifndef NODESIZE_TESTING
+#ifdef BIG_TYPE_TESTING
+BIG_TYPE_BENCHMARKS(1, 4);
+BIG_TYPE_BENCHMARKS(4, 1);
+BIG_TYPE_BENCHMARKS(4, 4);
+BIG_TYPE_BENCHMARKS(1, 8);
+BIG_TYPE_BENCHMARKS(8, 1);
+BIG_TYPE_BENCHMARKS(8, 8);
+BIG_TYPE_BENCHMARKS(1, 16);
+BIG_TYPE_BENCHMARKS(16, 1);
+BIG_TYPE_BENCHMARKS(16, 16);
+BIG_TYPE_BENCHMARKS(1, 32);
+BIG_TYPE_BENCHMARKS(32, 1);
+BIG_TYPE_BENCHMARKS(32, 32);
+#else
+BIG_TYPE_BENCHMARKS(32, 32);
+#endif
+#endif
+
+// Benchmark using unique_ptrs to large value types. In order to be able to use
+// the same benchmark code as the other types, use a type that holds a
+// unique_ptr and has a copy constructor.
+template <int Size>
+struct BigTypePtr {
+  BigTypePtr() : BigTypePtr(0) {}
+  explicit BigTypePtr(int x) {
+    ptr = absl::make_unique<BigType<Size, Size>>(x);
+  }
+  BigTypePtr(const BigTypePtr& other) {
+    ptr = absl::make_unique<BigType<Size, Size>>(*other.ptr);
+  }
+  BigTypePtr(BigTypePtr&& other) noexcept = default;
+  BigTypePtr& operator=(const BigTypePtr& other) {
+    ptr = absl::make_unique<BigType<Size, Size>>(*other.ptr);
+  }
+  BigTypePtr& operator=(BigTypePtr&& other) noexcept = default;
+
+  bool operator<(const BigTypePtr& other) const { return *ptr < *other.ptr; }
+  bool operator==(const BigTypePtr& other) const { return *ptr == *other.ptr; }
+
+  std::unique_ptr<BigType<Size, Size>> ptr;
+};
+
+template <int Size>
+double ContainerInfo(const btree_set<BigTypePtr<Size>>& b) {
+  const double bytes_used =
+      b.bytes_used() + b.size() * sizeof(BigType<Size, Size>);
+  const double bytes_per_value = bytes_used / b.size();
+  BtreeContainerInfoLog(b, bytes_used, bytes_per_value);
+  return bytes_per_value;
+}
+template <int Size>
+double ContainerInfo(const btree_map<int, BigTypePtr<Size>>& b) {
+  const double bytes_used =
+      b.bytes_used() + b.size() * sizeof(BigType<Size, Size>);
+  const double bytes_per_value = bytes_used / b.size();
+  BtreeContainerInfoLog(b, bytes_used, bytes_per_value);
+  return bytes_per_value;
+}
+
+#define BIG_TYPE_PTR_BENCHMARKS(SIZE)                                          \
+  using stl_set_size##SIZE##copies##SIZE##ptr = std::set<BigType<SIZE, SIZE>>; \
+  using stl_map_size##SIZE##copies##SIZE##ptr =                                \
+      std::map<int, BigType<SIZE, SIZE>>;                                      \
+  using stl_unordered_set_size##SIZE##copies##SIZE##ptr =                      \
+      std::unordered_set<BigType<SIZE, SIZE>,                                  \
+                         absl::Hash<BigType<SIZE, SIZE>>>;                     \
+  using stl_unordered_map_size##SIZE##copies##SIZE##ptr =                      \
+      std::unordered_map<int, BigType<SIZE, SIZE>>;                            \
+  using flat_hash_set_size##SIZE##copies##SIZE##ptr =                          \
+      flat_hash_set<BigType<SIZE, SIZE>>;                                      \
+  using flat_hash_map_size##SIZE##copies##SIZE##ptr =                          \
+      flat_hash_map<int, BigTypePtr<SIZE>>;                                    \
+  using btree_256_set_size##SIZE##copies##SIZE##ptr =                          \
+      btree_set<BigTypePtr<SIZE>>;                                             \
+  using btree_256_map_size##SIZE##copies##SIZE##ptr =                          \
+      btree_map<int, BigTypePtr<SIZE>>;                                        \
+  MY_BENCHMARK3(stl_set_size##SIZE##copies##SIZE##ptr);                        \
+  MY_BENCHMARK3(stl_unordered_set_size##SIZE##copies##SIZE##ptr);              \
+  MY_BENCHMARK3(flat_hash_set_size##SIZE##copies##SIZE##ptr);                  \
+  MY_BENCHMARK3(btree_256_set_size##SIZE##copies##SIZE##ptr);                  \
+  MY_BENCHMARK3(stl_map_size##SIZE##copies##SIZE##ptr);                        \
+  MY_BENCHMARK3(stl_unordered_map_size##SIZE##copies##SIZE##ptr);              \
+  MY_BENCHMARK3(flat_hash_map_size##SIZE##copies##SIZE##ptr);                  \
+  MY_BENCHMARK3(btree_256_map_size##SIZE##copies##SIZE##ptr)
+
+BIG_TYPE_PTR_BENCHMARKS(32);
+
+}  // namespace
+}  // namespace container_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/container/btree_map.h b/absl/container/btree_map.h
index 9f35f63..abc09b0 100644
--- a/absl/container/btree_map.h
+++ b/absl/container/btree_map.h
@@ -51,6 +51,7 @@
 #include "absl/container/internal/btree_container.h"  // IWYU pragma: export
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // absl::btree_map<>
 //
@@ -184,7 +185,7 @@
   // template <typename K> size_type erase(const K& key):
   //
   //   Erases the element with the matching key, if it exists, returning the
-  //   number of elements erased.
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // btree_map::insert()
@@ -225,6 +226,30 @@
   //   Inserts the elements within the initializer list `ilist`.
   using Base::insert;
 
+  // btree_map::insert_or_assign()
+  //
+  // Inserts an element of the specified value into the `btree_map` provided
+  // that a value with the given key does not already exist, or replaces the
+  // corresponding mapped type with the forwarded `obj` argument if a key for
+  // that value already exists, returning an iterator pointing to the newly
+  // inserted element. Overloads are listed below.
+  //
+  // pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj):
+  // pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj):
+  //
+  //   Inserts/Assigns (or moves) the element of the specified key into the
+  //   `btree_map`. If the returned bool is true, insertion took place, and if
+  //   it's false, assignment took place.
+  //
+  // iterator insert_or_assign(const_iterator hint,
+  //                           const key_type& k, M&& obj):
+  // iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj):
+  //
+  //   Inserts/Assigns (or moves) the element of the specified key into the
+  //   `btree_map` using the position of `hint` as a non-binding suggestion
+  //   for where to begin the insertion search.
+  using Base::insert_or_assign;
+
   // btree_map::emplace()
   //
   // Inserts an element of the specified value by constructing it in-place
@@ -293,13 +318,18 @@
   //   Extracts the element at the indicated position and returns a node handle
   //   owning that extracted data.
   //
-  // template <typename K> node_type extract(const K& x):
+  // template <typename K> node_type extract(const K& k):
   //
   //   Extracts the element with the key matching the passed key value and
   //   returns a node handle owning that extracted data. If the `btree_map`
   //   does not contain an element with a matching key, this function returns an
   //   empty node handle.
   //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
+  //
   // NOTE: In this context, `node_type` refers to the C++17 concept of a
   // move-only type that owns and provides access to the elements in associative
   // containers (https://en.cppreference.com/w/cpp/container/node_handle).
@@ -411,6 +441,20 @@
   return x.swap(y);
 }
 
+// absl::erase_if(absl::btree_map<>, Pred)
+//
+// Erases all elements that satisfy the predicate pred from the container.
+template <typename K, typename V, typename C, typename A, typename Pred>
+void erase_if(btree_map<K, V, C, A> &map, Pred pred) {
+  for (auto it = map.begin(); it != map.end();) {
+    if (pred(*it)) {
+      it = map.erase(it);
+    } else {
+      ++it;
+    }
+  }
+}
+
 // absl::btree_multimap
 //
 // An `absl::btree_multimap<K, V>` is an ordered associative container of
@@ -606,13 +650,18 @@
   //   Extracts the element at the indicated position and returns a node handle
   //   owning that extracted data.
   //
-  // template <typename K> node_type extract(const K& x):
+  // template <typename K> node_type extract(const K& k):
   //
   //   Extracts the element with the key matching the passed key value and
   //   returns a node handle owning that extracted data. If the `btree_multimap`
   //   does not contain an element with a matching key, this function returns an
   //   empty node handle.
   //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
+  //
   // NOTE: In this context, `node_type` refers to the C++17 concept of a
   // move-only type that owns and provides access to the elements in associative
   // containers (https://en.cppreference.com/w/cpp/container/node_handle).
@@ -700,6 +749,21 @@
   return x.swap(y);
 }
 
+// absl::erase_if(absl::btree_multimap<>, Pred)
+//
+// Erases all elements that satisfy the predicate pred from the container.
+template <typename K, typename V, typename C, typename A, typename Pred>
+void erase_if(btree_multimap<K, V, C, A> &map, Pred pred) {
+  for (auto it = map.begin(); it != map.end();) {
+    if (pred(*it)) {
+      it = map.erase(it);
+    } else {
+      ++it;
+    }
+  }
+}
+
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_BTREE_MAP_H_
diff --git a/absl/container/btree_set.h b/absl/container/btree_set.h
index 6e47b4a..21ef0a0 100644
--- a/absl/container/btree_set.h
+++ b/absl/container/btree_set.h
@@ -51,6 +51,7 @@
 #include "absl/container/internal/btree_container.h"  // IWYU pragma: export
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // absl::btree_set<>
 //
@@ -182,7 +183,7 @@
   // template <typename K> size_type erase(const K& key):
   //
   //   Erases the element with the matching key, if it exists, returning the
-  //   number of elements erased.
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // btree_set::insert()
@@ -262,7 +263,7 @@
   //   Extracts the element at the indicated position and returns a node handle
   //   owning that extracted data.
   //
-  // template <typename K> node_type extract(const K& x):
+  // template <typename K> node_type extract(const K& k):
   //
   //   Extracts the element with the key matching the passed key value and
   //   returns a node handle owning that extracted data. If the `btree_set`
@@ -359,6 +360,20 @@
   return x.swap(y);
 }
 
+// absl::erase_if(absl::btree_set<>, Pred)
+//
+// Erases all elements that satisfy the predicate pred from the container.
+template <typename K, typename C, typename A, typename Pred>
+void erase_if(btree_set<K, C, A> &set, Pred pred) {
+  for (auto it = set.begin(); it != set.end();) {
+    if (pred(*it)) {
+      it = set.erase(it);
+    } else {
+      ++it;
+    }
+  }
+}
+
 // absl::btree_multiset<>
 //
 // An `absl::btree_multiset<K>` is an ordered associative container of
@@ -552,7 +567,7 @@
   //   Extracts the element at the indicated position and returns a node handle
   //   owning that extracted data.
   //
-  // template <typename K> node_type extract(const K& x):
+  // template <typename K> node_type extract(const K& k):
   //
   //   Extracts the element with the key matching the passed key value and
   //   returns a node handle owning that extracted data. If the `btree_multiset`
@@ -648,6 +663,21 @@
   return x.swap(y);
 }
 
+// absl::erase_if(absl::btree_multiset<>, Pred)
+//
+// Erases all elements that satisfy the predicate pred from the container.
+template <typename K, typename C, typename A, typename Pred>
+void erase_if(btree_multiset<K, C, A> &set, Pred pred) {
+  for (auto it = set.begin(); it != set.end();) {
+    if (pred(*it)) {
+      it = set.erase(it);
+    } else {
+      ++it;
+    }
+  }
+}
+
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_BTREE_SET_H_
diff --git a/absl/container/btree_test.cc b/absl/container/btree_test.cc
index 4edb277..367d75b 100644
--- a/absl/container/btree_test.cc
+++ b/absl/container/btree_test.cc
@@ -15,6 +15,7 @@
 #include "absl/container/btree_test.h"
 
 #include <cstdint>
+#include <limits>
 #include <map>
 #include <memory>
 #include <stdexcept>
@@ -42,14 +43,19 @@
 ABSL_FLAG(int, test_values, 10000, "The number of values to use for tests");
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
+using ::absl::test_internal::CopyableMovableInstance;
 using ::absl::test_internal::InstanceTracker;
 using ::absl::test_internal::MovableOnlyInstance;
 using ::testing::ElementsAre;
 using ::testing::ElementsAreArray;
+using ::testing::IsEmpty;
+using ::testing::IsNull;
 using ::testing::Pair;
+using ::testing::SizeIs;
 
 template <typename T, typename U>
 void CheckPairEquals(const T &x, const U &y) {
@@ -86,8 +92,8 @@
 
  public:
   base_checker() : const_tree_(tree_) {}
-  base_checker(const base_checker &x)
-      : tree_(x.tree_), const_tree_(tree_), checker_(x.checker_) {}
+  base_checker(const base_checker &other)
+      : tree_(other.tree_), const_tree_(tree_), checker_(other.checker_) {}
   template <typename InputIterator>
   base_checker(InputIterator b, InputIterator e)
       : tree_(b, e), const_tree_(tree_), checker_(b, e) {}
@@ -121,11 +127,11 @@
     }
     return tree_iter;
   }
-  void value_check(const value_type &x) {
+  void value_check(const value_type &v) {
     typename KeyOfValue<typename TreeType::key_type,
                         typename TreeType::value_type>::type key_of_value;
-    const key_type &key = key_of_value(x);
-    CheckPairEquals(*find(key), x);
+    const key_type &key = key_of_value(v);
+    CheckPairEquals(*find(key), v);
     lower_bound(key);
     upper_bound(key);
     equal_range(key);
@@ -177,18 +183,16 @@
   const_iterator find(const key_type &key) const {
     return iter_check(tree_.find(key), checker_.find(key));
   }
-  bool contains(const key_type &key) const {
-    return find(key) != end();
-  }
+  bool contains(const key_type &key) const { return find(key) != end(); }
   size_type count(const key_type &key) const {
     size_type res = checker_.count(key);
     EXPECT_EQ(res, tree_.count(key));
     return res;
   }
 
-  base_checker &operator=(const base_checker &x) {
-    tree_ = x.tree_;
-    checker_ = x.checker_;
+  base_checker &operator=(const base_checker &other) {
+    tree_ = other.tree_;
+    checker_ = other.checker_;
     return *this;
   }
 
@@ -237,8 +241,10 @@
         ++checker_end;
       }
     }
-    checker_.erase(checker_begin, checker_end);
-    tree_.erase(begin, end);
+    const auto checker_ret = checker_.erase(checker_begin, checker_end);
+    const auto tree_ret = tree_.erase(begin, end);
+    EXPECT_EQ(std::distance(checker_.begin(), checker_ret),
+              std::distance(tree_.begin(), tree_ret));
     EXPECT_EQ(tree_.size(), checker_.size());
     EXPECT_EQ(tree_.size(), size - count);
   }
@@ -247,9 +253,9 @@
     tree_.clear();
     checker_.clear();
   }
-  void swap(base_checker &x) {
-    tree_.swap(x.tree_);
-    checker_.swap(x.checker_);
+  void swap(base_checker &other) {
+    tree_.swap(other.tree_);
+    checker_.swap(other.checker_);
   }
 
   void verify() const {
@@ -320,28 +326,28 @@
 
  public:
   unique_checker() : super_type() {}
-  unique_checker(const unique_checker &x) : super_type(x) {}
+  unique_checker(const unique_checker &other) : super_type(other) {}
   template <class InputIterator>
   unique_checker(InputIterator b, InputIterator e) : super_type(b, e) {}
-  unique_checker& operator=(const unique_checker&) = default;
+  unique_checker &operator=(const unique_checker &) = default;
 
   // Insertion routines.
-  std::pair<iterator, bool> insert(const value_type &x) {
+  std::pair<iterator, bool> insert(const value_type &v) {
     int size = this->tree_.size();
     std::pair<typename CheckerType::iterator, bool> checker_res =
-        this->checker_.insert(x);
-    std::pair<iterator, bool> tree_res = this->tree_.insert(x);
+        this->checker_.insert(v);
+    std::pair<iterator, bool> tree_res = this->tree_.insert(v);
     CheckPairEquals(*tree_res.first, *checker_res.first);
     EXPECT_EQ(tree_res.second, checker_res.second);
     EXPECT_EQ(this->tree_.size(), this->checker_.size());
     EXPECT_EQ(this->tree_.size(), size + tree_res.second);
     return tree_res;
   }
-  iterator insert(iterator position, const value_type &x) {
+  iterator insert(iterator position, const value_type &v) {
     int size = this->tree_.size();
     std::pair<typename CheckerType::iterator, bool> checker_res =
-        this->checker_.insert(x);
-    iterator tree_res = this->tree_.insert(position, x);
+        this->checker_.insert(v);
+    iterator tree_res = this->tree_.insert(position, v);
     CheckPairEquals(*tree_res, *checker_res.first);
     EXPECT_EQ(this->tree_.size(), this->checker_.size());
     EXPECT_EQ(this->tree_.size(), size + checker_res.second);
@@ -368,25 +374,25 @@
 
  public:
   multi_checker() : super_type() {}
-  multi_checker(const multi_checker &x) : super_type(x) {}
+  multi_checker(const multi_checker &other) : super_type(other) {}
   template <class InputIterator>
   multi_checker(InputIterator b, InputIterator e) : super_type(b, e) {}
-  multi_checker& operator=(const multi_checker&) = default;
+  multi_checker &operator=(const multi_checker &) = default;
 
   // Insertion routines.
-  iterator insert(const value_type &x) {
+  iterator insert(const value_type &v) {
     int size = this->tree_.size();
-    auto checker_res = this->checker_.insert(x);
-    iterator tree_res = this->tree_.insert(x);
+    auto checker_res = this->checker_.insert(v);
+    iterator tree_res = this->tree_.insert(v);
     CheckPairEquals(*tree_res, *checker_res);
     EXPECT_EQ(this->tree_.size(), this->checker_.size());
     EXPECT_EQ(this->tree_.size(), size + 1);
     return tree_res;
   }
-  iterator insert(iterator position, const value_type &x) {
+  iterator insert(iterator position, const value_type &v) {
     int size = this->tree_.size();
-    auto checker_res = this->checker_.insert(x);
-    iterator tree_res = this->tree_.insert(position, x);
+    auto checker_res = this->checker_.insert(v);
+    iterator tree_res = this->tree_.insert(position, v);
     CheckPairEquals(*tree_res, *checker_res);
     EXPECT_EQ(this->tree_.size(), this->checker_.size());
     EXPECT_EQ(this->tree_.size(), size + 1);
@@ -809,10 +815,12 @@
 TEST(Btree, set_int32) { SetTest<int32_t>(); }
 TEST(Btree, set_int64) { SetTest<int64_t>(); }
 TEST(Btree, set_string) { SetTest<std::string>(); }
+TEST(Btree, set_cord) { SetTest<absl::Cord>(); }
 TEST(Btree, set_pair) { SetTest<std::pair<int, int>>(); }
 TEST(Btree, map_int32) { MapTest<int32_t>(); }
 TEST(Btree, map_int64) { MapTest<int64_t>(); }
 TEST(Btree, map_string) { MapTest<std::string>(); }
+TEST(Btree, map_cord) { MapTest<absl::Cord>(); }
 TEST(Btree, map_pair) { MapTest<std::pair<int, int>>(); }
 
 template <typename K, int N = 256>
@@ -844,10 +852,12 @@
 TEST(Btree, multiset_int32) { MultiSetTest<int32_t>(); }
 TEST(Btree, multiset_int64) { MultiSetTest<int64_t>(); }
 TEST(Btree, multiset_string) { MultiSetTest<std::string>(); }
+TEST(Btree, multiset_cord) { MultiSetTest<absl::Cord>(); }
 TEST(Btree, multiset_pair) { MultiSetTest<std::pair<int, int>>(); }
 TEST(Btree, multimap_int32) { MultiMapTest<int32_t>(); }
 TEST(Btree, multimap_int64) { MultiMapTest<int64_t>(); }
 TEST(Btree, multimap_string) { MultiMapTest<std::string>(); }
+TEST(Btree, multimap_cord) { MultiMapTest<absl::Cord>(); }
 TEST(Btree, multimap_pair) { MultiMapTest<std::pair<int, int>>(); }
 
 struct CompareIntToString {
@@ -865,7 +875,7 @@
 
 struct NonTransparentCompare {
   template <typename T, typename U>
-  bool operator()(const T& t, const U& u) const {
+  bool operator()(const T &t, const U &u) const {
     // Treating all comparators as transparent can cause inefficiencies (see
     // N3657 C++ proposal). Test that for comparators without 'is_transparent'
     // alias (like this one), we do not attempt heterogeneous lookup.
@@ -1002,21 +1012,15 @@
  public:
   StringLike() = default;
 
-  StringLike(const char* s) : s_(s) {  // NOLINT
+  StringLike(const char *s) : s_(s) {  // NOLINT
     ++constructor_calls_;
   }
 
-  bool operator<(const StringLike& a) const {
-    return s_ < a.s_;
-  }
+  bool operator<(const StringLike &a) const { return s_ < a.s_; }
 
-  static void clear_constructor_call_count() {
-    constructor_calls_ = 0;
-  }
+  static void clear_constructor_call_count() { constructor_calls_ = 0; }
 
-  static int constructor_calls() {
-    return constructor_calls_;
-  }
+  static int constructor_calls() { return constructor_calls_; }
 
  private:
   static int constructor_calls_;
@@ -1179,6 +1183,103 @@
   EXPECT_EQ(1, tmap.size());
 }
 
+}  // namespace
+
+class BtreeNodePeer {
+ public:
+  // Yields the size of a leaf node with a specific number of values.
+  template <typename ValueType>
+  constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {
+    return btree_node<
+        set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,
+                   /*TargetNodeSize=*/256,  // This parameter isn't used here.
+                   /*Multi=*/false>>::SizeWithNValues(target_values_per_node);
+  }
+
+  // Yields the number of values in a (non-root) leaf node for this btree.
+  template <typename Btree>
+  constexpr static size_t GetNumValuesPerNode() {
+    return btree_node<typename Btree::params_type>::kNodeValues;
+  }
+
+  template <typename Btree>
+  constexpr static size_t GetMaxFieldType() {
+    return std::numeric_limits<
+        typename btree_node<typename Btree::params_type>::field_type>::max();
+  }
+
+  template <typename Btree>
+  constexpr static bool UsesLinearNodeSearch() {
+    return btree_node<typename Btree::params_type>::use_linear_search::value;
+  }
+};
+
+namespace {
+
+class BtreeMapTest : public ::testing::Test {
+ public:
+  struct Key {};
+  struct Cmp {
+    template <typename T>
+    bool operator()(T, T) const {
+      return false;
+    }
+  };
+
+  struct KeyLin {
+    using absl_btree_prefer_linear_node_search = std::true_type;
+  };
+  struct CmpLin : Cmp {
+    using absl_btree_prefer_linear_node_search = std::true_type;
+  };
+
+  struct KeyBin {
+    using absl_btree_prefer_linear_node_search = std::false_type;
+  };
+  struct CmpBin : Cmp {
+    using absl_btree_prefer_linear_node_search = std::false_type;
+  };
+
+  template <typename K, typename C>
+  static bool IsLinear() {
+    return BtreeNodePeer::UsesLinearNodeSearch<absl::btree_map<K, int, C>>();
+  }
+};
+
+TEST_F(BtreeMapTest, TestLinearSearchPreferredForKeyLinearViaAlias) {
+  // Test requesting linear search by directly exporting an alias.
+  EXPECT_FALSE((IsLinear<Key, Cmp>()));
+  EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
+  EXPECT_TRUE((IsLinear<Key, CmpLin>()));
+  EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
+}
+
+TEST_F(BtreeMapTest, LinearChoiceTree) {
+  // Cmp has precedence, and is forcing binary
+  EXPECT_FALSE((IsLinear<Key, CmpBin>()));
+  EXPECT_FALSE((IsLinear<KeyLin, CmpBin>()));
+  EXPECT_FALSE((IsLinear<KeyBin, CmpBin>()));
+  EXPECT_FALSE((IsLinear<int, CmpBin>()));
+  EXPECT_FALSE((IsLinear<std::string, CmpBin>()));
+  // Cmp has precedence, and is forcing linear
+  EXPECT_TRUE((IsLinear<Key, CmpLin>()));
+  EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
+  EXPECT_TRUE((IsLinear<KeyBin, CmpLin>()));
+  EXPECT_TRUE((IsLinear<int, CmpLin>()));
+  EXPECT_TRUE((IsLinear<std::string, CmpLin>()));
+  // Cmp has no preference, Key determines linear vs binary.
+  EXPECT_FALSE((IsLinear<Key, Cmp>()));
+  EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
+  EXPECT_FALSE((IsLinear<KeyBin, Cmp>()));
+  // arithmetic key w/ std::less or std::greater: linear
+  EXPECT_TRUE((IsLinear<int, std::less<int>>()));
+  EXPECT_TRUE((IsLinear<double, std::greater<double>>()));
+  // arithmetic key w/ custom compare: binary
+  EXPECT_FALSE((IsLinear<int, Cmp>()));
+  // non-arithmetic key: binary
+  EXPECT_FALSE((IsLinear<std::string, std::less<std::string>>()));
+}
+
 TEST(Btree, BtreeMapCanHoldMoveOnlyTypes) {
   absl::btree_map<std::string, std::unique_ptr<std::string>> m;
 
@@ -1271,6 +1372,8 @@
   AssertKeyCompareToAdapted<std::less<absl::string_view>, absl::string_view>();
   AssertKeyCompareToAdapted<std::greater<absl::string_view>,
                             absl::string_view>();
+  AssertKeyCompareToAdapted<std::less<absl::Cord>, absl::Cord>();
+  AssertKeyCompareToAdapted<std::greater<absl::Cord>, absl::Cord>();
   AssertKeyCompareToNotAdapted<std::less<int>, int>();
   AssertKeyCompareToNotAdapted<std::greater<int>, int>();
 }
@@ -1322,28 +1425,6 @@
   EXPECT_EQ(tracker.swaps(), 0);
 }
 
-}  // namespace
-
-class BtreeNodePeer {
- public:
-  // Yields the size of a leaf node with a specific number of values.
-  template <typename ValueType>
-  constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {
-    return btree_node<
-        set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,
-                   /*TargetNodeSize=*/256,  // This parameter isn't used here.
-                   /*Multi=*/false>>::SizeWithNValues(target_values_per_node);
-  }
-
-  // Yields the number of values in a (non-root) leaf node for this set.
-  template <typename Set>
-  constexpr static size_t GetNumValuesPerNode() {
-    return btree_node<typename Set::params_type>::kNodeValues;
-  }
-};
-
-namespace {
-
 // A btree set with a specific number of values per node.
 template <typename Key, int TargetValuesPerNode, typename Cmp = std::less<Key>>
 class SizedBtreeSet
@@ -1473,7 +1554,7 @@
   int num;
   explicit NoDefaultCtor(int i) : num(i) {}
 
-  friend bool operator<(const NoDefaultCtor& a, const NoDefaultCtor& b) {
+  friend bool operator<(const NoDefaultCtor &a, const NoDefaultCtor &b) {
     return a.num < b.num;
   }
 };
@@ -1540,7 +1621,7 @@
 #ifdef ABSL_HAVE_EXCEPTIONS
   EXPECT_THROW(map.at(3), std::out_of_range);
 #else
-  EXPECT_DEATH(map.at(3), "absl::btree_map::at");
+  EXPECT_DEATH_IF_SUPPORTED(map.at(3), "absl::btree_map::at");
 #endif
 }
 
@@ -1823,25 +1904,80 @@
   EXPECT_EQ(res.node.value(), 3);
 }
 
-struct Deref {
-  bool operator()(const std::unique_ptr<int> &lhs,
-                  const std::unique_ptr<int> &rhs) const {
-    return *lhs < *rhs;
-  }
-};
+template <typename Set>
+void TestExtractWithTrackingForSet() {
+  InstanceTracker tracker;
+  {
+    Set s;
+    // Add enough elements to make sure we test internal nodes too.
+    const size_t kSize = 1000;
+    while (s.size() < kSize) {
+      s.insert(MovableOnlyInstance(s.size()));
+    }
+    for (int i = 0; i < kSize; ++i) {
+      // Extract with key
+      auto nh = s.extract(MovableOnlyInstance(i));
+      EXPECT_EQ(s.size(), kSize - 1);
+      EXPECT_EQ(nh.value().value(), i);
+      // Insert with node
+      s.insert(std::move(nh));
+      EXPECT_EQ(s.size(), kSize);
 
-TEST(Btree, ExtractWithUniquePtr) {
-  absl::btree_set<std::unique_ptr<int>, Deref> s;
-  s.insert(absl::make_unique<int>(1));
-  s.insert(absl::make_unique<int>(2));
-  s.insert(absl::make_unique<int>(3));
-  s.insert(absl::make_unique<int>(4));
-  s.insert(absl::make_unique<int>(5));
-  auto nh = s.extract(s.find(absl::make_unique<int>(3)));
-  EXPECT_EQ(s.size(), 4);
-  EXPECT_EQ(*nh.value(), 3);
-  s.insert(std::move(nh));
-  EXPECT_EQ(s.size(), 5);
+      // Extract with iterator
+      auto it = s.find(MovableOnlyInstance(i));
+      nh = s.extract(it);
+      EXPECT_EQ(s.size(), kSize - 1);
+      EXPECT_EQ(nh.value().value(), i);
+      // Insert with node and hint
+      s.insert(s.begin(), std::move(nh));
+      EXPECT_EQ(s.size(), kSize);
+    }
+  }
+  EXPECT_EQ(0, tracker.instances());
+}
+
+template <typename Map>
+void TestExtractWithTrackingForMap() {
+  InstanceTracker tracker;
+  {
+    Map m;
+    // Add enough elements to make sure we test internal nodes too.
+    const size_t kSize = 1000;
+    while (m.size() < kSize) {
+      m.insert(
+          {CopyableMovableInstance(m.size()), MovableOnlyInstance(m.size())});
+    }
+    for (int i = 0; i < kSize; ++i) {
+      // Extract with key
+      auto nh = m.extract(CopyableMovableInstance(i));
+      EXPECT_EQ(m.size(), kSize - 1);
+      EXPECT_EQ(nh.key().value(), i);
+      EXPECT_EQ(nh.mapped().value(), i);
+      // Insert with node
+      m.insert(std::move(nh));
+      EXPECT_EQ(m.size(), kSize);
+
+      // Extract with iterator
+      auto it = m.find(CopyableMovableInstance(i));
+      nh = m.extract(it);
+      EXPECT_EQ(m.size(), kSize - 1);
+      EXPECT_EQ(nh.key().value(), i);
+      EXPECT_EQ(nh.mapped().value(), i);
+      // Insert with node and hint
+      m.insert(m.begin(), std::move(nh));
+      EXPECT_EQ(m.size(), kSize);
+    }
+  }
+  EXPECT_EQ(0, tracker.instances());
+}
+
+TEST(Btree, ExtractTracking) {
+  TestExtractWithTrackingForSet<absl::btree_set<MovableOnlyInstance>>();
+  TestExtractWithTrackingForSet<absl::btree_multiset<MovableOnlyInstance>>();
+  TestExtractWithTrackingForMap<
+      absl::btree_map<CopyableMovableInstance, MovableOnlyInstance>>();
+  TestExtractWithTrackingForMap<
+      absl::btree_multimap<CopyableMovableInstance, MovableOnlyInstance>>();
 }
 
 TEST(Btree, ExtractAndInsertNodeHandleMultiSet) {
@@ -1902,6 +2038,30 @@
   EXPECT_EQ(res, ++other.begin());
 }
 
+TEST(Btree, ExtractMultiMapEquivalentKeys) {
+  // Note: using string keys means a three-way comparator.
+  absl::btree_multimap<std::string, int> map;
+  for (int i = 0; i < 100; ++i) {
+    for (int j = 0; j < 100; ++j) {
+      map.insert({absl::StrCat(i), j});
+    }
+  }
+
+  for (int i = 0; i < 100; ++i) {
+    const std::string key = absl::StrCat(i);
+    auto node_handle = map.extract(key);
+    EXPECT_EQ(node_handle.key(), key);
+    EXPECT_EQ(node_handle.mapped(), 0) << i;
+  }
+
+  for (int i = 0; i < 100; ++i) {
+    const std::string key = absl::StrCat(i);
+    auto node_handle = map.extract(key);
+    EXPECT_EQ(node_handle.key(), key);
+    EXPECT_EQ(node_handle.mapped(), 1) << i;
+  }
+}
+
 // For multisets, insert with hint also affects correctness because we need to
 // insert immediately before the hint if possible.
 struct InsertMultiHintData {
@@ -2043,6 +2203,31 @@
                                Pair(4, 1), Pair(4, 4), Pair(5, 5)));
 }
 
+TEST(Btree, MergeIntoSetMovableOnly) {
+  absl::btree_set<MovableOnlyInstance> src;
+  src.insert(MovableOnlyInstance(1));
+  absl::btree_multiset<MovableOnlyInstance> dst1;
+  dst1.insert(MovableOnlyInstance(2));
+  absl::btree_set<MovableOnlyInstance> dst2;
+
+  // Test merge into multiset.
+  dst1.merge(src);
+
+  EXPECT_TRUE(src.empty());
+  // ElementsAre/ElementsAreArray don't work with move-only types.
+  ASSERT_THAT(dst1, SizeIs(2));
+  EXPECT_EQ(*dst1.begin(), MovableOnlyInstance(1));
+  EXPECT_EQ(*std::next(dst1.begin()), MovableOnlyInstance(2));
+
+  // Test merge into set.
+  dst2.merge(dst1);
+
+  EXPECT_TRUE(dst1.empty());
+  ASSERT_THAT(dst2, SizeIs(2));
+  EXPECT_EQ(*dst2.begin(), MovableOnlyInstance(1));
+  EXPECT_EQ(*std::next(dst2.begin()), MovableOnlyInstance(2));
+}
+
 struct KeyCompareToWeakOrdering {
   template <typename T>
   absl::weak_ordering operator()(const T &a, const T &b) const {
@@ -2074,11 +2259,11 @@
 TEST(Btree, TryEmplaceBasicTest) {
   absl::btree_map<int, std::string> m;
 
-  // Should construct a std::string from the literal.
+  // Should construct a string from the literal.
   m.try_emplace(1, "one");
   EXPECT_EQ(1, m.size());
 
-  // Try other std::string constructors and const lvalue key.
+  // Try other string constructors and const lvalue key.
   const int key(42);
   m.try_emplace(key, 3, 'a');
   m.try_emplace(2, std::string("two"));
@@ -2239,6 +2424,476 @@
   }
 }
 
+TEST(Btree, EmptyTree) {
+  absl::btree_set<int> s;
+  EXPECT_TRUE(s.empty());
+  EXPECT_EQ(s.size(), 0);
+  EXPECT_GT(s.max_size(), 0);
+}
+
+bool IsEven(int k) { return k % 2 == 0; }
+
+TEST(Btree, EraseIf) {
+  // Test that erase_if works with all the container types and supports lambdas.
+  {
+    absl::btree_set<int> s = {1, 3, 5, 6, 100};
+    erase_if(s, [](int k) { return k > 3; });
+    EXPECT_THAT(s, ElementsAre(1, 3));
+  }
+  {
+    absl::btree_multiset<int> s = {1, 3, 3, 5, 6, 6, 100};
+    erase_if(s, [](int k) { return k <= 3; });
+    EXPECT_THAT(s, ElementsAre(5, 6, 6, 100));
+  }
+  {
+    absl::btree_map<int, int> m = {{1, 1}, {3, 3}, {6, 6}, {100, 100}};
+    erase_if(m, [](std::pair<const int, int> kv) { return kv.first > 3; });
+    EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3)));
+  }
+  {
+    absl::btree_multimap<int, int> m = {{1, 1}, {3, 3}, {3, 6},
+                                        {6, 6}, {6, 7}, {100, 6}};
+    erase_if(m, [](std::pair<const int, int> kv) { return kv.second == 6; });
+    EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3), Pair(6, 7)));
+  }
+  // Test that erasing all elements from a large set works and test support for
+  // function pointers.
+  {
+    absl::btree_set<int> s;
+    for (int i = 0; i < 1000; ++i) s.insert(2 * i);
+    erase_if(s, IsEven);
+    EXPECT_THAT(s, IsEmpty());
+  }
+  // Test that erase_if supports other format of function pointers.
+  {
+    absl::btree_set<int> s = {1, 3, 5, 6, 100};
+    erase_if(s, &IsEven);
+    EXPECT_THAT(s, ElementsAre(1, 3, 5));
+  }
+}
+
+TEST(Btree, InsertOrAssign) {
+  absl::btree_map<int, int> m = {{1, 1}, {3, 3}};
+  using value_type = typename decltype(m)::value_type;
+
+  auto ret = m.insert_or_assign(4, 4);
+  EXPECT_EQ(*ret.first, value_type(4, 4));
+  EXPECT_TRUE(ret.second);
+  ret = m.insert_or_assign(3, 100);
+  EXPECT_EQ(*ret.first, value_type(3, 100));
+  EXPECT_FALSE(ret.second);
+
+  auto hint_ret = m.insert_or_assign(ret.first, 3, 200);
+  EXPECT_EQ(*hint_ret, value_type(3, 200));
+  hint_ret = m.insert_or_assign(m.find(1), 0, 1);
+  EXPECT_EQ(*hint_ret, value_type(0, 1));
+  // Test with bad hint.
+  hint_ret = m.insert_or_assign(m.end(), -1, 1);
+  EXPECT_EQ(*hint_ret, value_type(-1, 1));
+
+  EXPECT_THAT(m, ElementsAre(Pair(-1, 1), Pair(0, 1), Pair(1, 1), Pair(3, 200),
+                             Pair(4, 4)));
+}
+
+TEST(Btree, InsertOrAssignMovableOnly) {
+  absl::btree_map<int, MovableOnlyInstance> m;
+  using value_type = typename decltype(m)::value_type;
+
+  auto ret = m.insert_or_assign(4, MovableOnlyInstance(4));
+  EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(4)));
+  EXPECT_TRUE(ret.second);
+  ret = m.insert_or_assign(4, MovableOnlyInstance(100));
+  EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(100)));
+  EXPECT_FALSE(ret.second);
+
+  auto hint_ret = m.insert_or_assign(ret.first, 3, MovableOnlyInstance(200));
+  EXPECT_EQ(*hint_ret, value_type(3, MovableOnlyInstance(200)));
+
+  EXPECT_EQ(m.size(), 2);
+}
+
+TEST(Btree, BitfieldArgument) {
+  union {
+    int n : 1;
+  };
+  n = 0;
+  absl::btree_map<int, int> m;
+  m.erase(n);
+  m.count(n);
+  m.find(n);
+  m.contains(n);
+  m.equal_range(n);
+  m.insert_or_assign(n, n);
+  m.insert_or_assign(m.end(), n, n);
+  m.try_emplace(n);
+  m.try_emplace(m.end(), n);
+  m.at(n);
+  m[n];
+}
+
+TEST(Btree, SetRangeConstructorAndInsertSupportExplicitConversionComparable) {
+  const absl::string_view names[] = {"n1", "n2"};
+
+  absl::btree_set<std::string> name_set1{std::begin(names), std::end(names)};
+  EXPECT_THAT(name_set1, ElementsAreArray(names));
+
+  absl::btree_set<std::string> name_set2;
+  name_set2.insert(std::begin(names), std::end(names));
+  EXPECT_THAT(name_set2, ElementsAreArray(names));
+}
+
+// A type that is explicitly convertible from int and counts constructor calls.
+struct ConstructorCounted {
+  explicit ConstructorCounted(int i) : i(i) { ++constructor_calls; }
+  bool operator==(int other) const { return i == other; }
+
+  int i;
+  static int constructor_calls;
+};
+int ConstructorCounted::constructor_calls = 0;
+
+struct ConstructorCountedCompare {
+  bool operator()(int a, const ConstructorCounted &b) const { return a < b.i; }
+  bool operator()(const ConstructorCounted &a, int b) const { return a.i < b; }
+  bool operator()(const ConstructorCounted &a,
+                  const ConstructorCounted &b) const {
+    return a.i < b.i;
+  }
+  using is_transparent = void;
+};
+
+TEST(Btree,
+     SetRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
+  const int i[] = {0, 1, 1};
+  ConstructorCounted::constructor_calls = 0;
+
+  absl::btree_set<ConstructorCounted, ConstructorCountedCompare> set{
+      std::begin(i), std::end(i)};
+  EXPECT_THAT(set, ElementsAre(0, 1));
+  EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
+
+  set.insert(std::begin(i), std::end(i));
+  EXPECT_THAT(set, ElementsAre(0, 1));
+  EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
+}
+
+TEST(Btree,
+     SetRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
+  const int i[] = {0, 1};
+
+  absl::btree_set<std::vector<void *>> s1{std::begin(i), std::end(i)};
+  EXPECT_THAT(s1, ElementsAre(IsEmpty(), ElementsAre(IsNull())));
+
+  absl::btree_set<std::vector<void *>> s2;
+  s2.insert(std::begin(i), std::end(i));
+  EXPECT_THAT(s2, ElementsAre(IsEmpty(), ElementsAre(IsNull())));
+}
+
+// libstdc++ included with GCC 4.9 has a bug in the std::pair constructors that
+// prevents explicit conversions between pair types.
+// We only run this test for the libstdc++ from GCC 7 or newer because we can't
+// reliably check the libstdc++ version prior to that release.
+#if !defined(__GLIBCXX__) || \
+    (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7)
+TEST(Btree, MapRangeConstructorAndInsertSupportExplicitConversionComparable) {
+  const std::pair<absl::string_view, int> names[] = {{"n1", 1}, {"n2", 2}};
+
+  absl::btree_map<std::string, int> name_map1{std::begin(names),
+                                              std::end(names)};
+  EXPECT_THAT(name_map1, ElementsAre(Pair("n1", 1), Pair("n2", 2)));
+
+  absl::btree_map<std::string, int> name_map2;
+  name_map2.insert(std::begin(names), std::end(names));
+  EXPECT_THAT(name_map2, ElementsAre(Pair("n1", 1), Pair("n2", 2)));
+}
+
+TEST(Btree,
+     MapRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
+  const std::pair<int, int> i[] = {{0, 1}, {1, 2}, {1, 3}};
+  ConstructorCounted::constructor_calls = 0;
+
+  absl::btree_map<ConstructorCounted, int, ConstructorCountedCompare> map{
+      std::begin(i), std::end(i)};
+  EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));
+  EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
+
+  map.insert(std::begin(i), std::end(i));
+  EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));
+  EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
+}
+
+TEST(Btree,
+     MapRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
+  const std::pair<int, int> i[] = {{0, 1}, {1, 2}};
+
+  absl::btree_map<std::vector<void *>, int> m1{std::begin(i), std::end(i)};
+  EXPECT_THAT(m1,
+              ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));
+
+  absl::btree_map<std::vector<void *>, int> m2;
+  m2.insert(std::begin(i), std::end(i));
+  EXPECT_THAT(m2,
+              ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));
+}
+
+TEST(Btree, HeterogeneousTryEmplace) {
+  absl::btree_map<std::string, int> m;
+  std::string s = "key";
+  absl::string_view sv = s;
+  m.try_emplace(sv, 1);
+  EXPECT_EQ(m[s], 1);
+
+  m.try_emplace(m.end(), sv, 2);
+  EXPECT_EQ(m[s], 1);
+}
+
+TEST(Btree, HeterogeneousOperatorMapped) {
+  absl::btree_map<std::string, int> m;
+  std::string s = "key";
+  absl::string_view sv = s;
+  m[sv] = 1;
+  EXPECT_EQ(m[s], 1);
+
+  m[sv] = 2;
+  EXPECT_EQ(m[s], 2);
+}
+
+TEST(Btree, HeterogeneousInsertOrAssign) {
+  absl::btree_map<std::string, int> m;
+  std::string s = "key";
+  absl::string_view sv = s;
+  m.insert_or_assign(sv, 1);
+  EXPECT_EQ(m[s], 1);
+
+  m.insert_or_assign(m.end(), sv, 2);
+  EXPECT_EQ(m[s], 2);
+}
+#endif
+
+// This test requires std::launder for mutable key access in node handles.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+TEST(Btree, NodeHandleMutableKeyAccess) {
+  {
+    absl::btree_map<std::string, std::string> map;
+
+    map["key1"] = "mapped";
+
+    auto nh = map.extract(map.begin());
+    nh.key().resize(3);
+    map.insert(std::move(nh));
+
+    EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
+  }
+  // Also for multimap.
+  {
+    absl::btree_multimap<std::string, std::string> map;
+
+    map.emplace("key1", "mapped");
+
+    auto nh = map.extract(map.begin());
+    nh.key().resize(3);
+    map.insert(std::move(nh));
+
+    EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
+  }
+}
+#endif
+
+struct MultiKey {
+  int i1;
+  int i2;
+};
+
+bool operator==(const MultiKey a, const MultiKey b) {
+  return a.i1 == b.i1 && a.i2 == b.i2;
+}
+
+// A heterogeneous comparator that has different equivalence classes for
+// different lookup types.
+struct MultiKeyComp {
+  using is_transparent = void;
+  bool operator()(const MultiKey a, const MultiKey b) const {
+    if (a.i1 != b.i1) return a.i1 < b.i1;
+    return a.i2 < b.i2;
+  }
+  bool operator()(const int a, const MultiKey b) const { return a < b.i1; }
+  bool operator()(const MultiKey a, const int b) const { return a.i1 < b; }
+};
+
+// A heterogeneous, three-way comparator that has different equivalence classes
+// for different lookup types.
+struct MultiKeyThreeWayComp {
+  using is_transparent = void;
+  absl::weak_ordering operator()(const MultiKey a, const MultiKey b) const {
+    if (a.i1 < b.i1) return absl::weak_ordering::less;
+    if (a.i1 > b.i1) return absl::weak_ordering::greater;
+    if (a.i2 < b.i2) return absl::weak_ordering::less;
+    if (a.i2 > b.i2) return absl::weak_ordering::greater;
+    return absl::weak_ordering::equivalent;
+  }
+  absl::weak_ordering operator()(const int a, const MultiKey b) const {
+    if (a < b.i1) return absl::weak_ordering::less;
+    if (a > b.i1) return absl::weak_ordering::greater;
+    return absl::weak_ordering::equivalent;
+  }
+  absl::weak_ordering operator()(const MultiKey a, const int b) const {
+    if (a.i1 < b) return absl::weak_ordering::less;
+    if (a.i1 > b) return absl::weak_ordering::greater;
+    return absl::weak_ordering::equivalent;
+  }
+};
+
+template <typename Compare>
+class BtreeMultiKeyTest : public ::testing::Test {};
+using MultiKeyComps = ::testing::Types<MultiKeyComp, MultiKeyThreeWayComp>;
+TYPED_TEST_SUITE(BtreeMultiKeyTest, MultiKeyComps);
+
+TYPED_TEST(BtreeMultiKeyTest, EqualRange) {
+  absl::btree_set<MultiKey, TypeParam> set;
+  for (int i = 0; i < 100; ++i) {
+    for (int j = 0; j < 100; ++j) {
+      set.insert({i, j});
+    }
+  }
+
+  for (int i = 0; i < 100; ++i) {
+    auto equal_range = set.equal_range(i);
+    EXPECT_EQ(equal_range.first->i1, i);
+    EXPECT_EQ(equal_range.first->i2, 0) << i;
+    EXPECT_EQ(std::distance(equal_range.first, equal_range.second), 100) << i;
+  }
+}
+
+TYPED_TEST(BtreeMultiKeyTest, Extract) {
+  absl::btree_set<MultiKey, TypeParam> set;
+  for (int i = 0; i < 100; ++i) {
+    for (int j = 0; j < 100; ++j) {
+      set.insert({i, j});
+    }
+  }
+
+  for (int i = 0; i < 100; ++i) {
+    auto node_handle = set.extract(i);
+    EXPECT_EQ(node_handle.value().i1, i);
+    EXPECT_EQ(node_handle.value().i2, 0) << i;
+  }
+
+  for (int i = 0; i < 100; ++i) {
+    auto node_handle = set.extract(i);
+    EXPECT_EQ(node_handle.value().i1, i);
+    EXPECT_EQ(node_handle.value().i2, 1) << i;
+  }
+}
+
+TYPED_TEST(BtreeMultiKeyTest, Erase) {
+  absl::btree_set<MultiKey, TypeParam> set = {
+      {1, 1}, {2, 1}, {2, 2}, {3, 1}};
+  EXPECT_EQ(set.erase(2), 2);
+  EXPECT_THAT(set, ElementsAre(MultiKey{1, 1}, MultiKey{3, 1}));
+}
+
+TYPED_TEST(BtreeMultiKeyTest, Count) {
+  const absl::btree_set<MultiKey, TypeParam> set = {
+      {1, 1}, {2, 1}, {2, 2}, {3, 1}};
+  EXPECT_EQ(set.count(2), 2);
+}
+
+TEST(Btree, AllocConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  Set set(alloc);
+
+  set.insert({1, 2, 3});
+
+  EXPECT_THAT(set, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocInitializerListConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  Set set({1, 2, 3}, alloc);
+
+  EXPECT_THAT(set, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocRangeConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  std::vector<int> v = {1, 2, 3};
+  Set set(v.begin(), v.end(), alloc);
+
+  EXPECT_THAT(set, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocCopyConstructor) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used1 = 0;
+  Alloc alloc1(&bytes_used1);
+  Set set1(alloc1);
+
+  set1.insert({1, 2, 3});
+
+  int64_t bytes_used2 = 0;
+  Alloc alloc2(&bytes_used2);
+  Set set2(set1, alloc2);
+
+  EXPECT_THAT(set1, ElementsAre(1, 2, 3));
+  EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+  EXPECT_GT(bytes_used1, set1.size() * sizeof(int));
+  EXPECT_EQ(bytes_used1, bytes_used2);
+}
+
+TEST(Btree, AllocMoveConstructor_SameAlloc) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used = 0;
+  Alloc alloc(&bytes_used);
+  Set set1(alloc);
+
+  set1.insert({1, 2, 3});
+
+  const int64_t original_bytes_used = bytes_used;
+  EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
+
+  Set set2(std::move(set1), alloc);
+
+  EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+  EXPECT_EQ(bytes_used, original_bytes_used);
+}
+
+TEST(Btree, AllocMoveConstructor_DifferentAlloc) {
+  using Alloc = CountingAllocator<int>;
+  using Set = absl::btree_set<int, std::less<int>, Alloc>;
+  int64_t bytes_used1 = 0;
+  Alloc alloc1(&bytes_used1);
+  Set set1(alloc1);
+
+  set1.insert({1, 2, 3});
+
+  const int64_t original_bytes_used = bytes_used1;
+  EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
+
+  int64_t bytes_used2 = 0;
+  Alloc alloc2(&bytes_used2);
+  Set set2(std::move(set1), alloc2);
+
+  EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+  // We didn't free these bytes allocated by `set1` yet.
+  EXPECT_EQ(bytes_used1, original_bytes_used);
+  EXPECT_EQ(bytes_used2, original_bytes_used);
+}
+
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/btree_test.h b/absl/container/btree_test.h
index 5ecf43c..6249080 100644
--- a/absl/container/btree_test.h
+++ b/absl/container/btree_test.h
@@ -25,9 +25,11 @@
 #include "absl/container/btree_map.h"
 #include "absl/container/btree_set.h"
 #include "absl/container/flat_hash_set.h"
+#include "absl/strings/cord.h"
 #include "absl/time/time.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 // Like remove_const but propagates the removal through std::pair.
@@ -99,6 +101,16 @@
   }
 };
 
+template <>
+struct Generator<Cord> {
+  int maxval;
+  explicit Generator(int m) : maxval(m) {}
+  Cord operator()(int i) const {
+    char buf[16];
+    return Cord(GenerateDigits(buf, i, maxval));
+  }
+};
+
 template <typename T, typename U>
 struct Generator<std::pair<T, U> > {
   Generator<typename remove_pair_const<T>::type> tgen;
@@ -148,6 +160,7 @@
 }
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_BTREE_TEST_H_
diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h
index 70e94ad..fcb3e54 100644
--- a/absl/container/fixed_array.h
+++ b/absl/container/fixed_array.h
@@ -41,6 +41,7 @@
 #include <type_traits>
 
 #include "absl/algorithm/algorithm.h"
+#include "absl/base/config.h"
 #include "absl/base/dynamic_annotations.h"
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/base/macros.h"
@@ -50,6 +51,7 @@
 #include "absl/memory/memory.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
 
@@ -105,13 +107,13 @@
 
  public:
   using allocator_type = typename AllocatorTraits::allocator_type;
-  using value_type = typename allocator_type::value_type;
-  using pointer = typename allocator_type::pointer;
-  using const_pointer = typename allocator_type::const_pointer;
-  using reference = typename allocator_type::reference;
-  using const_reference = typename allocator_type::const_reference;
-  using size_type = typename allocator_type::size_type;
-  using difference_type = typename allocator_type::difference_type;
+  using value_type = typename AllocatorTraits::value_type;
+  using pointer = typename AllocatorTraits::pointer;
+  using const_pointer = typename AllocatorTraits::const_pointer;
+  using reference = value_type&;
+  using const_reference = const value_type&;
+  using size_type = typename AllocatorTraits::size_type;
+  using difference_type = typename AllocatorTraits::difference_type;
   using iterator = pointer;
   using const_iterator = const_pointer;
   using reverse_iterator = std::reverse_iterator<iterator>;
@@ -216,7 +218,7 @@
   // Returns a reference the ith element of the fixed array.
   // REQUIRES: 0 <= i < size()
   reference operator[](size_type i) {
-    assert(i < size());
+    ABSL_HARDENING_ASSERT(i < size());
     return data()[i];
   }
 
@@ -224,14 +226,14 @@
   // ith element of the fixed array.
   // REQUIRES: 0 <= i < size()
   const_reference operator[](size_type i) const {
-    assert(i < size());
+    ABSL_HARDENING_ASSERT(i < size());
     return data()[i];
   }
 
   // FixedArray::at
   //
-  // Bounds-checked access.  Returns a reference to the ith element of the
-  // fiexed array, or throws std::out_of_range
+  // Bounds-checked access.  Returns a reference to the ith element of the fixed
+  // array, or throws std::out_of_range
   reference at(size_type i) {
     if (ABSL_PREDICT_FALSE(i >= size())) {
       base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check");
@@ -251,20 +253,32 @@
   // FixedArray::front()
   //
   // Returns a reference to the first element of the fixed array.
-  reference front() { return *begin(); }
+  reference front() {
+    ABSL_HARDENING_ASSERT(!empty());
+    return data()[0];
+  }
 
   // Overload of FixedArray::front() to return a reference to the first element
   // of a fixed array of const values.
-  const_reference front() const { return *begin(); }
+  const_reference front() const {
+    ABSL_HARDENING_ASSERT(!empty());
+    return data()[0];
+  }
 
   // FixedArray::back()
   //
   // Returns a reference to the last element of the fixed array.
-  reference back() { return *(end() - 1); }
+  reference back() {
+    ABSL_HARDENING_ASSERT(!empty());
+    return data()[size() - 1];
+  }
 
   // Overload of FixedArray::back() to return a reference to the last element
   // of a fixed array of const values.
-  const_reference back() const { return *(end() - 1); }
+  const_reference back() const {
+    ABSL_HARDENING_ASSERT(!empty());
+    return data()[size() - 1];
+  }
 
   // FixedArray::begin()
   //
@@ -409,15 +423,15 @@
     void AnnotateConstruct(size_type n);
     void AnnotateDestruct(size_type n);
 
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
     void* RedzoneBegin() { return &redzone_begin_; }
     void* RedzoneEnd() { return &redzone_end_ + 1; }
-#endif  // ADDRESS_SANITIZER
+#endif  // ABSL_HAVE_ADDRESS_SANITIZER
 
    private:
-    ADDRESS_SANITIZER_REDZONE(redzone_begin_);
+    ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_);
     alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
-    ADDRESS_SANITIZER_REDZONE(redzone_end_);
+    ABSL_ADDRESS_SANITIZER_REDZONE(redzone_end_);
   };
 
   class EmptyInlinedStorage {
@@ -490,24 +504,29 @@
 template <typename T, size_t N, typename A>
 void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateConstruct(
     typename FixedArray<T, N, A>::size_type n) {
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
   if (!n) return;
-  ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), data() + n);
-  ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(), RedzoneBegin());
-#endif                   // ADDRESS_SANITIZER
+  ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(),
+                                     data() + n);
+  ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(),
+                                     RedzoneBegin());
+#endif  // ABSL_HAVE_ADDRESS_SANITIZER
   static_cast<void>(n);  // Mark used when not in asan mode
 }
 
 template <typename T, size_t N, typename A>
 void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateDestruct(
     typename FixedArray<T, N, A>::size_type n) {
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
   if (!n) return;
-  ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, RedzoneEnd());
-  ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(), data());
-#endif                   // ADDRESS_SANITIZER
+  ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n,
+                                     RedzoneEnd());
+  ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(),
+                                     data());
+#endif  // ABSL_HAVE_ADDRESS_SANITIZER
   static_cast<void>(n);  // Mark used when not in asan mode
 }
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_FIXED_ARRAY_H_
diff --git a/absl/container/fixed_array_exception_safety_test.cc b/absl/container/fixed_array_exception_safety_test.cc
index 9aabfd5..e5f5929 100644
--- a/absl/container/fixed_array_exception_safety_test.cc
+++ b/absl/container/fixed_array_exception_safety_test.cc
@@ -12,9 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/container/fixed_array.h"
-
 #include "absl/base/config.h"
+#include "absl/container/fixed_array.h"
 
 #ifdef ABSL_HAVE_EXCEPTIONS
 
@@ -24,6 +23,7 @@
 #include "absl/base/internal/exception_safety_testing.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace {
 
@@ -37,10 +37,19 @@
 using ::testing::TestThrowingCtor;
 
 using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;
-using FixedArr = absl::FixedArray<Thrower, kInlined>;
-
+using ThrowAlloc =
+    testing::ThrowingAllocator<Thrower, testing::AllocSpec::kEverythingThrows>;
 using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
+using MoveThrowAlloc =
+    testing::ThrowingAllocator<MoveThrower,
+                               testing::AllocSpec::kEverythingThrows>;
+
+using FixedArr = absl::FixedArray<Thrower, kInlined>;
+using FixedArrWithAlloc = absl::FixedArray<Thrower, kInlined, ThrowAlloc>;
+
 using MoveFixedArr = absl::FixedArray<MoveThrower, kInlined>;
+using MoveFixedArrWithAlloc =
+    absl::FixedArray<MoveThrower, kInlined, MoveThrowAlloc>;
 
 TEST(FixedArrayExceptionSafety, CopyConstructor) {
   auto small = FixedArr(kSmallSize);
@@ -50,6 +59,14 @@
   TestThrowingCtor<FixedArr>(large);
 }
 
+TEST(FixedArrayExceptionSafety, CopyConstructorWithAlloc) {
+  auto small = FixedArrWithAlloc(kSmallSize);
+  TestThrowingCtor<FixedArrWithAlloc>(small);
+
+  auto large = FixedArrWithAlloc(kLargeSize);
+  TestThrowingCtor<FixedArrWithAlloc>(large);
+}
+
 TEST(FixedArrayExceptionSafety, MoveConstructor) {
   TestThrowingCtor<FixedArr>(FixedArr(kSmallSize));
   TestThrowingCtor<FixedArr>(FixedArr(kLargeSize));
@@ -59,16 +76,35 @@
   TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kLargeSize));
 }
 
+TEST(FixedArrayExceptionSafety, MoveConstructorWithAlloc) {
+  TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kSmallSize));
+  TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kLargeSize));
+
+  // TypeSpec::kNoThrowMove
+  TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kSmallSize));
+  TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kLargeSize));
+}
+
 TEST(FixedArrayExceptionSafety, SizeConstructor) {
   TestThrowingCtor<FixedArr>(kSmallSize);
   TestThrowingCtor<FixedArr>(kLargeSize);
 }
 
+TEST(FixedArrayExceptionSafety, SizeConstructorWithAlloc) {
+  TestThrowingCtor<FixedArrWithAlloc>(kSmallSize);
+  TestThrowingCtor<FixedArrWithAlloc>(kLargeSize);
+}
+
 TEST(FixedArrayExceptionSafety, SizeValueConstructor) {
   TestThrowingCtor<FixedArr>(kSmallSize, Thrower());
   TestThrowingCtor<FixedArr>(kLargeSize, Thrower());
 }
 
+TEST(FixedArrayExceptionSafety, SizeValueConstructorWithAlloc) {
+  TestThrowingCtor<FixedArrWithAlloc>(kSmallSize, Thrower());
+  TestThrowingCtor<FixedArrWithAlloc>(kLargeSize, Thrower());
+}
+
 TEST(FixedArrayExceptionSafety, IteratorConstructor) {
   auto small = FixedArr(kSmallSize);
   TestThrowingCtor<FixedArr>(small.begin(), small.end());
@@ -77,6 +113,14 @@
   TestThrowingCtor<FixedArr>(large.begin(), large.end());
 }
 
+TEST(FixedArrayExceptionSafety, IteratorConstructorWithAlloc) {
+  auto small = FixedArrWithAlloc(kSmallSize);
+  TestThrowingCtor<FixedArrWithAlloc>(small.begin(), small.end());
+
+  auto large = FixedArrWithAlloc(kLargeSize);
+  TestThrowingCtor<FixedArrWithAlloc>(large.begin(), large.end());
+}
+
 TEST(FixedArrayExceptionSafety, InitListConstructor) {
   constexpr int small_inlined = 3;
   using SmallFixedArr = absl::FixedArray<Thrower, small_inlined>;
@@ -90,9 +134,23 @@
       Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}});
 }
 
-testing::AssertionResult ReadMemory(FixedArr* fixed_arr) {
-  // Marked volatile to prevent optimization. Used for running asan tests.
-  volatile int sum = 0;
+TEST(FixedArrayExceptionSafety, InitListConstructorWithAlloc) {
+  constexpr int small_inlined = 3;
+  using SmallFixedArrWithAlloc =
+      absl::FixedArray<Thrower, small_inlined, ThrowAlloc>;
+
+  TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{});
+  // Test inlined allocation
+  TestThrowingCtor<SmallFixedArrWithAlloc>(
+      std::initializer_list<Thrower>{Thrower{}, Thrower{}});
+  // Test out of line allocation
+  TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{
+      Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}});
+}
+
+template <typename FixedArrT>
+testing::AssertionResult ReadMemory(FixedArrT* fixed_arr) {
+  int sum = 0;
   for (const auto& thrower : *fixed_arr) {
     sum += thrower.Get();
   }
@@ -101,7 +159,7 @@
 
 TEST(FixedArrayExceptionSafety, Fill) {
   auto test_fill = testing::MakeExceptionSafetyTester()
-                       .WithContracts(ReadMemory)
+                       .WithContracts(ReadMemory<FixedArr>)
                        .WithOperation([&](FixedArr* fixed_arr_ptr) {
                          auto thrower =
                              Thrower(kUpdatedValue, testing::nothrow_ctor);
@@ -116,8 +174,28 @@
           .Test());
 }
 
+TEST(FixedArrayExceptionSafety, FillWithAlloc) {
+  auto test_fill = testing::MakeExceptionSafetyTester()
+                       .WithContracts(ReadMemory<FixedArrWithAlloc>)
+                       .WithOperation([&](FixedArrWithAlloc* fixed_arr_ptr) {
+                         auto thrower =
+                             Thrower(kUpdatedValue, testing::nothrow_ctor);
+                         fixed_arr_ptr->fill(thrower);
+                       });
+
+  EXPECT_TRUE(test_fill
+                  .WithInitialValue(
+                      FixedArrWithAlloc(kSmallSize, Thrower(kInitialValue)))
+                  .Test());
+  EXPECT_TRUE(test_fill
+                  .WithInitialValue(
+                      FixedArrWithAlloc(kLargeSize, Thrower(kInitialValue)))
+                  .Test());
+}
+
 }  // namespace
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_HAVE_EXCEPTIONS
diff --git a/absl/container/fixed_array_test.cc b/absl/container/fixed_array_test.cc
index 2b1cf47..49598e7 100644
--- a/absl/container/fixed_array_test.cc
+++ b/absl/container/fixed_array_test.cc
@@ -27,7 +27,10 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/exception_testing.h"
+#include "absl/base/options.h"
+#include "absl/container/internal/counting_allocator.h"
 #include "absl/hash/hash_testing.h"
 #include "absl/memory/memory.h"
 
@@ -188,6 +191,21 @@
                                  "failed bounds check");
 }
 
+TEST(FixedArrayTest, Hardened) {
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+  absl::FixedArray<int> a = {1, 2, 3};
+  EXPECT_EQ(a[2], 3);
+  EXPECT_DEATH_IF_SUPPORTED(a[3], "");
+  EXPECT_DEATH_IF_SUPPORTED(a[-1], "");
+
+  absl::FixedArray<int> empty(0);
+  EXPECT_DEATH_IF_SUPPORTED(empty[0], "");
+  EXPECT_DEATH_IF_SUPPORTED(empty[-1], "");
+  EXPECT_DEATH_IF_SUPPORTED(empty.front(), "");
+  EXPECT_DEATH_IF_SUPPORTED(empty.back(), "");
+#endif
+}
+
 TEST(FixedArrayRelationalsTest, EqualArrays) {
   for (int i = 0; i < 10; ++i) {
     absl::FixedArray<int, 5> a1(i);
@@ -604,19 +622,16 @@
   empty.fill(fill_val);
 }
 
-// TODO(johnsoncj): Investigate InlinedStorage default initialization in GCC 4.x
 #ifndef __GNUC__
 TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) {
   using T = char;
   constexpr auto capacity = 10;
   using FixedArrType = absl::FixedArray<T, capacity>;
-  using FixedArrBuffType =
-      absl::aligned_storage_t<sizeof(FixedArrType), alignof(FixedArrType)>;
   constexpr auto scrubbed_bits = 0x95;
   constexpr auto length = capacity / 2;
 
-  FixedArrBuffType buff;
-  std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrBuffType));
+  alignas(FixedArrType) unsigned char buff[sizeof(FixedArrType)];
+  std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrType));
 
   FixedArrType* arr =
       ::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length);
@@ -625,70 +640,9 @@
 }
 #endif  // __GNUC__
 
-// This is a stateful allocator, but the state lives outside of the
-// allocator (in whatever test is using the allocator). This is odd
-// but helps in tests where the allocator is propagated into nested
-// containers - that chain of allocators uses the same state and is
-// thus easier to query for aggregate allocation information.
-template <typename T>
-class CountingAllocator : public std::allocator<T> {
- public:
-  using Alloc = std::allocator<T>;
-  using pointer = typename Alloc::pointer;
-  using size_type = typename Alloc::size_type;
-
-  CountingAllocator() : bytes_used_(nullptr), instance_count_(nullptr) {}
-  explicit CountingAllocator(int64_t* b)
-      : bytes_used_(b), instance_count_(nullptr) {}
-  CountingAllocator(int64_t* b, int64_t* a)
-      : bytes_used_(b), instance_count_(a) {}
-
-  template <typename U>
-  explicit CountingAllocator(const CountingAllocator<U>& x)
-      : Alloc(x),
-        bytes_used_(x.bytes_used_),
-        instance_count_(x.instance_count_) {}
-
-  pointer allocate(size_type n, const void* const hint = nullptr) {
-    assert(bytes_used_ != nullptr);
-    *bytes_used_ += n * sizeof(T);
-    return Alloc::allocate(n, hint);
-  }
-
-  void deallocate(pointer p, size_type n) {
-    Alloc::deallocate(p, n);
-    assert(bytes_used_ != nullptr);
-    *bytes_used_ -= n * sizeof(T);
-  }
-
-  template <typename... Args>
-  void construct(pointer p, Args&&... args) {
-    Alloc::construct(p, absl::forward<Args>(args)...);
-    if (instance_count_) {
-      *instance_count_ += 1;
-    }
-  }
-
-  void destroy(pointer p) {
-    Alloc::destroy(p);
-    if (instance_count_) {
-      *instance_count_ -= 1;
-    }
-  }
-
-  template <typename U>
-  class rebind {
-   public:
-    using other = CountingAllocator<U>;
-  };
-
-  int64_t* bytes_used_;
-  int64_t* instance_count_;
-};
-
 TEST(AllocatorSupportTest, CountInlineAllocations) {
   constexpr size_t inlined_size = 4;
-  using Alloc = CountingAllocator<int>;
+  using Alloc = absl::container_internal::CountingAllocator<int>;
   using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
 
   int64_t allocated = 0;
@@ -709,7 +663,7 @@
 
 TEST(AllocatorSupportTest, CountOutoflineAllocations) {
   constexpr size_t inlined_size = 4;
-  using Alloc = CountingAllocator<int>;
+  using Alloc = absl::container_internal::CountingAllocator<int>;
   using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
 
   int64_t allocated = 0;
@@ -730,7 +684,7 @@
 
 TEST(AllocatorSupportTest, CountCopyInlineAllocations) {
   constexpr size_t inlined_size = 4;
-  using Alloc = CountingAllocator<int>;
+  using Alloc = absl::container_internal::CountingAllocator<int>;
   using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
 
   int64_t allocated1 = 0;
@@ -758,7 +712,7 @@
 
 TEST(AllocatorSupportTest, CountCopyOutoflineAllocations) {
   constexpr size_t inlined_size = 4;
-  using Alloc = CountingAllocator<int>;
+  using Alloc = absl::container_internal::CountingAllocator<int>;
   using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
 
   int64_t allocated1 = 0;
@@ -790,7 +744,7 @@
   using testing::SizeIs;
 
   constexpr size_t inlined_size = 4;
-  using Alloc = CountingAllocator<int>;
+  using Alloc = absl::container_internal::CountingAllocator<int>;
   using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
 
   {
@@ -814,16 +768,16 @@
   }
 }
 
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
 TEST(FixedArrayTest, AddressSanitizerAnnotations1) {
   absl::FixedArray<int, 32> a(10);
   int* raw = a.data();
   raw[0] = 0;
   raw[9] = 0;
-  EXPECT_DEATH(raw[-2] = 0, "container-overflow");
-  EXPECT_DEATH(raw[-1] = 0, "container-overflow");
-  EXPECT_DEATH(raw[10] = 0, "container-overflow");
-  EXPECT_DEATH(raw[31] = 0, "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[-2] = 0, "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[10] = 0, "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[31] = 0, "container-overflow");
 }
 
 TEST(FixedArrayTest, AddressSanitizerAnnotations2) {
@@ -831,10 +785,10 @@
   char* raw = a.data();
   raw[0] = 0;
   raw[11] = 0;
-  EXPECT_DEATH(raw[-7] = 0, "container-overflow");
-  EXPECT_DEATH(raw[-1] = 0, "container-overflow");
-  EXPECT_DEATH(raw[12] = 0, "container-overflow");
-  EXPECT_DEATH(raw[17] = 0, "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[-7] = 0, "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[12] = 0, "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[17] = 0, "container-overflow");
 }
 
 TEST(FixedArrayTest, AddressSanitizerAnnotations3) {
@@ -842,8 +796,8 @@
   uint64_t* raw = a.data();
   raw[0] = 0;
   raw[19] = 0;
-  EXPECT_DEATH(raw[-1] = 0, "container-overflow");
-  EXPECT_DEATH(raw[20] = 0, "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[20] = 0, "container-overflow");
 }
 
 TEST(FixedArrayTest, AddressSanitizerAnnotations4) {
@@ -855,13 +809,13 @@
   // there is only a 8-byte red zone before the container range, so we only
   // access the last 4 bytes of the struct to make sure it stays within the red
   // zone.
-  EXPECT_DEATH(raw[-1].z_ = 0, "container-overflow");
-  EXPECT_DEATH(raw[10] = ThreeInts(), "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[-1].z_ = 0, "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[10] = ThreeInts(), "container-overflow");
   // The actual size of storage is kDefaultBytes=256, 21*12 = 252,
   // so reading raw[21] should still trigger the correct warning.
-  EXPECT_DEATH(raw[21] = ThreeInts(), "container-overflow");
+  EXPECT_DEATH_IF_SUPPORTED(raw[21] = ThreeInts(), "container-overflow");
 }
-#endif  // ADDRESS_SANITIZER
+#endif  // ABSL_HAVE_ADDRESS_SANITIZER
 
 TEST(FixedArrayTest, AbslHashValueWorks) {
   using V = absl::FixedArray<int>;
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h
index 5c16ac8..74def0d 100644
--- a/absl/container/flat_hash_map.h
+++ b/absl/container/flat_hash_map.h
@@ -42,6 +42,7 @@
 #include "absl/memory/memory.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 template <class K, class V>
 struct FlatHashMapPolicy;
@@ -233,7 +234,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // flat_hash_map::insert()
@@ -382,6 +384,11 @@
   //   key value and returns a node handle owning that extracted data. If the
   //   `flat_hash_map` does not contain an element with a matching key, this
   //   function returns an empty node handle.
+  //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
   using Base::extract;
 
   // flat_hash_map::merge()
@@ -401,7 +408,7 @@
   // for the past-the-end iterator, which is invalidated.
   //
   // `swap()` requires that the flat hash map's hashing and key equivalence
-  // functions be Swappable, and are exchaged using unqualified calls to
+  // functions be Swappable, and are exchanged using unqualified calls to
   // non-member `swap()`. If the map's allocator has
   // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value`
   // set to `true`, the allocators are also exchanged using an unqualified call
@@ -531,6 +538,15 @@
   using Base::key_eq;
 };
 
+// erase_if(flat_hash_map<>, Pred)
+//
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+template <typename K, typename V, typename H, typename E, typename A,
+          typename Predicate>
+void erase_if(flat_hash_map<K, V, H, E, A>& c, Predicate pred) {
+  container_internal::EraseIf(pred, &c);
+}
+
 namespace container_internal {
 
 template <class K, class V>
@@ -584,6 +600,7 @@
 
 }  // namespace container_algorithm_internal
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_FLAT_HASH_MAP_H_
diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc
index 6cff1a2..89ec60c 100644
--- a/absl/container/flat_hash_map_test.cc
+++ b/absl/container/flat_hash_map_test.cc
@@ -16,6 +16,7 @@
 
 #include <memory>
 
+#include "absl/base/internal/raw_logging.h"
 #include "absl/container/internal/hash_generator_testing.h"
 #include "absl/container/internal/unordered_map_constructor_test.h"
 #include "absl/container/internal/unordered_map_lookup_test.h"
@@ -24,14 +25,29 @@
 #include "absl/types/any.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 using ::absl::container_internal::hash_internal::Enum;
 using ::absl::container_internal::hash_internal::EnumClass;
 using ::testing::_;
+using ::testing::IsEmpty;
 using ::testing::Pair;
 using ::testing::UnorderedElementsAre;
 
+// Check that absl::flat_hash_map works in a global constructor.
+struct BeforeMain {
+  BeforeMain() {
+    absl::flat_hash_map<int, int> x;
+    x.insert({1, 1});
+    ABSL_RAW_CHECK(x.find(0) == x.end(), "x should not contain 0");
+    auto it = x.find(1);
+    ABSL_RAW_CHECK(it != x.end(), "x should contain 1");
+    ABSL_RAW_CHECK(it->second, "1 should map to 1");
+  }
+};
+const BeforeMain before_main;
+
 template <class K, class V>
 using Map = flat_hash_map<K, V, StatefulTestingHash, StatefulTestingEqual,
                           Alloc<std::pair<const K, V>>>;
@@ -214,41 +230,59 @@
   EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 17), Pair(2, 9)));
 }
 
-#if (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) && \
-    !defined(__EMSCRIPTEN__)
-TEST(FlatHashMap, Any) {
-  absl::flat_hash_map<int, absl::any> m;
-  m.emplace(1, 7);
-  auto it = m.find(1);
-  ASSERT_NE(it, m.end());
-  EXPECT_EQ(7, absl::any_cast<int>(it->second));
+bool FirstIsEven(std::pair<const int, int> p) { return p.first % 2 == 0; }
 
-  m.emplace(std::piecewise_construct, std::make_tuple(2), std::make_tuple(8));
-  it = m.find(2);
-  ASSERT_NE(it, m.end());
-  EXPECT_EQ(8, absl::any_cast<int>(it->second));
-
-  m.emplace(std::piecewise_construct, std::make_tuple(3),
-            std::make_tuple(absl::any(9)));
-  it = m.find(3);
-  ASSERT_NE(it, m.end());
-  EXPECT_EQ(9, absl::any_cast<int>(it->second));
-
-  struct H {
-    size_t operator()(const absl::any&) const { return 0; }
-  };
-  struct E {
-    bool operator()(const absl::any&, const absl::any&) const { return true; }
-  };
-  absl::flat_hash_map<absl::any, int, H, E> m2;
-  m2.emplace(1, 7);
-  auto it2 = m2.find(1);
-  ASSERT_NE(it2, m2.end());
-  EXPECT_EQ(7, it2->second);
+TEST(FlatHashMap, EraseIf) {
+  // Erase all elements.
+  {
+    flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    erase_if(s, [](std::pair<const int, int>) { return true; });
+    EXPECT_THAT(s, IsEmpty());
+  }
+  // Erase no elements.
+  {
+    flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    erase_if(s, [](std::pair<const int, int>) { return false; });
+    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3),
+                                        Pair(4, 4), Pair(5, 5)));
+  }
+  // Erase specific elements.
+  {
+    flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    erase_if(s,
+             [](std::pair<const int, int> kvp) { return kvp.first % 2 == 1; });
+    EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4)));
+  }
+  // Predicate is function reference.
+  {
+    flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    erase_if(s, FirstIsEven);
+    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
+  }
+  // Predicate is function pointer.
+  {
+    flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    erase_if(s, &FirstIsEven);
+    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
+  }
 }
-#endif  // (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) &&
-        // !defined(__EMSCRIPTEN__)
+
+// This test requires std::launder for mutable key access in node handles.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+TEST(FlatHashMap, NodeHandleMutableKeyAccess) {
+  flat_hash_map<std::string, std::string> map;
+
+  map["key1"] = "mapped";
+
+  auto nh = map.extract(map.begin());
+  nh.key().resize(3);
+  map.insert(std::move(nh));
+
+  EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
+}
+#endif
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index 2a51c34..6b89da6 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -40,6 +40,7 @@
 #include "absl/memory/memory.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 template <typename T>
 struct FlatHashSetPolicy;
@@ -226,7 +227,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // flat_hash_set::insert()
@@ -322,7 +324,7 @@
 
   // flat_hash_set::merge()
   //
-  // Extracts elements from a given `source` flat hash map into this
+  // Extracts elements from a given `source` flat hash set into this
   // `flat_hash_set`. If the destination `flat_hash_set` already contains an
   // element with an equivalent key, that element is not extracted.
   using Base::merge;
@@ -438,6 +440,14 @@
   using Base::key_eq;
 };
 
+// erase_if(flat_hash_set<>, Pred)
+//
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+template <typename T, typename H, typename E, typename A, typename Predicate>
+void erase_if(flat_hash_set<T, H, E, A>& c, Predicate pred) {
+  container_internal::EraseIf(pred, &c);
+}
+
 namespace container_internal {
 
 template <class T>
@@ -488,6 +498,7 @@
 
 }  // namespace container_algorithm_internal
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_FLAT_HASH_SET_H_
diff --git a/absl/container/flat_hash_set_test.cc b/absl/container/flat_hash_set_test.cc
index b55be59..8f6f994 100644
--- a/absl/container/flat_hash_set_test.cc
+++ b/absl/container/flat_hash_set_test.cc
@@ -16,6 +16,7 @@
 
 #include <vector>
 
+#include "absl/base/internal/raw_logging.h"
 #include "absl/container/internal/hash_generator_testing.h"
 #include "absl/container/internal/unordered_set_constructor_test.h"
 #include "absl/container/internal/unordered_set_lookup_test.h"
@@ -25,15 +26,28 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
 using ::absl::container_internal::hash_internal::Enum;
 using ::absl::container_internal::hash_internal::EnumClass;
+using ::testing::IsEmpty;
 using ::testing::Pointee;
 using ::testing::UnorderedElementsAre;
 using ::testing::UnorderedElementsAreArray;
 
+// Check that absl::flat_hash_set works in a global constructor.
+struct BeforeMain {
+  BeforeMain() {
+    absl::flat_hash_set<int> x;
+    x.insert(1);
+    ABSL_RAW_CHECK(!x.contains(0), "x should not contain 0");
+    ABSL_RAW_CHECK(x.contains(1), "x should contain 1");
+  }
+};
+const BeforeMain before_main;
+
 template <class T>
 using Set =
     absl::flat_hash_set<T, StatefulTestingHash, StatefulTestingEqual, Alloc<T>>;
@@ -123,6 +137,42 @@
   EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23)));
 }
 
+bool IsEven(int k) { return k % 2 == 0; }
+
+TEST(FlatHashSet, EraseIf) {
+  // Erase all elements.
+  {
+    flat_hash_set<int> s = {1, 2, 3, 4, 5};
+    erase_if(s, [](int) { return true; });
+    EXPECT_THAT(s, IsEmpty());
+  }
+  // Erase no elements.
+  {
+    flat_hash_set<int> s = {1, 2, 3, 4, 5};
+    erase_if(s, [](int) { return false; });
+    EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+  }
+  // Erase specific elements.
+  {
+    flat_hash_set<int> s = {1, 2, 3, 4, 5};
+    erase_if(s, [](int k) { return k % 2 == 1; });
+    EXPECT_THAT(s, UnorderedElementsAre(2, 4));
+  }
+  // Predicate is function reference.
+  {
+    flat_hash_set<int> s = {1, 2, 3, 4, 5};
+    erase_if(s, IsEven);
+    EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
+  }
+  // Predicate is function pointer.
+  {
+    flat_hash_set<int> s = {1, 2, 3, 4, 5};
+    erase_if(s, &IsEven);
+    EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
+  }
+}
+
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index 5138348..90bb96e 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -48,12 +48,14 @@
 
 #include "absl/algorithm/algorithm.h"
 #include "absl/base/internal/throw_delegate.h"
+#include "absl/base/macros.h"
 #include "absl/base/optimization.h"
 #include "absl/base/port.h"
 #include "absl/container/internal/inlined_vector.h"
 #include "absl/memory/memory.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 // -----------------------------------------------------------------------------
 // InlinedVector
 // -----------------------------------------------------------------------------
@@ -62,16 +64,17 @@
 // `std::vector` for use cases where the vector's size is sufficiently small
 // that it can be inlined. If the inlined vector does grow beyond its estimated
 // capacity, it will trigger an initial allocation on the heap, and will behave
-// as a `std:vector`. The API of the `absl::InlinedVector` within this file is
+// as a `std::vector`. The API of the `absl::InlinedVector` within this file is
 // designed to cover the same API footprint as covered by `std::vector`.
 template <typename T, size_t N, typename A = std::allocator<T>>
 class InlinedVector {
   static_assert(N > 0, "`absl::InlinedVector` requires an inlined capacity.");
 
   using Storage = inlined_vector_internal::Storage<T, N, A>;
-  using rvalue_reference = typename Storage::rvalue_reference;
-  using MoveIterator = typename Storage::MoveIterator;
+
   using AllocatorTraits = typename Storage::AllocatorTraits;
+  using RValueReference = typename Storage::RValueReference;
+  using MoveIterator = typename Storage::MoveIterator;
   using IsMemcpyOk = typename Storage::IsMemcpyOk;
 
   template <typename Iterator>
@@ -92,10 +95,10 @@
   using value_type = typename Storage::value_type;
   using pointer = typename Storage::pointer;
   using const_pointer = typename Storage::const_pointer;
-  using reference = typename Storage::reference;
-  using const_reference = typename Storage::const_reference;
   using size_type = typename Storage::size_type;
   using difference_type = typename Storage::difference_type;
+  using reference = typename Storage::reference;
+  using const_reference = typename Storage::const_reference;
   using iterator = typename Storage::iterator;
   using const_iterator = typename Storage::const_iterator;
   using reverse_iterator = typename Storage::reverse_iterator;
@@ -305,16 +308,14 @@
   //
   // Returns a `reference` to the `i`th element of the inlined vector.
   reference operator[](size_type i) {
-    assert(i < size());
-
+    ABSL_HARDENING_ASSERT(i < size());
     return data()[i];
   }
 
   // Overload of `InlinedVector::operator[](...)` that returns a
   // `const_reference` to the `i`th element of the inlined vector.
   const_reference operator[](size_type i) const {
-    assert(i < size());
-
+    ABSL_HARDENING_ASSERT(i < size());
     return data()[i];
   }
 
@@ -329,7 +330,6 @@
       base_internal::ThrowStdOutOfRange(
           "`InlinedVector::at(size_type)` failed bounds check");
     }
-
     return data()[i];
   }
 
@@ -343,7 +343,6 @@
       base_internal::ThrowStdOutOfRange(
           "`InlinedVector::at(size_type) const` failed bounds check");
     }
-
     return data()[i];
   }
 
@@ -351,34 +350,30 @@
   //
   // Returns a `reference` to the first element of the inlined vector.
   reference front() {
-    assert(!empty());
-
-    return at(0);
+    ABSL_HARDENING_ASSERT(!empty());
+    return data()[0];
   }
 
   // Overload of `InlinedVector::front()` that returns a `const_reference` to
   // the first element of the inlined vector.
   const_reference front() const {
-    assert(!empty());
-
-    return at(0);
+    ABSL_HARDENING_ASSERT(!empty());
+    return data()[0];
   }
 
   // `InlinedVector::back()`
   //
   // Returns a `reference` to the last element of the inlined vector.
   reference back() {
-    assert(!empty());
-
-    return at(size() - 1);
+    ABSL_HARDENING_ASSERT(!empty());
+    return data()[size() - 1];
   }
 
   // Overload of `InlinedVector::back()` that returns a `const_reference` to the
   // last element of the inlined vector.
   const_reference back() const {
-    assert(!empty());
-
-    return at(size() - 1);
+    ABSL_HARDENING_ASSERT(!empty());
+    return data()[size() - 1];
   }
 
   // `InlinedVector::begin()`
@@ -529,7 +524,7 @@
   void assign(InputIterator first, InputIterator last) {
     size_type i = 0;
     for (; i < size() && first != last; ++i, static_cast<void>(++first)) {
-      at(i) = *first;
+      data()[i] = *first;
     }
 
     erase(data() + i, data() + size());
@@ -540,9 +535,12 @@
   //
   // Resizes the inlined vector to contain `n` elements.
   //
-  // NOTE: if `n` is smaller than `size()`, extra elements are destroyed. If `n`
+  // NOTE: If `n` is smaller than `size()`, extra elements are destroyed. If `n`
   // is larger than `size()`, new elements are value-initialized.
-  void resize(size_type n) { storage_.Resize(DefaultValueAdapter(), n); }
+  void resize(size_type n) {
+    ABSL_HARDENING_ASSERT(n <= max_size());
+    storage_.Resize(DefaultValueAdapter(), n);
+  }
 
   // Overload of `InlinedVector::resize(...)` that resizes the inlined vector to
   // contain `n` elements.
@@ -550,6 +548,7 @@
   // NOTE: if `n` is smaller than `size()`, extra elements are destroyed. If `n`
   // is larger than `size()`, new elements are copied-constructed from `v`.
   void resize(size_type n, const_reference v) {
+    ABSL_HARDENING_ASSERT(n <= max_size());
     storage_.Resize(CopyValueAdapter(v), n);
   }
 
@@ -563,7 +562,7 @@
 
   // Overload of `InlinedVector::insert(...)` that inserts `v` at `pos` using
   // move semantics, returning an `iterator` to the newly inserted element.
-  iterator insert(const_iterator pos, rvalue_reference v) {
+  iterator insert(const_iterator pos, RValueReference v) {
     return emplace(pos, std::move(v));
   }
 
@@ -571,8 +570,8 @@
   // of `v` starting at `pos`, returning an `iterator` pointing to the first of
   // the newly inserted elements.
   iterator insert(const_iterator pos, size_type n, const_reference v) {
-    assert(pos >= begin());
-    assert(pos <= end());
+    ABSL_HARDENING_ASSERT(pos >= begin());
+    ABSL_HARDENING_ASSERT(pos <= end());
 
     if (ABSL_PREDICT_TRUE(n != 0)) {
       value_type dealias = v;
@@ -598,8 +597,8 @@
             EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
   iterator insert(const_iterator pos, ForwardIterator first,
                   ForwardIterator last) {
-    assert(pos >= begin());
-    assert(pos <= end());
+    ABSL_HARDENING_ASSERT(pos >= begin());
+    ABSL_HARDENING_ASSERT(pos <= end());
 
     if (ABSL_PREDICT_TRUE(first != last)) {
       return storage_.Insert(pos, IteratorValueAdapter<ForwardIterator>(first),
@@ -617,8 +616,8 @@
   template <typename InputIterator,
             DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
   iterator insert(const_iterator pos, InputIterator first, InputIterator last) {
-    assert(pos >= begin());
-    assert(pos <= end());
+    ABSL_HARDENING_ASSERT(pos >= begin());
+    ABSL_HARDENING_ASSERT(pos <= end());
 
     size_type index = std::distance(cbegin(), pos);
     for (size_type i = index; first != last; ++i, static_cast<void>(++first)) {
@@ -634,8 +633,8 @@
   // `pos`, returning an `iterator` pointing to the newly emplaced element.
   template <typename... Args>
   iterator emplace(const_iterator pos, Args&&... args) {
-    assert(pos >= begin());
-    assert(pos <= end());
+    ABSL_HARDENING_ASSERT(pos >= begin());
+    ABSL_HARDENING_ASSERT(pos <= end());
 
     value_type dealias(std::forward<Args>(args)...);
     return storage_.Insert(pos,
@@ -660,7 +659,7 @@
 
   // Overload of `InlinedVector::push_back(...)` for inserting `v` at `end()`
   // using move semantics.
-  void push_back(rvalue_reference v) {
+  void push_back(RValueReference v) {
     static_cast<void>(emplace_back(std::move(v)));
   }
 
@@ -668,7 +667,7 @@
   //
   // Destroys the element at `back()`, reducing the size by `1`.
   void pop_back() noexcept {
-    assert(!empty());
+    ABSL_HARDENING_ASSERT(!empty());
 
     AllocatorTraits::destroy(*storage_.GetAllocPtr(), data() + (size() - 1));
     storage_.SubtractSize(1);
@@ -681,8 +680,8 @@
   //
   // NOTE: may return `end()`, which is not dereferencable.
   iterator erase(const_iterator pos) {
-    assert(pos >= begin());
-    assert(pos < end());
+    ABSL_HARDENING_ASSERT(pos >= begin());
+    ABSL_HARDENING_ASSERT(pos < end());
 
     return storage_.Erase(pos, pos + 1);
   }
@@ -693,9 +692,9 @@
   //
   // NOTE: may return `end()`, which is not dereferencable.
   iterator erase(const_iterator from, const_iterator to) {
-    assert(from >= begin());
-    assert(from <= to);
-    assert(to <= end());
+    ABSL_HARDENING_ASSERT(from >= begin());
+    ABSL_HARDENING_ASSERT(from <= to);
+    ABSL_HARDENING_ASSERT(to <= end());
 
     if (ABSL_PREDICT_TRUE(from != to)) {
       return storage_.Erase(from, to);
@@ -840,6 +839,7 @@
   return H::combine(H::combine_contiguous(std::move(h), a.data(), size), size);
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INLINED_VECTOR_H_
diff --git a/absl/container/inlined_vector_benchmark.cc b/absl/container/inlined_vector_benchmark.cc
index 3f2b4ed..b8dafe9 100644
--- a/absl/container/inlined_vector_benchmark.cc
+++ b/absl/container/inlined_vector_benchmark.cc
@@ -83,7 +83,7 @@
   }
   ABSL_RAW_LOG(
       FATAL,
-      "Failed to find a std::string larger than the short std::string optimization");
+      "Failed to find a string larger than the short string optimization");
   return -1;
 }
 
diff --git a/absl/container/inlined_vector_exception_safety_test.cc b/absl/container/inlined_vector_exception_safety_test.cc
index 25994f1..0e6a05b 100644
--- a/absl/container/inlined_vector_exception_safety_test.cc
+++ b/absl/container/inlined_vector_exception_safety_test.cc
@@ -16,7 +16,7 @@
 
 #include "absl/base/config.h"
 
-#ifdef ABSL_HAVE_EXCEPTIONS
+#if defined(ABSL_HAVE_EXCEPTIONS)
 
 #include <array>
 #include <initializer_list>
@@ -364,9 +364,11 @@
   using VecT = typename TypeParam::VecT;
   constexpr static auto size = TypeParam::GetSizeAt(0);
 
+  // For testing calls to `emplace_back(...)` that reallocate.
   VecT full_vec{size};
   full_vec.resize(full_vec.capacity());
 
+  // For testing calls to `emplace_back(...)` that don't reallocate.
   VecT nonfull_vec{size};
   nonfull_vec.reserve(size + 1);
 
@@ -374,12 +376,11 @@
       InlinedVectorInvariants<VecT>);
 
   EXPECT_TRUE(tester.WithInitialValue(nonfull_vec).Test([](VecT* vec) {
-    vec->emplace_back();  //
+    vec->emplace_back();
   }));
 
-  EXPECT_TRUE(tester.WithInitialValue(full_vec).Test([](VecT* vec) {
-    vec->emplace_back();  //
-  }));
+  EXPECT_TRUE(tester.WithInitialValue(full_vec).Test(
+      [](VecT* vec) { vec->emplace_back(); }));
 }
 
 TYPED_TEST(OneSizeTest, PopBack) {
@@ -418,6 +419,19 @@
 
   EXPECT_TRUE(tester.Test([](VecT* vec) {
     auto it = vec->begin();
+    vec->erase(it, it);
+  }));
+  EXPECT_TRUE(tester.Test([](VecT* vec) {
+    auto it = vec->begin() + (vec->size() / 2);
+    vec->erase(it, it);
+  }));
+  EXPECT_TRUE(tester.Test([](VecT* vec) {
+    auto it = vec->begin() + (vec->size() - 1);
+    vec->erase(it, it);
+  }));
+
+  EXPECT_TRUE(tester.Test([](VecT* vec) {
+    auto it = vec->begin();
     vec->erase(it, it + 1);
   }));
   EXPECT_TRUE(tester.Test([](VecT* vec) {
@@ -452,9 +466,7 @@
                     .WithInitialValue(VecT{from_size})
                     .WithContracts(InlinedVectorInvariants<VecT>);
 
-  EXPECT_TRUE(tester.Test([](VecT* vec) {
-    vec->reserve(to_capacity);  //
-  }));
+  EXPECT_TRUE(tester.Test([](VecT* vec) { vec->reserve(to_capacity); }));
 }
 
 TYPED_TEST(OneSizeTest, ShrinkToFit) {
@@ -493,4 +505,4 @@
 
 }  // namespace
 
-#endif  // ABSL_HAVE_EXCEPTIONS
+#endif  // defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/absl/container/inlined_vector_test.cc b/absl/container/inlined_vector_test.cc
index 080ea95..98aff33 100644
--- a/absl/container/inlined_vector_test.cc
+++ b/absl/container/inlined_vector_test.cc
@@ -30,6 +30,7 @@
 #include "absl/base/internal/exception_testing.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/macros.h"
+#include "absl/base/options.h"
 #include "absl/container/internal/counting_allocator.h"
 #include "absl/container/internal/test_instance_tracker.h"
 #include "absl/hash/hash_testing.h"
@@ -247,6 +248,16 @@
   }
 }
 
+TEST(IntVec, Hardened) {
+  IntVec v;
+  Fill(&v, 10);
+  EXPECT_EQ(v[9], 9);
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+  EXPECT_DEATH_IF_SUPPORTED(v[10], "");
+  EXPECT_DEATH_IF_SUPPORTED(v[-1], "");
+#endif
+}
+
 // At the end of this test loop, the elements between [erase_begin, erase_end)
 // should have reference counts == 0, and all others elements should have
 // reference counts == 1.
@@ -725,22 +736,26 @@
   // In particular, ensure that std::allocator doesn't cost anything to store.
   // The union should be absorbing some of the allocation bookkeeping overhead
   // in the larger vectors, leaving only the size_ field as overhead.
-  EXPECT_EQ(2 * sizeof(int*),
-            sizeof(absl::InlinedVector<int*, 1>) - 1 * sizeof(int*));
-  EXPECT_EQ(1 * sizeof(int*),
-            sizeof(absl::InlinedVector<int*, 2>) - 2 * sizeof(int*));
-  EXPECT_EQ(1 * sizeof(int*),
-            sizeof(absl::InlinedVector<int*, 3>) - 3 * sizeof(int*));
-  EXPECT_EQ(1 * sizeof(int*),
-            sizeof(absl::InlinedVector<int*, 4>) - 4 * sizeof(int*));
-  EXPECT_EQ(1 * sizeof(int*),
-            sizeof(absl::InlinedVector<int*, 5>) - 5 * sizeof(int*));
-  EXPECT_EQ(1 * sizeof(int*),
-            sizeof(absl::InlinedVector<int*, 6>) - 6 * sizeof(int*));
-  EXPECT_EQ(1 * sizeof(int*),
-            sizeof(absl::InlinedVector<int*, 7>) - 7 * sizeof(int*));
-  EXPECT_EQ(1 * sizeof(int*),
-            sizeof(absl::InlinedVector<int*, 8>) - 8 * sizeof(int*));
+
+  struct T { void* val; };
+  size_t expected_overhead = sizeof(T);
+
+  EXPECT_EQ((2 * expected_overhead),
+            sizeof(absl::InlinedVector<T, 1>) - sizeof(T[1]));
+  EXPECT_EQ(expected_overhead,
+            sizeof(absl::InlinedVector<T, 2>) - sizeof(T[2]));
+  EXPECT_EQ(expected_overhead,
+            sizeof(absl::InlinedVector<T, 3>) - sizeof(T[3]));
+  EXPECT_EQ(expected_overhead,
+            sizeof(absl::InlinedVector<T, 4>) - sizeof(T[4]));
+  EXPECT_EQ(expected_overhead,
+            sizeof(absl::InlinedVector<T, 5>) - sizeof(T[5]));
+  EXPECT_EQ(expected_overhead,
+            sizeof(absl::InlinedVector<T, 6>) - sizeof(T[6]));
+  EXPECT_EQ(expected_overhead,
+            sizeof(absl::InlinedVector<T, 7>) - sizeof(T[7]));
+  EXPECT_EQ(expected_overhead,
+            sizeof(absl::InlinedVector<T, 8>) - sizeof(T[8]));
 }
 
 TEST(IntVec, Clear) {
@@ -780,7 +795,7 @@
 TEST(StringVec, SelfRefPushBack) {
   std::vector<std::string> std_v;
   absl::InlinedVector<std::string, 4> v;
-  const std::string s = "A quite long std::string to ensure heap.";
+  const std::string s = "A quite long string to ensure heap.";
   std_v.push_back(s);
   v.push_back(s);
   for (int i = 0; i < 20; ++i) {
@@ -795,7 +810,7 @@
 TEST(StringVec, SelfRefPushBackWithMove) {
   std::vector<std::string> std_v;
   absl::InlinedVector<std::string, 4> v;
-  const std::string s = "A quite long std::string to ensure heap.";
+  const std::string s = "A quite long string to ensure heap.";
   std_v.push_back(s);
   v.push_back(s);
   for (int i = 0; i < 20; ++i) {
@@ -808,7 +823,7 @@
 }
 
 TEST(StringVec, SelfMove) {
-  const std::string s = "A quite long std::string to ensure heap.";
+  const std::string s = "A quite long string to ensure heap.";
   for (int len = 0; len < 20; len++) {
     SCOPED_TRACE(len);
     absl::InlinedVector<std::string, 8> v;
@@ -1754,6 +1769,30 @@
   }
 }
 
+TEST(InlinedVectorTest, MinimumAllocatorCompilesUsingTraits) {
+  using T = int;
+  using A = std::allocator<T>;
+  using ATraits = absl::allocator_traits<A>;
+
+  struct MinimumAllocator {
+    using value_type = T;
+
+    value_type* allocate(size_t n) {
+      A a;
+      return ATraits::allocate(a, n);
+    }
+
+    void deallocate(value_type* p, size_t n) {
+      A a;
+      ATraits::deallocate(a, p, n);
+    }
+  };
+
+  absl::InlinedVector<T, 1, MinimumAllocator> vec;
+  vec.emplace_back();
+  vec.resize(0);
+}
+
 TEST(InlinedVectorTest, AbslHashValueWorks) {
   using V = absl::InlinedVector<int, 4>;
   std::vector<V> cases;
diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h
index b255984..6f5f01b 100644
--- a/absl/container/internal/btree.h
+++ b/absl/container/internal/btree.h
@@ -65,11 +65,13 @@
 #include "absl/container/internal/layout.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
+#include "absl/strings/cord.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/compare.h"
 #include "absl/utility/utility.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 // A helper class that indicates if the Compare parameter is a key-compare-to
@@ -92,6 +94,19 @@
                                  absl::string_view rhs) const {
     return compare_internal::compare_result_as_ordering(lhs.compare(rhs));
   }
+  StringBtreeDefaultLess(std::less<absl::Cord>) {}  // NOLINT
+  absl::weak_ordering operator()(const absl::Cord &lhs,
+                                 const absl::Cord &rhs) const {
+    return compare_internal::compare_result_as_ordering(lhs.Compare(rhs));
+  }
+  absl::weak_ordering operator()(const absl::Cord &lhs,
+                                 absl::string_view rhs) const {
+    return compare_internal::compare_result_as_ordering(lhs.Compare(rhs));
+  }
+  absl::weak_ordering operator()(absl::string_view lhs,
+                                 const absl::Cord &rhs) const {
+    return compare_internal::compare_result_as_ordering(-rhs.Compare(lhs));
+  }
 };
 
 struct StringBtreeDefaultGreater {
@@ -106,17 +121,30 @@
                                  absl::string_view rhs) const {
     return compare_internal::compare_result_as_ordering(rhs.compare(lhs));
   }
+  StringBtreeDefaultGreater(std::greater<absl::Cord>) {}  // NOLINT
+  absl::weak_ordering operator()(const absl::Cord &lhs,
+                                 const absl::Cord &rhs) const {
+    return compare_internal::compare_result_as_ordering(rhs.Compare(lhs));
+  }
+  absl::weak_ordering operator()(const absl::Cord &lhs,
+                                 absl::string_view rhs) const {
+    return compare_internal::compare_result_as_ordering(-lhs.Compare(rhs));
+  }
+  absl::weak_ordering operator()(absl::string_view lhs,
+                                 const absl::Cord &rhs) const {
+    return compare_internal::compare_result_as_ordering(rhs.Compare(lhs));
+  }
 };
 
 // A helper class to convert a boolean comparison into a three-way "compare-to"
-// comparison that returns a negative value to indicate less-than, zero to
-// indicate equality and a positive value to indicate greater-than. This helper
+// comparison that returns an `absl::weak_ordering`. This helper
 // class is specialized for less<std::string>, greater<std::string>,
-// less<string_view>, and greater<string_view>.
+// less<string_view>, greater<string_view>, less<absl::Cord>, and
+// greater<absl::Cord>.
 //
 // key_compare_to_adapter is provided so that btree users
 // automatically get the more efficient compare-to code when using common
-// google string types with common comparison functors.
+// Abseil string types with common comparison functors.
 // These string-like specializations also turn on heterogeneous lookup by
 // default.
 template <typename Compare>
@@ -144,10 +172,52 @@
   using type = StringBtreeDefaultGreater;
 };
 
+template <>
+struct key_compare_to_adapter<std::less<absl::Cord>> {
+  using type = StringBtreeDefaultLess;
+};
+
+template <>
+struct key_compare_to_adapter<std::greater<absl::Cord>> {
+  using type = StringBtreeDefaultGreater;
+};
+
+// Detects an 'absl_btree_prefer_linear_node_search' member. This is
+// a protocol used as an opt-in or opt-out of linear search.
+//
+//  For example, this would be useful for key types that wrap an integer
+//  and define their own cheap operator<(). For example:
+//
+//   class K {
+//    public:
+//     using absl_btree_prefer_linear_node_search = std::true_type;
+//     ...
+//    private:
+//     friend bool operator<(K a, K b) { return a.k_ < b.k_; }
+//     int k_;
+//   };
+//
+//   btree_map<K, V> m;  // Uses linear search
+//
+// If T has the preference tag, then it has a preference.
+// Btree will use the tag's truth value.
+template <typename T, typename = void>
+struct has_linear_node_search_preference : std::false_type {};
+template <typename T, typename = void>
+struct prefers_linear_node_search : std::false_type {};
+template <typename T>
+struct has_linear_node_search_preference<
+    T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
+    : std::true_type {};
+template <typename T>
+struct prefers_linear_node_search<
+    T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
+    : T::absl_btree_prefer_linear_node_search {};
+
 template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
           bool Multi, typename SlotPolicy>
 struct common_params {
-  // If Compare is a common comparator for a std::string-like type, then we adapt it
+  // If Compare is a common comparator for a string-like type, then we adapt it
   // to use heterogeneous lookup and to be a key-compare-to comparator.
   using key_compare = typename key_compare_to_adapter<Compare>::type;
   // A type which indicates if we have a key-compare-to functor or a plain old
@@ -159,9 +229,6 @@
   using size_type = std::make_signed<size_t>::type;
   using difference_type = ptrdiff_t;
 
-  // True if this is a multiset or multimap.
-  using is_multi_container = std::integral_constant<bool, Multi>;
-
   using slot_policy = SlotPolicy;
   using slot_type = typename slot_policy::slot_type;
   using value_type = typename slot_policy::value_type;
@@ -171,6 +238,23 @@
   using reference = value_type &;
   using const_reference = const value_type &;
 
+  // For the given lookup key type, returns whether we can have multiple
+  // equivalent keys in the btree. If this is a multi-container, then we can.
+  // Otherwise, we can have multiple equivalent keys only if all of the
+  // following conditions are met:
+  // - The comparator is transparent.
+  // - The lookup key type is not the same as key_type.
+  // - The comparator is not a StringBtreeDefault{Less,Greater} comparator
+  //   that we know has the same equivalence classes for all lookup types.
+  template <typename LookupKey>
+  constexpr static bool can_have_multiple_equivalent_keys() {
+    return Multi ||
+           (IsTransparent<key_compare>::value &&
+            !std::is_same<LookupKey, Key>::value &&
+            !std::is_same<key_compare, StringBtreeDefaultLess>::value &&
+            !std::is_same<key_compare, StringBtreeDefaultGreater>::value);
+  }
+
   enum {
     kTargetNodeSize = TargetNodeSize,
 
@@ -216,10 +300,6 @@
   static void move(Alloc *alloc, slot_type *src, slot_type *dest) {
     slot_policy::move(alloc, src, dest);
   }
-  static void move(Alloc *alloc, slot_type *first, slot_type *last,
-                   slot_type *result) {
-    slot_policy::move(alloc, first, last, result);
-  }
 };
 
 // A parameters structure for holding the type parameters for a btree_map.
@@ -251,9 +331,17 @@
   };
   using is_map_container = std::true_type;
 
-  static const Key &key(const value_type &x) { return x.first; }
-  static const Key &key(const init_type &x) { return x.first; }
-  static const Key &key(const slot_type *x) { return slot_policy::key(x); }
+  template <typename V>
+  static auto key(const V &value) -> decltype(value.first) {
+    return value.first;
+  }
+  static const Key &key(const slot_type *s) { return slot_policy::key(s); }
+  static const Key &key(slot_type *s) { return slot_policy::key(s); }
+  // For use in node handle.
+  static auto mutable_key(slot_type *s)
+      -> decltype(slot_policy::mutable_key(s)) {
+    return slot_policy::mutable_key(s);
+  }
   static mapped_type &value(value_type *value) { return value->second; }
 };
 
@@ -294,13 +382,6 @@
   static void move(Alloc * /*alloc*/, slot_type *src, slot_type *dest) {
     *dest = std::move(*src);
   }
-
-  template <typename Alloc>
-  static void move(Alloc *alloc, slot_type *first, slot_type *last,
-                   slot_type *result) {
-    for (slot_type *src = first, *dest = result; src != last; ++src, ++dest)
-      move(alloc, src, dest);
-  }
 };
 
 // A parameters structure for holding the type parameters for a btree_set.
@@ -314,8 +395,10 @@
   using value_compare = typename set_params::common_params::key_compare;
   using is_map_container = std::false_type;
 
-  static const Key &key(const value_type &x) { return x; }
-  static const Key &key(const slot_type *x) { return *x; }
+  template <typename V>
+  static const V &key(const V &value) { return value; }
+  static const Key &key(const slot_type *slot) { return *slot; }
+  static const Key &key(slot_type *slot) { return *slot; }
 };
 
 // An adapter class that converts a lower-bound compare into an upper-bound
@@ -325,8 +408,8 @@
 template <typename Compare>
 struct upper_bound_adapter {
   explicit upper_bound_adapter(const Compare &c) : comp(c) {}
-  template <typename K, typename LK>
-  bool operator()(const K &a, const LK &b) const {
+  template <typename K1, typename K2>
+  bool operator()(const K1 &a, const K2 &b) const {
     // Returns true when a is not greater than b.
     return !compare_internal::compare_result_as_less_than(comp(b, a));
   }
@@ -351,6 +434,10 @@
 // useful information.
 template <typename V>
 struct SearchResult<V, false> {
+  SearchResult() {}
+  explicit SearchResult(V value) : value(value) {}
+  SearchResult(V value, MatchKind /*match*/) : value(value) {}
+
   V value;
 
   static constexpr bool HasMatch() { return false; }
@@ -363,7 +450,6 @@
 template <typename Params>
 class btree_node {
   using is_key_compare_to = typename Params::is_key_compare_to;
-  using is_multi_container = typename Params::is_multi_container;
   using field_type = typename Params::node_count_type;
   using allocator_type = typename Params::allocator_type;
   using slot_type = typename Params::slot_type;
@@ -381,15 +467,22 @@
   using difference_type = typename Params::difference_type;
 
   // Btree decides whether to use linear node search as follows:
+  //   - If the comparator expresses a preference, use that.
+  //   - If the key expresses a preference, use that.
   //   - If the key is arithmetic and the comparator is std::less or
   //     std::greater, choose linear.
   //   - Otherwise, choose binary.
   // TODO(ezb): Might make sense to add condition(s) based on node-size.
   using use_linear_search = std::integral_constant<
       bool,
-                std::is_arithmetic<key_type>::value &&
-                    (std::is_same<std::less<key_type>, key_compare>::value ||
-                     std::is_same<std::greater<key_type>, key_compare>::value)>;
+      has_linear_node_search_preference<key_compare>::value
+          ? prefers_linear_node_search<key_compare>::value
+          : has_linear_node_search_preference<key_type>::value
+                ? prefers_linear_node_search<key_type>::value
+                : std::is_arithmetic<key_type>::value &&
+                      (std::is_same<std::less<key_type>, key_compare>::value ||
+                       std::is_same<std::greater<key_type>,
+                                    key_compare>::value)>;
 
   // This class is organized by gtl::Layout as if it had the following
   // structure:
@@ -402,8 +495,9 @@
   //   // TODO(ezb): right now, `start` is always 0. Update insertion/merge
   //   // logic to allow for floating storage within nodes.
   //   field_type start;
-  //   // The count of the number of populated values in the node.
-  //   field_type count;
+  //   // The index after the last populated value in `values`. Currently, this
+  //   // is the same as the count of values.
+  //   field_type finish;
   //   // The maximum number of values the node can hold. This is an integer in
   //   // [1, kNodeValues] for root leaf nodes, kNodeValues for non-root leaf
   //   // nodes, and kInternalNodeMaxCount (as a sentinel value) for internal
@@ -414,7 +508,7 @@
   //
   //   // The array of values. The capacity is `max_count` for leaf nodes and
   //   // kNodeValues for internal nodes. Only the values in
-  //   // [start, start + count) have been initialized and are valid.
+  //   // [start, finish) have been initialized and are valid.
   //   slot_type values[max_count];
   //
   //   // The array of child pointers. The keys in children[i] are all less
@@ -445,7 +539,7 @@
                                                        slot_type, btree_node *>;
   constexpr static size_type SizeWithNValues(size_type n) {
     return layout_type(/*parent*/ 1,
-                       /*position, start, count, max_count*/ 4,
+                       /*position, start, finish, max_count*/ 4,
                        /*values*/ n,
                        /*children*/ 0)
         .AllocSize();
@@ -482,13 +576,13 @@
   // Leaves can have less than kNodeValues values.
   constexpr static layout_type LeafLayout(const int max_values = kNodeValues) {
     return layout_type(/*parent*/ 1,
-                       /*position, start, count, max_count*/ 4,
+                       /*position, start, finish, max_count*/ 4,
                        /*values*/ max_values,
                        /*children*/ 0);
   }
   constexpr static layout_type InternalLayout() {
     return layout_type(/*parent*/ 1,
-                       /*position, start, count, max_count*/ 4,
+                       /*position, start, finish, max_count*/ 4,
                        /*values*/ kNodeValues,
                        /*children*/ kNodeValues + 1);
   }
@@ -514,12 +608,14 @@
         reinterpret_cast<const char *>(this));
   }
   void set_parent(btree_node *p) { *GetField<0>() = p; }
-  field_type &mutable_count() { return GetField<1>()[2]; }
+  field_type &mutable_finish() { return GetField<1>()[2]; }
   slot_type *slot(int i) { return &GetField<2>()[i]; }
+  slot_type *start_slot() { return slot(start()); }
+  slot_type *finish_slot() { return slot(finish()); }
   const slot_type *slot(int i) const { return &GetField<2>()[i]; }
   void set_position(field_type v) { GetField<1>()[0] = v; }
   void set_start(field_type v) { GetField<1>()[1] = v; }
-  void set_count(field_type v) { GetField<1>()[2] = v; }
+  void set_finish(field_type v) { GetField<1>()[2] = v; }
   // This method is only called by the node init methods.
   void set_max_count(field_type v) { GetField<1>()[3] = v; }
 
@@ -532,10 +628,20 @@
   field_type position() const { return GetField<1>()[0]; }
 
   // Getter for the offset of the first value in the `values` array.
-  field_type start() const { return GetField<1>()[1]; }
+  field_type start() const {
+    // TODO(ezb): when floating storage is implemented, return GetField<1>()[1];
+    assert(GetField<1>()[1] == 0);
+    return 0;
+  }
+
+  // Getter for the offset after the last value in the `values` array.
+  field_type finish() const { return GetField<1>()[2]; }
 
   // Getters for the number of values stored in this node.
-  field_type count() const { return GetField<1>()[2]; }
+  field_type count() const {
+    assert(finish() >= start());
+    return finish() - start();
+  }
   field_type max_count() const {
     // Internal nodes have max_count==kInternalNodeMaxCount.
     // Leaf nodes have max_count in [1, kNodeValues].
@@ -563,6 +669,7 @@
 
   // Getters/setter for the child at position i in the node.
   btree_node *child(int i) const { return GetField<3>()[i]; }
+  btree_node *start_child() const { return child(start()); }
   btree_node *&mutable_child(int i) { return GetField<3>()[i]; }
   void clear_child(int i) {
     absl::container_internal::SanitizerPoisonObject(&mutable_child(i));
@@ -595,14 +702,14 @@
   template <typename K, typename Compare>
   SearchResult<int, btree_is_key_compare_to<Compare, key_type>::value>
   linear_search(const K &k, const Compare &comp) const {
-    return linear_search_impl(k, 0, count(), comp,
+    return linear_search_impl(k, start(), finish(), comp,
                               btree_is_key_compare_to<Compare, key_type>());
   }
 
   template <typename K, typename Compare>
   SearchResult<int, btree_is_key_compare_to<Compare, key_type>::value>
   binary_search(const K &k, const Compare &comp) const {
-    return binary_search_impl(k, 0, count(), comp,
+    return binary_search_impl(k, start(), finish(), comp,
                               btree_is_key_compare_to<Compare, key_type>());
   }
 
@@ -618,7 +725,7 @@
       }
       ++s;
     }
-    return {s};
+    return SearchResult<int, false>{s};
   }
 
   // Returns the position of the first value whose key is not less than k using
@@ -653,7 +760,7 @@
         e = mid;
       }
     }
-    return {s};
+    return SearchResult<int, false>{s};
   }
 
   // Returns the position of the first value whose key is not less than k using
@@ -662,7 +769,7 @@
   SearchResult<int, true> binary_search_impl(
       const K &k, int s, int e, const CompareTo &comp,
       std::true_type /* IsCompareTo */) const {
-    if (is_multi_container::value) {
+    if (params_type::template can_have_multiple_equivalent_keys<K>()) {
       MatchKind exact_match = MatchKind::kNe;
       while (s != e) {
         const int mid = (s + e) >> 1;
@@ -673,14 +780,14 @@
           e = mid;
           if (c == 0) {
             // Need to return the first value whose key is not less than k,
-            // which requires continuing the binary search if this is a
-            // multi-container.
+            // which requires continuing the binary search if there could be
+            // multiple equivalent keys.
             exact_match = MatchKind::kEq;
           }
         }
       }
       return {s, exact_match};
-    } else {  // Not a multi-container.
+    } else {  // Can't have multiple equivalent keys.
       while (s != e) {
         const int mid = (s + e) >> 1;
         const absl::weak_ordering c = comp(key(mid), k);
@@ -701,14 +808,10 @@
   template <typename... Args>
   void emplace_value(size_type i, allocator_type *alloc, Args &&... args);
 
-  // Removes the value at position i, shifting all existing values and children
-  // at positions > i to the left by 1.
-  void remove_value(int i, allocator_type *alloc);
-
-  // Removes the values at positions [i, i + to_erase), shifting all values
-  // after that range to the left by to_erase. Does not change children at all.
-  void remove_values_ignore_children(int i, int to_erase,
-                                     allocator_type *alloc);
+  // Removes the values at positions [i, i + to_erase), shifting all existing
+  // values and children after that range to the left by to_erase. Clears all
+  // children between [i, i + to_erase).
+  void remove_values(field_type i, field_type to_erase, allocator_type *alloc);
 
   // Rebalances a node with its right sibling.
   void rebalance_right_to_left(int to_move, btree_node *right,
@@ -720,74 +823,87 @@
   void split(int insert_position, btree_node *dest, allocator_type *alloc);
 
   // Merges a node with its right sibling, moving all of the values and the
-  // delimiting key in the parent node onto itself.
-  void merge(btree_node *sibling, allocator_type *alloc);
-
-  // Swap the contents of "this" and "src".
-  void swap(btree_node *src, allocator_type *alloc);
+  // delimiting key in the parent node onto itself, and deleting the src node.
+  void merge(btree_node *src, allocator_type *alloc);
 
   // Node allocation/deletion routines.
-  static btree_node *init_leaf(btree_node *n, btree_node *parent,
-                               int max_count) {
-    n->set_parent(parent);
-    n->set_position(0);
-    n->set_start(0);
-    n->set_count(0);
-    n->set_max_count(max_count);
+  void init_leaf(btree_node *parent, int max_count) {
+    set_parent(parent);
+    set_position(0);
+    set_start(0);
+    set_finish(0);
+    set_max_count(max_count);
     absl::container_internal::SanitizerPoisonMemoryRegion(
-        n->slot(0), max_count * sizeof(slot_type));
-    return n;
+        start_slot(), max_count * sizeof(slot_type));
   }
-  static btree_node *init_internal(btree_node *n, btree_node *parent) {
-    init_leaf(n, parent, kNodeValues);
+  void init_internal(btree_node *parent) {
+    init_leaf(parent, kNodeValues);
     // Set `max_count` to a sentinel value to indicate that this node is
     // internal.
-    n->set_max_count(kInternalNodeMaxCount);
+    set_max_count(kInternalNodeMaxCount);
     absl::container_internal::SanitizerPoisonMemoryRegion(
-        &n->mutable_child(0), (kNodeValues + 1) * sizeof(btree_node *));
-    return n;
-  }
-  void destroy(allocator_type *alloc) {
-    for (int i = 0; i < count(); ++i) {
-      value_destroy(i, alloc);
-    }
+        &mutable_child(start()), (kNodeValues + 1) * sizeof(btree_node *));
   }
 
- public:
-  // Exposed only for tests.
-  static bool testonly_uses_linear_node_search() {
-    return use_linear_search::value;
+  static void deallocate(const size_type size, btree_node *node,
+                         allocator_type *alloc) {
+    absl::container_internal::Deallocate<Alignment()>(alloc, node, size);
   }
 
+  // Deletes a node and all of its children.
+  static void clear_and_delete(btree_node *node, allocator_type *alloc);
+
  private:
   template <typename... Args>
-  void value_init(const size_type i, allocator_type *alloc, Args &&... args) {
+  void value_init(const field_type i, allocator_type *alloc, Args &&... args) {
     absl::container_internal::SanitizerUnpoisonObject(slot(i));
     params_type::construct(alloc, slot(i), std::forward<Args>(args)...);
   }
-  void value_destroy(const size_type i, allocator_type *alloc) {
+  void value_destroy(const field_type i, allocator_type *alloc) {
     params_type::destroy(alloc, slot(i));
     absl::container_internal::SanitizerPoisonObject(slot(i));
   }
-
-  // Move n values starting at value i in this node into the values starting at
-  // value j in node x.
-  void uninitialized_move_n(const size_type n, const size_type i,
-                            const size_type j, btree_node *x,
-                            allocator_type *alloc) {
-    absl::container_internal::SanitizerUnpoisonMemoryRegion(
-        x->slot(j), n * sizeof(slot_type));
-    for (slot_type *src = slot(i), *end = src + n, *dest = x->slot(j);
-         src != end; ++src, ++dest) {
-      params_type::construct(alloc, dest, src);
+  void value_destroy_n(const field_type i, const field_type n,
+                       allocator_type *alloc) {
+    for (slot_type *s = slot(i), *end = slot(i + n); s != end; ++s) {
+      params_type::destroy(alloc, s);
+      absl::container_internal::SanitizerPoisonObject(s);
     }
   }
 
-  // Destroys a range of n values, starting at index i.
-  void value_destroy_n(const size_type i, const size_type n,
-                       allocator_type *alloc) {
-    for (int j = 0; j < n; ++j) {
-      value_destroy(i + j, alloc);
+  static void transfer(slot_type *dest, slot_type *src, allocator_type *alloc) {
+    absl::container_internal::SanitizerUnpoisonObject(dest);
+    params_type::transfer(alloc, dest, src);
+    absl::container_internal::SanitizerPoisonObject(src);
+  }
+
+  // Transfers value from slot `src_i` in `src_node` to slot `dest_i` in `this`.
+  void transfer(const size_type dest_i, const size_type src_i,
+                btree_node *src_node, allocator_type *alloc) {
+    transfer(slot(dest_i), src_node->slot(src_i), alloc);
+  }
+
+  // Transfers `n` values starting at value `src_i` in `src_node` into the
+  // values starting at value `dest_i` in `this`.
+  void transfer_n(const size_type n, const size_type dest_i,
+                  const size_type src_i, btree_node *src_node,
+                  allocator_type *alloc) {
+    for (slot_type *src = src_node->slot(src_i), *end = src + n,
+                   *dest = slot(dest_i);
+         src != end; ++src, ++dest) {
+      transfer(dest, src, alloc);
+    }
+  }
+
+  // Same as above, except that we start at the end and work our way to the
+  // beginning.
+  void transfer_n_backward(const size_type n, const size_type dest_i,
+                           const size_type src_i, btree_node *src_node,
+                           allocator_type *alloc) {
+    for (slot_type *src = src_node->slot(src_i + n - 1), *end = src - n,
+                   *dest = slot(dest_i + n - 1);
+         src != end; --src, --dest) {
+      transfer(dest, src, alloc);
     }
   }
 
@@ -804,6 +920,7 @@
   using key_type = typename Node::key_type;
   using size_type = typename Node::size_type;
   using params_type = typename Node::params_type;
+  using is_map_container = typename params_type::is_map_container;
 
   using node_type = Node;
   using normal_node = typename std::remove_const<Node>::type;
@@ -815,7 +932,7 @@
   using slot_type = typename params_type::slot_type;
 
   using iterator =
-      btree_iterator<normal_node, normal_reference, normal_pointer>;
+     btree_iterator<normal_node, normal_reference, normal_pointer>;
   using const_iterator =
       btree_iterator<const_node, const_reference, const_pointer>;
 
@@ -828,23 +945,23 @@
   using iterator_category = std::bidirectional_iterator_tag;
 
   btree_iterator() : node(nullptr), position(-1) {}
+  explicit btree_iterator(Node *n) : node(n), position(n->start()) {}
   btree_iterator(Node *n, int p) : node(n), position(p) {}
 
   // NOTE: this SFINAE allows for implicit conversions from iterator to
-  // const_iterator, but it specifically avoids defining copy constructors so
-  // that btree_iterator can be trivially copyable. This is for performance and
-  // binary size reasons.
+  // const_iterator, but it specifically avoids hiding the copy constructor so
+  // that the trivial one will be used when possible.
   template <typename N, typename R, typename P,
             absl::enable_if_t<
                 std::is_same<btree_iterator<N, R, P>, iterator>::value &&
                     std::is_same<btree_iterator, const_iterator>::value,
                 int> = 0>
-  btree_iterator(const btree_iterator<N, R, P> &x)  // NOLINT
-      : node(x.node), position(x.position) {}
+  btree_iterator(const btree_iterator<N, R, P> other)  // NOLINT
+      : node(other.node), position(other.position) {}
 
  private:
   // This SFINAE allows explicit conversions from const_iterator to
-  // iterator, but also avoids defining a copy constructor.
+  // iterator, but also avoids hiding the copy constructor.
   // NOTE: the const_cast is safe because this constructor is only called by
   // non-const methods and the container owns the nodes.
   template <typename N, typename R, typename P,
@@ -852,12 +969,12 @@
                 std::is_same<btree_iterator<N, R, P>, const_iterator>::value &&
                     std::is_same<btree_iterator, iterator>::value,
                 int> = 0>
-  explicit btree_iterator(const btree_iterator<N, R, P> &x)
-      : node(const_cast<node_type *>(x.node)), position(x.position) {}
+  explicit btree_iterator(const btree_iterator<N, R, P> other)
+      : node(const_cast<node_type *>(other.node)), position(other.position) {}
 
   // Increment/decrement the iterator.
   void increment() {
-    if (node->leaf() && ++position < node->count()) {
+    if (node->leaf() && ++position < node->finish()) {
       return;
     }
     increment_slow();
@@ -865,7 +982,7 @@
   void increment_slow();
 
   void decrement() {
-    if (node->leaf() && --position >= 0) {
+    if (node->leaf() && --position >= node->start()) {
       return;
     }
     decrement_slow();
@@ -873,26 +990,33 @@
   void decrement_slow();
 
  public:
-  bool operator==(const const_iterator &x) const {
-    return node == x.node && position == x.position;
+  bool operator==(const iterator &other) const {
+    return node == other.node && position == other.position;
   }
-  bool operator!=(const const_iterator &x) const {
-    return node != x.node || position != x.position;
+  bool operator==(const const_iterator &other) const {
+    return node == other.node && position == other.position;
+  }
+  bool operator!=(const iterator &other) const {
+    return node != other.node || position != other.position;
+  }
+  bool operator!=(const const_iterator &other) const {
+    return node != other.node || position != other.position;
   }
 
   // Accessors for the key/value the iterator is pointing at.
   reference operator*() const {
+    ABSL_HARDENING_ASSERT(node != nullptr);
+    ABSL_HARDENING_ASSERT(node->start() <= position);
+    ABSL_HARDENING_ASSERT(node->finish() > position);
     return node->value(position);
   }
-  pointer operator->() const {
-    return &node->value(position);
-  }
+  pointer operator->() const { return &operator*(); }
 
-  btree_iterator& operator++() {
+  btree_iterator &operator++() {
     increment();
     return *this;
   }
-  btree_iterator& operator--() {
+  btree_iterator &operator--() {
     decrement();
     return *this;
   }
@@ -908,6 +1032,8 @@
   }
 
  private:
+  friend iterator;
+  friend const_iterator;
   template <typename Params>
   friend class btree;
   template <typename Tree>
@@ -918,8 +1044,6 @@
   friend class btree_map_container;
   template <typename Tree>
   friend class btree_multiset_container;
-  template <typename N, typename R, typename P>
-  friend struct btree_iterator;
   template <typename TreeType, typename CheckerType>
   friend class base_checker;
 
@@ -929,7 +1053,8 @@
   // The node in the tree the iterator is pointing at.
   Node *node;
   // The position within the node of the tree the iterator is pointing at.
-  // TODO(ezb): make this a field_type
+  // NOTE: this is an int rather than a field_type because iterators can point
+  // to invalid positions (such as -1) in certain circumstances.
   int position;
 };
 
@@ -937,6 +1062,8 @@
 class btree {
   using node_type = btree_node<Params>;
   using is_key_compare_to = typename Params::is_key_compare_to;
+  using init_type = typename Params::init_type;
+  using field_type = typename node_type::field_type;
 
   // We use a static empty node for the root/leftmost/rightmost of empty btrees
   // in order to avoid branching in begin()/end().
@@ -945,7 +1072,7 @@
     node_type *parent;
     field_type position = 0;
     field_type start = 0;
-    field_type count = 0;
+    field_type finish = 0;
     // max_count must be != kInternalNodeMaxCount (so that this node is regarded
     // as a leaf node). max_count() is never called when the tree is empty.
     field_type max_count = node_type::kInternalNodeMaxCount + 1;
@@ -960,7 +1087,7 @@
 
   static node_type *EmptyNode() {
 #ifdef _MSC_VER
-    static EmptyNodeType* empty_node = new EmptyNodeType;
+    static EmptyNodeType *empty_node = new EmptyNodeType;
     // This assert fails on some other construction methods.
     assert(empty_node->parent == empty_node);
     return empty_node;
@@ -971,7 +1098,7 @@
 #endif
   }
 
-  enum {
+  enum : uint32_t {
     kNodeValues = node_type::kNodeValues,
     kMinNodeValues = kNodeValues / 2,
   };
@@ -979,14 +1106,11 @@
   struct node_stats {
     using size_type = typename Params::size_type;
 
-    node_stats(size_type l, size_type i)
-        : leaf_nodes(l),
-          internal_nodes(i) {
-    }
+    node_stats(size_type l, size_type i) : leaf_nodes(l), internal_nodes(i) {}
 
-    node_stats& operator+=(const node_stats &x) {
-      leaf_nodes += x.leaf_nodes;
-      internal_nodes += x.internal_nodes;
+    node_stats &operator+=(const node_stats &other) {
+      leaf_nodes += other.leaf_nodes;
+      internal_nodes += other.internal_nodes;
       return *this;
     }
 
@@ -1006,7 +1130,8 @@
   using const_reference = typename Params::const_reference;
   using pointer = typename Params::pointer;
   using const_pointer = typename Params::const_pointer;
-  using iterator = btree_iterator<node_type, reference, pointer>;
+  using iterator =
+      typename btree_iterator<node_type, reference, pointer>::iterator;
   using const_iterator = typename iterator::const_iterator;
   using reverse_iterator = std::reverse_iterator<iterator>;
   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
@@ -1018,28 +1143,46 @@
 
  private:
   // For use in copy_or_move_values_in_order.
-  const value_type &maybe_move_from_iterator(const_iterator x) { return *x; }
-  value_type &&maybe_move_from_iterator(iterator x) { return std::move(*x); }
+  const value_type &maybe_move_from_iterator(const_iterator it) { return *it; }
+  value_type &&maybe_move_from_iterator(iterator it) {
+    // This is a destructive operation on the other container so it's safe for
+    // us to const_cast and move from the keys here even if it's a set.
+    return std::move(const_cast<value_type &>(*it));
+  }
 
   // Copies or moves (depending on the template parameter) the values in
-  // x into this btree in their order in x. This btree must be empty before this
-  // method is called. This method is used in copy construction, copy
-  // assignment, and move assignment.
+  // other into this btree in their order in other. This btree must be empty
+  // before this method is called. This method is used in copy construction,
+  // copy assignment, and move assignment.
   template <typename Btree>
-  void copy_or_move_values_in_order(Btree *x);
+  void copy_or_move_values_in_order(Btree &other);
 
   // Validates that various assumptions/requirements are true at compile time.
   constexpr static bool static_assert_validation();
 
  public:
-  btree(const key_compare &comp, const allocator_type &alloc);
+  btree(const key_compare &comp, const allocator_type &alloc)
+      : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {}
 
-  btree(const btree &x);
-  btree(btree &&x) noexcept
-      : root_(std::move(x.root_)),
-        rightmost_(absl::exchange(x.rightmost_, EmptyNode())),
-        size_(absl::exchange(x.size_, 0)) {
-    x.mutable_root() = EmptyNode();
+  btree(const btree &other) : btree(other, other.allocator()) {}
+  btree(const btree &other, const allocator_type &alloc)
+      : btree(other.key_comp(), alloc) {
+    copy_or_move_values_in_order(other);
+  }
+  btree(btree &&other) noexcept
+      : root_(std::move(other.root_)),
+        rightmost_(absl::exchange(other.rightmost_, EmptyNode())),
+        size_(absl::exchange(other.size_, 0)) {
+    other.mutable_root() = EmptyNode();
+  }
+  btree(btree &&other, const allocator_type &alloc)
+      : btree(other.key_comp(), alloc) {
+    if (alloc == other.allocator()) {
+      swap(other);
+    } else {
+      // Move values from `other` one at a time when allocators are different.
+      copy_or_move_values_in_order(other);
+    }
   }
 
   ~btree() {
@@ -1049,44 +1192,41 @@
     clear();
   }
 
-  // Assign the contents of x to *this.
-  btree &operator=(const btree &x);
-  btree &operator=(btree &&x) noexcept;
+  // Assign the contents of other to *this.
+  btree &operator=(const btree &other);
+  btree &operator=(btree &&other) noexcept;
 
-  iterator begin() {
-    return iterator(leftmost(), 0);
-  }
-  const_iterator begin() const {
-    return const_iterator(leftmost(), 0);
-  }
-  iterator end() { return iterator(rightmost_, rightmost_->count()); }
+  iterator begin() { return iterator(leftmost()); }
+  const_iterator begin() const { return const_iterator(leftmost()); }
+  iterator end() { return iterator(rightmost_, rightmost_->finish()); }
   const_iterator end() const {
-    return const_iterator(rightmost_, rightmost_->count());
+    return const_iterator(rightmost_, rightmost_->finish());
   }
-  reverse_iterator rbegin() {
-    return reverse_iterator(end());
-  }
+  reverse_iterator rbegin() { return reverse_iterator(end()); }
   const_reverse_iterator rbegin() const {
     return const_reverse_iterator(end());
   }
-  reverse_iterator rend() {
-    return reverse_iterator(begin());
-  }
+  reverse_iterator rend() { return reverse_iterator(begin()); }
   const_reverse_iterator rend() const {
     return const_reverse_iterator(begin());
   }
 
-  // Finds the first element whose key is not less than key.
+  // Finds the first element whose key is not less than `key`.
   template <typename K>
   iterator lower_bound(const K &key) {
-    return internal_end(internal_lower_bound(key));
+    return internal_end(internal_lower_bound(key).value);
   }
   template <typename K>
   const_iterator lower_bound(const K &key) const {
-    return internal_end(internal_lower_bound(key));
+    return internal_end(internal_lower_bound(key).value);
   }
 
-  // Finds the first element whose key is greater than key.
+  // Finds the first element whose key is not less than `key` and also returns
+  // whether that element is equal to `key`.
+  template <typename K>
+  std::pair<iterator, bool> lower_bound_equal(const K &key) const;
+
+  // Finds the first element whose key is greater than `key`.
   template <typename K>
   iterator upper_bound(const K &key) {
     return internal_end(internal_upper_bound(key));
@@ -1097,23 +1237,21 @@
   }
 
   // Finds the range of values which compare equal to key. The first member of
-  // the returned pair is equal to lower_bound(key). The second member pair of
-  // the pair is equal to upper_bound(key).
+  // the returned pair is equal to lower_bound(key). The second member of the
+  // pair is equal to upper_bound(key).
   template <typename K>
-  std::pair<iterator, iterator> equal_range(const K &key) {
-    return {lower_bound(key), upper_bound(key)};
-  }
+  std::pair<iterator, iterator> equal_range(const K &key);
   template <typename K>
   std::pair<const_iterator, const_iterator> equal_range(const K &key) const {
-    return {lower_bound(key), upper_bound(key)};
+    return const_cast<btree *>(this)->equal_range(key);
   }
 
   // Inserts a value into the btree only if it does not already exist. The
   // boolean return value indicates whether insertion succeeded or failed.
   // Requirement: if `key` already exists in the btree, does not consume `args`.
   // Requirement: `key` is never referenced after consuming `args`.
-  template <typename... Args>
-  std::pair<iterator, bool> insert_unique(const key_type &key, Args &&... args);
+  template <typename K, typename... Args>
+  std::pair<iterator, bool> insert_unique(const K &key, Args &&... args);
 
   // Inserts with hint. Checks to see if the value should be placed immediately
   // before `position` in the tree. If so, then the insertion will take
@@ -1121,14 +1259,23 @@
   // logarithmic time as if a call to insert_unique() were made.
   // Requirement: if `key` already exists in the btree, does not consume `args`.
   // Requirement: `key` is never referenced after consuming `args`.
-  template <typename... Args>
+  template <typename K, typename... Args>
   std::pair<iterator, bool> insert_hint_unique(iterator position,
-                                               const key_type &key,
+                                               const K &key,
                                                Args &&... args);
 
   // Insert a range of values into the btree.
+  // Note: the first overload avoids constructing a value_type if the key
+  // already exists in the btree.
+  template <typename InputIterator,
+            typename = decltype(std::declval<const key_compare &>()(
+                params_type::key(*std::declval<InputIterator>()),
+                std::declval<const key_type &>()))>
+  void insert_iterator_unique(InputIterator b, InputIterator e, int);
+  // We need the second overload for cases in which we need to construct a
+  // value_type in order to compare it with the keys already in the btree.
   template <typename InputIterator>
-  void insert_iterator_unique(InputIterator b, InputIterator e);
+  void insert_iterator_unique(InputIterator b, InputIterator e, char);
 
   // Inserts a value into the btree.
   template <typename ValueType>
@@ -1159,20 +1306,10 @@
 
   // Erases range. Returns the number of keys erased and an iterator pointing
   // to the element after the last erased element.
-  std::pair<size_type, iterator> erase(iterator begin, iterator end);
+  std::pair<size_type, iterator> erase_range(iterator begin, iterator end);
 
-  // Erases the specified key from the btree. Returns 1 if an element was
-  // erased and 0 otherwise.
-  template <typename K>
-  size_type erase_unique(const K &key);
-
-  // Erases all of the entries matching the specified key from the
-  // btree. Returns the number of elements erased.
-  template <typename K>
-  size_type erase_multi(const K &key);
-
-  // Finds the iterator corresponding to a key or returns end() if the key is
-  // not present.
+  // Finds an element with key equivalent to `key` or returns `end()` if `key`
+  // is not present.
   template <typename K>
   iterator find(const K &key) {
     return internal_end(internal_find(key));
@@ -1182,35 +1319,18 @@
     return internal_end(internal_find(key));
   }
 
-  // Returns a count of the number of times the key appears in the btree.
-  template <typename K>
-  size_type count_unique(const K &key) const {
-    const iterator begin = internal_find(key);
-    if (begin.node == nullptr) {
-      // The key doesn't exist in the tree.
-      return 0;
-    }
-    return 1;
-  }
-  // Returns a count of the number of times the key appears in the btree.
-  template <typename K>
-  size_type count_multi(const K &key) const {
-    const auto range = equal_range(key);
-    return std::distance(range.first, range.second);
-  }
-
   // Clear the btree, deleting all of the values it contains.
   void clear();
 
-  // Swap the contents of *this and x.
-  void swap(btree &x);
+  // Swaps the contents of `this` and `other`.
+  void swap(btree &other);
 
   const key_compare &key_comp() const noexcept {
     return root_.template get<0>();
   }
-  template <typename K, typename LK>
-  bool compare_keys(const K &x, const LK &y) const {
-    return compare_internal::compare_result_as_less_than(key_comp()(x, y));
+  template <typename K1, typename K2>
+  bool compare_keys(const K1 &a, const K2 &b) const {
+    return compare_internal::compare_result_as_less_than(key_comp()(a, b));
   }
 
   value_compare value_comp() const { return value_compare(key_comp()); }
@@ -1226,7 +1346,7 @@
   // The height of the btree. An empty tree will have height 0.
   size_type height() const {
     size_type h = 0;
-    if (root()) {
+    if (!empty()) {
       // Count the length of the chain from the leftmost node up to the
       // root. We actually count from the root back around to the level below
       // the root, but the calculation is the same because of the circularity
@@ -1241,9 +1361,7 @@
   }
 
   // The number of internal, leaf and total nodes used by the btree.
-  size_type leaf_nodes() const {
-    return internal_stats(root()).leaf_nodes;
-  }
+  size_type leaf_nodes() const { return internal_stats(root()).leaf_nodes; }
   size_type internal_nodes() const {
     return internal_stats(root()).internal_nodes;
   }
@@ -1256,11 +1374,9 @@
   size_type bytes_used() const {
     node_stats stats = internal_stats(root());
     if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) {
-      return sizeof(*this) +
-             node_type::LeafSize(root()->max_count());
+      return sizeof(*this) + node_type::LeafSize(root()->max_count());
     } else {
-      return sizeof(*this) +
-             stats.leaf_nodes * node_type::LeafSize() +
+      return sizeof(*this) + stats.leaf_nodes * node_type::LeafSize() +
              stats.internal_nodes * node_type::InternalSize();
     }
   }
@@ -1277,24 +1393,23 @@
   // divided by the maximum number of elements a tree with the current number
   // of nodes could hold. A value of 1 indicates perfect space
   // utilization. Smaller values indicate space wastage.
+  // Returns 0 for empty trees.
   double fullness() const {
+    if (empty()) return 0.0;
     return static_cast<double>(size()) / (nodes() * kNodeValues);
   }
   // The overhead of the btree structure in bytes per node. Computed as the
   // total number of bytes used by the btree minus the number of bytes used for
   // storing elements divided by the number of elements.
+  // Returns 0 for empty trees.
   double overhead() const {
-    if (empty()) {
-      return 0.0;
-    }
+    if (empty()) return 0.0;
     return (bytes_used() - size() * sizeof(value_type)) /
            static_cast<double>(size());
   }
 
   // The allocator used by the btree.
-  allocator_type get_allocator() const {
-    return allocator();
-  }
+  allocator_type get_allocator() const { return allocator(); }
 
  private:
   // Internal accessor routines.
@@ -1324,39 +1439,25 @@
   }
 
   // Node creation/deletion routines.
-  node_type* new_internal_node(node_type *parent) {
-    node_type *p = allocate(node_type::InternalSize());
-    return node_type::init_internal(p, parent);
+  node_type *new_internal_node(node_type *parent) {
+    node_type *n = allocate(node_type::InternalSize());
+    n->init_internal(parent);
+    return n;
   }
-  node_type* new_leaf_node(node_type *parent) {
-    node_type *p = allocate(node_type::LeafSize());
-    return node_type::init_leaf(p, parent, kNodeValues);
+  node_type *new_leaf_node(node_type *parent) {
+    node_type *n = allocate(node_type::LeafSize());
+    n->init_leaf(parent, kNodeValues);
+    return n;
   }
   node_type *new_leaf_root_node(const int max_count) {
-    node_type *p = allocate(node_type::LeafSize(max_count));
-    return node_type::init_leaf(p, p, max_count);
+    node_type *n = allocate(node_type::LeafSize(max_count));
+    n->init_leaf(/*parent=*/n, max_count);
+    return n;
   }
 
   // Deletion helper routines.
-  void erase_same_node(iterator begin, iterator end);
-  iterator erase_from_leaf_node(iterator begin, size_type to_erase);
   iterator rebalance_after_delete(iterator iter);
 
-  // Deallocates a node of a certain size in bytes using the allocator.
-  void deallocate(const size_type size, node_type *node) {
-    absl::container_internal::Deallocate<node_type::Alignment()>(
-        mutable_allocator(), node, size);
-  }
-
-  void delete_internal_node(node_type *node) {
-    node->destroy(mutable_allocator());
-    deallocate(node_type::InternalSize(), node);
-  }
-  void delete_leaf_node(node_type *node) {
-    node->destroy(mutable_allocator());
-    deallocate(node_type::LeafSize(node->max_count()), node);
-  }
-
   // Rebalances or splits the node iter points to.
   void rebalance_or_split(iterator *iter);
 
@@ -1386,36 +1487,27 @@
   iterator internal_emplace(iterator iter, Args &&... args);
 
   // Returns an iterator pointing to the first value >= the value "iter" is
-  // pointing at. Note that "iter" might be pointing to an invalid location as
-  // iter.position == iter.node->count(). This routine simply moves iter up in
-  // the tree to a valid location.
+  // pointing at. Note that "iter" might be pointing to an invalid location such
+  // as iter.position == iter.node->finish(). This routine simply moves iter up
+  // in the tree to a valid location.
   // Requires: iter.node is non-null.
   template <typename IterType>
   static IterType internal_last(IterType iter);
 
   // Returns an iterator pointing to the leaf position at which key would
-  // reside in the tree. We provide 2 versions of internal_locate. The first
-  // version uses a less-than comparator and is incapable of distinguishing when
-  // there is an exact match. The second version is for the key-compare-to
-  // specialization and distinguishes exact matches. The key-compare-to
-  // specialization allows the caller to avoid a subsequent comparison to
-  // determine if an exact match was made, which is important for keys with
-  // expensive comparison, such as strings.
+  // reside in the tree, unless there is an exact match - in which case, the
+  // result may not be on a leaf. When there's a three-way comparator, we can
+  // return whether there was an exact match. This allows the caller to avoid a
+  // subsequent comparison to determine if an exact match was made, which is
+  // important for keys with expensive comparison, such as strings.
   template <typename K>
   SearchResult<iterator, is_key_compare_to::value> internal_locate(
       const K &key) const;
 
-  template <typename K>
-  SearchResult<iterator, false> internal_locate_impl(
-      const K &key, std::false_type /* IsCompareTo */) const;
-
-  template <typename K>
-  SearchResult<iterator, true> internal_locate_impl(
-      const K &key, std::true_type /* IsCompareTo */) const;
-
   // Internal routine which implements lower_bound().
   template <typename K>
-  iterator internal_lower_bound(const K &key) const;
+  SearchResult<iterator, is_key_compare_to::value> internal_lower_bound(
+      const K &key) const;
 
   // Internal routine which implements upper_bound().
   template <typename K>
@@ -1425,12 +1517,9 @@
   template <typename K>
   iterator internal_find(const K &key) const;
 
-  // Deletes a node and all of its children.
-  void internal_clear(node_type *node);
-
   // Verifies the tree structure of node.
-  int internal_verify(const node_type *node,
-                      const key_type *lo, const key_type *hi) const;
+  int internal_verify(const node_type *node, const key_type *lo,
+                      const key_type *hi) const;
 
   node_stats internal_stats(const node_type *node) const {
     // The root can be a static empty node.
@@ -1441,19 +1530,12 @@
       return node_stats(1, 0);
     }
     node_stats res(0, 1);
-    for (int i = 0; i <= node->count(); ++i) {
+    for (int i = node->start(); i <= node->finish(); ++i) {
       res += internal_stats(node->child(i));
     }
     return res;
   }
 
- public:
-  // Exposed only for tests.
-  static bool testonly_uses_linear_node_search() {
-    return node_type::testonly_uses_linear_node_search();
-  }
-
- private:
   // We use compressed tuple in order to save space because key_compare and
   // allocator_type are usually empty.
   absl::container_internal::CompressedTuple<key_compare, allocator_type,
@@ -1475,20 +1557,19 @@
 inline void btree_node<P>::emplace_value(const size_type i,
                                          allocator_type *alloc,
                                          Args &&... args) {
-  assert(i <= count());
+  assert(i >= start());
+  assert(i <= finish());
   // Shift old values to create space for new value and then construct it in
   // place.
-  if (i < count()) {
-    value_init(count(), alloc, slot(count() - 1));
-    for (size_type j = count() - 1; j > i; --j)
-      params_type::move(alloc, slot(j - 1), slot(j));
-    value_destroy(i, alloc);
+  if (i < finish()) {
+    transfer_n_backward(finish() - i, /*dest_i=*/i + 1, /*src_i=*/i, this,
+                        alloc);
   }
   value_init(i, alloc, std::forward<Args>(args)...);
-  set_count(count() + 1);
+  set_finish(finish() + 1);
 
-  if (!leaf() && count() > i + 1) {
-    for (int j = count(); j > i + 1; --j) {
+  if (!leaf() && finish() > i + 1) {
+    for (int j = finish(); j > i + 1; --j) {
       set_child(j, child(j - 1));
     }
     clear_child(i + 1);
@@ -1496,24 +1577,27 @@
 }
 
 template <typename P>
-inline void btree_node<P>::remove_value(const int i, allocator_type *alloc) {
-  if (!leaf() && count() > i + 1) {
-    assert(child(i + 1)->count() == 0);
-    for (size_type j = i + 1; j < count(); ++j) {
-      set_child(j, child(j + 1));
+inline void btree_node<P>::remove_values(const field_type i,
+                                         const field_type to_erase,
+                                         allocator_type *alloc) {
+  // Transfer values after the removed range into their new places.
+  value_destroy_n(i, to_erase, alloc);
+  const field_type orig_finish = finish();
+  const field_type src_i = i + to_erase;
+  transfer_n(orig_finish - src_i, i, src_i, this, alloc);
+
+  if (!leaf()) {
+    // Delete all children between begin and end.
+    for (int j = 0; j < to_erase; ++j) {
+      clear_and_delete(child(i + j + 1), alloc);
     }
-    clear_child(count());
+    // Rotate children after end into new positions.
+    for (int j = i + to_erase + 1; j <= orig_finish; ++j) {
+      set_child(j - to_erase, child(j));
+      clear_child(j);
+    }
   }
-
-  remove_values_ignore_children(i, /*to_erase=*/1, alloc);
-}
-
-template <typename P>
-inline void btree_node<P>::remove_values_ignore_children(
-    const int i, const int to_erase, allocator_type *alloc) {
-  params_type::move(alloc, slot(i + to_erase), slot(count()), slot(i));
-  value_destroy_n(count() - to_erase, to_erase, alloc);
-  set_count(count() - to_erase);
+  set_finish(orig_finish - to_erase);
 }
 
 template <typename P>
@@ -1527,37 +1611,33 @@
   assert(to_move <= right->count());
 
   // 1) Move the delimiting value in the parent to the left node.
-  value_init(count(), alloc, parent()->slot(position()));
+  transfer(finish(), position(), parent(), alloc);
 
   // 2) Move the (to_move - 1) values from the right node to the left node.
-  right->uninitialized_move_n(to_move - 1, 0, count() + 1, this, alloc);
+  transfer_n(to_move - 1, finish() + 1, right->start(), right, alloc);
 
   // 3) Move the new delimiting value to the parent from the right node.
-  params_type::move(alloc, right->slot(to_move - 1),
-                    parent()->slot(position()));
+  parent()->transfer(position(), right->start() + to_move - 1, right, alloc);
 
-  // 4) Shift the values in the right node to their correct position.
-  params_type::move(alloc, right->slot(to_move), right->slot(right->count()),
-                    right->slot(0));
-
-  // 5) Destroy the now-empty to_move entries in the right node.
-  right->value_destroy_n(right->count() - to_move, to_move, alloc);
+  // 4) Shift the values in the right node to their correct positions.
+  right->transfer_n(right->count() - to_move, right->start(),
+                    right->start() + to_move, right, alloc);
 
   if (!leaf()) {
     // Move the child pointers from the right to the left node.
     for (int i = 0; i < to_move; ++i) {
-      init_child(count() + i + 1, right->child(i));
+      init_child(finish() + i + 1, right->child(i));
     }
-    for (int i = 0; i <= right->count() - to_move; ++i) {
+    for (int i = right->start(); i <= right->finish() - to_move; ++i) {
       assert(i + to_move <= right->max_count());
       right->init_child(i, right->child(i + to_move));
       right->clear_child(i + to_move);
     }
   }
 
-  // Fixup the counts on the left and right nodes.
-  set_count(count() + to_move);
-  right->set_count(right->count() - to_move);
+  // Fixup `finish` on the left and right nodes.
+  set_finish(finish() + to_move);
+  right->set_finish(right->finish() - to_move);
 }
 
 template <typename P>
@@ -1576,67 +1656,35 @@
   // Lastly, a new delimiting value is moved from the left node into the
   // parent, and the remaining empty left node entries are destroyed.
 
-  if (right->count() >= to_move) {
-    // The original location of the right->count() values are sufficient to hold
-    // the new to_move entries from the parent and left node.
+  // 1) Shift existing values in the right node to their correct positions.
+  right->transfer_n_backward(right->count(), right->start() + to_move,
+                             right->start(), right, alloc);
 
-    // 1) Shift existing values in the right node to their correct positions.
-    right->uninitialized_move_n(to_move, right->count() - to_move,
-                                right->count(), right, alloc);
-    for (slot_type *src = right->slot(right->count() - to_move - 1),
-                   *dest = right->slot(right->count() - 1),
-                   *end = right->slot(0);
-         src >= end; --src, --dest) {
-      params_type::move(alloc, src, dest);
-    }
+  // 2) Move the delimiting value in the parent to the right node.
+  right->transfer(right->start() + to_move - 1, position(), parent(), alloc);
 
-    // 2) Move the delimiting value in the parent to the right node.
-    params_type::move(alloc, parent()->slot(position()),
-                      right->slot(to_move - 1));
-
-    // 3) Move the (to_move - 1) values from the left node to the right node.
-    params_type::move(alloc, slot(count() - (to_move - 1)), slot(count()),
-                      right->slot(0));
-  } else {
-    // The right node does not have enough initialized space to hold the new
-    // to_move entries, so part of them will move to uninitialized space.
-
-    // 1) Shift existing values in the right node to their correct positions.
-    right->uninitialized_move_n(right->count(), 0, to_move, right, alloc);
-
-    // 2) Move the delimiting value in the parent to the right node.
-    right->value_init(to_move - 1, alloc, parent()->slot(position()));
-
-    // 3) Move the (to_move - 1) values from the left node to the right node.
-    const size_type uninitialized_remaining = to_move - right->count() - 1;
-    uninitialized_move_n(uninitialized_remaining,
-                         count() - uninitialized_remaining, right->count(),
-                         right, alloc);
-    params_type::move(alloc, slot(count() - (to_move - 1)),
-                      slot(count() - uninitialized_remaining), right->slot(0));
-  }
+  // 3) Move the (to_move - 1) values from the left node to the right node.
+  right->transfer_n(to_move - 1, right->start(), finish() - (to_move - 1), this,
+                    alloc);
 
   // 4) Move the new delimiting value to the parent from the left node.
-  params_type::move(alloc, slot(count() - to_move), parent()->slot(position()));
-
-  // 5) Destroy the now-empty to_move entries in the left node.
-  value_destroy_n(count() - to_move, to_move, alloc);
+  parent()->transfer(position(), finish() - to_move, this, alloc);
 
   if (!leaf()) {
     // Move the child pointers from the left to the right node.
-    for (int i = right->count(); i >= 0; --i) {
+    for (int i = right->finish(); i >= right->start(); --i) {
       right->init_child(i + to_move, right->child(i));
       right->clear_child(i);
     }
     for (int i = 1; i <= to_move; ++i) {
-      right->init_child(i - 1, child(count() - to_move + i));
-      clear_child(count() - to_move + i);
+      right->init_child(i - 1, child(finish() - to_move + i));
+      clear_child(finish() - to_move + i);
     }
   }
 
   // Fixup the counts on the left and right nodes.
-  set_count(count() - to_move);
-  right->set_count(right->count() + to_move);
+  set_finish(finish() - to_move);
+  right->set_finish(right->finish() + to_move);
 }
 
 template <typename P>
@@ -1649,33 +1697,31 @@
   // inserting at the beginning of the left node then bias the split to put
   // more values on the right node. If we're inserting at the end of the
   // right node then bias the split to put more values on the left node.
-  if (insert_position == 0) {
-    dest->set_count(count() - 1);
+  if (insert_position == start()) {
+    dest->set_finish(dest->start() + finish() - 1);
   } else if (insert_position == kNodeValues) {
-    dest->set_count(0);
+    dest->set_finish(dest->start());
   } else {
-    dest->set_count(count() / 2);
+    dest->set_finish(dest->start() + count() / 2);
   }
-  set_count(count() - dest->count());
+  set_finish(finish() - dest->count());
   assert(count() >= 1);
 
   // Move values from the left sibling to the right sibling.
-  uninitialized_move_n(dest->count(), count(), 0, dest, alloc);
-
-  // Destroy the now-empty entries in the left node.
-  value_destroy_n(count(), dest->count(), alloc);
+  dest->transfer_n(dest->count(), dest->start(), finish(), this, alloc);
 
   // The split key is the largest value in the left sibling.
-  set_count(count() - 1);
-  parent()->emplace_value(position(), alloc, slot(count()));
-  value_destroy(count(), alloc);
+  --mutable_finish();
+  parent()->emplace_value(position(), alloc, finish_slot());
+  value_destroy(finish(), alloc);
   parent()->init_child(position() + 1, dest);
 
   if (!leaf()) {
-    for (int i = 0; i <= dest->count(); ++i) {
-      assert(child(count() + i + 1) != nullptr);
-      dest->init_child(i, child(count() + i + 1));
-      clear_child(count() + i + 1);
+    for (int i = dest->start(), j = finish() + 1; i <= dest->finish();
+         ++i, ++j) {
+      assert(child(j) != nullptr);
+      dest->init_child(i, child(j));
+      clear_child(j);
     }
   }
 }
@@ -1686,74 +1732,76 @@
   assert(position() + 1 == src->position());
 
   // Move the delimiting value to the left node.
-  value_init(count(), alloc, parent()->slot(position()));
+  value_init(finish(), alloc, parent()->slot(position()));
 
   // Move the values from the right to the left node.
-  src->uninitialized_move_n(src->count(), 0, count() + 1, this, alloc);
-
-  // Destroy the now-empty entries in the right node.
-  src->value_destroy_n(0, src->count(), alloc);
+  transfer_n(src->count(), finish() + 1, src->start(), src, alloc);
 
   if (!leaf()) {
     // Move the child pointers from the right to the left node.
-    for (int i = 0; i <= src->count(); ++i) {
-      init_child(count() + i + 1, src->child(i));
+    for (int i = src->start(), j = finish() + 1; i <= src->finish(); ++i, ++j) {
+      init_child(j, src->child(i));
       src->clear_child(i);
     }
   }
 
-  // Fixup the counts on the src and dest nodes.
-  set_count(1 + count() + src->count());
-  src->set_count(0);
+  // Fixup `finish` on the src and dest nodes.
+  set_finish(start() + 1 + count() + src->count());
+  src->set_finish(src->start());
 
-  // Remove the value on the parent node.
-  parent()->remove_value(position(), alloc);
+  // Remove the value on the parent node and delete the src node.
+  parent()->remove_values(position(), /*to_erase=*/1, alloc);
 }
 
 template <typename P>
-void btree_node<P>::swap(btree_node *x, allocator_type *alloc) {
-  using std::swap;
-  assert(leaf() == x->leaf());
-
-  // Determine which is the smaller/larger node.
-  btree_node *smaller = this, *larger = x;
-  if (smaller->count() > larger->count()) {
-    swap(smaller, larger);
+void btree_node<P>::clear_and_delete(btree_node *node, allocator_type *alloc) {
+  if (node->leaf()) {
+    node->value_destroy_n(node->start(), node->count(), alloc);
+    deallocate(LeafSize(node->max_count()), node, alloc);
+    return;
+  }
+  if (node->count() == 0) {
+    deallocate(InternalSize(), node, alloc);
+    return;
   }
 
-  // Swap the values.
-  for (slot_type *a = smaller->slot(0), *b = larger->slot(0),
-                 *end = a + smaller->count();
-       a != end; ++a, ++b) {
-    params_type::swap(alloc, a, b);
+  // The parent of the root of the subtree we are deleting.
+  btree_node *delete_root_parent = node->parent();
+
+  // Navigate to the leftmost leaf under node, and then delete upwards.
+  while (!node->leaf()) node = node->start_child();
+  // Use `int` because `pos` needs to be able to hold `kNodeValues+1`, which
+  // isn't guaranteed to be a valid `field_type`.
+  int pos = node->position();
+  btree_node *parent = node->parent();
+  for (;;) {
+    // In each iteration of the next loop, we delete one leaf node and go right.
+    assert(pos <= parent->finish());
+    do {
+      node = parent->child(pos);
+      if (!node->leaf()) {
+        // Navigate to the leftmost leaf under node.
+        while (!node->leaf()) node = node->start_child();
+        pos = node->position();
+        parent = node->parent();
+      }
+      node->value_destroy_n(node->start(), node->count(), alloc);
+      deallocate(LeafSize(node->max_count()), node, alloc);
+      ++pos;
+    } while (pos <= parent->finish());
+
+    // Once we've deleted all children of parent, delete parent and go up/right.
+    assert(pos > parent->finish());
+    do {
+      node = parent;
+      pos = node->position();
+      parent = node->parent();
+      node->value_destroy_n(node->start(), node->count(), alloc);
+      deallocate(InternalSize(), node, alloc);
+      if (parent == delete_root_parent) return;
+      ++pos;
+    } while (pos > parent->finish());
   }
-
-  // Move values that can't be swapped.
-  const size_type to_move = larger->count() - smaller->count();
-  larger->uninitialized_move_n(to_move, smaller->count(), smaller->count(),
-                               smaller, alloc);
-  larger->value_destroy_n(smaller->count(), to_move, alloc);
-
-  if (!leaf()) {
-    // Swap the child pointers.
-    std::swap_ranges(&smaller->mutable_child(0),
-                     &smaller->mutable_child(smaller->count() + 1),
-                     &larger->mutable_child(0));
-    // Update swapped children's parent pointers.
-    int i = 0;
-    for (; i <= smaller->count(); ++i) {
-      smaller->child(i)->set_parent(smaller);
-      larger->child(i)->set_parent(larger);
-    }
-    // Move the child pointers that couldn't be swapped.
-    for (; i <= larger->count(); ++i) {
-      smaller->init_child(i, larger->child(i));
-      larger->clear_child(i);
-    }
-  }
-
-  // Swap the counts.
-  swap(mutable_count(), x->mutable_count());
 }
 
 ////
@@ -1761,23 +1809,24 @@
 template <typename N, typename R, typename P>
 void btree_iterator<N, R, P>::increment_slow() {
   if (node->leaf()) {
-    assert(position >= node->count());
+    assert(position >= node->finish());
     btree_iterator save(*this);
-    while (position == node->count() && !node->is_root()) {
+    while (position == node->finish() && !node->is_root()) {
       assert(node->parent()->child(node->position()) == node);
       position = node->position();
       node = node->parent();
     }
-    if (position == node->count()) {
+    // TODO(ezb): assert we aren't incrementing end() instead of handling.
+    if (position == node->finish()) {
       *this = save;
     }
   } else {
-    assert(position < node->count());
+    assert(position < node->finish());
     node = node->child(position + 1);
     while (!node->leaf()) {
-      node = node->child(0);
+      node = node->start_child();
     }
-    position = 0;
+    position = node->start();
   }
 }
 
@@ -1786,21 +1835,22 @@
   if (node->leaf()) {
     assert(position <= -1);
     btree_iterator save(*this);
-    while (position < 0 && !node->is_root()) {
+    while (position < node->start() && !node->is_root()) {
       assert(node->parent()->child(node->position()) == node);
       position = node->position() - 1;
       node = node->parent();
     }
-    if (position < 0) {
+    // TODO(ezb): assert we aren't decrementing begin() instead of handling.
+    if (position < node->start()) {
       *this = save;
     }
   } else {
-    assert(position >= 0);
+    assert(position >= node->start());
     node = node->child(position);
     while (!node->leaf()) {
-      node = node->child(node->count());
+      node = node->child(node->finish());
     }
-    position = node->count() - 1;
+    position = node->finish() - 1;
   }
 }
 
@@ -1808,7 +1858,7 @@
 // btree methods
 template <typename P>
 template <typename Btree>
-void btree<P>::copy_or_move_values_in_order(Btree *x) {
+void btree<P>::copy_or_move_values_in_order(Btree &other) {
   static_assert(std::is_same<btree, Btree>::value ||
                     std::is_same<const btree, Btree>::value,
                 "Btree type must be same or const.");
@@ -1816,11 +1866,11 @@
 
   // We can avoid key comparisons because we know the order of the
   // values is the same order we'll store them in.
-  auto iter = x->begin();
-  if (iter == x->end()) return;
+  auto iter = other.begin();
+  if (iter == other.end()) return;
   insert_multi(maybe_move_from_iterator(iter));
   ++iter;
-  for (; iter != x->end(); ++iter) {
+  for (; iter != other.end(); ++iter) {
     // If the btree is not empty, we can just insert the new value at the end
     // of the tree.
     internal_emplace(end(), maybe_move_from_iterator(iter));
@@ -1859,24 +1909,57 @@
 }
 
 template <typename P>
-btree<P>::btree(const key_compare &comp, const allocator_type &alloc)
-    : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {}
-
-template <typename P>
-btree<P>::btree(const btree &x) : btree(x.key_comp(), x.allocator()) {
-  copy_or_move_values_in_order(&x);
+template <typename K>
+auto btree<P>::lower_bound_equal(const K &key) const
+    -> std::pair<iterator, bool> {
+  const SearchResult<iterator, is_key_compare_to::value> res =
+      internal_lower_bound(key);
+  const iterator lower = iterator(internal_end(res.value));
+  const bool equal = res.HasMatch()
+                         ? res.IsEq()
+                         : lower != end() && !compare_keys(key, lower.key());
+  return {lower, equal};
 }
 
 template <typename P>
-template <typename... Args>
-auto btree<P>::insert_unique(const key_type &key, Args &&... args)
+template <typename K>
+auto btree<P>::equal_range(const K &key) -> std::pair<iterator, iterator> {
+  const std::pair<iterator, bool> lower_and_equal = lower_bound_equal(key);
+  const iterator lower = lower_and_equal.first;
+  if (!lower_and_equal.second) {
+    return {lower, lower};
+  }
+
+  const iterator next = std::next(lower);
+  if (!params_type::template can_have_multiple_equivalent_keys<K>()) {
+    // The next iterator after lower must point to a key greater than `key`.
+    // Note: if this assert fails, then it may indicate that the comparator does
+    // not meet the equivalence requirements for Compare
+    // (see https://en.cppreference.com/w/cpp/named_req/Compare).
+    assert(next == end() || compare_keys(key, next.key()));
+    return {lower, next};
+  }
+  // Try once more to avoid the call to upper_bound() if there's only one
+  // equivalent key. This should prevent all calls to upper_bound() in cases of
+  // unique-containers with heterogeneous comparators in which all comparison
+  // operators have the same equivalence classes.
+  if (next == end() || compare_keys(key, next.key())) return {lower, next};
+
+  // In this case, we need to call upper_bound() to avoid worst case O(N)
+  // behavior if we were to iterate over equal keys.
+  return {lower, upper_bound(key)};
+}
+
+template <typename P>
+template <typename K, typename... Args>
+auto btree<P>::insert_unique(const K &key, Args &&... args)
     -> std::pair<iterator, bool> {
   if (empty()) {
     mutable_root() = rightmost_ = new_leaf_root_node(1);
   }
 
-  auto res = internal_locate(key);
-  iterator &iter = res.value;
+  SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
+  iterator iter = res.value;
 
   if (res.HasMatch()) {
     if (res.IsEq()) {
@@ -1894,14 +1977,13 @@
 }
 
 template <typename P>
-template <typename... Args>
-inline auto btree<P>::insert_hint_unique(iterator position, const key_type &key,
+template <typename K, typename... Args>
+inline auto btree<P>::insert_hint_unique(iterator position, const K &key,
                                          Args &&... args)
     -> std::pair<iterator, bool> {
   if (!empty()) {
     if (position == end() || compare_keys(key, position.key())) {
-      iterator prev = position;
-      if (position == begin() || compare_keys((--prev).key(), key)) {
+      if (position == begin() || compare_keys(std::prev(position).key(), key)) {
         // prev.key() < key < position.key()
         return {internal_emplace(position, std::forward<Args>(args)...), true};
       }
@@ -1920,14 +2002,23 @@
 }
 
 template <typename P>
-template <typename InputIterator>
-void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e) {
+template <typename InputIterator, typename>
+void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, int) {
   for (; b != e; ++b) {
     insert_hint_unique(end(), params_type::key(*b), *b);
   }
 }
 
 template <typename P>
+template <typename InputIterator>
+void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, char) {
+  for (; b != e; ++b) {
+    init_type value(*b);
+    insert_hint_unique(end(), params_type::key(value), std::move(value));
+  }
+}
+
+template <typename P>
 template <typename ValueType>
 auto btree<P>::insert_multi(const key_type &key, ValueType &&v) -> iterator {
   if (empty()) {
@@ -1947,17 +2038,16 @@
   if (!empty()) {
     const key_type &key = params_type::key(v);
     if (position == end() || !compare_keys(position.key(), key)) {
-      iterator prev = position;
-      if (position == begin() || !compare_keys(key, (--prev).key())) {
+      if (position == begin() ||
+          !compare_keys(key, std::prev(position).key())) {
         // prev.key() <= key <= position.key()
         return internal_emplace(position, std::forward<ValueType>(v));
       }
     } else {
-      iterator next = position;
-      ++next;
-      if (next == end() || !compare_keys(next.key(), key)) {
-        // position.key() < key <= next.key()
-        return internal_emplace(next, std::forward<ValueType>(v));
+      ++position;
+      if (position == end() || !compare_keys(position.key(), key)) {
+        // {original `position`}.key() < key < {current `position`}.key()
+        return internal_emplace(position, std::forward<ValueType>(v));
       }
     }
   }
@@ -1973,46 +2063,47 @@
 }
 
 template <typename P>
-auto btree<P>::operator=(const btree &x) -> btree & {
-  if (this != &x) {
+auto btree<P>::operator=(const btree &other) -> btree & {
+  if (this != &other) {
     clear();
 
-    *mutable_key_comp() = x.key_comp();
+    *mutable_key_comp() = other.key_comp();
     if (absl::allocator_traits<
             allocator_type>::propagate_on_container_copy_assignment::value) {
-      *mutable_allocator() = x.allocator();
+      *mutable_allocator() = other.allocator();
     }
 
-    copy_or_move_values_in_order(&x);
+    copy_or_move_values_in_order(other);
   }
   return *this;
 }
 
 template <typename P>
-auto btree<P>::operator=(btree &&x) noexcept -> btree & {
-  if (this != &x) {
+auto btree<P>::operator=(btree &&other) noexcept -> btree & {
+  if (this != &other) {
     clear();
 
     using std::swap;
     if (absl::allocator_traits<
             allocator_type>::propagate_on_container_copy_assignment::value) {
       // Note: `root_` also contains the allocator and the key comparator.
-      swap(root_, x.root_);
-      swap(rightmost_, x.rightmost_);
-      swap(size_, x.size_);
+      swap(root_, other.root_);
+      swap(rightmost_, other.rightmost_);
+      swap(size_, other.size_);
     } else {
-      if (allocator() == x.allocator()) {
-        swap(mutable_root(), x.mutable_root());
-        swap(*mutable_key_comp(), *x.mutable_key_comp());
-        swap(rightmost_, x.rightmost_);
-        swap(size_, x.size_);
+      if (allocator() == other.allocator()) {
+        swap(mutable_root(), other.mutable_root());
+        swap(*mutable_key_comp(), *other.mutable_key_comp());
+        swap(rightmost_, other.rightmost_);
+        swap(size_, other.size_);
       } else {
         // We aren't allowed to propagate the allocator and the allocator is
         // different so we can't take over its memory. We must move each element
-        // individually. We need both `x` and `this` to have `x`s key comparator
-        // while moving the values so we can't swap the key comparators.
-        *mutable_key_comp() = x.key_comp();
-        copy_or_move_values_in_order(&x);
+        // individually. We need both `other` and `this` to have `other`s key
+        // comparator while moving the values so we can't swap the key
+        // comparators.
+        *mutable_key_comp() = other.key_comp();
+        copy_or_move_values_in_order(other);
       }
     }
   }
@@ -2024,20 +2115,19 @@
   bool internal_delete = false;
   if (!iter.node->leaf()) {
     // Deletion of a value on an internal node. First, move the largest value
-    // from our left child here, then delete that position (in remove_value()
+    // from our left child here, then delete that position (in remove_values()
     // below). We can get to the largest value from our left child by
     // decrementing iter.
     iterator internal_iter(iter);
     --iter;
     assert(iter.node->leaf());
-    assert(!compare_keys(internal_iter.key(), iter.key()));
     params_type::move(mutable_allocator(), iter.node->slot(iter.position),
                       internal_iter.node->slot(internal_iter.position));
     internal_delete = true;
   }
 
   // Delete the key from the leaf.
-  iter.node->remove_value(iter.position, mutable_allocator());
+  iter.node->remove_values(iter.position, /*to_erase=*/1, mutable_allocator());
   --size_;
 
   // We want to return the next value after the one we just erased. If we
@@ -2088,8 +2178,8 @@
 
   // Adjust our return value. If we're pointing at the end of a node, advance
   // the iterator.
-  if (res.position == res.node->count()) {
-    res.position = res.node->count() - 1;
+  if (res.position == res.node->finish()) {
+    res.position = res.node->finish() - 1;
     ++res;
   }
 
@@ -2097,7 +2187,7 @@
 }
 
 template <typename P>
-auto btree<P>::erase(iterator begin, iterator end)
+auto btree<P>::erase_range(iterator begin, iterator end)
     -> std::pair<size_type, iterator> {
   difference_type count = std::distance(begin, end);
   assert(count >= 0);
@@ -2112,7 +2202,9 @@
   }
 
   if (begin.node == end.node) {
-    erase_same_node(begin, end);
+    assert(end.position > begin.position);
+    begin.node->remove_values(begin.position, end.position - begin.position,
+                              mutable_allocator());
     size_ -= count;
     return {count, rebalance_after_delete(begin)};
   }
@@ -2121,9 +2213,12 @@
   while (size_ > target_size) {
     if (begin.node->leaf()) {
       const size_type remaining_to_erase = size_ - target_size;
-      const size_type remaining_in_node = begin.node->count() - begin.position;
-      begin = erase_from_leaf_node(
-          begin, (std::min)(remaining_to_erase, remaining_in_node));
+      const size_type remaining_in_node = begin.node->finish() - begin.position;
+      const size_type to_erase =
+          (std::min)(remaining_to_erase, remaining_in_node);
+      begin.node->remove_values(begin.position, to_erase, mutable_allocator());
+      size_ -= to_erase;
+      begin = rebalance_after_delete(begin);
     } else {
       begin = erase(begin);
     }
@@ -2132,78 +2227,9 @@
 }
 
 template <typename P>
-void btree<P>::erase_same_node(iterator begin, iterator end) {
-  assert(begin.node == end.node);
-  assert(end.position > begin.position);
-
-  node_type *node = begin.node;
-  size_type to_erase = end.position - begin.position;
-  if (!node->leaf()) {
-    // Delete all children between begin and end.
-    for (size_type i = 0; i < to_erase; ++i) {
-      internal_clear(node->child(begin.position + i + 1));
-    }
-    // Rotate children after end into new positions.
-    for (size_type i = begin.position + to_erase + 1; i <= node->count(); ++i) {
-      node->set_child(i - to_erase, node->child(i));
-      node->clear_child(i);
-    }
-  }
-  node->remove_values_ignore_children(begin.position, to_erase,
-                                      mutable_allocator());
-
-  // Do not need to update rightmost_, because
-  // * either end == this->end(), and therefore node == rightmost_, and still
-  //   exists
-  // * or end != this->end(), and therefore rightmost_ hasn't been erased, since
-  //   it wasn't covered in [begin, end)
-}
-
-template <typename P>
-auto btree<P>::erase_from_leaf_node(iterator begin, size_type to_erase)
-    -> iterator {
-  node_type *node = begin.node;
-  assert(node->leaf());
-  assert(node->count() > begin.position);
-  assert(begin.position + to_erase <= node->count());
-
-  node->remove_values_ignore_children(begin.position, to_erase,
-                                      mutable_allocator());
-
-  size_ -= to_erase;
-
-  return rebalance_after_delete(begin);
-}
-
-template <typename P>
-template <typename K>
-auto btree<P>::erase_unique(const K &key) -> size_type {
-  const iterator iter = internal_find(key);
-  if (iter.node == nullptr) {
-    // The key doesn't exist in the tree, return nothing done.
-    return 0;
-  }
-  erase(iter);
-  return 1;
-}
-
-template <typename P>
-template <typename K>
-auto btree<P>::erase_multi(const K &key) -> size_type {
-  const iterator begin = internal_lower_bound(key);
-  if (begin.node == nullptr) {
-    // The key doesn't exist in the tree, return nothing done.
-    return 0;
-  }
-  // Delete all of the keys between begin and upper_bound(key).
-  const iterator end = internal_end(internal_upper_bound(key));
-  return erase(begin, end).first;
-}
-
-template <typename P>
 void btree<P>::clear() {
   if (!empty()) {
-    internal_clear(root());
+    node_type::clear_and_delete(root(), mutable_allocator());
   }
   mutable_root() = EmptyNode();
   rightmost_ = EmptyNode();
@@ -2211,20 +2237,20 @@
 }
 
 template <typename P>
-void btree<P>::swap(btree &x) {
+void btree<P>::swap(btree &other) {
   using std::swap;
   if (absl::allocator_traits<
           allocator_type>::propagate_on_container_swap::value) {
     // Note: `root_` also contains the allocator and the key comparator.
-    swap(root_, x.root_);
+    swap(root_, other.root_);
   } else {
     // It's undefined behavior if the allocators are unequal here.
-    assert(allocator() == x.allocator());
-    swap(mutable_root(), x.mutable_root());
-    swap(*mutable_key_comp(), *x.mutable_key_comp());
+    assert(allocator() == other.allocator());
+    swap(mutable_root(), other.mutable_root());
+    swap(*mutable_key_comp(), *other.mutable_key_comp());
   }
-  swap(rightmost_, x.rightmost_);
-  swap(size_, x.size_);
+  swap(rightmost_, other.rightmost_);
+  swap(size_, other.size_);
 }
 
 template <typename P>
@@ -2234,7 +2260,7 @@
   assert(rightmost_ != nullptr);
   assert(empty() || size() == internal_verify(root(), nullptr, nullptr));
   assert(leftmost() == (++const_iterator(root(), -1)).node);
-  assert(rightmost_ == (--const_iterator(root(), root()->count())).node);
+  assert(rightmost_ == (--const_iterator(root(), root()->finish())).node);
   assert(leftmost()->leaf());
   assert(rightmost_->leaf());
 }
@@ -2249,7 +2275,7 @@
   // First try to make room on the node by rebalancing.
   node_type *parent = node->parent();
   if (node != root()) {
-    if (node->position() > 0) {
+    if (node->position() > parent->start()) {
       // Try rebalancing with our left sibling.
       node_type *left = parent->child(node->position() - 1);
       assert(left->max_count() == kNodeValues);
@@ -2258,16 +2284,16 @@
         // inserting at the end of the right node then we bias rebalancing to
         // fill up the left node.
         int to_move = (kNodeValues - left->count()) /
-                      (1 + (insert_position < kNodeValues));
+                      (1 + (insert_position < static_cast<int>(kNodeValues)));
         to_move = (std::max)(1, to_move);
 
-        if (((insert_position - to_move) >= 0) ||
-            ((left->count() + to_move) < kNodeValues)) {
+        if (insert_position - to_move >= node->start() ||
+            left->count() + to_move < static_cast<int>(kNodeValues)) {
           left->rebalance_right_to_left(to_move, node, mutable_allocator());
 
           assert(node->max_count() - node->count() == to_move);
           insert_position = insert_position - to_move;
-          if (insert_position < 0) {
+          if (insert_position < node->start()) {
             insert_position = insert_position + left->count() + 1;
             node = left;
           }
@@ -2278,7 +2304,7 @@
       }
     }
 
-    if (node->position() < parent->count()) {
+    if (node->position() < parent->finish()) {
       // Try rebalancing with our right sibling.
       node_type *right = parent->child(node->position() + 1);
       assert(right->max_count() == kNodeValues);
@@ -2286,15 +2312,15 @@
         // We bias rebalancing based on the position being inserted. If we're
         // inserting at the beginning of the left node then we bias rebalancing
         // to fill up the right node.
-        int to_move =
-            (kNodeValues - right->count()) / (1 + (insert_position > 0));
+        int to_move = (static_cast<int>(kNodeValues) - right->count()) /
+                      (1 + (insert_position > node->start()));
         to_move = (std::max)(1, to_move);
 
-        if ((insert_position <= (node->count() - to_move)) ||
-            ((right->count() + to_move) < kNodeValues)) {
+        if (insert_position <= node->finish() - to_move ||
+            right->count() + to_move < static_cast<int>(kNodeValues)) {
           node->rebalance_left_to_right(to_move, right, mutable_allocator());
 
-          if (insert_position > node->count()) {
+          if (insert_position > node->finish()) {
             insert_position = insert_position - node->count() - 1;
             node = right;
           }
@@ -2317,10 +2343,11 @@
     // Create a new root node and set the current root node as the child of the
     // new root.
     parent = new_internal_node(parent);
-    parent->init_child(0, root());
+    parent->init_child(parent->start(), root());
     mutable_root() = parent;
     // If the former root was a leaf node, then it's now the rightmost node.
-    assert(!parent->child(0)->leaf() || parent->child(0) == rightmost_);
+    assert(!parent->start_child()->leaf() ||
+           parent->start_child() == rightmost_);
   }
 
   // Split the node.
@@ -2334,7 +2361,7 @@
     node->split(insert_position, split_node, mutable_allocator());
   }
 
-  if (insert_position > node->count()) {
+  if (insert_position > node->finish()) {
     insert_position = insert_position - node->count() - 1;
     node = split_node;
   }
@@ -2343,33 +2370,28 @@
 template <typename P>
 void btree<P>::merge_nodes(node_type *left, node_type *right) {
   left->merge(right, mutable_allocator());
-  if (right->leaf()) {
-    if (rightmost_ == right) rightmost_ = left;
-    delete_leaf_node(right);
-  } else {
-    delete_internal_node(right);
-  }
+  if (rightmost_ == right) rightmost_ = left;
 }
 
 template <typename P>
 bool btree<P>::try_merge_or_rebalance(iterator *iter) {
   node_type *parent = iter->node->parent();
-  if (iter->node->position() > 0) {
+  if (iter->node->position() > parent->start()) {
     // Try merging with our left sibling.
     node_type *left = parent->child(iter->node->position() - 1);
     assert(left->max_count() == kNodeValues);
-    if ((1 + left->count() + iter->node->count()) <= kNodeValues) {
+    if (1U + left->count() + iter->node->count() <= kNodeValues) {
       iter->position += 1 + left->count();
       merge_nodes(left, iter->node);
       iter->node = left;
       return true;
     }
   }
-  if (iter->node->position() < parent->count()) {
+  if (iter->node->position() < parent->finish()) {
     // Try merging with our right sibling.
     node_type *right = parent->child(iter->node->position() + 1);
     assert(right->max_count() == kNodeValues);
-    if ((1 + iter->node->count() + right->count()) <= kNodeValues) {
+    if (1U + iter->node->count() + right->count() <= kNodeValues) {
       merge_nodes(iter->node, right);
       return true;
     }
@@ -2377,24 +2399,22 @@
     // we deleted the first element from iter->node and the node is not
     // empty. This is a small optimization for the common pattern of deleting
     // from the front of the tree.
-    if ((right->count() > kMinNodeValues) &&
-        ((iter->node->count() == 0) ||
-         (iter->position > 0))) {
+    if (right->count() > kMinNodeValues &&
+        (iter->node->count() == 0 || iter->position > iter->node->start())) {
       int to_move = (right->count() - iter->node->count()) / 2;
       to_move = (std::min)(to_move, right->count() - 1);
       iter->node->rebalance_right_to_left(to_move, right, mutable_allocator());
       return false;
     }
   }
-  if (iter->node->position() > 0) {
+  if (iter->node->position() > parent->start()) {
     // Try rebalancing with our left sibling. We don't perform rebalancing if
     // we deleted the last element from iter->node and the node is not
     // empty. This is a small optimization for the common pattern of deleting
     // from the back of the tree.
     node_type *left = parent->child(iter->node->position() - 1);
-    if ((left->count() > kMinNodeValues) &&
-        ((iter->node->count() == 0) ||
-         (iter->position < iter->node->count()))) {
+    if (left->count() > kMinNodeValues &&
+        (iter->node->count() == 0 || iter->position < iter->node->finish())) {
       int to_move = (left->count() - iter->node->count()) / 2;
       to_move = (std::min)(to_move, left->count() - 1);
       left->rebalance_left_to_right(to_move, iter->node, mutable_allocator());
@@ -2407,28 +2427,27 @@
 
 template <typename P>
 void btree<P>::try_shrink() {
-  if (root()->count() > 0) {
+  node_type *orig_root = root();
+  if (orig_root->count() > 0) {
     return;
   }
   // Deleted the last item on the root node, shrink the height of the tree.
-  if (root()->leaf()) {
+  if (orig_root->leaf()) {
     assert(size() == 0);
-    delete_leaf_node(root());
-    mutable_root() = EmptyNode();
-    rightmost_ = EmptyNode();
+    mutable_root() = rightmost_ = EmptyNode();
   } else {
-    node_type *child = root()->child(0);
+    node_type *child = orig_root->start_child();
     child->make_root();
-    delete_internal_node(root());
     mutable_root() = child;
   }
+  node_type::clear_and_delete(orig_root, mutable_allocator());
 }
 
 template <typename P>
 template <typename IterType>
 inline IterType btree<P>::internal_last(IterType iter) {
   assert(iter.node != nullptr);
-  while (iter.position == iter.node->count()) {
+  while (iter.position == iter.node->finish()) {
     iter.position = iter.node->position();
     iter.node = iter.node->parent();
     if (iter.node->leaf()) {
@@ -2449,7 +2468,8 @@
     --iter;
     ++iter.position;
   }
-  const int max_count = iter.node->max_count();
+  const field_type max_count = iter.node->max_count();
+  allocator_type *alloc = mutable_allocator();
   if (iter.node->count() == max_count) {
     // Make room in the leaf for the new item.
     if (max_count < kNodeValues) {
@@ -2458,16 +2478,20 @@
       assert(iter.node == root());
       iter.node =
           new_leaf_root_node((std::min<int>)(kNodeValues, 2 * max_count));
-      iter.node->swap(root(), mutable_allocator());
-      delete_leaf_node(root());
-      mutable_root() = iter.node;
-      rightmost_ = iter.node;
+      // Transfer the values from the old root to the new root.
+      node_type *old_root = root();
+      node_type *new_root = iter.node;
+      new_root->transfer_n(old_root->count(), new_root->start(),
+                           old_root->start(), old_root, alloc);
+      new_root->set_finish(old_root->finish());
+      old_root->set_finish(old_root->start());
+      node_type::clear_and_delete(old_root, alloc);
+      mutable_root() = rightmost_ = new_root;
     } else {
       rebalance_or_split(&iter);
     }
   }
-  iter.node->emplace_value(iter.position, mutable_allocator(),
-                           std::forward<Args>(args)...);
+  iter.node->emplace_value(iter.position, alloc, std::forward<Args>(args)...);
   ++size_;
   return iter;
 }
@@ -2476,67 +2500,57 @@
 template <typename K>
 inline auto btree<P>::internal_locate(const K &key) const
     -> SearchResult<iterator, is_key_compare_to::value> {
-  return internal_locate_impl(key, is_key_compare_to());
-}
-
-template <typename P>
-template <typename K>
-inline auto btree<P>::internal_locate_impl(
-    const K &key, std::false_type /* IsCompareTo */) const
-    -> SearchResult<iterator, false> {
-  iterator iter(const_cast<node_type *>(root()), 0);
+  iterator iter(const_cast<node_type *>(root()));
   for (;;) {
-    iter.position = iter.node->lower_bound(key, key_comp()).value;
-    // NOTE: we don't need to walk all the way down the tree if the keys are
-    // equal, but determining equality would require doing an extra comparison
-    // on each node on the way down, and we will need to go all the way to the
-    // leaf node in the expected case.
-    if (iter.node->leaf()) {
-      break;
-    }
-    iter.node = iter.node->child(iter.position);
-  }
-  return {iter};
-}
-
-template <typename P>
-template <typename K>
-inline auto btree<P>::internal_locate_impl(
-    const K &key, std::true_type /* IsCompareTo */) const
-    -> SearchResult<iterator, true> {
-  iterator iter(const_cast<node_type *>(root()), 0);
-  for (;;) {
-    SearchResult<int, true> res = iter.node->lower_bound(key, key_comp());
+    SearchResult<int, is_key_compare_to::value> res =
+        iter.node->lower_bound(key, key_comp());
     iter.position = res.value;
-    if (res.match == MatchKind::kEq) {
+    if (res.IsEq()) {
       return {iter, MatchKind::kEq};
     }
+    // Note: in the non-key-compare-to case, we don't need to walk all the way
+    // down the tree if the keys are equal, but determining equality would
+    // require doing an extra comparison on each node on the way down, and we
+    // will need to go all the way to the leaf node in the expected case.
     if (iter.node->leaf()) {
       break;
     }
     iter.node = iter.node->child(iter.position);
   }
+  // Note: in the non-key-compare-to case, the key may actually be equivalent
+  // here (and the MatchKind::kNe is ignored).
   return {iter, MatchKind::kNe};
 }
 
 template <typename P>
 template <typename K>
-auto btree<P>::internal_lower_bound(const K &key) const -> iterator {
-  iterator iter(const_cast<node_type *>(root()), 0);
+auto btree<P>::internal_lower_bound(const K &key) const
+    -> SearchResult<iterator, is_key_compare_to::value> {
+  if (!params_type::template can_have_multiple_equivalent_keys<K>()) {
+    SearchResult<iterator, is_key_compare_to::value> ret = internal_locate(key);
+    ret.value = internal_last(ret.value);
+    return ret;
+  }
+  iterator iter(const_cast<node_type *>(root()));
+  SearchResult<int, is_key_compare_to::value> res;
+  bool seen_eq = false;
   for (;;) {
-    iter.position = iter.node->lower_bound(key, key_comp()).value;
+    res = iter.node->lower_bound(key, key_comp());
+    iter.position = res.value;
     if (iter.node->leaf()) {
       break;
     }
+    seen_eq = seen_eq || res.IsEq();
     iter.node = iter.node->child(iter.position);
   }
-  return internal_last(iter);
+  if (res.IsEq()) return {iter, MatchKind::kEq};
+  return {internal_last(iter), seen_eq ? MatchKind::kEq : MatchKind::kNe};
 }
 
 template <typename P>
 template <typename K>
 auto btree<P>::internal_upper_bound(const K &key) const -> iterator {
-  iterator iter(const_cast<node_type *>(root()), 0);
+  iterator iter(const_cast<node_type *>(root()));
   for (;;) {
     iter.position = iter.node->upper_bound(key, key_comp());
     if (iter.node->leaf()) {
@@ -2550,7 +2564,7 @@
 template <typename P>
 template <typename K>
 auto btree<P>::internal_find(const K &key) const -> iterator {
-  auto res = internal_locate(key);
+  SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
   if (res.HasMatch()) {
     if (res.IsEq()) {
       return res.value;
@@ -2565,47 +2579,35 @@
 }
 
 template <typename P>
-void btree<P>::internal_clear(node_type *node) {
-  if (!node->leaf()) {
-    for (int i = 0; i <= node->count(); ++i) {
-      internal_clear(node->child(i));
-    }
-    delete_internal_node(node);
-  } else {
-    delete_leaf_node(node);
-  }
-}
-
-template <typename P>
-int btree<P>::internal_verify(
-    const node_type *node, const key_type *lo, const key_type *hi) const {
+int btree<P>::internal_verify(const node_type *node, const key_type *lo,
+                              const key_type *hi) const {
   assert(node->count() > 0);
   assert(node->count() <= node->max_count());
   if (lo) {
-    assert(!compare_keys(node->key(0), *lo));
+    assert(!compare_keys(node->key(node->start()), *lo));
   }
   if (hi) {
-    assert(!compare_keys(*hi, node->key(node->count() - 1)));
+    assert(!compare_keys(*hi, node->key(node->finish() - 1)));
   }
-  for (int i = 1; i < node->count(); ++i) {
+  for (int i = node->start() + 1; i < node->finish(); ++i) {
     assert(!compare_keys(node->key(i), node->key(i - 1)));
   }
   int count = node->count();
   if (!node->leaf()) {
-    for (int i = 0; i <= node->count(); ++i) {
+    for (int i = node->start(); i <= node->finish(); ++i) {
       assert(node->child(i) != nullptr);
       assert(node->child(i)->parent() == node);
       assert(node->child(i)->position() == i);
-      count += internal_verify(
-          node->child(i),
-          (i == 0) ? lo : &node->key(i - 1),
-          (i == node->count()) ? hi : &node->key(i));
+      count += internal_verify(node->child(i),
+                               i == node->start() ? lo : &node->key(i - 1),
+                               i == node->finish() ? hi : &node->key(i));
     }
   }
   return count;
 }
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_BTREE_H_
diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h
index 726861d..03be708 100644
--- a/absl/container/internal/btree_container.h
+++ b/absl/container/internal/btree_container.h
@@ -23,9 +23,11 @@
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/container/internal/btree.h"  // IWYU pragma: export
 #include "absl/container/internal/common.h"
+#include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 // A common base class for btree_set, btree_map, btree_multiset, and
@@ -67,10 +69,23 @@
   explicit btree_container(const key_compare &comp,
                            const allocator_type &alloc = allocator_type())
       : tree_(comp, alloc) {}
-  btree_container(const btree_container &x) = default;
-  btree_container(btree_container &&x) noexcept = default;
-  btree_container &operator=(const btree_container &x) = default;
-  btree_container &operator=(btree_container &&x) noexcept(
+  explicit btree_container(const allocator_type &alloc)
+      : tree_(key_compare(), alloc) {}
+
+  btree_container(const btree_container &other)
+      : btree_container(other, absl::allocator_traits<allocator_type>::
+                                   select_on_container_copy_construction(
+                                       other.get_allocator())) {}
+  btree_container(const btree_container &other, const allocator_type &alloc)
+      : tree_(other.tree_, alloc) {}
+
+  btree_container(btree_container &&other) noexcept(
+      std::is_nothrow_move_constructible<Tree>::value) = default;
+  btree_container(btree_container &&other, const allocator_type &alloc)
+      : tree_(std::move(other.tree_), alloc) {}
+
+  btree_container &operator=(const btree_container &other) = default;
+  btree_container &operator=(btree_container &&other) noexcept(
       std::is_nothrow_move_assignable<Tree>::value) = default;
 
   // Iterator routines.
@@ -89,6 +104,11 @@
 
   // Lookup routines.
   template <typename K = key_type>
+  size_type count(const key_arg<K> &key) const {
+    auto equal_range = this->equal_range(key);
+    return std::distance(equal_range.first, equal_range.second);
+  }
+  template <typename K = key_type>
   iterator find(const key_arg<K> &key) {
     return tree_.find(key);
   }
@@ -135,7 +155,12 @@
   iterator erase(const_iterator iter) { return tree_.erase(iterator(iter)); }
   iterator erase(iterator iter) { return tree_.erase(iter); }
   iterator erase(const_iterator first, const_iterator last) {
-    return tree_.erase(iterator(first), iterator(last)).second;
+    return tree_.erase_range(iterator(first), iterator(last)).second;
+  }
+  template <typename K = key_type>
+  size_type erase(const key_arg<K> &key) {
+    auto equal_range = this->equal_range(key);
+    return tree_.erase_range(equal_range.first, equal_range.second).first;
   }
 
   // Extract routines.
@@ -150,10 +175,9 @@
     return extract(iterator(position));
   }
 
- public:
   // Utility routines.
   void clear() { tree_.clear(); }
-  void swap(btree_container &x) { tree_.swap(x.tree_); }
+  void swap(btree_container &other) { tree_.swap(other.tree_); }
   void verify() const { tree_.verify(); }
 
   // Size routines.
@@ -234,7 +258,7 @@
   using super_type::super_type;
   btree_set_container() {}
 
-  // Range constructor.
+  // Range constructors.
   template <class InputIterator>
   btree_set_container(InputIterator b, InputIterator e,
                       const key_compare &comp = key_compare(),
@@ -242,63 +266,63 @@
       : super_type(comp, alloc) {
     insert(b, e);
   }
+  template <class InputIterator>
+  btree_set_container(InputIterator b, InputIterator e,
+                      const allocator_type &alloc)
+      : btree_set_container(b, e, key_compare(), alloc) {}
 
-  // Initializer list constructor.
+  // Initializer list constructors.
   btree_set_container(std::initializer_list<init_type> init,
                       const key_compare &comp = key_compare(),
                       const allocator_type &alloc = allocator_type())
       : btree_set_container(init.begin(), init.end(), comp, alloc) {}
-
-  // Lookup routines.
-  template <typename K = key_type>
-  size_type count(const key_arg<K> &key) const {
-    return this->tree_.count_unique(key);
-  }
+  btree_set_container(std::initializer_list<init_type> init,
+                      const allocator_type &alloc)
+      : btree_set_container(init.begin(), init.end(), alloc) {}
 
   // Insertion routines.
-  std::pair<iterator, bool> insert(const value_type &x) {
-    return this->tree_.insert_unique(params_type::key(x), x);
+  std::pair<iterator, bool> insert(const value_type &v) {
+    return this->tree_.insert_unique(params_type::key(v), v);
   }
-  std::pair<iterator, bool> insert(value_type &&x) {
-    return this->tree_.insert_unique(params_type::key(x), std::move(x));
+  std::pair<iterator, bool> insert(value_type &&v) {
+    return this->tree_.insert_unique(params_type::key(v), std::move(v));
   }
   template <typename... Args>
   std::pair<iterator, bool> emplace(Args &&... args) {
     init_type v(std::forward<Args>(args)...);
     return this->tree_.insert_unique(params_type::key(v), std::move(v));
   }
-  iterator insert(const_iterator position, const value_type &x) {
+  iterator insert(const_iterator hint, const value_type &v) {
     return this->tree_
-        .insert_hint_unique(iterator(position), params_type::key(x), x)
+        .insert_hint_unique(iterator(hint), params_type::key(v), v)
         .first;
   }
-  iterator insert(const_iterator position, value_type &&x) {
+  iterator insert(const_iterator hint, value_type &&v) {
     return this->tree_
-        .insert_hint_unique(iterator(position), params_type::key(x),
-                            std::move(x))
+        .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))
         .first;
   }
   template <typename... Args>
-  iterator emplace_hint(const_iterator position, Args &&... args) {
+  iterator emplace_hint(const_iterator hint, Args &&... args) {
     init_type v(std::forward<Args>(args)...);
     return this->tree_
-        .insert_hint_unique(iterator(position), params_type::key(v),
-                            std::move(v))
+        .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))
         .first;
   }
   template <typename InputIterator>
   void insert(InputIterator b, InputIterator e) {
-    this->tree_.insert_iterator_unique(b, e);
+    this->tree_.insert_iterator_unique(b, e, 0);
   }
   void insert(std::initializer_list<init_type> init) {
-    this->tree_.insert_iterator_unique(init.begin(), init.end());
+    this->tree_.insert_iterator_unique(init.begin(), init.end(), 0);
   }
   insert_return_type insert(node_type &&node) {
     if (!node) return {this->end(), false, node_type()};
     std::pair<iterator, bool> res =
-        insert(std::move(params_type::element(CommonAccess::GetSlot(node))));
+        this->tree_.insert_unique(params_type::key(CommonAccess::GetSlot(node)),
+                                  CommonAccess::GetSlot(node));
     if (res.second) {
-      CommonAccess::Reset(&node);
+      CommonAccess::Destroy(&node);
       return {res.first, true, node_type()};
     } else {
       return {res.first, false, std::move(node)};
@@ -308,23 +332,18 @@
     if (!node) return this->end();
     std::pair<iterator, bool> res = this->tree_.insert_hint_unique(
         iterator(hint), params_type::key(CommonAccess::GetSlot(node)),
-        std::move(params_type::element(CommonAccess::GetSlot(node))));
-    if (res.second) CommonAccess::Reset(&node);
+        CommonAccess::GetSlot(node));
+    if (res.second) CommonAccess::Destroy(&node);
     return res.first;
   }
 
-  // Deletion routines.
-  template <typename K = key_type>
-  size_type erase(const key_arg<K> &key) {
-    return this->tree_.erase_unique(key);
-  }
-  using super_type::erase;
-
   // Node extraction routines.
   template <typename K = key_type>
   node_type extract(const key_arg<K> &key) {
-    auto it = find(key);
-    return it == this->end() ? node_type() : extract(it);
+    const std::pair<iterator, bool> lower_and_equal =
+        this->tree_.lower_bound_equal(key);
+    return lower_and_equal.second ? extract(lower_and_equal.first)
+                                  : node_type();
   }
   using super_type::extract;
 
@@ -342,7 +361,7 @@
           int> = 0>
   void merge(btree_container<T> &src) {  // NOLINT
     for (auto src_it = src.begin(); src_it != src.end();) {
-      if (insert(std::move(*src_it)).second) {
+      if (insert(std::move(params_type::element(src_it.slot()))).second) {
         src_it = src.erase(src_it);
       } else {
         ++src_it;
@@ -369,8 +388,9 @@
 class btree_map_container : public btree_set_container<Tree> {
   using super_type = btree_set_container<Tree>;
   using params_type = typename Tree::params_type;
+  friend class BtreeNodePeer;
 
- protected:
+ private:
   template <class K>
   using key_arg = typename super_type::template key_arg<K>;
 
@@ -388,50 +408,74 @@
   btree_map_container() {}
 
   // Insertion routines.
-  template <typename... Args>
-  std::pair<iterator, bool> try_emplace(const key_type &k, Args &&... args) {
-    return this->tree_.insert_unique(
-        k, std::piecewise_construct, std::forward_as_tuple(k),
-        std::forward_as_tuple(std::forward<Args>(args)...));
+  // Note: the nullptr template arguments and extra `const M&` overloads allow
+  // for supporting bitfield arguments.
+  template <typename K = key_type, class M>
+  std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k,
+                                             const M &obj) {
+    return insert_or_assign_impl(k, obj);
   }
-  template <typename... Args>
-  std::pair<iterator, bool> try_emplace(key_type &&k, Args &&... args) {
-    // Note: `key_ref` exists to avoid a ClangTidy warning about moving from `k`
-    // and then using `k` unsequenced. This is safe because the move is into a
-    // forwarding reference and insert_unique guarantees that `key` is never
-    // referenced after consuming `args`.
-    const key_type& key_ref = k;
-    return this->tree_.insert_unique(
-        key_ref, std::piecewise_construct, std::forward_as_tuple(std::move(k)),
-        std::forward_as_tuple(std::forward<Args>(args)...));
+  template <typename K = key_type, class M, K * = nullptr>
+  std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, const M &obj) {
+    return insert_or_assign_impl(std::forward<K>(k), obj);
   }
-  template <typename... Args>
-  iterator try_emplace(const_iterator hint, const key_type &k,
+  template <typename K = key_type, class M, M * = nullptr>
+  std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, M &&obj) {
+    return insert_or_assign_impl(k, std::forward<M>(obj));
+  }
+  template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
+  std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, M &&obj) {
+    return insert_or_assign_impl(std::forward<K>(k), std::forward<M>(obj));
+  }
+  template <typename K = key_type, class M>
+  iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
+                            const M &obj) {
+    return insert_or_assign_hint_impl(hint, k, obj);
+  }
+  template <typename K = key_type, class M, K * = nullptr>
+  iterator insert_or_assign(const_iterator hint, key_arg<K> &&k, const M &obj) {
+    return insert_or_assign_hint_impl(hint, std::forward<K>(k), obj);
+  }
+  template <typename K = key_type, class M, M * = nullptr>
+  iterator insert_or_assign(const_iterator hint, const key_arg<K> &k, M &&obj) {
+    return insert_or_assign_hint_impl(hint, k, std::forward<M>(obj));
+  }
+  template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
+  iterator insert_or_assign(const_iterator hint, key_arg<K> &&k, M &&obj) {
+    return insert_or_assign_hint_impl(hint, std::forward<K>(k),
+                                      std::forward<M>(obj));
+  }
+
+  template <typename K = key_type, typename... Args,
+            typename absl::enable_if_t<
+                !std::is_convertible<K, const_iterator>::value, int> = 0>
+  std::pair<iterator, bool> try_emplace(const key_arg<K> &k, Args &&... args) {
+    return try_emplace_impl(k, std::forward<Args>(args)...);
+  }
+  template <typename K = key_type, typename... Args,
+            typename absl::enable_if_t<
+                !std::is_convertible<K, const_iterator>::value, int> = 0>
+  std::pair<iterator, bool> try_emplace(key_arg<K> &&k, Args &&... args) {
+    return try_emplace_impl(std::forward<K>(k), std::forward<Args>(args)...);
+  }
+  template <typename K = key_type, typename... Args>
+  iterator try_emplace(const_iterator hint, const key_arg<K> &k,
                        Args &&... args) {
-    return this->tree_
-        .insert_hint_unique(iterator(hint), k, std::piecewise_construct,
-                            std::forward_as_tuple(k),
-                            std::forward_as_tuple(std::forward<Args>(args)...))
-        .first;
+    return try_emplace_hint_impl(hint, k, std::forward<Args>(args)...);
   }
-  template <typename... Args>
-  iterator try_emplace(const_iterator hint, key_type &&k, Args &&... args) {
-    // Note: `key_ref` exists to avoid a ClangTidy warning about moving from `k`
-    // and then using `k` unsequenced. This is safe because the move is into a
-    // forwarding reference and insert_hint_unique guarantees that `key` is
-    // never referenced after consuming `args`.
-    const key_type& key_ref = k;
-    return this->tree_
-        .insert_hint_unique(iterator(hint), key_ref, std::piecewise_construct,
-                            std::forward_as_tuple(std::move(k)),
-                            std::forward_as_tuple(std::forward<Args>(args)...))
-        .first;
+  template <typename K = key_type, typename... Args>
+  iterator try_emplace(const_iterator hint, key_arg<K> &&k, Args &&... args) {
+    return try_emplace_hint_impl(hint, std::forward<K>(k),
+                                 std::forward<Args>(args)...);
   }
-  mapped_type &operator[](const key_type &k) {
+
+  template <typename K = key_type>
+  mapped_type &operator[](const key_arg<K> &k) {
     return try_emplace(k).first->second;
   }
-  mapped_type &operator[](key_type &&k) {
-    return try_emplace(std::move(k)).first->second;
+  template <typename K = key_type>
+  mapped_type &operator[](key_arg<K> &&k) {
+    return try_emplace(std::forward<K>(k)).first->second;
   }
 
   template <typename K = key_type>
@@ -448,6 +492,40 @@
       base_internal::ThrowStdOutOfRange("absl::btree_map::at");
     return it->second;
   }
+
+ private:
+  // Note: when we call `std::forward<M>(obj)` twice, it's safe because
+  // insert_unique/insert_hint_unique are guaranteed to not consume `obj` when
+  // `ret.second` is false.
+  template <class K, class M>
+  std::pair<iterator, bool> insert_or_assign_impl(K &&k, M &&obj) {
+    const std::pair<iterator, bool> ret =
+        this->tree_.insert_unique(k, std::forward<K>(k), std::forward<M>(obj));
+    if (!ret.second) ret.first->second = std::forward<M>(obj);
+    return ret;
+  }
+  template <class K, class M>
+  iterator insert_or_assign_hint_impl(const_iterator hint, K &&k, M &&obj) {
+    const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
+        iterator(hint), k, std::forward<K>(k), std::forward<M>(obj));
+    if (!ret.second) ret.first->second = std::forward<M>(obj);
+    return ret.first;
+  }
+
+  template <class K, class... Args>
+  std::pair<iterator, bool> try_emplace_impl(K &&k, Args &&... args) {
+    return this->tree_.insert_unique(
+        k, std::piecewise_construct, std::forward_as_tuple(std::forward<K>(k)),
+        std::forward_as_tuple(std::forward<Args>(args)...));
+  }
+  template <class K, class... Args>
+  iterator try_emplace_hint_impl(const_iterator hint, K &&k, Args &&... args) {
+    return this->tree_
+        .insert_hint_unique(iterator(hint), k, std::piecewise_construct,
+                            std::forward_as_tuple(std::forward<K>(k)),
+                            std::forward_as_tuple(std::forward<Args>(args)...))
+        .first;
+  }
 };
 
 // A common base class for btree_multiset and btree_multimap.
@@ -475,7 +553,7 @@
   using super_type::super_type;
   btree_multiset_container() {}
 
-  // Range constructor.
+  // Range constructors.
   template <class InputIterator>
   btree_multiset_container(InputIterator b, InputIterator e,
                            const key_compare &comp = key_compare(),
@@ -483,29 +561,30 @@
       : super_type(comp, alloc) {
     insert(b, e);
   }
+  template <class InputIterator>
+  btree_multiset_container(InputIterator b, InputIterator e,
+                           const allocator_type &alloc)
+      : btree_multiset_container(b, e, key_compare(), alloc) {}
 
-  // Initializer list constructor.
+  // Initializer list constructors.
   btree_multiset_container(std::initializer_list<init_type> init,
                            const key_compare &comp = key_compare(),
                            const allocator_type &alloc = allocator_type())
       : btree_multiset_container(init.begin(), init.end(), comp, alloc) {}
-
-  // Lookup routines.
-  template <typename K = key_type>
-  size_type count(const key_arg<K> &key) const {
-    return this->tree_.count_multi(key);
-  }
+  btree_multiset_container(std::initializer_list<init_type> init,
+                           const allocator_type &alloc)
+      : btree_multiset_container(init.begin(), init.end(), alloc) {}
 
   // Insertion routines.
-  iterator insert(const value_type &x) { return this->tree_.insert_multi(x); }
-  iterator insert(value_type &&x) {
-    return this->tree_.insert_multi(std::move(x));
+  iterator insert(const value_type &v) { return this->tree_.insert_multi(v); }
+  iterator insert(value_type &&v) {
+    return this->tree_.insert_multi(std::move(v));
   }
-  iterator insert(const_iterator position, const value_type &x) {
-    return this->tree_.insert_hint_multi(iterator(position), x);
+  iterator insert(const_iterator hint, const value_type &v) {
+    return this->tree_.insert_hint_multi(iterator(hint), v);
   }
-  iterator insert(const_iterator position, value_type &&x) {
-    return this->tree_.insert_hint_multi(iterator(position), std::move(x));
+  iterator insert(const_iterator hint, value_type &&v) {
+    return this->tree_.insert_hint_multi(iterator(hint), std::move(v));
   }
   template <typename InputIterator>
   void insert(InputIterator b, InputIterator e) {
@@ -519,42 +598,34 @@
     return this->tree_.insert_multi(init_type(std::forward<Args>(args)...));
   }
   template <typename... Args>
-  iterator emplace_hint(const_iterator position, Args &&... args) {
+  iterator emplace_hint(const_iterator hint, Args &&... args) {
     return this->tree_.insert_hint_multi(
-        iterator(position), init_type(std::forward<Args>(args)...));
+        iterator(hint), init_type(std::forward<Args>(args)...));
   }
-
- private:
-  template <typename... Args>
-  iterator insert_node_helper(node_type &&node, Args &&... args) {
+  iterator insert(node_type &&node) {
     if (!node) return this->end();
     iterator res =
-        insert(std::forward<Args>(args)...,
-               std::move(params_type::element(CommonAccess::GetSlot(node))));
-    CommonAccess::Reset(&node);
+        this->tree_.insert_multi(params_type::key(CommonAccess::GetSlot(node)),
+                                 CommonAccess::GetSlot(node));
+    CommonAccess::Destroy(&node);
     return res;
   }
-
- public:
-  iterator insert(node_type &&node) {
-    return insert_node_helper(std::move(node));
-  }
   iterator insert(const_iterator hint, node_type &&node) {
-    return insert_node_helper(std::move(node), hint);
+    if (!node) return this->end();
+    iterator res = this->tree_.insert_hint_multi(
+        iterator(hint),
+        std::move(params_type::element(CommonAccess::GetSlot(node))));
+    CommonAccess::Destroy(&node);
+    return res;
   }
 
-  // Deletion routines.
-  template <typename K = key_type>
-  size_type erase(const key_arg<K> &key) {
-    return this->tree_.erase_multi(key);
-  }
-  using super_type::erase;
-
   // Node extraction routines.
   template <typename K = key_type>
   node_type extract(const key_arg<K> &key) {
-    auto it = find(key);
-    return it == this->end() ? node_type() : extract(it);
+    const std::pair<iterator, bool> lower_and_equal =
+        this->tree_.lower_bound_equal(key);
+    return lower_and_equal.second ? extract(lower_and_equal.first)
+                                  : node_type();
   }
   using super_type::extract;
 
@@ -570,8 +641,9 @@
                            typename T::params_type::is_map_container>>::value,
           int> = 0>
   void merge(btree_container<T> &src) {  // NOLINT
-    insert(std::make_move_iterator(src.begin()),
-           std::make_move_iterator(src.end()));
+    for (auto src_it = src.begin(), end = src.end(); src_it != end; ++src_it) {
+      insert(std::move(params_type::element(src_it.slot())));
+    }
     src.clear();
   }
 
@@ -604,6 +676,7 @@
 };
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
diff --git a/absl/container/internal/common.h b/absl/container/internal/common.h
index 591d3ea..030e9d4 100644
--- a/absl/container/internal/common.h
+++ b/absl/container/internal/common.h
@@ -22,6 +22,7 @@
 #include "absl/types/optional.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <class, class = void>
@@ -55,7 +56,7 @@
  public:
   using allocator_type = Alloc;
 
-  constexpr node_handle_base() {}
+  constexpr node_handle_base() = default;
   node_handle_base(node_handle_base&& other) noexcept {
     *this = std::move(other);
   }
@@ -108,16 +109,15 @@
   allocator_type* alloc() { return std::addressof(*alloc_); }
 
  private:
-  absl::optional<allocator_type> alloc_;
-  mutable absl::aligned_storage_t<sizeof(slot_type), alignof(slot_type)>
-      slot_space_;
+  absl::optional<allocator_type> alloc_ = {};
+  alignas(slot_type) mutable unsigned char slot_space_[sizeof(slot_type)] = {};
 };
 
 // For sets.
 template <typename Policy, typename PolicyTraits, typename Alloc,
           typename = void>
 class node_handle : public node_handle_base<PolicyTraits, Alloc> {
-  using Base = typename node_handle::node_handle_base;
+  using Base = node_handle_base<PolicyTraits, Alloc>;
 
  public:
   using value_type = typename PolicyTraits::value_type;
@@ -137,7 +137,8 @@
 class node_handle<Policy, PolicyTraits, Alloc,
                   absl::void_t<typename Policy::mapped_type>>
     : public node_handle_base<PolicyTraits, Alloc> {
-  using Base = typename node_handle::node_handle_base;
+  using Base = node_handle_base<PolicyTraits, Alloc>;
+  using slot_type = typename PolicyTraits::slot_type;
 
  public:
   using key_type = typename Policy::key_type;
@@ -145,8 +146,11 @@
 
   constexpr node_handle() {}
 
-  auto key() const -> decltype(PolicyTraits::key(this->slot())) {
-    return PolicyTraits::key(this->slot());
+  // When C++17 is available, we can use std::launder to provide mutable
+  // access to the key. Otherwise, we provide const access.
+  auto key() const
+      -> decltype(PolicyTraits::mutable_key(std::declval<slot_type*>())) {
+    return PolicyTraits::mutable_key(this->slot());
   }
 
   mapped_type& mapped() const {
@@ -167,6 +171,11 @@
   }
 
   template <typename Node>
+  static void Destroy(Node* node) {
+    node->destroy();
+  }
+
+  template <typename Node>
   static void Reset(Node* node) {
     node->reset();
   }
@@ -191,6 +200,7 @@
 };
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_CONTAINER_H_
diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h
index 7d08e37..5ebe164 100644
--- a/absl/container/internal/compressed_tuple.h
+++ b/absl/container/internal/compressed_tuple.h
@@ -48,6 +48,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <typename... Ts>
@@ -168,9 +169,33 @@
 }
 
 template <typename T, typename V>
-using TupleMoveConstructible = typename std::conditional<
-      std::is_reference<T>::value, std::is_convertible<V, T>,
-      std::is_constructible<T, V&&>>::type;
+using TupleElementMoveConstructible =
+    typename std::conditional<std::is_reference<T>::value,
+                              std::is_convertible<V, T>,
+                              std::is_constructible<T, V&&>>::type;
+
+template <bool SizeMatches, class T, class... Vs>
+struct TupleMoveConstructible : std::false_type {};
+
+template <class... Ts, class... Vs>
+struct TupleMoveConstructible<true, CompressedTuple<Ts...>, Vs...>
+    : std::integral_constant<
+          bool, absl::conjunction<
+                    TupleElementMoveConstructible<Ts, Vs&&>...>::value> {};
+
+template <typename T>
+struct compressed_tuple_size;
+
+template <typename... Es>
+struct compressed_tuple_size<CompressedTuple<Es...>>
+    : public std::integral_constant<std::size_t, sizeof...(Es)> {};
+
+template <class T, class... Vs>
+struct TupleItemsMoveConstructible
+    : std::integral_constant<
+          bool, TupleMoveConstructible<compressed_tuple_size<T>::value ==
+                                           sizeof...(Vs),
+                                       T, Vs...>::value> {};
 
 }  // namespace internal_compressed_tuple
 
@@ -216,22 +241,23 @@
   explicit constexpr CompressedTuple(const Ts&... base)
       : CompressedTuple::CompressedTupleImpl(absl::in_place, base...) {}
 
-  template <typename... Vs,
+  template <typename First, typename... Vs,
             absl::enable_if_t<
                 absl::conjunction<
                     // Ensure we are not hiding default copy/move constructors.
                     absl::negation<std::is_same<void(CompressedTuple),
-                                                void(absl::decay_t<Vs>...)>>,
-                    internal_compressed_tuple::TupleMoveConstructible<
-                        Ts, Vs&&>...>::value,
+                                                void(absl::decay_t<First>)>>,
+                    internal_compressed_tuple::TupleItemsMoveConstructible<
+                        CompressedTuple<Ts...>, First, Vs...>>::value,
                 bool> = true>
-  explicit constexpr CompressedTuple(Vs&&... base)
+  explicit constexpr CompressedTuple(First&& first, Vs&&... base)
       : CompressedTuple::CompressedTupleImpl(absl::in_place,
+                                             absl::forward<First>(first),
                                              absl::forward<Vs>(base)...) {}
 
   template <int I>
   ElemT<I>& get() & {
-    return internal_compressed_tuple::Storage<ElemT<I>, I>::get();
+    return StorageT<I>::get();
   }
 
   template <int I>
@@ -256,6 +282,7 @@
 class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {};
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
diff --git a/absl/container/internal/compressed_tuple_test.cc b/absl/container/internal/compressed_tuple_test.cc
index 19af8f1..62a7483 100644
--- a/absl/container/internal/compressed_tuple_test.cc
+++ b/absl/container/internal/compressed_tuple_test.cc
@@ -48,6 +48,7 @@
 
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
@@ -276,11 +277,11 @@
 
 TEST(CompressedTupleTest, Reference) {
   int i = 7;
-  std::string s = "Very long std::string that goes in the heap";
+  std::string s = "Very long string that goes in the heap";
   CompressedTuple<int, int&, std::string, std::string&> x(i, i, s, s);
 
   // Sanity check. We should have not moved from `s`
-  EXPECT_EQ(s, "Very long std::string that goes in the heap");
+  EXPECT_EQ(s, "Very long string that goes in the heap");
 
   EXPECT_EQ(x.get<0>(), x.get<1>());
   EXPECT_NE(&x.get<0>(), &x.get<1>());
@@ -332,10 +333,6 @@
 
   a = 0.5f;
   EXPECT_EQ(absl::any_cast<float>(x.get<1>()), 0.5);
-
-  // Ensure copy construction work in the face of a type with a universal
-  // implicit constructor;
-  CompressedTuple<absl::any> c{}, d(c);  // NOLINT
 }
 
 TEST(CompressedTupleTest, Constexpr) {
@@ -408,4 +405,5 @@
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h
index e5bb977..e67529e 100644
--- a/absl/container/internal/container_memory.h
+++ b/absl/container/internal/container_memory.h
@@ -15,27 +15,34 @@
 #ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
 #define ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
 
-#ifdef ADDRESS_SANITIZER
-#include <sanitizer/asan_interface.h>
-#endif
-
-#ifdef MEMORY_SANITIZER
-#include <sanitizer/msan_interface.h>
-#endif
-
 #include <cassert>
 #include <cstddef>
 #include <memory>
+#include <new>
 #include <tuple>
 #include <type_traits>
 #include <utility>
 
+#include "absl/base/config.h"
 #include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
 #include "absl/utility/utility.h"
 
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#include <sanitizer/asan_interface.h>
+#endif
+
+#ifdef ABSL_HAVE_MEMORY_SANITIZER
+#include <sanitizer/msan_interface.h>
+#endif
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
+template <size_t Alignment>
+struct alignas(Alignment) AlignedType {};
+
 // Allocates at least n bytes aligned to the specified alignment.
 // Alignment must be a power of 2. It must be positive.
 //
@@ -47,11 +54,14 @@
 void* Allocate(Alloc* alloc, size_t n) {
   static_assert(Alignment > 0, "");
   assert(n && "n must be positive");
-  struct alignas(Alignment) M {};
+  using M = AlignedType<Alignment>;
   using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
   using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
-  A mem_alloc(*alloc);
-  void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
+  // On macOS, "mem_alloc" is a #define with one argument defined in
+  // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
+  // with the "foo(bar)" syntax.
+  A my_mem_alloc(*alloc);
+  void* p = AT::allocate(my_mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
   assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&
          "allocator does not respect alignment");
   return p;
@@ -63,11 +73,14 @@
 void Deallocate(Alloc* alloc, void* p, size_t n) {
   static_assert(Alignment > 0, "");
   assert(n && "n must be positive");
-  struct alignas(Alignment) M {};
+  using M = AlignedType<Alignment>;
   using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
   using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
-  A mem_alloc(*alloc);
-  AT::deallocate(mem_alloc, static_cast<M*>(p),
+  // On macOS, "mem_alloc" is a #define with one argument defined in
+  // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
+  // with the "foo(bar)" syntax.
+  A my_mem_alloc(*alloc);
+  AT::deallocate(my_mem_alloc, static_cast<M*>(p),
                  (n + sizeof(M) - 1) / sizeof(M));
 }
 
@@ -204,10 +217,10 @@
 
 // Helper functions for asan and msan.
 inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) {
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
   ASAN_POISON_MEMORY_REGION(m, s);
 #endif
-#ifdef MEMORY_SANITIZER
+#ifdef ABSL_HAVE_MEMORY_SANITIZER
   __msan_poison(m, s);
 #endif
   (void)m;
@@ -215,10 +228,10 @@
 }
 
 inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) {
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
   ASAN_UNPOISON_MEMORY_REGION(m, s);
 #endif
-#ifdef MEMORY_SANITIZER
+#ifdef ABSL_HAVE_MEMORY_SANITIZER
   __msan_unpoison(m, s);
 #endif
   (void)m;
@@ -245,8 +258,8 @@
 // type, which is non-portable.
 template <class Pair, class = std::true_type>
 struct OffsetOf {
-  static constexpr size_t kFirst = -1;
-  static constexpr size_t kSecond = -1;
+  static constexpr size_t kFirst = static_cast<size_t>(-1);
+  static constexpr size_t kSecond = static_cast<size_t>(-1);
 };
 
 template <class Pair>
@@ -315,11 +328,12 @@
   map_slot_type() {}
   ~map_slot_type() = delete;
   using value_type = std::pair<const K, V>;
-  using mutable_value_type = std::pair<K, V>;
+  using mutable_value_type =
+      std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>;
 
   value_type value;
   mutable_value_type mutable_value;
-  K key;
+  absl::remove_const_t<K> key;
 };
 
 template <class K, class V>
@@ -345,6 +359,20 @@
     return slot->value;
   }
 
+  // When C++17 is available, we can use std::launder to provide mutable
+  // access to the key for use in node handle.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+  static K& mutable_key(slot_type* slot) {
+    // Still check for kMutableKeys so that we can avoid calling std::launder
+    // unless necessary because it can interfere with optimizations.
+    return kMutableKeys::value ? slot->key
+                               : *std::launder(const_cast<K*>(
+                                     std::addressof(slot->value.first)));
+  }
+#else  // !(defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606)
+  static const K& mutable_key(slot_type* slot) { return key(slot); }
+#endif
+
   static const K& key(const slot_type* slot) {
     return kMutableKeys::value ? slot->key : slot->value.first;
   }
@@ -423,16 +451,10 @@
                                                    std::move(src->value));
     }
   }
-
-  template <class Allocator>
-  static void move(Allocator* alloc, slot_type* first, slot_type* last,
-                   slot_type* result) {
-    for (slot_type *src = first, *dest = result; src != last; ++src, ++dest)
-      move(alloc, src, dest);
-  }
 };
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
diff --git a/absl/container/internal/container_memory_test.cc b/absl/container/internal/container_memory_test.cc
index d6b0495..6a7fcd2 100644
--- a/absl/container/internal/container_memory_test.cc
+++ b/absl/container/internal/container_memory_test.cc
@@ -16,16 +16,25 @@
 
 #include <cstdint>
 #include <tuple>
+#include <typeindex>
+#include <typeinfo>
 #include <utility>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/container/internal/test_instance_tracker.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
+using ::absl::test_internal::CopyableMovableInstance;
+using ::absl::test_internal::InstanceTracker;
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::Gt;
 using ::testing::Pair;
 
 TEST(Memory, AlignmentLargerThanBase) {
@@ -44,6 +53,39 @@
   Deallocate<2>(&alloc, mem, 3);
 }
 
+std::map<std::type_index, int>& AllocationMap() {
+  static auto* map = new std::map<std::type_index, int>;
+  return *map;
+}
+
+template <typename T>
+struct TypeCountingAllocator {
+  TypeCountingAllocator() = default;
+  template <typename U>
+  TypeCountingAllocator(const TypeCountingAllocator<U>&) {}  // NOLINT
+
+  using value_type = T;
+
+  T* allocate(size_t n, const void* = nullptr) {
+    AllocationMap()[typeid(T)] += n;
+    return std::allocator<T>().allocate(n);
+  }
+  void deallocate(T* p, std::size_t n) {
+    AllocationMap()[typeid(T)] -= n;
+    return std::allocator<T>().deallocate(p, n);
+  }
+};
+
+TEST(Memory, AllocateDeallocateMatchType) {
+  TypeCountingAllocator<int> alloc;
+  void* mem = Allocate<1>(&alloc, 1);
+  // Verify that it was allocated
+  EXPECT_THAT(AllocationMap(), ElementsAre(Pair(_, Gt(0))));
+  Deallocate<1>(&alloc, mem, 1);
+  // Verify that the deallocation matched.
+  EXPECT_THAT(AllocationMap(), ElementsAre(Pair(_, 0)));
+}
+
 class Fixture : public ::testing::Test {
   using Alloc = std::allocator<std::string>;
 
@@ -183,6 +225,32 @@
                                 std::make_tuple(0.5)));
 }
 
+TEST(MapSlotPolicy, ConstKeyAndValue) {
+  using slot_policy = map_slot_policy<const CopyableMovableInstance,
+                                      const CopyableMovableInstance>;
+  using slot_type = typename slot_policy::slot_type;
+
+  union Slots {
+    Slots() {}
+    ~Slots() {}
+    slot_type slots[100];
+  } slots;
+
+  std::allocator<
+      std::pair<const CopyableMovableInstance, const CopyableMovableInstance>>
+      alloc;
+  InstanceTracker tracker;
+  slot_policy::construct(&alloc, &slots.slots[0], CopyableMovableInstance(1),
+                         CopyableMovableInstance(1));
+  for (int i = 0; i < 99; ++i) {
+    slot_policy::transfer(&alloc, &slots.slots[i + 1], &slots.slots[i]);
+  }
+  slot_policy::destroy(&alloc, &slots.slots[99]);
+
+  EXPECT_EQ(tracker.copies(), 0);
+}
+
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/counting_allocator.h b/absl/container/internal/counting_allocator.h
index 4e717be..927cf08 100644
--- a/absl/container/internal/counting_allocator.h
+++ b/absl/container/internal/counting_allocator.h
@@ -15,11 +15,13 @@
 #ifndef ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
 #define ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
 
-#include <cassert>
 #include <cstdint>
 #include <memory>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 // This is a stateful allocator, but the state lives outside of the
@@ -28,33 +30,63 @@
 // containers - that chain of allocators uses the same state and is
 // thus easier to query for aggregate allocation information.
 template <typename T>
-class CountingAllocator : public std::allocator<T> {
+class CountingAllocator {
  public:
-  using Alloc = std::allocator<T>;
-  using pointer = typename Alloc::pointer;
-  using size_type = typename Alloc::size_type;
+  using Allocator = std::allocator<T>;
+  using AllocatorTraits = std::allocator_traits<Allocator>;
+  using value_type = typename AllocatorTraits::value_type;
+  using pointer = typename AllocatorTraits::pointer;
+  using const_pointer = typename AllocatorTraits::const_pointer;
+  using size_type = typename AllocatorTraits::size_type;
+  using difference_type = typename AllocatorTraits::difference_type;
 
-  CountingAllocator() : bytes_used_(nullptr) {}
-  explicit CountingAllocator(int64_t* b) : bytes_used_(b) {}
+  CountingAllocator() = default;
+  explicit CountingAllocator(int64_t* bytes_used) : bytes_used_(bytes_used) {}
+  CountingAllocator(int64_t* bytes_used, int64_t* instance_count)
+      : bytes_used_(bytes_used), instance_count_(instance_count) {}
 
   template <typename U>
   CountingAllocator(const CountingAllocator<U>& x)
-      : Alloc(x), bytes_used_(x.bytes_used_) {}
+      : bytes_used_(x.bytes_used_), instance_count_(x.instance_count_) {}
 
-  pointer allocate(size_type n,
-                   std::allocator<void>::const_pointer hint = nullptr) {
-    assert(bytes_used_ != nullptr);
-    *bytes_used_ += n * sizeof(T);
-    return Alloc::allocate(n, hint);
+  pointer allocate(
+      size_type n,
+      typename AllocatorTraits::const_void_pointer hint = nullptr) {
+    Allocator allocator;
+    pointer ptr = AllocatorTraits::allocate(allocator, n, hint);
+    if (bytes_used_ != nullptr) {
+      *bytes_used_ += n * sizeof(T);
+    }
+    return ptr;
   }
 
   void deallocate(pointer p, size_type n) {
-    Alloc::deallocate(p, n);
-    assert(bytes_used_ != nullptr);
-    *bytes_used_ -= n * sizeof(T);
+    Allocator allocator;
+    AllocatorTraits::deallocate(allocator, p, n);
+    if (bytes_used_ != nullptr) {
+      *bytes_used_ -= n * sizeof(T);
+    }
   }
 
-  template<typename U>
+  template <typename U, typename... Args>
+  void construct(U* p, Args&&... args) {
+    Allocator allocator;
+    AllocatorTraits::construct(allocator, p, std::forward<Args>(args)...);
+    if (instance_count_ != nullptr) {
+      *instance_count_ += 1;
+    }
+  }
+
+  template <typename U>
+  void destroy(U* p) {
+    Allocator allocator;
+    AllocatorTraits::destroy(allocator, p);
+    if (instance_count_ != nullptr) {
+      *instance_count_ -= 1;
+    }
+  }
+
+  template <typename U>
   class rebind {
    public:
     using other = CountingAllocator<U>;
@@ -62,7 +94,8 @@
 
   friend bool operator==(const CountingAllocator& a,
                          const CountingAllocator& b) {
-    return a.bytes_used_ == b.bytes_used_;
+    return a.bytes_used_ == b.bytes_used_ &&
+           a.instance_count_ == b.instance_count_;
   }
 
   friend bool operator!=(const CountingAllocator& a,
@@ -70,10 +103,12 @@
     return !(a == b);
   }
 
-  int64_t* bytes_used_;
+  int64_t* bytes_used_ = nullptr;
+  int64_t* instance_count_ = nullptr;
 };
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
diff --git a/absl/container/internal/hash_function_defaults.h b/absl/container/internal/hash_function_defaults.h
index cb8f03c..0683422 100644
--- a/absl/container/internal/hash_function_defaults.h
+++ b/absl/container/internal/hash_function_defaults.h
@@ -53,9 +53,11 @@
 
 #include "absl/base/config.h"
 #include "absl/hash/hash.h"
+#include "absl/strings/cord.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 // The hash of an object of type T is computed by using absl::Hash.
@@ -71,6 +73,9 @@
   size_t operator()(absl::string_view v) const {
     return absl::Hash<absl::string_view>{}(v);
   }
+  size_t operator()(const absl::Cord& v) const {
+    return absl::Hash<absl::Cord>{}(v);
+  }
 };
 
 // Supports heterogeneous lookup for string-like elements.
@@ -81,6 +86,15 @@
     bool operator()(absl::string_view lhs, absl::string_view rhs) const {
       return lhs == rhs;
     }
+    bool operator()(const absl::Cord& lhs, const absl::Cord& rhs) const {
+      return lhs == rhs;
+    }
+    bool operator()(const absl::Cord& lhs, absl::string_view rhs) const {
+      return lhs == rhs;
+    }
+    bool operator()(absl::string_view lhs, const absl::Cord& rhs) const {
+      return lhs == rhs;
+    }
   };
 };
 
@@ -88,6 +102,8 @@
 struct HashEq<std::string> : StringHashEq {};
 template <>
 struct HashEq<absl::string_view> : StringHashEq {};
+template <>
+struct HashEq<absl::Cord> : StringHashEq {};
 
 // Supports heterogeneous lookup for pointers and smart pointers.
 template <class T>
@@ -139,6 +155,7 @@
 using hash_default_eq = typename container_internal::HashEq<T>::Eq;
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_
diff --git a/absl/container/internal/hash_function_defaults_test.cc b/absl/container/internal/hash_function_defaults_test.cc
index 82708db..59576b8 100644
--- a/absl/container/internal/hash_function_defaults_test.cc
+++ b/absl/container/internal/hash_function_defaults_test.cc
@@ -19,9 +19,13 @@
 #include <utility>
 
 #include "gtest/gtest.h"
+#include "absl/random/random.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/cord_test_helpers.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
@@ -202,10 +206,91 @@
   EXPECT_NE(hash(&dummy), hash(cuptr));
 }
 
+TEST(EqCord, Works) {
+  hash_default_eq<absl::Cord> eq;
+  const absl::string_view a_string_view = "a";
+  const absl::Cord a_cord(a_string_view);
+  const absl::string_view b_string_view = "b";
+  const absl::Cord b_cord(b_string_view);
+
+  EXPECT_TRUE(eq(a_cord, a_cord));
+  EXPECT_TRUE(eq(a_cord, a_string_view));
+  EXPECT_TRUE(eq(a_string_view, a_cord));
+  EXPECT_FALSE(eq(a_cord, b_cord));
+  EXPECT_FALSE(eq(a_cord, b_string_view));
+  EXPECT_FALSE(eq(b_string_view, a_cord));
+}
+
+TEST(HashCord, Works) {
+  hash_default_hash<absl::Cord> hash;
+  const absl::string_view a_string_view = "a";
+  const absl::Cord a_cord(a_string_view);
+  const absl::string_view b_string_view = "b";
+  const absl::Cord b_cord(b_string_view);
+
+  EXPECT_EQ(hash(a_cord), hash(a_cord));
+  EXPECT_EQ(hash(b_cord), hash(b_cord));
+  EXPECT_EQ(hash(a_string_view), hash(a_cord));
+  EXPECT_EQ(hash(b_string_view), hash(b_cord));
+  EXPECT_EQ(hash(absl::Cord("")), hash(""));
+  EXPECT_EQ(hash(absl::Cord()), hash(absl::string_view()));
+
+  EXPECT_NE(hash(a_cord), hash(b_cord));
+  EXPECT_NE(hash(a_cord), hash(b_string_view));
+  EXPECT_NE(hash(a_string_view), hash(b_cord));
+  EXPECT_NE(hash(a_string_view), hash(b_string_view));
+}
+
+void NoOpReleaser(absl::string_view data, void* arg) {}
+
+TEST(HashCord, FragmentedCordWorks) {
+  hash_default_hash<absl::Cord> hash;
+  absl::Cord c = absl::MakeFragmentedCord({"a", "b", "c"});
+  EXPECT_FALSE(c.TryFlat().has_value());
+  EXPECT_EQ(hash(c), hash("abc"));
+}
+
+TEST(HashCord, FragmentedLongCordWorks) {
+  hash_default_hash<absl::Cord> hash;
+  // Crete some large strings which do not fit on the stack.
+  std::string a(65536, 'a');
+  std::string b(65536, 'b');
+  absl::Cord c = absl::MakeFragmentedCord({a, b});
+  EXPECT_FALSE(c.TryFlat().has_value());
+  EXPECT_EQ(hash(c), hash(a + b));
+}
+
+TEST(HashCord, RandomCord) {
+  hash_default_hash<absl::Cord> hash;
+  auto bitgen = absl::BitGen();
+  for (int i = 0; i < 1000; ++i) {
+    const int number_of_segments = absl::Uniform(bitgen, 0, 10);
+    std::vector<std::string> pieces;
+    for (size_t s = 0; s < number_of_segments; ++s) {
+      std::string str;
+      str.resize(absl::Uniform(bitgen, 0, 4096));
+      // MSVC needed the explicit return type in the lambda.
+      std::generate(str.begin(), str.end(), [&]() -> char {
+        return static_cast<char>(absl::Uniform<unsigned char>(bitgen));
+      });
+      pieces.push_back(str);
+    }
+    absl::Cord c = absl::MakeFragmentedCord(pieces);
+    EXPECT_EQ(hash(c), hash(std::string(c)));
+  }
+}
+
 // Cartesian product of (std::string, absl::string_view)
-// with (std::string, absl::string_view, const char*).
+// with (std::string, absl::string_view, const char*, absl::Cord).
 using StringTypesCartesianProduct = Types<
     // clang-format off
+    std::pair<absl::Cord, std::string>,
+    std::pair<absl::Cord, absl::string_view>,
+    std::pair<absl::Cord, absl::Cord>,
+    std::pair<absl::Cord, const char*>,
+
+    std::pair<std::string, absl::Cord>,
+    std::pair<absl::string_view, absl::Cord>,
 
     std::pair<absl::string_view, std::string>,
     std::pair<absl::string_view, absl::string_view>,
@@ -248,14 +333,15 @@
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 enum Hash : size_t {
-  kStd = 0x2,       // std::hash
+  kStd = 0x1,       // std::hash
 #ifdef _MSC_VER
   kExtension = kStd,  // In MSVC, std::hash == ::hash
 #else                 // _MSC_VER
-  kExtension = 0x4,  // ::hash (GCC extension)
+  kExtension = 0x2,  // ::hash (GCC extension)
 #endif                // _MSC_VER
 };
 
@@ -278,6 +364,7 @@
 }  // namespace std
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
@@ -292,4 +379,5 @@
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/hash_generator_testing.cc b/absl/container/internal/hash_generator_testing.cc
index 37a23d6..59cc5aa 100644
--- a/absl/container/internal/hash_generator_testing.cc
+++ b/absl/container/internal/hash_generator_testing.cc
@@ -17,6 +17,7 @@
 #include <deque>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace hash_internal {
 namespace {
@@ -40,8 +41,10 @@
 }  // namespace
 
 std::mt19937_64* GetSharedRng() {
-  RandomDeviceSeedSeq seed_seq;
-  static auto* rng = new std::mt19937_64(seed_seq);
+  static auto* rng = [] {
+    RandomDeviceSeedSeq seed_seq;
+    return new std::mt19937_64(seed_seq);
+  }();
   return rng;
 }
 
@@ -69,4 +72,5 @@
 
 }  // namespace hash_internal
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/hash_generator_testing.h b/absl/container/internal/hash_generator_testing.h
index 477215c..6869fe4 100644
--- a/absl/container/internal/hash_generator_testing.h
+++ b/absl/container/internal/hash_generator_testing.h
@@ -33,6 +33,7 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace hash_internal {
 namespace generator_internal {
@@ -154,6 +155,7 @@
 
 }  // namespace hash_internal
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_
diff --git a/absl/container/internal/hash_policy_testing.h b/absl/container/internal/hash_policy_testing.h
index c57407a..01c40d2 100644
--- a/absl/container/internal/hash_policy_testing.h
+++ b/absl/container/internal/hash_policy_testing.h
@@ -30,6 +30,7 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace hash_testing_internal {
 
@@ -162,6 +163,7 @@
 }
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 // ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS is false for glibcxx versions
diff --git a/absl/container/internal/hash_policy_testing_test.cc b/absl/container/internal/hash_policy_testing_test.cc
index 0c95eb5..f0b20fe 100644
--- a/absl/container/internal/hash_policy_testing_test.cc
+++ b/absl/container/internal/hash_policy_testing_test.cc
@@ -17,6 +17,7 @@
 #include "gtest/gtest.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
@@ -40,4 +41,5 @@
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/hash_policy_traits.h b/absl/container/internal/hash_policy_traits.h
index fd007de..46c97b1 100644
--- a/absl/container/internal/hash_policy_traits.h
+++ b/absl/container/internal/hash_policy_traits.h
@@ -17,26 +17,47 @@
 
 #include <cstddef>
 #include <memory>
+#include <new>
 #include <type_traits>
 #include <utility>
 
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 // Defines how slots are initialized/destroyed/moved.
 template <class Policy, class = void>
 struct hash_policy_traits {
+  // The type of the keys stored in the hashtable.
+  using key_type = typename Policy::key_type;
+
  private:
   struct ReturnKey {
-    // We return `Key` here.
+    // When C++17 is available, we can use std::launder to provide mutable
+    // access to the key for use in node handle.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+    template <class Key,
+              absl::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0>
+    static key_type& Impl(Key&& k, int) {
+      return *std::launder(
+          const_cast<key_type*>(std::addressof(std::forward<Key>(k))));
+    }
+#endif
+
+    template <class Key>
+    static Key Impl(Key&& k, char) {
+      return std::forward<Key>(k);
+    }
+
     // When Key=T&, we forward the lvalue reference.
     // When Key=T, we return by value to avoid a dangling reference.
     // eg, for string_hash_map.
     template <class Key, class... Args>
-    Key operator()(Key&& k, const Args&...) const {
-      return std::forward<Key>(k);
+    auto operator()(Key&& k, const Args&...) const
+        -> decltype(Impl(std::forward<Key>(k), 0)) {
+      return Impl(std::forward<Key>(k), 0);
     }
   };
 
@@ -51,9 +72,6 @@
   // The actual object stored in the hash table.
   using slot_type = typename Policy::slot_type;
 
-  // The type of the keys stored in the hashtable.
-  using key_type = typename Policy::key_type;
-
   // The argument type for insertions into the hashtable. This is different
   // from value_type for increased performance. See initializer_list constructor
   // and insert() member functions for more details.
@@ -155,7 +173,7 @@
   // Returns the "key" portion of the slot.
   // Used for node handle manipulation.
   template <class P = Policy>
-  static auto key(slot_type* slot)
+  static auto mutable_key(slot_type* slot)
       -> decltype(P::apply(ReturnKey(), element(slot))) {
     return P::apply(ReturnKey(), element(slot));
   }
@@ -184,6 +202,7 @@
 };
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_HASH_POLICY_TRAITS_H_
diff --git a/absl/container/internal/hash_policy_traits_test.cc b/absl/container/internal/hash_policy_traits_test.cc
index e643d18..6ef8b9e 100644
--- a/absl/container/internal/hash_policy_traits_test.cc
+++ b/absl/container/internal/hash_policy_traits_test.cc
@@ -22,6 +22,7 @@
 #include "gtest/gtest.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
@@ -139,4 +140,5 @@
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/hashtable_debug.h b/absl/container/internal/hashtable_debug.h
index 7193000..19d5212 100644
--- a/absl/container/internal/hashtable_debug.h
+++ b/absl/container/internal/hashtable_debug.h
@@ -38,6 +38,7 @@
 #include "absl/container/internal/hashtable_debug_hooks.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 // Returns the number of probes required to lookup `key`.  Returns 0 for a
@@ -103,6 +104,7 @@
 }
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
diff --git a/absl/container/internal/hashtable_debug_hooks.h b/absl/container/internal/hashtable_debug_hooks.h
index 371ce81..3e9ea59 100644
--- a/absl/container/internal/hashtable_debug_hooks.h
+++ b/absl/container/internal/hashtable_debug_hooks.h
@@ -23,7 +23,10 @@
 #include <type_traits>
 #include <vector>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace hashtable_debug_internal {
 
@@ -76,6 +79,7 @@
 
 }  // namespace hashtable_debug_internal
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_HOOKS_H_
diff --git a/absl/container/internal/hashtablez_sampler.cc b/absl/container/internal/hashtablez_sampler.cc
index d03dd82..e4484fb 100644
--- a/absl/container/internal/hashtablez_sampler.cc
+++ b/absl/container/internal/hashtablez_sampler.cc
@@ -21,12 +21,14 @@
 #include <limits>
 
 #include "absl/base/attributes.h"
+#include "absl/base/internal/exponential_biased.h"
 #include "absl/container/internal/have_sse.h"
 #include "absl/debugging/stacktrace.h"
 #include "absl/memory/memory.h"
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 constexpr int HashtablezInfo::kMaxStackDepth;
 
@@ -37,80 +39,17 @@
 ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_sample_parameter{1 << 10};
 ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_max_samples{1 << 20};
 
-// Returns the next pseudo-random value.
-// pRNG is: aX+b mod c with a = 0x5DEECE66D, b =  0xB, c = 1<<48
-// This is the lrand64 generator.
-uint64_t NextRandom(uint64_t rnd) {
-  const uint64_t prng_mult = uint64_t{0x5DEECE66D};
-  const uint64_t prng_add = 0xB;
-  const uint64_t prng_mod_power = 48;
-  const uint64_t prng_mod_mask = ~(~uint64_t{0} << prng_mod_power);
-  return (prng_mult * rnd + prng_add) & prng_mod_mask;
-}
-
-// Generates a geometric variable with the specified mean.
-// This is done by generating a random number between 0 and 1 and applying
-// the inverse cumulative distribution function for an exponential.
-// Specifically: Let m be the inverse of the sample period, then
-// the probability distribution function is m*exp(-mx) so the CDF is
-// p = 1 - exp(-mx), so
-// q = 1 - p = exp(-mx)
-// log_e(q) = -mx
-// -log_e(q)/m = x
-// log_2(q) * (-log_e(2) * 1/m) = x
-// In the code, q is actually in the range 1 to 2**26, hence the -26 below
-//
-int64_t GetGeometricVariable(int64_t mean) {
-#if ABSL_HAVE_THREAD_LOCAL
-  thread_local
-#else   // ABSL_HAVE_THREAD_LOCAL
-  // SampleSlow and hence GetGeometricVariable is guarded by a single mutex when
-  // there are not thread locals.  Thus, a single global rng is acceptable for
-  // that case.
-  static
-#endif  // ABSL_HAVE_THREAD_LOCAL
-      uint64_t rng = []() {
-        // We don't get well distributed numbers from this so we call
-        // NextRandom() a bunch to mush the bits around.  We use a global_rand
-        // to handle the case where the same thread (by memory address) gets
-        // created and destroyed repeatedly.
-        ABSL_CONST_INIT static std::atomic<uint32_t> global_rand(0);
-        uint64_t r = reinterpret_cast<uint64_t>(&rng) +
-                   global_rand.fetch_add(1, std::memory_order_relaxed);
-        for (int i = 0; i < 20; ++i) {
-          r = NextRandom(r);
-        }
-        return r;
-      }();
-
-  rng = NextRandom(rng);
-
-  // Take the top 26 bits as the random number
-  // (This plus the 1<<58 sampling bound give a max possible step of
-  // 5194297183973780480 bytes.)
-  const uint64_t prng_mod_power = 48;  // Number of bits in prng
-  // The uint32_t cast is to prevent a (hard-to-reproduce) NAN
-  // under piii debug for some binaries.
-  double q = static_cast<uint32_t>(rng >> (prng_mod_power - 26)) + 1.0;
-  // Put the computed p-value through the CDF of a geometric.
-  double interval = (log2(q) - 26) * (-std::log(2.0) * mean);
-
-  // Very large values of interval overflow int64_t. If we happen to
-  // hit such improbable condition, we simply cheat and clamp interval
-  // to largest supported value.
-  if (interval > static_cast<double>(std::numeric_limits<int64_t>::max() / 2)) {
-    return std::numeric_limits<int64_t>::max() / 2;
-  }
-
-  // Small values of interval are equivalent to just sampling next time.
-  if (interval < 1) {
-    return 1;
-  }
-  return static_cast<int64_t>(interval);
-}
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+ABSL_PER_THREAD_TLS_KEYWORD absl::base_internal::ExponentialBiased
+    g_exponential_biased_generator;
+#endif
 
 }  // namespace
 
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample = 0;
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+
 HashtablezSampler& HashtablezSampler::Global() {
   static auto* sampler = new HashtablezSampler();
   return *sampler;
@@ -128,6 +67,7 @@
   capacity.store(0, std::memory_order_relaxed);
   size.store(0, std::memory_order_relaxed);
   num_erases.store(0, std::memory_order_relaxed);
+  num_rehashes.store(0, std::memory_order_relaxed);
   max_probe_length.store(0, std::memory_order_relaxed);
   total_probe_length.store(0, std::memory_order_relaxed);
   hashes_bitwise_or.store(0, std::memory_order_relaxed);
@@ -228,15 +168,39 @@
   return dropped_samples_.load(std::memory_order_relaxed);
 }
 
+static bool ShouldForceSampling() {
+  enum ForceState {
+    kDontForce,
+    kForce,
+    kUninitialized
+  };
+  ABSL_CONST_INIT static std::atomic<ForceState> global_state{
+      kUninitialized};
+  ForceState state = global_state.load(std::memory_order_relaxed);
+  if (ABSL_PREDICT_TRUE(state == kDontForce)) return false;
+
+  if (state == kUninitialized) {
+    state = AbslContainerInternalSampleEverything() ? kForce : kDontForce;
+    global_state.store(state, std::memory_order_relaxed);
+  }
+  return state == kForce;
+}
+
 HashtablezInfo* SampleSlow(int64_t* next_sample) {
-  if (kAbslContainerInternalSampleEverything) {
+  if (ABSL_PREDICT_FALSE(ShouldForceSampling())) {
     *next_sample = 1;
     return HashtablezSampler::Global().Register();
   }
 
+#if !defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+  *next_sample = std::numeric_limits<int64_t>::max();
+  return nullptr;
+#else
   bool first = *next_sample < 0;
-  *next_sample = GetGeometricVariable(
+  *next_sample = g_exponential_biased_generator.GetStride(
       g_hashtablez_sample_parameter.load(std::memory_order_relaxed));
+  // Small values of interval are equivalent to just sampling next time.
+  ABSL_ASSERT(*next_sample >= 1);
 
   // g_hashtablez_enabled can be dynamically flipped, we need to set a threshold
   // low enough that we will start sampling in a reasonable time, so we just use
@@ -251,12 +215,9 @@
   }
 
   return HashtablezSampler::Global().Register();
+#endif
 }
 
-#if ABSL_PER_THREAD_TLS == 1
-ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample = 0;
-#endif  // ABSL_PER_THREAD_TLS == 1
-
 void UnsampleSlow(HashtablezInfo* info) {
   HashtablezSampler::Global().Unregister(info);
 }
@@ -266,7 +227,7 @@
   // SwissTables probe in groups of 16, so scale this to count items probes and
   // not offset from desired.
   size_t probe_length = distance_from_desired;
-#if SWISSTABLE_HAVE_SSE2
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
   probe_length /= 16;
 #else
   probe_length /= 8;
@@ -305,4 +266,5 @@
 }
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h
index 4112175..394348d 100644
--- a/absl/container/internal/hashtablez_sampler.h
+++ b/absl/container/internal/hashtablez_sampler.h
@@ -51,6 +51,7 @@
 #include "absl/utility/utility.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 // Stores information about a sampled hashtable.  All mutations to this *must*
@@ -72,6 +73,7 @@
   std::atomic<size_t> capacity;
   std::atomic<size_t> size;
   std::atomic<size_t> num_erases;
+  std::atomic<size_t> num_rehashes;
   std::atomic<size_t> max_probe_length;
   std::atomic<size_t> total_probe_length;
   std::atomic<size_t> hashes_bitwise_or;
@@ -97,13 +99,18 @@
 };
 
 inline void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length) {
-#if SWISSTABLE_HAVE_SSE2
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
   total_probe_length /= 16;
 #else
   total_probe_length /= 8;
 #endif
   info->total_probe_length.store(total_probe_length, std::memory_order_relaxed);
   info->num_erases.store(0, std::memory_order_relaxed);
+  // There is only one concurrent writer, so `load` then `store` is sufficient
+  // instead of using `fetch_add`.
+  info->num_rehashes.store(
+      1 + info->num_rehashes.load(std::memory_order_relaxed),
+      std::memory_order_relaxed);
 }
 
 inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
@@ -112,7 +119,8 @@
   info->capacity.store(capacity, std::memory_order_relaxed);
   if (size == 0) {
     // This is a clear, reset the total/num_erases too.
-    RecordRehashSlow(info, 0);
+    info->total_probe_length.store(0, std::memory_order_relaxed);
+    info->num_erases.store(0, std::memory_order_relaxed);
   }
 }
 
@@ -121,12 +129,21 @@
 
 inline void RecordEraseSlow(HashtablezInfo* info) {
   info->size.fetch_sub(1, std::memory_order_relaxed);
-  info->num_erases.fetch_add(1, std::memory_order_relaxed);
+  // There is only one concurrent writer, so `load` then `store` is sufficient
+  // instead of using `fetch_add`.
+  info->num_erases.store(
+      1 + info->num_erases.load(std::memory_order_relaxed),
+      std::memory_order_relaxed);
 }
 
 HashtablezInfo* SampleSlow(int64_t* next_sample);
 void UnsampleSlow(HashtablezInfo* info);
 
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+#error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 class HashtablezInfoHandle {
  public:
   explicit HashtablezInfoHandle() : info_(nullptr) {}
@@ -178,24 +195,39 @@
   friend class HashtablezInfoHandlePeer;
   HashtablezInfo* info_;
 };
+#else
+// Ensure that when Hashtablez is turned off at compile time, HashtablezInfo can
+// be removed by the linker, in order to reduce the binary size.
+class HashtablezInfoHandle {
+ public:
+  explicit HashtablezInfoHandle() = default;
+  explicit HashtablezInfoHandle(std::nullptr_t) {}
 
-#if ABSL_PER_THREAD_TLS == 1
+  inline void RecordStorageChanged(size_t /*size*/, size_t /*capacity*/) {}
+  inline void RecordRehash(size_t /*total_probe_length*/) {}
+  inline void RecordInsert(size_t /*hash*/, size_t /*distance_from_desired*/) {}
+  inline void RecordErase() {}
+
+  friend inline void swap(HashtablezInfoHandle& /*lhs*/,
+                          HashtablezInfoHandle& /*rhs*/) {}
+};
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 extern ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample;
-#endif  // ABSL_PER_THREAD_TLS
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 
 // Returns an RAII sampling handle that manages registration and unregistation
 // with the global sampler.
 inline HashtablezInfoHandle Sample() {
-#if ABSL_PER_THREAD_TLS == 0
-  static auto* mu = new absl::Mutex;
-  static int64_t global_next_sample = 0;
-  absl::MutexLock l(mu);
-#endif  // !ABSL_HAVE_THREAD_LOCAL
-
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
   if (ABSL_PREDICT_TRUE(--global_next_sample > 0)) {
     return HashtablezInfoHandle(nullptr);
   }
   return HashtablezInfoHandle(SampleSlow(&global_next_sample));
+#else
+  return HashtablezInfoHandle(nullptr);
+#endif  // !ABSL_PER_THREAD_TLS
 }
 
 // Holds samples and their associated stack traces with a soft limit of
@@ -280,9 +312,10 @@
 // initialization of static storage duration objects.
 // The definition of this constant is weak, which allows us to inject a
 // different value for it at link time.
-extern "C" const bool kAbslContainerInternalSampleEverything;
+extern "C" bool AbslContainerInternalSampleEverything();
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
diff --git a/absl/container/internal/hashtablez_sampler_force_weak_definition.cc b/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
index 4ca6ffd..78b9d36 100644
--- a/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
+++ b/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
@@ -17,11 +17,14 @@
 #include "absl/base/attributes.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 // See hashtablez_sampler.h for details.
-extern "C" ABSL_ATTRIBUTE_WEAK const bool
-    kAbslContainerInternalSampleEverything = false;
+extern "C" ABSL_ATTRIBUTE_WEAK bool AbslContainerInternalSampleEverything() {
+  return false;
+}
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc
index 7f9e8dd..8d10a1e 100644
--- a/absl/container/internal/hashtablez_sampler_test.cc
+++ b/absl/container/internal/hashtablez_sampler_test.cc
@@ -29,14 +29,16 @@
 #include "absl/time/clock.h"
 #include "absl/time/time.h"
 
-#if SWISSTABLE_HAVE_SSE2
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
 constexpr int kProbeLength = 16;
 #else
 constexpr int kProbeLength = 8;
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 class HashtablezInfoHandlePeer {
  public:
   static bool IsSampled(const HashtablezInfoHandle& h) {
@@ -45,6 +47,13 @@
 
   static HashtablezInfo* GetInfo(HashtablezInfoHandle* h) { return h->info_; }
 };
+#else
+class HashtablezInfoHandlePeer {
+ public:
+  static bool IsSampled(const HashtablezInfoHandle&) { return false; }
+  static HashtablezInfo* GetInfo(HashtablezInfoHandle*) { return nullptr; }
+};
+#endif  // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 
 namespace {
 using ::absl::synchronization_internal::ThreadPool;
@@ -75,6 +84,7 @@
   EXPECT_EQ(info.capacity.load(), 0);
   EXPECT_EQ(info.size.load(), 0);
   EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.num_rehashes.load(), 0);
   EXPECT_EQ(info.max_probe_length.load(), 0);
   EXPECT_EQ(info.total_probe_length.load(), 0);
   EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
@@ -94,6 +104,7 @@
   EXPECT_EQ(info.capacity.load(), 0);
   EXPECT_EQ(info.size.load(), 0);
   EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.num_rehashes.load(), 0);
   EXPECT_EQ(info.max_probe_length.load(), 0);
   EXPECT_EQ(info.total_probe_length.load(), 0);
   EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
@@ -166,8 +177,10 @@
   EXPECT_EQ(info.size.load(), 2);
   EXPECT_EQ(info.total_probe_length.load(), 3);
   EXPECT_EQ(info.num_erases.load(), 0);
+  EXPECT_EQ(info.num_rehashes.load(), 1);
 }
 
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 TEST(HashtablezSamplerTest, SmallSampleParameter) {
   SetHashtablezEnabled(true);
   SetHashtablezSampleParameter(100);
@@ -240,6 +253,8 @@
   });
   EXPECT_FALSE(found);
 }
+#endif
+
 
 TEST(HashtablezSamplerTest, Registration) {
   HashtablezSampler sampler;
@@ -352,4 +367,5 @@
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/have_sse.h b/absl/container/internal/have_sse.h
index 4341441..e75e1a1 100644
--- a/absl/container/internal/have_sse.h
+++ b/absl/container/internal/have_sse.h
@@ -16,33 +16,34 @@
 #ifndef ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
 #define ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
 
-#ifndef SWISSTABLE_HAVE_SSE2
+#ifndef ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
 #if defined(__SSE2__) ||  \
     (defined(_MSC_VER) && \
      (defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2)))
-#define SWISSTABLE_HAVE_SSE2 1
+#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 1
 #else
-#define SWISSTABLE_HAVE_SSE2 0
+#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 0
 #endif
 #endif
 
-#ifndef SWISSTABLE_HAVE_SSSE3
+#ifndef ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
 #ifdef __SSSE3__
-#define SWISSTABLE_HAVE_SSSE3 1
+#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 1
 #else
-#define SWISSTABLE_HAVE_SSSE3 0
+#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 0
 #endif
 #endif
 
-#if SWISSTABLE_HAVE_SSSE3 && !SWISSTABLE_HAVE_SSE2
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 && \
+    !ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
 #error "Bad configuration!"
 #endif
 
-#if SWISSTABLE_HAVE_SSE2
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
 #include <emmintrin.h>
 #endif
 
-#if SWISSTABLE_HAVE_SSSE3
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
 #include <tmmintrin.h>
 #endif
 
diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h
index 54369c8..120849c 100644
--- a/absl/container/internal/inlined_vector.h
+++ b/absl/container/internal/inlined_vector.h
@@ -30,23 +30,31 @@
 #include "absl/types/span.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace inlined_vector_internal {
 
+// GCC does not deal very well with the below code
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+
 template <typename Iterator>
 using IsAtLeastForwardIterator = std::is_convertible<
     typename std::iterator_traits<Iterator>::iterator_category,
     std::forward_iterator_tag>;
 
-template <typename AllocatorType>
-using IsMemcpyOk = absl::conjunction<
-    std::is_same<std::allocator<typename AllocatorType::value_type>,
-                 AllocatorType>,
-    absl::is_trivially_copy_constructible<typename AllocatorType::value_type>,
-    absl::is_trivially_copy_assignable<typename AllocatorType::value_type>,
-    absl::is_trivially_destructible<typename AllocatorType::value_type>>;
+template <typename AllocatorType,
+          typename ValueType =
+              typename absl::allocator_traits<AllocatorType>::value_type>
+using IsMemcpyOk =
+    absl::conjunction<std::is_same<AllocatorType, std::allocator<ValueType>>,
+                      absl::is_trivially_copy_constructible<ValueType>,
+                      absl::is_trivially_copy_assignable<ValueType>,
+                      absl::is_trivially_destructible<ValueType>>;
 
-template <typename AllocatorType, typename ValueType, typename SizeType>
-void DestroyElements(AllocatorType* alloc_ptr, ValueType* destroy_first,
+template <typename AllocatorType, typename Pointer, typename SizeType>
+void DestroyElements(AllocatorType* alloc_ptr, Pointer destroy_first,
                      SizeType destroy_size) {
   using AllocatorTraits = absl::allocator_traits<AllocatorType>;
 
@@ -57,20 +65,25 @@
     }
 
 #if !defined(NDEBUG)
-    // Overwrite unused memory with `0xab` so we can catch uninitialized usage.
-    //
-    // Cast to `void*` to tell the compiler that we don't care that we might be
-    // scribbling on a vtable pointer.
-    auto* memory_ptr = static_cast<void*>(destroy_first);
-    auto memory_size = sizeof(ValueType) * destroy_size;
-    std::memset(memory_ptr, 0xab, memory_size);
+    {
+      using ValueType = typename AllocatorTraits::value_type;
+
+      // Overwrite unused memory with `0xab` so we can catch uninitialized
+      // usage.
+      //
+      // Cast to `void*` to tell the compiler that we don't care that we might
+      // be scribbling on a vtable pointer.
+      void* memory_ptr = destroy_first;
+      auto memory_size = destroy_size * sizeof(ValueType);
+      std::memset(memory_ptr, 0xab, memory_size);
+    }
 #endif  // !defined(NDEBUG)
   }
 }
 
-template <typename AllocatorType, typename ValueType, typename ValueAdapter,
+template <typename AllocatorType, typename Pointer, typename ValueAdapter,
           typename SizeType>
-void ConstructElements(AllocatorType* alloc_ptr, ValueType* construct_first,
+void ConstructElements(AllocatorType* alloc_ptr, Pointer construct_first,
                        ValueAdapter* values_ptr, SizeType construct_size) {
   for (SizeType i = 0; i < construct_size; ++i) {
     ABSL_INTERNAL_TRY {
@@ -83,8 +96,8 @@
   }
 }
 
-template <typename ValueType, typename ValueAdapter, typename SizeType>
-void AssignElements(ValueType* assign_first, ValueAdapter* values_ptr,
+template <typename Pointer, typename ValueAdapter, typename SizeType>
+void AssignElements(Pointer assign_first, ValueAdapter* values_ptr,
                     SizeType assign_size) {
   for (SizeType i = 0; i < assign_size; ++i) {
     values_ptr->AssignNext(assign_first + i);
@@ -93,28 +106,29 @@
 
 template <typename AllocatorType>
 struct StorageView {
-  using pointer = typename AllocatorType::pointer;
-  using size_type = typename AllocatorType::size_type;
+  using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+  using Pointer = typename AllocatorTraits::pointer;
+  using SizeType = typename AllocatorTraits::size_type;
 
-  pointer data;
-  size_type size;
-  size_type capacity;
+  Pointer data;
+  SizeType size;
+  SizeType capacity;
 };
 
 template <typename AllocatorType, typename Iterator>
 class IteratorValueAdapter {
-  using pointer = typename AllocatorType::pointer;
   using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+  using Pointer = typename AllocatorTraits::pointer;
 
  public:
   explicit IteratorValueAdapter(const Iterator& it) : it_(it) {}
 
-  void ConstructNext(AllocatorType* alloc_ptr, pointer construct_at) {
+  void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) {
     AllocatorTraits::construct(*alloc_ptr, construct_at, *it_);
     ++it_;
   }
 
-  void AssignNext(pointer assign_at) {
+  void AssignNext(Pointer assign_at) {
     *assign_at = *it_;
     ++it_;
   }
@@ -125,46 +139,45 @@
 
 template <typename AllocatorType>
 class CopyValueAdapter {
-  using pointer = typename AllocatorType::pointer;
-  using const_pointer = typename AllocatorType::const_pointer;
-  using const_reference = typename AllocatorType::const_reference;
   using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+  using ValueType = typename AllocatorTraits::value_type;
+  using Pointer = typename AllocatorTraits::pointer;
+  using ConstPointer = typename AllocatorTraits::const_pointer;
 
  public:
-  explicit CopyValueAdapter(const_reference v) : ptr_(std::addressof(v)) {}
+  explicit CopyValueAdapter(const ValueType& v) : ptr_(std::addressof(v)) {}
 
-  void ConstructNext(AllocatorType* alloc_ptr, pointer construct_at) {
+  void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) {
     AllocatorTraits::construct(*alloc_ptr, construct_at, *ptr_);
   }
 
-  void AssignNext(pointer assign_at) { *assign_at = *ptr_; }
+  void AssignNext(Pointer assign_at) { *assign_at = *ptr_; }
 
  private:
-  const_pointer ptr_;
+  ConstPointer ptr_;
 };
 
 template <typename AllocatorType>
 class DefaultValueAdapter {
-  using pointer = typename AllocatorType::pointer;
-  using value_type = typename AllocatorType::value_type;
   using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+  using ValueType = typename AllocatorTraits::value_type;
+  using Pointer = typename AllocatorTraits::pointer;
 
  public:
   explicit DefaultValueAdapter() {}
 
-  void ConstructNext(AllocatorType* alloc_ptr, pointer construct_at) {
+  void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) {
     AllocatorTraits::construct(*alloc_ptr, construct_at);
   }
 
-  void AssignNext(pointer assign_at) { *assign_at = value_type(); }
+  void AssignNext(Pointer assign_at) { *assign_at = ValueType(); }
 };
 
 template <typename AllocatorType>
 class AllocationTransaction {
-  using value_type = typename AllocatorType::value_type;
-  using pointer = typename AllocatorType::pointer;
-  using size_type = typename AllocatorType::size_type;
   using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+  using Pointer = typename AllocatorTraits::pointer;
+  using SizeType = typename AllocatorTraits::size_type;
 
  public:
   explicit AllocationTransaction(AllocatorType* alloc_ptr)
@@ -180,11 +193,11 @@
   void operator=(const AllocationTransaction&) = delete;
 
   AllocatorType& GetAllocator() { return alloc_data_.template get<0>(); }
-  pointer& GetData() { return alloc_data_.template get<1>(); }
-  size_type& GetCapacity() { return capacity_; }
+  Pointer& GetData() { return alloc_data_.template get<1>(); }
+  SizeType& GetCapacity() { return capacity_; }
 
   bool DidAllocate() { return GetData() != nullptr; }
-  pointer Allocate(size_type capacity) {
+  Pointer Allocate(SizeType capacity) {
     GetData() = AllocatorTraits::allocate(GetAllocator(), capacity);
     GetCapacity() = capacity;
     return GetData();
@@ -196,14 +209,15 @@
   }
 
  private:
-  container_internal::CompressedTuple<AllocatorType, pointer> alloc_data_;
-  size_type capacity_ = 0;
+  container_internal::CompressedTuple<AllocatorType, Pointer> alloc_data_;
+  SizeType capacity_ = 0;
 };
 
 template <typename AllocatorType>
 class ConstructionTransaction {
-  using pointer = typename AllocatorType::pointer;
-  using size_type = typename AllocatorType::size_type;
+  using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+  using Pointer = typename AllocatorTraits::pointer;
+  using SizeType = typename AllocatorTraits::size_type;
 
  public:
   explicit ConstructionTransaction(AllocatorType* alloc_ptr)
@@ -220,12 +234,12 @@
   void operator=(const ConstructionTransaction&) = delete;
 
   AllocatorType& GetAllocator() { return alloc_data_.template get<0>(); }
-  pointer& GetData() { return alloc_data_.template get<1>(); }
-  size_type& GetSize() { return size_; }
+  Pointer& GetData() { return alloc_data_.template get<1>(); }
+  SizeType& GetSize() { return size_; }
 
   bool DidConstruct() { return GetData() != nullptr; }
   template <typename ValueAdapter>
-  void Construct(pointer data, ValueAdapter* values_ptr, size_type size) {
+  void Construct(Pointer data, ValueAdapter* values_ptr, SizeType size) {
     inlined_vector_internal::ConstructElements(std::addressof(GetAllocator()),
                                                data, values_ptr, size);
     GetData() = data;
@@ -237,28 +251,29 @@
   }
 
  private:
-  container_internal::CompressedTuple<AllocatorType, pointer> alloc_data_;
-  size_type size_ = 0;
+  container_internal::CompressedTuple<AllocatorType, Pointer> alloc_data_;
+  SizeType size_ = 0;
 };
 
 template <typename T, size_t N, typename A>
 class Storage {
  public:
-  using allocator_type = A;
-  using value_type = typename allocator_type::value_type;
-  using pointer = typename allocator_type::pointer;
-  using const_pointer = typename allocator_type::const_pointer;
-  using reference = typename allocator_type::reference;
-  using const_reference = typename allocator_type::const_reference;
-  using rvalue_reference = typename allocator_type::value_type&&;
-  using size_type = typename allocator_type::size_type;
-  using difference_type = typename allocator_type::difference_type;
+  using AllocatorTraits = absl::allocator_traits<A>;
+  using allocator_type = typename AllocatorTraits::allocator_type;
+  using value_type = typename AllocatorTraits::value_type;
+  using pointer = typename AllocatorTraits::pointer;
+  using const_pointer = typename AllocatorTraits::const_pointer;
+  using size_type = typename AllocatorTraits::size_type;
+  using difference_type = typename AllocatorTraits::difference_type;
+
+  using reference = value_type&;
+  using const_reference = const value_type&;
+  using RValueReference = value_type&&;
   using iterator = pointer;
   using const_iterator = const_pointer;
   using reverse_iterator = std::reverse_iterator<iterator>;
   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
   using MoveIterator = std::move_iterator<iterator>;
-  using AllocatorTraits = absl::allocator_traits<allocator_type>;
   using IsMemcpyOk = inlined_vector_internal::IsMemcpyOk<allocator_type>;
 
   using StorageView = inlined_vector_internal::StorageView<allocator_type>;
@@ -289,9 +304,10 @@
   // Storage Constructors and Destructor
   // ---------------------------------------------------------------------------
 
-  Storage() : metadata_() {}
+  Storage() : metadata_(allocator_type(), /* size and is_allocated */ 0) {}
 
-  explicit Storage(const allocator_type& alloc) : metadata_(alloc, {}) {}
+  explicit Storage(const allocator_type& alloc)
+      : metadata_(alloc, /* size and is_allocated */ 0) {}
 
   ~Storage() {
     pointer data = GetIsAllocated() ? GetAllocatedData() : GetInlinedData();
@@ -453,6 +469,9 @@
     Inlined inlined;
   };
 
+  template <typename... Args>
+  ABSL_ATTRIBUTE_NOINLINE reference EmplaceBackSlow(Args&&... args);
+
   Metadata metadata_;
   Data data_;
 };
@@ -471,12 +490,9 @@
     // safe to take on the allocation with size `0`. If `ConstructElements(...)`
     // throws, deallocation will be automatically handled by `~Storage()`.
     size_type new_capacity = ComputeCapacity(GetInlinedCapacity(), new_size);
-    pointer new_data = AllocatorTraits::allocate(*GetAllocPtr(), new_capacity);
-
-    SetAllocatedData(new_data, new_capacity);
+    construct_data = AllocatorTraits::allocate(*GetAllocPtr(), new_capacity);
+    SetAllocatedData(construct_data, new_capacity);
     SetIsAllocated();
-
-    construct_data = new_data;
   } else {
     construct_data = GetInlinedData();
   }
@@ -503,9 +519,7 @@
 
   if (new_size > storage_view.capacity) {
     size_type new_capacity = ComputeCapacity(storage_view.capacity, new_size);
-    pointer new_data = allocation_tx.Allocate(new_capacity);
-
-    construct_loop = {new_data, new_size};
+    construct_loop = {allocation_tx.Allocate(new_capacity), new_size};
     destroy_loop = {storage_view.data, storage_view.size};
   } else if (new_size > storage_view.size) {
     assign_loop = {storage_view.data, storage_view.size};
@@ -538,49 +552,42 @@
 template <typename ValueAdapter>
 auto Storage<T, N, A>::Resize(ValueAdapter values, size_type new_size) -> void {
   StorageView storage_view = MakeStorageView();
-
-  AllocationTransaction allocation_tx(GetAllocPtr());
-  ConstructionTransaction construction_tx(GetAllocPtr());
-
-  IteratorValueAdapter<MoveIterator> move_values(
-      MoveIterator(storage_view.data));
-
-  absl::Span<value_type> construct_loop;
-  absl::Span<value_type> move_construct_loop;
-  absl::Span<value_type> destroy_loop;
-
-  if (new_size > storage_view.capacity) {
+  auto* const base = storage_view.data;
+  const size_type size = storage_view.size;
+  auto* alloc = GetAllocPtr();
+  if (new_size <= size) {
+    // Destroy extra old elements.
+    inlined_vector_internal::DestroyElements(alloc, base + new_size,
+                                             size - new_size);
+  } else if (new_size <= storage_view.capacity) {
+    // Construct new elements in place.
+    inlined_vector_internal::ConstructElements(alloc, base + size, &values,
+                                               new_size - size);
+  } else {
+    // Steps:
+    //  a. Allocate new backing store.
+    //  b. Construct new elements in new backing store.
+    //  c. Move existing elements from old backing store to now.
+    //  d. Destroy all elements in old backing store.
+    // Use transactional wrappers for the first two steps so we can roll
+    // back if necessary due to exceptions.
+    AllocationTransaction allocation_tx(alloc);
     size_type new_capacity = ComputeCapacity(storage_view.capacity, new_size);
     pointer new_data = allocation_tx.Allocate(new_capacity);
 
-    construct_loop = {new_data + storage_view.size,
-                      new_size - storage_view.size};
-    move_construct_loop = {new_data, storage_view.size};
-    destroy_loop = {storage_view.data, storage_view.size};
-  } else if (new_size > storage_view.size) {
-    construct_loop = {storage_view.data + storage_view.size,
-                      new_size - storage_view.size};
-  } else {
-    destroy_loop = {storage_view.data + new_size, storage_view.size - new_size};
-  }
+    ConstructionTransaction construction_tx(alloc);
+    construction_tx.Construct(new_data + size, &values, new_size - size);
 
-  construction_tx.Construct(construct_loop.data(), &values,
-                            construct_loop.size());
+    IteratorValueAdapter<MoveIterator> move_values((MoveIterator(base)));
+    inlined_vector_internal::ConstructElements(alloc, new_data, &move_values,
+                                               size);
 
-  inlined_vector_internal::ConstructElements(
-      GetAllocPtr(), move_construct_loop.data(), &move_values,
-      move_construct_loop.size());
-
-  inlined_vector_internal::DestroyElements(GetAllocPtr(), destroy_loop.data(),
-                                           destroy_loop.size());
-
-  construction_tx.Commit();
-  if (allocation_tx.DidAllocate()) {
+    inlined_vector_internal::DestroyElements(alloc, base, size);
+    construction_tx.Commit();
     DeallocateIfAllocated();
     AcquireAllocatedData(&allocation_tx);
     SetIsAllocated();
   }
-
   SetSize(new_size);
 }
 
@@ -681,54 +688,57 @@
 template <typename... Args>
 auto Storage<T, N, A>::EmplaceBack(Args&&... args) -> reference {
   StorageView storage_view = MakeStorageView();
+  const auto n = storage_view.size;
+  if (ABSL_PREDICT_TRUE(n != storage_view.capacity)) {
+    // Fast path; new element fits.
+    pointer last_ptr = storage_view.data + n;
+    AllocatorTraits::construct(*GetAllocPtr(), last_ptr,
+                               std::forward<Args>(args)...);
+    AddSize(1);
+    return *last_ptr;
+  }
+  // TODO(b/173712035): Annotate with musttail attribute to prevent regression.
+  return EmplaceBackSlow(std::forward<Args>(args)...);
+}
 
+template <typename T, size_t N, typename A>
+template <typename... Args>
+auto Storage<T, N, A>::EmplaceBackSlow(Args&&... args) -> reference {
+  StorageView storage_view = MakeStorageView();
   AllocationTransaction allocation_tx(GetAllocPtr());
-
   IteratorValueAdapter<MoveIterator> move_values(
       MoveIterator(storage_view.data));
+  size_type new_capacity = NextCapacity(storage_view.capacity);
+  pointer construct_data = allocation_tx.Allocate(new_capacity);
+  pointer last_ptr = construct_data + storage_view.size;
 
-  pointer construct_data;
-  if (storage_view.size == storage_view.capacity) {
-    size_type new_capacity = NextCapacity(storage_view.capacity);
-    pointer new_data = allocation_tx.Allocate(new_capacity);
-
-    construct_data = new_data;
-  } else {
-    construct_data = storage_view.data;
-  }
-
-  AllocatorTraits::construct(*GetAllocPtr(), construct_data + storage_view.size,
+  // Construct new element.
+  AllocatorTraits::construct(*GetAllocPtr(), last_ptr,
                              std::forward<Args>(args)...);
-
-  if (allocation_tx.DidAllocate()) {
-    ABSL_INTERNAL_TRY {
-      inlined_vector_internal::ConstructElements(
-          GetAllocPtr(), allocation_tx.GetData(), &move_values,
-          storage_view.size);
-    }
-    ABSL_INTERNAL_CATCH_ANY {
-      AllocatorTraits::destroy(*GetAllocPtr(),
-                               construct_data + storage_view.size);
-      ABSL_INTERNAL_RETHROW;
-    }
-
-    inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data,
-                                             storage_view.size);
-
-    DeallocateIfAllocated();
-    AcquireAllocatedData(&allocation_tx);
-    SetIsAllocated();
+  // Move elements from old backing store to new backing store.
+  ABSL_INTERNAL_TRY {
+    inlined_vector_internal::ConstructElements(
+        GetAllocPtr(), allocation_tx.GetData(), &move_values,
+        storage_view.size);
   }
+  ABSL_INTERNAL_CATCH_ANY {
+    AllocatorTraits::destroy(*GetAllocPtr(), last_ptr);
+    ABSL_INTERNAL_RETHROW;
+  }
+  // Destroy elements in old backing store.
+  inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data,
+                                           storage_view.size);
 
+  DeallocateIfAllocated();
+  AcquireAllocatedData(&allocation_tx);
+  SetIsAllocated();
   AddSize(1);
-  return *(construct_data + storage_view.size);
+  return *last_ptr;
 }
 
 template <typename T, size_t N, typename A>
 auto Storage<T, N, A>::Erase(const_iterator from, const_iterator to)
     -> iterator {
-  assert(from != to);
-
   StorageView storage_view = MakeStorageView();
 
   size_type erase_size = std::distance(from, to);
@@ -795,9 +805,7 @@
   pointer construct_data;
   if (storage_view.size > GetInlinedCapacity()) {
     size_type new_capacity = storage_view.size;
-    pointer new_data = allocation_tx.Allocate(new_capacity);
-
-    construct_data = new_data;
+    construct_data = allocation_tx.Allocate(new_capacity);
   } else {
     construct_data = GetInlinedData();
   }
@@ -887,7 +895,13 @@
   swap(*GetAllocPtr(), *other_storage_ptr->GetAllocPtr());
 }
 
+// End ignore "maybe-uninitialized"
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
 }  // namespace inlined_vector_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
diff --git a/absl/container/internal/layout.h b/absl/container/internal/layout.h
index bbdde50..2336783 100644
--- a/absl/container/internal/layout.h
+++ b/absl/container/internal/layout.h
@@ -163,6 +163,7 @@
 #include <assert.h>
 #include <stddef.h>
 #include <stdint.h>
+
 #include <ostream>
 #include <string>
 #include <tuple>
@@ -170,15 +171,16 @@
 #include <typeinfo>
 #include <utility>
 
-#ifdef ADDRESS_SANITIZER
-#include <sanitizer/asan_interface.h>
-#endif
-
+#include "absl/base/config.h"
 #include "absl/meta/type_traits.h"
 #include "absl/strings/str_cat.h"
 #include "absl/types/span.h"
 #include "absl/utility/utility.h"
 
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#include <sanitizer/asan_interface.h>
+#endif
+
 #if defined(__GXX_RTTI)
 #define ABSL_INTERNAL_HAS_CXA_DEMANGLE
 #endif
@@ -188,6 +190,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 // A type wrapper that instructs `Layout` to use the specific alignment for the
@@ -613,7 +616,7 @@
   void PoisonPadding(const Char* p) const {
     static_assert(N < NumOffsets, "Index out of bounds");
     (void)p;
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
     PoisonPadding<Char, N - 1>(p);
     // The `if` is an optimization. It doesn't affect the observable behaviour.
     if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) {
@@ -734,6 +737,7 @@
 };
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_LAYOUT_H_
diff --git a/absl/container/internal/layout_benchmark.cc b/absl/container/internal/layout_benchmark.cc
new file mode 100644
index 0000000..d8636e8
--- /dev/null
+++ b/absl/container/internal/layout_benchmark.cc
@@ -0,0 +1,122 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Every benchmark should have the same performance as the corresponding
+// headroom benchmark.
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/container/internal/layout.h"
+#include "benchmark/benchmark.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+namespace {
+
+using ::benchmark::DoNotOptimize;
+
+using Int128 = int64_t[2];
+
+// This benchmark provides the upper bound on performance for BM_OffsetConstant.
+template <size_t Offset, class... Ts>
+void BM_OffsetConstantHeadroom(benchmark::State& state) {
+  for (auto _ : state) {
+    DoNotOptimize(Offset);
+  }
+}
+
+template <size_t Offset, class... Ts>
+void BM_OffsetConstant(benchmark::State& state) {
+  using L = Layout<Ts...>;
+  ABSL_RAW_CHECK(L::Partial(3, 5, 7).template Offset<3>() == Offset,
+                 "Invalid offset");
+  for (auto _ : state) {
+    DoNotOptimize(L::Partial(3, 5, 7).template Offset<3>());
+  }
+}
+
+template <class... Ts>
+size_t VariableOffset(size_t n, size_t m, size_t k);
+
+template <>
+size_t VariableOffset<int8_t, int16_t, int32_t, Int128>(size_t n, size_t m,
+                                                        size_t k) {
+  auto Align = [](size_t n, size_t m) { return (n + m - 1) & ~(m - 1); };
+  return Align(Align(Align(n * 1, 2) + m * 2, 4) + k * 4, 8);
+}
+
+template <>
+size_t VariableOffset<Int128, int32_t, int16_t, int8_t>(size_t n, size_t m,
+                                                        size_t k) {
+  // No alignment is necessary.
+  return n * 16 + m * 4 + k * 2;
+}
+
+// This benchmark provides the upper bound on performance for BM_OffsetVariable.
+template <size_t Offset, class... Ts>
+void BM_OffsetVariableHeadroom(benchmark::State& state) {
+  size_t n = 3;
+  size_t m = 5;
+  size_t k = 7;
+  ABSL_RAW_CHECK(VariableOffset<Ts...>(n, m, k) == Offset, "Invalid offset");
+  for (auto _ : state) {
+    DoNotOptimize(n);
+    DoNotOptimize(m);
+    DoNotOptimize(k);
+    DoNotOptimize(VariableOffset<Ts...>(n, m, k));
+  }
+}
+
+template <size_t Offset, class... Ts>
+void BM_OffsetVariable(benchmark::State& state) {
+  using L = Layout<Ts...>;
+  size_t n = 3;
+  size_t m = 5;
+  size_t k = 7;
+  ABSL_RAW_CHECK(L::Partial(n, m, k).template Offset<3>() == Offset,
+                 "Inavlid offset");
+  for (auto _ : state) {
+    DoNotOptimize(n);
+    DoNotOptimize(m);
+    DoNotOptimize(k);
+    DoNotOptimize(L::Partial(n, m, k).template Offset<3>());
+  }
+}
+
+// Run all benchmarks in two modes:
+//
+//   Layout with padding: int8_t[3], int16_t[5], int32_t[7], Int128[?].
+//   Layout without padding: Int128[3], int32_t[5], int16_t[7], int8_t[?].
+
+#define OFFSET_BENCHMARK(NAME, OFFSET, T1, T2, T3, T4) \
+  auto& NAME##_##OFFSET##_##T1##_##T2##_##T3##_##T4 =  \
+      NAME<OFFSET, T1, T2, T3, T4>;                    \
+  BENCHMARK(NAME##_##OFFSET##_##T1##_##T2##_##T3##_##T4)
+
+OFFSET_BENCHMARK(BM_OffsetConstantHeadroom, 48, int8_t, int16_t, int32_t,
+                 Int128);
+OFFSET_BENCHMARK(BM_OffsetConstant, 48, int8_t, int16_t, int32_t, Int128);
+OFFSET_BENCHMARK(BM_OffsetConstantHeadroom, 82, Int128, int32_t, int16_t,
+                 int8_t);
+OFFSET_BENCHMARK(BM_OffsetConstant, 82, Int128, int32_t, int16_t, int8_t);
+OFFSET_BENCHMARK(BM_OffsetVariableHeadroom, 48, int8_t, int16_t, int32_t,
+                 Int128);
+OFFSET_BENCHMARK(BM_OffsetVariable, 48, int8_t, int16_t, int32_t, Int128);
+OFFSET_BENCHMARK(BM_OffsetVariableHeadroom, 82, Int128, int32_t, int16_t,
+                 int8_t);
+OFFSET_BENCHMARK(BM_OffsetVariable, 82, Int128, int32_t, int16_t, int8_t);
+}  // namespace
+}  // namespace container_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/container/internal/layout_test.cc b/absl/container/internal/layout_test.cc
index 33b72bd..1d7158f 100644
--- a/absl/container/internal/layout_test.cc
+++ b/absl/container/internal/layout_test.cc
@@ -17,6 +17,7 @@
 // We need ::max_align_t because some libstdc++ versions don't provide
 // std::max_align_t
 #include <stddef.h>
+
 #include <cstdint>
 #include <memory>
 #include <sstream>
@@ -24,10 +25,12 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/types/span.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
@@ -125,8 +128,10 @@
   {
     using L = Layout<int32_t, int32_t>;
     SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>();
-    SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial())::ElementTypes>();
-    SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial(0))::ElementTypes>();
+    SameType<std::tuple<int32_t, int32_t>,
+             decltype(L::Partial())::ElementTypes>();
+    SameType<std::tuple<int32_t, int32_t>,
+             decltype(L::Partial(0))::ElementTypes>();
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
@@ -365,18 +370,21 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p))));
   }
   {
     using L = Layout<int32_t, int32_t>;
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
-    EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
     EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
+              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
     EXPECT_EQ(12,
-              Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
+              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
+    EXPECT_EQ(
+        12, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p))));
     EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p))));
   }
@@ -384,39 +392,44 @@
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p))));
-    EXPECT_EQ(4, Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
+    EXPECT_EQ(4,
+              Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p))));
-    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
+    EXPECT_EQ(8,
+              Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
-    EXPECT_EQ(4,
-              Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
+    EXPECT_EQ(
+        4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
     EXPECT_EQ(8,
               Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
-    EXPECT_EQ(8,
-              Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
+    EXPECT_EQ(
+        8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
+        0,
+        Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
     EXPECT_EQ(
-        4, Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
+        4,
+        Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(
         8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(
@@ -425,7 +438,8 @@
         24,
         Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
     EXPECT_EQ(
-        8, Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
+        8,
+        Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p))));
     EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p))));
     EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p))));
@@ -436,75 +450,78 @@
   alignas(max_align_t) const unsigned char p[100] = {};
   {
     using L = Layout<int32_t>;
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p))));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
-    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
-    EXPECT_EQ(4,
-              Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
-    EXPECT_EQ(8,
-              Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+        0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
+        0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        4,
+        Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        8,
+        Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
+                                 L::Partial(0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         0,
         Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
+        0,
+        Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
+                                 L::Partial(1, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         8,
         Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
     EXPECT_EQ(
-        0, Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
+        0,
+        Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
+    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
+                                 L::Partial(5, 3).Pointer<int32_t>(p))));
     EXPECT_EQ(
         24,
         Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+                                 L::Partial(0, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
+                                 L::Partial(0, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<const Int128*>(
                                  L::Partial(0, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(
-        4,
-        Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+                                 L::Partial(1, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
+                                 L::Partial(1, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(8, Distance(p, Type<const Int128*>(
                                  L::Partial(1, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
+    EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+                                 L::Partial(5, 3, 1).Pointer<int8_t>(p))));
     EXPECT_EQ(24, Distance(p, Type<const Int128*>(
                                   L::Partial(5, 3, 1).Pointer<Int128>(p))));
-    EXPECT_EQ(
-        8,
-        Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
+    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
+                                 L::Partial(5, 3, 1).Pointer<int32_t>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
-    EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
   }
 }
 
@@ -545,15 +562,18 @@
     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
     EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
-    EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
+    EXPECT_EQ(4,
+              Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
     EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
-    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
+    EXPECT_EQ(8,
+              Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p))));
     EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p))));
     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p))));
@@ -565,48 +585,61 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p))));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
-    EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
+    EXPECT_EQ(4,
+              Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
-    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(8,
+              Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(0,
               Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(8,
               Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
-    EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
+    EXPECT_EQ(0,
+              Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
     EXPECT_EQ(24,
               Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
-    EXPECT_EQ(4,
-              Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        4,
+        Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
     EXPECT_EQ(
         8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p))));
-    EXPECT_EQ(0,
-              Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
+    EXPECT_EQ(
+        0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
     EXPECT_EQ(
         24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p))));
-    EXPECT_EQ(8,
-              Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
+    EXPECT_EQ(
+        8,
+        Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p))));
     EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
@@ -787,67 +820,72 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
-    EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+    EXPECT_EQ(0,
+              Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
   }
   {
     using L = Layout<int32_t, int32_t>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
     EXPECT_EQ(
         12,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
-    EXPECT_EQ(12,
-              Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        12, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
     EXPECT_EQ(
         0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+               p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
     EXPECT_EQ(
         0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        4,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        8,
-        Distance(p,
-                 Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+               p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+            p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        4,
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        8,
+        Distance(
+            p, Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p,
+            Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
@@ -861,7 +899,8 @@
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
+            p,
+            Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
         4,
         Distance(
@@ -875,7 +914,8 @@
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
+            p,
+            Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(
@@ -887,12 +927,14 @@
             p,
             Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
+        0,
+        Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
     EXPECT_EQ(
-        8, Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
+        8,
+        Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
   }
 }
 
@@ -903,98 +945,94 @@
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
+            p,
+            Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
+            p,
+            Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
+        0,
+        Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
+            p,
+            Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
             p,
-            Type<Span<const int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        4,
-        Distance(
-            p,
-            Type<Span<const int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        8,
-        Distance(
-            p,
-            Type<Span<const int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
+            Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
             p,
-            Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
+            Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p))
+        Distance(p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p))
                         .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(0, 0).Slice<int32_t>(p))
+                                 .data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p))
+                        .data()));
+    EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(1, 0).Slice<int32_t>(p))
+                                 .data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p))
+                        .data()));
+    EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(5, 3).Slice<int32_t>(p))
+                                 .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+                                 L::Partial(0, 0, 0).Slice<int8_t>(p))
+                                 .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(0, 0, 0).Slice<int32_t>(p))
+                                 .data()));
     EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(
                                  L::Partial(0, 0, 0).Slice<Int128>(p))
                                  .data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p,
-            Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        4,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p))
-                        .data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+                                 L::Partial(1, 0, 0).Slice<int8_t>(p))
+                                 .data()));
+    EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(1, 0, 0).Slice<int32_t>(p))
+                                 .data()));
     EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>(
                                  L::Partial(1, 0, 0).Slice<Int128>(p))
                                  .data()));
-    EXPECT_EQ(
-        0,
-        Distance(
-            p,
-            Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+                                 L::Partial(5, 3, 1).Slice<int8_t>(p))
+                                 .data()));
     EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>(
                                   L::Partial(5, 3, 1).Slice<Int128>(p))
                                   .data()));
-    EXPECT_EQ(
-        8,
-        Distance(p, Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p))
-                        .data()));
+    EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
+                                 L::Partial(5, 3, 1).Slice<int32_t>(p))
+                                 .data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
+        Distance(p,
+                 Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(p,
                  Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        8, Distance(
-               p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
+        8,
+        Distance(
+            p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
   }
 }
 
@@ -1002,18 +1040,19 @@
   alignas(max_align_t) unsigned char p[100];
   {
     using L = Layout<int32_t>;
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
     EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data()));
   }
   {
     using L = Layout<int32_t, int32_t>;
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
+        0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
     EXPECT_EQ(
         12,
         Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
@@ -1022,55 +1061,63 @@
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
+        0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+        0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        4, Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
-    EXPECT_EQ(
-        8, Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+        0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+        Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
+        Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        4,
+        Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        8,
+        Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(
+               p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(
+               p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
     EXPECT_EQ(
         0, Distance(
                p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
     EXPECT_EQ(
-        4,
-        Distance(p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
+        4, Distance(
+               p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
     EXPECT_EQ(
         8, Distance(
                p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
+        0, Distance(
+               p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(
         24, Distance(
                 p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
     EXPECT_EQ(
-        8,
-        Distance(p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
-    EXPECT_EQ(0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
+        8, Distance(
+               p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
+    EXPECT_EQ(0,
+              Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
     EXPECT_EQ(24,
               Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
-    EXPECT_EQ(8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
+    EXPECT_EQ(8,
+              Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
   }
 }
 
@@ -1079,66 +1126,84 @@
   {
     using L = Layout<int32_t>;
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
+        0, Distance(
+               p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
-        0,
-        Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
+        0, Distance(
+               p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(0,
+              Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
   }
   {
     using L = Layout<int8_t, int32_t, Int128>;
     EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
+        0,
+        Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
+        Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        4, Distance(
-               p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
+        Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
-        Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
-    EXPECT_EQ(
-        8, Distance(
-               p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
+        Distance(p,
+                 Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
-            p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
+            p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p,
+                 Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(
+        4,
+        Distance(
+            p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(p,
+                 Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(
+        8,
+        Distance(
+            p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p,
+            Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
+    EXPECT_EQ(
+        0,
+        Distance(
+            p,
+            Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
         0,
         Distance(
             p,
             Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
+        0,
+        Distance(
+            p,
+            Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         4,
         Distance(
-            p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
+            p,
+            Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
     EXPECT_EQ(
         8,
         Distance(
             p,
             Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        0, Distance(
-               p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
+        0,
+        Distance(
+            p,
+            Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(
@@ -1147,14 +1212,16 @@
     EXPECT_EQ(
         8,
         Distance(
-            p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
-    EXPECT_EQ(0,
-              Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
+            p,
+            Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
+    EXPECT_EQ(
+        0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
     EXPECT_EQ(
         24,
         Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
     EXPECT_EQ(
-        8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
+        8,
+        Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
   }
 }
 
@@ -1253,17 +1320,17 @@
   }
   {
     const auto x = L::Partial(1, 2, 3);
-    EXPECT_THAT(
-        (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
-        Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
-              IsSameSlice(x.Slice<2>(p))));
+    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
+                    x.Slices(p))),
+                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
+                      IsSameSlice(x.Slice<2>(p))));
   }
   {
     const L x(1, 2, 3);
-    EXPECT_THAT(
-        (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
-        Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
-              IsSameSlice(x.Slice<2>(p))));
+    EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
+                    x.Slices(p))),
+                Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
+                      IsSameSlice(x.Slice<2>(p))));
   }
 }
 
@@ -1313,7 +1380,7 @@
 };
 
 void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) {
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
   for (size_t i = 0; i != n; ++i) {
     EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i));
   }
@@ -1395,7 +1462,8 @@
               x.DebugString());
   }
   {
-    constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
+    constexpr auto x =
+        Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
     EXPECT_EQ(
         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
         "@16" +
@@ -1403,7 +1471,8 @@
         x.DebugString());
   }
   {
-    constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
+    constexpr auto x =
+        Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
     EXPECT_EQ(
         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
         "@16" +
@@ -1562,4 +1631,5 @@
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/node_hash_policy.h b/absl/container/internal/node_hash_policy.h
index 19b4fc0..4617162 100644
--- a/absl/container/internal/node_hash_policy.h
+++ b/absl/container/internal/node_hash_policy.h
@@ -39,7 +39,10 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <class Reference, class Policy>
@@ -83,6 +86,7 @@
 };
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_NODE_HASH_POLICY_H_
diff --git a/absl/container/internal/node_hash_policy_test.cc b/absl/container/internal/node_hash_policy_test.cc
index f1d3ec3..84aabba 100644
--- a/absl/container/internal/node_hash_policy_test.cc
+++ b/absl/container/internal/node_hash_policy_test.cc
@@ -21,6 +21,7 @@
 #include "absl/container/internal/hash_policy_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
@@ -64,4 +65,5 @@
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/raw_hash_map.h b/absl/container/internal/raw_hash_map.h
index 7dad120..0a02757 100644
--- a/absl/container/internal/raw_hash_map.h
+++ b/absl/container/internal/raw_hash_map.h
@@ -24,6 +24,7 @@
 #include "absl/container/internal/raw_hash_set.h"  // IWYU pragma: export
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <class Policy, class Hash, class Eq, class Alloc>
@@ -190,6 +191,7 @@
 };
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_RAW_HASH_MAP_H_
diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc
index ac2d10a..bfef071 100644
--- a/absl/container/internal/raw_hash_set.cc
+++ b/absl/container/internal/raw_hash_set.cc
@@ -20,13 +20,14 @@
 #include "absl/base/config.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 constexpr size_t Group::kWidth;
 
 // Returns "random" seed.
 inline size_t RandomSeed() {
-#if ABSL_HAVE_THREAD_LOCAL
+#ifdef ABSL_HAVE_THREAD_LOCAL
   static thread_local size_t counter = 0;
   size_t value = ++counter;
 #else   // ABSL_HAVE_THREAD_LOCAL
@@ -42,5 +43,19 @@
   return (H1(hash, ctrl) ^ RandomSeed()) % 13 > 6;
 }
 
+void ConvertDeletedToEmptyAndFullToDeleted(
+    ctrl_t* ctrl, size_t capacity) {
+  assert(ctrl[capacity] == kSentinel);
+  assert(IsValidCapacity(capacity));
+  for (ctrl_t* pos = ctrl; pos != ctrl + capacity + 1; pos += Group::kWidth) {
+    Group{pos}.ConvertSpecialToEmptyAndFullToDeleted(pos);
+  }
+  // Copy the cloned ctrl bytes.
+  std::memcpy(ctrl + capacity + 1, ctrl, Group::kWidth);
+  ctrl[capacity] = kSentinel;
+}
+
+
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 2e6f4dd..74b2ef4 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -102,8 +102,8 @@
 #include <type_traits>
 #include <utility>
 
-#include "absl/base/internal/bits.h"
 #include "absl/base/internal/endian.h"
+#include "absl/base/optimization.h"
 #include "absl/base/port.h"
 #include "absl/container/internal/common.h"
 #include "absl/container/internal/compressed_tuple.h"
@@ -115,11 +115,23 @@
 #include "absl/container/internal/layout.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
+#include "absl/numeric/bits.h"
 #include "absl/utility/utility.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
+template <typename AllocType>
+void SwapAlloc(AllocType& lhs, AllocType& rhs,
+               std::true_type /* propagate_on_container_swap */) {
+  using std::swap;
+  swap(lhs, rhs);
+}
+template <typename AllocType>
+void SwapAlloc(AllocType& /*lhs*/, AllocType& /*rhs*/,
+               std::false_type /* propagate_on_container_swap */) {}
+
 template <size_t Width>
 class probe_seq {
  public:
@@ -167,24 +179,19 @@
 
 // TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
 template <class T>
-constexpr bool IsNoThrowSwappable() {
+constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) {
   using std::swap;
   return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
 }
-
-template <typename T>
-int TrailingZeros(T x) {
-  return sizeof(T) == 8 ? base_internal::CountTrailingZerosNonZero64(
-                              static_cast<uint64_t>(x))
-                        : base_internal::CountTrailingZerosNonZero32(
-                              static_cast<uint32_t>(x));
+template <class T>
+constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) {
+  return false;
 }
 
 template <typename T>
-int LeadingZeros(T x) {
-  return sizeof(T) == 8
-             ? base_internal::CountLeadingZeros64(static_cast<uint64_t>(x))
-             : base_internal::CountLeadingZeros32(static_cast<uint32_t>(x));
+uint32_t TrailingZeros(T x) {
+  ABSL_INTERNAL_ASSUME(x != 0);
+  return countr_zero(x);
 }
 
 // An abstraction over a bitmask. It provides an easy way to iterate through the
@@ -214,26 +221,24 @@
   }
   explicit operator bool() const { return mask_ != 0; }
   int operator*() const { return LowestBitSet(); }
-  int LowestBitSet() const {
+  uint32_t LowestBitSet() const {
     return container_internal::TrailingZeros(mask_) >> Shift;
   }
-  int HighestBitSet() const {
-    return (sizeof(T) * CHAR_BIT - container_internal::LeadingZeros(mask_) -
-            1) >>
-           Shift;
+  uint32_t HighestBitSet() const {
+    return static_cast<uint32_t>((bit_width(mask_) - 1) >> Shift);
   }
 
   BitMask begin() const { return *this; }
   BitMask end() const { return BitMask(0); }
 
-  int TrailingZeros() const {
+  uint32_t TrailingZeros() const {
     return container_internal::TrailingZeros(mask_) >> Shift;
   }
 
-  int LeadingZeros() const {
+  uint32_t LeadingZeros() const {
     constexpr int total_significant_bits = SignificantBits << Shift;
     constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits;
-    return container_internal::LeadingZeros(mask_ << extra_bits) >> Shift;
+    return countl_zero(mask_ << extra_bits) >> Shift;
   }
 
  private:
@@ -311,7 +316,7 @@
 inline bool IsDeleted(ctrl_t c) { return c == kDeleted; }
 inline bool IsEmptyOrDeleted(ctrl_t c) { return c < kSentinel; }
 
-#if SWISSTABLE_HAVE_SSE2
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
 
 // https://github.com/abseil/abseil-cpp/issues/209
 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
@@ -345,7 +350,7 @@
 
   // Returns a bitmask representing the positions of empty slots.
   BitMask<uint32_t, kWidth> MatchEmpty() const {
-#if SWISSTABLE_HAVE_SSSE3
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
     // This only works because kEmpty is -128.
     return BitMask<uint32_t, kWidth>(
         _mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl)));
@@ -364,14 +369,14 @@
   // Returns the number of trailing empty or deleted elements in the group.
   uint32_t CountLeadingEmptyOrDeleted() const {
     auto special = _mm_set1_epi8(kSentinel);
-    return TrailingZeros(
-        _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1);
+    return TrailingZeros(static_cast<uint32_t>(
+        _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1));
   }
 
   void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
     auto msbs = _mm_set1_epi8(static_cast<char>(-128));
     auto x126 = _mm_set1_epi8(126);
-#if SWISSTABLE_HAVE_SSSE3
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
     auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
 #else
     auto zero = _mm_setzero_si128();
@@ -383,7 +388,7 @@
 
   __m128i ctrl;
 };
-#endif  // SWISSTABLE_HAVE_SSE2
+#endif  // ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
 
 struct GroupPortableImpl {
   static constexpr size_t kWidth = 8;
@@ -437,7 +442,7 @@
   uint64_t ctrl;
 };
 
-#if SWISSTABLE_HAVE_SSE2
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
 using Group = GroupSse2Impl;
 #else
 using Group = GroupPortableImpl;
@@ -456,21 +461,11 @@
 //   DELETED -> EMPTY
 //   EMPTY -> EMPTY
 //   FULL -> DELETED
-inline void ConvertDeletedToEmptyAndFullToDeleted(
-    ctrl_t* ctrl, size_t capacity) {
-  assert(ctrl[capacity] == kSentinel);
-  assert(IsValidCapacity(capacity));
-  for (ctrl_t* pos = ctrl; pos != ctrl + capacity + 1; pos += Group::kWidth) {
-    Group{pos}.ConvertSpecialToEmptyAndFullToDeleted(pos);
-  }
-  // Copy the cloned ctrl bytes.
-  std::memcpy(ctrl + capacity + 1, ctrl, Group::kWidth);
-  ctrl[capacity] = kSentinel;
-}
+void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity);
 
 // Rounds up the capacity to the next power of 2 minus 1, with a minimum of 1.
 inline size_t NormalizeCapacity(size_t n) {
-  return n ? ~size_t{} >> LeadingZeros(n) : 1;
+  return n ? ~size_t{} >> countl_zero(n) : 1;
 }
 
 // We use 7/8th as maximum load factor.
@@ -495,6 +490,76 @@
   return growth + static_cast<size_t>((static_cast<int64_t>(growth) - 1) / 7);
 }
 
+inline void AssertIsFull(ctrl_t* ctrl) {
+  ABSL_HARDENING_ASSERT((ctrl != nullptr && IsFull(*ctrl)) &&
+                        "Invalid operation on iterator. The element might have "
+                        "been erased, or the table might have rehashed.");
+}
+
+inline void AssertIsValid(ctrl_t* ctrl) {
+  ABSL_HARDENING_ASSERT((ctrl == nullptr || IsFull(*ctrl)) &&
+                        "Invalid operation on iterator. The element might have "
+                        "been erased, or the table might have rehashed.");
+}
+
+struct FindInfo {
+  size_t offset;
+  size_t probe_length;
+};
+
+// 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.
+inline bool is_small(size_t capacity) { return capacity < Group::kWidth - 1; }
+
+inline probe_seq<Group::kWidth> probe(ctrl_t* ctrl, size_t hash,
+                                      size_t capacity) {
+  return probe_seq<Group::kWidth>(H1(hash, ctrl), capacity);
+}
+
+// Probes the raw_hash_set with the probe sequence for hash and returns the
+// pointer to the first empty or deleted slot.
+// NOTE: this function must work with tables having both kEmpty and kDelete
+// in one group. Such tables appears during drop_deletes_without_resize.
+//
+// This function is very useful when insertions happen and:
+// - the input is already a set
+// - there are enough slots
+// - the element with the hash is not in the table
+inline FindInfo find_first_non_full(ctrl_t* ctrl, size_t hash,
+                                    size_t capacity) {
+  auto seq = probe(ctrl, hash, capacity);
+  while (true) {
+    Group g{ctrl + seq.offset()};
+    auto mask = g.MatchEmptyOrDeleted();
+    if (mask) {
+#if !defined(NDEBUG)
+      // 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
+      // the group.
+      // TODO(kfm,sbenza): revisit after we do unconditional mixing
+      if (!is_small(capacity) && ShouldInsertBackwards(hash, ctrl)) {
+        return {seq.offset(mask.HighestBitSet()), seq.index()};
+      }
+#endif
+      return {seq.offset(mask.LowestBitSet()), seq.index()};
+    }
+    seq.next();
+    assert(seq.index() < capacity && "full table!");
+  }
+}
+
 // Policy: a policy defines how to perform different operations on
 // the slots of the hashtable (see hash_policy_traits.h for the full interface
 // of policy).
@@ -509,7 +574,8 @@
 // if they are equal, false if they are not. If two keys compare equal, then
 // their hash values as defined by Hash MUST be equal.
 //
-// Allocator: an Allocator [https://devdocs.io/cpp/concept/allocator] with which
+// Allocator: an Allocator
+// [https://en.cppreference.com/w/cpp/named_req/Allocator] with which
 // the storage of the hashtable will be allocated and the elements will be
 // constructed and destroyed.
 template <class Policy, class Hash, class Eq, class Alloc>
@@ -614,13 +680,17 @@
     iterator() {}
 
     // PRECONDITION: not an end() iterator.
-    reference operator*() const { return PolicyTraits::element(slot_); }
+    reference operator*() const {
+      AssertIsFull(ctrl_);
+      return PolicyTraits::element(slot_);
+    }
 
     // PRECONDITION: not an end() iterator.
     pointer operator->() const { return &operator*(); }
 
     // PRECONDITION: not an end() iterator.
     iterator& operator++() {
+      AssertIsFull(ctrl_);
       ++ctrl_;
       ++slot_;
       skip_empty_or_deleted();
@@ -634,6 +704,8 @@
     }
 
     friend bool operator==(const iterator& a, const iterator& b) {
+      AssertIsValid(a.ctrl_);
+      AssertIsValid(b.ctrl_);
       return a.ctrl_ == b.ctrl_;
     }
     friend bool operator!=(const iterator& a, const iterator& b) {
@@ -641,23 +713,23 @@
     }
 
    private:
-    iterator(ctrl_t* ctrl) : ctrl_(ctrl) {}  // for end()
-    iterator(ctrl_t* ctrl, slot_type* slot) : ctrl_(ctrl), slot_(slot) {}
+    iterator(ctrl_t* ctrl, slot_type* slot) : ctrl_(ctrl), slot_(slot) {
+      // This assumption helps the compiler know that any non-end iterator is
+      // not equal to any end iterator.
+      ABSL_INTERNAL_ASSUME(ctrl != nullptr);
+    }
 
     void skip_empty_or_deleted() {
       while (IsEmptyOrDeleted(*ctrl_)) {
-        // ctrl is not necessarily aligned to Group::kWidth. It is also likely
-        // to read past the space for ctrl bytes and into slots. This is ok
-        // because ctrl has sizeof() == 1 and slot has sizeof() >= 1 so there
-        // is no way to read outside the combined slot array.
         uint32_t shift = Group{ctrl_}.CountLeadingEmptyOrDeleted();
         ctrl_ += shift;
         slot_ += shift;
       }
+      if (ABSL_PREDICT_FALSE(*ctrl_ == kSentinel)) ctrl_ = nullptr;
     }
 
     ctrl_t* ctrl_ = nullptr;
-    // To avoid uninitialized member warnigs, put slot_ in an anonymous union.
+    // To avoid uninitialized member warnings, put slot_ in an anonymous union.
     // The member is not initialized on singleton and end iterators.
     union {
       slot_type* slot_;
@@ -715,7 +787,6 @@
       : ctrl_(EmptyGroup()), settings_(0, hash, eq, alloc) {
     if (bucket_count) {
       capacity_ = NormalizeCapacity(bucket_count);
-      reset_growth_left();
       initialize_slots();
     }
   }
@@ -821,7 +892,7 @@
     // than a full `insert`.
     for (const auto& v : that) {
       const size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, v);
-      auto target = find_first_non_full(hash);
+      auto target = find_first_non_full(ctrl_, hash, capacity_);
       set_ctrl(target.offset, H2(hash));
       emplace_at(target.offset, v);
       infoz_.RecordInsert(hash, target.probe_length);
@@ -895,12 +966,12 @@
     it.skip_empty_or_deleted();
     return it;
   }
-  iterator end() { return {ctrl_ + capacity_}; }
+  iterator end() { return {}; }
 
   const_iterator begin() const {
     return const_cast<raw_hash_set*>(this)->begin();
   }
-  const_iterator end() const { return const_cast<raw_hash_set*>(this)->end(); }
+  const_iterator end() const { return {}; }
   const_iterator cbegin() const { return begin(); }
   const_iterator cend() const { return end(); }
 
@@ -938,8 +1009,11 @@
   //
   //   flat_hash_map<std::string, int> m;
   //   m.insert(std::make_pair("abc", 42));
+  // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
+  // bug.
   template <class T, RequiresInsertable<T> = 0,
-            typename std::enable_if<IsDecomposable<T>::value, int>::type = 0,
+            class T2 = T,
+            typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
             T* = nullptr>
   std::pair<iterator, bool> insert(T&& value) {
     return emplace(std::forward<T>(value));
@@ -975,8 +1049,10 @@
     return emplace(std::move(value));
   }
 
-  template <class T, RequiresInsertable<T> = 0,
-            typename std::enable_if<IsDecomposable<T>::value, int>::type = 0,
+  // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
+  // bug.
+  template <class T, RequiresInsertable<T> = 0, class T2 = T,
+            typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
             T* = nullptr>
   iterator insert(const_iterator, T&& value) {
     return insert(std::forward<T>(value)).first;
@@ -998,7 +1074,7 @@
 
   template <class InputIt>
   void insert(InputIt first, InputIt last) {
-    for (; first != last; ++first) insert(*first);
+    for (; first != last; ++first) emplace(*first);
   }
 
   template <class T, RequiresNotInit<T> = 0, RequiresInsertable<const T&> = 0>
@@ -1025,7 +1101,9 @@
   }
 
   iterator insert(const_iterator, node_type&& node) {
-    return insert(std::move(node)).first;
+    auto res = insert(std::move(node));
+    node = std::move(res.node);
+    return res.position;
   }
 
   // This overload kicks in if we can deduce the key from args. This enables us
@@ -1050,8 +1128,7 @@
   template <class... Args, typename std::enable_if<
                                !IsDecomposable<Args...>::value, int>::type = 0>
   std::pair<iterator, bool> emplace(Args&&... args) {
-    typename std::aligned_storage<sizeof(slot_type), alignof(slot_type)>::type
-        raw;
+    alignas(slot_type) unsigned char raw[sizeof(slot_type)];
     slot_type* slot = reinterpret_cast<slot_type*>(&raw);
 
     PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
@@ -1067,10 +1144,15 @@
   // Extension API: support for lazy emplace.
   //
   // Looks up key in the table. If found, returns the iterator to the element.
-  // Otherwise calls f with one argument of type raw_hash_set::constructor. f
-  // MUST call raw_hash_set::constructor with arguments as if a
-  // raw_hash_set::value_type is constructed, otherwise the behavior is
-  // undefined.
+  // Otherwise calls `f` with one argument of type `raw_hash_set::constructor`.
+  //
+  // `f` must abide by several restrictions:
+  //  - it MUST call `raw_hash_set::constructor` with arguments as if a
+  //    `raw_hash_set::value_type` is constructed,
+  //  - it MUST NOT access the container before the call to
+  //    `raw_hash_set::constructor`, and
+  //  - it MUST NOT erase the lazily emplaced element.
+  // Doing any of these is undefined behavior.
   //
   // For example:
   //
@@ -1150,7 +1232,7 @@
   // This overload is necessary because otherwise erase<K>(const K&) would be
   // a better match if non-const iterator is passed as an argument.
   void erase(iterator it) {
-    assert(it != end());
+    AssertIsFull(it.ctrl_);
     PolicyTraits::destroy(&alloc_ref(), it.slot_);
     erase_meta_only(it);
   }
@@ -1167,12 +1249,14 @@
   template <typename H, typename E>
   void merge(raw_hash_set<Policy, H, E, Alloc>& src) {  // NOLINT
     assert(this != &src);
-    for (auto it = src.begin(), e = src.end(); it != e; ++it) {
+    for (auto it = src.begin(), e = src.end(); it != e;) {
+      auto next = std::next(it);
       if (PolicyTraits::apply(InsertSlot<false>{*this, std::move(*it.slot_)},
                               PolicyTraits::element(it.slot_))
               .second) {
         src.erase_meta_only(it);
       }
+      it = next;
     }
   }
 
@@ -1182,6 +1266,7 @@
   }
 
   node_type extract(const_iterator position) {
+    AssertIsFull(position.inner_.ctrl_);
     auto node =
         CommonAccess::Transfer<node_type>(alloc_ref(), position.inner_.slot_);
     erase_meta_only(position);
@@ -1198,8 +1283,8 @@
 
   void swap(raw_hash_set& that) noexcept(
       IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() &&
-      (!AllocTraits::propagate_on_container_swap::value ||
-       IsNoThrowSwappable<allocator_type>())) {
+      IsNoThrowSwappable<allocator_type>(
+          typename AllocTraits::propagate_on_container_swap{})) {
     using std::swap;
     swap(ctrl_, that.ctrl_);
     swap(slots_, that.slots_);
@@ -1209,12 +1294,8 @@
     swap(hash_ref(), that.hash_ref());
     swap(eq_ref(), that.eq_ref());
     swap(infoz_, that.infoz_);
-    if (AllocTraits::propagate_on_container_swap::value) {
-      swap(alloc_ref(), that.alloc_ref());
-    } else {
-      // If the allocators do not compare equal it is officially undefined
-      // behavior. We choose to do nothing.
-    }
+    SwapAlloc(alloc_ref(), that.alloc_ref(),
+              typename AllocTraits::propagate_on_container_swap{});
   }
 
   void rehash(size_t n) {
@@ -1233,7 +1314,12 @@
     }
   }
 
-  void reserve(size_t n) { rehash(GrowthToLowerboundCapacity(n)); }
+  void reserve(size_t n) {
+    size_t m = GrowthToLowerboundCapacity(n);
+    if (m > capacity_) {
+      resize(NormalizeCapacity(m));
+    }
+  }
 
   // Extension API: support for heterogeneous keys.
   //
@@ -1258,7 +1344,7 @@
   void prefetch(const key_arg<K>& key) const {
     (void)key;
 #if defined(__GNUC__)
-    auto seq = probe(hash_ref()(key));
+    auto seq = probe(ctrl_, hash_ref()(key), capacity_);
     __builtin_prefetch(static_cast<const void*>(ctrl_ + seq.offset()));
     __builtin_prefetch(static_cast<const void*>(slots_ + seq.offset()));
 #endif  // __GNUC__
@@ -1273,7 +1359,7 @@
   // called heterogeneous key support.
   template <class K = key_type>
   iterator find(const key_arg<K>& key, size_t hash) {
-    auto seq = probe(hash);
+    auto seq = probe(ctrl_, hash, capacity_);
     while (true) {
       Group g{ctrl_ + seq.offset()};
       for (int i : g.Match(H2(hash))) {
@@ -1284,6 +1370,7 @@
       }
       if (ABSL_PREDICT_TRUE(g.MatchEmpty())) return end();
       seq.next();
+      assert(seq.index() < capacity_ && "full table!");
     }
   }
   template <class K = key_type>
@@ -1494,7 +1581,7 @@
       if (IsFull(old_ctrl[i])) {
         size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
                                           PolicyTraits::element(old_slots + i));
-        auto target = find_first_non_full(hash);
+        auto target = find_first_non_full(ctrl_, hash, capacity_);
         size_t new_i = target.offset;
         total_probe_length += target.probe_length;
         set_ctrl(new_i, H2(hash));
@@ -1513,7 +1600,7 @@
 
   void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE {
     assert(IsValidCapacity(capacity_));
-    assert(!is_small());
+    assert(!is_small(capacity_));
     // Algorithm:
     // - mark all DELETED slots as EMPTY
     // - mark all FULL slots as DELETED
@@ -1531,15 +1618,14 @@
     //       mark target as FULL
     //       repeat procedure for current slot with moved from element (target)
     ConvertDeletedToEmptyAndFullToDeleted(ctrl_, capacity_);
-    typename std::aligned_storage<sizeof(slot_type), alignof(slot_type)>::type
-        raw;
+    alignas(slot_type) unsigned char raw[sizeof(slot_type)];
     size_t total_probe_length = 0;
     slot_type* slot = reinterpret_cast<slot_type*>(&raw);
     for (size_t i = 0; i != capacity_; ++i) {
       if (!IsDeleted(ctrl_[i])) continue;
       size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
                                         PolicyTraits::element(slots_ + i));
-      auto target = find_first_non_full(hash);
+      auto target = find_first_non_full(ctrl_, hash, capacity_);
       size_t new_i = target.offset;
       total_probe_length += target.probe_length;
 
@@ -1547,7 +1633,8 @@
       // If they do, we don't need to move the object as it falls already in the
       // best probe we can.
       const auto probe_index = [&](size_t pos) {
-        return ((pos - probe(hash).offset()) & capacity_) / Group::kWidth;
+        return ((pos - probe(ctrl_, hash, capacity_).offset()) & capacity_) /
+               Group::kWidth;
       };
 
       // Element doesn't move.
@@ -1591,7 +1678,7 @@
 
   bool has_element(const value_type& elem) const {
     size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, elem);
-    auto seq = probe(hash);
+    auto seq = probe(ctrl_, hash, capacity_);
     while (true) {
       Group g{ctrl_ + seq.offset()};
       for (int i : g.Match(H2(hash))) {
@@ -1606,41 +1693,6 @@
     return false;
   }
 
-  // Probes the raw_hash_set with the probe sequence for hash and returns the
-  // pointer to the first empty or deleted slot.
-  // NOTE: this function must work with tables having both kEmpty and kDelete
-  // in one group. Such tables appears during drop_deletes_without_resize.
-  //
-  // This function is very useful when insertions happen and:
-  // - the input is already a set
-  // - there are enough slots
-  // - the element with the hash is not in the table
-  struct FindInfo {
-    size_t offset;
-    size_t probe_length;
-  };
-  FindInfo find_first_non_full(size_t hash) {
-    auto seq = probe(hash);
-    while (true) {
-      Group g{ctrl_ + seq.offset()};
-      auto mask = g.MatchEmptyOrDeleted();
-      if (mask) {
-#if !defined(NDEBUG)
-        // 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
-        // the group.
-        // TODO(kfm,sbenza): revisit after we do unconditional mixing
-        if (!is_small() && ShouldInsertBackwards(hash, ctrl_)) {
-          return {seq.offset(mask.HighestBitSet()), seq.index()};
-        }
-#endif
-        return {seq.offset(mask.LowestBitSet()), seq.index()};
-      }
-      assert(seq.index() < capacity_ && "full table!");
-      seq.next();
-    }
-  }
-
   // TODO(alkis): Optimize this assuming *this and that don't overlap.
   raw_hash_set& move_assign(raw_hash_set&& that, std::true_type) {
     raw_hash_set tmp(std::move(that));
@@ -1657,7 +1709,7 @@
   template <class K>
   std::pair<size_t, bool> find_or_prepare_insert(const K& key) {
     auto hash = hash_ref()(key);
-    auto seq = probe(hash);
+    auto seq = probe(ctrl_, hash, capacity_);
     while (true) {
       Group g{ctrl_ + seq.offset()};
       for (int i : g.Match(H2(hash))) {
@@ -1668,16 +1720,17 @@
       }
       if (ABSL_PREDICT_TRUE(g.MatchEmpty())) break;
       seq.next();
+      assert(seq.index() < capacity_ && "full table!");
     }
     return {prepare_insert(hash), true};
   }
 
   size_t prepare_insert(size_t hash) ABSL_ATTRIBUTE_NOINLINE {
-    auto target = find_first_non_full(hash);
+    auto target = find_first_non_full(ctrl_, hash, capacity_);
     if (ABSL_PREDICT_FALSE(growth_left() == 0 &&
                            !IsDeleted(ctrl_[target.offset]))) {
       rehash_and_grow_if_necessary();
-      target = find_first_non_full(hash);
+      target = find_first_non_full(ctrl_, hash, capacity_);
     }
     ++size_;
     growth_left() -= IsEmpty(ctrl_[target.offset]);
@@ -1710,10 +1763,6 @@
  private:
   friend struct RawHashSetTestOnlyAccess;
 
-  probe_seq<Group::kWidth> probe(size_t hash) const {
-    return probe_seq<Group::kWidth>(H1(hash, ctrl_), capacity_);
-  }
-
   // Reset all ctrl bytes back to kEmpty, except the sentinel.
   void reset_ctrl() {
     std::memset(ctrl_, kEmpty, capacity_ + Group::kWidth);
@@ -1743,22 +1792,6 @@
 
   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>(); }
   const hasher& hash_ref() const { return settings_.template get<1>(); }
   key_equal& eq_ref() { return settings_.template get<2>(); }
@@ -1781,6 +1814,17 @@
       settings_{0, hasher{}, key_equal{}, allocator_type{}};
 };
 
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+template <typename P, typename H, typename E, typename A, typename Predicate>
+void EraseIf(Predicate pred, raw_hash_set<P, H, E, A>* c) {
+  for (auto it = c->begin(), last = c->end(); it != last;) {
+    auto copy_it = it++;
+    if (pred(*copy_it)) {
+      c->erase(copy_it);
+    }
+  }
+}
+
 namespace hashtable_debug_internal {
 template <typename Set>
 struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
@@ -1791,7 +1835,7 @@
                              const typename Set::key_type& key) {
     size_t num_probes = 0;
     size_t hash = set.hash_ref()(key);
-    auto seq = set.probe(hash);
+    auto seq = probe(set.ctrl_, hash, set.capacity_);
     while (true) {
       container_internal::Group g{set.ctrl_ + seq.offset()};
       for (int i : g.Match(container_internal::H2(hash))) {
@@ -1842,6 +1886,7 @@
 
 }  // namespace hashtable_debug_internal
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
diff --git a/absl/container/internal/raw_hash_set_allocator_test.cc b/absl/container/internal/raw_hash_set_allocator_test.cc
index a5eff0b..e73f53f 100644
--- a/absl/container/internal/raw_hash_set_allocator_test.cc
+++ b/absl/container/internal/raw_hash_set_allocator_test.cc
@@ -20,6 +20,7 @@
 #include "absl/container/internal/tracked.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
@@ -423,6 +424,82 @@
   EXPECT_EQ(0, it->num_copies());
 }
 
+// This allocator is similar to std::pmr::polymorphic_allocator.
+// Note the disabled assignment.
+template <class T>
+class PAlloc {
+  template <class>
+  friend class PAlloc;
+
+ public:
+  // types
+  using value_type = T;
+
+  // traits
+  using propagate_on_container_swap = std::false_type;
+
+  PAlloc() noexcept = default;
+  explicit PAlloc(size_t id) noexcept : id_(id) {}
+  PAlloc(const PAlloc&) noexcept = default;
+  PAlloc& operator=(const PAlloc&) noexcept = delete;
+
+  template <class U>
+  PAlloc(const PAlloc<U>& that) noexcept : id_(that.id_) {}  // NOLINT
+
+  template <class U>
+  struct rebind {
+    using other = PAlloc<U>;
+  };
+
+  constexpr PAlloc select_on_container_copy_construction() const { return {}; }
+
+  // public member functions
+  T* allocate(size_t) { return new T; }
+  void deallocate(T* p, size_t) { delete p; }
+
+  friend bool operator==(const PAlloc& a, const PAlloc& b) {
+    return a.id_ == b.id_;
+  }
+  friend bool operator!=(const PAlloc& a, const PAlloc& b) { return !(a == b); }
+
+ private:
+  size_t id_ = std::numeric_limits<size_t>::max();
+};
+
+// This doesn't compile with GCC 5.4 and 5.5 due to a bug in noexcept handing.
+#if !defined(__GNUC__) || __GNUC__ != 5 || (__GNUC_MINOR__ != 4 && \
+    __GNUC_MINOR__ != 5)
+TEST(NoPropagateOn, Swap) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(PA{2});
+  swap(t1, t2);
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA(2));
+}
+#endif
+
+TEST(NoPropagateOn, CopyConstruct) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(t1);
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA());
+}
+
+TEST(NoPropagateOn, Assignment) {
+  using PA = PAlloc<char>;
+  using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+  Table t1(PA{1}), t2(PA{2});
+  t1 = t2;
+  EXPECT_EQ(t1.get_allocator(), PA(1));
+  EXPECT_EQ(t2.get_allocator(), PA(2));
+}
+
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/raw_hash_set_benchmark.cc b/absl/container/internal/raw_hash_set_benchmark.cc
new file mode 100644
index 0000000..f9be2c5
--- /dev/null
+++ b/absl/container/internal/raw_hash_set_benchmark.cc
@@ -0,0 +1,396 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/container/internal/raw_hash_set.h"
+
+#include <numeric>
+#include <random>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/container/internal/hash_function_defaults.h"
+#include "absl/strings/str_format.h"
+#include "benchmark/benchmark.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+struct RawHashSetTestOnlyAccess {
+  template <typename C>
+  static auto GetSlots(const C& c) -> decltype(c.slots_) {
+    return c.slots_;
+  }
+};
+
+namespace {
+
+struct IntPolicy {
+  using slot_type = int64_t;
+  using key_type = int64_t;
+  using init_type = int64_t;
+
+  static void construct(void*, int64_t* slot, int64_t v) { *slot = v; }
+  static void destroy(void*, int64_t*) {}
+  static void transfer(void*, int64_t* new_slot, int64_t* old_slot) {
+    *new_slot = *old_slot;
+  }
+
+  static int64_t& element(slot_type* slot) { return *slot; }
+
+  template <class F>
+  static auto apply(F&& f, int64_t x) -> decltype(std::forward<F>(f)(x, x)) {
+    return std::forward<F>(f)(x, x);
+  }
+};
+
+class StringPolicy {
+  template <class F, class K, class V,
+            class = typename std::enable_if<
+                std::is_convertible<const K&, absl::string_view>::value>::type>
+  decltype(std::declval<F>()(
+      std::declval<const absl::string_view&>(), std::piecewise_construct,
+      std::declval<std::tuple<K>>(),
+      std::declval<V>())) static apply_impl(F&& f,
+                                            std::pair<std::tuple<K>, V> p) {
+    const absl::string_view& key = std::get<0>(p.first);
+    return std::forward<F>(f)(key, std::piecewise_construct, std::move(p.first),
+                              std::move(p.second));
+  }
+
+ public:
+  struct slot_type {
+    struct ctor {};
+
+    template <class... Ts>
+    slot_type(ctor, Ts&&... ts) : pair(std::forward<Ts>(ts)...) {}
+
+    std::pair<std::string, std::string> pair;
+  };
+
+  using key_type = std::string;
+  using init_type = std::pair<std::string, std::string>;
+
+  template <class allocator_type, class... Args>
+  static void construct(allocator_type* alloc, slot_type* slot, Args... args) {
+    std::allocator_traits<allocator_type>::construct(
+        *alloc, slot, typename slot_type::ctor(), std::forward<Args>(args)...);
+  }
+
+  template <class allocator_type>
+  static void destroy(allocator_type* alloc, slot_type* slot) {
+    std::allocator_traits<allocator_type>::destroy(*alloc, slot);
+  }
+
+  template <class allocator_type>
+  static void transfer(allocator_type* alloc, slot_type* new_slot,
+                       slot_type* old_slot) {
+    construct(alloc, new_slot, std::move(old_slot->pair));
+    destroy(alloc, old_slot);
+  }
+
+  static std::pair<std::string, std::string>& element(slot_type* slot) {
+    return slot->pair;
+  }
+
+  template <class F, class... Args>
+  static auto apply(F&& f, Args&&... args)
+      -> decltype(apply_impl(std::forward<F>(f),
+                             PairArgs(std::forward<Args>(args)...))) {
+    return apply_impl(std::forward<F>(f),
+                      PairArgs(std::forward<Args>(args)...));
+  }
+};
+
+struct StringHash : container_internal::hash_default_hash<absl::string_view> {
+  using is_transparent = void;
+};
+struct StringEq : std::equal_to<absl::string_view> {
+  using is_transparent = void;
+};
+
+struct StringTable
+    : raw_hash_set<StringPolicy, StringHash, StringEq, std::allocator<int>> {
+  using Base = typename StringTable::raw_hash_set;
+  StringTable() {}
+  using Base::Base;
+};
+
+struct IntTable
+    : raw_hash_set<IntPolicy, container_internal::hash_default_hash<int64_t>,
+                   std::equal_to<int64_t>, std::allocator<int64_t>> {
+  using Base = typename IntTable::raw_hash_set;
+  IntTable() {}
+  using Base::Base;
+};
+
+struct string_generator {
+  template <class RNG>
+  std::string operator()(RNG& rng) const {
+    std::string res;
+    res.resize(12);
+    std::uniform_int_distribution<uint32_t> printable_ascii(0x20, 0x7E);
+    std::generate(res.begin(), res.end(), [&] { return printable_ascii(rng); });
+    return res;
+  }
+
+  size_t size;
+};
+
+// Model a cache in steady state.
+//
+// On a table of size N, keep deleting the LRU entry and add a random one.
+void BM_CacheInSteadyState(benchmark::State& state) {
+  std::random_device rd;
+  std::mt19937 rng(rd());
+  string_generator gen{12};
+  StringTable t;
+  std::deque<std::string> keys;
+  while (t.size() < state.range(0)) {
+    auto x = t.emplace(gen(rng), gen(rng));
+    if (x.second) keys.push_back(x.first->first);
+  }
+  ABSL_RAW_CHECK(state.range(0) >= 10, "");
+  while (state.KeepRunning()) {
+    // Some cache hits.
+    std::deque<std::string>::const_iterator it;
+    for (int i = 0; i != 90; ++i) {
+      if (i % 10 == 0) it = keys.end();
+      ::benchmark::DoNotOptimize(t.find(*--it));
+    }
+    // Some cache misses.
+    for (int i = 0; i != 10; ++i) ::benchmark::DoNotOptimize(t.find(gen(rng)));
+    ABSL_RAW_CHECK(t.erase(keys.front()), keys.front().c_str());
+    keys.pop_front();
+    while (true) {
+      auto x = t.emplace(gen(rng), gen(rng));
+      if (x.second) {
+        keys.push_back(x.first->first);
+        break;
+      }
+    }
+  }
+  state.SetItemsProcessed(state.iterations());
+  state.SetLabel(absl::StrFormat("load_factor=%.2f", t.load_factor()));
+}
+
+template <typename Benchmark>
+void CacheInSteadyStateArgs(Benchmark* bm) {
+  // The default.
+  const float max_load_factor = 0.875;
+  // When the cache is at the steady state, the probe sequence will equal
+  // capacity if there is no reclamation of deleted slots. Pick a number large
+  // enough to make the benchmark slow for that case.
+  const size_t capacity = 1 << 10;
+
+  // Check N data points to cover load factors in [0.4, 0.8).
+  const size_t kNumPoints = 10;
+  for (size_t i = 0; i != kNumPoints; ++i)
+    bm->Arg(std::ceil(
+        capacity * (max_load_factor + i * max_load_factor / kNumPoints) / 2));
+}
+BENCHMARK(BM_CacheInSteadyState)->Apply(CacheInSteadyStateArgs);
+
+void BM_EndComparison(benchmark::State& state) {
+  std::random_device rd;
+  std::mt19937 rng(rd());
+  string_generator gen{12};
+  StringTable t;
+  while (t.size() < state.range(0)) {
+    t.emplace(gen(rng), gen(rng));
+  }
+
+  for (auto _ : state) {
+    for (auto it = t.begin(); it != t.end(); ++it) {
+      benchmark::DoNotOptimize(it);
+      benchmark::DoNotOptimize(t);
+      benchmark::DoNotOptimize(it != t.end());
+    }
+  }
+}
+BENCHMARK(BM_EndComparison)->Arg(400);
+
+void BM_CopyCtor(benchmark::State& state) {
+  std::random_device rd;
+  std::mt19937 rng(rd());
+  IntTable t;
+  std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
+
+  while (t.size() < state.range(0)) {
+    t.emplace(dist(rng));
+  }
+
+  for (auto _ : state) {
+    IntTable t2 = t;
+    benchmark::DoNotOptimize(t2);
+  }
+}
+BENCHMARK(BM_CopyCtor)->Range(128, 4096);
+
+void BM_CopyAssign(benchmark::State& state) {
+  std::random_device rd;
+  std::mt19937 rng(rd());
+  IntTable t;
+  std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
+  while (t.size() < state.range(0)) {
+    t.emplace(dist(rng));
+  }
+
+  IntTable t2;
+  for (auto _ : state) {
+    t2 = t;
+    benchmark::DoNotOptimize(t2);
+  }
+}
+BENCHMARK(BM_CopyAssign)->Range(128, 4096);
+
+void BM_NoOpReserveIntTable(benchmark::State& state) {
+  IntTable t;
+  t.reserve(100000);
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(t);
+    t.reserve(100000);
+  }
+}
+BENCHMARK(BM_NoOpReserveIntTable);
+
+void BM_NoOpReserveStringTable(benchmark::State& state) {
+  StringTable t;
+  t.reserve(100000);
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(t);
+    t.reserve(100000);
+  }
+}
+BENCHMARK(BM_NoOpReserveStringTable);
+
+void BM_ReserveIntTable(benchmark::State& state) {
+  int reserve_size = state.range(0);
+  for (auto _ : state) {
+    state.PauseTiming();
+    IntTable t;
+    state.ResumeTiming();
+    benchmark::DoNotOptimize(t);
+    t.reserve(reserve_size);
+  }
+}
+BENCHMARK(BM_ReserveIntTable)->Range(128, 4096);
+
+void BM_ReserveStringTable(benchmark::State& state) {
+  int reserve_size = state.range(0);
+  for (auto _ : state) {
+    state.PauseTiming();
+    StringTable t;
+    state.ResumeTiming();
+    benchmark::DoNotOptimize(t);
+    t.reserve(reserve_size);
+  }
+}
+BENCHMARK(BM_ReserveStringTable)->Range(128, 4096);
+
+void BM_Group_Match(benchmark::State& state) {
+  std::array<ctrl_t, Group::kWidth> group;
+  std::iota(group.begin(), group.end(), -4);
+  Group g{group.data()};
+  h2_t h = 1;
+  for (auto _ : state) {
+    ::benchmark::DoNotOptimize(h);
+    ::benchmark::DoNotOptimize(g.Match(h));
+  }
+}
+BENCHMARK(BM_Group_Match);
+
+void BM_Group_MatchEmpty(benchmark::State& state) {
+  std::array<ctrl_t, Group::kWidth> group;
+  std::iota(group.begin(), group.end(), -4);
+  Group g{group.data()};
+  for (auto _ : state) ::benchmark::DoNotOptimize(g.MatchEmpty());
+}
+BENCHMARK(BM_Group_MatchEmpty);
+
+void BM_Group_MatchEmptyOrDeleted(benchmark::State& state) {
+  std::array<ctrl_t, Group::kWidth> group;
+  std::iota(group.begin(), group.end(), -4);
+  Group g{group.data()};
+  for (auto _ : state) ::benchmark::DoNotOptimize(g.MatchEmptyOrDeleted());
+}
+BENCHMARK(BM_Group_MatchEmptyOrDeleted);
+
+void BM_Group_CountLeadingEmptyOrDeleted(benchmark::State& state) {
+  std::array<ctrl_t, Group::kWidth> group;
+  std::iota(group.begin(), group.end(), -2);
+  Group g{group.data()};
+  for (auto _ : state)
+    ::benchmark::DoNotOptimize(g.CountLeadingEmptyOrDeleted());
+}
+BENCHMARK(BM_Group_CountLeadingEmptyOrDeleted);
+
+void BM_Group_MatchFirstEmptyOrDeleted(benchmark::State& state) {
+  std::array<ctrl_t, Group::kWidth> group;
+  std::iota(group.begin(), group.end(), -2);
+  Group g{group.data()};
+  for (auto _ : state) ::benchmark::DoNotOptimize(*g.MatchEmptyOrDeleted());
+}
+BENCHMARK(BM_Group_MatchFirstEmptyOrDeleted);
+
+void BM_DropDeletes(benchmark::State& state) {
+  constexpr size_t capacity = (1 << 20) - 1;
+  std::vector<ctrl_t> ctrl(capacity + 1 + Group::kWidth);
+  ctrl[capacity] = kSentinel;
+  std::vector<ctrl_t> pattern = {kEmpty, 2, kDeleted, 2, kEmpty, 1, kDeleted};
+  for (size_t i = 0; i != capacity; ++i) {
+    ctrl[i] = pattern[i % pattern.size()];
+  }
+  while (state.KeepRunning()) {
+    state.PauseTiming();
+    std::vector<ctrl_t> ctrl_copy = ctrl;
+    state.ResumeTiming();
+    ConvertDeletedToEmptyAndFullToDeleted(ctrl_copy.data(), capacity);
+    ::benchmark::DoNotOptimize(ctrl_copy[capacity]);
+  }
+}
+BENCHMARK(BM_DropDeletes);
+
+}  // namespace
+}  // namespace container_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+// These methods are here to make it easy to examine the assembly for targeted
+// parts of the API.
+auto CodegenAbslRawHashSetInt64Find(absl::container_internal::IntTable* table,
+                                    int64_t key) -> decltype(table->find(key)) {
+  return table->find(key);
+}
+
+bool CodegenAbslRawHashSetInt64FindNeEnd(
+    absl::container_internal::IntTable* table, int64_t key) {
+  return table->find(key) != table->end();
+}
+
+bool CodegenAbslRawHashSetInt64Contains(
+    absl::container_internal::IntTable* table, int64_t key) {
+  return table->contains(key);
+}
+
+void CodegenAbslRawHashSetInt64Iterate(
+    absl::container_internal::IntTable* table) {
+  for (auto x : *table) benchmark::DoNotOptimize(x);
+}
+
+int odr =
+    (::benchmark::DoNotOptimize(std::make_tuple(
+         &CodegenAbslRawHashSetInt64Find, &CodegenAbslRawHashSetInt64FindNeEnd,
+         &CodegenAbslRawHashSetInt64Contains,
+         &CodegenAbslRawHashSetInt64Iterate)),
+     1);
diff --git a/absl/container/internal/raw_hash_set_probe_benchmark.cc b/absl/container/internal/raw_hash_set_probe_benchmark.cc
new file mode 100644
index 0000000..7169a2e
--- /dev/null
+++ b/absl/container/internal/raw_hash_set_probe_benchmark.cc
@@ -0,0 +1,590 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// Generates probe length statistics for many combinations of key types and key
+// distributions, all using the default hash function for swisstable.
+
+#include <memory>
+#include <regex>  // NOLINT
+#include <vector>
+
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/internal/hash_function_defaults.h"
+#include "absl/container/internal/hashtable_debug.h"
+#include "absl/container/internal/raw_hash_set.h"
+#include "absl/random/distributions.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+
+namespace {
+
+enum class OutputStyle { kRegular, kBenchmark };
+
+// The --benchmark command line flag.
+// This is populated from main().
+// When run in "benchmark" mode, we have different output. This allows
+// A/B comparisons with tools like `benchy`.
+absl::string_view benchmarks;
+
+OutputStyle output() {
+  return !benchmarks.empty() ? OutputStyle::kBenchmark : OutputStyle::kRegular;
+}
+
+template <class T>
+struct Policy {
+  using slot_type = T;
+  using key_type = T;
+  using init_type = T;
+
+  template <class allocator_type, class Arg>
+  static void construct(allocator_type* alloc, slot_type* slot,
+                        const Arg& arg) {
+    std::allocator_traits<allocator_type>::construct(*alloc, slot, arg);
+  }
+
+  template <class allocator_type>
+  static void destroy(allocator_type* alloc, slot_type* slot) {
+    std::allocator_traits<allocator_type>::destroy(*alloc, slot);
+  }
+
+  static slot_type& element(slot_type* slot) { return *slot; }
+
+  template <class F, class... Args>
+  static auto apply(F&& f, const slot_type& arg)
+      -> decltype(std::forward<F>(f)(arg, arg)) {
+    return std::forward<F>(f)(arg, arg);
+  }
+};
+
+absl::BitGen& GlobalBitGen() {
+  static auto* value = new absl::BitGen;
+  return *value;
+}
+
+// Keeps a pool of allocations and randomly gives one out.
+// This introduces more randomization to the addresses given to swisstable and
+// should help smooth out this factor from probe length calculation.
+template <class T>
+class RandomizedAllocator {
+ public:
+  using value_type = T;
+
+  RandomizedAllocator() = default;
+  template <typename U>
+  RandomizedAllocator(RandomizedAllocator<U>) {}  // NOLINT
+
+  static T* allocate(size_t n) {
+    auto& pointers = GetPointers(n);
+    // Fill the pool
+    while (pointers.size() < kRandomPool) {
+      pointers.push_back(std::allocator<T>{}.allocate(n));
+    }
+
+    // Choose a random one.
+    size_t i = absl::Uniform<size_t>(GlobalBitGen(), 0, pointers.size());
+    T* result = pointers[i];
+    pointers[i] = pointers.back();
+    pointers.pop_back();
+    return result;
+  }
+
+  static void deallocate(T* p, size_t n) {
+    // Just put it back on the pool. No need to release the memory.
+    GetPointers(n).push_back(p);
+  }
+
+ private:
+  // We keep at least kRandomPool allocations for each size.
+  static constexpr size_t kRandomPool = 20;
+
+  static std::vector<T*>& GetPointers(size_t n) {
+    static auto* m = new absl::flat_hash_map<size_t, std::vector<T*>>();
+    return (*m)[n];
+  }
+};
+
+template <class T>
+struct DefaultHash {
+  using type = absl::container_internal::hash_default_hash<T>;
+};
+
+template <class T>
+using DefaultHashT = typename DefaultHash<T>::type;
+
+template <class T>
+struct Table : absl::container_internal::raw_hash_set<
+                   Policy<T>, DefaultHashT<T>,
+                   absl::container_internal::hash_default_eq<T>,
+                   RandomizedAllocator<T>> {};
+
+struct LoadSizes {
+  size_t min_load;
+  size_t max_load;
+};
+
+LoadSizes GetMinMaxLoadSizes() {
+  static const auto sizes = [] {
+    Table<int> t;
+
+    // First, fill enough to have a good distribution.
+    constexpr size_t kMinSize = 10000;
+    while (t.size() < kMinSize) t.insert(t.size());
+
+    const auto reach_min_load_factor = [&] {
+      const double lf = t.load_factor();
+      while (lf <= t.load_factor()) t.insert(t.size());
+    };
+
+    // Then, insert until we reach min load factor.
+    reach_min_load_factor();
+    const size_t min_load_size = t.size();
+
+    // Keep going until we hit min load factor again, then go back one.
+    t.insert(t.size());
+    reach_min_load_factor();
+
+    return LoadSizes{min_load_size, t.size() - 1};
+  }();
+  return sizes;
+}
+
+struct Ratios {
+  double min_load;
+  double avg_load;
+  double max_load;
+};
+
+// See absl/container/internal/hashtable_debug.h for details on
+// probe length calculation.
+template <class ElemFn>
+Ratios CollectMeanProbeLengths() {
+  const auto min_max_sizes = GetMinMaxLoadSizes();
+
+  ElemFn elem;
+  using Key = decltype(elem());
+  Table<Key> t;
+
+  Ratios result;
+  while (t.size() < min_max_sizes.min_load) t.insert(elem());
+  result.min_load =
+      absl::container_internal::GetHashtableDebugProbeSummary(t).mean;
+
+  while (t.size() < (min_max_sizes.min_load + min_max_sizes.max_load) / 2)
+    t.insert(elem());
+  result.avg_load =
+      absl::container_internal::GetHashtableDebugProbeSummary(t).mean;
+
+  while (t.size() < min_max_sizes.max_load) t.insert(elem());
+  result.max_load =
+      absl::container_internal::GetHashtableDebugProbeSummary(t).mean;
+
+  return result;
+}
+
+template <int Align>
+uintptr_t PointerForAlignment() {
+  alignas(Align) static constexpr uintptr_t kInitPointer = 0;
+  return reinterpret_cast<uintptr_t>(&kInitPointer);
+}
+
+// This incomplete type is used for testing hash of pointers of different
+// alignments.
+// NOTE: We are generating invalid pointer values on the fly with
+// reinterpret_cast. There are not "safely derived" pointers so using them is
+// technically UB. It is unlikely to be a problem, though.
+template <int Align>
+struct Ptr;
+
+template <int Align>
+Ptr<Align>* MakePtr(uintptr_t v) {
+  if (sizeof(v) == 8) {
+    constexpr int kCopyBits = 16;
+    // Ensure high bits are all the same.
+    v = static_cast<uintptr_t>(static_cast<intptr_t>(v << kCopyBits) >>
+                               kCopyBits);
+  }
+  return reinterpret_cast<Ptr<Align>*>(v);
+}
+
+struct IntIdentity {
+  uint64_t i;
+  friend bool operator==(IntIdentity a, IntIdentity b) { return a.i == b.i; }
+  IntIdentity operator++(int) { return IntIdentity{i++}; }
+};
+
+template <int Align>
+struct PtrIdentity {
+  explicit PtrIdentity(uintptr_t val = PointerForAlignment<Align>()) : i(val) {}
+  uintptr_t i;
+  friend bool operator==(PtrIdentity a, PtrIdentity b) { return a.i == b.i; }
+  PtrIdentity operator++(int) {
+    PtrIdentity p(i);
+    i += Align;
+    return p;
+  }
+};
+
+constexpr char kStringFormat[] = "/path/to/file/name-%07d-of-9999999.txt";
+
+template <bool small>
+struct String {
+  std::string value;
+  static std::string Make(uint32_t v) {
+    return {small ? absl::StrCat(v) : absl::StrFormat(kStringFormat, v)};
+  }
+};
+
+template <>
+struct DefaultHash<IntIdentity> {
+  struct type {
+    size_t operator()(IntIdentity t) const { return t.i; }
+  };
+};
+
+template <int Align>
+struct DefaultHash<PtrIdentity<Align>> {
+  struct type {
+    size_t operator()(PtrIdentity<Align> t) const { return t.i; }
+  };
+};
+
+template <class T>
+struct Sequential {
+  T operator()() const { return current++; }
+  mutable T current{};
+};
+
+template <int Align>
+struct Sequential<Ptr<Align>*> {
+  Ptr<Align>* operator()() const {
+    auto* result = MakePtr<Align>(current);
+    current += Align;
+    return result;
+  }
+  mutable uintptr_t current = PointerForAlignment<Align>();
+};
+
+
+template <bool small>
+struct Sequential<String<small>> {
+  std::string operator()() const { return String<small>::Make(current++); }
+  mutable uint32_t current = 0;
+};
+
+template <class T, class U>
+struct Sequential<std::pair<T, U>> {
+  mutable Sequential<T> tseq;
+  mutable Sequential<U> useq;
+
+  using RealT = decltype(tseq());
+  using RealU = decltype(useq());
+
+  mutable std::vector<RealT> ts;
+  mutable std::vector<RealU> us;
+  mutable size_t ti = 0, ui = 0;
+
+  std::pair<RealT, RealU> operator()() const {
+    std::pair<RealT, RealU> value{get_t(), get_u()};
+    if (ti == 0) {
+      ti = ui + 1;
+      ui = 0;
+    } else {
+      --ti;
+      ++ui;
+    }
+    return value;
+  }
+
+  RealT get_t() const {
+    while (ti >= ts.size()) ts.push_back(tseq());
+    return ts[ti];
+  }
+
+  RealU get_u() const {
+    while (ui >= us.size()) us.push_back(useq());
+    return us[ui];
+  }
+};
+
+template <class T, int percent_skip>
+struct AlmostSequential {
+  mutable Sequential<T> current;
+
+  auto operator()() const -> decltype(current()) {
+    while (absl::Uniform(GlobalBitGen(), 0.0, 1.0) <= percent_skip / 100.)
+      current();
+    return current();
+  }
+};
+
+struct Uniform {
+  template <typename T>
+  T operator()(T) const {
+    return absl::Uniform<T>(absl::IntervalClosed, GlobalBitGen(), T{0}, ~T{0});
+  }
+};
+
+struct Gaussian {
+  template <typename T>
+  T operator()(T) const {
+    double d;
+    do {
+      d = absl::Gaussian<double>(GlobalBitGen(), 1e6, 1e4);
+    } while (d <= 0 || d > std::numeric_limits<T>::max() / 2);
+    return static_cast<T>(d);
+  }
+};
+
+struct Zipf {
+  template <typename T>
+  T operator()(T) const {
+    return absl::Zipf<T>(GlobalBitGen(), std::numeric_limits<T>::max(), 1.6);
+  }
+};
+
+template <class T, class Dist>
+struct Random {
+  T operator()() const { return Dist{}(T{}); }
+};
+
+template <class Dist, int Align>
+struct Random<Ptr<Align>*, Dist> {
+  Ptr<Align>* operator()() const {
+    return MakePtr<Align>(Random<uintptr_t, Dist>{}() * Align);
+  }
+};
+
+template <class Dist>
+struct Random<IntIdentity, Dist> {
+  IntIdentity operator()() const {
+    return IntIdentity{Random<uint64_t, Dist>{}()};
+  }
+};
+
+template <class Dist, int Align>
+struct Random<PtrIdentity<Align>, Dist> {
+  PtrIdentity<Align> operator()() const {
+    return PtrIdentity<Align>{Random<uintptr_t, Dist>{}() * Align};
+  }
+};
+
+template <class Dist, bool small>
+struct Random<String<small>, Dist> {
+  std::string operator()() const {
+    return String<small>::Make(Random<uint32_t, Dist>{}());
+  }
+};
+
+template <class T, class U, class Dist>
+struct Random<std::pair<T, U>, Dist> {
+  auto operator()() const
+      -> decltype(std::make_pair(Random<T, Dist>{}(), Random<U, Dist>{}())) {
+    return std::make_pair(Random<T, Dist>{}(), Random<U, Dist>{}());
+  }
+};
+
+template <typename>
+std::string Name();
+
+std::string Name(uint32_t*) { return "u32"; }
+std::string Name(uint64_t*) { return "u64"; }
+std::string Name(IntIdentity*) { return "IntIdentity"; }
+
+template <int Align>
+std::string Name(Ptr<Align>**) {
+  return absl::StrCat("Ptr", Align);
+}
+
+template <int Align>
+std::string Name(PtrIdentity<Align>*) {
+  return absl::StrCat("PtrIdentity", Align);
+}
+
+template <bool small>
+std::string Name(String<small>*) {
+  return small ? "StrS" : "StrL";
+}
+
+template <class T, class U>
+std::string Name(std::pair<T, U>*) {
+  if (output() == OutputStyle::kBenchmark)
+    return absl::StrCat("P_", Name<T>(), "_", Name<U>());
+  return absl::StrCat("P<", Name<T>(), ",", Name<U>(), ">");
+}
+
+template <class T>
+std::string Name(Sequential<T>*) {
+  return "Sequential";
+}
+
+template <class T, int P>
+std::string Name(AlmostSequential<T, P>*) {
+  return absl::StrCat("AlmostSeq_", P);
+}
+
+template <class T>
+std::string Name(Random<T, Uniform>*) {
+  return "UnifRand";
+}
+
+template <class T>
+std::string Name(Random<T, Gaussian>*) {
+  return "GausRand";
+}
+
+template <class T>
+std::string Name(Random<T, Zipf>*) {
+  return "ZipfRand";
+}
+
+template <typename T>
+std::string Name() {
+  return Name(static_cast<T*>(nullptr));
+}
+
+constexpr int kNameWidth = 15;
+constexpr int kDistWidth = 16;
+
+bool CanRunBenchmark(absl::string_view name) {
+  static std::regex* const filter = []() -> std::regex* {
+    return benchmarks.empty() || benchmarks == "all"
+               ? nullptr
+               : new std::regex(std::string(benchmarks));
+  }();
+  return filter == nullptr || std::regex_search(std::string(name), *filter);
+}
+
+struct Result {
+  std::string name;
+  std::string dist_name;
+  Ratios ratios;
+};
+
+template <typename T, typename Dist>
+void RunForTypeAndDistribution(std::vector<Result>& results) {
+  std::string name = absl::StrCat(Name<T>(), "/", Name<Dist>());
+  // We have to check against all three names (min/avg/max) before we run it.
+  // If any of them is enabled, we run it.
+  if (!CanRunBenchmark(absl::StrCat(name, "/min")) &&
+      !CanRunBenchmark(absl::StrCat(name, "/avg")) &&
+      !CanRunBenchmark(absl::StrCat(name, "/max"))) {
+    return;
+  }
+  results.push_back({Name<T>(), Name<Dist>(), CollectMeanProbeLengths<Dist>()});
+}
+
+template <class T>
+void RunForType(std::vector<Result>& results) {
+  RunForTypeAndDistribution<T, Sequential<T>>(results);
+  RunForTypeAndDistribution<T, AlmostSequential<T, 20>>(results);
+  RunForTypeAndDistribution<T, AlmostSequential<T, 50>>(results);
+  RunForTypeAndDistribution<T, Random<T, Uniform>>(results);
+#ifdef NDEBUG
+  // Disable these in non-opt mode because they take too long.
+  RunForTypeAndDistribution<T, Random<T, Gaussian>>(results);
+  RunForTypeAndDistribution<T, Random<T, Zipf>>(results);
+#endif  // NDEBUG
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  // Parse the benchmark flags. Ignore all of them except the regex pattern.
+  for (int i = 1; i < argc; ++i) {
+    absl::string_view arg = argv[i];
+    const auto next = [&] { return argv[std::min(i + 1, argc - 1)]; };
+
+    if (absl::ConsumePrefix(&arg, "--benchmark_filter")) {
+      if (arg == "") {
+        // --benchmark_filter X
+        benchmarks = next();
+      } else if (absl::ConsumePrefix(&arg, "=")) {
+        // --benchmark_filter=X
+        benchmarks = arg;
+      }
+    }
+
+    // Any --benchmark flag turns on the mode.
+    if (absl::ConsumePrefix(&arg, "--benchmark")) {
+      if (benchmarks.empty()) benchmarks="all";
+    }
+  }
+
+  std::vector<Result> results;
+  RunForType<uint64_t>(results);
+  RunForType<IntIdentity>(results);
+  RunForType<Ptr<8>*>(results);
+  RunForType<Ptr<16>*>(results);
+  RunForType<Ptr<32>*>(results);
+  RunForType<Ptr<64>*>(results);
+  RunForType<PtrIdentity<8>>(results);
+  RunForType<PtrIdentity<16>>(results);
+  RunForType<PtrIdentity<32>>(results);
+  RunForType<PtrIdentity<64>>(results);
+  RunForType<std::pair<uint32_t, uint32_t>>(results);
+  RunForType<String<true>>(results);
+  RunForType<String<false>>(results);
+  RunForType<std::pair<uint64_t, String<true>>>(results);
+  RunForType<std::pair<String<true>, uint64_t>>(results);
+  RunForType<std::pair<uint64_t, String<false>>>(results);
+  RunForType<std::pair<String<false>, uint64_t>>(results);
+
+  switch (output()) {
+    case OutputStyle::kRegular:
+      absl::PrintF("%-*s%-*s       Min       Avg       Max\n%s\n", kNameWidth,
+                   "Type", kDistWidth, "Distribution",
+                   std::string(kNameWidth + kDistWidth + 10 * 3, '-'));
+      for (const auto& result : results) {
+        absl::PrintF("%-*s%-*s  %8.4f  %8.4f  %8.4f\n", kNameWidth, result.name,
+                     kDistWidth, result.dist_name, result.ratios.min_load,
+                     result.ratios.avg_load, result.ratios.max_load);
+      }
+      break;
+    case OutputStyle::kBenchmark: {
+      absl::PrintF("{\n");
+      absl::PrintF("  \"benchmarks\": [\n");
+      absl::string_view comma;
+      for (const auto& result : results) {
+        auto print = [&](absl::string_view stat, double Ratios::*val) {
+          std::string name =
+              absl::StrCat(result.name, "/", result.dist_name, "/", stat);
+          // Check the regex again. We might had have enabled only one of the
+          // stats for the benchmark.
+          if (!CanRunBenchmark(name)) return;
+          absl::PrintF("    %s{\n", comma);
+          absl::PrintF("      \"cpu_time\": %f,\n", 1e9 * result.ratios.*val);
+          absl::PrintF("      \"real_time\": %f,\n", 1e9 * result.ratios.*val);
+          absl::PrintF("      \"iterations\": 1,\n");
+          absl::PrintF("      \"name\": \"%s\",\n", name);
+          absl::PrintF("      \"time_unit\": \"ns\"\n");
+          absl::PrintF("    }\n");
+          comma = ",";
+        };
+        print("min", &Ratios::min_load);
+        print("avg", &Ratios::avg_load);
+        print("max", &Ratios::max_load);
+      }
+      absl::PrintF("  ],\n");
+      absl::PrintF("  \"context\": {\n");
+      absl::PrintF("  }\n");
+      absl::PrintF("}\n");
+      break;
+    }
+  }
+
+  return 0;
+}
diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc
index ed4ca8c..0fba46f 100644
--- a/absl/container/internal/raw_hash_set_test.cc
+++ b/absl/container/internal/raw_hash_set_test.cc
@@ -26,6 +26,7 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/cycleclock.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/container/internal/container_memory.h"
@@ -35,6 +36,7 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 struct RawHashSetTestOnlyAccess {
@@ -248,25 +250,43 @@
   }
 }
 
-struct IntPolicy {
-  using slot_type = int64_t;
-  using key_type = int64_t;
-  using init_type = int64_t;
+template <class T>
+struct ValuePolicy {
+  using slot_type = T;
+  using key_type = T;
+  using init_type = T;
 
-  static void construct(void*, int64_t* slot, int64_t v) { *slot = v; }
-  static void destroy(void*, int64_t*) {}
-  static void transfer(void*, int64_t* new_slot, int64_t* old_slot) {
-    *new_slot = *old_slot;
+  template <class Allocator, class... Args>
+  static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
+    absl::allocator_traits<Allocator>::construct(*alloc, slot,
+                                                 std::forward<Args>(args)...);
   }
 
-  static int64_t& element(slot_type* slot) { return *slot; }
+  template <class Allocator>
+  static void destroy(Allocator* alloc, slot_type* slot) {
+    absl::allocator_traits<Allocator>::destroy(*alloc, slot);
+  }
 
-  template <class F>
-  static auto apply(F&& f, int64_t x) -> decltype(std::forward<F>(f)(x, x)) {
-    return std::forward<F>(f)(x, x);
+  template <class Allocator>
+  static void transfer(Allocator* alloc, slot_type* new_slot,
+                       slot_type* old_slot) {
+    construct(alloc, new_slot, std::move(*old_slot));
+    destroy(alloc, old_slot);
+  }
+
+  static T& element(slot_type* slot) { return *slot; }
+
+  template <class F, class... Args>
+  static decltype(absl::container_internal::DecomposeValue(
+      std::declval<F>(), std::declval<Args>()...))
+  apply(F&& f, Args&&... args) {
+    return absl::container_internal::DecomposeValue(
+        std::forward<F>(f), std::forward<Args>(args)...);
   }
 };
 
+using IntPolicy = ValuePolicy<int64_t>;
+
 class StringPolicy {
   template <class F, class K, class V,
             class = typename std::enable_if<
@@ -417,53 +437,6 @@
   EXPECT_TRUE(t.empty());
 }
 
-#ifdef __GNUC__
-template <class T>
-ABSL_ATTRIBUTE_ALWAYS_INLINE inline void DoNotOptimize(const T& v) {
-  asm volatile("" : : "r,m"(v) : "memory");
-}
-#endif
-
-TEST(Table, Prefetch) {
-  IntTable t;
-  t.emplace(1);
-  // Works for both present and absent keys.
-  t.prefetch(1);
-  t.prefetch(2);
-
-  // Do not run in debug mode, when prefetch is not implemented, or when
-  // sanitizers are enabled, or on WebAssembly.
-#if defined(NDEBUG) && defined(__GNUC__) && defined(__x86_64__) &&          \
-    !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) &&            \
-    !defined(THREAD_SANITIZER) && !defined(UNDEFINED_BEHAVIOR_SANITIZER) && \
-    !defined(__EMSCRIPTEN__)
-  const auto now = [] { return absl::base_internal::CycleClock::Now(); };
-
-  // Make size enough to not fit in L2 cache (16.7 Mb)
-  static constexpr int size = 1 << 22;
-  for (int i = 0; i < size; ++i) t.insert(i);
-
-  int64_t no_prefetch = 0, prefetch = 0;
-  for (int iter = 0; iter < 10; ++iter) {
-    int64_t time = now();
-    for (int i = 0; i < size; ++i) {
-      DoNotOptimize(t.find(i));
-    }
-    no_prefetch += now() - time;
-
-    time = now();
-    for (int i = 0; i < size; ++i) {
-      t.prefetch(i + 20);
-      DoNotOptimize(t.find(i));
-    }
-    prefetch += now() - time;
-  }
-
-  // no_prefetch is at least 30% slower.
-  EXPECT_GE(1.0 * no_prefetch / prefetch, 1.3);
-#endif
-}
-
 TEST(Table, LookupEmpty) {
   IntTable t;
   auto it = t.find(0);
@@ -892,7 +865,8 @@
 std::vector<int64_t> CollectBadMergeKeys(size_t N) {
   static constexpr int kGroupSize = Group::kWidth - 1;
 
-  auto topk_range = [](size_t b, size_t e, IntTable* t) -> std::vector<int64_t> {
+  auto topk_range = [](size_t b, size_t e,
+                       IntTable* t) -> std::vector<int64_t> {
     for (size_t i = b; i != e; ++i) {
       t->emplace(i);
     }
@@ -1046,8 +1020,8 @@
 // 1. Create new table and reserve it to keys.size() * 2
 // 2. Insert all keys xored with seed
 // 3. Collect ProbeStats from final table.
-ProbeStats CollectProbeStatsOnKeysXoredWithSeed(const std::vector<int64_t>& keys,
-                                                size_t num_iters) {
+ProbeStats CollectProbeStatsOnKeysXoredWithSeed(
+    const std::vector<int64_t>& keys, size_t num_iters) {
   const size_t reserve_size = keys.size() * 2;
 
   ProbeStats stats;
@@ -1701,6 +1675,38 @@
   EXPECT_THAT(t2, UnorderedElementsAre(Pair("0", "~0")));
 }
 
+TEST(Table, IteratorEmplaceConstructibleRequirement) {
+  struct Value {
+    explicit Value(absl::string_view view) : value(view) {}
+    std::string value;
+
+    bool operator==(const Value& other) const { return value == other.value; }
+  };
+  struct H {
+    size_t operator()(const Value& v) const {
+      return absl::Hash<std::string>{}(v.value);
+    }
+  };
+
+  struct Table : raw_hash_set<ValuePolicy<Value>, H, std::equal_to<Value>,
+                              std::allocator<Value>> {
+    using Base = typename Table::raw_hash_set;
+    using Base::Base;
+  };
+
+  std::string input[3]{"A", "B", "C"};
+
+  Table t(std::begin(input), std::end(input));
+  EXPECT_THAT(t, UnorderedElementsAre(Value{"A"}, Value{"B"}, Value{"C"}));
+
+  input[0] = "D";
+  input[1] = "E";
+  input[2] = "F";
+  t.insert(std::begin(input), std::end(input));
+  EXPECT_THAT(t, UnorderedElementsAre(Value{"A"}, Value{"B"}, Value{"C"},
+                                      Value{"D"}, Value{"E"}, Value{"F"}));
+}
+
 TEST(Nodes, EmptyNodeType) {
   using node_type = StringTable::node_type;
   node_type n;
@@ -1712,9 +1718,9 @@
 }
 
 TEST(Nodes, ExtractInsert) {
-  constexpr char k0[] = "Very long std::string zero.";
-  constexpr char k1[] = "Very long std::string one.";
-  constexpr char k2[] = "Very long std::string two.";
+  constexpr char k0[] = "Very long string zero.";
+  constexpr char k1[] = "Very long string one.";
+  constexpr char k2[] = "Very long string two.";
   StringTable t = {{k0, ""}, {k1, ""}, {k2, ""}};
   EXPECT_THAT(t,
               UnorderedElementsAre(Pair(k0, ""), Pair(k1, ""), Pair(k2, "")));
@@ -1755,6 +1761,26 @@
   EXPECT_FALSE(node);
 }
 
+TEST(Nodes, HintInsert) {
+  IntTable t = {1, 2, 3};
+  auto node = t.extract(1);
+  EXPECT_THAT(t, UnorderedElementsAre(2, 3));
+  auto it = t.insert(t.begin(), std::move(node));
+  EXPECT_THAT(t, UnorderedElementsAre(1, 2, 3));
+  EXPECT_EQ(*it, 1);
+  EXPECT_FALSE(node);
+
+  node = t.extract(2);
+  EXPECT_THAT(t, UnorderedElementsAre(1, 3));
+  // reinsert 2 to make the next insert fail.
+  t.insert(2);
+  EXPECT_THAT(t, UnorderedElementsAre(1, 2, 3));
+  it = t.insert(t.begin(), std::move(node));
+  EXPECT_EQ(*it, 2);
+  // The node was not emptied by the insert call.
+  EXPECT_TRUE(node);
+}
+
 IntTable MakeSimpleTable(size_t size) {
   IntTable t;
   while (t.size() < size) t.insert(t.size());
@@ -1837,10 +1863,11 @@
 
   IntTable t;
   // Extra simple "regexp" as regexp support is highly varied across platforms.
-  constexpr char kDeathMsg[] = "it != end";
+  constexpr char kDeathMsg[] = "Invalid operation on iterator";
   EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()), kDeathMsg);
 }
 
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
 TEST(RawHashSamplerTest, Sample) {
   // Enable the feature even if the prod default is off.
   SetHashtablezEnabled(true);
@@ -1861,6 +1888,7 @@
   EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
               0.01, 0.005);
 }
+#endif  // ABSL_INTERNAL_HASHTABLEZ_SAMPLE
 
 TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {
   // Enable the feature even if the prod default is off.
@@ -1883,7 +1911,7 @@
               0.00, 0.001);
 }
 
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
 TEST(Sanitizer, PoisoningUnused) {
   IntTable t;
   t.reserve(5);
@@ -1907,8 +1935,9 @@
   t.erase(0);
   EXPECT_TRUE(__asan_address_is_poisoned(&v));
 }
-#endif  // ADDRESS_SANITIZER
+#endif  // ABSL_HAVE_ADDRESS_SANITIZER
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/test_instance_tracker.cc b/absl/container/internal/test_instance_tracker.cc
index 5a66cb4..f9947f0 100644
--- a/absl/container/internal/test_instance_tracker.cc
+++ b/absl/container/internal/test_instance_tracker.cc
@@ -15,6 +15,7 @@
 #include "absl/container/internal/test_instance_tracker.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace test_internal {
 int BaseCountedInstance::num_instances_ = 0;
 int BaseCountedInstance::num_live_instances_ = 0;
@@ -24,4 +25,5 @@
 int BaseCountedInstance::num_comparisons_ = 0;
 
 }  // namespace test_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/test_instance_tracker.h b/absl/container/internal/test_instance_tracker.h
index c4731db..5ff6fd7 100644
--- a/absl/container/internal/test_instance_tracker.h
+++ b/absl/container/internal/test_instance_tracker.h
@@ -21,6 +21,7 @@
 #include "absl/types/compare.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace test_internal {
 
 // A type that counts number of occurrences of the type, the live occurrences of
@@ -267,6 +268,7 @@
 };
 
 }  // namespace test_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_
diff --git a/absl/container/internal/tracked.h b/absl/container/internal/tracked.h
index 75173ab..29f5829 100644
--- a/absl/container/internal/tracked.h
+++ b/absl/container/internal/tracked.h
@@ -16,10 +16,14 @@
 #define ABSL_CONTAINER_INTERNAL_TRACKED_H_
 
 #include <stddef.h>
+
 #include <memory>
 #include <utility>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 // A class that tracks its copies and moves so that it can be queried in tests.
@@ -73,6 +77,7 @@
 };
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_TRACKED_H_
diff --git a/absl/container/internal/unordered_map_constructor_test.h b/absl/container/internal/unordered_map_constructor_test.h
index 68817e4..76ee95e 100644
--- a/absl/container/internal/unordered_map_constructor_test.h
+++ b/absl/container/internal/unordered_map_constructor_test.h
@@ -24,6 +24,7 @@
 #include "absl/container/internal/hash_policy_testing.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <class UnordMap>
@@ -482,6 +483,7 @@
     AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf);
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_
diff --git a/absl/container/internal/unordered_map_lookup_test.h b/absl/container/internal/unordered_map_lookup_test.h
index ebd3612..e76421e 100644
--- a/absl/container/internal/unordered_map_lookup_test.h
+++ b/absl/container/internal/unordered_map_lookup_test.h
@@ -21,6 +21,7 @@
 #include "absl/container/internal/hash_policy_testing.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <class UnordMap>
@@ -110,6 +111,7 @@
                            EqualRange);
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_
diff --git a/absl/container/internal/unordered_map_members_test.h b/absl/container/internal/unordered_map_members_test.h
index 1bf31ab..7d48cdb 100644
--- a/absl/container/internal/unordered_map_members_test.h
+++ b/absl/container/internal/unordered_map_members_test.h
@@ -21,6 +21,7 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <class UnordMap>
@@ -80,6 +81,7 @@
 REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd);
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_
diff --git a/absl/container/internal/unordered_map_modifiers_test.h b/absl/container/internal/unordered_map_modifiers_test.h
index f6aff54..8c9ca77 100644
--- a/absl/container/internal/unordered_map_modifiers_test.h
+++ b/absl/container/internal/unordered_map_modifiers_test.h
@@ -23,6 +23,7 @@
 #include "absl/container/internal/hash_policy_testing.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <class UnordMap>
@@ -285,6 +286,8 @@
   }
 };
 
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniquePtrModifiersTest);
+
 TYPED_TEST_SUITE_P(UniquePtrModifiersTest);
 
 // Test that we do not move from rvalue arguments if an insertion does not
@@ -309,6 +312,7 @@
 REGISTER_TYPED_TEST_SUITE_P(UniquePtrModifiersTest, TryEmplace);
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_
diff --git a/absl/container/internal/unordered_map_test.cc b/absl/container/internal/unordered_map_test.cc
index 114b342..9cbf512 100644
--- a/absl/container/internal/unordered_map_test.cc
+++ b/absl/container/internal/unordered_map_test.cc
@@ -21,6 +21,7 @@
 #include "absl/container/internal/unordered_map_modifiers_test.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
@@ -45,4 +46,5 @@
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/internal/unordered_set_constructor_test.h b/absl/container/internal/unordered_set_constructor_test.h
index f484468..41165b0 100644
--- a/absl/container/internal/unordered_set_constructor_test.h
+++ b/absl/container/internal/unordered_set_constructor_test.h
@@ -26,6 +26,7 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <class UnordMap>
@@ -489,6 +490,7 @@
     AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf);
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_
diff --git a/absl/container/internal/unordered_set_lookup_test.h b/absl/container/internal/unordered_set_lookup_test.h
index 05b32b5..8f2f4b2 100644
--- a/absl/container/internal/unordered_set_lookup_test.h
+++ b/absl/container/internal/unordered_set_lookup_test.h
@@ -21,6 +21,7 @@
 #include "absl/container/internal/hash_policy_testing.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <class UnordSet>
@@ -84,6 +85,7 @@
 REGISTER_TYPED_TEST_CASE_P(LookupTest, Count, Find, EqualRange);
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_
diff --git a/absl/container/internal/unordered_set_members_test.h b/absl/container/internal/unordered_set_members_test.h
index b96c945..4c5e104 100644
--- a/absl/container/internal/unordered_set_members_test.h
+++ b/absl/container/internal/unordered_set_members_test.h
@@ -21,6 +21,7 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <class UnordSet>
@@ -79,6 +80,7 @@
 REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd);
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_
diff --git a/absl/container/internal/unordered_set_modifiers_test.h b/absl/container/internal/unordered_set_modifiers_test.h
index 79a8d42..26be58d 100644
--- a/absl/container/internal/unordered_set_modifiers_test.h
+++ b/absl/container/internal/unordered_set_modifiers_test.h
@@ -21,6 +21,7 @@
 #include "absl/container/internal/hash_policy_testing.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 
 template <class UnordSet>
@@ -183,6 +184,7 @@
                            EraseKey, Swap);
 
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_
diff --git a/absl/container/internal/unordered_set_test.cc b/absl/container/internal/unordered_set_test.cc
index 6478fac..a134b53 100644
--- a/absl/container/internal/unordered_set_test.cc
+++ b/absl/container/internal/unordered_set_test.cc
@@ -20,6 +20,7 @@
 #include "absl/container/internal/unordered_set_modifiers_test.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
@@ -36,4 +37,5 @@
 
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h
index a718842..7a39f62 100644
--- a/absl/container/node_hash_map.h
+++ b/absl/container/node_hash_map.h
@@ -48,6 +48,7 @@
 #include "absl/memory/memory.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 template <class Key, class Value>
 class NodeHashMapPolicy;
@@ -224,7 +225,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // node_hash_map::insert()
@@ -373,6 +375,11 @@
   //   key value and returns a node handle owning that extracted data. If the
   //   `node_hash_map` does not contain an element with a matching key, this
   //   function returns an empty node handle.
+  //
+  // NOTE: when compiled in an earlier version of C++ than C++17,
+  // `node_type::key()` returns a const reference to the key instead of a
+  // mutable reference. We cannot safely return a mutable reference without
+  // std::launder (which is not available before C++17).
   using Base::extract;
 
   // node_hash_map::merge()
@@ -513,14 +520,17 @@
   //
   // Returns the function used for comparing keys equality.
   using Base::key_eq;
-
-  ABSL_DEPRECATED("Call `hash_function()` instead.")
-  typename Base::hasher hash_funct() { return this->hash_function(); }
-
-  ABSL_DEPRECATED("Call `rehash()` instead.")
-  void resize(typename Base::size_type hint) { this->rehash(hint); }
 };
 
+// erase_if(node_hash_map<>, Pred)
+//
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+template <typename K, typename V, typename H, typename E, typename A,
+          typename Predicate>
+void erase_if(node_hash_map<K, V, H, E, A>& c, Predicate pred) {
+  container_internal::EraseIf(pred, &c);
+}
+
 namespace container_internal {
 
 template <class Key, class Value>
@@ -581,6 +591,7 @@
 
 }  // namespace container_algorithm_internal
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_NODE_HASH_MAP_H_
diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc
index 0f2714a..8f59a1e 100644
--- a/absl/container/node_hash_map_test.cc
+++ b/absl/container/node_hash_map_test.cc
@@ -21,10 +21,12 @@
 #include "absl/container/internal/unordered_map_modifiers_test.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 
 using ::testing::Field;
+using ::testing::IsEmpty;
 using ::testing::Pair;
 using ::testing::UnorderedElementsAre;
 
@@ -215,6 +217,59 @@
   EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70), Elem(17, 23)));
 }
 
+bool FirstIsEven(std::pair<const int, int> p) { return p.first % 2 == 0; }
+
+TEST(NodeHashMap, EraseIf) {
+  // Erase all elements.
+  {
+    node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    erase_if(s, [](std::pair<const int, int>) { return true; });
+    EXPECT_THAT(s, IsEmpty());
+  }
+  // Erase no elements.
+  {
+    node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    erase_if(s, [](std::pair<const int, int>) { return false; });
+    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3),
+                                        Pair(4, 4), Pair(5, 5)));
+  }
+  // Erase specific elements.
+  {
+    node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    erase_if(s,
+             [](std::pair<const int, int> kvp) { return kvp.first % 2 == 1; });
+    EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4)));
+  }
+  // Predicate is function reference.
+  {
+    node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    erase_if(s, FirstIsEven);
+    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
+  }
+  // Predicate is function pointer.
+  {
+    node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+    erase_if(s, &FirstIsEven);
+    EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
+  }
+}
+
+// This test requires std::launder for mutable key access in node handles.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+TEST(NodeHashMap, NodeHandleMutableKeyAccess) {
+  node_hash_map<std::string, std::string> map;
+
+  map["key1"] = "mapped";
+
+  auto nh = map.extract(map.begin());
+  nh.key().resize(3);
+  map.insert(std::move(nh));
+
+  EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
+}
+#endif
+
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h
index 0cd1fe5..93b15f4 100644
--- a/absl/container/node_hash_set.h
+++ b/absl/container/node_hash_set.h
@@ -18,7 +18,7 @@
 //
 // An `absl::node_hash_set<T>` is an unordered associative container designed to
 // be a more efficient replacement for `std::unordered_set`. Like
-// `unordered_set`, search, insertion, and deletion of map elements can be done
+// `unordered_set`, search, insertion, and deletion of set elements can be done
 // as an `O(1)` operation. However, `node_hash_set` (and other unordered
 // associative containers known as the collection of Abseil "Swiss tables")
 // contain other optimizations that result in both memory and computation
@@ -44,6 +44,7 @@
 #include "absl/memory/memory.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 template <typename T>
 struct NodeHashSetPolicy;
@@ -59,7 +60,7 @@
 // following notable differences:
 //
 // * Supports heterogeneous lookup, through `find()`, `operator[]()` and
-//   `insert()`, provided that the map is provided a compatible heterogeneous
+//   `insert()`, provided that the set is provided a compatible heterogeneous
 //   hashing function and equality operator.
 // * Contains a `capacity()` member function indicating the number of element
 //   slots (open, deleted, and empty) within the hash set.
@@ -75,13 +76,13 @@
 // Example:
 //
 //   // Create a node hash set of three strings
-//   absl::node_hash_map<std::string, std::string> ducks =
-//     {"huey", "dewey"}, "louie"};
+//   absl::node_hash_set<std::string> ducks =
+//     {"huey", "dewey", "louie"};
 //
-//  // Insert a new element into the node hash map
-//  ducks.insert("donald"};
+//  // Insert a new element into the node hash set
+//  ducks.insert("donald");
 //
-//  // Force a rehash of the node hash map
+//  // Force a rehash of the node hash set
 //  ducks.rehash(0);
 //
 //  // See if "dewey" is present
@@ -99,7 +100,7 @@
  public:
   // Constructors and Assignment Operators
   //
-  // A node_hash_set supports the same overload set as `std::unordered_map`
+  // A node_hash_set supports the same overload set as `std::unordered_set`
   // for construction and assignment:
   //
   // *  Default constructor
@@ -110,7 +111,7 @@
   // * Initializer List constructor
   //
   //   absl::node_hash_set<std::string> set2 =
-  //       {{"huey"}, {"dewey"}, {"louie"},};
+  //       {{"huey"}, {"dewey"}, {"louie"}};
   //
   // * Copy constructor
   //
@@ -166,7 +167,7 @@
   // available within the `node_hash_set`.
   //
   // NOTE: this member function is particular to `absl::node_hash_set` and is
-  // not provided in the `std::unordered_map` API.
+  // not provided in the `std::unordered_set` API.
   using Base::capacity;
 
   // node_hash_set::empty()
@@ -207,7 +208,7 @@
   //   `void`.
   //
   //   NOTE: this return behavior is different than that of STL containers in
-  //   general and `std::unordered_map` in particular.
+  //   general and `std::unordered_set` in particular.
   //
   // iterator erase(const_iterator first, const_iterator last):
   //
@@ -216,7 +217,8 @@
   //
   // size_type erase(const key_type& key):
   //
-  //   Erases the element with the matching key, if it exists.
+  //   Erases the element with the matching key, if it exists, returning the
+  //   number of elements erased (0 or 1).
   using Base::erase;
 
   // node_hash_set::insert()
@@ -312,7 +314,7 @@
 
   // node_hash_set::merge()
   //
-  // Extracts elements from a given `source` flat hash map into this
+  // Extracts elements from a given `source` node hash set into this
   // `node_hash_set`. If the destination `node_hash_set` already contains an
   // element with an equivalent key, that element is not extracted.
   using Base::merge;
@@ -320,15 +322,15 @@
   // node_hash_set::swap(node_hash_set& other)
   //
   // Exchanges the contents of this `node_hash_set` with those of the `other`
-  // flat hash map, avoiding invocation of any move, copy, or swap operations on
+  // node hash set, avoiding invocation of any move, copy, or swap operations on
   // individual elements.
   //
   // All iterators and references on the `node_hash_set` remain valid, excepting
   // for the past-the-end iterator, which is invalidated.
   //
-  // `swap()` requires that the flat hash set's hashing and key equivalence
+  // `swap()` requires that the node hash set's hashing and key equivalence
   // functions be Swappable, and are exchaged using unqualified calls to
-  // non-member `swap()`. If the map's allocator has
+  // non-member `swap()`. If the set's allocator has
   // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value`
   // set to `true`, the allocators are also exchanged using an unqualified call
   // to non-member `swap()`; otherwise, the allocators are not swapped.
@@ -383,14 +385,14 @@
   // node_hash_set::bucket_count()
   //
   // Returns the number of "buckets" within the `node_hash_set`. Note that
-  // because a flat hash map contains all elements within its internal storage,
+  // because a node hash set contains all elements within its internal storage,
   // this value simply equals the current capacity of the `node_hash_set`.
   using Base::bucket_count;
 
   // node_hash_set::load_factor()
   //
   // Returns the current load factor of the `node_hash_set` (the average number
-  // of slots occupied with a value within the hash map).
+  // of slots occupied with a value within the hash set).
   using Base::load_factor;
 
   // node_hash_set::max_load_factor()
@@ -426,14 +428,16 @@
   //
   // Returns the function used for comparing keys equality.
   using Base::key_eq;
-
-  ABSL_DEPRECATED("Call `hash_function()` instead.")
-  typename Base::hasher hash_funct() { return this->hash_function(); }
-
-  ABSL_DEPRECATED("Call `rehash()` instead.")
-  void resize(typename Base::size_type hint) { this->rehash(hint); }
 };
 
+// erase_if(node_hash_set<>, Pred)
+//
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+template <typename T, typename H, typename E, typename A, typename Predicate>
+void erase_if(node_hash_set<T, H, E, A>& c, Predicate pred) {
+  container_internal::EraseIf(pred, &c);
+}
+
 namespace container_internal {
 
 template <class T>
@@ -483,6 +487,7 @@
     : std::true_type {};
 
 }  // namespace container_algorithm_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_CONTAINER_NODE_HASH_SET_H_
diff --git a/absl/container/node_hash_set_test.cc b/absl/container/node_hash_set_test.cc
index 0ea76e7..7ddad20 100644
--- a/absl/container/node_hash_set_test.cc
+++ b/absl/container/node_hash_set_test.cc
@@ -20,10 +20,12 @@
 #include "absl/container/internal/unordered_set_modifiers_test.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace container_internal {
 namespace {
 using ::absl::container_internal::hash_internal::Enum;
 using ::absl::container_internal::hash_internal::EnumClass;
+using ::testing::IsEmpty;
 using ::testing::Pointee;
 using ::testing::UnorderedElementsAre;
 
@@ -100,6 +102,42 @@
   EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23)));
 }
 
+bool IsEven(int k) { return k % 2 == 0; }
+
+TEST(NodeHashSet, EraseIf) {
+  // Erase all elements.
+  {
+    node_hash_set<int> s = {1, 2, 3, 4, 5};
+    erase_if(s, [](int) { return true; });
+    EXPECT_THAT(s, IsEmpty());
+  }
+  // Erase no elements.
+  {
+    node_hash_set<int> s = {1, 2, 3, 4, 5};
+    erase_if(s, [](int) { return false; });
+    EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+  }
+  // Erase specific elements.
+  {
+    node_hash_set<int> s = {1, 2, 3, 4, 5};
+    erase_if(s, [](int k) { return k % 2 == 1; });
+    EXPECT_THAT(s, UnorderedElementsAre(2, 4));
+  }
+  // Predicate is function reference.
+  {
+    node_hash_set<int> s = {1, 2, 3, 4, 5};
+    erase_if(s, IsEven);
+    EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
+  }
+  // Predicate is function pointer.
+  {
+    node_hash_set<int> s = {1, 2, 3, 4, 5};
+    erase_if(s, &IsEven);
+    EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
+  }
+}
+
 }  // namespace
 }  // namespace container_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/copts/AbseilConfigureCopts.cmake b/absl/copts/AbseilConfigureCopts.cmake
index b430873..acd46d0 100644
--- a/absl/copts/AbseilConfigureCopts.cmake
+++ b/absl/copts/AbseilConfigureCopts.cmake
@@ -5,10 +5,36 @@
 set(ABSL_HAVE_LSAN OFF)
 set(ABSL_DEFAULT_LINKOPTS "")
 
+if (BUILD_SHARED_LIBS AND MSVC)
+  set(ABSL_BUILD_DLL TRUE)
+  set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
+else()
+  set(ABSL_BUILD_DLL FALSE)
+endif()
+
+if("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "x86_64|amd64|AMD64")
+  if (MSVC)
+    set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_MSVC_X64_FLAGS}")
+  else()
+    set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_X64_FLAGS}")
+  endif()
+elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm.*|aarch64")
+  if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
+    set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_ARM64_FLAGS}")
+  elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
+    set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_ARM32_FLAGS}")
+  else()
+    message(WARNING "Value of CMAKE_SIZEOF_VOID_P (${CMAKE_SIZEOF_VOID_P}) is not supported.")
+  endif()
+else()
+  message(WARNING "Value of CMAKE_SYSTEM_PROCESSOR (${CMAKE_SYSTEM_PROCESSOR}) is unknown and cannot be used to set ABSL_RANDOM_RANDEN_COPTS")
+  set(ABSL_RANDOM_RANDEN_COPTS "")
+endif()
+
+
 if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
   set(ABSL_DEFAULT_COPTS "${ABSL_GCC_FLAGS}")
   set(ABSL_TEST_COPTS "${ABSL_GCC_FLAGS};${ABSL_GCC_TEST_FLAGS}")
-  set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_X64_FLAGS}")
 elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
   # MATCHES so we get both Clang and AppleClang
   if(MSVC)
@@ -16,11 +42,9 @@
     set(ABSL_DEFAULT_COPTS "${ABSL_CLANG_CL_FLAGS}")
     set(ABSL_TEST_COPTS "${ABSL_CLANG_CL_FLAGS};${ABSL_CLANG_CL_TEST_FLAGS}")
     set(ABSL_DEFAULT_LINKOPTS "${ABSL_MSVC_LINKOPTS}")
-    set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_MSVC_X64_FLAGS}")
   else()
     set(ABSL_DEFAULT_COPTS "${ABSL_LLVM_FLAGS}")
     set(ABSL_TEST_COPTS "${ABSL_LLVM_FLAGS};${ABSL_LLVM_TEST_FLAGS}")
-    set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_X64_FLAGS}")
     if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
       # AppleClang doesn't have lsan
       # https://developer.apple.com/documentation/code_diagnostics
@@ -34,19 +58,10 @@
   set(ABSL_DEFAULT_COPTS "${ABSL_MSVC_FLAGS}")
   set(ABSL_TEST_COPTS "${ABSL_MSVC_FLAGS};${ABSL_MSVC_TEST_FLAGS}")
   set(ABSL_DEFAULT_LINKOPTS "${ABSL_MSVC_LINKOPTS}")
-  set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_MSVC_X64_FLAGS}")
 else()
   message(WARNING "Unknown compiler: ${CMAKE_CXX_COMPILER}.  Building with no default flags")
   set(ABSL_DEFAULT_COPTS "")
   set(ABSL_TEST_COPTS "")
-  set(ABSL_RANDOM_RANDEN_COPTS "")
 endif()
 
-if("${CMAKE_CXX_STANDARD}" EQUAL 98)
-  message(FATAL_ERROR "Abseil requires at least C++11")
-elseif(NOT "${CMAKE_CXX_STANDARD}")
-  message(STATUS "No CMAKE_CXX_STANDARD set, assuming 11")
-  set(ABSL_CXX_STANDARD 11)
-else()
-  set(ABSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
-endif()
+set(ABSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake
index 39b79c5..51742c9 100644
--- a/absl/copts/GENERATED_AbseilCopts.cmake
+++ b/absl/copts/GENERATED_AbseilCopts.cmake
@@ -5,48 +5,6 @@
 
 list(APPEND ABSL_CLANG_CL_FLAGS
     "/W3"
-    "-Wno-c++98-compat-pedantic"
-    "-Wno-conversion"
-    "-Wno-covered-switch-default"
-    "-Wno-deprecated"
-    "-Wno-disabled-macro-expansion"
-    "-Wno-double-promotion"
-    "-Wno-comma"
-    "-Wno-extra-semi"
-    "-Wno-extra-semi-stmt"
-    "-Wno-packed"
-    "-Wno-padded"
-    "-Wno-sign-compare"
-    "-Wno-float-conversion"
-    "-Wno-float-equal"
-    "-Wno-format-nonliteral"
-    "-Wno-gcc-compat"
-    "-Wno-global-constructors"
-    "-Wno-exit-time-destructors"
-    "-Wno-nested-anon-types"
-    "-Wno-non-modular-include-in-module"
-    "-Wno-old-style-cast"
-    "-Wno-range-loop-analysis"
-    "-Wno-reserved-id-macro"
-    "-Wno-shorten-64-to-32"
-    "-Wno-switch-enum"
-    "-Wno-thread-safety-negative"
-    "-Wno-unknown-warning-option"
-    "-Wno-unreachable-code"
-    "-Wno-unused-macros"
-    "-Wno-weak-vtables"
-    "-Wno-zero-as-null-pointer-constant"
-    "-Wbitfield-enum-conversion"
-    "-Wbool-conversion"
-    "-Wconstant-conversion"
-    "-Wenum-conversion"
-    "-Wint-conversion"
-    "-Wliteral-conversion"
-    "-Wnon-literal-null-conversion"
-    "-Wnull-conversion"
-    "-Wobjc-literal-conversion"
-    "-Wno-sign-conversion"
-    "-Wstring-conversion"
     "/DNOMINMAX"
     "/DWIN32_LEAN_AND_MEAN"
     "/D_CRT_SECURE_NO_WARNINGS"
@@ -79,16 +37,17 @@
     "-Wextra"
     "-Wcast-qual"
     "-Wconversion-null"
+    "-Wformat-security"
     "-Wmissing-declarations"
     "-Woverlength-strings"
     "-Wpointer-arith"
+    "-Wundef"
     "-Wunused-local-typedefs"
     "-Wunused-result"
     "-Wvarargs"
     "-Wvla"
     "-Wwrite-strings"
-    "-Wno-missing-field-initializers"
-    "-Wno-sign-compare"
+    "-DNOMINMAX"
 )
 
 list(APPEND ABSL_GCC_TEST_FLAGS
@@ -104,49 +63,37 @@
 list(APPEND ABSL_LLVM_FLAGS
     "-Wall"
     "-Wextra"
-    "-Weverything"
-    "-Wno-c++98-compat-pedantic"
-    "-Wno-conversion"
-    "-Wno-covered-switch-default"
-    "-Wno-deprecated"
-    "-Wno-disabled-macro-expansion"
-    "-Wno-double-promotion"
-    "-Wno-comma"
-    "-Wno-extra-semi"
-    "-Wno-extra-semi-stmt"
-    "-Wno-packed"
-    "-Wno-padded"
-    "-Wno-sign-compare"
-    "-Wno-float-conversion"
-    "-Wno-float-equal"
-    "-Wno-format-nonliteral"
-    "-Wno-gcc-compat"
-    "-Wno-global-constructors"
-    "-Wno-exit-time-destructors"
-    "-Wno-nested-anon-types"
-    "-Wno-non-modular-include-in-module"
-    "-Wno-old-style-cast"
-    "-Wno-range-loop-analysis"
-    "-Wno-reserved-id-macro"
-    "-Wno-shorten-64-to-32"
-    "-Wno-switch-enum"
-    "-Wno-thread-safety-negative"
-    "-Wno-unknown-warning-option"
-    "-Wno-unreachable-code"
-    "-Wno-unused-macros"
-    "-Wno-weak-vtables"
-    "-Wno-zero-as-null-pointer-constant"
-    "-Wbitfield-enum-conversion"
-    "-Wbool-conversion"
-    "-Wconstant-conversion"
-    "-Wenum-conversion"
-    "-Wint-conversion"
+    "-Wcast-qual"
+    "-Wconversion"
+    "-Wfloat-overflow-conversion"
+    "-Wfloat-zero-conversion"
+    "-Wfor-loop-analysis"
+    "-Wformat-security"
+    "-Wgnu-redeclared-enum"
+    "-Winfinite-recursion"
     "-Wliteral-conversion"
-    "-Wnon-literal-null-conversion"
-    "-Wnull-conversion"
-    "-Wobjc-literal-conversion"
-    "-Wno-sign-conversion"
+    "-Wmissing-declarations"
+    "-Woverlength-strings"
+    "-Wpointer-arith"
+    "-Wself-assign"
+    "-Wshadow"
     "-Wstring-conversion"
+    "-Wtautological-overlap-compare"
+    "-Wundef"
+    "-Wuninitialized"
+    "-Wunreachable-code"
+    "-Wunused-comparison"
+    "-Wunused-local-typedefs"
+    "-Wunused-result"
+    "-Wvla"
+    "-Wwrite-strings"
+    "-Wno-float-conversion"
+    "-Wno-implicit-float-conversion"
+    "-Wno-implicit-int-float-conversion"
+    "-Wno-implicit-int-conversion"
+    "-Wno-shorten-64-to-32"
+    "-Wno-sign-conversion"
+    "-DNOMINMAX"
 )
 
 list(APPEND ABSL_LLVM_TEST_FLAGS
diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl
index 7d645cc..6707488 100644
--- a/absl/copts/GENERATED_copts.bzl
+++ b/absl/copts/GENERATED_copts.bzl
@@ -6,48 +6,6 @@
 
 ABSL_CLANG_CL_FLAGS = [
     "/W3",
-    "-Wno-c++98-compat-pedantic",
-    "-Wno-conversion",
-    "-Wno-covered-switch-default",
-    "-Wno-deprecated",
-    "-Wno-disabled-macro-expansion",
-    "-Wno-double-promotion",
-    "-Wno-comma",
-    "-Wno-extra-semi",
-    "-Wno-extra-semi-stmt",
-    "-Wno-packed",
-    "-Wno-padded",
-    "-Wno-sign-compare",
-    "-Wno-float-conversion",
-    "-Wno-float-equal",
-    "-Wno-format-nonliteral",
-    "-Wno-gcc-compat",
-    "-Wno-global-constructors",
-    "-Wno-exit-time-destructors",
-    "-Wno-nested-anon-types",
-    "-Wno-non-modular-include-in-module",
-    "-Wno-old-style-cast",
-    "-Wno-range-loop-analysis",
-    "-Wno-reserved-id-macro",
-    "-Wno-shorten-64-to-32",
-    "-Wno-switch-enum",
-    "-Wno-thread-safety-negative",
-    "-Wno-unknown-warning-option",
-    "-Wno-unreachable-code",
-    "-Wno-unused-macros",
-    "-Wno-weak-vtables",
-    "-Wno-zero-as-null-pointer-constant",
-    "-Wbitfield-enum-conversion",
-    "-Wbool-conversion",
-    "-Wconstant-conversion",
-    "-Wenum-conversion",
-    "-Wint-conversion",
-    "-Wliteral-conversion",
-    "-Wnon-literal-null-conversion",
-    "-Wnull-conversion",
-    "-Wobjc-literal-conversion",
-    "-Wno-sign-conversion",
-    "-Wstring-conversion",
     "/DNOMINMAX",
     "/DWIN32_LEAN_AND_MEAN",
     "/D_CRT_SECURE_NO_WARNINGS",
@@ -80,16 +38,17 @@
     "-Wextra",
     "-Wcast-qual",
     "-Wconversion-null",
+    "-Wformat-security",
     "-Wmissing-declarations",
     "-Woverlength-strings",
     "-Wpointer-arith",
+    "-Wundef",
     "-Wunused-local-typedefs",
     "-Wunused-result",
     "-Wvarargs",
     "-Wvla",
     "-Wwrite-strings",
-    "-Wno-missing-field-initializers",
-    "-Wno-sign-compare",
+    "-DNOMINMAX",
 ]
 
 ABSL_GCC_TEST_FLAGS = [
@@ -105,49 +64,37 @@
 ABSL_LLVM_FLAGS = [
     "-Wall",
     "-Wextra",
-    "-Weverything",
-    "-Wno-c++98-compat-pedantic",
-    "-Wno-conversion",
-    "-Wno-covered-switch-default",
-    "-Wno-deprecated",
-    "-Wno-disabled-macro-expansion",
-    "-Wno-double-promotion",
-    "-Wno-comma",
-    "-Wno-extra-semi",
-    "-Wno-extra-semi-stmt",
-    "-Wno-packed",
-    "-Wno-padded",
-    "-Wno-sign-compare",
-    "-Wno-float-conversion",
-    "-Wno-float-equal",
-    "-Wno-format-nonliteral",
-    "-Wno-gcc-compat",
-    "-Wno-global-constructors",
-    "-Wno-exit-time-destructors",
-    "-Wno-nested-anon-types",
-    "-Wno-non-modular-include-in-module",
-    "-Wno-old-style-cast",
-    "-Wno-range-loop-analysis",
-    "-Wno-reserved-id-macro",
-    "-Wno-shorten-64-to-32",
-    "-Wno-switch-enum",
-    "-Wno-thread-safety-negative",
-    "-Wno-unknown-warning-option",
-    "-Wno-unreachable-code",
-    "-Wno-unused-macros",
-    "-Wno-weak-vtables",
-    "-Wno-zero-as-null-pointer-constant",
-    "-Wbitfield-enum-conversion",
-    "-Wbool-conversion",
-    "-Wconstant-conversion",
-    "-Wenum-conversion",
-    "-Wint-conversion",
+    "-Wcast-qual",
+    "-Wconversion",
+    "-Wfloat-overflow-conversion",
+    "-Wfloat-zero-conversion",
+    "-Wfor-loop-analysis",
+    "-Wformat-security",
+    "-Wgnu-redeclared-enum",
+    "-Winfinite-recursion",
     "-Wliteral-conversion",
-    "-Wnon-literal-null-conversion",
-    "-Wnull-conversion",
-    "-Wobjc-literal-conversion",
-    "-Wno-sign-conversion",
+    "-Wmissing-declarations",
+    "-Woverlength-strings",
+    "-Wpointer-arith",
+    "-Wself-assign",
+    "-Wshadow",
     "-Wstring-conversion",
+    "-Wtautological-overlap-compare",
+    "-Wundef",
+    "-Wuninitialized",
+    "-Wunreachable-code",
+    "-Wunused-comparison",
+    "-Wunused-local-typedefs",
+    "-Wunused-result",
+    "-Wvla",
+    "-Wwrite-strings",
+    "-Wno-float-conversion",
+    "-Wno-implicit-float-conversion",
+    "-Wno-implicit-int-float-conversion",
+    "-Wno-implicit-int-conversion",
+    "-Wno-shorten-64-to-32",
+    "-Wno-sign-conversion",
+    "-DNOMINMAX",
 ]
 
 ABSL_LLVM_TEST_FLAGS = [
diff --git a/absl/copts/configure_copts.bzl b/absl/copts/configure_copts.bzl
index 2829e4e..4d34254 100644
--- a/absl/copts/configure_copts.bzl
+++ b/absl/copts/configure_copts.bzl
@@ -6,6 +6,8 @@
 
 load(
     "//absl:copts/GENERATED_copts.bzl",
+    "ABSL_CLANG_CL_FLAGS",
+    "ABSL_CLANG_CL_TEST_FLAGS",
     "ABSL_GCC_FLAGS",
     "ABSL_GCC_TEST_FLAGS",
     "ABSL_LLVM_FLAGS",
@@ -21,15 +23,13 @@
 
 ABSL_DEFAULT_COPTS = select({
     "//absl:windows": ABSL_MSVC_FLAGS,
-    "//absl:llvm_compiler": ABSL_LLVM_FLAGS,
+    "//absl:clang_compiler": ABSL_LLVM_FLAGS,
     "//conditions:default": ABSL_GCC_FLAGS,
 })
 
-# in absence of modules (--compiler=gcc or -c opt), cc_tests leak their copts
-# to their (included header) dependencies and fail to build outside absl
 ABSL_TEST_COPTS = ABSL_DEFAULT_COPTS + select({
     "//absl:windows": ABSL_MSVC_TEST_FLAGS,
-    "//absl:llvm_compiler": ABSL_LLVM_TEST_FLAGS,
+    "//absl:clang_compiler": ABSL_LLVM_TEST_FLAGS,
     "//conditions:default": ABSL_GCC_TEST_FLAGS,
 })
 
@@ -46,7 +46,7 @@
     ":cpu_darwin": ABSL_RANDOM_HWAES_X64_FLAGS,
     ":cpu_x64_windows_msvc": ABSL_RANDOM_HWAES_MSVC_X64_FLAGS,
     ":cpu_x64_windows": ABSL_RANDOM_HWAES_MSVC_X64_FLAGS,
-    ":cpu_haswell": ABSL_RANDOM_HWAES_X64_FLAGS,
+    ":cpu_k8": ABSL_RANDOM_HWAES_X64_FLAGS,
     ":cpu_ppc": ["-mcrypto"],
 
     # Supported by default or unsupported.
@@ -63,7 +63,7 @@
     # These configs have consistent flags to enable HWAES intsructions.
     cpu_configs = [
         "ppc",
-        "haswell",
+        "k8",
         "darwin_x86_64",
         "darwin",
         "x64_windows_msvc",
diff --git a/absl/copts/copts.py b/absl/copts/copts.py
index a542541..cf52981 100644
--- a/absl/copts/copts.py
+++ b/absl/copts/copts.py
@@ -16,78 +16,6 @@
     "/W3",
 ]
 
-LLVM_BIG_WARNING_FLAGS = [
-    "-Wall",
-    "-Wextra",
-    "-Weverything",
-]
-
-# Docs on single flags is preceded by a comment.
-# Docs on groups of flags is preceded by ###.
-LLVM_DISABLE_WARNINGS_FLAGS = [
-    # Abseil does not support C++98
-    "-Wno-c++98-compat-pedantic",
-    # Turns off all implicit conversion warnings. Most are re-enabled below.
-    "-Wno-conversion",
-    "-Wno-covered-switch-default",
-    "-Wno-deprecated",
-    "-Wno-disabled-macro-expansion",
-    "-Wno-double-promotion",
-    ###
-    # Turned off as they include valid C++ code.
-    "-Wno-comma",
-    "-Wno-extra-semi",
-    "-Wno-extra-semi-stmt",
-    "-Wno-packed",
-    "-Wno-padded",
-    ###
-    # Google style does not use unsigned integers, though STL containers
-    # have unsigned types.
-    "-Wno-sign-compare",
-    ###
-    "-Wno-float-conversion",
-    "-Wno-float-equal",
-    "-Wno-format-nonliteral",
-    # Too aggressive: warns on Clang extensions enclosed in Clang-only
-    # compilation paths.
-    "-Wno-gcc-compat",
-    ###
-    # Some internal globals are necessary. Don't do this at home.
-    "-Wno-global-constructors",
-    "-Wno-exit-time-destructors",
-    ###
-    "-Wno-nested-anon-types",
-    "-Wno-non-modular-include-in-module",
-    "-Wno-old-style-cast",
-    # Warns on preferred usage of non-POD types such as string_view
-    "-Wno-range-loop-analysis",
-    "-Wno-reserved-id-macro",
-    "-Wno-shorten-64-to-32",
-    "-Wno-switch-enum",
-    "-Wno-thread-safety-negative",
-    "-Wno-unknown-warning-option",
-    "-Wno-unreachable-code",
-    # Causes warnings on include guards
-    "-Wno-unused-macros",
-    "-Wno-weak-vtables",
-    # Causes warnings on usage of types/compare.h comparison operators.
-    "-Wno-zero-as-null-pointer-constant",
-    ###
-    # Implicit conversion warnings turned off by -Wno-conversion
-    # which are re-enabled below.
-    "-Wbitfield-enum-conversion",
-    "-Wbool-conversion",
-    "-Wconstant-conversion",
-    "-Wenum-conversion",
-    "-Wint-conversion",
-    "-Wliteral-conversion",
-    "-Wnon-literal-null-conversion",
-    "-Wnull-conversion",
-    "-Wobjc-literal-conversion",
-    "-Wno-sign-conversion",
-    "-Wstring-conversion",
-]
-
 LLVM_TEST_DISABLE_WARNINGS_FLAGS = [
     "-Wno-c99-extensions",
     "-Wno-deprecated-declarations",
@@ -126,21 +54,18 @@
         "-Wextra",
         "-Wcast-qual",
         "-Wconversion-null",
+        "-Wformat-security",
         "-Wmissing-declarations",
         "-Woverlength-strings",
         "-Wpointer-arith",
+        "-Wundef",
         "-Wunused-local-typedefs",
         "-Wunused-result",
         "-Wvarargs",
         "-Wvla",  # variable-length array
         "-Wwrite-strings",
-        # gcc-4.x has spurious missing field initializer warnings.
-        # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750
-        # Remove when gcc-4.x is no longer supported.
-        "-Wno-missing-field-initializers",
-        # Google style does not use unsigned integers, though STL containers
-        # have unsigned types.
-        "-Wno-sign-compare",
+        # Don't define min and max macros (Build on Windows using gcc)
+        "-DNOMINMAX",
     ],
     "ABSL_GCC_TEST_FLAGS": [
         "-Wno-conversion-null",
@@ -151,12 +76,48 @@
         "-Wno-unused-parameter",
         "-Wno-unused-private-field",
     ],
-    "ABSL_LLVM_FLAGS":
-        LLVM_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS,
+    "ABSL_LLVM_FLAGS": [
+        "-Wall",
+        "-Wextra",
+        "-Wcast-qual",
+        "-Wconversion",
+        "-Wfloat-overflow-conversion",
+        "-Wfloat-zero-conversion",
+        "-Wfor-loop-analysis",
+        "-Wformat-security",
+        "-Wgnu-redeclared-enum",
+        "-Winfinite-recursion",
+        "-Wliteral-conversion",
+        "-Wmissing-declarations",
+        "-Woverlength-strings",
+        "-Wpointer-arith",
+        "-Wself-assign",
+        "-Wshadow",
+        "-Wstring-conversion",
+        "-Wtautological-overlap-compare",
+        "-Wundef",
+        "-Wuninitialized",
+        "-Wunreachable-code",
+        "-Wunused-comparison",
+        "-Wunused-local-typedefs",
+        "-Wunused-result",
+        "-Wvla",
+        "-Wwrite-strings",
+        # Warnings that are enabled by group warning flags like -Wall that we
+        # explicitly disable.
+        "-Wno-float-conversion",
+        "-Wno-implicit-float-conversion",
+        "-Wno-implicit-int-float-conversion",
+        "-Wno-implicit-int-conversion",
+        "-Wno-shorten-64-to-32",
+        "-Wno-sign-conversion",
+        # Don't define min and max macros (Build on Windows using clang)
+        "-DNOMINMAX",
+    ],
     "ABSL_LLVM_TEST_FLAGS":
         LLVM_TEST_DISABLE_WARNINGS_FLAGS,
     "ABSL_CLANG_CL_FLAGS":
-        (MSVC_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS + MSVC_DEFINES),
+        (MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES),
     "ABSL_CLANG_CL_TEST_FLAGS":
         LLVM_TEST_DISABLE_WARNINGS_FLAGS,
     "ABSL_MSVC_FLAGS":
diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel
index b87c55a..cd6e454 100644
--- a/absl/debugging/BUILD.bazel
+++ b/absl/debugging/BUILD.bazel
@@ -26,11 +26,19 @@
     default_visibility = ["//visibility:public"],
 )
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "stacktrace",
     srcs = [
+        "internal/stacktrace_aarch64-inl.inc",
+        "internal/stacktrace_arm-inl.inc",
+        "internal/stacktrace_config.h",
+        "internal/stacktrace_generic-inl.inc",
+        "internal/stacktrace_powerpc-inl.inc",
+        "internal/stacktrace_unimplemented-inl.inc",
+        "internal/stacktrace_win32-inl.inc",
+        "internal/stacktrace_x86-inl.inc",
         "stacktrace.cc",
     ],
     hdrs = ["stacktrace.h"],
@@ -38,6 +46,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":debugging_internal",
+        "//absl/base:config",
         "//absl/base:core_headers",
     ],
 )
@@ -46,6 +55,7 @@
     name = "symbolize",
     srcs = [
         "symbolize.cc",
+        "symbolize_darwin.inc",
         "symbolize_elf.inc",
         "symbolize_unimplemented.inc",
         "symbolize_win32.inc",
@@ -55,30 +65,43 @@
         "symbolize.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS + select({
+        "//absl:windows": ["-DEFAULTLIB:dbghelp.lib"],
+        "//conditions:default": [],
+    }),
     deps = [
         ":debugging_internal",
         ":demangle_internal",
         "//absl/base",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
         "//absl/base:malloc_internal",
         "//absl/base:raw_logging_internal",
+        "//absl/strings",
     ],
 )
 
 cc_test(
     name = "symbolize_test",
     srcs = ["symbolize_test.cc"],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
+    copts = ABSL_TEST_COPTS + select({
+        "//absl:windows": ["/Z7"],
+        "//conditions:default": [],
+    }),
+    linkopts = ABSL_DEFAULT_LINKOPTS + select({
+        "//absl:windows": ["/DEBUG"],
+        "//conditions:default": [],
+    }),
     deps = [
         ":stack_consumption",
         ":symbolize",
         "//absl/base",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
         "//absl/memory",
+        "//absl/strings",
         "@com_google_googletest//:gtest",
     ],
 )
@@ -97,6 +120,7 @@
     deps = [
         ":stacktrace",
         ":symbolize",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
     ],
@@ -114,6 +138,7 @@
         "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:errno_saver",
         "//absl/base:raw_logging_internal",
     ],
 )
@@ -124,6 +149,7 @@
     copts = ABSL_TEST_COPTS,
     linkopts = select({
         "//absl:windows": [],
+        "//absl:wasm": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
@@ -146,21 +172,15 @@
     hdrs = [
         "internal/address_is_readable.h",
         "internal/elf_mem_image.h",
-        "internal/stacktrace_aarch64-inl.inc",
-        "internal/stacktrace_arm-inl.inc",
-        "internal/stacktrace_config.h",
-        "internal/stacktrace_generic-inl.inc",
-        "internal/stacktrace_powerpc-inl.inc",
-        "internal/stacktrace_unimplemented-inl.inc",
-        "internal/stacktrace_win32-inl.inc",
-        "internal/stacktrace_x86-inl.inc",
         "internal/vdso_support.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
+        "//absl/base:errno_saver",
         "//absl/base:raw_logging_internal",
     ],
 )
@@ -172,6 +192,7 @@
     copts = ABSL_DEFAULT_COPTS,
     deps = [
         "//absl/base",
+        "//absl/base:config",
         "//absl/base:core_headers",
     ],
 )
@@ -184,6 +205,7 @@
     deps = [
         ":demangle_internal",
         ":stack_consumption",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
         "//absl/memory",
@@ -196,7 +218,10 @@
     srcs = ["leak_check.cc"],
     hdrs = ["leak_check.h"],
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = ["//absl/base:core_headers"],
+    deps = [
+        "//absl/base:config",
+        "//absl/base:core_headers",
+    ],
 )
 
 # Adding a dependency to leak_check_disable will disable
@@ -207,13 +232,14 @@
     srcs = ["leak_check_disable.cc"],
     linkopts = ABSL_DEFAULT_LINKOPTS,
     linkstatic = 1,
+    deps = ["//absl/base:config"],
     alwayslink = 1,
 )
 
 # These targets exists for use in tests only, explicitly configuring the
 # LEAK_SANITIZER macro. It must be linked with -fsanitize=leak for lsan.
 ABSL_LSAN_LINKOPTS = select({
-    "//absl:llvm_compiler": ["-fsanitize=leak"],
+    "//absl:clang_compiler": ["-fsanitize=leak"],
     "//conditions:default": [],
 })
 
@@ -223,11 +249,14 @@
     srcs = ["leak_check.cc"],
     hdrs = ["leak_check.h"],
     copts = select({
-        "//absl:llvm_compiler": ["-DLEAK_SANITIZER"],
+        "//absl:clang_compiler": ["-DLEAK_SANITIZER"],
         "//conditions:default": [],
     }),
     linkopts = ABSL_DEFAULT_LINKOPTS,
     visibility = ["//visibility:private"],
+    deps = [
+        "//absl/base:config",
+    ],
 )
 
 cc_library(
@@ -238,13 +267,16 @@
     copts = ["-ULEAK_SANITIZER"],
     linkopts = ABSL_DEFAULT_LINKOPTS,
     visibility = ["//visibility:private"],
+    deps = [
+        "//absl/base:config",
+    ],
 )
 
 cc_test(
     name = "leak_check_test",
     srcs = ["leak_check_test.cc"],
     copts = select({
-        "//absl:llvm_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
+        "//absl:clang_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
         "//conditions:default": [],
     }),
     linkopts = ABSL_LSAN_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
@@ -295,6 +327,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     visibility = ["//visibility:private"],
     deps = [
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
     ],
diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt
index c409e33..074b44c 100644
--- a/absl/debugging/CMakeLists.txt
+++ b/absl/debugging/CMakeLists.txt
@@ -19,12 +19,21 @@
     stacktrace
   HDRS
     "stacktrace.h"
+    "internal/stacktrace_aarch64-inl.inc"
+    "internal/stacktrace_arm-inl.inc"
+    "internal/stacktrace_config.h"
+    "internal/stacktrace_generic-inl.inc"
+    "internal/stacktrace_powerpc-inl.inc"
+    "internal/stacktrace_unimplemented-inl.inc"
+    "internal/stacktrace_win32-inl.inc"
+    "internal/stacktrace_x86-inl.inc"
   SRCS
     "stacktrace.cc"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::debugging_internal
+    absl::config
     absl::core_headers
   PUBLIC
 )
@@ -37,6 +46,7 @@
     "internal/symbolize.h"
   SRCS
     "symbolize.cc"
+    "symbolize_darwin.inc"
     "symbolize_elf.inc"
     "symbolize_unimplemented.inc"
     "symbolize_win32.inc"
@@ -44,14 +54,17 @@
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
+    $<$<BOOL:${MINGW}>:"dbghelp">
   DEPS
     absl::debugging_internal
     absl::demangle_internal
     absl::base
+    absl::config
     absl::core_headers
     absl::dynamic_annotations
     absl::malloc_internal
     absl::raw_logging_internal
+    absl::strings
   PUBLIC
 )
 
@@ -62,13 +75,18 @@
     "symbolize_test.cc"
   COPTS
     ${ABSL_TEST_COPTS}
+    $<$<BOOL:${MSVC}>:-Z7>
+  LINKOPTS
+    $<$<BOOL:${MSVC}>:-DEBUG>
   DEPS
     absl::stack_consumption
     absl::symbolize
     absl::base
+    absl::config
     absl::core_headers
     absl::memory
     absl::raw_logging_internal
+    absl::strings
     gmock
 )
 
@@ -84,6 +102,7 @@
   DEPS
     absl::stacktrace
     absl::symbolize
+    absl::config
     absl::core_headers
     absl::raw_logging_internal
 )
@@ -103,6 +122,7 @@
     absl::base
     absl::config
     absl::core_headers
+    absl::errno_saver
     absl::raw_logging_internal
   PUBLIC
 )
@@ -130,14 +150,6 @@
   HDRS
     "internal/address_is_readable.h"
     "internal/elf_mem_image.h"
-    "internal/stacktrace_aarch64-inl.inc"
-    "internal/stacktrace_arm-inl.inc"
-    "internal/stacktrace_config.h"
-    "internal/stacktrace_generic-inl.inc"
-    "internal/stacktrace_powerpc-inl.inc"
-    "internal/stacktrace_unimplemented-inl.inc"
-    "internal/stacktrace_win32-inl.inc"
-    "internal/stacktrace_x86-inl.inc"
     "internal/vdso_support.h"
   SRCS
     "internal/address_is_readable.cc"
@@ -147,7 +159,9 @@
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::core_headers
+    absl::config
     absl::dynamic_annotations
+    absl::errno_saver
     absl::raw_logging_internal
 )
 
@@ -176,6 +190,7 @@
   DEPS
     absl::demangle_internal
     absl::stack_consumption
+    absl::config
     absl::core_headers
     absl::memory
     absl::raw_logging_internal
@@ -192,6 +207,7 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
+    absl::config
     absl::core_headers
   PUBLIC
 )
@@ -238,7 +254,7 @@
   SRCS
     "leak_check_test.cc"
   COPTS
-    ${ABSL_DEFAULT_COPTS}
+    ${ABSL_TEST_COPTS}
     "$<$<BOOL:${ABSL_HAVE_LSAN}>:-DABSL_EXPECT_LEAK_SANITIZER>"
   LINKOPTS
     "${ABSL_LSAN_LINKOPTS}"
@@ -289,6 +305,7 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
+    absl::config
     absl::core_headers
     absl::raw_logging_internal
   TESTONLY
diff --git a/absl/debugging/failure_signal_handler.cc b/absl/debugging/failure_signal_handler.cc
index c6a4d96..5d13bdb 100644
--- a/absl/debugging/failure_signal_handler.cc
+++ b/absl/debugging/failure_signal_handler.cc
@@ -24,6 +24,10 @@
 #include <unistd.h>
 #endif
 
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#endif
+
 #ifdef ABSL_HAVE_MMAP
 #include <sys/mman.h>
 #endif
@@ -37,6 +41,7 @@
 #include <ctime>
 
 #include "absl/base/attributes.h"
+#include "absl/base/internal/errno_saver.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/sysinfo.h"
 #include "absl/debugging/internal/examine_stack.h"
@@ -44,9 +49,15 @@
 
 #ifndef _WIN32
 #define ABSL_HAVE_SIGACTION
+// Apple WatchOS and TVOS don't allow sigaltstack
+#if !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \
+    !(defined(TARGET_OS_TV) && TARGET_OS_TV)
+#define ABSL_HAVE_SIGALTSTACK
+#endif
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 ABSL_CONST_INIT static FailureSignalHandlerOptions fsh_options;
 
@@ -116,7 +127,7 @@
 
 }  // namespace debugging_internal
 
-#ifndef _WIN32
+#ifdef ABSL_HAVE_SIGALTSTACK
 
 static bool SetupAlternateStackOnce() {
 #if defined(__wasm__) || defined (__asjms__)
@@ -125,8 +136,8 @@
   const size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
 #endif
   size_t stack_size = (std::max(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
-    defined(THREAD_SANITIZER)
+#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
+    defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
   // Account for sanitizer instrumentation requiring additional stack space.
   stack_size *= 5;
 #endif
@@ -168,7 +179,7 @@
 // Returns the appropriate flag for sig_action.sa_flags
 // if the system supports using an alternate stack.
 static int MaybeSetupAlternateStack() {
-#ifndef _WIN32
+#ifdef ABSL_HAVE_SIGALTSTACK
   ABSL_ATTRIBUTE_UNUSED static const bool kOnce = SetupAlternateStackOnce();
   return SA_ONSTACK;
 #else
@@ -204,9 +215,8 @@
 #endif
 
 static void WriteToStderr(const char* data) {
-  int old_errno = errno;
+  absl::base_internal::ErrnoSaver errno_saver;
   absl::raw_logging_internal::SafeWriteToStderr(data, strlen(data));
-  errno = old_errno;
 }
 
 static void WriteSignalMessage(int signo, void (*writerfn)(const char*)) {
@@ -356,4 +366,5 @@
   }
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/debugging/failure_signal_handler.h b/absl/debugging/failure_signal_handler.h
index 1beb78b..0c0f585 100644
--- a/absl/debugging/failure_signal_handler.h
+++ b/absl/debugging/failure_signal_handler.h
@@ -44,7 +44,10 @@
 #ifndef ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_
 #define ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // FailureSignalHandlerOptions
 //
@@ -85,7 +88,7 @@
   bool call_previous_handler = false;
 
   // If non-null, indicates a pointer to a callback function that will be called
-  // upon failure, with a std::string argument containing failure data. This function
+  // upon failure, with a string argument containing failure data. This function
   // may be used as a hook to write failure data to a secondary location, such
   // as a log file. This function may also be called with null data, as a hint
   // to flush any buffered data before the program may be terminated. Consider
@@ -112,6 +115,7 @@
 const char* FailureSignalToString(int signo);
 }  // namespace debugging_internal
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_
diff --git a/absl/debugging/failure_signal_handler_test.cc b/absl/debugging/failure_signal_handler_test.cc
index bb2cc48..d8283b2 100644
--- a/absl/debugging/failure_signal_handler_test.cc
+++ b/absl/debugging/failure_signal_handler_test.cc
@@ -23,6 +23,7 @@
 #include <fstream>
 
 #include "gtest/gtest.h"
+#include "gmock/gmock.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/debugging/stacktrace.h"
 #include "absl/debugging/symbolize.h"
@@ -31,6 +32,8 @@
 
 namespace {
 
+using testing::StartsWith;
+
 #if GTEST_HAS_DEATH_TEST
 
 // For the parameterized death tests. GetParam() returns the signal number.
@@ -52,7 +55,7 @@
               exit_regex);
 #else
   // Windows doesn't have testing::KilledBySignal().
-  EXPECT_DEATH(InstallHandlerAndRaise(signo), exit_regex);
+  EXPECT_DEATH_IF_SUPPORTED(InstallHandlerAndRaise(signo), exit_regex);
 #endif
 }
 
@@ -104,8 +107,8 @@
               testing::KilledBySignal(signo), exit_regex);
 #else
   // Windows doesn't have testing::KilledBySignal().
-  EXPECT_DEATH(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),
-               exit_regex);
+  EXPECT_DEATH_IF_SUPPORTED(
+      InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo), exit_regex);
 #endif
 
   // Open the file in this process and check its contents.
@@ -113,15 +116,15 @@
   ASSERT_TRUE(error_output.is_open()) << file;
   std::string error_line;
   std::getline(error_output, error_line);
-  EXPECT_TRUE(absl::StartsWith(
+  EXPECT_THAT(
       error_line,
-      absl::StrCat("*** ",
-                   absl::debugging_internal::FailureSignalToString(signo),
-                   " received at ")));
+      StartsWith(absl::StrCat(
+          "*** ", absl::debugging_internal::FailureSignalToString(signo),
+          " received at ")));
 
   if (absl::debugging_internal::StackTraceWorksForTest()) {
     std::getline(error_output, error_line);
-    EXPECT_TRUE(absl::StartsWith(error_line, "PC: "));
+    EXPECT_THAT(error_line, StartsWith("PC: "));
   }
 }
 
diff --git a/absl/debugging/internal/address_is_readable.cc b/absl/debugging/internal/address_is_readable.cc
index 99c4c64..329c285 100644
--- a/absl/debugging/internal/address_is_readable.cc
+++ b/absl/debugging/internal/address_is_readable.cc
@@ -20,12 +20,14 @@
 #if !defined(__linux__) || defined(__ANDROID__)
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 // On platforms other than Linux, just return true.
 bool AddressIsReadable(const void* /* addr */) { return true; }
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #else
@@ -33,13 +35,16 @@
 #include <fcntl.h>
 #include <sys/syscall.h>
 #include <unistd.h>
+
 #include <atomic>
 #include <cerrno>
 #include <cstdint>
 
+#include "absl/base/internal/errno_saver.h"
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 // Pack a pid and two file descriptors into a 64-bit word,
@@ -63,8 +68,9 @@
 // unimplemented.
 // This is a namespace-scoped variable for correct zero-initialization.
 static std::atomic<uint64_t> pid_and_fds;  // initially 0, an invalid pid.
+
 bool AddressIsReadable(const void *addr) {
-  int save_errno = errno;
+  absl::base_internal::ErrnoSaver errno_saver;
   // We test whether a byte is readable by using write().  Normally, this would
   // be done via a cached file descriptor to /dev/null, but linux fails to
   // check whether the byte is readable when the destination is /dev/null, so
@@ -81,7 +87,7 @@
     int pid;
     int read_fd;
     int write_fd;
-    uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
+    uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_acquire);
     Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
     while (current_pid != pid) {
       int p[2];
@@ -93,13 +99,13 @@
       fcntl(p[1], F_SETFD, FD_CLOEXEC);
       uint64_t new_pid_and_fds = Pack(current_pid, p[0], p[1]);
       if (pid_and_fds.compare_exchange_strong(
-              local_pid_and_fds, new_pid_and_fds, std::memory_order_relaxed,
+              local_pid_and_fds, new_pid_and_fds, std::memory_order_release,
               std::memory_order_relaxed)) {
         local_pid_and_fds = new_pid_and_fds;  // fds exposed to other threads
       } else {  // fds not exposed to other threads; we can close them.
         close(p[0]);
         close(p[1]);
-        local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
+        local_pid_and_fds = pid_and_fds.load(std::memory_order_acquire);
       }
       Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
     }
@@ -119,15 +125,15 @@
       // If pid_and_fds contains the problematic file descriptors we just used,
       // this call will forget them, and the loop will try again.
       pid_and_fds.compare_exchange_strong(local_pid_and_fds, 0,
-                                          std::memory_order_relaxed,
+                                          std::memory_order_release,
                                           std::memory_order_relaxed);
     }
   } while (errno == EBADF);
-  errno = save_errno;
   return bytes_written == 1;
 }
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif
diff --git a/absl/debugging/internal/address_is_readable.h b/absl/debugging/internal/address_is_readable.h
index ca8003e..4bbaf4d 100644
--- a/absl/debugging/internal/address_is_readable.h
+++ b/absl/debugging/internal/address_is_readable.h
@@ -15,7 +15,10 @@
 #ifndef ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
 #define ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 // Return whether the byte at *addr is readable, without faulting.
@@ -23,6 +26,7 @@
 bool AddressIsReadable(const void *addr);
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc
index 52a553f..46cdb67 100644
--- a/absl/debugging/internal/demangle.cc
+++ b/absl/debugging/internal/demangle.cc
@@ -24,6 +24,7 @@
 #include <limits>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 typedef struct {
@@ -93,6 +94,8 @@
 };
 
 // List of builtin types from Itanium C++ ABI.
+//
+// Invariant: only one- or two-character type abbreviations here.
 static const AbbrevPair kBuiltinTypeList[] = {
     {"v", "void", 0},
     {"w", "wchar_t", 0},
@@ -115,6 +118,17 @@
     {"e", "long double", 0},
     {"g", "__float128", 0},
     {"z", "ellipsis", 0},
+
+    {"De", "decimal128", 0},      // IEEE 754r decimal floating point (128 bits)
+    {"Dd", "decimal64", 0},       // IEEE 754r decimal floating point (64 bits)
+    {"Dc", "decltype(auto)", 0},
+    {"Da", "auto", 0},
+    {"Dn", "std::nullptr_t", 0},  // i.e., decltype(nullptr)
+    {"Df", "decimal32", 0},       // IEEE 754r decimal floating point (32 bits)
+    {"Di", "char32_t", 0},
+    {"Du", "char8_t", 0},
+    {"Ds", "char16_t", 0},
+    {"Dh", "float16", 0},         // IEEE 754r half-precision float (16 bits)
     {nullptr, nullptr, 0},
 };
 
@@ -138,7 +152,7 @@
 // frame, so every byte counts.
 typedef struct {
   int mangled_idx;                   // Cursor of mangled name.
-  int out_cur_idx;                   // Cursor of output std::string.
+  int out_cur_idx;                   // Cursor of output string.
   int prev_name_idx;                 // For constructors/destructors.
   signed int prev_name_length : 16;  // For constructors/destructors.
   signed int nest_level : 15;        // For nested names.
@@ -159,8 +173,8 @@
 // Only one copy of this exists for each call to Demangle, so the size of this
 // struct is nearly inconsequential.
 typedef struct {
-  const char *mangled_begin;  // Beginning of input std::string.
-  char *out;                  // Beginning of output std::string.
+  const char *mangled_begin;  // Beginning of input string.
+  char *out;                  // Beginning of output string.
   int out_end_idx;            // One past last allowed output character.
   int recursion_depth;        // For stack exhaustion prevention.
   int steps;               // Cap how much work we'll do, regardless of depth.
@@ -396,6 +410,7 @@
 
 static bool EndsWith(State *state, const char chr) {
   return state->parse_state.out_cur_idx > 0 &&
+         state->parse_state.out_cur_idx < state->out_end_idx &&
          chr == state->out[state->parse_state.out_cur_idx - 1];
 }
 
@@ -408,8 +423,10 @@
     if (str[0] == '<' && EndsWith(state, '<')) {
       Append(state, " ", 1);
     }
-    // Remember the last identifier name for ctors/dtors.
-    if (IsAlpha(str[0]) || str[0] == '_') {
+    // Remember the last identifier name for ctors/dtors,
+    // but only if we haven't yet overflown the buffer.
+    if (state->parse_state.out_cur_idx < state->out_end_idx &&
+        (IsAlpha(str[0]) || str[0] == '_')) {
       state->parse_state.prev_name_idx = state->parse_state.out_cur_idx;
       state->parse_state.prev_name_length = length;
     }
@@ -949,6 +966,7 @@
 //                ::= TT <type>
 //                ::= TI <type>
 //                ::= TS <type>
+//                ::= TH <type>  # thread-local
 //                ::= Tc <call-offset> <call-offset> <(base) encoding>
 //                ::= GV <(object) name>
 //                ::= T <call-offset> <(base) encoding>
@@ -967,7 +985,7 @@
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
   ParseState copy = state->parse_state;
-  if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "VTIS") &&
+  if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "VTISH") &&
       ParseType(state)) {
     return true;
   }
@@ -1064,20 +1082,28 @@
   return false;
 }
 
-// <ctor-dtor-name> ::= C1 | C2 | C3
+// <ctor-dtor-name> ::= C1 | C2 | C3 | CI1 <base-class-type> | CI2
+// <base-class-type>
 //                  ::= D0 | D1 | D2
 // # GCC extensions: "unified" constructor/destructor.  See
-// # https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847
+// #
+// https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847
 //                  ::= C4 | D4
 static bool ParseCtorDtorName(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
   ParseState copy = state->parse_state;
-  if (ParseOneCharToken(state, 'C') && ParseCharClass(state, "1234")) {
-    const char *const prev_name = state->out + state->parse_state.prev_name_idx;
-    MaybeAppendWithLength(state, prev_name,
-                          state->parse_state.prev_name_length);
-    return true;
+  if (ParseOneCharToken(state, 'C')) {
+    if (ParseCharClass(state, "1234")) {
+      const char *const prev_name =
+          state->out + state->parse_state.prev_name_idx;
+      MaybeAppendWithLength(state, prev_name,
+                            state->parse_state.prev_name_length);
+      return true;
+    } else if (ParseOneCharToken(state, 'I') && ParseCharClass(state, "12") &&
+               ParseClassEnumType(state)) {
+      return true;
+    }
   }
   state->parse_state = copy;
 
@@ -1126,6 +1152,7 @@
 //        ::= <decltype>
 //        ::= <substitution>
 //        ::= Dp <type>          # pack expansion of (C++0x)
+//        ::= Dv <num-elems> _   # GNU vector extension
 //
 static bool ParseType(State *state) {
   ComplexityGuard guard(state);
@@ -1168,12 +1195,6 @@
   }
   state->parse_state = copy;
 
-  // nullptr_t, i.e. decltype(nullptr).
-  if (ParseTwoCharToken(state, "Dn")) {
-    return true;
-  }
-  state->parse_state = copy;
-
   if (ParseOneCharToken(state, 'U') && ParseSourceName(state) &&
       ParseType(state)) {
     return true;
@@ -1198,6 +1219,12 @@
     return true;
   }
 
+  if (ParseTwoCharToken(state, "Dv") && ParseNumber(state, nullptr) &&
+      ParseOneCharToken(state, '_')) {
+    return true;
+  }
+  state->parse_state = copy;
+
   return false;
 }
 
@@ -1214,16 +1241,26 @@
   return num_cv_qualifiers > 0;
 }
 
-// <builtin-type> ::= v, etc.
+// <builtin-type> ::= v, etc.  # single-character builtin types
 //                ::= u <source-name>
+//                ::= Dd, etc.  # two-character builtin types
+//
+// Not supported:
+//                ::= DF <number> _ # _FloatN (N bits)
+//
 static bool ParseBuiltinType(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
   const AbbrevPair *p;
   for (p = kBuiltinTypeList; p->abbrev != nullptr; ++p) {
-    if (RemainingInput(state)[0] == p->abbrev[0]) {
+    // Guaranteed only 1- or 2-character strings in kBuiltinTypeList.
+    if (p->abbrev[1] == '\0') {
+      if (ParseOneCharToken(state, p->abbrev[0])) {
+        MaybeAppend(state, p->real_name);
+        return true;
+      }
+    } else if (p->abbrev[2] == '\0' && ParseTwoCharToken(state, p->abbrev)) {
       MaybeAppend(state, p->real_name);
-      ++state->parse_state.mangled_idx;
       return true;
     }
   }
@@ -1236,13 +1273,42 @@
   return false;
 }
 
-// <function-type> ::= F [Y] <bare-function-type> E
+//  <exception-spec> ::= Do                # non-throwing
+//                                           exception-specification (e.g.,
+//                                           noexcept, throw())
+//                   ::= DO <expression> E # computed (instantiation-dependent)
+//                                           noexcept
+//                   ::= Dw <type>+ E      # dynamic exception specification
+//                                           with instantiation-dependent types
+static bool ParseExceptionSpec(State *state) {
+  ComplexityGuard guard(state);
+  if (guard.IsTooComplex()) return false;
+
+  if (ParseTwoCharToken(state, "Do")) return true;
+
+  ParseState copy = state->parse_state;
+  if (ParseTwoCharToken(state, "DO") && ParseExpression(state) &&
+      ParseOneCharToken(state, 'E')) {
+    return true;
+  }
+  state->parse_state = copy;
+  if (ParseTwoCharToken(state, "Dw") && OneOrMore(ParseType, state) &&
+      ParseOneCharToken(state, 'E')) {
+    return true;
+  }
+  state->parse_state = copy;
+
+  return false;
+}
+
+// <function-type> ::= [exception-spec] F [Y] <bare-function-type> [O] E
 static bool ParseFunctionType(State *state) {
   ComplexityGuard guard(state);
   if (guard.IsTooComplex()) return false;
   ParseState copy = state->parse_state;
-  if (ParseOneCharToken(state, 'F') &&
+  if (Optional(ParseExceptionSpec(state)) && ParseOneCharToken(state, 'F') &&
       Optional(ParseOneCharToken(state, 'Y')) && ParseBareFunctionType(state) &&
+      Optional(ParseOneCharToken(state, 'O')) &&
       ParseOneCharToken(state, 'E')) {
     return true;
   }
@@ -1870,8 +1936,10 @@
 bool Demangle(const char *mangled, char *out, int out_size) {
   State state;
   InitState(&state, mangled, out, out_size);
-  return ParseTopLevelMangledName(&state) && !Overflowed(&state);
+  return ParseTopLevelMangledName(&state) && !Overflowed(&state) &&
+         state.parse_state.out_cur_idx > 0;
 }
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/debugging/internal/demangle.h b/absl/debugging/internal/demangle.h
index 81bb0df..c314d9b 100644
--- a/absl/debugging/internal/demangle.h
+++ b/absl/debugging/internal/demangle.h
@@ -53,7 +53,10 @@
 #ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_
 #define ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 // Demangle `mangled`.  On success, return true and write the
@@ -62,6 +65,7 @@
 bool Demangle(const char *mangled, char *out, int out_size);
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_
diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc
index a68ce32..0bed735 100644
--- a/absl/debugging/internal/demangle_test.cc
+++ b/absl/debugging/internal/demangle_test.cc
@@ -18,11 +18,13 @@
 #include <string>
 
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/debugging/internal/stack_consumption.h"
 #include "absl/memory/memory.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 namespace {
 
@@ -81,9 +83,10 @@
 // Tests that verify that Demangle footprint is within some limit.
 // They are not to be run under sanitizers as the sanitizers increase
 // stack consumption by about 4x.
-#if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) &&   \
-    !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) && \
-    !defined(THREAD_SANITIZER)
+#if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) && \
+    !defined(ABSL_HAVE_ADDRESS_SANITIZER) &&                   \
+    !defined(ABSL_HAVE_MEMORY_SANITIZER) &&                    \
+    !defined(ABSL_HAVE_THREAD_SANITIZER)
 
 static const char *g_mangled;
 static char g_demangle_buffer[4096];
@@ -190,4 +193,5 @@
 
 }  // namespace
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/debugging/internal/elf_mem_image.cc b/absl/debugging/internal/elf_mem_image.cc
index e7408bc..24cc013 100644
--- a/absl/debugging/internal/elf_mem_image.cc
+++ b/absl/debugging/internal/elf_mem_image.cc
@@ -38,6 +38,7 @@
 #define VERSYM_VERSION 0x7fff
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 namespace {
@@ -375,6 +376,7 @@
 }
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_HAVE_ELF_MEM_IMAGE
diff --git a/absl/debugging/internal/elf_mem_image.h b/absl/debugging/internal/elf_mem_image.h
index d84200d..46bfade 100644
--- a/absl/debugging/internal/elf_mem_image.h
+++ b/absl/debugging/internal/elf_mem_image.h
@@ -23,6 +23,8 @@
 // used.
 #include <climits>
 
+#include "absl/base/config.h"
+
 // Maybe one day we can rewrite this file not to require the elf
 // symbol extensions in glibc, but for right now we need them.
 #ifdef ABSL_HAVE_ELF_MEM_IMAGE
@@ -39,6 +41,7 @@
 #include <link.h>  // for ElfW
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 // An in-memory ELF image (may not exist on disk).
@@ -123,6 +126,7 @@
 };
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_HAVE_ELF_MEM_IMAGE
diff --git a/absl/debugging/internal/examine_stack.cc b/absl/debugging/internal/examine_stack.cc
index 1ebc788..6e5ff1f 100644
--- a/absl/debugging/internal/examine_stack.cc
+++ b/absl/debugging/internal/examine_stack.cc
@@ -20,6 +20,10 @@
 #include <unistd.h>
 #endif
 
+#ifdef __APPLE__
+#include <sys/ucontext.h>
+#endif
+
 #include <csignal>
 #include <cstdio>
 
@@ -30,6 +34,7 @@
 #include "absl/debugging/symbolize.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 // Returns the program counter from signal context, nullptr if
@@ -52,6 +57,8 @@
     return reinterpret_cast<void*>(context->uc_mcontext.gp_regs[32]);
 #elif defined(__powerpc__)
     return reinterpret_cast<void*>(context->uc_mcontext.regs->nip);
+#elif defined(__riscv)
+    return reinterpret_cast<void*>(context->uc_mcontext.__gregs[REG_PC]);
 #elif defined(__s390__) && !defined(__s390x__)
     return reinterpret_cast<void*>(context->uc_mcontext.psw.addr & 0x7fffffff);
 #elif defined(__s390__) && defined(__s390x__)
@@ -63,6 +70,32 @@
 #error "Undefined Architecture."
 #endif
   }
+#elif defined(__APPLE__)
+  if (vuc != nullptr) {
+    ucontext_t* signal_ucontext = reinterpret_cast<ucontext_t*>(vuc);
+#if defined(__aarch64__)
+    return reinterpret_cast<void*>(
+        __darwin_arm_thread_state64_get_pc(signal_ucontext->uc_mcontext->__ss));
+#elif defined(__arm__)
+#if __DARWIN_UNIX03
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__pc);
+#else
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.pc);
+#endif
+#elif defined(__i386__)
+#if __DARWIN_UNIX03
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__eip);
+#else
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.eip);
+#endif
+#elif defined(__x86_64__)
+#if __DARWIN_UNIX03
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__rip);
+#else
+    return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.rip);
+#endif
+#endif
+  }
 #elif defined(__akaros__)
   auto* ctx = reinterpret_cast<struct user_context*>(vuc);
   return reinterpret_cast<void*>(get_user_ctx_pc(ctx));
@@ -150,4 +183,5 @@
 }
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/debugging/internal/examine_stack.h b/absl/debugging/internal/examine_stack.h
index 56c9763..3933691 100644
--- a/absl/debugging/internal/examine_stack.h
+++ b/absl/debugging/internal/examine_stack.h
@@ -17,7 +17,10 @@
 #ifndef ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_
 #define ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 // Returns the program counter from signal context, or nullptr if
@@ -33,6 +36,7 @@
     void (*writerfn)(const char*, void*), void* writerfn_arg);
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_
diff --git a/absl/debugging/internal/stack_consumption.cc b/absl/debugging/internal/stack_consumption.cc
index 4b05f49..e3dd51c 100644
--- a/absl/debugging/internal/stack_consumption.cc
+++ b/absl/debugging/internal/stack_consumption.cc
@@ -27,6 +27,7 @@
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 namespace {
 
@@ -41,7 +42,8 @@
 // one of them is null, the results of p<q, p>q, p<=q, and p>=q are
 // unspecified. Therefore, instead we hardcode the direction of the
 // stack on platforms we know about.
-#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \
+    defined(__aarch64__)
 constexpr bool kStackGrowsDown = true;
 #else
 #error Need to define kStackGrowsDown
@@ -115,10 +117,11 @@
   // Set up the alt-signal-stack (and save the older one).
   stack_t sigstk;
   memset(&sigstk, 0, sizeof(sigstk));
-  stack_t old_sigstk;
   sigstk.ss_sp = altstack;
   sigstk.ss_size = kAlternateStackSize;
   sigstk.ss_flags = 0;
+  stack_t old_sigstk;
+  memset(&old_sigstk, 0, sizeof(old_sigstk));
   ABSL_RAW_CHECK(sigaltstack(&sigstk, &old_sigstk) == 0,
                  "sigaltstack() failed");
 
@@ -152,6 +155,15 @@
   int signal_handler_stack_consumption = GetStackConsumption(altstack);
 
   // Now restore the old alt-signal-stack and signal handlers.
+  if (old_sigstk.ss_sp == nullptr && old_sigstk.ss_size == 0 &&
+      (old_sigstk.ss_flags & SS_DISABLE)) {
+    // https://git.musl-libc.org/cgit/musl/commit/src/signal/sigaltstack.c?id=7829f42a2c8944555439380498ab8b924d0f2070
+    // The original stack has ss_size==0 and ss_flags==SS_DISABLE, but some
+    // versions of musl have a bug that rejects ss_size==0. Work around this by
+    // setting ss_size to MINSIGSTKSZ, which should be ignored by the kernel
+    // when SS_DISABLE is set.
+    old_sigstk.ss_size = MINSIGSTKSZ;
+  }
   ABSL_RAW_CHECK(sigaltstack(&old_sigstk, nullptr) == 0,
                  "sigaltstack() failed");
   ABSL_RAW_CHECK(sigaction(SIGUSR1, &old_sa1, nullptr) == 0,
@@ -167,6 +179,7 @@
 }
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
diff --git a/absl/debugging/internal/stack_consumption.h b/absl/debugging/internal/stack_consumption.h
index b860a3c..2b5e715 100644
--- a/absl/debugging/internal/stack_consumption.h
+++ b/absl/debugging/internal/stack_consumption.h
@@ -18,15 +18,19 @@
 #ifndef ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_
 #define ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_
 
+#include "absl/base/config.h"
+
 // The code in this module is not portable.
 // Use this feature test macro to detect its availability.
 #ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
 #error ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION cannot be set directly
-#elif !defined(__APPLE__) && !defined(_WIN32) && \
-    (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))
+#elif !defined(__APPLE__) && !defined(_WIN32) &&                     \
+    (defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \
+     defined(__aarch64__))
 #define ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 1
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 // Returns the stack consumption in bytes for the code exercised by
@@ -38,6 +42,7 @@
 int GetSignalHandlerStackConsumption(void (*signal_handler)(int));
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
diff --git a/absl/debugging/internal/stack_consumption_test.cc b/absl/debugging/internal/stack_consumption_test.cc
index 68bfa12..80445bf 100644
--- a/absl/debugging/internal/stack_consumption_test.cc
+++ b/absl/debugging/internal/stack_consumption_test.cc
@@ -23,6 +23,7 @@
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 namespace {
 
@@ -43,6 +44,7 @@
 
 }  // namespace
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
diff --git a/absl/debugging/internal/stacktrace_aarch64-inl.inc b/absl/debugging/internal/stacktrace_aarch64-inl.inc
index 7ed6b3e..f4859d7 100644
--- a/absl/debugging/internal/stacktrace_aarch64-inl.inc
+++ b/absl/debugging/internal/stacktrace_aarch64-inl.inc
@@ -37,8 +37,11 @@
   absl::debugging_internal::VDSOSupport vdso;
   if (vdso.IsPresent()) {
     absl::debugging_internal::VDSOSupport::SymbolInfo symbol_info;
-    if (!vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_2.6.39", STT_FUNC,
-                           &symbol_info) ||
+    auto lookup = [&](int type) {
+      return vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_2.6.39", type,
+                               &symbol_info);
+    };
+    if ((!lookup(STT_FUNC) && !lookup(STT_NOTYPE)) ||
         symbol_info.address == nullptr) {
       // Unexpected: VDSO is present, yet the expected symbol is missing
       // or null.
@@ -74,6 +77,8 @@
 // checks (the strictness of which is controlled by the boolean parameter
 // "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
 template<bool STRICT_UNWINDING, bool WITH_CONTEXT>
+ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
+ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
 static void **NextStackFrame(void **old_frame_pointer, const void *uc) {
   void **new_frame_pointer = reinterpret_cast<void**>(*old_frame_pointer);
   bool check_frame_size = true;
@@ -123,6 +128,8 @@
 }
 
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
+ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS  // May read random elements from stack.
+ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY   // May read random elements from stack.
 static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
                       const void *ucp, int *min_dropped_frames) {
 #ifdef __GNUC__
@@ -180,11 +187,13 @@
 }
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 bool StackTraceWorksForTest() {
   return true;
 }
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_AARCH64_INL_H_
diff --git a/absl/debugging/internal/stacktrace_arm-inl.inc b/absl/debugging/internal/stacktrace_arm-inl.inc
index c840833..2a1bf2e 100644
--- a/absl/debugging/internal/stacktrace_arm-inl.inc
+++ b/absl/debugging/internal/stacktrace_arm-inl.inc
@@ -1,9 +1,18 @@
-// Copyright 2011 and onwards Google Inc.
-// All rights reserved.
+// Copyright 2017 The Abseil Authors.
 //
-// Author: Doug Kwan
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
 // This is inspired by Craig Silverstein's PowerPC stacktrace code.
-//
 
 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_ARM_INL_H_
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_ARM_INL_H_
@@ -113,11 +122,13 @@
 }
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 bool StackTraceWorksForTest() {
   return false;
 }
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_ARM_INL_H_
diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h
index d4e8480..cca410d 100644
--- a/absl/debugging/internal/stacktrace_config.h
+++ b/absl/debugging/internal/stacktrace_config.h
@@ -21,6 +21,8 @@
 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
 
+#include "absl/base/config.h"
+
 #if defined(ABSL_STACKTRACE_INL_HEADER)
 #error ABSL_STACKTRACE_INL_HEADER cannot be directly set
 
@@ -28,43 +30,51 @@
 #define ABSL_STACKTRACE_INL_HEADER \
     "absl/debugging/internal/stacktrace_win32-inl.inc"
 
+#elif defined(__APPLE__)
+#ifdef ABSL_HAVE_THREAD_LOCAL
+// Thread local support required for UnwindImpl.
+#define ABSL_STACKTRACE_INL_HEADER \
+  "absl/debugging/internal/stacktrace_generic-inl.inc"
+#endif
+
 #elif defined(__linux__) && !defined(__ANDROID__)
 
-#if !defined(NO_FRAME_POINTER)
-# if defined(__i386__) || defined(__x86_64__)
+#if defined(NO_FRAME_POINTER) && \
+    (defined(__i386__) || defined(__x86_64__) || defined(__aarch64__))
+// Note: The libunwind-based implementation is not available to open-source
+// users.
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_x86-inl.inc"
-# elif defined(__ppc__) || defined(__PPC__)
-#define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_powerpc-inl.inc"
-# elif defined(__aarch64__)
-#define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_aarch64-inl.inc"
-# elif defined(__arm__)
+  "absl/debugging/internal/stacktrace_libunwind-inl.inc"
+#define STACKTRACE_USES_LIBUNWIND 1
+#elif defined(NO_FRAME_POINTER) && defined(__has_include)
+#if __has_include(<execinfo.h>)
 // Note: When using glibc this may require -funwind-tables to function properly.
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_generic-inl.inc"
-# else
+#endif
+#elif defined(__i386__) || defined(__x86_64__)
 #define ABSL_STACKTRACE_INL_HEADER \
-   "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-# endif
-#else  // defined(NO_FRAME_POINTER)
-# if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
+  "absl/debugging/internal/stacktrace_x86-inl.inc"
+#elif defined(__ppc__) || defined(__PPC__)
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_generic-inl.inc"
-# elif defined(__ppc__) || defined(__PPC__)
+  "absl/debugging/internal/stacktrace_powerpc-inl.inc"
+#elif defined(__aarch64__)
 #define ABSL_STACKTRACE_INL_HEADER \
-    "absl/debugging/internal/stacktrace_generic-inl.inc"
-# else
+  "absl/debugging/internal/stacktrace_aarch64-inl.inc"
+#elif defined(__has_include)
+#if __has_include(<execinfo.h>)
+// Note: When using glibc this may require -funwind-tables to function properly.
 #define ABSL_STACKTRACE_INL_HEADER \
-   "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-# endif
-#endif  // NO_FRAME_POINTER
+  "absl/debugging/internal/stacktrace_generic-inl.inc"
+#endif
+#endif
 
-#else
+#endif
+
+// Fallback to the empty implementation.
+#if !defined(ABSL_STACKTRACE_INL_HEADER)
 #define ABSL_STACKTRACE_INL_HEADER \
   "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-
 #endif
 
 #endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
diff --git a/absl/debugging/internal/stacktrace_generic-inl.inc b/absl/debugging/internal/stacktrace_generic-inl.inc
index 81a49ef..b2792a1 100644
--- a/absl/debugging/internal/stacktrace_generic-inl.inc
+++ b/absl/debugging/internal/stacktrace_generic-inl.inc
@@ -1,7 +1,16 @@
-// Copyright 2000 - 2007 Google Inc.
-// All rights reserved.
+// Copyright 2017 The Abseil Authors.
 //
-// Author: Sanjay Ghemawat
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
 //
 // Portable implementation - just use glibc
 //
@@ -87,11 +96,13 @@
 }
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 bool StackTraceWorksForTest() {
   return true;
 }
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_
diff --git a/absl/debugging/internal/stacktrace_powerpc-inl.inc b/absl/debugging/internal/stacktrace_powerpc-inl.inc
index 3a070ee..2e7c2f4 100644
--- a/absl/debugging/internal/stacktrace_powerpc-inl.inc
+++ b/absl/debugging/internal/stacktrace_powerpc-inl.inc
@@ -236,11 +236,13 @@
 }
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 bool StackTraceWorksForTest() {
   return true;
 }
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_
diff --git a/absl/debugging/internal/stacktrace_unimplemented-inl.inc b/absl/debugging/internal/stacktrace_unimplemented-inl.inc
index e256fdd..5b8fb19 100644
--- a/absl/debugging/internal/stacktrace_unimplemented-inl.inc
+++ b/absl/debugging/internal/stacktrace_unimplemented-inl.inc
@@ -12,11 +12,13 @@
 }
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 bool StackTraceWorksForTest() {
   return false;
 }
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_UNIMPLEMENTED_INL_H_
diff --git a/absl/debugging/internal/stacktrace_win32-inl.inc b/absl/debugging/internal/stacktrace_win32-inl.inc
index b46491f..1c666c8 100644
--- a/absl/debugging/internal/stacktrace_win32-inl.inc
+++ b/absl/debugging/internal/stacktrace_win32-inl.inc
@@ -46,15 +46,23 @@
     OUT PVOID *backtrace,
     OUT PULONG backtrace_hash);
 
+// It is not possible to load RtlCaptureStackBackTrace at static init time in
+// UWP. CaptureStackBackTrace is the public version of RtlCaptureStackBackTrace
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
+    !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
+    &::CaptureStackBackTrace;
+#else
 // Load the function we need at static init time, where we don't have
 // to worry about someone else holding the loader's lock.
 static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
-   (RtlCaptureStackBackTrace_Function*)
-   GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
+    (RtlCaptureStackBackTrace_Function*)GetProcAddress(
+        GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
+#endif  // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
 
 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
 static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
-                      const void *ucp, int *min_dropped_frames) {
+                      const void*, int* min_dropped_frames) {
   int n = 0;
   if (!RtlCaptureStackBackTrace_fn) {
     // can't find a stacktrace with no function to call
@@ -73,11 +81,13 @@
 }
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 bool StackTraceWorksForTest() {
   return false;
 }
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_
diff --git a/absl/debugging/internal/stacktrace_x86-inl.inc b/absl/debugging/internal/stacktrace_x86-inl.inc
index 9494441..bc320ff 100644
--- a/absl/debugging/internal/stacktrace_x86-inl.inc
+++ b/absl/debugging/internal/stacktrace_x86-inl.inc
@@ -173,6 +173,7 @@
     static const unsigned char *kernel_rt_sigreturn_address = nullptr;
     static const unsigned char *kernel_vsyscall_address = nullptr;
     if (num_push_instructions == -1) {
+#ifdef ABSL_HAVE_VDSO_SUPPORT
       absl::debugging_internal::VDSOSupport vdso;
       if (vdso.IsPresent()) {
         absl::debugging_internal::VDSOSupport::SymbolInfo
@@ -201,6 +202,9 @@
       } else {
         num_push_instructions = 0;
       }
+#else  // ABSL_HAVE_VDSO_SUPPORT
+      num_push_instructions = 0;
+#endif  // ABSL_HAVE_VDSO_SUPPORT
     }
     if (num_push_instructions != 0 && kernel_rt_sigreturn_address != nullptr &&
         old_fp[1] == kernel_rt_sigreturn_address) {
@@ -330,11 +334,13 @@
 }
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 bool StackTraceWorksForTest() {
   return true;
 }
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_
diff --git a/absl/debugging/internal/symbolize.h b/absl/debugging/internal/symbolize.h
index 3e53789..4f26130 100644
--- a/absl/debugging/internal/symbolize.h
+++ b/absl/debugging/internal/symbolize.h
@@ -18,9 +18,14 @@
 #ifndef ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
 #define ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
 
+#ifdef __cplusplus
+
 #include <cstddef>
 #include <cstdint>
 
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+
 #ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
 #error ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE cannot be directly set
 #elif defined(__ELF__) && defined(__GLIBC__) && !defined(__native_client__) && \
@@ -33,6 +38,7 @@
 #include <string>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 // Iterates over all sections, invoking callback on each with the section name
@@ -42,7 +48,7 @@
 //
 // This is not async-signal-safe.
 bool ForEachSection(int fd,
-                    const std::function<bool(const std::string& name,
+                    const std::function<bool(absl::string_view name,
                                              const ElfW(Shdr) &)>& callback);
 
 // Gets the section header for the given name, if it exists. Returns true on
@@ -51,11 +57,19 @@
                             ElfW(Shdr) *out);
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
 
+#ifdef ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
+#error ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE cannot be directly set
+#elif defined(__APPLE__)
+#define ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE 1
+#endif
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 struct SymbolDecoratorArgs {
@@ -104,19 +118,30 @@
 //   filename != nullptr
 //
 // Returns true if the file was successfully registered.
-bool RegisterFileMappingHint(
-    const void* start, const void* end, uint64_t offset, const char* filename);
+bool RegisterFileMappingHint(const void* start, const void* end,
+                             uint64_t offset, const char* filename);
 
 // Looks up the file mapping registered by RegisterFileMappingHint for an
 // address range. If there is one, the file name is stored in *filename and
 // *start and *end are modified to reflect the registered mapping. Returns
 // whether any hint was found.
-bool GetFileMappingHint(const void** start,
-                        const void** end,
-                        uint64_t    *  offset,
+bool GetFileMappingHint(const void** start, const void** end, uint64_t* offset,
                         const char** filename);
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
+#endif  // __cplusplus
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C"
+#endif  // __cplusplus
+
+    bool
+    AbslInternalGetFileMappingHint(const void** start, const void** end,
+                                   uint64_t* offset, const char** filename);
+
 #endif  // ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
diff --git a/absl/debugging/internal/vdso_support.cc b/absl/debugging/internal/vdso_support.cc
index d13ef25..6be16d9 100644
--- a/absl/debugging/internal/vdso_support.cc
+++ b/absl/debugging/internal/vdso_support.cc
@@ -38,6 +38,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 ABSL_CONST_INIT
@@ -75,15 +76,6 @@
   }
 #endif  // __GLIBC_PREREQ(2, 16)
   if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {
-    // Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[]
-    // on stack, and so glibc works as if VDSO was not present.
-    // But going directly to kernel via /proc/self/auxv below bypasses
-    // Valgrind zapping. So we check for Valgrind separately.
-    if (RunningOnValgrind()) {
-      vdso_base_.store(nullptr, std::memory_order_relaxed);
-      getcpu_fn_.store(&GetCPUViaSyscall, std::memory_order_relaxed);
-      return nullptr;
-    }
     int fd = open("/proc/self/auxv", O_RDONLY);
     if (fd == -1) {
       // Kernel too old to have a VDSO.
@@ -174,19 +166,8 @@
   return ret_code == 0 ? cpu : ret_code;
 }
 
-// We need to make sure VDSOSupport::Init() is called before
-// InitGoogle() does any setuid or chroot calls.  If VDSOSupport
-// is used in any global constructor, this will happen, since
-// VDSOSupport's constructor calls Init.  But if not, we need to
-// ensure it here, with a global constructor of our own.  This
-// is an allowed exception to the normal rule against non-trivial
-// global constructors.
-static class VDSOInitHelper {
- public:
-  VDSOInitHelper() { VDSOSupport::Init(); }
-} vdso_init_helper;
-
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_HAVE_VDSO_SUPPORT
diff --git a/absl/debugging/internal/vdso_support.h b/absl/debugging/internal/vdso_support.h
index 9895b48..6562c6c 100644
--- a/absl/debugging/internal/vdso_support.h
+++ b/absl/debugging/internal/vdso_support.h
@@ -53,6 +53,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace debugging_internal {
 
 // NOTE: this class may be used from within tcmalloc, and can not
@@ -149,6 +150,7 @@
 int GetCPU();
 
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_HAVE_ELF_MEM_IMAGE
diff --git a/absl/debugging/leak_check.cc b/absl/debugging/leak_check.cc
index ffe3d1b..ff90495 100644
--- a/absl/debugging/leak_check.cc
+++ b/absl/debugging/leak_check.cc
@@ -21,12 +21,14 @@
 #ifndef LEAK_SANITIZER
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 bool HaveLeakSanitizer() { return false; }
 void DoIgnoreLeak(const void*) { }
 void RegisterLivePointers(const void*, size_t) { }
 void UnRegisterLivePointers(const void*, size_t) { }
 LeakCheckDisabler::LeakCheckDisabler() { }
 LeakCheckDisabler::~LeakCheckDisabler() { }
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #else
@@ -34,6 +36,7 @@
 #include <sanitizer/lsan_interface.h>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 bool HaveLeakSanitizer() { return true; }
 void DoIgnoreLeak(const void* ptr) { __lsan_ignore_object(ptr); }
 void RegisterLivePointers(const void* ptr, size_t size) {
@@ -44,6 +47,7 @@
 }
 LeakCheckDisabler::LeakCheckDisabler() { __lsan_disable(); }
 LeakCheckDisabler::~LeakCheckDisabler() { __lsan_enable(); }
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // LEAK_SANITIZER
diff --git a/absl/debugging/leak_check.h b/absl/debugging/leak_check.h
index 4d489c5..b66a81c 100644
--- a/absl/debugging/leak_check.h
+++ b/absl/debugging/leak_check.h
@@ -32,7 +32,10 @@
 
 #include <cstddef>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // HaveLeakSanitizer()
 //
@@ -59,7 +62,8 @@
 //
 // If the passed `ptr` does not point to an actively allocated object at the
 // time `IgnoreLeak()` is called, the call is a no-op; if it is actively
-// allocated, the object must not get deallocated later.
+// allocated, leak sanitizer will assume this object is referenced even if
+// there is no actual reference in user memory.
 //
 template <typename T>
 T* IgnoreLeak(T* ptr) {
@@ -104,6 +108,7 @@
 // `RegisterLivePointers()`, enabling leak checking of those pointers.
 void UnRegisterLivePointers(const void* ptr, size_t size);
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_LEAK_CHECK_H_
diff --git a/absl/debugging/leak_check_fail_test.cc b/absl/debugging/leak_check_fail_test.cc
index 2887cea..c49b81a 100644
--- a/absl/debugging/leak_check_fail_test.cc
+++ b/absl/debugging/leak_check_fail_test.cc
@@ -25,7 +25,7 @@
   // failed exit code.
 
   char* foo = strdup("lsan should complain about this leaked string");
-  ABSL_RAW_LOG(INFO, "Should detect leaked std::string %s", foo);
+  ABSL_RAW_LOG(INFO, "Should detect leaked string %s", foo);
 }
 
 TEST(LeakCheckTest, LeakMemoryAfterDisablerScope) {
@@ -34,7 +34,7 @@
   // failed exit code.
   { absl::LeakCheckDisabler disabler; }
   char* foo = strdup("lsan should also complain about this leaked string");
-  ABSL_RAW_LOG(INFO, "Re-enabled leak detection.Should detect leaked std::string %s",
+  ABSL_RAW_LOG(INFO, "Re-enabled leak detection.Should detect leaked string %s",
                foo);
 }
 
diff --git a/absl/debugging/leak_check_test.cc b/absl/debugging/leak_check_test.cc
index 93a7edd..b5cc487 100644
--- a/absl/debugging/leak_check_test.cc
+++ b/absl/debugging/leak_check_test.cc
@@ -30,13 +30,13 @@
 
 TEST(LeakCheckTest, IgnoreLeakSuppressesLeakedMemoryErrors) {
   auto foo = absl::IgnoreLeak(new std::string("some ignored leaked string"));
-  ABSL_RAW_LOG(INFO, "Ignoring leaked std::string %s", foo->c_str());
+  ABSL_RAW_LOG(INFO, "Ignoring leaked string %s", foo->c_str());
 }
 
 TEST(LeakCheckTest, LeakCheckDisablerIgnoresLeak) {
   absl::LeakCheckDisabler disabler;
-  auto foo = new std::string("some std::string leaked while checks are disabled");
-  ABSL_RAW_LOG(INFO, "Ignoring leaked std::string %s", foo->c_str());
+  auto foo = new std::string("some string leaked while checks are disabled");
+  ABSL_RAW_LOG(INFO, "Ignoring leaked string %s", foo->c_str());
 }
 
 }  // namespace
diff --git a/absl/debugging/stacktrace.cc b/absl/debugging/stacktrace.cc
index 9de8782..1f7c7d8 100644
--- a/absl/debugging/stacktrace.cc
+++ b/absl/debugging/stacktrace.cc
@@ -57,6 +57,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 typedef int (*Unwinder)(void**, int*, int, int, const void*, int*);
@@ -135,4 +136,5 @@
   return n;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/debugging/stacktrace.h b/absl/debugging/stacktrace.h
index 3fc1c03..0ec0ffd 100644
--- a/absl/debugging/stacktrace.h
+++ b/absl/debugging/stacktrace.h
@@ -31,15 +31,18 @@
 #ifndef ABSL_DEBUGGING_STACKTRACE_H_
 #define ABSL_DEBUGGING_STACKTRACE_H_
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // GetStackFrames()
 //
 // Records program counter values for up to `max_depth` frames, skipping the
-// most recent `skip_count` stack frames, and stores their corresponding values
-// and sizes in `results` and `sizes` buffers. (Note that the frame generated
-// for the `absl::GetStackFrames()` routine itself is also skipped.)
-// routine itself.
+// most recent `skip_count` stack frames, stores their corresponding values
+// and sizes in `results` and `sizes` buffers, and returns the number of frames
+// stored. (Note that the frame generated for the `absl::GetStackFrames()`
+// routine itself is also skipped.)
 //
 // Example:
 //
@@ -54,8 +57,8 @@
 // The current stack frame would consist of three function calls: `bar()`,
 // `foo()`, and then `main()`; however, since the `GetStackFrames()` call sets
 // `skip_count` to `1`, it will skip the frame for `bar()`, the most recently
-// invoked function call. It will therefore return two program counters and will
-// produce values that map to the following function calls:
+// invoked function call. It will therefore return 2 and fill `result` with
+// program counters within the following functions:
 //
 //      result[0]       foo()
 //      result[1]       main()
@@ -82,9 +85,10 @@
 //
 // Records program counter values obtained from a signal handler. Records
 // program counter values for up to `max_depth` frames, skipping the most recent
-// `skip_count` stack frames, and stores their corresponding values and sizes in
-// `results` and `sizes` buffers. (Note that the frame generated for the
-// `absl::GetStackFramesWithContext()` routine itself is also skipped.)
+// `skip_count` stack frames, stores their corresponding values and sizes in
+// `results` and `sizes` buffers, and returns the number of frames stored. (Note
+// that the frame generated for the `absl::GetStackFramesWithContext()` routine
+// itself is also skipped.)
 //
 // The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value
 // passed to a signal handler registered via the `sa_sigaction` field of a
@@ -105,8 +109,9 @@
 // GetStackTrace()
 //
 // Records program counter values for up to `max_depth` frames, skipping the
-// most recent `skip_count` stack frames, and stores their corresponding values
-// in `results`. Note that this function is similar to `absl::GetStackFrames()`
+// most recent `skip_count` stack frames, stores their corresponding values
+// in `results`, and returns the number of frames
+// stored. Note that this function is similar to `absl::GetStackFrames()`
 // except that it returns the stack trace only, and not stack frame sizes.
 //
 // Example:
@@ -131,9 +136,9 @@
 //
 // Records program counter values obtained from a signal handler. Records
 // program counter values for up to `max_depth` frames, skipping the most recent
-// `skip_count` stack frames, and stores their corresponding values in
-// `results`. (Note that the frame generated for the
-// `absl::GetStackFramesWithContext()` routine itself is also skipped.)
+// `skip_count` stack frames, stores their corresponding values in `results`,
+// and returns the number of frames stored. (Note that the frame generated for
+// the `absl::GetStackFramesWithContext()` routine itself is also skipped.)
 //
 // The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value
 // passed to a signal handler registered via the `sa_sigaction` field of a
@@ -220,6 +225,7 @@
 // working.
 extern bool StackTraceWorksForTest();
 }  // namespace debugging_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_STACKTRACE_H_
diff --git a/absl/debugging/symbolize.cc b/absl/debugging/symbolize.cc
index 24e3a7f..5e4a25d 100644
--- a/absl/debugging/symbolize.cc
+++ b/absl/debugging/symbolize.cc
@@ -14,15 +14,23 @@
 
 #include "absl/debugging/symbolize.h"
 
+#ifdef _WIN32
+#include <winapifamily.h>
+#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) || \
+    WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+// UWP doesn't have access to win32 APIs.
+#define ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32
+#endif
+#endif
+
 #if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE)
 #include "absl/debugging/symbolize_elf.inc"
-#elif defined(_WIN32) && defined(_DEBUG)
-// The Windows Symbolizer only works in debug mode. Note that _DEBUG
-// is the macro that defines whether or not MS C-Runtime debug info is
-// available. Note that the PDB files containing the debug info must
-// also be available to the program at runtime for the symbolizer to
-// work.
+#elif defined(ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32)
+// The Windows Symbolizer only works if PDB files containing the debug info
+// are available to the program at runtime.
 #include "absl/debugging/symbolize_win32.inc"
+#elif defined(__APPLE__)
+#include "absl/debugging/symbolize_darwin.inc"
 #else
 #include "absl/debugging/symbolize_unimplemented.inc"
 #endif
diff --git a/absl/debugging/symbolize.h b/absl/debugging/symbolize.h
index a73dbd9..43d93a8 100644
--- a/absl/debugging/symbolize.h
+++ b/absl/debugging/symbolize.h
@@ -55,6 +55,7 @@
 #include "absl/debugging/internal/symbolize.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // InitializeSymbolizer()
 //
@@ -70,7 +71,7 @@
 //   // Now you can use the symbolizer
 // }
 void InitializeSymbolizer(const char* argv0);
-
+//
 // Symbolize()
 //
 // Symbolizes a program counter (instruction pointer value) `pc` and, on
@@ -88,10 +89,11 @@
 //     if (absl::Symbolize(pc, tmp, sizeof(tmp))) {
 //       symbol = tmp;
 //     }
-//     absl::PrintF("%*p  %s\n", pc, symbol);
+//     absl::PrintF("%p  %s\n", pc, symbol);
 //  }
 bool Symbolize(const void *pc, char *out, int out_size);
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_DEBUGGING_SYMBOLIZE_H_
diff --git a/absl/debugging/symbolize_darwin.inc b/absl/debugging/symbolize_darwin.inc
new file mode 100644
index 0000000..443ce9e
--- /dev/null
+++ b/absl/debugging/symbolize_darwin.inc
@@ -0,0 +1,101 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cxxabi.h>
+#include <execinfo.h>
+
+#include <algorithm>
+#include <cstring>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/debugging/internal/demangle.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+void InitializeSymbolizer(const char*) {}
+
+namespace debugging_internal {
+namespace {
+
+static std::string GetSymbolString(absl::string_view backtrace_line) {
+  // Example Backtrace lines:
+  // 0   libimaging_shared.dylib             0x018c152a
+  // _ZNSt11_Deque_baseIN3nik7mediadb4PageESaIS2_EE17_M_initialize_mapEm + 3478
+  //
+  // or
+  // 0   libimaging_shared.dylib             0x0000000001895c39
+  // _ZN3nik4util19register_shared_ptrINS_3gpu7TextureEEEvPKvS5_ + 39
+  //
+  // or
+  // 0   mysterious_app                      0x0124000120120009 main + 17
+  auto address_pos = backtrace_line.find(" 0x");
+  if (address_pos == absl::string_view::npos) return std::string();
+  absl::string_view symbol_view = backtrace_line.substr(address_pos + 1);
+
+  auto space_pos = symbol_view.find(" ");
+  if (space_pos == absl::string_view::npos) return std::string();
+  symbol_view = symbol_view.substr(space_pos + 1);  // to mangled symbol
+
+  auto plus_pos = symbol_view.find(" + ");
+  if (plus_pos == absl::string_view::npos) return std::string();
+  symbol_view = symbol_view.substr(0, plus_pos);  // strip remainng
+
+  return std::string(symbol_view);
+}
+
+}  // namespace
+}  // namespace debugging_internal
+
+bool Symbolize(const void* pc, char* out, int out_size) {
+  if (out_size <= 0 || pc == nullptr) {
+    out = nullptr;
+    return false;
+  }
+
+  // This allocates a char* array.
+  char** frame_strings = backtrace_symbols(const_cast<void**>(&pc), 1);
+
+  if (frame_strings == nullptr) return false;
+
+  std::string symbol = debugging_internal::GetSymbolString(frame_strings[0]);
+  free(frame_strings);
+
+  char tmp_buf[1024];
+  if (debugging_internal::Demangle(symbol.c_str(), tmp_buf, sizeof(tmp_buf))) {
+    size_t len = strlen(tmp_buf);
+    if (len + 1 <= static_cast<size_t>(out_size)) {  // +1 for '\0'
+      assert(len < sizeof(tmp_buf));
+      memmove(out, tmp_buf, len + 1);
+    }
+  } else {
+    strncpy(out, symbol.c_str(), out_size);
+  }
+
+  if (out[out_size - 1] != '\0') {
+    // strncpy() does not '\0' terminate when it truncates.
+    static constexpr char kEllipsis[] = "...";
+    int ellipsis_size = std::min<int>(sizeof(kEllipsis) - 1, out_size - 1);
+    memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size);
+    out[out_size - 1] = '\0';
+  }
+
+  return true;
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc
index 14f0c97..f4d5727 100644
--- a/absl/debugging/symbolize_elf.inc
+++ b/absl/debugging/symbolize_elf.inc
@@ -57,6 +57,7 @@
 #include <unistd.h>
 
 #include <algorithm>
+#include <array>
 #include <atomic>
 #include <cerrno>
 #include <cinttypes>
@@ -74,13 +75,21 @@
 #include "absl/base/port.h"
 #include "absl/debugging/internal/demangle.h"
 #include "absl/debugging/internal/vdso_support.h"
+#include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // Value of argv[0]. Used by MaybeInitializeObjFile().
 static char *argv0_value = nullptr;
 
 void InitializeSymbolizer(const char *argv0) {
+#ifdef ABSL_HAVE_VDSO_SUPPORT
+  // We need to make sure VDSOSupport::Init() is called before any setuid or
+  // chroot calls, so InitializeSymbolizer() should be called very early in the
+  // life of a program.
+  absl::debugging_internal::VDSOSupport::Init();
+#endif
   if (argv0_value != nullptr) {
     free(argv0_value);
     argv0_value = nullptr;
@@ -148,13 +157,15 @@
 // Moreover, we are using only TryLock(), if the decorator list
 // is being modified (is busy), we skip all decorators, and possibly
 // loose some info. Sorry, that's the best we could do.
-base_internal::SpinLock g_decorators_mu(base_internal::kLinkerInitialized);
+ABSL_CONST_INIT absl::base_internal::SpinLock g_decorators_mu(
+    absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY);
 
 const int kMaxFileMappingHints = 8;
 int g_num_file_mapping_hints;
 FileMappingHint g_file_mapping_hints[kMaxFileMappingHints];
 // Protects g_file_mapping_hints.
-base_internal::SpinLock g_file_mapping_mu(base_internal::kLinkerInitialized);
+ABSL_CONST_INIT absl::base_internal::SpinLock g_file_mapping_mu(
+    absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY);
 
 // Async-signal-safe function to zero a buffer.
 // memset() is not guaranteed to be async-signal-safe.
@@ -174,6 +185,7 @@
         fd(-1),
         elf_type(-1) {
     SafeMemZero(&elf_header, sizeof(elf_header));
+    SafeMemZero(&phdr[0], sizeof(phdr));
   }
 
   char *filename;
@@ -186,6 +198,10 @@
   int fd;
   int elf_type;
   ElfW(Ehdr) elf_header;
+
+  // PT_LOAD program header describing executable code.
+  // Normally we expect just one, but SWIFT binaries have two.
+  std::array<ElfW(Phdr), 2> phdr;
 };
 
 // Build 4-way associative cache for symbols. Within each cache line, symbols
@@ -495,7 +511,7 @@
 const int kMaxSectionNameLen = 64;
 
 bool ForEachSection(int fd,
-                    const std::function<bool(const std::string &name,
+                    const std::function<bool(absl::string_view name,
                                              const ElfW(Shdr) &)> &callback) {
   ElfW(Ehdr) elf_header;
   if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
@@ -517,7 +533,7 @@
       return false;
     }
     off_t name_offset = shstrtab.sh_offset + out.sh_name;
-    char header_name[kMaxSectionNameLen + 1];
+    char header_name[kMaxSectionNameLen];
     ssize_t n_read =
         ReadFromOffset(fd, &header_name, kMaxSectionNameLen, name_offset);
     if (n_read == -1) {
@@ -526,9 +542,8 @@
       // Long read?
       return false;
     }
-    header_name[n_read] = '\0';
 
-    std::string name(header_name);
+    absl::string_view name(header_name, strnlen(header_name, n_read));
     if (!callback(name, out)) {
       break;
     }
@@ -1263,6 +1278,36 @@
       ABSL_RAW_LOG(WARNING, "%s: failed to read elf header", obj->filename);
       return false;
     }
+    const int phnum = obj->elf_header.e_phnum;
+    const int phentsize = obj->elf_header.e_phentsize;
+    size_t phoff = obj->elf_header.e_phoff;
+    size_t num_executable_load_segments = 0;
+    for (int j = 0; j < phnum; j++) {
+      ElfW(Phdr) phdr;
+      if (!ReadFromOffsetExact(obj->fd, &phdr, sizeof(phdr), phoff)) {
+        ABSL_RAW_LOG(WARNING, "%s: failed to read program header %d",
+                     obj->filename, j);
+        return false;
+      }
+      phoff += phentsize;
+      constexpr int rx = PF_X | PF_R;
+      if (phdr.p_type != PT_LOAD || (phdr.p_flags & rx) != rx) {
+        // Not a LOAD segment, or not executable code.
+        continue;
+      }
+      if (num_executable_load_segments < obj->phdr.size()) {
+        memcpy(&obj->phdr[num_executable_load_segments++], &phdr, sizeof(phdr));
+      } else {
+        ABSL_RAW_LOG(WARNING, "%s: too many executable LOAD segments",
+                     obj->filename);
+        break;
+      }
+    }
+    if (num_executable_load_segments == 0) {
+      // This object has no "r-x" LOAD segments. That's unexpected.
+      ABSL_RAW_LOG(WARNING, "%s: no executable LOAD segments", obj->filename);
+      return false;
+    }
   }
   return true;
 }
@@ -1286,23 +1331,52 @@
   int fd = -1;
   if (obj != nullptr) {
     if (MaybeInitializeObjFile(obj)) {
-      if (obj->elf_type == ET_DYN &&
-          reinterpret_cast<uint64_t>(obj->start_addr) >= obj->offset) {
+      const size_t start_addr = reinterpret_cast<size_t>(obj->start_addr);
+      if (obj->elf_type == ET_DYN && start_addr >= obj->offset) {
         // This object was relocated.
         //
         // For obj->offset > 0, adjust the relocation since a mapping at offset
         // X in the file will have a start address of [true relocation]+X.
-        relocation = reinterpret_cast<ptrdiff_t>(obj->start_addr) - obj->offset;
+        relocation = start_addr - obj->offset;
+
+        // Note: some binaries have multiple "rx" LOAD segments. We must
+        // find the right one.
+        ElfW(Phdr) *phdr = nullptr;
+        for (size_t j = 0; j < obj->phdr.size(); j++) {
+          ElfW(Phdr) &p = obj->phdr[j];
+          if (p.p_type != PT_LOAD) {
+            // We only expect PT_LOADs. This must be PT_NULL that we didn't
+            // write over (i.e. we exhausted all interesting PT_LOADs).
+            ABSL_RAW_CHECK(p.p_type == PT_NULL, "unexpected p_type");
+            break;
+          }
+          if (pc < reinterpret_cast<void *>(start_addr + p.p_memsz)) {
+            phdr = &p;
+            break;
+          }
+        }
+        if (phdr == nullptr) {
+          // That's unexpected. Hope for the best.
+          ABSL_RAW_LOG(
+              WARNING,
+              "%s: unable to find LOAD segment for pc: %p, start_addr: %zx",
+              obj->filename, pc, start_addr);
+        } else {
+          // Adjust relocation in case phdr.p_vaddr != 0.
+          // This happens for binaries linked with `lld --rosegment`, and for
+          // binaries linked with BFD `ld -z separate-code`.
+          relocation -= phdr->p_vaddr - phdr->p_offset;
+        }
       }
 
       fd = obj->fd;
-    }
-    if (GetSymbolFromObjectFile(*obj, pc, relocation, symbol_buf_,
-                                sizeof(symbol_buf_), tmp_buf_,
-                                sizeof(tmp_buf_)) == SYMBOL_FOUND) {
-      // Only try to demangle the symbol name if it fit into symbol_buf_.
-      DemangleInplace(symbol_buf_, sizeof(symbol_buf_), tmp_buf_,
-                      sizeof(tmp_buf_));
+      if (GetSymbolFromObjectFile(*obj, pc, relocation, symbol_buf_,
+                                  sizeof(symbol_buf_), tmp_buf_,
+                                  sizeof(tmp_buf_)) == SYMBOL_FOUND) {
+        // Only try to demangle the symbol name if it fit into symbol_buf_.
+        DemangleInplace(symbol_buf_, sizeof(symbol_buf_), tmp_buf_,
+                        sizeof(tmp_buf_));
+      }
     }
   } else {
 #if ABSL_HAVE_VDSO_SUPPORT
@@ -1373,7 +1447,7 @@
 
   if (!g_decorators_mu.TryLock()) {
     // Someone else is using decorators. Get out.
-    return false;
+    return -2;
   }
   int ret = ticket;
   if (g_num_decorators >= kMaxDecorators) {
@@ -1401,7 +1475,7 @@
   if (g_num_file_mapping_hints >= kMaxFileMappingHints) {
     ret = false;
   } else {
-    // TODO(ckennelly): Move this into a std::string copy routine.
+    // TODO(ckennelly): Move this into a string copy routine.
     int len = strlen(filename);
     char *dst = static_cast<char *>(
         base_internal::LowLevelAlloc::AllocWithArena(len + 1, SigSafeArena()));
@@ -1452,7 +1526,7 @@
 
 bool Symbolize(const void *pc, char *out, int out_size) {
   // Symbolization is very slow under tsan.
-  ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
+  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
   SAFE_ASSERT(out_size >= 0);
   debugging_internal::Symbolizer *s = debugging_internal::AllocateSymbolizer();
   const char *name = s->GetSymbol(pc);
@@ -1471,8 +1545,16 @@
     }
   }
   debugging_internal::FreeSymbolizer(s);
-  ANNOTATE_IGNORE_READS_AND_WRITES_END();
+  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
   return ok;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
+
+extern "C" bool AbslInternalGetFileMappingHint(const void **start,
+                                               const void **end, uint64_t *offset,
+                                               const char **filename) {
+  return absl::debugging_internal::GetFileMappingHint(start, end, offset,
+                                                      filename);
+}
diff --git a/absl/debugging/symbolize_test.cc b/absl/debugging/symbolize_test.cc
index 08068c3..a2dd495 100644
--- a/absl/debugging/symbolize_test.cc
+++ b/absl/debugging/symbolize_test.cc
@@ -27,18 +27,39 @@
 #include "gtest/gtest.h"
 #include "absl/base/attributes.h"
 #include "absl/base/casts.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/per_thread_tls.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/optimization.h"
 #include "absl/debugging/internal/stack_consumption.h"
 #include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
 
 using testing::Contains;
 
+#ifdef _WIN32
+#define ABSL_SYMBOLIZE_TEST_NOINLINE __declspec(noinline)
+#else
+#define ABSL_SYMBOLIZE_TEST_NOINLINE ABSL_ATTRIBUTE_NOINLINE
+#endif
+
 // Functions to symbolize. Use C linkage to avoid mangled names.
 extern "C" {
-void nonstatic_func() { ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); }
-static void static_func() { ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); }
+ABSL_SYMBOLIZE_TEST_NOINLINE void nonstatic_func() {
+  // The next line makes this a unique function to prevent the compiler from
+  // folding identical functions together.
+  volatile int x = __LINE__;
+  static_cast<void>(x);
+  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
+}
+
+ABSL_SYMBOLIZE_TEST_NOINLINE static void static_func() {
+  // The next line makes this a unique function to prevent the compiler from
+  // folding identical functions together.
+  volatile int x = __LINE__;
+  static_cast<void>(x);
+  ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
+}
 }  // extern "C"
 
 struct Foo {
@@ -46,7 +67,11 @@
 };
 
 // A C++ method that should have a mangled name.
-void ABSL_ATTRIBUTE_NOINLINE Foo::func(int) {
+ABSL_SYMBOLIZE_TEST_NOINLINE void Foo::func(int) {
+  // The next line makes this a unique function to prevent the compiler from
+  // folding identical functions together.
+  volatile int x = __LINE__;
+  static_cast<void>(x);
   ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
 }
 
@@ -80,6 +105,7 @@
     symbolize_test_thread_big[2 * 1024 * 1024];
 #endif
 
+#if !defined(__EMSCRIPTEN__)
 // Used below to hopefully inhibit some compiler/linker optimizations
 // that may remove kHpageTextPadding, kPadding0, and kPadding1 from
 // the binary.
@@ -89,6 +115,7 @@
 static constexpr size_t kHpageSize = 1 << 21;
 const char kHpageTextPadding[kHpageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(
     .text) = "";
+#endif  // !defined(__EMSCRIPTEN__)
 
 static char try_symbolize_buffer[4096];
 
@@ -119,7 +146,8 @@
   return TrySymbolizeWithLimit(pc, sizeof(try_symbolize_buffer));
 }
 
-#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
+#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \
+    defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)
 
 TEST(Symbolize, Cached) {
   // Compilers should give us pointers to them.
@@ -193,8 +221,8 @@
 static int GetStackConsumptionUpperLimit() {
   // Symbolize stack consumption should be within 2kB.
   int stack_consumption_upper_limit = 2048;
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
-    defined(THREAD_SANITIZER)
+#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
+    defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
   // Account for sanitizer instrumentation requiring additional stack space.
   stack_consumption_upper_limit *= 5;
 #endif
@@ -233,6 +261,7 @@
 
 #endif  // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
 
+#ifndef ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
 // Use a 64K page size for PPC.
 const size_t kPageSize = 64 << 10;
 // We place a read-only symbols into the .text section and verify that we can
@@ -374,8 +403,8 @@
 
   std::vector<std::string> sections;
   ASSERT_TRUE(absl::debugging_internal::ForEachSection(
-      fd, [&sections](const std::string &name, const ElfW(Shdr) &) {
-        sections.push_back(name);
+      fd, [&sections](const absl::string_view name, const ElfW(Shdr) &) {
+        sections.emplace_back(name);
         return true;
       }));
 
@@ -388,6 +417,7 @@
 
   close(fd);
 }
+#endif  // !ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
 
 // x86 specific tests.  Uses some inline assembler.
 extern "C" {
@@ -447,14 +477,15 @@
 #endif
 }
 
-#elif defined(_WIN32) && defined(_DEBUG)
+#elif defined(_WIN32)
+#if !defined(ABSL_CONSUME_DLL)
 
 TEST(Symbolize, Basics) {
   EXPECT_STREQ("nonstatic_func", TrySymbolize((void *)(&nonstatic_func)));
 
   // The name of an internal linkage symbol is not specified; allow either a
   // mangled or an unmangled name here.
-  const char* static_func_symbol = TrySymbolize((void *)(&static_func));
+  const char *static_func_symbol = TrySymbolize((void *)(&static_func));
   ASSERT_TRUE(static_func_symbol != nullptr);
   EXPECT_TRUE(strstr(static_func_symbol, "static_func") != nullptr);
 
@@ -481,11 +512,12 @@
 }
 
 TEST(Symbolize, SymbolizeWithDemangling) {
-  const char* result = TrySymbolize((void *)(&Foo::func));
+  const char *result = TrySymbolize((void *)(&Foo::func));
   ASSERT_TRUE(result != nullptr);
   EXPECT_TRUE(strstr(result, "Foo::func") != nullptr) << result;
 }
 
+#endif  // !defined(ABSL_CONSUME_DLL)
 #else  // Symbolizer unimplemented
 
 TEST(Symbolize, Unimplemented) {
@@ -498,10 +530,12 @@
 #endif
 
 int main(int argc, char **argv) {
+#if !defined(__EMSCRIPTEN__)
   // Make sure kHpageTextPadding is linked into the binary.
   if (volatile_bool) {
     ABSL_RAW_LOG(INFO, "%s", kHpageTextPadding);
   }
+#endif  // !defined(__EMSCRIPTEN__)
 
 #if ABSL_PER_THREAD_TLS
   // Touch the per-thread variables.
@@ -512,7 +546,8 @@
   absl::InitializeSymbolizer(argv[0]);
   testing::InitGoogleTest(&argc, argv);
 
-#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
+#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \
+    defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)
   TestWithPCInsideInlineFunction();
   TestWithPCInsideNonInlineFunction();
   TestWithReturnAddress();
diff --git a/absl/debugging/symbolize_unimplemented.inc b/absl/debugging/symbolize_unimplemented.inc
index 7c580fe..db24456 100644
--- a/absl/debugging/symbolize_unimplemented.inc
+++ b/absl/debugging/symbolize_unimplemented.inc
@@ -17,6 +17,7 @@
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace debugging_internal {
 
@@ -35,4 +36,5 @@
 void InitializeSymbolizer(const char*) {}
 bool Symbolize(const void *, char *, int) { return false; }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/debugging/symbolize_win32.inc b/absl/debugging/symbolize_win32.inc
index 5a55f29..c3df46f 100644
--- a/absl/debugging/symbolize_win32.inc
+++ b/absl/debugging/symbolize_win32.inc
@@ -17,10 +17,10 @@
 
 #include <windows.h>
 
-// MSVC header DbgHelp.h has a warning for an ignored typedef.
+// MSVC header dbghelp.h has a warning for an ignored typedef.
 #pragma warning(push)
 #pragma warning(disable:4091)
-#include <DbgHelp.h>
+#include <dbghelp.h>
 #pragma warning(pop)
 
 #pragma comment(lib, "dbghelp.lib")
@@ -31,10 +31,11 @@
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 static HANDLE process = NULL;
 
-void InitializeSymbolizer(const char *argv0) {
+void InitializeSymbolizer(const char*) {
   if (process != nullptr) {
     return;
   }
@@ -53,13 +54,12 @@
   }
 }
 
-bool Symbolize(const void *pc, char *out, int out_size) {
+bool Symbolize(const void* pc, char* out, int out_size) {
   if (out_size <= 0) {
     return false;
   }
-  std::aligned_storage<sizeof(SYMBOL_INFO) + MAX_SYM_NAME,
-                       alignof(SYMBOL_INFO)>::type buf;
-  SYMBOL_INFO *symbol = reinterpret_cast<SYMBOL_INFO *>(&buf);
+  alignas(SYMBOL_INFO) char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
+  SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>(buf);
   symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
   symbol->MaxNameLen = MAX_SYM_NAME;
   if (!SymFromAddr(process, reinterpret_cast<DWORD64>(pc), nullptr, symbol)) {
@@ -77,4 +77,5 @@
   return true;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index 2bf562f..1937609 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -14,7 +14,7 @@
 # limitations under the License.
 #
 
-load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
 load(
     "//absl:copts/configure_copts.bzl",
     "ABSL_DEFAULT_COPTS",
@@ -24,23 +24,21 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
-    name = "flag_internal",
-    srcs = [
-        "internal/flag.cc",
-    ],
+    name = "path_util",
     hdrs = [
-        "internal/flag.h",
+        "internal/path_util.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = ["//visibility:private"],
+    visibility = [
+        "//absl/flags:__pkg__",
+    ],
     deps = [
-        ":handle",
-        ":registry",
-        "//absl/synchronization",
+        "//absl/base:config",
+        "//absl/strings",
     ],
 )
 
@@ -59,27 +57,14 @@
     ],
     deps = [
         ":path_util",
+        "//absl/base:config",
+        "//absl/base:core_headers",
         "//absl/strings",
         "//absl/synchronization",
     ],
 )
 
 cc_library(
-    name = "path_util",
-    hdrs = [
-        "internal/path_util.h",
-    ],
-    copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl/flags:__pkg__",
-    ],
-    deps = [
-        "//absl/strings",
-    ],
-)
-
-cc_library(
     name = "config",
     srcs = [
         "usage_config.cc",
@@ -93,6 +78,7 @@
     deps = [
         ":path_util",
         ":program_name",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/strings",
         "//absl/synchronization",
@@ -110,14 +96,16 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:log_severity",
         "//absl/strings",
         "//absl/strings:str_format",
     ],
 )
 
 cc_library(
-    name = "handle",
+    name = "commandlineflag_internal",
     srcs = [
         "internal/commandlineflag.cc",
     ],
@@ -126,29 +114,38 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl/flags:__pkg__",
-    ],
     deps = [
-        ":config",
-        ":marshalling",
-        "//absl/base:core_headers",
-        "//absl/base:raw_logging_internal",
+        "//absl/base:config",
+        "//absl/base:fast_type_id",
+    ],
+)
+
+cc_library(
+    name = "commandlineflag",
+    srcs = [
+        "commandlineflag.cc",
+    ],
+    hdrs = [
+        "commandlineflag.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":commandlineflag_internal",
+        "//absl/base:config",
+        "//absl/base:fast_type_id",
         "//absl/strings",
-        "//absl/synchronization",
         "//absl/types:optional",
     ],
 )
 
 cc_library(
-    name = "registry",
+    name = "private_handle_accessor",
     srcs = [
-        "internal/registry.cc",
-        "internal/type_erased.cc",
+        "internal/private_handle_accessor.cc",
     ],
     hdrs = [
-        "internal/registry.h",
-        "internal/type_erased.h",
+        "internal/private_handle_accessor.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -156,17 +153,67 @@
         "//absl/flags:__pkg__",
     ],
     deps = [
+        ":commandlineflag",
+        ":commandlineflag_internal",
+        "//absl/base:config",
+        "//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "reflection",
+    srcs = [
+        "reflection.cc",
+    ],
+    hdrs = [
+        "internal/registry.h",
+        "reflection.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":commandlineflag",
+        ":commandlineflag_internal",
         ":config",
-        ":handle",
+        ":private_handle_accessor",
+        "//absl/base:config",
         "//absl/base:core_headers",
-        "//absl/base:dynamic_annotations",
-        "//absl/base:raw_logging_internal",
+        "//absl/container:flat_hash_map",
         "//absl/strings",
         "//absl/synchronization",
     ],
 )
 
 cc_library(
+    name = "flag_internal",
+    srcs = [
+        "internal/flag.cc",
+    ],
+    hdrs = [
+        "internal/flag.h",
+        "internal/sequence_lock.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = ["//absl/base:__subpackages__"],
+    deps = [
+        ":commandlineflag",
+        ":commandlineflag_internal",
+        ":config",
+        ":marshalling",
+        ":reflection",
+        "//absl/base",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/memory",
+        "//absl/meta:type_traits",
+        "//absl/strings",
+        "//absl/synchronization",
+        "//absl/utility",
+    ],
+)
+
+cc_library(
     name = "flag",
     srcs = [
         "flag.cc",
@@ -180,9 +227,9 @@
     deps = [
         ":config",
         ":flag_internal",
-        ":handle",
-        ":marshalling",
+        ":reflection",
         "//absl/base",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/strings",
     ],
@@ -202,13 +249,17 @@
         "//absl/flags:__pkg__",
     ],
     deps = [
+        ":commandlineflag",
         ":config",
         ":flag",
-        ":handle",
+        ":flag_internal",
         ":path_util",
+        ":private_handle_accessor",
         ":program_name",
+        ":reflection",
+        "//absl/base:config",
+        "//absl/base:core_headers",
         "//absl/strings",
-        "//absl/synchronization",
     ],
 )
 
@@ -224,6 +275,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":usage_internal",
+        "//absl/base:config",
+        "//absl/base:core_headers",
         "//absl/strings",
         "//absl/synchronization",
     ],
@@ -239,12 +292,18 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":commandlineflag",
+        ":commandlineflag_internal",
         ":config",
         ":flag",
+        ":flag_internal",
+        ":private_handle_accessor",
         ":program_name",
-        ":registry",
+        ":reflection",
         ":usage",
         ":usage_internal",
+        "//absl/base:config",
+        "//absl/base:core_headers",
         "//absl/strings",
         "//absl/synchronization",
     ],
@@ -257,15 +316,17 @@
     name = "commandlineflag_test",
     size = "small",
     srcs = [
-        "internal/commandlineflag_test.cc",
+        "commandlineflag_test.cc",
     ],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":commandlineflag",
+        ":commandlineflag_internal",
         ":config",
         ":flag",
-        ":handle",
-        ":registry",
+        ":private_handle_accessor",
+        ":reflection",
         "//absl/memory",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
@@ -298,11 +359,42 @@
     deps = [
         ":config",
         ":flag",
+        ":flag_internal",
+        ":marshalling",
+        ":reflection",
+        "//absl/base:core_headers",
+        "//absl/base:malloc_internal",
         "//absl/strings",
+        "//absl/time",
         "@com_google_googletest//:gtest_main",
     ],
 )
 
+cc_binary(
+    name = "flag_benchmark",
+    testonly = 1,
+    srcs = [
+        "flag_benchmark.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = select({
+        "//conditions:default": [],
+    }) + ABSL_DEFAULT_LINKOPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        "flag_benchmark.lds",
+        ":flag",
+        ":marshalling",
+        ":parse",
+        ":reflection",
+        "//absl/strings",
+        "//absl/time",
+        "//absl/types:optional",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
+
 cc_test(
     name = "marshalling_test",
     size = "small",
@@ -318,20 +410,6 @@
 )
 
 cc_test(
-    name = "path_util_test",
-    size = "small",
-    srcs = [
-        "internal/path_util_test.cc",
-    ],
-    copts = ABSL_TEST_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = [
-        ":path_util",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
-
-cc_test(
     name = "parse_test",
     size = "small",
     srcs = [
@@ -342,6 +420,8 @@
     deps = [
         ":flag",
         ":parse",
+        ":reflection",
+        ":usage_internal",
         "//absl/base:raw_logging_internal",
         "//absl/base:scoped_set_env",
         "//absl/strings",
@@ -351,6 +431,20 @@
 )
 
 cc_test(
+    name = "path_util_test",
+    size = "small",
+    srcs = [
+        "internal/path_util_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":path_util",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
     name = "program_name_test",
     size = "small",
     srcs = [
@@ -366,16 +460,19 @@
 )
 
 cc_test(
-    name = "type_erased_test",
+    name = "reflection_test",
     size = "small",
     srcs = [
-        "internal/type_erased_test.cc",
+        "reflection_test.cc",
     ],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":commandlineflag_internal",
         ":flag",
-        ":registry",
+        ":marshalling",
+        ":reflection",
+        ":usage_internal",
         "//absl/memory",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
@@ -383,6 +480,25 @@
 )
 
 cc_test(
+    name = "sequence_lock_test",
+    size = "small",
+    timeout = "moderate",
+    srcs = [
+        "internal/sequence_lock_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    shard_count = 32,
+    deps = [
+        ":flag_internal",
+        "//absl/base",
+        "//absl/container:fixed_array",
+        "//absl/time",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
     name = "usage_config_test",
     size = "small",
     srcs = [
@@ -413,9 +529,9 @@
         ":parse",
         ":path_util",
         ":program_name",
+        ":reflection",
         ":usage",
         ":usage_internal",
-        "//absl/memory",
         "//absl/strings",
         "@com_google_googletest//:gtest",
     ],
diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt
index 3a7162f..caac69c 100644
--- a/absl/flags/CMakeLists.txt
+++ b/absl/flags/CMakeLists.txt
@@ -17,19 +17,16 @@
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
-    flags_internal
-  SRCS
-    "internal/flag.cc"
+    flags_path_util
   HDRS
-    "internal/flag.h"
+    "internal/path_util.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
-    absl::flags_handle
-    absl::flags_registry
-    absl::synchronization
+    absl::config
+    absl::strings
   PUBLIC
 )
 
@@ -46,27 +43,14 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
+    absl::core_headers
     absl::flags_path_util
     absl::strings
     absl::synchronization
   PUBLIC
 )
 
-# Internal-only target, do not depend on directly.
-absl_cc_library(
-  NAME
-    flags_path_util
-  HDRS
-    "internal/path_util.h"
-  COPTS
-    ${ABSL_DEFAULT_COPTS}
-  LINKOPTS
-    ${ABSL_DEFAULT_LINKOPTS}
-  DEPS
-    absl::strings
-  PUBLIC
-)
-
 absl_cc_library(
   NAME
     flags_config
@@ -80,6 +64,7 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
     absl::flags_path_util
     absl::flags_program_name
     absl::core_headers
@@ -99,7 +84,9 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
     absl::core_headers
+    absl::log_severity
     absl::strings
     absl::str_format
 )
@@ -107,7 +94,7 @@
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
-    flags_handle
+    flags_commandlineflag_internal
   SRCS
     "internal/commandlineflag.cc"
   HDRS
@@ -117,37 +104,94 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
-    absl::flags_config
-    absl::flags_marshalling
-    absl::core_headers
-    absl::optional
-    absl::raw_logging_internal
-    absl::strings
-    absl::synchronization
+    absl::config
+    absl::fast_type_id
 )
 
-# Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
-    flags_registry
+    flags_commandlineflag
   SRCS
-    "internal/registry.cc"
-    "internal/type_erased.cc"
+    "commandlineflag.cc"
   HDRS
-    "internal/registry.h"
-    "internal/type_erased.h"
+    "commandlineflag.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
+    absl::fast_type_id
+    absl::flags_commandlineflag_internal
+    absl::optional
+    absl::strings
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    flags_private_handle_accessor
+  SRCS
+    "internal/private_handle_accessor.cc"
+  HDRS
+    "internal/private_handle_accessor.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::flags_commandlineflag
+    absl::flags_commandlineflag_internal
+    absl::strings
+)
+
+absl_cc_library(
+  NAME
+    flags_reflection
+  SRCS
+    "reflection.cc"
+  HDRS
+    "reflection.h"
+    "internal/registry.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::flags_commandlineflag
+    absl::flags_private_handle_accessor
     absl::flags_config
-    absl::flags_handle
-    absl::core_headers
-    absl::dynamic_annotations
-    absl::raw_logging_internal
     absl::strings
     absl::synchronization
+    absl::flat_hash_map
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    flags_internal
+  SRCS
+    "internal/flag.cc"
+  HDRS
+    "internal/flag.h"
+    "internal/sequence_lock.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::base
+    absl::config
+    absl::flags_commandlineflag
+    absl::flags_commandlineflag_internal
+    absl::flags_config
+    absl::flags_marshalling
+    absl::synchronization
+    absl::meta
+    absl::utility
+  PUBLIC
 )
 
 absl_cc_library(
@@ -163,10 +207,11 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
+    absl::flags_commandlineflag
     absl::flags_config
-    absl::flags_handle
     absl::flags_internal
-    absl::flags_marshalling
+    absl::flags_reflection
     absl::base
     absl::core_headers
     absl::strings
@@ -185,11 +230,15 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
     absl::flags_config
     absl::flags
-    absl::flags_handle
+    absl::flags_commandlineflag
+    absl::flags_internal
     absl::flags_path_util
+    absl::flags_private_handle_accessor
     absl::flags_program_name
+    absl::flags_reflection
     absl::strings
     absl::synchronization
 )
@@ -206,6 +255,8 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
+    absl::core_headers
     absl::flags_usage_internal
     absl::strings
     absl::synchronization
@@ -224,10 +275,16 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
+    absl::core_headers
     absl::flags_config
     absl::flags
+    absl::flags_commandlineflag
+    absl::flags_commandlineflag_internal
+    absl::flags_internal
+    absl::flags_private_handle_accessor
     absl::flags_program_name
-    absl::flags_registry
+    absl::flags_reflection
     absl::flags_usage
     absl::strings
     absl::synchronization
@@ -240,14 +297,16 @@
   NAME
     flags_commandlineflag_test
   SRCS
-    "internal/commandlineflag_test.cc"
+    "commandlineflag_test.cc"
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
     absl::flags
+    absl::flags_commandlineflag
+    absl::flags_commandlineflag_internal
     absl::flags_config
-    absl::flags_handle
-    absl::flags_registry
+    absl::flags_private_handle_accessor
+    absl::flags_reflection
     absl::memory
     absl::strings
     gtest_main
@@ -274,9 +333,14 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::core_headers
     absl::flags
     absl::flags_config
+    absl::flags_internal
+    absl::flags_marshalling
+    absl::flags_reflection
     absl::strings
+    absl::time
     gtest_main
 )
 
@@ -302,6 +366,8 @@
   DEPS
     absl::flags
     absl::flags_parse
+    absl::flags_reflection
+    absl::flags_usage_internal
     absl::raw_logging_internal
     absl::scoped_set_env
     absl::span
@@ -336,17 +402,33 @@
 
 absl_cc_test(
   NAME
-    flags_type_erased_test
+    flags_reflection_test
   SRCS
-    "internal/type_erased_test.cc"
+    "reflection_test.cc"
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::flags_commandlineflag_internal
     absl::flags
-    absl::flags_registry
+    absl::flags_reflection
+    absl::flags_usage
     absl::memory
     absl::strings
-    gtest_main
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    flags_sequence_lock_test
+  SRCS
+    "internal/sequence_lock_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::base
+    absl::flags_internal
+    absl::time
+    gmock_main
 )
 
 absl_cc_test(
@@ -377,8 +459,8 @@
     absl::flags_path_util
     absl::flags_program_name
     absl::flags_parse
+    absl::flags_reflection
     absl::flags_usage
-    absl::memory
     absl::strings
     gtest
 )
diff --git a/absl/flags/commandlineflag.cc b/absl/flags/commandlineflag.cc
new file mode 100644
index 0000000..9f3b4a5
--- /dev/null
+++ b/absl/flags/commandlineflag.cc
@@ -0,0 +1,34 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/commandlineflag.h"
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+bool CommandLineFlag::IsRetired() const { return false; }
+bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) {
+  return ParseFrom(value, flags_internal::SET_FLAGS_VALUE,
+                   flags_internal::kProgrammaticChange, *error);
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/flags/commandlineflag.h b/absl/flags/commandlineflag.h
new file mode 100644
index 0000000..f2fa089
--- /dev/null
+++ b/absl/flags/commandlineflag.h
@@ -0,0 +1,200 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: commandlineflag.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `CommandLineFlag`, which acts as a type-erased
+// handle for accessing metadata about the Abseil Flag in question.
+//
+// Because an actual Abseil flag is of an unspecified type, you should not
+// manipulate or interact directly with objects of that type. Instead, use the
+// CommandLineFlag type as an intermediary.
+#ifndef ABSL_FLAGS_COMMANDLINEFLAG_H_
+#define ABSL_FLAGS_COMMANDLINEFLAG_H_
+
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+class PrivateHandleAccessor;
+}  // namespace flags_internal
+
+// CommandLineFlag
+//
+// This type acts as a type-erased handle for an instance of an Abseil Flag and
+// holds reflection information pertaining to that flag. Use CommandLineFlag to
+// access a flag's name, location, help string etc.
+//
+// To obtain an absl::CommandLineFlag, invoke `absl::FindCommandLineFlag()`
+// passing it the flag name string.
+//
+// Example:
+//
+//   // Obtain reflection handle for a flag named "flagname".
+//   const absl::CommandLineFlag* my_flag_data =
+//        absl::FindCommandLineFlag("flagname");
+//
+//   // Now you can get flag info from that reflection handle.
+//   std::string flag_location = my_flag_data->Filename();
+//   ...
+class CommandLineFlag {
+ public:
+  constexpr CommandLineFlag() = default;
+
+  // Not copyable/assignable.
+  CommandLineFlag(const CommandLineFlag&) = delete;
+  CommandLineFlag& operator=(const CommandLineFlag&) = delete;
+
+  // absl::CommandLineFlag::IsOfType()
+  //
+  // Return true iff flag has type T.
+  template <typename T>
+  inline bool IsOfType() const {
+    return TypeId() == base_internal::FastTypeId<T>();
+  }
+
+  // absl::CommandLineFlag::TryGet()
+  //
+  // Attempts to retrieve the flag value. Returns value on success,
+  // absl::nullopt otherwise.
+  template <typename T>
+  absl::optional<T> TryGet() const {
+    if (IsRetired() || !IsOfType<T>()) {
+      return absl::nullopt;
+    }
+
+    // Implementation notes:
+    //
+    // We are wrapping a union around the value of `T` to serve three purposes:
+    //
+    //  1. `U.value` has correct size and alignment for a value of type `T`
+    //  2. The `U.value` constructor is not invoked since U's constructor does
+    //     not do it explicitly.
+    //  3. The `U.value` destructor is invoked since U's destructor does it
+    //     explicitly. This makes `U` a kind of RAII wrapper around non default
+    //     constructible value of T, which is destructed when we leave the
+    //     scope. We do need to destroy U.value, which is constructed by
+    //     CommandLineFlag::Read even though we left it in a moved-from state
+    //     after std::move.
+    //
+    // All of this serves to avoid requiring `T` being default constructible.
+    union U {
+      T value;
+      U() {}
+      ~U() { value.~T(); }
+    };
+    U u;
+
+    Read(&u.value);
+    // allow retired flags to be "read", so we can report invalid access.
+    if (IsRetired()) {
+      return absl::nullopt;
+    }
+    return std::move(u.value);
+  }
+
+  // absl::CommandLineFlag::Name()
+  //
+  // Returns name of this flag.
+  virtual absl::string_view Name() const = 0;
+
+  // absl::CommandLineFlag::Filename()
+  //
+  // Returns name of the file where this flag is defined.
+  virtual std::string Filename() const = 0;
+
+  // absl::CommandLineFlag::Help()
+  //
+  // Returns help message associated with this flag.
+  virtual std::string Help() const = 0;
+
+  // absl::CommandLineFlag::IsRetired()
+  //
+  // Returns true iff this object corresponds to retired flag.
+  virtual bool IsRetired() const;
+
+  // absl::CommandLineFlag::DefaultValue()
+  //
+  // Returns the default value for this flag.
+  virtual std::string DefaultValue() const = 0;
+
+  // absl::CommandLineFlag::CurrentValue()
+  //
+  // Returns the current value for this flag.
+  virtual std::string CurrentValue() const = 0;
+
+  // absl::CommandLineFlag::ParseFrom()
+  //
+  // Sets the value of the flag based on specified string `value`. If the flag
+  // was successfully set to new value, it returns true. Otherwise, sets `error`
+  // to indicate the error, leaves the flag unchanged, and returns false.
+  bool ParseFrom(absl::string_view value, std::string* error);
+
+ protected:
+  ~CommandLineFlag() = default;
+
+ private:
+  friend class flags_internal::PrivateHandleAccessor;
+
+  // Sets the value of the flag based on specified string `value`. If the flag
+  // was successfully set to new value, it returns true. Otherwise, sets `error`
+  // to indicate the error, leaves the flag unchanged, and returns false. There
+  // are three ways to set the flag's value:
+  //  * Update the current flag value
+  //  * Update the flag's default value
+  //  * Update the current flag value if it was never set before
+  // The mode is selected based on `set_mode` parameter.
+  virtual bool ParseFrom(absl::string_view value,
+                         flags_internal::FlagSettingMode set_mode,
+                         flags_internal::ValueSource source,
+                         std::string& error) = 0;
+
+  // Returns id of the flag's value type.
+  virtual flags_internal::FlagFastTypeId TypeId() const = 0;
+
+  // Interface to save flag to some persistent state. Returns current flag state
+  // or nullptr if flag does not support saving and restoring a state.
+  virtual std::unique_ptr<flags_internal::FlagStateInterface> SaveState() = 0;
+
+  // Copy-construct a new value of the flag's type in a memory referenced by
+  // the dst based on the current flag's value.
+  virtual void Read(void* dst) const = 0;
+
+  // To be deleted. Used to return true if flag's current value originated from
+  // command line.
+  virtual bool IsSpecifiedOnCommandLine() const = 0;
+
+  // Validates supplied value usign validator or parseflag routine
+  virtual bool ValidateInputValue(absl::string_view value) const = 0;
+
+  // Checks that flags default value can be converted to string and back to the
+  // flag's value type.
+  virtual void CheckDefaultValueParsingRoundtrip() const = 0;
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_COMMANDLINEFLAG_H_
diff --git a/absl/flags/commandlineflag_test.cc b/absl/flags/commandlineflag_test.cc
new file mode 100644
index 0000000..585db4b
--- /dev/null
+++ b/absl/flags/commandlineflag_test.cc
@@ -0,0 +1,231 @@
+//
+//  Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/commandlineflag.h"
+
+#include <memory>
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/private_handle_accessor.h"
+#include "absl/flags/reflection.h"
+#include "absl/flags/usage_config.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
+ABSL_FLAG(int, int_flag, 201, "int_flag help");
+ABSL_FLAG(std::string, string_flag, "dflt",
+          absl::StrCat("string_flag", " help"));
+ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
+
+// These are only used to test default values.
+ABSL_FLAG(int, int_flag2, 201, "");
+ABSL_FLAG(std::string, string_flag2, "dflt", "");
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+class CommandLineFlagTest : public testing::Test {
+ protected:
+  static void SetUpTestSuite() {
+    // Install a function to normalize filenames before this test is run.
+    absl::FlagsUsageConfig default_config;
+    default_config.normalize_filename = &CommandLineFlagTest::NormalizeFileName;
+    absl::SetFlagsUsageConfig(default_config);
+  }
+
+  void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
+  void TearDown() override { flag_saver_.reset(); }
+
+ private:
+  static std::string NormalizeFileName(absl::string_view fname) {
+#ifdef _WIN32
+    std::string normalized(fname);
+    std::replace(normalized.begin(), normalized.end(), '\\', '/');
+    fname = normalized;
+#endif
+    return std::string(fname);
+  }
+
+  std::unique_ptr<absl::FlagSaver> flag_saver_;
+};
+
+TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
+  auto* flag_01 = absl::FindCommandLineFlag("int_flag");
+
+  ASSERT_TRUE(flag_01);
+  EXPECT_EQ(flag_01->Name(), "int_flag");
+  EXPECT_EQ(flag_01->Help(), "int_flag help");
+  EXPECT_TRUE(!flag_01->IsRetired());
+  EXPECT_TRUE(flag_01->IsOfType<int>());
+  EXPECT_TRUE(!flag_01->IsOfType<bool>());
+  EXPECT_TRUE(!flag_01->IsOfType<std::string>());
+  EXPECT_TRUE(absl::EndsWith(flag_01->Filename(),
+                             "absl/flags/commandlineflag_test.cc"))
+      << flag_01->Filename();
+
+  auto* flag_02 = absl::FindCommandLineFlag("string_flag");
+
+  ASSERT_TRUE(flag_02);
+  EXPECT_EQ(flag_02->Name(), "string_flag");
+  EXPECT_EQ(flag_02->Help(), "string_flag help");
+  EXPECT_TRUE(!flag_02->IsRetired());
+  EXPECT_TRUE(flag_02->IsOfType<std::string>());
+  EXPECT_TRUE(!flag_02->IsOfType<bool>());
+  EXPECT_TRUE(!flag_02->IsOfType<int>());
+  EXPECT_TRUE(absl::EndsWith(flag_02->Filename(),
+                             "absl/flags/commandlineflag_test.cc"))
+      << flag_02->Filename();
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
+  absl::SetFlag(&FLAGS_int_flag2, 301);
+  auto* flag_01 = absl::FindCommandLineFlag("int_flag2");
+
+  ASSERT_TRUE(flag_01);
+  EXPECT_EQ(flag_01->CurrentValue(), "301");
+  EXPECT_EQ(flag_01->DefaultValue(), "201");
+
+  absl::SetFlag(&FLAGS_string_flag2, "new_str_value");
+  auto* flag_02 = absl::FindCommandLineFlag("string_flag2");
+
+  ASSERT_TRUE(flag_02);
+  EXPECT_EQ(flag_02->CurrentValue(), "new_str_value");
+  EXPECT_EQ(flag_02->DefaultValue(), "dflt");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
+  std::string err;
+
+  auto* flag_01 = absl::FindCommandLineFlag("int_flag");
+  EXPECT_FALSE(
+      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "11", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
+  EXPECT_FALSE(
+      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "-123", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+      err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
+  EXPECT_FALSE(
+      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+  EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+      err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
+  EXPECT_EQ(err, "Illegal value 'xyz' specified for flag 'int_flag'");
+  EXPECT_FALSE(
+      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+  EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "A1", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
+  EXPECT_EQ(err, "Illegal value 'A1' specified for flag 'int_flag'");
+  EXPECT_FALSE(
+      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "0x10", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+      err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);
+  EXPECT_FALSE(
+      flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "011", flags::SET_FLAGS_VALUE, flags::kCommandLine, err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
+  EXPECT_TRUE(flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+  EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
+  EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'");
+
+  auto* flag_02 = absl::FindCommandLineFlag("string_flag");
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_02, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+      err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz");
+
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_02, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {
+  std::string err;
+
+  auto* flag_01 = absl::FindCommandLineFlag("int_flag");
+
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
+      err));
+  EXPECT_EQ(flag_01->DefaultValue(), "111");
+
+  auto* flag_02 = absl::FindCommandLineFlag("string_flag");
+
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
+      err));
+  EXPECT_EQ(flag_02->DefaultValue(), "abc");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestParseFromIfDefault) {
+  std::string err;
+
+  auto* flag_01 = absl::FindCommandLineFlag("int_flag");
+
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "22", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+      err))
+      << err;
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
+
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+      err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
+  // EXPECT_EQ(err, "ERROR: int_flag is already set to 22");
+
+  // Reset back to default value
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "201", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+      err));
+
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+      *flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+      err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201);
+  // EXPECT_EQ(err, "ERROR: int_flag is already set to 201");
+}
+
+}  // namespace
diff --git a/absl/flags/config.h b/absl/flags/config.h
index a9fd97a..5ab1f31 100644
--- a/absl/flags/config.h
+++ b/absl/flags/config.h
@@ -45,4 +45,32 @@
 #define ABSL_FLAGS_STRIP_HELP ABSL_FLAGS_STRIP_NAMES
 #endif
 
+// ABSL_FLAGS_INTERNAL_HAS_RTTI macro is used for selecting if we can use RTTI
+// for flag type identification.
+#ifdef ABSL_FLAGS_INTERNAL_HAS_RTTI
+#error ABSL_FLAGS_INTERNAL_HAS_RTTI cannot be directly set
+#elif !defined(__GNUC__) || defined(__GXX_RTTI)
+#define ABSL_FLAGS_INTERNAL_HAS_RTTI 1
+#endif  // !defined(__GNUC__) || defined(__GXX_RTTI)
+
+// These macros represent the "source of truth" for the list of supported
+// built-in types.
+#define ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \
+  A(bool, bool)                              \
+  A(short, short)                            \
+  A(unsigned short, unsigned_short)          \
+  A(int, int)                                \
+  A(unsigned int, unsigned_int)              \
+  A(long, long)                              \
+  A(unsigned long, unsigned_long)            \
+  A(long long, long_long)                    \
+  A(unsigned long long, unsigned_long_long)  \
+  A(double, double)                          \
+  A(float, float)
+
+#define ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(A) \
+  ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A)         \
+  A(std::string, std_string)                   \
+  A(std::vector<std::string>, std_vector_of_string)
+
 #endif  // ABSL_FLAGS_CONFIG_H_
diff --git a/absl/flags/declare.h b/absl/flags/declare.h
index 0a113a2..b9794d8 100644
--- a/absl/flags/declare.h
+++ b/absl/flags/declare.h
@@ -25,9 +25,10 @@
 #ifndef ABSL_FLAGS_DECLARE_H_
 #define ABSL_FLAGS_DECLARE_H_
 
-#include "absl/strings/string_view.h"
+#include "absl/base/config.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 // absl::Flag<T> represents a flag of type 'T' created by ABSL_FLAG.
@@ -39,7 +40,7 @@
 // Flag
 //
 // Forward declaration of the `absl::Flag` type for use in defining the macro.
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && !defined(__clang__)
 template <typename T>
 class Flag;
 #else
@@ -47,6 +48,7 @@
 using Flag = flags_internal::Flag<T>;
 #endif
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 // ABSL_DECLARE_FLAG()
diff --git a/absl/flags/flag.cc b/absl/flags/flag.cc
index a02d069..531df12 100644
--- a/absl/flags/flag.cc
+++ b/absl/flags/flag.cc
@@ -15,46 +15,24 @@
 
 #include "absl/flags/flag.h"
 
-#include <cstring>
+#include "absl/base/config.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
-// We want to validate the type mismatch between type definition and
-// declaration. The lock-free implementation does not allow us to do it,
-// so in debug builds we always use the slower implementation, which always
-// validates the type.
-#ifndef NDEBUG
-#define ABSL_FLAGS_ATOMIC_GET(T) \
-  T GetFlag(const absl::Flag<T>& flag) { return flag.Get(); }
-#else
-#define ABSL_FLAGS_ATOMIC_GET(T)         \
-  T GetFlag(const absl::Flag<T>& flag) { \
-    T result;                            \
-    if (flag.AtomicGet(&result)) {       \
-      return result;                     \
-    }                                    \
-    return flag.Get();                   \
-  }
-#endif
-
-ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(ABSL_FLAGS_ATOMIC_GET)
-
-#undef ABSL_FLAGS_ATOMIC_GET
-
-// This global nutex protects on-demand construction of flag objects in MSVC
+// This global mutex protects on-demand construction of flag objects in MSVC
 // builds.
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && !defined(__clang__)
 
 namespace flags_internal {
 
 ABSL_CONST_INIT static absl::Mutex construction_guard(absl::kConstInit);
 
-void LockGlobalConstructionGuard() { construction_guard.Lock(); }
-
-void UnlockGlobalConstructionGuard() { construction_guard.Unlock(); }
+absl::Mutex* GetGlobalConstructionGuard() { return &construction_guard; }
 
 }  // namespace flags_internal
 
 #endif
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index 881f850..a9cb2b7 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -29,15 +29,19 @@
 #ifndef ABSL_FLAGS_FLAG_H_
 #define ABSL_FLAGS_FLAG_H_
 
+#include <string>
+#include <type_traits>
+
 #include "absl/base/attributes.h"
-#include "absl/base/casts.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
 #include "absl/flags/config.h"
-#include "absl/flags/declare.h"
-#include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/internal/flag.h"
-#include "absl/flags/marshalling.h"
+#include "absl/flags/internal/registry.h"
+#include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // Flag
 //
@@ -63,98 +67,104 @@
 //      ABSL_FLAG(int, count, 0, "Count of items to process");
 //
 // No public methods of `absl::Flag<T>` are part of the Abseil Flags API.
-#if !defined(_MSC_VER)
+#if !defined(_MSC_VER) || defined(__clang__)
 template <typename T>
 using Flag = flags_internal::Flag<T>;
 #else
-// MSVC debug builds do not implement constexpr correctly for classes with
-// virtual methods. To work around this we adding level of indirection, so that
-// the class `absl::Flag` contains an `internal::Flag*` (instead of being an
-// alias to that class) and dynamically allocates an instance when necessary.
-// We also forward all calls to internal::Flag methods via trampoline methods.
-// In this setup the `absl::Flag` class does not have virtual methods and thus
-// MSVC is able to initialize it at link time. To deal with multiple threads
-// accessing the flag for the first time concurrently we use an atomic boolean
-// indicating if flag object is constructed. We also employ the double-checked
-// locking pattern where the second level of protection is a global Mutex, so
-// if two threads attempt to construct the flag concurrently only one wins.
+// MSVC debug builds do not implement initialization with constexpr constructors
+// correctly. To work around this we add a level of indirection, so that the
+// class `absl::Flag` contains an `internal::Flag*` (instead of being an alias
+// to that class) and dynamically allocates an instance when necessary. We also
+// forward all calls to internal::Flag methods via trampoline methods. In this
+// setup the `absl::Flag` class does not have constructor and virtual methods,
+// all the data members are public and thus MSVC is able to initialize it at
+// link time. To deal with multiple threads accessing the flag for the first
+// time concurrently we use an atomic boolean indicating if flag object is
+// initialized. We also employ the double-checked locking pattern where the
+// second level of protection is a global Mutex, so if two threads attempt to
+// construct the flag concurrently only one wins.
+// This solution is based on a recomendation here:
+// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html?childToView=648454#comment-648454
 
 namespace flags_internal {
-void LockGlobalConstructionGuard();
-void UnlockGlobalConstructionGuard();
+absl::Mutex* GetGlobalConstructionGuard();
 }  // namespace flags_internal
 
 template <typename T>
 class Flag {
  public:
-  constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen,
-                 const char* filename,
-                 const flags_internal::FlagMarshallingOpFn marshalling_op,
-                 const flags_internal::InitialValGenFunc initial_value_gen)
+  // No constructor and destructor to ensure this is an aggregate type.
+  // Visual Studio 2015 still requires the constructor for class to be
+  // constexpr initializable.
+#if _MSC_VER <= 1900
+  constexpr Flag(const char* name, const char* filename,
+                 const flags_internal::HelpGenFunc help_gen,
+                 const flags_internal::FlagDfltGenFunc default_value_gen)
       : name_(name),
-        help_gen_(help_gen),
         filename_(filename),
-        marshalling_op_(marshalling_op),
-        initial_value_gen_(initial_value_gen),
-        inited_(false) {}
+        help_gen_(help_gen),
+        default_value_gen_(default_value_gen),
+        inited_(false),
+        impl_(nullptr) {}
+#endif
 
-  flags_internal::Flag<T>* GetImpl() const {
+  flags_internal::Flag<T>& GetImpl() const {
     if (!inited_.load(std::memory_order_acquire)) {
-      flags_internal::LockGlobalConstructionGuard();
+      absl::MutexLock l(flags_internal::GetGlobalConstructionGuard());
 
       if (inited_.load(std::memory_order_acquire)) {
-        return impl_;
+        return *impl_;
       }
 
-      impl_ = new flags_internal::Flag<T>(name_, help_gen_, filename_,
-                                          marshalling_op_, initial_value_gen_);
+      impl_ = new flags_internal::Flag<T>(
+          name_, filename_,
+          {flags_internal::FlagHelpMsg(help_gen_),
+           flags_internal::FlagHelpKind::kGenFunc},
+          {flags_internal::FlagDefaultSrc(default_value_gen_),
+           flags_internal::FlagDefaultKind::kGenFunc});
       inited_.store(true, std::memory_order_release);
-
-      flags_internal::UnlockGlobalConstructionGuard();
     }
 
-    return impl_;
+    return *impl_;
   }
 
-  // absl::Flag API
-  bool IsRetired() const { return GetImpl()->IsRetired(); }
-  bool IsAbseilFlag() const { return GetImpl()->IsAbseilFlag(); }
-  absl::string_view Name() const { return GetImpl()->Name(); }
-  std::string Help() const { return GetImpl()->Help(); }
-  bool IsModified() const { return GetImpl()->IsModified(); }
-  void SetModified(bool is_modified) { GetImpl()->SetModified(is_modified); }
+  // Public methods of `absl::Flag<T>` are NOT part of the Abseil Flags API.
+  // See https://abseil.io/docs/cpp/guides/flags
+  bool IsRetired() const { return GetImpl().IsRetired(); }
+  absl::string_view Name() const { return GetImpl().Name(); }
+  std::string Help() const { return GetImpl().Help(); }
+  bool IsModified() const { return GetImpl().IsModified(); }
   bool IsSpecifiedOnCommandLine() const {
-    GetImpl()->IsSpecifiedOnCommandLine();
+    return GetImpl().IsSpecifiedOnCommandLine();
   }
-  absl::string_view Typename() const { return GetImpl()->Typename(); }
-  std::string Filename() const { return GetImpl()->Filename(); }
-  std::string DefaultValue() const { return GetImpl()->DefaultValue(); }
-  std::string CurrentValue() const { return GetImpl()->CurrentValue(); }
-  bool HasValidatorFn() const { return GetImpl()->HasValidatorFn(); }
-  bool InvokeValidator(const void* value) const {
-    return GetImpl()->InvokeValidator(value);
-  }
-  template <typename T>
+  std::string Filename() const { return GetImpl().Filename(); }
+  std::string DefaultValue() const { return GetImpl().DefaultValue(); }
+  std::string CurrentValue() const { return GetImpl().CurrentValue(); }
+  template <typename U>
   inline bool IsOfType() const {
-    return GetImpl()->IsOftype<T>();
+    return GetImpl().template IsOfType<U>();
   }
-  T Get() const { return GetImpl()->Get(); }
-  bool AtomicGet(T* v) const { return GetImpl()->AtomicGet(v); }
-  void Set(const T& v) { GetImpl()->Set(v); }
-  void SetCallback(const flags_internal::FlagCallback mutation_callback) {
-    GetImpl()->SetCallback(mutation_callback);
+  T Get() const {
+    return flags_internal::FlagImplPeer::InvokeGet<T>(GetImpl());
   }
-  void InvokeCallback() { GetImpl()->InvokeCallback(); }
+  void Set(const T& v) {
+    flags_internal::FlagImplPeer::InvokeSet(GetImpl(), v);
+  }
+  void InvokeCallback() { GetImpl().InvokeCallback(); }
 
- private:
+  const CommandLineFlag& Reflect() const {
+    return flags_internal::FlagImplPeer::InvokeReflect(GetImpl());
+  }
+
+  // The data members are logically private, but they need to be public for
+  // this to be an aggregate type.
   const char* name_;
-  const flags_internal::HelpGenFunc help_gen_;
   const char* filename_;
-  const flags_internal::FlagMarshallingOpFn marshalling_op_;
-  const flags_internal::InitialValGenFunc initial_value_gen_;
+  const flags_internal::HelpGenFunc help_gen_;
+  const flags_internal::FlagDfltGenFunc default_value_gen_;
 
   mutable std::atomic<bool> inited_;
-  mutable flags_internal::Flag<T>* impl_ = nullptr;
+  mutable flags_internal::Flag<T>* impl_;
 };
 #endif
 
@@ -176,22 +186,9 @@
 //   std::string first_name = absl::GetFlag(FLAGS_firstname);
 template <typename T>
 ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
-#define ABSL_FLAGS_INTERNAL_LOCK_FREE_VALIDATE(BIT) \
-  static_assert(                                    \
-      !std::is_same<T, BIT>::value,                 \
-      "Do not specify explicit template parameters to absl::GetFlag");
-  ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(ABSL_FLAGS_INTERNAL_LOCK_FREE_VALIDATE)
-#undef ABSL_FLAGS_INTERNAL_LOCK_FREE_VALIDATE
-
-  return flag.Get();
+  return flags_internal::FlagImplPeer::InvokeGet<T>(flag);
 }
 
-// Overload for `GetFlag()` for types that support lock-free reads.
-#define ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT(T) \
-  ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag);
-ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT)
-#undef ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT
-
 // SetFlag()
 //
 // Sets the value of an `absl::Flag` to the value `v`. Do not construct an
@@ -201,7 +198,7 @@
 // but especially within performance-critical code.
 template <typename T>
 void SetFlag(absl::Flag<T>* flag, const T& v) {
-  flag->Set(v);
+  flags_internal::FlagImplPeer::InvokeSet(*flag, v);
 }
 
 // Overload of `SetFlag()` to allow callers to pass in a value that is
@@ -210,9 +207,25 @@
 template <typename T, typename V>
 void SetFlag(absl::Flag<T>* flag, const V& v) {
   T value(v);
-  flag->Set(value);
+  flags_internal::FlagImplPeer::InvokeSet(*flag, value);
 }
 
+// GetFlagReflectionHandle()
+//
+// Returns the reflection handle corresponding to specified Abseil Flag
+// instance. Use this handle to access flag's reflection information, like name,
+// location, default value etc.
+//
+// Example:
+//
+//   std::string = absl::GetFlagReflectionHandle(FLAGS_count).DefaultValue();
+
+template <typename T>
+const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
+  return flags_internal::FlagImplPeer::InvokeReflect(f);
+}
+
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 
@@ -272,27 +285,29 @@
 // -----------------------------------------------------------------------------
 
 // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES
+#if !defined(_MSC_VER) || defined(__clang__)
+#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag
+#define ABSL_FLAG_IMPL_HELP_ARG(name)                      \
+  absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \
+      FLAGS_help_storage_##name)
+#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) \
+  absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)
+#else
+#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag.GetImpl()
+#define ABSL_FLAG_IMPL_HELP_ARG(name) &AbslFlagHelpGenFor##name::NonConst
+#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) &AbslFlagDefaultGenFor##name::Gen
+#endif
 
 #if ABSL_FLAGS_STRIP_NAMES
 #define ABSL_FLAG_IMPL_FLAGNAME(txt) ""
 #define ABSL_FLAG_IMPL_FILENAME() ""
-#if !defined(_MSC_VER)
 #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, false>(&flag)
-#else
-#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, false>(flag.GetImpl())
-#endif
+  absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
 #else
 #define ABSL_FLAG_IMPL_FLAGNAME(txt) txt
 #define ABSL_FLAG_IMPL_FILENAME() __FILE__
-#if !defined(_MSC_VER)
 #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, true>(&flag)
-#else
-#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, true>(flag.GetImpl())
-#endif
+  absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
 #endif
 
 // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
@@ -303,32 +318,53 @@
 #define ABSL_FLAG_IMPL_FLAGHELP(txt) txt
 #endif
 
-#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt) \
-  static std::string AbslFlagsWrapHelp##name() {       \
-    return ABSL_FLAG_IMPL_FLAGHELP(txt);               \
-  }
+// AbslFlagHelpGenFor##name is used to encapsulate both immediate (method Const)
+// and lazy (method NonConst) evaluation of help message expression. We choose
+// between the two via the call to HelpArg in absl::Flag instantiation below.
+// If help message expression is constexpr evaluable compiler will optimize
+// away this whole struct.
+// TODO(rogeeff): place these generated structs into local namespace and apply
+// ABSL_INTERNAL_UNIQUE_SHORT_NAME.
+// TODO(rogeeff): Apply __attribute__((nodebug)) to FLAGS_help_storage_##name
+#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt)                       \
+  struct AbslFlagHelpGenFor##name {                                          \
+    /* The expression is run in the caller as part of the   */               \
+    /* default value argument. That keeps temporaries alive */               \
+    /* long enough for NonConst to work correctly.          */               \
+    static constexpr absl::string_view Value(                                \
+        absl::string_view v = ABSL_FLAG_IMPL_FLAGHELP(txt)) {                \
+      return v;                                                              \
+    }                                                                        \
+    static std::string NonConst() { return std::string(Value()); }           \
+  };                                                                         \
+  constexpr auto FLAGS_help_storage_##name ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
+      ABSL_ATTRIBUTE_SECTION_VARIABLE(flags_help_cold) =                     \
+          absl::flags_internal::HelpStringAsArray<AbslFlagHelpGenFor##name>( \
+              0);
 
-#define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)   \
-  static void* AbslFlagsInitFlag##name() {                                  \
-    return absl::flags_internal::MakeFromDefaultValue<Type>(default_value); \
-  }
+#define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)     \
+  struct AbslFlagDefaultGenFor##name {                                        \
+    Type value = absl::flags_internal::InitDefaultValue<Type>(default_value); \
+    static void Gen(void* p) {                                                \
+      new (p) Type(AbslFlagDefaultGenFor##name{}.value);                      \
+    }                                                                         \
+  };
 
 // ABSL_FLAG_IMPL
 //
 // Note: Name of registrar object is not arbitrary. It is used to "grab"
 // global name for FLAGS_no<flag_name> symbol, thus preventing the possibility
 // of defining two flags with names foo and nofoo.
-#define ABSL_FLAG_IMPL(Type, name, default_value, help)             \
-  namespace absl /* block flags in namespaces */ {}                 \
-  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
-  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help)                   \
-  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name(                    \
-      ABSL_FLAG_IMPL_FLAGNAME(#name), &AbslFlagsWrapHelp##name,     \
-      ABSL_FLAG_IMPL_FILENAME(),                                    \
-      &absl::flags_internal::FlagMarshallingOps<Type>,              \
-      &AbslFlagsInitFlag##name);                                    \
-  extern bool FLAGS_no##name;                                       \
-  bool FLAGS_no##name = ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
+#define ABSL_FLAG_IMPL(Type, name, default_value, help)                       \
+  namespace absl /* block flags in namespaces */ {}                           \
+  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)           \
+  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help)                             \
+  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                              \
+      ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(),              \
+      ABSL_FLAG_IMPL_HELP_ARG(name), ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \
+  extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;             \
+  absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =                   \
+      ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
 
 // ABSL_RETIRED_FLAG
 //
@@ -349,11 +385,12 @@
 //
 // `default_value` is only used as a double check on the type. `explanation` is
 // unused.
-// TODO(rogeeff): Return an anonymous struct instead of bool, and place it into
-// the unnamed namespace.
-#define ABSL_RETIRED_FLAG(type, flagname, default_value, explanation) \
-  ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname =        \
-      ([] { return type(default_value); },                            \
-       absl::flags_internal::RetiredFlag<type>(#flagname))
+// TODO(rogeeff): replace RETIRED_FLAGS with FLAGS once forward declarations of
+// retired flags are cleaned up.
+#define ABSL_RETIRED_FLAG(type, name, default_value, explanation)      \
+  static absl::flags_internal::RetiredFlag<type> RETIRED_FLAGS_##name; \
+  ABSL_ATTRIBUTE_UNUSED static const auto RETIRED_FLAGS_REG_##name =   \
+      (RETIRED_FLAGS_##name.Retire(#name),                             \
+       ::absl::flags_internal::FlagRegistrarEmpty{})
 
 #endif  // ABSL_FLAGS_FLAG_H_
diff --git a/absl/flags/flag_benchmark.cc b/absl/flags/flag_benchmark.cc
new file mode 100644
index 0000000..57584f8
--- /dev/null
+++ b/absl/flags/flag_benchmark.cc
@@ -0,0 +1,168 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/flags/flag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/flags/parse.h"
+#include "absl/flags/reflection.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+#include "absl/types/optional.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+using String = std::string;
+using VectorOfStrings = std::vector<std::string>;
+using AbslDuration = absl::Duration;
+
+// We do not want to take over marshalling for the types absl::optional<int>,
+// absl::optional<std::string> which we do not own. Instead we introduce unique
+// "aliases" to these types, which we do.
+using AbslOptionalInt = absl::optional<int>;
+struct OptionalInt : AbslOptionalInt {
+  using AbslOptionalInt::AbslOptionalInt;
+};
+// Next two functions represent Abseil Flags marshalling for OptionalInt.
+bool AbslParseFlag(absl::string_view src, OptionalInt* flag,
+                   std::string* error) {
+  int val;
+  if (src.empty())
+    flag->reset();
+  else if (!absl::ParseFlag(src, &val, error))
+    return false;
+  *flag = val;
+  return true;
+}
+std::string AbslUnparseFlag(const OptionalInt& flag) {
+  return !flag ? "" : absl::UnparseFlag(*flag);
+}
+
+using AbslOptionalString = absl::optional<std::string>;
+struct OptionalString : AbslOptionalString {
+  using AbslOptionalString::AbslOptionalString;
+};
+// Next two functions represent Abseil Flags marshalling for OptionalString.
+bool AbslParseFlag(absl::string_view src, OptionalString* flag,
+                   std::string* error) {
+  std::string val;
+  if (src.empty())
+    flag->reset();
+  else if (!absl::ParseFlag(src, &val, error))
+    return false;
+  *flag = val;
+  return true;
+}
+std::string AbslUnparseFlag(const OptionalString& flag) {
+  return !flag ? "" : absl::UnparseFlag(*flag);
+}
+
+struct UDT {
+  UDT() = default;
+  UDT(const UDT&) {}
+  UDT& operator=(const UDT&) { return *this; }
+};
+// Next two functions represent Abseil Flags marshalling for UDT.
+bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
+std::string AbslUnparseFlag(const UDT&) { return ""; }
+
+}  // namespace
+
+#define BENCHMARKED_TYPES(A) \
+  A(bool)                    \
+  A(int16_t)                 \
+  A(uint16_t)                \
+  A(int32_t)                 \
+  A(uint32_t)                \
+  A(int64_t)                 \
+  A(uint64_t)                \
+  A(double)                  \
+  A(float)                   \
+  A(String)                  \
+  A(VectorOfStrings)         \
+  A(OptionalInt)             \
+  A(OptionalString)          \
+  A(AbslDuration)            \
+  A(UDT)
+
+#define FLAG_DEF(T) ABSL_FLAG(T, T##_flag, {}, "");
+
+#if defined(__clang__) && defined(__linux__)
+// Force the flags used for benchmarks into a separate ELF section.
+// This ensures that, even when other parts of the code might change size,
+// the layout of the flags across cachelines is kept constant. This makes
+// benchmark results more reproducible across unrelated code changes.
+#pragma clang section data = ".benchmark_flags"
+#endif
+BENCHMARKED_TYPES(FLAG_DEF)
+#if defined(__clang__) && defined(__linux__)
+#pragma clang section data = ""
+#endif
+// Register thousands of flags to bloat up the size of the registry.
+// This mimics real life production binaries.
+#define DEFINE_FLAG_0(name) ABSL_FLAG(int, name, 0, "");
+#define DEFINE_FLAG_1(name) DEFINE_FLAG_0(name##0) DEFINE_FLAG_0(name##1)
+#define DEFINE_FLAG_2(name) DEFINE_FLAG_1(name##0) DEFINE_FLAG_1(name##1)
+#define DEFINE_FLAG_3(name) DEFINE_FLAG_2(name##0) DEFINE_FLAG_2(name##1)
+#define DEFINE_FLAG_4(name) DEFINE_FLAG_3(name##0) DEFINE_FLAG_3(name##1)
+#define DEFINE_FLAG_5(name) DEFINE_FLAG_4(name##0) DEFINE_FLAG_4(name##1)
+#define DEFINE_FLAG_6(name) DEFINE_FLAG_5(name##0) DEFINE_FLAG_5(name##1)
+#define DEFINE_FLAG_7(name) DEFINE_FLAG_6(name##0) DEFINE_FLAG_6(name##1)
+#define DEFINE_FLAG_8(name) DEFINE_FLAG_7(name##0) DEFINE_FLAG_7(name##1)
+#define DEFINE_FLAG_9(name) DEFINE_FLAG_8(name##0) DEFINE_FLAG_8(name##1)
+#define DEFINE_FLAG_10(name) DEFINE_FLAG_9(name##0) DEFINE_FLAG_9(name##1)
+#define DEFINE_FLAG_11(name) DEFINE_FLAG_10(name##0) DEFINE_FLAG_10(name##1)
+#define DEFINE_FLAG_12(name) DEFINE_FLAG_11(name##0) DEFINE_FLAG_11(name##1)
+DEFINE_FLAG_12(bloat_flag_);
+
+namespace {
+
+#define BM_GetFlag(T)                                            \
+  void BM_GetFlag_##T(benchmark::State& state) {                 \
+    for (auto _ : state) {                                       \
+      benchmark::DoNotOptimize(absl::GetFlag(FLAGS_##T##_flag)); \
+    }                                                            \
+  }                                                              \
+  BENCHMARK(BM_GetFlag_##T)->ThreadRange(1, 16);
+
+BENCHMARKED_TYPES(BM_GetFlag)
+
+void BM_ThreadedFindCommandLineFlag(benchmark::State& state) {
+  char dummy[] = "dummy";
+  char* argv[] = {dummy};
+  // We need to ensure that flags have been parsed. That is where the registry
+  // is finalized.
+  absl::ParseCommandLine(1, argv);
+
+  for (auto s : state) {
+    benchmark::DoNotOptimize(
+        absl::FindCommandLineFlag("bloat_flag_010101010101"));
+  }
+}
+BENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16);
+
+}  // namespace
+
+#define InvokeGetFlag(T)                                               \
+  T AbslInvokeGetFlag##T() { return absl::GetFlag(FLAGS_##T##_flag); } \
+  int odr##T = (benchmark::DoNotOptimize(AbslInvokeGetFlag##T), 1);
+
+BENCHMARKED_TYPES(InvokeGetFlag)
+
+// To veiw disassembly use: gdb ${BINARY}  -batch -ex "disassemble /s $FUNC"
diff --git a/absl/flags/flag_benchmark.lds b/absl/flags/flag_benchmark.lds
new file mode 100644
index 0000000..af115df
--- /dev/null
+++ b/absl/flags/flag_benchmark.lds
@@ -0,0 +1,13 @@
+/* This linker script forces the flags used by flags_benchmark
+ * into a separate page-aligned section. This isn't necessary for
+ * correctness but ensures that the benchmark results are more
+ * reproducible across unrelated code changes.
+ */
+SECTIONS {
+  .benchmark_flags : {
+    . = ALIGN(0x1000);
+    * (.benchmark_flags);
+  }
+}
+
+INSERT AFTER .data
diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc
index a652042..72507b9 100644
--- a/absl/flags/flag_test.cc
+++ b/absl/flags/flag_test.cc
@@ -15,15 +15,31 @@
 
 #include "absl/flags/flag.h"
 
-#include <algorithm>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+#include <cmath>
+#include <new>
 #include <string>
+#include <thread>  // NOLINT
+#include <vector>
 
 #include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/macros.h"
+#include "absl/flags/config.h"
+#include "absl/flags/declare.h"
+#include "absl/flags/internal/flag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/flags/reflection.h"
 #include "absl/flags/usage_config.h"
 #include "absl/strings/match.h"
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
 
 ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag);
 ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag);
@@ -32,34 +48,16 @@
 
 namespace flags = absl::flags_internal;
 
-std::string TestHelpMsg() { return "help"; }
+std::string TestHelpMsg() { return "dynamic help"; }
+#if defined(_MSC_VER) && !defined(__clang__)
+std::string TestLiteralHelpMsg() { return "literal help"; }
+#endif
 template <typename T>
-void* TestMakeDflt() {
-  return new T{};
+void TestMakeDflt(void* dst) {
+  new (dst) T{};
 }
 void TestCallback() {}
 
-template <typename T>
-bool TestConstructionFor() {
-  constexpr flags::Flag<T> f1("f1", &TestHelpMsg, "file",
-                              &absl::flags_internal::FlagMarshallingOps<T>,
-                              &TestMakeDflt<T>);
-  EXPECT_EQ(f1.Name(), "f1");
-  EXPECT_EQ(f1.Help(), "help");
-  EXPECT_EQ(f1.Filename(), "file");
-
-  ABSL_CONST_INIT static flags::Flag<T> f2(
-      "f2", &TestHelpMsg, "file", &absl::flags_internal::FlagMarshallingOps<T>,
-      &TestMakeDflt<T>);
-  flags::FlagRegistrar<T, false>(&f2).OnUpdate(TestCallback);
-
-  EXPECT_EQ(f2.Name(), "f2");
-  EXPECT_EQ(f2.Help(), "help");
-  EXPECT_EQ(f2.Filename(), "file");
-
-  return true;
-}
-
 struct UDT {
   UDT() = default;
   UDT(const UDT&) = default;
@@ -85,21 +83,124 @@
 #endif
     return std::string(fname);
   }
+  absl::FlagSaver flag_saver_;
 };
 
-TEST_F(FlagTest, TestConstruction) {
-  TestConstructionFor<bool>();
-  TestConstructionFor<int16_t>();
-  TestConstructionFor<uint16_t>();
-  TestConstructionFor<int32_t>();
-  TestConstructionFor<uint32_t>();
-  TestConstructionFor<int64_t>();
-  TestConstructionFor<uint64_t>();
-  TestConstructionFor<double>();
-  TestConstructionFor<float>();
-  TestConstructionFor<std::string>();
+struct S1 {
+  S1() = default;
+  S1(const S1&) = default;
+  int32_t f1;
+  int64_t f2;
+};
 
-  TestConstructionFor<UDT>();
+struct S2 {
+  S2() = default;
+  S2(const S2&) = default;
+  int64_t f1;
+  double f2;
+};
+
+TEST_F(FlagTest, Traits) {
+  EXPECT_EQ(flags::StorageKind<int>(),
+            flags::FlagValueStorageKind::kOneWordAtomic);
+  EXPECT_EQ(flags::StorageKind<bool>(),
+            flags::FlagValueStorageKind::kOneWordAtomic);
+  EXPECT_EQ(flags::StorageKind<double>(),
+            flags::FlagValueStorageKind::kOneWordAtomic);
+  EXPECT_EQ(flags::StorageKind<int64_t>(),
+            flags::FlagValueStorageKind::kOneWordAtomic);
+
+  EXPECT_EQ(flags::StorageKind<S1>(),
+            flags::FlagValueStorageKind::kSequenceLocked);
+  EXPECT_EQ(flags::StorageKind<S2>(),
+            flags::FlagValueStorageKind::kSequenceLocked);
+// Make sure absl::Duration uses the sequence-locked code path. MSVC 2015
+// doesn't consider absl::Duration to be trivially-copyable so we just
+// restrict this to clang as it seems to be a well-behaved compiler.
+#ifdef __clang__
+  EXPECT_EQ(flags::StorageKind<absl::Duration>(),
+            flags::FlagValueStorageKind::kSequenceLocked);
+#endif
+
+  EXPECT_EQ(flags::StorageKind<std::string>(),
+            flags::FlagValueStorageKind::kAlignedBuffer);
+  EXPECT_EQ(flags::StorageKind<std::vector<std::string>>(),
+            flags::FlagValueStorageKind::kAlignedBuffer);
+}
+
+// --------------------------------------------------------------------
+
+constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"),
+                                      flags::FlagHelpKind::kLiteral};
+
+using String = std::string;
+
+#if !defined(_MSC_VER) || defined(__clang__)
+#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind)                        \
+  constexpr flags::FlagDefaultArg f1default##T{                            \
+      flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind};     \
+  constexpr absl::Flag<T> f1##T{"f1", "file", help_arg, f1default##T};     \
+  ABSL_CONST_INIT absl::Flag<T> f2##T {                                    \
+    "f2", "file",                                                          \
+        {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
+        flags::FlagDefaultArg {                                            \
+      flags::FlagDefaultSrc(&TestMakeDflt<T>),                             \
+          flags::FlagDefaultKind::kGenFunc                                 \
+    }                                                                      \
+  }
+#else
+#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind)                    \
+  constexpr flags::FlagDefaultArg f1default##T{                        \
+      flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
+  constexpr absl::Flag<T> f1##T{"f1", "file", &TestLiteralHelpMsg,     \
+                                &TestMakeDflt<T>};                     \
+  ABSL_CONST_INIT absl::Flag<T> f2##T {                                \
+    "f2", "file", &TestHelpMsg, &TestMakeDflt<T>                       \
+  }
+#endif
+
+DEFINE_CONSTRUCTED_FLAG(bool, true, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(uint16_t, 2, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(int32_t, 3, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(uint32_t, 4, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(int64_t, 5, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(uint64_t, 6, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(float, 7.8, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(double, 9.10, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc);
+DEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc);
+
+template <typename T>
+bool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Name(), "f1");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), "literal help");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), "file");
+
+  flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2))
+      .OnUpdate(TestCallback);
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), "dynamic help");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), "file");
+
+  return true;
+}
+
+#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);
+
+TEST_F(FlagTest, TestConstruction) {
+  TEST_CONSTRUCTED_FLAG(bool);
+  TEST_CONSTRUCTED_FLAG(int16_t);
+  TEST_CONSTRUCTED_FLAG(uint16_t);
+  TEST_CONSTRUCTED_FLAG(int32_t);
+  TEST_CONSTRUCTED_FLAG(uint32_t);
+  TEST_CONSTRUCTED_FLAG(int64_t);
+  TEST_CONSTRUCTED_FLAG(uint64_t);
+  TEST_CONSTRUCTED_FLAG(float);
+  TEST_CONSTRUCTED_FLAG(double);
+  TEST_CONSTRUCTED_FLAG(String);
+  TEST_CONSTRUCTED_FLAG(UDT);
 }
 
 // --------------------------------------------------------------------
@@ -117,6 +218,7 @@
 ABSL_DECLARE_FLAG(double, test_flag_09);
 ABSL_DECLARE_FLAG(float, test_flag_10);
 ABSL_DECLARE_FLAG(std::string, test_flag_11);
+ABSL_DECLARE_FLAG(absl::Duration, test_flag_12);
 
 namespace {
 
@@ -124,17 +226,30 @@
 
 TEST_F(FlagTest, TestFlagDeclaration) {
   // test that we can access flag objects.
-  EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");
-  EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");
-  EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");
-  EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");
-  EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");
-  EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");
-  EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");
-  EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");
-  EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");
-  EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");
-  EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
+            "test_flag_01");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
+            "test_flag_02");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
+            "test_flag_03");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
+            "test_flag_04");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
+            "test_flag_05");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
+            "test_flag_06");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
+            "test_flag_07");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
+            "test_flag_08");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
+            "test_flag_09");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
+            "test_flag_10");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
+            "test_flag_11");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
+            "test_flag_12");
 }
 #endif  // !ABSL_FLAGS_STRIP_NAMES
 
@@ -153,6 +268,7 @@
 ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09");
 ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10");
 ABSL_FLAG(std::string, test_flag_11, "", "test flag 11");
+ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "test flag 12");
 
 namespace {
 
@@ -160,66 +276,169 @@
 TEST_F(FlagTest, TestFlagDefinition) {
   absl::string_view expected_file_name = "absl/flags/flag_test.cc";
 
-  EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");
-  EXPECT_EQ(FLAGS_test_flag_01.Help(), "test flag 01");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_01.Filename(), expected_file_name))
-      << FLAGS_test_flag_01.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
+            "test_flag_01");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(),
+            "test flag 01");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename();
 
-  EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");
-  EXPECT_EQ(FLAGS_test_flag_02.Help(), "test flag 02");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_02.Filename(), expected_file_name))
-      << FLAGS_test_flag_02.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
+            "test_flag_02");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(),
+            "test flag 02");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename();
 
-  EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");
-  EXPECT_EQ(FLAGS_test_flag_03.Help(), "test flag 03");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_03.Filename(), expected_file_name))
-      << FLAGS_test_flag_03.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
+            "test_flag_03");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(),
+            "test flag 03");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename();
 
-  EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");
-  EXPECT_EQ(FLAGS_test_flag_04.Help(), "test flag 04");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_04.Filename(), expected_file_name))
-      << FLAGS_test_flag_04.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
+            "test_flag_04");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(),
+            "test flag 04");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename();
 
-  EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");
-  EXPECT_EQ(FLAGS_test_flag_05.Help(), "test flag 05");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_05.Filename(), expected_file_name))
-      << FLAGS_test_flag_05.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
+            "test_flag_05");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(),
+            "test flag 05");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename();
 
-  EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");
-  EXPECT_EQ(FLAGS_test_flag_06.Help(), "test flag 06");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_06.Filename(), expected_file_name))
-      << FLAGS_test_flag_06.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
+            "test_flag_06");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(),
+            "test flag 06");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename();
 
-  EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");
-  EXPECT_EQ(FLAGS_test_flag_07.Help(), "test flag 07");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_07.Filename(), expected_file_name))
-      << FLAGS_test_flag_07.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
+            "test_flag_07");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(),
+            "test flag 07");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename();
 
-  EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");
-  EXPECT_EQ(FLAGS_test_flag_08.Help(), "test flag 08");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_08.Filename(), expected_file_name))
-      << FLAGS_test_flag_08.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
+            "test_flag_08");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(),
+            "test flag 08");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename();
 
-  EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");
-  EXPECT_EQ(FLAGS_test_flag_09.Help(), "test flag 09");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_09.Filename(), expected_file_name))
-      << FLAGS_test_flag_09.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
+            "test_flag_09");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(),
+            "test flag 09");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename();
 
-  EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");
-  EXPECT_EQ(FLAGS_test_flag_10.Help(), "test flag 10");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_10.Filename(), expected_file_name))
-      << FLAGS_test_flag_10.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
+            "test_flag_10");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(),
+            "test flag 10");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename();
 
-  EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11");
-  EXPECT_EQ(FLAGS_test_flag_11.Help(), "test flag 11");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_11.Filename(), expected_file_name))
-      << FLAGS_test_flag_11.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
+            "test_flag_11");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(),
+            "test flag 11");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
+            "test_flag_12");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(),
+            "test flag 12");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename();
 }
 #endif  // !ABSL_FLAGS_STRIP_NAMES
 
 // --------------------------------------------------------------------
 
 TEST_F(FlagTest, TestDefault) {
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(),
+            "true");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(),
+            "1234");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(),
+            "-34");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(),
+            "189");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(),
+            "10765");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(),
+            "40000");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(),
+            "-1234567");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(),
+            "9876543");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(),
+            "-9.876e-50");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(),
+            "1.234e+12");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(),
+            "");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).DefaultValue(),
+            "10m");
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(),
+            "true");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(),
+            "1234");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(),
+            "-34");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(),
+            "189");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(),
+            "10765");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(),
+            "40000");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(),
+            "-1234567");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(),
+            "9876543");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(),
+            "-9.876e-50");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(),
+            "1.234e+12");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(),
+            "");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(),
+            "10m");
+
   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
@@ -231,6 +450,68 @@
   EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
   EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
+}
+
+// --------------------------------------------------------------------
+
+struct NonTriviallyCopyableAggregate {
+  NonTriviallyCopyableAggregate() = default;
+  NonTriviallyCopyableAggregate(const NonTriviallyCopyableAggregate& rhs)
+      : value(rhs.value) {}
+  NonTriviallyCopyableAggregate& operator=(
+      const NonTriviallyCopyableAggregate& rhs) {
+    value = rhs.value;
+    return *this;
+  }
+
+  int value;
+};
+bool AbslParseFlag(absl::string_view src, NonTriviallyCopyableAggregate* f,
+                   std::string* e) {
+  return absl::ParseFlag(src, &f->value, e);
+}
+std::string AbslUnparseFlag(const NonTriviallyCopyableAggregate& ntc) {
+  return absl::StrCat(ntc.value);
+}
+
+bool operator==(const NonTriviallyCopyableAggregate& ntc1,
+                const NonTriviallyCopyableAggregate& ntc2) {
+  return ntc1.value == ntc2.value;
+}
+
+}  // namespace
+
+ABSL_FLAG(bool, test_flag_eb_01, {}, "");
+ABSL_FLAG(int32_t, test_flag_eb_02, {}, "");
+ABSL_FLAG(int64_t, test_flag_eb_03, {}, "");
+ABSL_FLAG(double, test_flag_eb_04, {}, "");
+ABSL_FLAG(std::string, test_flag_eb_05, {}, "");
+ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, "");
+
+namespace {
+
+TEST_F(FlagTest, TestEmptyBracesDefault) {
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(),
+            "false");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(),
+            "0");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(),
+            "0");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(),
+            "0");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(),
+            "");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_06).DefaultValue(),
+            "0");
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_03), 0);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_04), 0.0);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_05), "");
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_06),
+            NonTriviallyCopyableAggregate{});
 }
 
 // --------------------------------------------------------------------
@@ -268,6 +549,75 @@
 
   absl::SetFlag(&FLAGS_test_flag_11, "asdf");
   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf");
+
+  absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110));
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagTest, TestGetViaReflection) {
+  auto* handle = absl::FindCommandLineFlag("test_flag_01");
+  EXPECT_EQ(*handle->TryGet<bool>(), true);
+  handle = absl::FindCommandLineFlag("test_flag_02");
+  EXPECT_EQ(*handle->TryGet<int>(), 1234);
+  handle = absl::FindCommandLineFlag("test_flag_03");
+  EXPECT_EQ(*handle->TryGet<int16_t>(), -34);
+  handle = absl::FindCommandLineFlag("test_flag_04");
+  EXPECT_EQ(*handle->TryGet<uint16_t>(), 189);
+  handle = absl::FindCommandLineFlag("test_flag_05");
+  EXPECT_EQ(*handle->TryGet<int32_t>(), 10765);
+  handle = absl::FindCommandLineFlag("test_flag_06");
+  EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000);
+  handle = absl::FindCommandLineFlag("test_flag_07");
+  EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567);
+  handle = absl::FindCommandLineFlag("test_flag_08");
+  EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543);
+  handle = absl::FindCommandLineFlag("test_flag_09");
+  EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55);
+  handle = absl::FindCommandLineFlag("test_flag_10");
+  EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f);
+  handle = absl::FindCommandLineFlag("test_flag_11");
+  EXPECT_EQ(*handle->TryGet<std::string>(), "");
+  handle = absl::FindCommandLineFlag("test_flag_12");
+  EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagTest, ConcurrentSetAndGet) {
+  static constexpr int kNumThreads = 8;
+  // Two arbitrary durations. One thread will concurrently flip the flag
+  // between these two values, while the other threads read it and verify
+  // that no other value is seen.
+  static const absl::Duration kValidDurations[] = {
+      absl::Seconds(int64_t{0x6cebf47a9b68c802}) + absl::Nanoseconds(229702057),
+      absl::Seconds(int64_t{0x23fec0307e4e9d3}) + absl::Nanoseconds(44555374)};
+  absl::SetFlag(&FLAGS_test_flag_12, kValidDurations[0]);
+
+  std::atomic<bool> stop{false};
+  std::vector<std::thread> threads;
+  auto* handle = absl::FindCommandLineFlag("test_flag_12");
+  for (int i = 0; i < kNumThreads; i++) {
+    threads.emplace_back([&]() {
+      while (!stop.load(std::memory_order_relaxed)) {
+        // Try loading the flag both directly and via a reflection
+        // handle.
+        absl::Duration v = absl::GetFlag(FLAGS_test_flag_12);
+        EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
+        v = *handle->TryGet<absl::Duration>();
+        EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
+      }
+    });
+  }
+  absl::Time end_time = absl::Now() + absl::Seconds(1);
+  int i = 0;
+  while (absl::Now() < end_time) {
+    absl::SetFlag(&FLAGS_test_flag_12,
+                  kValidDurations[i++ % ABSL_ARRAYSIZE(kValidDurations)]);
+  }
+  stop.store(true, std::memory_order_relaxed);
+  for (auto& t : threads) t.join();
 }
 
 // --------------------------------------------------------------------
@@ -276,28 +626,33 @@
 
 }  // namespace
 
-ABSL_FLAG(int, test_flag_12, GetDflt1(), "test flag 12");
-ABSL_FLAG(std::string, test_flag_13, absl::StrCat("AAA", "BBB"),
-          "test flag 13");
+ABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(),
+          "test int flag non const default");
+ABSL_FLAG(std::string, test_string_flag_with_non_const_default,
+          absl::StrCat("AAA", "BBB"), "test string flag non const default");
 
 namespace {
 
 TEST_F(FlagTest, TestNonConstexprDefault) {
-  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), 1);
-  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), "AAABBB");
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default),
+            "AAABBB");
 }
 
 // --------------------------------------------------------------------
 
 }  // namespace
 
-ABSL_FLAG(bool, test_flag_14, true, absl::StrCat("test ", "flag ", "14"));
+ABSL_FLAG(bool, test_flag_with_non_const_help, true,
+          absl::StrCat("test ", "flag ", "non const help"));
 
 namespace {
 
 #if !ABSL_FLAGS_STRIP_HELP
 TEST_F(FlagTest, TestNonConstexprHelp) {
-  EXPECT_EQ(FLAGS_test_flag_14.Help(), "test flag 14");
+  EXPECT_EQ(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(),
+      "test flag non const help");
 }
 #endif  //! ABSL_FLAGS_STRIP_HELP
 
@@ -363,34 +718,39 @@
 
 }  // namespace
 
-ABSL_FLAG(CustomUDT, test_flag_15, CustomUDT(), "test flag 15");
+ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT");
 
 namespace {
 
 TEST_F(FlagTest, TestCustomUDT) {
-  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(1, 1));
-  absl::SetFlag(&FLAGS_test_flag_15, CustomUDT(2, 3));
-  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(2, 3));
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1));
+  absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3));
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3));
 }
 
 // MSVC produces link error on the type mismatch.
 // Linux does not have build errors and validations work as expected.
-#if 0  // !defined(_WIN32) && GTEST_HAS_DEATH_TEST
+#if !defined(_WIN32) && GTEST_HAS_DEATH_TEST
 
-TEST(Flagtest, TestTypeMismatchValidations) {
-  // For builtin types, GetFlag() only does validation in debug mode.
-  EXPECT_DEBUG_DEATH(
-      absl::GetFlag(FLAGS_mistyped_int_flag),
+using FlagDeathTest = FlagTest;
+
+TEST_F(FlagDeathTest, TestTypeMismatchValidations) {
+#if !defined(NDEBUG)
+  EXPECT_DEATH_IF_SUPPORTED(
+      static_cast<void>(absl::GetFlag(FLAGS_mistyped_int_flag)),
       "Flag 'mistyped_int_flag' is defined as one type and declared "
       "as another");
-  EXPECT_DEATH(absl::SetFlag(&FLAGS_mistyped_int_flag, 0),
-               "Flag 'mistyped_int_flag' is defined as one type and declared "
-               "as another");
+  EXPECT_DEATH_IF_SUPPORTED(
+      static_cast<void>(absl::GetFlag(FLAGS_mistyped_string_flag)),
+      "Flag 'mistyped_string_flag' is defined as one type and "
+      "declared as another");
+#endif
 
-  EXPECT_DEATH(absl::GetFlag(FLAGS_mistyped_string_flag),
-               "Flag 'mistyped_string_flag' is defined as one type and "
-               "declared as another");
-  EXPECT_DEATH(
+  EXPECT_DEATH_IF_SUPPORTED(
+      absl::SetFlag(&FLAGS_mistyped_int_flag, 1),
+      "Flag 'mistyped_int_flag' is defined as one type and declared "
+      "as another");
+  EXPECT_DEATH_IF_SUPPORTED(
       absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),
       "Flag 'mistyped_string_flag' is defined as one type and declared as "
       "another");
@@ -428,16 +788,17 @@
 
 // Flag default values can be specified with a value that converts to the flag
 // value type implicitly.
-ABSL_FLAG(ConversionTestVal, test_flag_16,
-          ConversionTestVal::ViaImplicitConv::kTen, "test flag 16");
+ABSL_FLAG(ConversionTestVal, test_flag_implicit_conv,
+          ConversionTestVal::ViaImplicitConv::kTen,
+          "test flag init via implicit conversion");
 
 namespace {
 
 TEST_F(FlagTest, CanSetViaImplicitConversion) {
-  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 10);
-  absl::SetFlag(&FLAGS_test_flag_16,
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10);
+  absl::SetFlag(&FLAGS_test_flag_implicit_conv,
                 ConversionTestVal::ViaImplicitConv::kEleven);
-  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 11);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11);
 }
 
 // --------------------------------------------------------------------
@@ -482,25 +843,103 @@
   EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25);
 }
 
-// --------------------------------------------------------------------
-
 }  // namespace
 
+// --------------------------------------------------------------------
+
 ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
 ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
 ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
 
+bool initializaion_order_fiasco_test = [] {
+  // Iterate over all the flags during static initialization.
+  // This should not trigger ASan's initialization-order-fiasco.
+  auto* handle1 = absl::FindCommandLineFlag("flag_on_separate_file");
+  auto* handle2 = absl::FindCommandLineFlag("retired_flag_on_separate_file");
+  if (handle1 != nullptr && handle2 != nullptr) {
+    return handle1->Name() == handle2->Name();
+  }
+  return true;
+}();
+
 namespace {
 
 TEST_F(FlagTest, TestRetiredFlagRegistration) {
-  bool is_bool = false;
-  EXPECT_TRUE(flags::IsRetiredFlag("old_bool_flag", &is_bool));
-  EXPECT_TRUE(is_bool);
-  EXPECT_TRUE(flags::IsRetiredFlag("old_int_flag", &is_bool));
-  EXPECT_FALSE(is_bool);
-  EXPECT_TRUE(flags::IsRetiredFlag("old_str_flag", &is_bool));
-  EXPECT_FALSE(is_bool);
-  EXPECT_FALSE(flags::IsRetiredFlag("some_other_flag", &is_bool));
+  auto* handle = absl::FindCommandLineFlag("old_bool_flag");
+  EXPECT_TRUE(handle->IsOfType<bool>());
+  EXPECT_TRUE(handle->IsRetired());
+  handle = absl::FindCommandLineFlag("old_int_flag");
+  EXPECT_TRUE(handle->IsOfType<int>());
+  EXPECT_TRUE(handle->IsRetired());
+  handle = absl::FindCommandLineFlag("old_str_flag");
+  EXPECT_TRUE(handle->IsOfType<std::string>());
+  EXPECT_TRUE(handle->IsRetired());
+}
+
+}  // namespace
+
+// --------------------------------------------------------------------
+
+namespace {
+
+// User-defined type with small alignment, but size exceeding 16.
+struct SmallAlignUDT {
+  SmallAlignUDT() : c('A'), s(12) {}
+  char c;
+  int16_t s;
+  char bytes[14];
+};
+
+bool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) {
+  return true;
+}
+std::string AbslUnparseFlag(const SmallAlignUDT&) { return ""; }
+
+// User-defined type with small size, but not trivially copyable.
+struct NonTriviallyCopyableUDT {
+  NonTriviallyCopyableUDT() : c('A') {}
+  NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {}
+  NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) {
+    c = rhs.c;
+    return *this;
+  }
+
+  char c;
+};
+
+bool AbslParseFlag(absl::string_view, NonTriviallyCopyableUDT*, std::string*) {
+  return true;
+}
+std::string AbslUnparseFlag(const NonTriviallyCopyableUDT&) { return ""; }
+
+}  // namespace
+
+ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, "help");
+ABSL_FLAG(NonTriviallyCopyableUDT, test_flag_ntc_udt, {}, "help");
+
+namespace {
+
+TEST_F(FlagTest, TestSmallAlignUDT) {
+  SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt);
+  EXPECT_EQ(value.c, 'A');
+  EXPECT_EQ(value.s, 12);
+
+  value.c = 'B';
+  value.s = 45;
+  absl::SetFlag(&FLAGS_test_flag_sa_udt, value);
+  value = absl::GetFlag(FLAGS_test_flag_sa_udt);
+  EXPECT_EQ(value.c, 'B');
+  EXPECT_EQ(value.s, 45);
+}
+
+TEST_F(FlagTest, TestNonTriviallyCopyableUDT) {
+  NonTriviallyCopyableUDT value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
+  EXPECT_EQ(value.c, 'A');
+
+  value.c = 'B';
+  absl::SetFlag(&FLAGS_test_flag_ntc_udt, value);
+  value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
+  EXPECT_EQ(value.c, 'B');
 }
 
 }  // namespace
diff --git a/absl/flags/flag_test_defs.cc b/absl/flags/flag_test_defs.cc
index 3366c58..4e1693c 100644
--- a/absl/flags/flag_test_defs.cc
+++ b/absl/flags/flag_test_defs.cc
@@ -20,3 +20,5 @@
 
 ABSL_FLAG(int, mistyped_int_flag, 0, "");
 ABSL_FLAG(std::string, mistyped_string_flag, "", "");
+ABSL_FLAG(bool, flag_on_separate_file, false, "");
+ABSL_RETIRED_FLAG(bool, retired_flag_on_separate_file, false, "");
diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc
index 53e2b84..4482955 100644
--- a/absl/flags/internal/commandlineflag.cc
+++ b/absl/flags/internal/commandlineflag.cc
@@ -1,5 +1,5 @@
 //
-// Copyright 2019 The Abseil Authors.
+// Copyright 2020 The Abseil Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -15,380 +15,12 @@
 
 #include "absl/flags/internal/commandlineflag.h"
 
-#include <cassert>
-
-#include "absl/base/internal/raw_logging.h"
-#include "absl/base/optimization.h"
-#include "absl/flags/config.h"
-#include "absl/flags/usage_config.h"
-#include "absl/strings/str_cat.h"
-#include "absl/synchronization/mutex.h"
-
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-// The help message indicating that the commandline flag has been
-// 'stripped'. It will not show up when doing "-help" and its
-// variants. The flag is stripped if ABSL_FLAGS_STRIP_HELP is set to 1
-// before including absl/flags/flag.h
-
-// This is used by this file, and also in commandlineflags_reporting.cc
-const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
-
-namespace {
-
-// Currently we only validate flag values for user-defined flag types.
-bool ShouldValidateFlagValue(const CommandLineFlag& flag) {
-#define DONT_VALIDATE(T) \
-  if (flag.IsOfType<T>()) return false;
-  ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(DONT_VALIDATE)
-  DONT_VALIDATE(std::string)
-  DONT_VALIDATE(std::vector<std::string>)
-#undef DONT_VALIDATE
-
-  return true;
-}
-
-}  // namespace
-
-absl::Mutex* InitFlag(CommandLineFlag* flag) {
-  ABSL_CONST_INIT static absl::Mutex init_lock(absl::kConstInit);
-  absl::Mutex* mu;
-
-  {
-    absl::MutexLock lock(&init_lock);
-
-    if (flag->locks_ == nullptr) {  // Must initialize Mutexes for this flag.
-      flag->locks_ = new flags_internal::CommandLineFlagLocks;
-    }
-
-    mu = &flag->locks_->primary_mu;
-  }
-
-  {
-    absl::MutexLock lock(mu);
-
-    if (!flag->IsRetired() && flag->def_ == nullptr) {
-      // Need to initialize def and cur fields.
-      flag->def_ = (*flag->make_init_value_)();
-      flag->cur_ = Clone(flag->op_, flag->def_);
-      UpdateCopy(flag);
-      flag->inited_.store(true, std::memory_order_release);
-      flag->InvokeCallback();
-    }
-  }
-
-  flag->inited_.store(true, std::memory_order_release);
-  return mu;
-}
-
-// Ensure that the lazily initialized fields of *flag have been initialized,
-// and return &flag->locks_->primary_mu.
-absl::Mutex* CommandLineFlag::InitFlagIfNecessary() const
-    ABSL_LOCK_RETURNED(locks_->primary_mu) {
-  if (!inited_.load(std::memory_order_acquire)) {
-    return InitFlag(const_cast<CommandLineFlag*>(this));
-  }
-
-  // All fields initialized; locks_ is therefore safe to read.
-  return &locks_->primary_mu;
-}
-
-bool CommandLineFlag::IsModified() const {
-  absl::MutexLock l(InitFlagIfNecessary());
-  return modified_;
-}
-
-void CommandLineFlag::SetModified(bool is_modified) {
-  absl::MutexLock l(InitFlagIfNecessary());
-  modified_ = is_modified;
-}
-
-bool CommandLineFlag::IsSpecifiedOnCommandLine() const {
-  absl::MutexLock l(InitFlagIfNecessary());
-  return on_command_line_;
-}
-
-absl::string_view CommandLineFlag::Typename() const {
-  // We do not store/report type in Abseil Flags, so that user do not rely on in
-  // at runtime
-  if (IsAbseilFlag() || IsRetired()) return "";
-
-#define HANDLE_V1_BUILTIN_TYPE(t) \
-  if (IsOfType<t>()) {            \
-    return #t;                    \
-  }
-
-  HANDLE_V1_BUILTIN_TYPE(bool);
-  HANDLE_V1_BUILTIN_TYPE(int32_t);
-  HANDLE_V1_BUILTIN_TYPE(int64_t);
-  HANDLE_V1_BUILTIN_TYPE(uint64_t);
-  HANDLE_V1_BUILTIN_TYPE(double);
-#undef HANDLE_V1_BUILTIN_TYPE
-
-  if (IsOfType<std::string>()) {
-    return "string";
-  }
-
-  return "";
-}
-
-std::string CommandLineFlag::Filename() const {
-  return flags_internal::GetUsageConfig().normalize_filename(filename_);
-}
-
-std::string CommandLineFlag::DefaultValue() const {
-  absl::MutexLock l(InitFlagIfNecessary());
-
-  return Unparse(marshalling_op_, def_);
-}
-
-std::string CommandLineFlag::CurrentValue() const {
-  absl::MutexLock l(InitFlagIfNecessary());
-
-  return Unparse(marshalling_op_, cur_);
-}
-
-// Attempts to parse supplied `value` string using parsing routine in the `flag`
-// argument. If parsing is successful, it will try to validate that the parsed
-// value is valid for the specified 'flag'. Finally this function stores the
-// parsed value in 'dst' assuming it is a pointer to the flag's value type. In
-// case if any error is encountered in either step, the error message is stored
-// in 'err'
-bool TryParseLocked(CommandLineFlag* flag, void* dst, absl::string_view value,
-                    std::string* err)
-    ABSL_EXCLUSIVE_LOCKS_REQUIRED(flag->locks_->primary_mu) {
-  void* tentative_value = Clone(flag->op_, flag->def_);
-  std::string parse_err;
-  if (!Parse(flag->marshalling_op_, value, tentative_value, &parse_err)) {
-    auto type_name = flag->Typename();
-    absl::string_view err_sep = parse_err.empty() ? "" : "; ";
-    absl::string_view typename_sep = type_name.empty() ? "" : " ";
-    *err = absl::StrCat("Illegal value '", value, "' specified for",
-                        typename_sep, type_name, " flag '", flag->Name(), "'",
-                        err_sep, parse_err);
-    Delete(flag->op_, tentative_value);
-    return false;
-  }
-
-  if (!flag->InvokeValidator(tentative_value)) {
-    *err = absl::StrCat("Failed validation of new value '",
-                        Unparse(flag->marshalling_op_, tentative_value),
-                        "' for flag '", flag->Name(), "'");
-    Delete(flag->op_, tentative_value);
-    return false;
-  }
-
-  flag->counter_++;
-  Copy(flag->op_, tentative_value, dst);
-  Delete(flag->op_, tentative_value);
-  return true;
-}
-
-// Sets the value of the flag based on specified string `value`. If the flag
-// was successfully set to new value, it returns true. Otherwise, sets `err`
-// to indicate the error, leaves the flag unchanged, and returns false. There
-// are three ways to set the flag's value:
-//  * Update the current flag value
-//  * Update the flag's default value
-//  * Update the current flag value if it was never set before
-// The mode is selected based on 'set_mode' parameter.
-bool CommandLineFlag::SetFromString(absl::string_view value,
-                                    FlagSettingMode set_mode,
-                                    ValueSource source, std::string* err) {
-  if (IsRetired()) return false;
-
-  absl::MutexLock l(InitFlagIfNecessary());
-
-  // Direct-access flags can be modified without going through the
-  // flag API. Detect such changes and update the flag->modified_ bit.
-  if (!IsAbseilFlag()) {
-    if (!modified_ && ChangedDirectly(this, cur_, def_)) {
-      modified_ = true;
-    }
-  }
-
-  switch (set_mode) {
-    case SET_FLAGS_VALUE: {
-      // set or modify the flag's value
-      if (!TryParseLocked(this, cur_, value, err)) return false;
-      modified_ = true;
-      UpdateCopy(this);
-      InvokeCallback();
-
-      if (source == kCommandLine) {
-        on_command_line_ = true;
-      }
-      break;
-    }
-    case SET_FLAG_IF_DEFAULT: {
-      // set the flag's value, but only if it hasn't been set by someone else
-      if (!modified_) {
-        if (!TryParseLocked(this, cur_, value, err)) return false;
-        modified_ = true;
-        UpdateCopy(this);
-        InvokeCallback();
-      } else {
-        // TODO(rogeeff): review and fix this semantic. Currently we do not fail
-        // in this case if flag is modified. This is misleading since the flag's
-        // value is not updated even though we return true.
-        // *err = absl::StrCat(Name(), " is already set to ",
-        //                     CurrentValue(), "\n");
-        // return false;
-        return true;
-      }
-      break;
-    }
-    case SET_FLAGS_DEFAULT: {
-      // modify the flag's default-value
-      if (!TryParseLocked(this, def_, value, err)) return false;
-
-      if (!modified_) {
-        // Need to set both defvalue *and* current, in this case
-        Copy(op_, def_, cur_);
-        UpdateCopy(this);
-        InvokeCallback();
-      }
-      break;
-    }
-    default: {
-      // unknown set_mode
-      assert(false);
-      return false;
-    }
-  }
-
-  return true;
-}
-
-void CommandLineFlag::CheckDefaultValueParsingRoundtrip() const {
-  std::string v = DefaultValue();
-
-  absl::MutexLock lock(InitFlagIfNecessary());
-
-  void* dst = Clone(op_, def_);
-  std::string error;
-  if (!flags_internal::Parse(marshalling_op_, v, dst, &error)) {
-    ABSL_INTERNAL_LOG(
-        FATAL,
-        absl::StrCat("Flag ", Name(), " (from ", Filename(),
-                     "): std::string form of default value '", v,
-                     "' could not be parsed; error=", error));
-  }
-
-  // We do not compare dst to def since parsing/unparsing may make
-  // small changes, e.g., precision loss for floating point types.
-  Delete(op_, dst);
-}
-
-bool CommandLineFlag::ValidateDefaultValue() const {
-  absl::MutexLock lock(InitFlagIfNecessary());
-  return InvokeValidator(def_);
-}
-
-bool CommandLineFlag::ValidateInputValue(absl::string_view value) const {
-  absl::MutexLock l(InitFlagIfNecessary());  // protect default value access
-
-  void* obj = Clone(op_, def_);
-  std::string ignored_error;
-  const bool result =
-      flags_internal::Parse(marshalling_op_, value, obj, &ignored_error) &&
-      InvokeValidator(obj);
-  Delete(op_, obj);
-  return result;
-}
-
-void CommandLineFlag::Read(void* dst,
-                           const flags_internal::FlagOpFn dst_op) const {
-  absl::ReaderMutexLock l(InitFlagIfNecessary());
-
-  // `dst_op` is the unmarshaling operation corresponding to the declaration
-  // visibile at the call site. `op` is the Flag's defined unmarshalling
-  // operation. They must match for this operation to be well-defined.
-  if (ABSL_PREDICT_FALSE(dst_op != op_)) {
-    ABSL_INTERNAL_LOG(
-        ERROR,
-        absl::StrCat("Flag '", Name(),
-                     "' is defined as one type and declared as another"));
-  }
-  CopyConstruct(op_, cur_, dst);
-}
-
-void CommandLineFlag::Write(const void* src,
-                            const flags_internal::FlagOpFn src_op) {
-  absl::MutexLock l(InitFlagIfNecessary());
-
-  // `src_op` is the marshalling operation corresponding to the declaration
-  // visible at the call site. `op` is the Flag's defined marshalling operation.
-  // They must match for this operation to be well-defined.
-  if (ABSL_PREDICT_FALSE(src_op != op_)) {
-    ABSL_INTERNAL_LOG(
-        ERROR,
-        absl::StrCat("Flag '", Name(),
-                     "' is defined as one type and declared as another"));
-  }
-
-  if (ShouldValidateFlagValue(*this)) {
-    void* obj = Clone(op_, src);
-    std::string ignored_error;
-    std::string src_as_str = Unparse(marshalling_op_, src);
-    if (!Parse(marshalling_op_, src_as_str, obj, &ignored_error) ||
-        !InvokeValidator(obj)) {
-      ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(),
-                                            "' to invalid value ", src_as_str));
-    }
-    Delete(op_, obj);
-  }
-
-  modified_ = true;
-  counter_++;
-  Copy(op_, src, cur_);
-
-  UpdateCopy(this);
-  InvokeCallback();
-}
-
-std::string HelpText::GetHelpText() const {
-  if (help_function_) return help_function_();
-  if (help_message_) return help_message_;
-
-  return {};
-}
-
-// Update any copy of the flag value that is stored in an atomic word.
-// In addition if flag has a mutation callback this function invokes it.
-void UpdateCopy(CommandLineFlag* flag) {
-#define STORE_ATOMIC(T)           \
-  else if (flag->IsOfType<T>()) { \
-    flag->StoreAtomic();          \
-  }
-
-  if (false) {
-  }
-  ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(STORE_ATOMIC)
-#undef STORE_ATOMIC
-}
-
-// Return true iff flag value was changed via direct-access.
-bool ChangedDirectly(CommandLineFlag* flag, const void* a, const void* b) {
-  if (!flag->IsAbseilFlag()) {
-// Need to compare values for direct-access flags.
-#define CHANGED_FOR_TYPE(T)                                                  \
-  if (flag->IsOfType<T>()) {                                                 \
-    return *reinterpret_cast<const T*>(a) != *reinterpret_cast<const T*>(b); \
-  }
-
-    CHANGED_FOR_TYPE(bool);
-    CHANGED_FOR_TYPE(int32_t);
-    CHANGED_FOR_TYPE(int64_t);
-    CHANGED_FOR_TYPE(uint64_t);
-    CHANGED_FOR_TYPE(double);
-    CHANGED_FOR_TYPE(std::string);
-#undef CHANGED_FOR_TYPE
-  }
-
-  return false;
-}
+FlagStateInterface::~FlagStateInterface() {}
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h
index 284286b..ebfe81b 100644
--- a/absl/flags/internal/commandlineflag.h
+++ b/absl/flags/internal/commandlineflag.h
@@ -16,29 +16,19 @@
 #ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
 #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
 
-#include <atomic>
-
-#include "absl/base/macros.h"
-#include "absl/flags/marshalling.h"
-#include "absl/synchronization/mutex.h"
-#include "absl/types/optional.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-// Type-specific operations, eg., parsing, copying, etc. are provided
-// by function specific to that type with a signature matching FlagOpFn.
-enum FlagOp {
-  kDelete,
-  kClone,
-  kCopy,
-  kCopyConstruct,
-  kSizeof,
-  kParse,
-  kUnparse
-};
-using FlagOpFn = void* (*)(FlagOp, const void*, void*);
-using FlagMarshallingOpFn = void* (*)(FlagOp, const void*, void*, void*);
+// An alias for flag fast type id. This value identifies the flag value type
+// similarly to typeid(T), without relying on RTTI being available. In most
+// cases this id is enough to uniquely identify the flag's value type. In a few
+// cases we'll have to resort to using actual RTTI implementation if it is
+// available.
+using FlagFastTypeId = absl::base_internal::FastTypeIdType;
 
 // Options that control SetCommandLineOptionWithMode.
 enum FlagSettingMode {
@@ -53,7 +43,7 @@
   SET_FLAGS_DEFAULT
 };
 
-// Options that control SetFromString: Source of a value.
+// Options that control ParseFrom: Source of a value.
 enum ValueSource {
   // Flag is being set by value specified on a command line.
   kCommandLine,
@@ -61,309 +51,18 @@
   kProgrammaticChange,
 };
 
-// Signature for the help generation function used as an argument for the
-// absl::Flag constructor.
-using HelpGenFunc = std::string (*)();
-
-// Signature for the function generating the initial flag value based (usually
-// based on default value supplied in flag's definition)
-using InitialValGenFunc = void* (*)();
-
-extern const char kStrippedFlagHelp[];
-
-// The per-type function
-template <typename T>
-void* FlagOps(FlagOp op, const void* v1, void* v2) {
-  switch (op) {
-    case kDelete:
-      delete static_cast<const T*>(v1);
-      return nullptr;
-    case kClone:
-      return new T(*static_cast<const T*>(v1));
-    case kCopy:
-      *static_cast<T*>(v2) = *static_cast<const T*>(v1);
-      return nullptr;
-    case kCopyConstruct:
-      new (v2) T(*static_cast<const T*>(v1));
-      return nullptr;
-    case kSizeof:
-      return reinterpret_cast<void*>(sizeof(T));
-    default:
-      return nullptr;
-  }
-}
-
-template <typename T>
-void* FlagMarshallingOps(FlagOp op, const void* v1, void* v2, void* v3) {
-  switch (op) {
-    case kParse: {
-      // initialize the temporary instance of type T based on current value in
-      // destination (which is going to be flag's default value).
-      T temp(*static_cast<T*>(v2));
-      if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp,
-                              static_cast<std::string*>(v3))) {
-        return nullptr;
-      }
-      *static_cast<T*>(v2) = std::move(temp);
-      return v2;
-    }
-    case kUnparse:
-      *static_cast<std::string*>(v2) =
-          absl::UnparseFlag<T>(*static_cast<const T*>(v1));
-      return nullptr;
-    default:
-      return nullptr;
-  }
-}
-
-// Functions that invoke flag-type-specific operations.
-inline void Delete(FlagOpFn op, const void* obj) {
-  op(flags_internal::kDelete, obj, nullptr);
-}
-
-inline void* Clone(FlagOpFn op, const void* obj) {
-  return op(flags_internal::kClone, obj, nullptr);
-}
-
-inline void Copy(FlagOpFn op, const void* src, void* dst) {
-  op(flags_internal::kCopy, src, dst);
-}
-
-inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
-  op(flags_internal::kCopyConstruct, src, dst);
-}
-
-inline bool Parse(FlagMarshallingOpFn op, absl::string_view text, void* dst,
-                  std::string* error) {
-  return op(flags_internal::kParse, &text, dst, error) != nullptr;
-}
-
-inline std::string Unparse(FlagMarshallingOpFn op, const void* val) {
-  std::string result;
-  op(flags_internal::kUnparse, val, &result, nullptr);
-  return result;
-}
-
-inline size_t Sizeof(FlagOpFn op) {
-  // This sequence of casts reverses the sequence from base::internal::FlagOps()
-  return static_cast<size_t>(reinterpret_cast<intptr_t>(
-      op(flags_internal::kSizeof, nullptr, nullptr)));
-}
-
-// The following struct contains the locks in a CommandLineFlag struct.
-// They are in a separate struct that is lazily allocated to avoid problems
-// with static initialization and to avoid multiple allocations.
-struct CommandLineFlagLocks {
-  absl::Mutex primary_mu;   // protects several fields in CommandLineFlag
-  absl::Mutex callback_mu;  // used to serialize callbacks
-};
-
-// Holds either a pointer to help text or a function which produces it.  This is
-// needed for supporting both static initialization of Flags while supporting
-// the legacy registration framework.  We can't use absl::variant<const char*,
-// const char*(*)()> since anybody passing 0 or nullptr in to a CommandLineFlag
-// would find an ambiguity.
-class HelpText {
+// Handle to FlagState objects. Specific flag state objects will restore state
+// of a flag produced this flag state from method CommandLineFlag::SaveState().
+class FlagStateInterface {
  public:
-  static constexpr HelpText FromFunctionPointer(const HelpGenFunc fn) {
-    return HelpText(fn, nullptr);
-  }
-  static constexpr HelpText FromStaticCString(const char* msg) {
-    return HelpText(nullptr, msg);
-  }
+  virtual ~FlagStateInterface();
 
-  std::string GetHelpText() const;
-
-  HelpText() = delete;
-  HelpText(const HelpText&) = default;
-  HelpText(HelpText&&) = default;
-
- private:
-  explicit constexpr HelpText(const HelpGenFunc fn, const char* msg)
-      : help_function_(fn), help_message_(msg) {}
-
-  HelpGenFunc help_function_;
-  const char* help_message_;
+  // Restores the flag originated this object to the saved state.
+  virtual void Restore() const = 0;
 };
 
-// Holds all information for a flag.
-class CommandLineFlag {
- public:
-  constexpr CommandLineFlag(
-      const char* name, HelpText help_text, const char* filename,
-      const flags_internal::FlagOpFn op,
-      const flags_internal::FlagMarshallingOpFn marshalling_op,
-      const flags_internal::InitialValGenFunc initial_value_gen, void* def,
-      void* cur)
-      : name_(name),
-        help_(help_text),
-        filename_(filename),
-        op_(op),
-        marshalling_op_(marshalling_op),
-        make_init_value_(initial_value_gen),
-        inited_(false),
-        modified_(false),
-        on_command_line_(false),
-        def_(def),
-        cur_(cur),
-        counter_(0),
-        locks_(nullptr) {}
-
-  // Virtual destructor
-  virtual void Destroy() const = 0;
-
-  // Not copyable/assignable.
-  CommandLineFlag(const CommandLineFlag&) = delete;
-  CommandLineFlag& operator=(const CommandLineFlag&) = delete;
-
-  // Access methods.
-
-  // Returns true iff this object corresponds to retired flag
-  virtual bool IsRetired() const { return false; }
-  // Returns true iff this is a handle to an Abseil Flag.
-  virtual bool IsAbseilFlag() const { return true; }
-
-  absl::string_view Name() const { return name_; }
-  std::string Help() const { return help_.GetHelpText(); }
-  bool IsModified() const;
-  void SetModified(bool is_modified);
-  bool IsSpecifiedOnCommandLine() const;
-
-  absl::string_view Typename() const;
-  std::string Filename() const;
-  std::string DefaultValue() const;
-  std::string CurrentValue() const;
-
-  // Interface to store the value in atomic if one used. This is short term
-  // interface. To be reworked once cur_ is moved.
-  virtual void StoreAtomic() {}
-
-  // Interfaces to operate on validators.
-  virtual bool HasValidatorFn() const { return false; }
-  virtual bool InvokeValidator(const void* /*value*/) const { return true; }
-  // Invoke the flag validators for old flags.
-  // TODO(rogeeff): implement proper validators for Abseil Flags
-  bool ValidateDefaultValue() const;
-  bool ValidateInputValue(absl::string_view value) const;
-
-  // Return true iff flag has type T.
-  template <typename T>
-  inline bool IsOfType() const {
-    return op_ == &flags_internal::FlagOps<T>;
-  }
-
-  // Attempts to retrieve the flag value. Returns value on success,
-  // absl::nullopt otherwise.
-  template <typename T>
-  absl::optional<T> Get() const {
-    if (IsRetired() || flags_internal::FlagOps<T> != op_) return absl::nullopt;
-
-    T res;
-    Read(&res, flags_internal::FlagOps<T>);
-
-    return res;
-  }
-
-  // Interfaces to overate on callbacks.
-  virtual void InvokeCallback() {}
-
-  // Sets the value of the flag based on specified std::string `value`. If the flag
-  // was successfully set to new value, it returns true. Otherwise, sets `error`
-  // to indicate the error, leaves the flag unchanged, and returns false. There
-  // are three ways to set the flag's value:
-  //  * Update the current flag value
-  //  * Update the flag's default value
-  //  * Update the current flag value if it was never set before
-  // The mode is selected based on `set_mode` parameter.
-  bool SetFromString(absl::string_view value,
-                     flags_internal::FlagSettingMode set_mode,
-                     flags_internal::ValueSource source, std::string* error);
-
-  void CheckDefaultValueParsingRoundtrip() const;
-
-  // Constant configuration for a particular flag.
- protected:
-  ~CommandLineFlag() = default;
-
-  const char* const name_;
-  const HelpText help_;
-  const char* const filename_;
-
-  const FlagOpFn op_;                         // Type-specific handler
-  const FlagMarshallingOpFn marshalling_op_;  // Marshalling ops handler
-  const InitialValGenFunc make_init_value_;  // Makes initial value for the flag
-  std::atomic<bool> inited_;  // fields have been lazily initialized
-
-  // Mutable state (guarded by locks_->primary_mu).
-  bool modified_;         // Has flag value been modified?
-  bool on_command_line_;  // Specified on command line.
-  void* def_;             // Lazily initialized pointer to default value
-  void* cur_;             // Lazily initialized pointer to current value
-  int64_t counter_;         // Mutation counter
-
-  // Lazily initialized mutexes for this flag value.  We cannot inline a
-  // SpinLock or Mutex here because those have non-constexpr constructors and
-  // so would prevent constant initialization of this type.
-  // TODO(rogeeff): fix it once Mutex has constexpr constructor
-  struct CommandLineFlagLocks* locks_;  // locks, laziliy allocated.
-
-  // Ensure that the lazily initialized fields of *flag have been initialized,
-  // and return the lock which should be locked when flag's state is mutated.
-  absl::Mutex* InitFlagIfNecessary() const ABSL_LOCK_RETURNED(locks_->primary_mu);
-
-  // copy construct new value of flag's type in a memory referenced by dst
-  // based on current flag's value
-  void Read(void* dst, const flags_internal::FlagOpFn dst_op) const;
-  // updates flag's value to *src (locked)
-  void Write(const void* src, const flags_internal::FlagOpFn src_op);
-
-  friend class FlagRegistry;
-  friend class FlagPtrMap;
-  friend class FlagSaverImpl;
-  friend bool TryParseLocked(CommandLineFlag* flag, void* dst,
-                             absl::string_view value, std::string* err);
-  friend absl::Mutex* InitFlag(CommandLineFlag* flag);
-
-  // This is a short term, until we completely rework persistent state
-  // storage API.
-  virtual void* GetValidator() const { return nullptr; }
-  virtual bool SetValidator(void*) { return false; }
-};
-
-// Update any copy of the flag value that is stored in an atomic word.
-// In addition if flag has a mutation callback this function invokes it. While
-// callback is being invoked the primary flag's mutex is unlocked and it is
-// re-locked back after call to callback is completed. Callback invocation is
-// guarded by flag's secondary mutex instead which prevents concurrent callback
-// invocation. Note that it is possible for other thread to grab the primary
-// lock and update flag's value at any time during the callback invocation.
-// This is by design. Callback can get a value of the flag if necessary, but it
-// might be different from the value initiated the callback and it also can be
-// different by the time the callback invocation is completed.
-// Requires that *primary_lock be held in exclusive mode; it may be released
-// and reacquired by the implementation.
-void UpdateCopy(CommandLineFlag* flag);
-// Return true iff flag value was changed via direct-access.
-bool ChangedDirectly(CommandLineFlag* flag, const void* a, const void* b);
-
-// This macro is the "source of truth" for the list of supported flag types we
-// expect to perform lock free operations on. Specifically it generates code,
-// a one argument macro operating on a type, supplied as a macro argument, for
-// each type in the list.
-#define ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(A) \
-  A(bool)                                         \
-  A(short)                                        \
-  A(unsigned short)                               \
-  A(int)                                          \
-  A(unsigned int)                                 \
-  A(long)                                         \
-  A(unsigned long)                                \
-  A(long long)                                    \
-  A(unsigned long long)                           \
-  A(double)                                       \
-  A(float)
-
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
diff --git a/absl/flags/internal/commandlineflag_test.cc b/absl/flags/internal/commandlineflag_test.cc
deleted file mode 100644
index 5a0c271..0000000
--- a/absl/flags/internal/commandlineflag_test.cc
+++ /dev/null
@@ -1,218 +0,0 @@
-//
-//  Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/flags/internal/commandlineflag.h"
-
-#include <algorithm>
-#include <string>
-
-#include "gtest/gtest.h"
-#include "absl/flags/flag.h"
-#include "absl/flags/internal/registry.h"
-#include "absl/flags/usage_config.h"
-#include "absl/memory/memory.h"
-#include "absl/strings/match.h"
-#include "absl/strings/str_cat.h"
-
-ABSL_FLAG(int, int_flag, 201, "int_flag help");
-ABSL_FLAG(std::string, string_flag, "dflt",
-          absl::StrCat("string_flag", " help"));
-ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
-
-namespace {
-
-namespace flags = absl::flags_internal;
-
-class CommandLineFlagTest : public testing::Test {
- protected:
-  static void SetUpTestSuite() {
-    // Install a function to normalize filenames before this test is run.
-    absl::FlagsUsageConfig default_config;
-    default_config.normalize_filename = &CommandLineFlagTest::NormalizeFileName;
-    absl::SetFlagsUsageConfig(default_config);
-  }
-
-  void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); }
-  void TearDown() override { flag_saver_.reset(); }
-
- private:
-  static std::string NormalizeFileName(absl::string_view fname) {
-#ifdef _WIN32
-    std::string normalized(fname);
-    std::replace(normalized.begin(), normalized.end(), '\\', '/');
-    fname = normalized;
-#endif
-    return std::string(fname);
-  }
-
-  std::unique_ptr<flags::FlagSaver> flag_saver_;
-};
-
-TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
-
-  ASSERT_TRUE(flag_01);
-  EXPECT_EQ(flag_01->Name(), "int_flag");
-  EXPECT_EQ(flag_01->Help(), "int_flag help");
-  EXPECT_EQ(flag_01->Typename(), "");
-  EXPECT_TRUE(!flag_01->IsRetired());
-  EXPECT_TRUE(flag_01->IsOfType<int>());
-  EXPECT_TRUE(
-      absl::EndsWith(flag_01->Filename(),
-                     "absl/flags/internal/commandlineflag_test.cc"))
-      << flag_01->Filename();
-
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
-
-  ASSERT_TRUE(flag_02);
-  EXPECT_EQ(flag_02->Name(), "string_flag");
-  EXPECT_EQ(flag_02->Help(), "string_flag help");
-  EXPECT_EQ(flag_02->Typename(), "");
-  EXPECT_TRUE(!flag_02->IsRetired());
-  EXPECT_TRUE(flag_02->IsOfType<std::string>());
-  EXPECT_TRUE(
-      absl::EndsWith(flag_02->Filename(),
-                     "absl/flags/internal/commandlineflag_test.cc"))
-      << flag_02->Filename();
-
-  auto* flag_03 = flags::FindRetiredFlag("bool_retired_flag");
-
-  ASSERT_TRUE(flag_03);
-  EXPECT_EQ(flag_03->Name(), "bool_retired_flag");
-  EXPECT_EQ(flag_03->Help(), "");
-  EXPECT_EQ(flag_03->Typename(), "");
-  EXPECT_TRUE(flag_03->IsRetired());
-  EXPECT_TRUE(flag_03->IsOfType<bool>());
-  EXPECT_EQ(flag_03->Filename(), "RETIRED");
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
-  absl::SetFlag(&FLAGS_int_flag, 301);
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
-
-  ASSERT_TRUE(flag_01);
-  EXPECT_EQ(flag_01->CurrentValue(), "301");
-  EXPECT_EQ(flag_01->DefaultValue(), "201");
-
-  absl::SetFlag(&FLAGS_string_flag, "new_str_value");
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
-
-  ASSERT_TRUE(flag_02);
-  EXPECT_EQ(flag_02->CurrentValue(), "new_str_value");
-  EXPECT_EQ(flag_02->DefaultValue(), "dflt");
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(CommandLineFlagTest, TestSetFromStringCurrentValue) {
-  std::string err;
-
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(flag_01->SetFromString("11", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(flag_01->SetFromString("-123", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(!flag_01->SetFromString("xyz", flags::SET_FLAGS_VALUE,
-                                      flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
-  EXPECT_EQ(err, "Illegal value 'xyz' specified for flag 'int_flag'");
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(!flag_01->SetFromString("A1", flags::SET_FLAGS_VALUE,
-                                      flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
-  EXPECT_EQ(err, "Illegal value 'A1' specified for flag 'int_flag'");
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(flag_01->SetFromString("0x10", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(flag_01->SetFromString("011", flags::SET_FLAGS_VALUE,
-                                     flags::kCommandLine, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
-  EXPECT_TRUE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(!flag_01->SetFromString("", flags::SET_FLAGS_VALUE,
-                                      flags::kProgrammaticChange, &err));
-  EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'");
-
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
-  EXPECT_TRUE(flag_02->SetFromString("xyz", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz");
-
-  EXPECT_TRUE(flag_02->SetFromString("", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(CommandLineFlagTest, TestSetFromStringDefaultValue) {
-  std::string err;
-
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
-
-  EXPECT_TRUE(flag_01->SetFromString("111", flags::SET_FLAGS_DEFAULT,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(flag_01->DefaultValue(), "111");
-
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
-
-  EXPECT_TRUE(flag_02->SetFromString("abc", flags::SET_FLAGS_DEFAULT,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(flag_02->DefaultValue(), "abc");
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(CommandLineFlagTest, TestSetFromStringIfDefault) {
-  std::string err;
-
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
-
-  EXPECT_TRUE(flag_01->SetFromString("22", flags::SET_FLAG_IF_DEFAULT,
-                                     flags::kProgrammaticChange, &err))
-      << err;
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
-
-  EXPECT_TRUE(flag_01->SetFromString("33", flags::SET_FLAG_IF_DEFAULT,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
-  // EXPECT_EQ(err, "ERROR: int_flag is already set to 22");
-
-  // Reset back to default value
-  EXPECT_TRUE(flag_01->SetFromString("201", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-
-  EXPECT_TRUE(flag_01->SetFromString("33", flags::SET_FLAG_IF_DEFAULT,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201);
-  // EXPECT_EQ(err, "ERROR: int_flag is already set to 201");
-}
-
-}  // namespace
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc
index 0f40358..f83c1fe 100644
--- a/absl/flags/internal/flag.cc
+++ b/absl/flags/internal/flag.cc
@@ -15,37 +15,567 @@
 
 #include "absl/flags/internal/flag.h"
 
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <array>
+#include <atomic>
+#include <memory>
+#include <new>
+#include <string>
+#include <typeinfo>
+
+#include "absl/base/call_once.h"
+#include "absl/base/casts.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/flags/config.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/usage_config.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-// If the flag has a mutation callback this function invokes it. While the
-// callback is being invoked the primary flag's mutex is unlocked and it is
-// re-locked back after call to callback is completed. Callback invocation is
-// guarded by flag's secondary mutex instead which prevents concurrent
-// callback invocation. Note that it is possible for other thread to grab the
-// primary lock and update flag's value at any time during the callback
-// invocation. This is by design. Callback can get a value of the flag if
-// necessary, but it might be different from the value initiated the callback
-// and it also can be different by the time the callback invocation is
-// completed. Requires that *primary_lock be held in exclusive mode; it may be
-// released and reacquired by the implementation.
-void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu,
-                    FlagCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(primary_mu) {
-  if (!cb) return;
+// The help message indicating that the commandline flag has been
+// 'stripped'. It will not show up when doing "-help" and its
+// variants. The flag is stripped if ABSL_FLAGS_STRIP_HELP is set to 1
+// before including absl/flags/flag.h
+const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
 
-  // When executing the callback we need the primary flag's mutex to be
-  // unlocked so that callback can retrieve the flag's value.
-  primary_mu->Unlock();
+namespace {
 
-  {
-    absl::MutexLock lock(callback_mu);
-    cb();
+// Currently we only validate flag values for user-defined flag types.
+bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {
+#define DONT_VALIDATE(T, _) \
+  if (flag_type_id == base_internal::FastTypeId<T>()) return false;
+  ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(DONT_VALIDATE)
+#undef DONT_VALIDATE
+
+  return true;
+}
+
+// RAII helper used to temporarily unlock and relock `absl::Mutex`.
+// This is used when we need to ensure that locks are released while
+// invoking user supplied callbacks and then reacquired, since callbacks may
+// need to acquire these locks themselves.
+class MutexRelock {
+ public:
+  explicit MutexRelock(absl::Mutex& mu) : mu_(mu) { mu_.Unlock(); }
+  ~MutexRelock() { mu_.Lock(); }
+
+  MutexRelock(const MutexRelock&) = delete;
+  MutexRelock& operator=(const MutexRelock&) = delete;
+
+ private:
+  absl::Mutex& mu_;
+};
+
+}  // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// Persistent state of the flag data.
+
+class FlagImpl;
+
+class FlagState : public flags_internal::FlagStateInterface {
+ public:
+  template <typename V>
+  FlagState(FlagImpl& flag_impl, const V& v, bool modified,
+            bool on_command_line, int64_t counter)
+      : flag_impl_(flag_impl),
+        value_(v),
+        modified_(modified),
+        on_command_line_(on_command_line),
+        counter_(counter) {}
+
+  ~FlagState() override {
+    if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer &&
+        flag_impl_.ValueStorageKind() != FlagValueStorageKind::kSequenceLocked)
+      return;
+    flags_internal::Delete(flag_impl_.op_, value_.heap_allocated);
   }
 
-  primary_mu->Lock();
+ private:
+  friend class FlagImpl;
+
+  // Restores the flag to the saved state.
+  void Restore() const override {
+    if (!flag_impl_.RestoreState(*this)) return;
+
+    ABSL_INTERNAL_LOG(INFO,
+                      absl::StrCat("Restore saved value of ", flag_impl_.Name(),
+                                   " to: ", flag_impl_.CurrentValue()));
+  }
+
+  // Flag and saved flag data.
+  FlagImpl& flag_impl_;
+  union SavedValue {
+    explicit SavedValue(void* v) : heap_allocated(v) {}
+    explicit SavedValue(int64_t v) : one_word(v) {}
+
+    void* heap_allocated;
+    int64_t one_word;
+  } value_;
+  bool modified_;
+  bool on_command_line_;
+  int64_t counter_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag implementation, which does not depend on flag value type.
+
+DynValueDeleter::DynValueDeleter(FlagOpFn op_arg) : op(op_arg) {}
+
+void DynValueDeleter::operator()(void* ptr) const {
+  if (op == nullptr) return;
+
+  Delete(op, ptr);
+}
+
+void FlagImpl::Init() {
+  new (&data_guard_) absl::Mutex;
+
+  auto def_kind = static_cast<FlagDefaultKind>(def_kind_);
+
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer:
+      // For this storage kind the default_value_ always points to gen_func
+      // during initialization.
+      assert(def_kind == FlagDefaultKind::kGenFunc);
+      (*default_value_.gen_func)(AlignedBufferValue());
+      break;
+    case FlagValueStorageKind::kOneWordAtomic: {
+      alignas(int64_t) std::array<char, sizeof(int64_t)> buf{};
+      if (def_kind == FlagDefaultKind::kGenFunc) {
+        (*default_value_.gen_func)(buf.data());
+      } else {
+        assert(def_kind != FlagDefaultKind::kDynamicValue);
+        std::memcpy(buf.data(), &default_value_, Sizeof(op_));
+      }
+      OneWordValue().store(absl::bit_cast<int64_t>(buf),
+                           std::memory_order_release);
+      break;
+    }
+    case FlagValueStorageKind::kSequenceLocked: {
+      // For this storage kind the default_value_ always points to gen_func
+      // during initialization.
+      assert(def_kind == FlagDefaultKind::kGenFunc);
+      (*default_value_.gen_func)(AtomicBufferValue());
+      break;
+    }
+  }
+  seq_lock_.MarkInitialized();
+}
+
+absl::Mutex* FlagImpl::DataGuard() const {
+  absl::call_once(const_cast<FlagImpl*>(this)->init_control_, &FlagImpl::Init,
+                  const_cast<FlagImpl*>(this));
+
+  // data_guard_ is initialized inside Init.
+  return reinterpret_cast<absl::Mutex*>(&data_guard_);
+}
+
+void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id,
+                               const std::type_info* (*gen_rtti)()) const {
+  FlagFastTypeId lhs_type_id = flags_internal::FastTypeId(op_);
+
+  // `rhs_type_id` is the fast type id corresponding to the declaration
+  // visibile at the call site. `lhs_type_id` is the fast type id
+  // corresponding to the type specified in flag definition. They must match
+  //  for this operation to be well-defined.
+  if (ABSL_PREDICT_TRUE(lhs_type_id == rhs_type_id)) return;
+
+  const std::type_info* lhs_runtime_type_id =
+      flags_internal::RuntimeTypeId(op_);
+  const std::type_info* rhs_runtime_type_id = (*gen_rtti)();
+
+  if (lhs_runtime_type_id == rhs_runtime_type_id) return;
+
+#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI)
+  if (*lhs_runtime_type_id == *rhs_runtime_type_id) return;
+#endif
+
+  ABSL_INTERNAL_LOG(
+      FATAL, absl::StrCat("Flag '", Name(),
+                          "' is defined as one type and declared as another"));
+}
+
+std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const {
+  void* res = nullptr;
+  switch (DefaultKind()) {
+    case FlagDefaultKind::kDynamicValue:
+      res = flags_internal::Clone(op_, default_value_.dynamic_value);
+      break;
+    case FlagDefaultKind::kGenFunc:
+      res = flags_internal::Alloc(op_);
+      (*default_value_.gen_func)(res);
+      break;
+    default:
+      res = flags_internal::Clone(op_, &default_value_);
+      break;
+  }
+  return {res, DynValueDeleter{op_}};
+}
+
+void FlagImpl::StoreValue(const void* src) {
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer:
+      Copy(op_, src, AlignedBufferValue());
+      seq_lock_.IncrementModificationCount();
+      break;
+    case FlagValueStorageKind::kOneWordAtomic: {
+      int64_t one_word_val = 0;
+      std::memcpy(&one_word_val, src, Sizeof(op_));
+      OneWordValue().store(one_word_val, std::memory_order_release);
+      seq_lock_.IncrementModificationCount();
+      break;
+    }
+    case FlagValueStorageKind::kSequenceLocked: {
+      seq_lock_.Write(AtomicBufferValue(), src, Sizeof(op_));
+      break;
+    }
+  }
+  modified_ = true;
+  InvokeCallback();
+}
+
+absl::string_view FlagImpl::Name() const { return name_; }
+
+std::string FlagImpl::Filename() const {
+  return flags_internal::GetUsageConfig().normalize_filename(filename_);
+}
+
+std::string FlagImpl::Help() const {
+  return HelpSourceKind() == FlagHelpKind::kLiteral ? help_.literal
+                                                    : help_.gen_func();
+}
+
+FlagFastTypeId FlagImpl::TypeId() const {
+  return flags_internal::FastTypeId(op_);
+}
+
+int64_t FlagImpl::ModificationCount() const {
+  return seq_lock_.ModificationCount();
+}
+
+bool FlagImpl::IsSpecifiedOnCommandLine() const {
+  absl::MutexLock l(DataGuard());
+  return on_command_line_;
+}
+
+std::string FlagImpl::DefaultValue() const {
+  absl::MutexLock l(DataGuard());
+
+  auto obj = MakeInitValue();
+  return flags_internal::Unparse(op_, obj.get());
+}
+
+std::string FlagImpl::CurrentValue() const {
+  auto* guard = DataGuard();  // Make sure flag initialized
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer: {
+      absl::MutexLock l(guard);
+      return flags_internal::Unparse(op_, AlignedBufferValue());
+    }
+    case FlagValueStorageKind::kOneWordAtomic: {
+      const auto one_word_val =
+          absl::bit_cast<std::array<char, sizeof(int64_t)>>(
+              OneWordValue().load(std::memory_order_acquire));
+      return flags_internal::Unparse(op_, one_word_val.data());
+    }
+    case FlagValueStorageKind::kSequenceLocked: {
+      std::unique_ptr<void, DynValueDeleter> cloned(flags_internal::Alloc(op_),
+                                                    DynValueDeleter{op_});
+      ReadSequenceLockedData(cloned.get());
+      return flags_internal::Unparse(op_, cloned.get());
+    }
+  }
+
+  return "";
+}
+
+void FlagImpl::SetCallback(const FlagCallbackFunc mutation_callback) {
+  absl::MutexLock l(DataGuard());
+
+  if (callback_ == nullptr) {
+    callback_ = new FlagCallback;
+  }
+  callback_->func = mutation_callback;
+
+  InvokeCallback();
+}
+
+void FlagImpl::InvokeCallback() const {
+  if (!callback_) return;
+
+  // Make a copy of the C-style function pointer that we are about to invoke
+  // before we release the lock guarding it.
+  FlagCallbackFunc cb = callback_->func;
+
+  // If the flag has a mutation callback this function invokes it. While the
+  // callback is being invoked the primary flag's mutex is unlocked and it is
+  // re-locked back after call to callback is completed. Callback invocation is
+  // guarded by flag's secondary mutex instead which prevents concurrent
+  // callback invocation. Note that it is possible for other thread to grab the
+  // primary lock and update flag's value at any time during the callback
+  // invocation. This is by design. Callback can get a value of the flag if
+  // necessary, but it might be different from the value initiated the callback
+  // and it also can be different by the time the callback invocation is
+  // completed. Requires that *primary_lock be held in exclusive mode; it may be
+  // released and reacquired by the implementation.
+  MutexRelock relock(*DataGuard());
+  absl::MutexLock lock(&callback_->guard);
+  cb();
+}
+
+std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {
+  absl::MutexLock l(DataGuard());
+
+  bool modified = modified_;
+  bool on_command_line = on_command_line_;
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer: {
+      return absl::make_unique<FlagState>(
+          *this, flags_internal::Clone(op_, AlignedBufferValue()), modified,
+          on_command_line, ModificationCount());
+    }
+    case FlagValueStorageKind::kOneWordAtomic: {
+      return absl::make_unique<FlagState>(
+          *this, OneWordValue().load(std::memory_order_acquire), modified,
+          on_command_line, ModificationCount());
+    }
+    case FlagValueStorageKind::kSequenceLocked: {
+      void* cloned = flags_internal::Alloc(op_);
+      // Read is guaranteed to be successful because we hold the lock.
+      bool success =
+          seq_lock_.TryRead(cloned, AtomicBufferValue(), Sizeof(op_));
+      assert(success);
+      static_cast<void>(success);
+      return absl::make_unique<FlagState>(*this, cloned, modified,
+                                          on_command_line, ModificationCount());
+    }
+  }
+  return nullptr;
+}
+
+bool FlagImpl::RestoreState(const FlagState& flag_state) {
+  absl::MutexLock l(DataGuard());
+  if (flag_state.counter_ == ModificationCount()) {
+    return false;
+  }
+
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer:
+    case FlagValueStorageKind::kSequenceLocked:
+      StoreValue(flag_state.value_.heap_allocated);
+      break;
+    case FlagValueStorageKind::kOneWordAtomic:
+      StoreValue(&flag_state.value_.one_word);
+      break;
+  }
+
+  modified_ = flag_state.modified_;
+  on_command_line_ = flag_state.on_command_line_;
+
+  return true;
+}
+
+template <typename StorageT>
+StorageT* FlagImpl::OffsetValue() const {
+  char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this));
+  // The offset is deduced via Flag value type specific op_.
+  size_t offset = flags_internal::ValueOffset(op_);
+
+  return reinterpret_cast<StorageT*>(p + offset);
+}
+
+void* FlagImpl::AlignedBufferValue() const {
+  assert(ValueStorageKind() == FlagValueStorageKind::kAlignedBuffer);
+  return OffsetValue<void>();
+}
+
+std::atomic<uint64_t>* FlagImpl::AtomicBufferValue() const {
+  assert(ValueStorageKind() == FlagValueStorageKind::kSequenceLocked);
+  return OffsetValue<std::atomic<uint64_t>>();
+}
+
+std::atomic<int64_t>& FlagImpl::OneWordValue() const {
+  assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic);
+  return OffsetValue<FlagOneWordValue>()->value;
+}
+
+// Attempts to parse supplied `value` string using parsing routine in the `flag`
+// argument. If parsing successful, this function replaces the dst with newly
+// parsed value. In case if any error is encountered in either step, the error
+// message is stored in 'err'
+std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse(
+    absl::string_view value, std::string& err) const {
+  std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue();
+
+  std::string parse_err;
+  if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) {
+    absl::string_view err_sep = parse_err.empty() ? "" : "; ";
+    err = absl::StrCat("Illegal value '", value, "' specified for flag '",
+                       Name(), "'", err_sep, parse_err);
+    return nullptr;
+  }
+
+  return tentative_value;
+}
+
+void FlagImpl::Read(void* dst) const {
+  auto* guard = DataGuard();  // Make sure flag initialized
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer: {
+      absl::MutexLock l(guard);
+      flags_internal::CopyConstruct(op_, AlignedBufferValue(), dst);
+      break;
+    }
+    case FlagValueStorageKind::kOneWordAtomic: {
+      const int64_t one_word_val =
+          OneWordValue().load(std::memory_order_acquire);
+      std::memcpy(dst, &one_word_val, Sizeof(op_));
+      break;
+    }
+    case FlagValueStorageKind::kSequenceLocked: {
+      ReadSequenceLockedData(dst);
+      break;
+    }
+  }
+}
+
+void FlagImpl::ReadSequenceLockedData(void* dst) const {
+  int size = Sizeof(op_);
+  // Attempt to read using the sequence lock.
+  if (ABSL_PREDICT_TRUE(seq_lock_.TryRead(dst, AtomicBufferValue(), size))) {
+    return;
+  }
+  // We failed due to contention. Acquire the lock to prevent contention
+  // and try again.
+  absl::ReaderMutexLock l(DataGuard());
+  bool success = seq_lock_.TryRead(dst, AtomicBufferValue(), size);
+  assert(success);
+  static_cast<void>(success);
+}
+
+void FlagImpl::Write(const void* src) {
+  absl::MutexLock l(DataGuard());
+
+  if (ShouldValidateFlagValue(flags_internal::FastTypeId(op_))) {
+    std::unique_ptr<void, DynValueDeleter> obj{flags_internal::Clone(op_, src),
+                                               DynValueDeleter{op_}};
+    std::string ignored_error;
+    std::string src_as_str = flags_internal::Unparse(op_, src);
+    if (!flags_internal::Parse(op_, src_as_str, obj.get(), &ignored_error)) {
+      ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(),
+                                            "' to invalid value ", src_as_str));
+    }
+  }
+
+  StoreValue(src);
+}
+
+// Sets the value of the flag based on specified string `value`. If the flag
+// was successfully set to new value, it returns true. Otherwise, sets `err`
+// to indicate the error, leaves the flag unchanged, and returns false. There
+// are three ways to set the flag's value:
+//  * Update the current flag value
+//  * Update the flag's default value
+//  * Update the current flag value if it was never set before
+// The mode is selected based on 'set_mode' parameter.
+bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode,
+                         ValueSource source, std::string& err) {
+  absl::MutexLock l(DataGuard());
+
+  switch (set_mode) {
+    case SET_FLAGS_VALUE: {
+      // set or modify the flag's value
+      auto tentative_value = TryParse(value, err);
+      if (!tentative_value) return false;
+
+      StoreValue(tentative_value.get());
+
+      if (source == kCommandLine) {
+        on_command_line_ = true;
+      }
+      break;
+    }
+    case SET_FLAG_IF_DEFAULT: {
+      // set the flag's value, but only if it hasn't been set by someone else
+      if (modified_) {
+        // TODO(rogeeff): review and fix this semantic. Currently we do not fail
+        // in this case if flag is modified. This is misleading since the flag's
+        // value is not updated even though we return true.
+        // *err = absl::StrCat(Name(), " is already set to ",
+        //                     CurrentValue(), "\n");
+        // return false;
+        return true;
+      }
+      auto tentative_value = TryParse(value, err);
+      if (!tentative_value) return false;
+
+      StoreValue(tentative_value.get());
+      break;
+    }
+    case SET_FLAGS_DEFAULT: {
+      auto tentative_value = TryParse(value, err);
+      if (!tentative_value) return false;
+
+      if (DefaultKind() == FlagDefaultKind::kDynamicValue) {
+        void* old_value = default_value_.dynamic_value;
+        default_value_.dynamic_value = tentative_value.release();
+        tentative_value.reset(old_value);
+      } else {
+        default_value_.dynamic_value = tentative_value.release();
+        def_kind_ = static_cast<uint8_t>(FlagDefaultKind::kDynamicValue);
+      }
+
+      if (!modified_) {
+        // Need to set both default value *and* current, in this case.
+        StoreValue(default_value_.dynamic_value);
+        modified_ = false;
+      }
+      break;
+    }
+  }
+
+  return true;
+}
+
+void FlagImpl::CheckDefaultValueParsingRoundtrip() const {
+  std::string v = DefaultValue();
+
+  absl::MutexLock lock(DataGuard());
+
+  auto dst = MakeInitValue();
+  std::string error;
+  if (!flags_internal::Parse(op_, v, dst.get(), &error)) {
+    ABSL_INTERNAL_LOG(
+        FATAL,
+        absl::StrCat("Flag ", Name(), " (from ", Filename(),
+                     "): string form of default value '", v,
+                     "' could not be parsed; error=", error));
+  }
+
+  // We do not compare dst to def since parsing/unparsing may make
+  // small changes, e.g., precision loss for floating point types.
+}
+
+bool FlagImpl::ValidateInputValue(absl::string_view value) const {
+  absl::MutexLock l(DataGuard());
+
+  auto obj = MakeInitValue();
+  std::string ignored_error;
+  return flags_internal::Parse(op_, value, obj.get(), &ignored_error);
 }
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index 1633038..8354814 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -16,58 +16,597 @@
 #ifndef ABSL_FLAGS_INTERNAL_FLAG_H_
 #define ABSL_FLAGS_INTERNAL_FLAG_H_
 
-#include <cstring>
+#include <stddef.h>
+#include <stdint.h>
 
+#include <atomic>
+#include <cstring>
+#include <memory>
+#include <new>
+#include <string>
+#include <type_traits>
+#include <typeinfo>
+
+#include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/config.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/internal/registry.h"
+#include "absl/flags/internal/sequence_lock.h"
+#include "absl/flags/marshalling.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/utility/utility.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Forward declaration of absl::Flag<T> public API.
+namespace flags_internal {
+template <typename T>
+class Flag;
+}  // namespace flags_internal
+
+#if defined(_MSC_VER) && !defined(__clang__)
+template <typename T>
+class Flag;
+#else
+template <typename T>
+using Flag = flags_internal::Flag<T>;
+#endif
+
+template <typename T>
+ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag);
+
+template <typename T>
+void SetFlag(absl::Flag<T>* flag, const T& v);
+
+template <typename T, typename V>
+void SetFlag(absl::Flag<T>* flag, const V& v);
+
+template <typename U>
+const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<U>& f);
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag value type operations, eg., parsing, copying, etc. are provided
+// by function specific to that type with a signature matching FlagOpFn.
+
 namespace flags_internal {
 
-constexpr int64_t AtomicInit() { return 0xababababababababll; }
+enum class FlagOp {
+  kAlloc,
+  kDelete,
+  kCopy,
+  kCopyConstruct,
+  kSizeof,
+  kFastTypeId,
+  kRuntimeTypeId,
+  kParse,
+  kUnparse,
+  kValueOffset,
+};
+using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*);
+
+// Forward declaration for Flag value specific operations.
+template <typename T>
+void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3);
+
+// Allocate aligned memory for a flag value.
+inline void* Alloc(FlagOpFn op) {
+  return op(FlagOp::kAlloc, nullptr, nullptr, nullptr);
+}
+// Deletes memory interpreting obj as flag value type pointer.
+inline void Delete(FlagOpFn op, void* obj) {
+  op(FlagOp::kDelete, nullptr, obj, nullptr);
+}
+// Copies src to dst interpreting as flag value type pointers.
+inline void Copy(FlagOpFn op, const void* src, void* dst) {
+  op(FlagOp::kCopy, src, dst, nullptr);
+}
+// Construct a copy of flag value in a location pointed by dst
+// based on src - pointer to the flag's value.
+inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
+  op(FlagOp::kCopyConstruct, src, dst, nullptr);
+}
+// Makes a copy of flag value pointed by obj.
+inline void* Clone(FlagOpFn op, const void* obj) {
+  void* res = flags_internal::Alloc(op);
+  flags_internal::CopyConstruct(op, obj, res);
+  return res;
+}
+// Returns true if parsing of input text is successfull.
+inline bool Parse(FlagOpFn op, absl::string_view text, void* dst,
+                  std::string* error) {
+  return op(FlagOp::kParse, &text, dst, error) != nullptr;
+}
+// Returns string representing supplied value.
+inline std::string Unparse(FlagOpFn op, const void* val) {
+  std::string result;
+  op(FlagOp::kUnparse, val, &result, nullptr);
+  return result;
+}
+// Returns size of flag value type.
+inline size_t Sizeof(FlagOpFn op) {
+  // This sequence of casts reverses the sequence from
+  // `flags_internal::FlagOps()`
+  return static_cast<size_t>(reinterpret_cast<intptr_t>(
+      op(FlagOp::kSizeof, nullptr, nullptr, nullptr)));
+}
+// Returns fast type id coresponding to the value type.
+inline FlagFastTypeId FastTypeId(FlagOpFn op) {
+  return reinterpret_cast<FlagFastTypeId>(
+      op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr));
+}
+// Returns fast type id coresponding to the value type.
+inline const std::type_info* RuntimeTypeId(FlagOpFn op) {
+  return reinterpret_cast<const std::type_info*>(
+      op(FlagOp::kRuntimeTypeId, nullptr, nullptr, nullptr));
+}
+// Returns offset of the field value_ from the field impl_ inside of
+// absl::Flag<T> data. Given FlagImpl pointer p you can get the
+// location of the corresponding value as:
+//      reinterpret_cast<char*>(p) + ValueOffset().
+inline ptrdiff_t ValueOffset(FlagOpFn op) {
+  // This sequence of casts reverses the sequence from
+  // `flags_internal::FlagOps()`
+  return static_cast<ptrdiff_t>(reinterpret_cast<intptr_t>(
+      op(FlagOp::kValueOffset, nullptr, nullptr, nullptr)));
+}
+
+// Returns an address of RTTI's typeid(T).
+template <typename T>
+inline const std::type_info* GenRuntimeTypeId() {
+#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI)
+  return &typeid(T);
+#else
+  return nullptr;
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag help auxiliary structs.
+
+// This is help argument for absl::Flag encapsulating the string literal pointer
+// or pointer to function generating it as well as enum descriminating two
+// cases.
+using HelpGenFunc = std::string (*)();
+
+template <size_t N>
+struct FixedCharArray {
+  char value[N];
+
+  template <size_t... I>
+  static constexpr FixedCharArray<N> FromLiteralString(
+      absl::string_view str, absl::index_sequence<I...>) {
+    return (void)str, FixedCharArray<N>({{str[I]..., '\0'}});
+  }
+};
+
+template <typename Gen, size_t N = Gen::Value().size()>
+constexpr FixedCharArray<N + 1> HelpStringAsArray(int) {
+  return FixedCharArray<N + 1>::FromLiteralString(
+      Gen::Value(), absl::make_index_sequence<N>{});
+}
+
+template <typename Gen>
+constexpr std::false_type HelpStringAsArray(char) {
+  return std::false_type{};
+}
+
+union FlagHelpMsg {
+  constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {}
+  constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {}
+
+  const char* literal;
+  HelpGenFunc gen_func;
+};
+
+enum class FlagHelpKind : uint8_t { kLiteral = 0, kGenFunc = 1 };
+
+struct FlagHelpArg {
+  FlagHelpMsg source;
+  FlagHelpKind kind;
+};
+
+extern const char kStrippedFlagHelp[];
+
+// These two HelpArg overloads allows us to select at compile time one of two
+// way to pass Help argument to absl::Flag. We'll be passing
+// AbslFlagHelpGenFor##name as Gen and integer 0 as a single argument to prefer
+// first overload if possible. If help message is evaluatable on constexpr
+// context We'll be able to make FixedCharArray out of it and we'll choose first
+// overload. In this case the help message expression is immediately evaluated
+// and is used to construct the absl::Flag. No additionl code is generated by
+// ABSL_FLAG Otherwise SFINAE kicks in and first overload is dropped from the
+// consideration, in which case the second overload will be used. The second
+// overload does not attempt to evaluate the help message expression
+// immediately and instead delays the evaluation by returing the function
+// pointer (&T::NonConst) genering the help message when necessary. This is
+// evaluatable in constexpr context, but the cost is an extra function being
+// generated in the ABSL_FLAG code.
+template <typename Gen, size_t N>
+constexpr FlagHelpArg HelpArg(const FixedCharArray<N>& value) {
+  return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral};
+}
+
+template <typename Gen>
+constexpr FlagHelpArg HelpArg(std::false_type) {
+  return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc};
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag default value auxiliary structs.
+
+// Signature for the function generating the initial flag value (usually
+// based on default value supplied in flag's definition)
+using FlagDfltGenFunc = void (*)(void*);
+
+union FlagDefaultSrc {
+  constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg)
+      : gen_func(gen_func_arg) {}
+
+#define ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE(T, name) \
+  T name##_value;                                  \
+  constexpr explicit FlagDefaultSrc(T value) : name##_value(value) {}  // NOLINT
+  ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE)
+#undef ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE
+
+  void* dynamic_value;
+  FlagDfltGenFunc gen_func;
+};
+
+enum class FlagDefaultKind : uint8_t {
+  kDynamicValue = 0,
+  kGenFunc = 1,
+  kOneWord = 2  // for default values UP to one word in size
+};
+
+struct FlagDefaultArg {
+  FlagDefaultSrc source;
+  FlagDefaultKind kind;
+};
+
+// This struct and corresponding overload to InitDefaultValue are used to
+// facilitate usage of {} as default value in ABSL_FLAG macro.
+// TODO(rogeeff): Fix handling types with explicit constructors.
+struct EmptyBraces {};
+
+template <typename T>
+constexpr T InitDefaultValue(T t) {
+  return t;
+}
+
+template <typename T>
+constexpr T InitDefaultValue(EmptyBraces) {
+  return T{};
+}
+
+template <typename ValueT, typename GenT,
+          typename std::enable_if<std::is_integral<ValueT>::value, int>::type =
+              (GenT{}, 0)>
+constexpr FlagDefaultArg DefaultArg(int) {
+  return {FlagDefaultSrc(GenT{}.value), FlagDefaultKind::kOneWord};
+}
+
+template <typename ValueT, typename GenT>
+constexpr FlagDefaultArg DefaultArg(char) {
+  return {FlagDefaultSrc(&GenT::Gen), FlagDefaultKind::kGenFunc};
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag current value auxiliary structs.
+
+constexpr int64_t UninitializedFlagValue() { return 0xababababababababll; }
+
+template <typename T>
+using FlagUseOneWordStorage = std::integral_constant<
+    bool, absl::type_traits_internal::is_trivially_copyable<T>::value &&
+              (sizeof(T) <= 8)>;
+
+template <class T>
+using FlagShouldUseSequenceLock = std::integral_constant<
+    bool, absl::type_traits_internal::is_trivially_copyable<T>::value &&
+              (sizeof(T) > 8)>;
+
+enum class FlagValueStorageKind : uint8_t {
+  kAlignedBuffer = 0,
+  kOneWordAtomic = 1,
+  kSequenceLocked = 2,
+};
+
+template <typename T>
+static constexpr FlagValueStorageKind StorageKind() {
+  return FlagUseOneWordStorage<T>::value ? FlagValueStorageKind::kOneWordAtomic
+         : FlagShouldUseSequenceLock<T>::value
+             ? FlagValueStorageKind::kSequenceLocked
+             : FlagValueStorageKind::kAlignedBuffer;
+}
+
+struct FlagOneWordValue {
+  constexpr FlagOneWordValue() : value(UninitializedFlagValue()) {}
+
+  std::atomic<int64_t> value;
+};
+
+template <typename T,
+          FlagValueStorageKind Kind = flags_internal::StorageKind<T>()>
+struct FlagValue;
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> {
+  bool Get(const SequenceLock&, T&) const { return false; }
+
+  alignas(T) char value[sizeof(T)];
+};
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue {
+  bool Get(const SequenceLock&, T& dst) const {
+    int64_t one_word_val = value.load(std::memory_order_acquire);
+    if (ABSL_PREDICT_FALSE(one_word_val == UninitializedFlagValue())) {
+      return false;
+    }
+    std::memcpy(&dst, static_cast<const void*>(&one_word_val), sizeof(T));
+    return true;
+  }
+};
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kSequenceLocked> {
+  bool Get(const SequenceLock& lock, T& dst) const {
+    return lock.TryRead(&dst, value_words, sizeof(T));
+  }
+
+  static constexpr int kNumWords =
+      flags_internal::AlignUp(sizeof(T), sizeof(uint64_t)) / sizeof(uint64_t);
+
+  alignas(T) alignas(
+      std::atomic<uint64_t>) std::atomic<uint64_t> value_words[kNumWords];
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag callback auxiliary structs.
 
 // Signature for the mutation callback used by watched Flags
 // The callback is noexcept.
 // TODO(rogeeff): add noexcept after C++17 support is added.
-using FlagCallback = void (*)();
+using FlagCallbackFunc = void (*)();
 
-void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu,
-                    FlagCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(primary_mu);
+struct FlagCallback {
+  FlagCallbackFunc func;
+  absl::Mutex guard;  // Guard for concurrent callback invocations.
+};
 
-// This is "unspecified" implementation of absl::Flag<T> type.
-template <typename T>
-class Flag final : public flags_internal::CommandLineFlag {
+///////////////////////////////////////////////////////////////////////////////
+// Flag implementation, which does not depend on flag value type.
+// The class encapsulates the Flag's data and access to it.
+
+struct DynValueDeleter {
+  explicit DynValueDeleter(FlagOpFn op_arg = nullptr);
+  void operator()(void* ptr) const;
+
+  FlagOpFn op;
+};
+
+class FlagState;
+
+class FlagImpl final : public CommandLineFlag {
  public:
-  constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen,
-                 const char* filename,
-                 const flags_internal::FlagMarshallingOpFn marshalling_op,
-                 const flags_internal::InitialValGenFunc initial_value_gen)
-      : flags_internal::CommandLineFlag(
-            name, flags_internal::HelpText::FromFunctionPointer(help_gen),
-            filename, &flags_internal::FlagOps<T>, marshalling_op,
-            initial_value_gen,
-            /*def=*/nullptr,
-            /*cur=*/nullptr),
-        atomic_(flags_internal::AtomicInit()),
-        callback_(nullptr) {}
+  constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op,
+                     FlagHelpArg help, FlagValueStorageKind value_kind,
+                     FlagDefaultArg default_arg)
+      : name_(name),
+        filename_(filename),
+        op_(op),
+        help_(help.source),
+        help_source_kind_(static_cast<uint8_t>(help.kind)),
+        value_storage_kind_(static_cast<uint8_t>(value_kind)),
+        def_kind_(static_cast<uint8_t>(default_arg.kind)),
+        modified_(false),
+        on_command_line_(false),
+        callback_(nullptr),
+        default_value_(default_arg.source),
+        data_guard_{} {}
+
+  // Constant access methods
+  void Read(void* dst) const override ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  // Mutating access methods
+  void Write(const void* src) ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  // Interfaces to operate on callbacks.
+  void SetCallback(const FlagCallbackFunc mutation_callback)
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+  void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+  // Used in read/write operations to validate source/target has correct type.
+  // For example if flag is declared as absl::Flag<int> FLAGS_foo, a call to
+  // absl::GetFlag(FLAGS_foo) validates that the type of FLAGS_foo is indeed
+  // int. To do that we pass the "assumed" type id (which is deduced from type
+  // int) as an argument `type_id`, which is in turn is validated against the
+  // type id stored in flag object by flag definition statement.
+  void AssertValidType(FlagFastTypeId type_id,
+                       const std::type_info* (*gen_rtti)()) const;
+
+ private:
+  template <typename T>
+  friend class Flag;
+  friend class FlagState;
+
+  // Ensures that `data_guard_` is initialized and returns it.
+  absl::Mutex* DataGuard() const
+      ABSL_LOCK_RETURNED(reinterpret_cast<absl::Mutex*>(data_guard_));
+  // Returns heap allocated value of type T initialized with default value.
+  std::unique_ptr<void, DynValueDeleter> MakeInitValue() const
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+  // Flag initialization called via absl::call_once.
+  void Init();
+
+  // Offset value access methods. One per storage kind. These methods to not
+  // respect const correctness, so be very carefull using them.
+
+  // This is a shared helper routine which encapsulates most of the magic. Since
+  // it is only used inside the three routines below, which are defined in
+  // flag.cc, we can define it in that file as well.
+  template <typename StorageT>
+  StorageT* OffsetValue() const;
+  // This is an accessor for a value stored in an aligned buffer storage
+  // used for non-trivially-copyable data types.
+  // Returns a mutable pointer to the start of a buffer.
+  void* AlignedBufferValue() const;
+
+  // The same as above, but used for sequencelock-protected storage.
+  std::atomic<uint64_t>* AtomicBufferValue() const;
+
+  // This is an accessor for a value stored as one word atomic. Returns a
+  // mutable reference to an atomic value.
+  std::atomic<int64_t>& OneWordValue() const;
+
+  // Attempts to parse supplied `value` string. If parsing is successful,
+  // returns new value. Otherwise returns nullptr.
+  std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value,
+                                                  std::string& err) const
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+  // Stores the flag value based on the pointer to the source.
+  void StoreValue(const void* src) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+  // Copy the flag data, protected by `seq_lock_` into `dst`.
+  //
+  // REQUIRES: ValueStorageKind() == kSequenceLocked.
+  void ReadSequenceLockedData(void* dst) const
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  FlagHelpKind HelpSourceKind() const {
+    return static_cast<FlagHelpKind>(help_source_kind_);
+  }
+  FlagValueStorageKind ValueStorageKind() const {
+    return static_cast<FlagValueStorageKind>(value_storage_kind_);
+  }
+  FlagDefaultKind DefaultKind() const
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()) {
+    return static_cast<FlagDefaultKind>(def_kind_);
+  }
+
+  // CommandLineFlag interface implementation
+  absl::string_view Name() const override;
+  std::string Filename() const override;
+  std::string Help() const override;
+  FlagFastTypeId TypeId() const override;
+  bool IsSpecifiedOnCommandLine() const override
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+  std::string DefaultValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard());
+  std::string CurrentValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard());
+  bool ValidateInputValue(absl::string_view value) const override
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+  void CheckDefaultValueParsingRoundtrip() const override
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  int64_t ModificationCount() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+  // Interfaces to save and restore flags to/from persistent state.
+  // Returns current flag state or nullptr if flag does not support
+  // saving and restoring a state.
+  std::unique_ptr<FlagStateInterface> SaveState() override
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  // Restores the flag state to the supplied state object. If there is
+  // nothing to restore returns false. Otherwise returns true.
+  bool RestoreState(const FlagState& flag_state)
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  bool ParseFrom(absl::string_view value, FlagSettingMode set_mode,
+                 ValueSource source, std::string& error) override
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  // Immutable flag's state.
+
+  // Flags name passed to ABSL_FLAG as second arg.
+  const char* const name_;
+  // The file name where ABSL_FLAG resides.
+  const char* const filename_;
+  // Type-specific operations "vtable".
+  const FlagOpFn op_;
+  // Help message literal or function to generate it.
+  const FlagHelpMsg help_;
+  // Indicates if help message was supplied as literal or generator func.
+  const uint8_t help_source_kind_ : 1;
+  // Kind of storage this flag is using for the flag's value.
+  const uint8_t value_storage_kind_ : 2;
+
+  uint8_t : 0;  // The bytes containing the const bitfields must not be
+                // shared with bytes containing the mutable bitfields.
+
+  // Mutable flag's state (guarded by `data_guard_`).
+
+  // def_kind_ is not guard by DataGuard() since it is accessed in Init without
+  // locks.
+  uint8_t def_kind_ : 2;
+  // Has this flag's value been modified?
+  bool modified_ : 1 ABSL_GUARDED_BY(*DataGuard());
+  // Has this flag been specified on command line.
+  bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard());
+
+  // Unique tag for absl::call_once call to initialize this flag.
+  absl::once_flag init_control_;
+
+  // Sequence lock / mutation counter.
+  flags_internal::SequenceLock seq_lock_;
+
+  // Optional flag's callback and absl::Mutex to guard the invocations.
+  FlagCallback* callback_ ABSL_GUARDED_BY(*DataGuard());
+  // Either a pointer to the function generating the default value based on the
+  // value specified in ABSL_FLAG or pointer to the dynamically set default
+  // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish
+  // these two cases.
+  FlagDefaultSrc default_value_;
+
+  // This is reserved space for an absl::Mutex to guard flag data. It will be
+  // initialized in FlagImpl::Init via placement new.
+  // We can't use "absl::Mutex data_guard_", since this class is not literal.
+  // We do not want to use "absl::Mutex* data_guard_", since this would require
+  // heap allocation during initialization, which is both slows program startup
+  // and can fail. Using reserved space + placement new allows us to avoid both
+  // problems.
+  alignas(absl::Mutex) mutable char data_guard_[sizeof(absl::Mutex)];
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// The Flag object parameterized by the flag's value type. This class implements
+// flag reflection handle interface.
+
+template <typename T>
+class Flag {
+ public:
+  constexpr Flag(const char* name, const char* filename, FlagHelpArg help,
+                 const FlagDefaultArg default_arg)
+      : impl_(name, filename, &FlagOps<T>, help,
+              flags_internal::StorageKind<T>(), default_arg),
+        value_() {}
+
+  // CommandLineFlag interface
+  absl::string_view Name() const { return impl_.Name(); }
+  std::string Filename() const { return impl_.Filename(); }
+  std::string Help() const { return impl_.Help(); }
+  // Do not use. To be removed.
+  bool IsSpecifiedOnCommandLine() const {
+    return impl_.IsSpecifiedOnCommandLine();
+  }
+  std::string DefaultValue() const { return impl_.DefaultValue(); }
+  std::string CurrentValue() const { return impl_.CurrentValue(); }
+
+ private:
+  template <typename, bool>
+  friend class FlagRegistrar;
+  friend class FlagImplPeer;
 
   T Get() const {
-    // Implementation notes:
-    //
-    // We are wrapping a union around the value of `T` to serve three purposes:
-    //
-    //  1. `U.value` has correct size and alignment for a value of type `T`
-    //  2. The `U.value` constructor is not invoked since U's constructor does
-    //  not
-    //     do it explicitly.
-    //  3. The `U.value` destructor is invoked since U's destructor does it
-    //     explicitly. This makes `U` a kind of RAII wrapper around non default
-    //     constructible value of T, which is destructed when we leave the
-    //     scope. We do need to destroy U.value, which is constructed by
-    //     CommandLineFlag::Read even though we left it in a moved-from state
-    //     after std::move.
-    //
-    // All of this serves to avoid requiring `T` being default constructible.
+    // See implementation notes in CommandLineFlag::Get().
     union U {
       T value;
       U() {}
@@ -75,97 +614,133 @@
     };
     U u;
 
-    Read(&u.value, &flags_internal::FlagOps<T>);
+#if !defined(NDEBUG)
+    impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
+#endif
+
+    if (ABSL_PREDICT_FALSE(!value_.Get(impl_.seq_lock_, u.value))) {
+      impl_.Read(&u.value);
+    }
     return std::move(u.value);
   }
-
-  bool AtomicGet(T* v) const {
-    const int64_t r = atomic_.load(std::memory_order_acquire);
-    if (r != flags_internal::AtomicInit()) {
-      std::memcpy(v, &r, sizeof(T));
-      return true;
-    }
-
-    return false;
+  void Set(const T& v) {
+    impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
+    impl_.Write(&v);
   }
 
-  void Set(const T& v) { Write(&v, &flags_internal::FlagOps<T>); }
-
-  void SetCallback(const flags_internal::FlagCallback mutation_callback) {
-    absl::MutexLock l(InitFlagIfNecessary());
-
-    callback_ = mutation_callback;
-
-    InvokeCallback();
-  }
-  void InvokeCallback() override
-      ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) {
-    flags_internal::InvokeCallback(&locks_->primary_mu, &locks_->callback_mu,
-                                   callback_);
-  }
-
- private:
-  void Destroy() const override {
-    // Values are heap allocated Abseil Flags.
-    if (cur_) Delete(op_, cur_);
-    if (def_) Delete(op_, def_);
-
-    delete locks_;
-  }
-
-  void StoreAtomic() override {
-    if (sizeof(T) <= sizeof(int64_t)) {
-      int64_t t = 0;
-      std::memcpy(&t, cur_, (std::min)(sizeof(T), sizeof(int64_t)));
-      atomic_.store(t, std::memory_order_release);
-    }
-  }
+  // Access to the reflection.
+  const CommandLineFlag& Reflect() const { return impl_; }
 
   // Flag's data
-  // For some types, a copy of the current value is kept in an atomically
-  // accessible field.
-  std::atomic<int64_t> atomic_;
-  FlagCallback callback_;  // Mutation callback
+  // The implementation depends on value_ field to be placed exactly after the
+  // impl_ field, so that impl_ can figure out the offset to the value and
+  // access it.
+  FlagImpl impl_;
+  FlagValue<T> value_;
 };
 
+///////////////////////////////////////////////////////////////////////////////
+// Trampoline for friend access
+
+class FlagImplPeer {
+ public:
+  template <typename T, typename FlagType>
+  static T InvokeGet(const FlagType& flag) {
+    return flag.Get();
+  }
+  template <typename FlagType, typename T>
+  static void InvokeSet(FlagType& flag, const T& v) {
+    flag.Set(v);
+  }
+  template <typename FlagType>
+  static const CommandLineFlag& InvokeReflect(const FlagType& f) {
+    return f.Reflect();
+  }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation of Flag value specific operations routine.
+template <typename T>
+void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
+  switch (op) {
+    case FlagOp::kAlloc: {
+      std::allocator<T> alloc;
+      return std::allocator_traits<std::allocator<T>>::allocate(alloc, 1);
+    }
+    case FlagOp::kDelete: {
+      T* p = static_cast<T*>(v2);
+      p->~T();
+      std::allocator<T> alloc;
+      std::allocator_traits<std::allocator<T>>::deallocate(alloc, p, 1);
+      return nullptr;
+    }
+    case FlagOp::kCopy:
+      *static_cast<T*>(v2) = *static_cast<const T*>(v1);
+      return nullptr;
+    case FlagOp::kCopyConstruct:
+      new (v2) T(*static_cast<const T*>(v1));
+      return nullptr;
+    case FlagOp::kSizeof:
+      return reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(T)));
+    case FlagOp::kFastTypeId:
+      return const_cast<void*>(base_internal::FastTypeId<T>());
+    case FlagOp::kRuntimeTypeId:
+      return const_cast<std::type_info*>(GenRuntimeTypeId<T>());
+    case FlagOp::kParse: {
+      // Initialize the temporary instance of type T based on current value in
+      // destination (which is going to be flag's default value).
+      T temp(*static_cast<T*>(v2));
+      if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp,
+                              static_cast<std::string*>(v3))) {
+        return nullptr;
+      }
+      *static_cast<T*>(v2) = std::move(temp);
+      return v2;
+    }
+    case FlagOp::kUnparse:
+      *static_cast<std::string*>(v2) =
+          absl::UnparseFlag<T>(*static_cast<const T*>(v1));
+      return nullptr;
+    case FlagOp::kValueOffset: {
+      // Round sizeof(FlagImp) to a multiple of alignof(FlagValue<T>) to get the
+      // offset of the data.
+      ptrdiff_t round_to = alignof(FlagValue<T>);
+      ptrdiff_t offset =
+          (sizeof(FlagImpl) + round_to - 1) / round_to * round_to;
+      return reinterpret_cast<void*>(offset);
+    }
+  }
+  return nullptr;
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // This class facilitates Flag object registration and tail expression-based
 // flag definition, for example:
 // ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher);
+struct FlagRegistrarEmpty {};
 template <typename T, bool do_register>
 class FlagRegistrar {
  public:
-  explicit FlagRegistrar(Flag<T>* flag) : flag_(flag) {
-    if (do_register) flags_internal::RegisterCommandLineFlag(flag_);
+  explicit FlagRegistrar(Flag<T>& flag) : flag_(flag) {
+    if (do_register) flags_internal::RegisterCommandLineFlag(flag_.impl_);
   }
 
-  FlagRegistrar& OnUpdate(flags_internal::FlagCallback cb) && {
-    flag_->SetCallback(cb);
+  FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
+    flag_.impl_.SetCallback(cb);
     return *this;
   }
 
-  // Make the registrar "die" gracefully as a bool on a line where registration
-  // happens. Registrar objects are intended to live only as temporary.
-  operator bool() const { return true; }  // NOLINT
+  // Make the registrar "die" gracefully as an empty struct on a line where
+  // registration happens. Registrar objects are intended to live only as
+  // temporary.
+  operator FlagRegistrarEmpty() const { return {}; }  // NOLINT
 
  private:
-  Flag<T>* flag_;  // Flag being registered (not owned).
+  Flag<T>& flag_;  // Flag being registered (not owned).
 };
 
-// This struct and corresponding overload to MakeDefaultValue are used to
-// facilitate usage of {} as default value in ABSL_FLAG macro.
-struct EmptyBraces {};
-
-template <typename T>
-T* MakeFromDefaultValue(T t) {
-  return new T(std::move(t));
-}
-
-template <typename T>
-T* MakeFromDefaultValue(EmptyBraces) {
-  return new T;
-}
-
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_FLAG_H_
diff --git a/absl/flags/internal/parse.h b/absl/flags/internal/parse.h
index fd3aca6..de706c8 100644
--- a/absl/flags/internal/parse.h
+++ b/absl/flags/internal/parse.h
@@ -19,7 +19,9 @@
 #include <string>
 #include <vector>
 
+#include "absl/base/config.h"
 #include "absl/flags/declare.h"
+#include "absl/strings/string_view.h"
 
 ABSL_DECLARE_FLAG(std::vector<std::string>, flagfile);
 ABSL_DECLARE_FLAG(std::vector<std::string>, fromenv);
@@ -27,6 +29,7 @@
 ABSL_DECLARE_FLAG(std::vector<std::string>, undefok);
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 enum class ArgvListAction { kRemoveParsedArgs, kKeepParsedArgs };
@@ -42,7 +45,15 @@
                                         UsageFlagsAction usage_flag_act,
                                         OnUndefinedFlag on_undef_flag);
 
+// --------------------------------------------------------------------
+// Inspect original command line
+
+// Returns true if flag with specified name was either present on the original
+// command line or specified in flag file present on the original command line.
+bool WasPresentOnCommandLine(absl::string_view flag_name);
+
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_PARSE_H_
diff --git a/absl/flags/internal/path_util.h b/absl/flags/internal/path_util.h
index 5615c0e..a6594d3 100644
--- a/absl/flags/internal/path_util.h
+++ b/absl/flags/internal/path_util.h
@@ -16,10 +16,11 @@
 #ifndef ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
 #define ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
 
-#include "absl/strings/match.h"
+#include "absl/base/config.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 // A portable interface that returns the basename of the filename passed as an
@@ -55,6 +56,7 @@
 }
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
diff --git a/absl/flags/internal/private_handle_accessor.cc b/absl/flags/internal/private_handle_accessor.cc
new file mode 100644
index 0000000..a7eb58b
--- /dev/null
+++ b/absl/flags/internal/private_handle_accessor.cc
@@ -0,0 +1,65 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/internal/private_handle_accessor.h"
+
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+FlagFastTypeId PrivateHandleAccessor::TypeId(const CommandLineFlag& flag) {
+  return flag.TypeId();
+}
+
+std::unique_ptr<FlagStateInterface> PrivateHandleAccessor::SaveState(
+    CommandLineFlag& flag) {
+  return flag.SaveState();
+}
+
+bool PrivateHandleAccessor::IsSpecifiedOnCommandLine(
+    const CommandLineFlag& flag) {
+  return flag.IsSpecifiedOnCommandLine();
+}
+
+bool PrivateHandleAccessor::ValidateInputValue(const CommandLineFlag& flag,
+                                               absl::string_view value) {
+  return flag.ValidateInputValue(value);
+}
+
+void PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
+    const CommandLineFlag& flag) {
+  flag.CheckDefaultValueParsingRoundtrip();
+}
+
+bool PrivateHandleAccessor::ParseFrom(CommandLineFlag& flag,
+                                      absl::string_view value,
+                                      flags_internal::FlagSettingMode set_mode,
+                                      flags_internal::ValueSource source,
+                                      std::string& error) {
+  return flag.ParseFrom(value, set_mode, source, error);
+}
+
+}  // namespace flags_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
diff --git a/absl/flags/internal/private_handle_accessor.h b/absl/flags/internal/private_handle_accessor.h
new file mode 100644
index 0000000..c64435c
--- /dev/null
+++ b/absl/flags/internal/private_handle_accessor.h
@@ -0,0 +1,61 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
+#define ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
+
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// This class serves as a trampoline to access private methods of
+// CommandLineFlag. This class is intended for use exclusively internally inside
+// of the Abseil Flags implementation.
+class PrivateHandleAccessor {
+ public:
+  // Access to CommandLineFlag::TypeId.
+  static FlagFastTypeId TypeId(const CommandLineFlag& flag);
+
+  // Access to CommandLineFlag::SaveState.
+  static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag& flag);
+
+  // Access to CommandLineFlag::IsSpecifiedOnCommandLine.
+  static bool IsSpecifiedOnCommandLine(const CommandLineFlag& flag);
+
+  // Access to CommandLineFlag::ValidateInputValue.
+  static bool ValidateInputValue(const CommandLineFlag& flag,
+                                 absl::string_view value);
+
+  // Access to CommandLineFlag::CheckDefaultValueParsingRoundtrip.
+  static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag);
+
+  static bool ParseFrom(CommandLineFlag& flag, absl::string_view value,
+                        flags_internal::FlagSettingMode set_mode,
+                        flags_internal::ValueSource source, std::string& error);
+};
+
+}  // namespace flags_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
diff --git a/absl/flags/internal/program_name.cc b/absl/flags/internal/program_name.cc
index f0811f1..51d698d 100644
--- a/absl/flags/internal/program_name.cc
+++ b/absl/flags/internal/program_name.cc
@@ -17,10 +17,16 @@
 
 #include <string>
 
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/const_init.h"
+#include "absl/base/thread_annotations.h"
 #include "absl/flags/internal/path_util.h"
+#include "absl/strings/string_view.h"
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 ABSL_CONST_INIT static absl::Mutex program_name_guard(absl::kConstInit);
@@ -50,4 +56,5 @@
 }
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/program_name.h b/absl/flags/internal/program_name.h
index 326f24b..b99b94f 100644
--- a/absl/flags/internal/program_name.h
+++ b/absl/flags/internal/program_name.h
@@ -18,12 +18,14 @@
 
 #include <string>
 
+#include "absl/base/config.h"
 #include "absl/strings/string_view.h"
 
 // --------------------------------------------------------------------
 // Program name
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 // Returns program invocation name or "UNKNOWN" if `SetProgramInvocationName()`
@@ -42,6 +44,7 @@
 void SetProgramInvocationName(absl::string_view prog_name_str);
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_
diff --git a/absl/flags/internal/program_name_test.cc b/absl/flags/internal/program_name_test.cc
index ed69218..aff9f63 100644
--- a/absl/flags/internal/program_name_test.cc
+++ b/absl/flags/internal/program_name_test.cc
@@ -15,14 +15,17 @@
 
 #include "absl/flags/internal/program_name.h"
 
+#include <string>
+
 #include "gtest/gtest.h"
 #include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
 
 namespace {
 
 namespace flags = absl::flags_internal;
 
-TEST(FlagsPathUtilTest, TestInitialProgamName) {
+TEST(FlagsPathUtilTest, TestProgamNameInterfaces) {
   flags::SetProgramInvocationName("absl/flags/program_name_test");
   std::string program_name = flags::ProgramInvocationName();
   for (char& c : program_name)
@@ -40,9 +43,7 @@
 
   EXPECT_TRUE(absl::EndsWith(program_name, expect_name)) << program_name;
   EXPECT_EQ(flags::ShortProgramInvocationName(), expect_basename);
-}
 
-TEST(FlagsPathUtilTest, TestProgamNameInterfaces) {
   flags::SetProgramInvocationName("a/my_test");
 
   EXPECT_EQ(flags::ProgramInvocationName(), "a/my_test");
diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc
deleted file mode 100644
index 4bea313..0000000
--- a/absl/flags/internal/registry.cc
+++ /dev/null
@@ -1,404 +0,0 @@
-//
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/flags/internal/registry.h"
-
-#include "absl/base/dynamic_annotations.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/flags/config.h"
-#include "absl/flags/usage_config.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
-#include "absl/synchronization/mutex.h"
-
-// --------------------------------------------------------------------
-// FlagRegistry implementation
-//    A FlagRegistry holds all flag objects indexed
-//    by their names so that if you know a flag's name you can access or
-//    set it.
-
-namespace absl {
-namespace flags_internal {
-
-// --------------------------------------------------------------------
-// FlagRegistry
-//    A FlagRegistry singleton object holds all flag objects indexed
-//    by their names so that if you know a flag's name (as a C
-//    string), you can access or set it.  If the function is named
-//    FooLocked(), you must own the registry lock before calling
-//    the function; otherwise, you should *not* hold the lock, and
-//    the function will acquire it itself if needed.
-// --------------------------------------------------------------------
-
-class FlagRegistry {
- public:
-  FlagRegistry() = default;
-  ~FlagRegistry() {
-    for (auto& p : flags_) {
-      p.second->Destroy();
-    }
-  }
-
-  // Store a flag in this registry.  Takes ownership of *flag.
-  void RegisterFlag(CommandLineFlag* flag);
-
-  void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); }
-  void Unlock() ABSL_UNLOCK_FUNCTION(lock_) { lock_.Unlock(); }
-
-  // Returns the flag object for the specified name, or nullptr if not found.
-  // Will emit a warning if a 'retired' flag is specified.
-  CommandLineFlag* FindFlagLocked(absl::string_view name);
-
-  // Returns the retired flag object for the specified name, or nullptr if not
-  // found or not retired.  Does not emit a warning.
-  CommandLineFlag* FindRetiredFlagLocked(absl::string_view name);
-
-  static FlagRegistry* GlobalRegistry();  // returns a singleton registry
-
- private:
-  friend class FlagSaverImpl;  // reads all the flags in order to copy them
-  friend void ForEachFlagUnlocked(
-      std::function<void(CommandLineFlag*)> visitor);
-
-  // The map from name to flag, for FindFlagLocked().
-  using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
-  using FlagIterator = FlagMap::iterator;
-  using FlagConstIterator = FlagMap::const_iterator;
-  FlagMap flags_;
-
-  absl::Mutex lock_;
-
-  // Disallow
-  FlagRegistry(const FlagRegistry&);
-  FlagRegistry& operator=(const FlagRegistry&);
-};
-
-FlagRegistry* FlagRegistry::GlobalRegistry() {
-  static FlagRegistry* global_registry = new FlagRegistry;
-  return global_registry;
-}
-
-namespace {
-
-class FlagRegistryLock {
- public:
-  explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
-  ~FlagRegistryLock() { fr_->Unlock(); }
-
- private:
-  FlagRegistry* const fr_;
-};
-
-}  // namespace
-
-void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
-  FlagRegistryLock registry_lock(this);
-  std::pair<FlagIterator, bool> ins =
-      flags_.insert(FlagMap::value_type(flag->Name(), flag));
-  if (ins.second == false) {  // means the name was already in the map
-    CommandLineFlag* old_flag = ins.first->second;
-    if (flag->IsRetired() != old_flag->IsRetired()) {
-      // All registrations must agree on the 'retired' flag.
-      flags_internal::ReportUsageError(
-          absl::StrCat(
-              "Retired flag '", flag->Name(),
-              "' was defined normally in file '",
-              (flag->IsRetired() ? old_flag->Filename() : flag->Filename()),
-              "'."),
-          true);
-    } else if (flag->op_ != old_flag->op_) {
-      flags_internal::ReportUsageError(
-          absl::StrCat("Flag '", flag->Name(),
-                       "' was defined more than once but with "
-                       "differing types. Defined in files '",
-                       old_flag->Filename(), "' and '", flag->Filename(),
-                       "' with types '", old_flag->Typename(), "' and '",
-                       flag->Typename(), "', respectively."),
-          true);
-    } else if (old_flag->IsRetired()) {
-      // Retired definitions are idempotent. Just keep the old one.
-      flag->Destroy();
-      return;
-    } else if (old_flag->Filename() != flag->Filename()) {
-      flags_internal::ReportUsageError(
-          absl::StrCat("Flag '", flag->Name(),
-                       "' was defined more than once (in files '",
-                       old_flag->Filename(), "' and '", flag->Filename(),
-                       "')."),
-          true);
-    } else {
-      flags_internal::ReportUsageError(
-          absl::StrCat(
-              "Something wrong with flag '", flag->Name(), "' in file '",
-              flag->Filename(), "'. One possibility: file '", flag->Filename(),
-              "' is being linked both statically and dynamically into this "
-              "executable. e.g. some files listed as srcs to a test and also "
-              "listed as srcs of some shared lib deps of the same test."),
-          true);
-    }
-    // All cases above are fatal, except for the retired flags.
-    std::exit(1);
-  }
-}
-
-CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) {
-  FlagConstIterator i = flags_.find(name);
-  if (i == flags_.end()) {
-    return nullptr;
-  }
-
-  if (i->second->IsRetired()) {
-    flags_internal::ReportUsageError(
-        absl::StrCat("Accessing retired flag '", name, "'"), false);
-  }
-
-  return i->second;
-}
-
-CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) {
-  FlagConstIterator i = flags_.find(name);
-  if (i == flags_.end() || !i->second->IsRetired()) {
-    return nullptr;
-  }
-
-  return i->second;
-}
-
-// --------------------------------------------------------------------
-// FlagSaver
-// FlagSaverImpl
-//    This class stores the states of all flags at construct time,
-//    and restores all flags to that state at destruct time.
-//    Its major implementation challenge is that it never modifies
-//    pointers in the 'main' registry, so global FLAG_* vars always
-//    point to the right place.
-// --------------------------------------------------------------------
-
-class FlagSaverImpl {
- public:
-  // Constructs an empty FlagSaverImpl object.
-  FlagSaverImpl() {}
-  ~FlagSaverImpl() {
-    // reclaim memory from each of our CommandLineFlags
-    for (const SavedFlag& src : backup_registry_) {
-      Delete(src.op, src.current);
-      Delete(src.op, src.default_value);
-    }
-  }
-
-  // Saves the flag states from the flag registry into this object.
-  // It's an error to call this more than once.
-  // Must be called when the registry mutex is not held.
-  void SaveFromRegistry() {
-    assert(backup_registry_.empty());  // call only once!
-    SavedFlag saved;
-    flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) {
-      if (flag->IsRetired()) return;
-
-      saved.name = flag->Name();
-      saved.op = flag->op_;
-      saved.marshalling_op = flag->marshalling_op_;
-      {
-        absl::MutexLock l(flag->InitFlagIfNecessary());
-        saved.validator = flag->GetValidator();
-        saved.modified = flag->modified_;
-        saved.on_command_line = flag->on_command_line_;
-        saved.current = Clone(saved.op, flag->cur_);
-        saved.default_value = Clone(saved.op, flag->def_);
-        saved.counter = flag->counter_;
-      }
-      backup_registry_.push_back(saved);
-    });
-  }
-
-  // Restores the saved flag states into the flag registry.  We
-  // assume no flags were added or deleted from the registry since
-  // the SaveFromRegistry; if they were, that's trouble!  Must be
-  // called when the registry mutex is not held.
-  void RestoreToRegistry() {
-    FlagRegistry* const global_registry = FlagRegistry::GlobalRegistry();
-    FlagRegistryLock frl(global_registry);
-    for (const SavedFlag& src : backup_registry_) {
-      CommandLineFlag* flag = global_registry->FindFlagLocked(src.name);
-      // If null, flag got deleted from registry.
-      if (!flag) continue;
-
-      bool restored = false;
-      {
-        // This function encapsulate the lock.
-        flag->SetValidator(src.validator);
-
-        absl::MutexLock l(flag->InitFlagIfNecessary());
-        flag->modified_ = src.modified;
-        flag->on_command_line_ = src.on_command_line;
-        if (flag->counter_ != src.counter ||
-            ChangedDirectly(flag, src.default_value, flag->def_)) {
-          restored = true;
-          Copy(src.op, src.default_value, flag->def_);
-        }
-        if (flag->counter_ != src.counter ||
-            ChangedDirectly(flag, src.current, flag->cur_)) {
-          restored = true;
-          Copy(src.op, src.current, flag->cur_);
-          UpdateCopy(flag);
-          flag->InvokeCallback();
-        }
-      }
-
-      if (restored) {
-        flag->counter_++;
-
-        // Revalidate the flag because the validator might store state based
-        // on the flag's value, which just changed due to the restore.
-        // Failing validation is ignored because it's assumed that the flag
-        // was valid previously and there's little that can be done about it
-        // here, anyway.
-        flag->ValidateInputValue(flag->CurrentValue());
-
-        ABSL_INTERNAL_LOG(
-            INFO, absl::StrCat("Restore saved value of ", flag->Name(), ": ",
-                               Unparse(src.marshalling_op, src.current)));
-      }
-    }
-  }
-
- private:
-  struct SavedFlag {
-    absl::string_view name;
-    FlagOpFn op;
-    FlagMarshallingOpFn marshalling_op;
-    int64_t counter;
-    void* validator;
-    bool modified;
-    bool on_command_line;
-    const void* current;        // nullptr after restore
-    const void* default_value;  // nullptr after restore
-  };
-
-  std::vector<SavedFlag> backup_registry_;
-
-  FlagSaverImpl(const FlagSaverImpl&);  // no copying!
-  void operator=(const FlagSaverImpl&);
-};
-
-FlagSaver::FlagSaver() : impl_(new FlagSaverImpl()) {
-  impl_->SaveFromRegistry();
-}
-
-void FlagSaver::Ignore() {
-  delete impl_;
-  impl_ = nullptr;
-}
-
-FlagSaver::~FlagSaver() {
-  if (!impl_) return;
-
-  impl_->RestoreToRegistry();
-  delete impl_;
-}
-
-// --------------------------------------------------------------------
-
-CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
-  if (name.empty()) return nullptr;
-  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
-  FlagRegistryLock frl(registry);
-
-  return registry->FindFlagLocked(name);
-}
-
-CommandLineFlag* FindRetiredFlag(absl::string_view name) {
-  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
-  FlagRegistryLock frl(registry);
-
-  return registry->FindRetiredFlagLocked(name);
-}
-
-// --------------------------------------------------------------------
-
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor) {
-  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
-  for (FlagRegistry::FlagConstIterator i = registry->flags_.begin();
-       i != registry->flags_.end(); ++i) {
-    visitor(i->second);
-  }
-}
-
-void ForEachFlag(std::function<void(CommandLineFlag*)> visitor) {
-  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
-  FlagRegistryLock frl(registry);
-  ForEachFlagUnlocked(visitor);
-}
-
-// --------------------------------------------------------------------
-
-bool RegisterCommandLineFlag(CommandLineFlag* flag) {
-  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
-  return true;
-}
-
-// --------------------------------------------------------------------
-
-namespace {
-
-class RetiredFlagObj final : public flags_internal::CommandLineFlag {
- public:
-  constexpr RetiredFlagObj(const char* name, FlagOpFn ops,
-                           FlagMarshallingOpFn marshalling_ops)
-      : flags_internal::CommandLineFlag(
-            name, flags_internal::HelpText::FromStaticCString(nullptr),
-            /*filename=*/"RETIRED", ops, marshalling_ops,
-            /*initial_value_gen=*/nullptr,
-            /*def=*/nullptr,
-            /*cur=*/nullptr) {}
-
- private:
-  bool IsRetired() const override { return true; }
-
-  void Destroy() const override {
-    // Values are heap allocated for Retired Flags.
-    if (cur_) Delete(op_, cur_);
-    if (def_) Delete(op_, def_);
-
-    if (locks_) delete locks_;
-
-    delete this;
-  }
-};
-
-}  // namespace
-
-bool Retire(const char* name, FlagOpFn ops,
-            FlagMarshallingOpFn marshalling_ops) {
-  auto* flag = new flags_internal::RetiredFlagObj(name, ops, marshalling_ops);
-  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
-  return true;
-}
-
-// --------------------------------------------------------------------
-
-bool IsRetiredFlag(absl::string_view name, bool* type_is_bool) {
-  assert(!name.empty());
-  CommandLineFlag* flag = flags_internal::FindRetiredFlag(name);
-  if (flag == nullptr) {
-    return false;
-  }
-  assert(type_is_bool);
-  *type_is_bool = flag->IsOfType<bool>();
-  return true;
-}
-
-}  // namespace flags_internal
-}  // namespace absl
diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h
index eb134a9..a8d9eb9 100644
--- a/absl/flags/internal/registry.h
+++ b/absl/flags/internal/registry.h
@@ -17,31 +17,28 @@
 #define ABSL_FLAGS_INTERNAL_REGISTRY_H_
 
 #include <functional>
-#include <map>
-#include <string>
 
-#include "absl/base/macros.h"
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
 #include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
 
 // --------------------------------------------------------------------
 // Global flags registry API.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-CommandLineFlag* FindCommandLineFlag(absl::string_view name);
-CommandLineFlag* FindRetiredFlag(absl::string_view name);
-
-// Executes specified visitor for each non-retired flag in the registry.
-// Requires the caller hold the registry lock.
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor);
 // Executes specified visitor for each non-retired flag in the registry. While
 // callback are executed, the registry is locked and can't be changed.
-void ForEachFlag(std::function<void(CommandLineFlag*)> visitor);
+void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
 
 //-----------------------------------------------------------------------------
 
-bool RegisterCommandLineFlag(CommandLineFlag*);
+bool RegisterCommandLineFlag(CommandLineFlag&);
+
+void FinalizeRegistry();
 
 //-----------------------------------------------------------------------------
 // Retired registrations:
@@ -76,47 +73,25 @@
 //
 
 // Retire flag with name "name" and type indicated by ops.
-bool Retire(const char* name, FlagOpFn ops,
-            FlagMarshallingOpFn marshalling_ops);
+void Retire(const char* name, FlagFastTypeId type_id, char* buf);
+
+constexpr size_t kRetiredFlagObjSize = 3 * sizeof(void*);
+constexpr size_t kRetiredFlagObjAlignment = alignof(void*);
 
 // Registered a retired flag with name 'flag_name' and type 'T'.
 template <typename T>
-inline bool RetiredFlag(const char* flag_name) {
-  return flags_internal::Retire(flag_name, flags_internal::FlagOps<T>,
-                                flags_internal::FlagMarshallingOps<T>);
-}
-
-// If the flag is retired, returns true and indicates in |*type_is_bool|
-// whether the type of the retired flag is a bool.
-// Only to be called by code that needs to explicitly ignore retired flags.
-bool IsRetiredFlag(absl::string_view name, bool* type_is_bool);
-
-//-----------------------------------------------------------------------------
-// Saves the states (value, default value, whether the user has set
-// the flag, registered validators, etc) of all flags, and restores
-// them when the FlagSaver is destroyed.
-//
-// This class is thread-safe.  However, its destructor writes to
-// exactly the set of flags that have changed value during its
-// lifetime, so concurrent _direct_ access to those flags
-// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe.
-
-class FlagSaver {
+class RetiredFlag {
  public:
-  FlagSaver();
-  ~FlagSaver();
-
-  FlagSaver(const FlagSaver&) = delete;
-  void operator=(const FlagSaver&) = delete;
-
-  // Prevents saver from restoring the saved state of flags.
-  void Ignore();
+  void Retire(const char* flag_name) {
+    flags_internal::Retire(flag_name, base_internal::FastTypeId<T>(), buf_);
+  }
 
  private:
-  class FlagSaverImpl* impl_;  // we use pimpl here to keep API steady
+  alignas(kRetiredFlagObjAlignment) char buf_[kRetiredFlagObjSize];
 };
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_REGISTRY_H_
diff --git a/absl/flags/internal/sequence_lock.h b/absl/flags/internal/sequence_lock.h
new file mode 100644
index 0000000..807b2a7
--- /dev/null
+++ b/absl/flags/internal/sequence_lock.h
@@ -0,0 +1,187 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
+#define ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+#include <cassert>
+#include <cstring>
+
+#include "absl/base/optimization.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// Align 'x' up to the nearest 'align' bytes.
+inline constexpr size_t AlignUp(size_t x, size_t align) {
+  return align * ((x + align - 1) / align);
+}
+
+// A SequenceLock implements lock-free reads. A sequence counter is incremented
+// before and after each write, and readers access the counter before and after
+// accessing the protected data. If the counter is verified to not change during
+// the access, and the sequence counter value was even, then the reader knows
+// that the read was race-free and valid. Otherwise, the reader must fall back
+// to a Mutex-based code path.
+//
+// This particular SequenceLock starts in an "uninitialized" state in which
+// TryRead() returns false. It must be enabled by calling MarkInitialized().
+// This serves as a marker that the associated flag value has not yet been
+// initialized and a slow path needs to be taken.
+//
+// The memory reads and writes protected by this lock must use the provided
+// `TryRead()` and `Write()` functions. These functions behave similarly to
+// `memcpy()`, with one oddity: the protected data must be an array of
+// `std::atomic<int64>`. This is to comply with the C++ standard, which
+// considers data races on non-atomic objects to be undefined behavior. See "Can
+// Seqlocks Get Along With Programming Language Memory Models?"[1] by Hans J.
+// Boehm for more details.
+//
+// [1] https://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf
+class SequenceLock {
+ public:
+  constexpr SequenceLock() : lock_(kUninitialized) {}
+
+  // Mark that this lock is ready for use.
+  void MarkInitialized() {
+    assert(lock_.load(std::memory_order_relaxed) == kUninitialized);
+    lock_.store(0, std::memory_order_release);
+  }
+
+  // Copy "size" bytes of data from "src" to "dst", protected as a read-side
+  // critical section of the sequence lock.
+  //
+  // Unlike traditional sequence lock implementations which loop until getting a
+  // clean read, this implementation returns false in the case of concurrent
+  // calls to `Write`. In such a case, the caller should fall back to a
+  // locking-based slow path.
+  //
+  // Returns false if the sequence lock was not yet marked as initialized.
+  //
+  // NOTE: If this returns false, "dst" may be overwritten with undefined
+  // (potentially uninitialized) data.
+  bool TryRead(void* dst, const std::atomic<uint64_t>* src, size_t size) const {
+    // Acquire barrier ensures that no loads done by f() are reordered
+    // above the first load of the sequence counter.
+    int64_t seq_before = lock_.load(std::memory_order_acquire);
+    if (ABSL_PREDICT_FALSE(seq_before & 1) == 1) return false;
+    RelaxedCopyFromAtomic(dst, src, size);
+    // Another acquire fence ensures that the load of 'lock_' below is
+    // strictly ordered after the RelaxedCopyToAtomic call above.
+    std::atomic_thread_fence(std::memory_order_acquire);
+    int64_t seq_after = lock_.load(std::memory_order_relaxed);
+    return ABSL_PREDICT_TRUE(seq_before == seq_after);
+  }
+
+  // Copy "size" bytes from "src" to "dst" as a write-side critical section
+  // of the sequence lock. Any concurrent readers will be forced to retry
+  // until they get a read that does not conflict with this write.
+  //
+  // This call must be externally synchronized against other calls to Write,
+  // but may proceed concurrently with reads.
+  void Write(std::atomic<uint64_t>* dst, const void* src, size_t size) {
+    // We can use relaxed instructions to increment the counter since we
+    // are extenally synchronized. The std::atomic_thread_fence below
+    // ensures that the counter updates don't get interleaved with the
+    // copy to the data.
+    int64_t orig_seq = lock_.load(std::memory_order_relaxed);
+    assert((orig_seq & 1) == 0);  // Must be initially unlocked.
+    lock_.store(orig_seq + 1, std::memory_order_relaxed);
+
+    // We put a release fence between update to lock_ and writes to shared data.
+    // Thus all stores to shared data are effectively release operations and
+    // update to lock_ above cannot be re-ordered past any of them. Note that
+    // this barrier is not for the fetch_add above.  A release barrier for the
+    // fetch_add would be before it, not after.
+    std::atomic_thread_fence(std::memory_order_release);
+    RelaxedCopyToAtomic(dst, src, size);
+    // "Release" semantics ensure that none of the writes done by
+    // RelaxedCopyToAtomic() can be reordered after the following modification.
+    lock_.store(orig_seq + 2, std::memory_order_release);
+  }
+
+  // Return the number of times that Write() has been called.
+  //
+  // REQUIRES: This must be externally synchronized against concurrent calls to
+  // `Write()` or `IncrementModificationCount()`.
+  // REQUIRES: `MarkInitialized()` must have been previously called.
+  int64_t ModificationCount() const {
+    int64_t val = lock_.load(std::memory_order_relaxed);
+    assert(val != kUninitialized && (val & 1) == 0);
+    return val / 2;
+  }
+
+  // REQUIRES: This must be externally synchronized against concurrent calls to
+  // `Write()` or `ModificationCount()`.
+  // REQUIRES: `MarkInitialized()` must have been previously called.
+  void IncrementModificationCount() {
+    int64_t val = lock_.load(std::memory_order_relaxed);
+    assert(val != kUninitialized);
+    lock_.store(val + 2, std::memory_order_relaxed);
+  }
+
+ private:
+  // Perform the equivalent of "memcpy(dst, src, size)", but using relaxed
+  // atomics.
+  static void RelaxedCopyFromAtomic(void* dst, const std::atomic<uint64_t>* src,
+                                    size_t size) {
+    char* dst_byte = static_cast<char*>(dst);
+    while (size >= sizeof(uint64_t)) {
+      uint64_t word = src->load(std::memory_order_relaxed);
+      std::memcpy(dst_byte, &word, sizeof(word));
+      dst_byte += sizeof(word);
+      src++;
+      size -= sizeof(word);
+    }
+    if (size > 0) {
+      uint64_t word = src->load(std::memory_order_relaxed);
+      std::memcpy(dst_byte, &word, size);
+    }
+  }
+
+  // Perform the equivalent of "memcpy(dst, src, size)", but using relaxed
+  // atomics.
+  static void RelaxedCopyToAtomic(std::atomic<uint64_t>* dst, const void* src,
+                                  size_t size) {
+    const char* src_byte = static_cast<const char*>(src);
+    while (size >= sizeof(uint64_t)) {
+      uint64_t word;
+      std::memcpy(&word, src_byte, sizeof(word));
+      dst->store(word, std::memory_order_relaxed);
+      src_byte += sizeof(word);
+      dst++;
+      size -= sizeof(word);
+    }
+    if (size > 0) {
+      uint64_t word = 0;
+      std::memcpy(&word, src_byte, size);
+      dst->store(word, std::memory_order_relaxed);
+    }
+  }
+
+  static constexpr int64_t kUninitialized = -1;
+  std::atomic<int64_t> lock_;
+};
+
+}  // namespace flags_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
diff --git a/absl/flags/internal/sequence_lock_test.cc b/absl/flags/internal/sequence_lock_test.cc
new file mode 100644
index 0000000..9aff1ed
--- /dev/null
+++ b/absl/flags/internal/sequence_lock_test.cc
@@ -0,0 +1,146 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "absl/flags/internal/sequence_lock.h"
+
+#include <atomic>
+#include <thread>  // NOLINT(build/c++11)
+#include <tuple>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/sysinfo.h"
+#include "absl/container/fixed_array.h"
+#include "absl/time/clock.h"
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+class ConcurrentSequenceLockTest
+    : public testing::TestWithParam<std::tuple<int, int>> {
+ public:
+  ConcurrentSequenceLockTest()
+      : buf_bytes_(std::get<0>(GetParam())),
+        num_threads_(std::get<1>(GetParam())) {}
+
+ protected:
+  const int buf_bytes_;
+  const int num_threads_;
+};
+
+TEST_P(ConcurrentSequenceLockTest, ReadAndWrite) {
+  const int buf_words =
+      flags::AlignUp(buf_bytes_, sizeof(uint64_t)) / sizeof(uint64_t);
+
+  // The buffer that will be protected by the SequenceLock.
+  absl::FixedArray<std::atomic<uint64_t>> protected_buf(buf_words);
+  for (auto& v : protected_buf) v = -1;
+
+  flags::SequenceLock seq_lock;
+  std::atomic<bool> stop{false};
+  std::atomic<int64_t> bad_reads{0};
+  std::atomic<int64_t> good_reads{0};
+  std::atomic<int64_t> unsuccessful_reads{0};
+
+  // Start a bunch of threads which read 'protected_buf' under the sequence
+  // lock. The main thread will concurrently update 'protected_buf'. The updates
+  // always consist of an array of identical integers. The reader ensures that
+  // any data it reads matches that pattern (i.e. the reads are not "torn").
+  std::vector<std::thread> threads;
+  for (int i = 0; i < num_threads_; i++) {
+    threads.emplace_back([&]() {
+      absl::FixedArray<char> local_buf(buf_bytes_);
+      while (!stop.load(std::memory_order_relaxed)) {
+        if (seq_lock.TryRead(local_buf.data(), protected_buf.data(),
+                             buf_bytes_)) {
+          bool good = true;
+          for (const auto& v : local_buf) {
+            if (v != local_buf[0]) good = false;
+          }
+          if (good) {
+            good_reads.fetch_add(1, std::memory_order_relaxed);
+          } else {
+            bad_reads.fetch_add(1, std::memory_order_relaxed);
+          }
+        } else {
+          unsuccessful_reads.fetch_add(1, std::memory_order_relaxed);
+        }
+      }
+    });
+  }
+  while (unsuccessful_reads.load(std::memory_order_relaxed) < num_threads_) {
+    absl::SleepFor(absl::Milliseconds(1));
+  }
+  seq_lock.MarkInitialized();
+
+  // Run a maximum of 5 seconds. On Windows, the scheduler behavior seems
+  // somewhat unfair and without an explicit timeout for this loop, the tests
+  // can run a long time.
+  absl::Time deadline = absl::Now() + absl::Seconds(5);
+  for (int i = 0; i < 100 && absl::Now() < deadline; i++) {
+    absl::FixedArray<char> writer_buf(buf_bytes_);
+    for (auto& v : writer_buf) v = i;
+    seq_lock.Write(protected_buf.data(), writer_buf.data(), buf_bytes_);
+    absl::SleepFor(absl::Microseconds(10));
+  }
+  stop.store(true, std::memory_order_relaxed);
+  for (auto& t : threads) t.join();
+  ASSERT_GE(good_reads, 0);
+  ASSERT_EQ(bad_reads, 0);
+}
+
+// Simple helper for generating a range of thread counts.
+// Generates [low, low*scale, low*scale^2, ...high)
+// (even if high is between low*scale^k and low*scale^(k+1)).
+std::vector<int> MultiplicativeRange(int low, int high, int scale) {
+  std::vector<int> result;
+  for (int current = low; current < high; current *= scale) {
+    result.push_back(current);
+  }
+  result.push_back(high);
+  return result;
+}
+
+INSTANTIATE_TEST_SUITE_P(TestManyByteSizes, ConcurrentSequenceLockTest,
+                         testing::Combine(
+                             // Buffer size (bytes).
+                             testing::Range(1, 128),
+                             // Number of reader threads.
+                             testing::ValuesIn(MultiplicativeRange(
+                                 1, absl::base_internal::NumCPUs(), 2))));
+
+// Simple single-threaded test, parameterized by the size of the buffer to be
+// protected.
+class SequenceLockTest : public testing::TestWithParam<int> {};
+
+TEST_P(SequenceLockTest, SingleThreaded) {
+  const int size = GetParam();
+  absl::FixedArray<std::atomic<uint64_t>> protected_buf(
+      flags::AlignUp(size, sizeof(uint64_t)) / sizeof(uint64_t));
+
+  flags::SequenceLock seq_lock;
+  seq_lock.MarkInitialized();
+
+  std::vector<char> src_buf(size, 'x');
+  seq_lock.Write(protected_buf.data(), src_buf.data(), size);
+
+  std::vector<char> dst_buf(size, '0');
+  ASSERT_TRUE(seq_lock.TryRead(dst_buf.data(), protected_buf.data(), size));
+  ASSERT_EQ(src_buf, dst_buf);
+}
+INSTANTIATE_TEST_SUITE_P(TestManyByteSizes, SequenceLockTest,
+                         // Buffer size (bytes).
+                         testing::Range(1, 128));
+
+}  // namespace
diff --git a/absl/flags/internal/type_erased.cc b/absl/flags/internal/type_erased.cc
deleted file mode 100644
index a1650fc..0000000
--- a/absl/flags/internal/type_erased.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/flags/internal/type_erased.h"
-
-#include "absl/base/internal/raw_logging.h"
-#include "absl/flags/config.h"
-#include "absl/flags/usage_config.h"
-#include "absl/strings/str_cat.h"
-
-namespace absl {
-namespace flags_internal {
-
-bool GetCommandLineOption(absl::string_view name, std::string* value) {
-  if (name.empty()) return false;
-  assert(value);
-
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-  if (flag == nullptr || flag->IsRetired()) {
-    return false;
-  }
-
-  *value = flag->CurrentValue();
-  return true;
-}
-
-bool SetCommandLineOption(absl::string_view name, absl::string_view value) {
-  return SetCommandLineOptionWithMode(name, value,
-                                      flags_internal::SET_FLAGS_VALUE);
-}
-
-bool SetCommandLineOptionWithMode(absl::string_view name,
-                                  absl::string_view value,
-                                  FlagSettingMode set_mode) {
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-
-  if (!flag || flag->IsRetired()) return false;
-
-  std::string error;
-  if (!flag->SetFromString(value, set_mode, kProgrammaticChange, &error)) {
-    // Errors here are all of the form: the provided name was a recognized
-    // flag, but the value was invalid (bad type, or validation failed).
-    flags_internal::ReportUsageError(error, false);
-    return false;
-  }
-
-  return true;
-}
-
-// --------------------------------------------------------------------
-
-bool IsValidFlagValue(absl::string_view name, absl::string_view value) {
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-
-  return flag != nullptr &&
-         (flag->IsRetired() || flag->ValidateInputValue(value));
-}
-
-// --------------------------------------------------------------------
-
-bool SpecifiedOnCommandLine(absl::string_view name) {
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-  if (flag != nullptr && !flag->IsRetired()) {
-    return flag->IsSpecifiedOnCommandLine();
-  }
-  return false;
-}
-
-}  // namespace flags_internal
-}  // namespace absl
diff --git a/absl/flags/internal/type_erased.h b/absl/flags/internal/type_erased.h
deleted file mode 100644
index a955116..0000000
--- a/absl/flags/internal/type_erased.h
+++ /dev/null
@@ -1,86 +0,0 @@
-//
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
-#define ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
-
-#include <string>
-
-#include "absl/flags/internal/commandlineflag.h"
-#include "absl/flags/internal/registry.h"
-
-// --------------------------------------------------------------------
-// Registry interfaces operating on type erased handles.
-
-namespace absl {
-namespace flags_internal {
-
-// If a flag named "name" exists, store its current value in *OUTPUT
-// and return true.  Else return false without changing *OUTPUT.
-// Thread-safe.
-bool GetCommandLineOption(absl::string_view name, std::string* value);
-
-// Set the value of the flag named "name" to value.  If successful,
-// returns true.  If not successful (e.g., the flag was not found or
-// the value is not a valid value), returns false.
-// Thread-safe.
-bool SetCommandLineOption(absl::string_view name, absl::string_view value);
-
-bool SetCommandLineOptionWithMode(absl::string_view name,
-                                  absl::string_view value,
-                                  FlagSettingMode set_mode);
-
-//-----------------------------------------------------------------------------
-
-// Returns true iff all of the following conditions are true:
-// (a) "name" names a registered flag
-// (b) "value" can be parsed succesfully according to the type of the flag
-// (c) parsed value passes any validator associated with the flag
-bool IsValidFlagValue(absl::string_view name, absl::string_view value);
-
-//-----------------------------------------------------------------------------
-
-// Returns true iff a flag named "name" was specified on the command line
-// (either directly, or via one of --flagfile or --fromenv or --tryfromenv).
-//
-// Any non-command-line modification of the flag does not affect the
-// result of this function.  So for example, if a flag was passed on
-// the command line but then reset via SET_FLAGS_DEFAULT, this
-// function will still return true.
-bool SpecifiedOnCommandLine(absl::string_view name);
-
-//-----------------------------------------------------------------------------
-
-// If a flag with specified "name" exists and has type T, store
-// its current value in *dst and return true.  Else return false
-// without touching *dst.  T must obey all of the requirements for
-// types passed to DEFINE_FLAG.
-template <typename T>
-inline bool GetByName(absl::string_view name, T* dst) {
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-  if (!flag) return false;
-
-  if (auto val = flag->Get<T>()) {
-    *dst = *val;
-    return true;
-  }
-
-  return false;
-}
-
-}  // namespace flags_internal
-}  // namespace absl
-
-#endif  // ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
diff --git a/absl/flags/internal/type_erased_test.cc b/absl/flags/internal/type_erased_test.cc
deleted file mode 100644
index ac749a6..0000000
--- a/absl/flags/internal/type_erased_test.cc
+++ /dev/null
@@ -1,147 +0,0 @@
-//
-//  Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/flags/internal/type_erased.h"
-
-#include <cmath>
-
-#include "gtest/gtest.h"
-#include "absl/flags/flag.h"
-#include "absl/memory/memory.h"
-#include "absl/strings/str_cat.h"
-
-ABSL_FLAG(int, int_flag, 1, "int_flag help");
-ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
-ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
-
-namespace {
-
-namespace flags = absl::flags_internal;
-
-class TypeErasedTest : public testing::Test {
- protected:
-  void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); }
-  void TearDown() override { flag_saver_.reset(); }
-
- private:
-  std::unique_ptr<flags::FlagSaver> flag_saver_;
-};
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestGetCommandLineOption) {
-  std::string value;
-  EXPECT_TRUE(flags::GetCommandLineOption("int_flag", &value));
-  EXPECT_EQ(value, "1");
-
-  EXPECT_TRUE(flags::GetCommandLineOption("string_flag", &value));
-  EXPECT_EQ(value, "dflt");
-
-  EXPECT_FALSE(flags::GetCommandLineOption("bool_retired_flag", &value));
-
-  EXPECT_FALSE(flags::GetCommandLineOption("unknown_flag", &value));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOption) {
-  EXPECT_TRUE(flags::SetCommandLineOption("int_flag", "101"));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
-  EXPECT_TRUE(flags::SetCommandLineOption("string_flag", "asdfgh"));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
-  EXPECT_FALSE(flags::SetCommandLineOption("bool_retired_flag", "true"));
-
-  EXPECT_FALSE(flags::SetCommandLineOption("unknown_flag", "true"));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_VALUE) {
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
-                                                  flags::SET_FLAGS_VALUE));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
-                                                  flags::SET_FLAGS_VALUE));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
-                                                   flags::SET_FLAGS_VALUE));
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
-                                                   flags::SET_FLAGS_VALUE));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAG_IF_DEFAULT) {
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
-                                                  flags::SET_FLAG_IF_DEFAULT));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
-  // This semantic is broken. We return true instead of false. Value is not
-  // updated.
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202",
-                                                  flags::SET_FLAG_IF_DEFAULT));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
-                                                  flags::SET_FLAG_IF_DEFAULT));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
-                                                   flags::SET_FLAG_IF_DEFAULT));
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
-                                                   flags::SET_FLAG_IF_DEFAULT));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_DEFAULT) {
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
-                                                  flags::SET_FLAGS_DEFAULT));
-
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
-                                                  flags::SET_FLAGS_DEFAULT));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
-                                                   flags::SET_FLAGS_DEFAULT));
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
-                                                   flags::SET_FLAGS_DEFAULT));
-
-  // This should be successfull, since flag is still is not set
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202",
-                                                  flags::SET_FLAG_IF_DEFAULT));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 202);
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestIsValidFlagValue) {
-  EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "57"));
-  EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "-101"));
-  EXPECT_FALSE(flags::IsValidFlagValue("int_flag", "1.1"));
-
-  EXPECT_TRUE(flags::IsValidFlagValue("string_flag", "#%^#%^$%DGHDG$W%adsf"));
-
-  EXPECT_TRUE(flags::IsValidFlagValue("bool_retired_flag", "true"));
-}
-
-}  // namespace
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
index 0304851..a588c7f 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -15,38 +15,48 @@
 
 #include "absl/flags/internal/usage.h"
 
-#include <map>
-#include <string>
+#include <stdint.h>
 
+#include <functional>
+#include <map>
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
 #include "absl/flags/flag.h"
+#include "absl/flags/internal/flag.h"
 #include "absl/flags/internal/path_util.h"
+#include "absl/flags/internal/private_handle_accessor.h"
 #include "absl/flags/internal/program_name.h"
+#include "absl/flags/internal/registry.h"
 #include "absl/flags/usage_config.h"
-#include "absl/strings/ascii.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
-#include "absl/synchronization/mutex.h"
 
-ABSL_FLAG(bool, help, false,
-          "show help on important flags for this binary [tip: all flags can "
-          "have two dashes]");
-ABSL_FLAG(bool, helpfull, false, "show help on all flags");
-ABSL_FLAG(bool, helpshort, false,
-          "show help on only the main module for this program");
-ABSL_FLAG(bool, helppackage, false,
-          "show help on all modules in the main package");
-ABSL_FLAG(bool, version, false, "show version and build info and exit");
-ABSL_FLAG(bool, only_check_args, false, "exit after checking all flags");
-ABSL_FLAG(std::string, helpon, "",
-          "show help on the modules named by this flag value");
-ABSL_FLAG(std::string, helpmatch, "",
-          "show help on modules whose name contains the specified substr");
+// Dummy global variables to prevent anyone else defining these.
+bool FLAGS_help = false;
+bool FLAGS_helpfull = false;
+bool FLAGS_helpshort = false;
+bool FLAGS_helppackage = false;
+bool FLAGS_version = false;
+bool FLAGS_only_check_args = false;
+bool FLAGS_helpon = false;
+bool FLAGS_helpmatch = false;
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 namespace {
 
+using PerFlagFilter = std::function<bool(const absl::CommandLineFlag&)>;
+
+// Maximum length size in a human readable format.
+constexpr size_t kHrfMaxLineLength = 80;
+
 // This class is used to emit an XML element with `tag` and `text`.
 // It adds opening and closing tags and escapes special characters in the text.
 // For example:
@@ -99,21 +109,24 @@
  public:
   // Pretty printer holds on to the std::ostream& reference to direct an output
   // to that stream.
-  FlagHelpPrettyPrinter(int max_line_len, std::ostream* out)
-      : out_(*out),
+  FlagHelpPrettyPrinter(size_t max_line_len, size_t min_line_len,
+                        size_t wrapped_line_indent, std::ostream& out)
+      : out_(out),
         max_line_len_(max_line_len),
+        min_line_len_(min_line_len),
+        wrapped_line_indent_(wrapped_line_indent),
         line_len_(0),
         first_line_(true) {}
 
   void Write(absl::string_view str, bool wrap_line = false) {
-    // Empty std::string - do nothing.
+    // Empty string - do nothing.
     if (str.empty()) return;
 
     std::vector<absl::string_view> tokens;
     if (wrap_line) {
       for (auto line : absl::StrSplit(str, absl::ByAnyChar("\n\r"))) {
         if (!tokens.empty()) {
-          // Keep line separators in the input std::string.
+          // Keep line separators in the input string.
           tokens.push_back("\n");
         }
         for (auto token :
@@ -128,14 +141,15 @@
     for (auto token : tokens) {
       bool new_line = (line_len_ == 0);
 
-      // Respect line separators in the input std::string.
+      // Respect line separators in the input string.
       if (token == "\n") {
         EndLine();
         continue;
       }
 
-      // Write the token, ending the std::string first if necessary/possible.
-      if (!new_line && (line_len_ + token.size() >= max_line_len_)) {
+      // Write the token, ending the string first if necessary/possible.
+      if (!new_line &&
+          (line_len_ + static_cast<int>(token.size()) >= max_line_len_)) {
         EndLine();
         new_line = true;
       }
@@ -154,13 +168,12 @@
 
   void StartLine() {
     if (first_line_) {
-      out_ << "    ";
-      line_len_ = 4;
+      line_len_ = min_line_len_;
       first_line_ = false;
     } else {
-      out_ << "      ";
-      line_len_ = 6;
+      line_len_ = min_line_len_ + wrapped_line_indent_;
     }
+    out_ << std::string(line_len_, ' ');
   }
   void EndLine() {
     out_ << '\n';
@@ -169,38 +182,36 @@
 
  private:
   std::ostream& out_;
-  const int max_line_len_;
-  int line_len_;
+  const size_t max_line_len_;
+  const size_t min_line_len_;
+  const size_t wrapped_line_indent_;
+  size_t line_len_;
   bool first_line_;
 };
 
-void FlagHelpHumanReadable(const flags_internal::CommandLineFlag& flag,
-                           std::ostream* out) {
-  FlagHelpPrettyPrinter printer(80, out);  // Max line length is 80.
+void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
+  FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 4, 2, out);
 
   // Flag name.
-  printer.Write(absl::StrCat("-", flag.Name()));
+  printer.Write(absl::StrCat("--", flag.Name()));
 
   // Flag help.
   printer.Write(absl::StrCat("(", flag.Help(), ");"), /*wrap_line=*/true);
 
-  // Flag data type (for V1 flags only).
-  if (!flag.IsAbseilFlag() && !flag.IsRetired()) {
-    printer.Write(absl::StrCat("type: ", flag.Typename(), ";"));
-  }
-
   // The listed default value will be the actual default from the flag
   // definition in the originating source file, unless the value has
   // subsequently been modified using SetCommandLineOption() with mode
   // SET_FLAGS_DEFAULT.
   std::string dflt_val = flag.DefaultValue();
+  std::string curr_val = flag.CurrentValue();
+  bool is_modified = curr_val != dflt_val;
+
   if (flag.IsOfType<std::string>()) {
     dflt_val = absl::StrCat("\"", dflt_val, "\"");
   }
   printer.Write(absl::StrCat("default: ", dflt_val, ";"));
 
-  if (flag.IsModified()) {
-    std::string curr_val = flag.CurrentValue();
+  if (is_modified) {
     if (flag.IsOfType<std::string>()) {
       curr_val = absl::StrCat("\"", curr_val, "\"");
     }
@@ -215,7 +226,7 @@
 // If a flag's help message has been stripped (e.g. by adding '#define
 // STRIP_FLAG_HELP 1' then this flag will not be displayed by '--help'
 // and its variants.
-void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
+void FlagsHelpImpl(std::ostream& out, PerFlagFilter filter_cb,
                    HelpFormat format, absl::string_view program_usage_message) {
   if (format == HelpFormat::kHumanReadable) {
     out << flags_internal::ShortProgramInvocationName() << ": "
@@ -223,6 +234,9 @@
   } else {
     // XML schema is not a part of our public API for now.
     out << "<?xml version=\"1.0\"?>\n"
+        << "<!-- This output should be used with care. We do not report type "
+           "names for flags with user defined types -->\n"
+        << "<!-- Prefer flag only_check_args for validating flag inputs -->\n"
         // The document.
         << "<AllFlags>\n"
         // The program name and usage.
@@ -237,30 +251,28 @@
   // This map is used to output matching flags grouped by package and file
   // name.
   std::map<std::string,
-           std::map<std::string,
-                    std::vector<const flags_internal::CommandLineFlag*>>>
+           std::map<std::string, std::vector<const absl::CommandLineFlag*>>>
       matching_flags;
 
-  flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) {
-    std::string flag_filename = flag->Filename();
-
+  flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) {
     // Ignore retired flags.
-    if (flag->IsRetired()) return;
+    if (flag.IsRetired()) return;
 
     // If the flag has been stripped, pretend that it doesn't exist.
-    if (flag->Help() == flags_internal::kStrippedFlagHelp) return;
+    if (flag.Help() == flags_internal::kStrippedFlagHelp) return;
 
     // Make sure flag satisfies the filter
-    if (!filter_cb || !filter_cb(flag_filename)) return;
+    if (!filter_cb(flag)) return;
+
+    std::string flag_filename = flag.Filename();
 
     matching_flags[std::string(flags_internal::Package(flag_filename))]
                   [flag_filename]
-                      .push_back(flag);
+                      .push_back(&flag);
   });
 
-  absl::string_view
-      package_separator;             // controls blank lines between packages.
-  absl::string_view file_separator;  // controls blank lines between files.
+  absl::string_view package_separator;  // controls blank lines between packages
+  absl::string_view file_separator;     // controls blank lines between files
   for (const auto& package : matching_flags) {
     if (format == HelpFormat::kHumanReadable) {
       out << package_separator;
@@ -282,27 +294,46 @@
   }
 
   if (format == HelpFormat::kHumanReadable) {
+    FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 0, 0, out);
+
     if (filter_cb && matching_flags.empty()) {
-      out << "  No modules matched: use -helpfull\n";
+      printer.Write("No flags matched.\n", true);
     }
+    printer.EndLine();
+    printer.Write(
+        "Try --helpfull to get a list of all flags or --help=substring "
+        "shows help for flags which include specified substring in either "
+        "in the name, or description or path.\n",
+        true);
   } else {
     // The end of the document.
     out << "</AllFlags>\n";
   }
 }
 
+void FlagsHelpImpl(std::ostream& out,
+                   flags_internal::FlagKindFilter filename_filter_cb,
+                   HelpFormat format, absl::string_view program_usage_message) {
+  FlagsHelpImpl(
+      out,
+      [&](const absl::CommandLineFlag& flag) {
+        return filename_filter_cb && filename_filter_cb(flag.Filename());
+      },
+      format, program_usage_message);
+}
+
 }  // namespace
 
 // --------------------------------------------------------------------
 // Produces the help message describing specific flag.
-void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag,
+void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
               HelpFormat format) {
   if (format == HelpFormat::kHumanReadable)
-    flags_internal::FlagHelpHumanReadable(flag, &out);
+    flags_internal::FlagHelpHumanReadable(flag, out);
 }
 
 // --------------------------------------------------------------------
-// Produces the help messages for all flags matching the filter.
+// Produces the help messages for all flags matching the filename filter.
 // If filter is empty produces help messages for all flags.
 void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,
                absl::string_view program_usage_message) {
@@ -317,67 +348,171 @@
 // If so, handles them appropriately.
 int HandleUsageFlags(std::ostream& out,
                      absl::string_view program_usage_message) {
-  if (absl::GetFlag(FLAGS_helpshort)) {
-    flags_internal::FlagsHelpImpl(
-        out, flags_internal::GetUsageConfig().contains_helpshort_flags,
-        HelpFormat::kHumanReadable, program_usage_message);
-    return 1;
-  }
+  switch (GetFlagsHelpMode()) {
+    case HelpMode::kNone:
+      break;
+    case HelpMode::kImportant:
+      flags_internal::FlagsHelpImpl(
+          out, flags_internal::GetUsageConfig().contains_help_flags,
+          GetFlagsHelpFormat(), program_usage_message);
+      return 1;
 
-  if (absl::GetFlag(FLAGS_helpfull)) {
-    // show all options
-    flags_internal::FlagsHelp(out, "", HelpFormat::kHumanReadable,
-                              program_usage_message);
-    return 1;
-  }
+    case HelpMode::kShort:
+      flags_internal::FlagsHelpImpl(
+          out, flags_internal::GetUsageConfig().contains_helpshort_flags,
+          GetFlagsHelpFormat(), program_usage_message);
+      return 1;
 
-  if (!absl::GetFlag(FLAGS_helpon).empty()) {
-    flags_internal::FlagsHelp(
-        out, absl::StrCat("/", absl::GetFlag(FLAGS_helpon), "."),
-        HelpFormat::kHumanReadable, program_usage_message);
-    return 1;
-  }
+    case HelpMode::kFull:
+      flags_internal::FlagsHelp(out, "", GetFlagsHelpFormat(),
+                                program_usage_message);
+      return 1;
 
-  if (!absl::GetFlag(FLAGS_helpmatch).empty()) {
-    flags_internal::FlagsHelp(out, absl::GetFlag(FLAGS_helpmatch),
-                              HelpFormat::kHumanReadable,
-                              program_usage_message);
-    return 1;
-  }
+    case HelpMode::kPackage:
+      flags_internal::FlagsHelpImpl(
+          out, flags_internal::GetUsageConfig().contains_helppackage_flags,
+          GetFlagsHelpFormat(), program_usage_message);
 
-  if (absl::GetFlag(FLAGS_help)) {
-    flags_internal::FlagsHelpImpl(
-        out, flags_internal::GetUsageConfig().contains_help_flags,
-        HelpFormat::kHumanReadable, program_usage_message);
+      return 1;
 
-    out << "\nTry --helpfull to get a list of all flags.\n";
+    case HelpMode::kMatch: {
+      std::string substr = GetFlagsHelpMatchSubstr();
+      if (substr.empty()) {
+        // show all options
+        flags_internal::FlagsHelp(out, substr, GetFlagsHelpFormat(),
+                                  program_usage_message);
+      } else {
+        auto filter_cb = [&substr](const absl::CommandLineFlag& flag) {
+          if (absl::StrContains(flag.Name(), substr)) return true;
+          if (absl::StrContains(flag.Filename(), substr)) return true;
+          if (absl::StrContains(flag.Help(), substr)) return true;
 
-    return 1;
-  }
+          return false;
+        };
+        flags_internal::FlagsHelpImpl(
+            out, filter_cb, HelpFormat::kHumanReadable, program_usage_message);
+      }
 
-  if (absl::GetFlag(FLAGS_helppackage)) {
-    flags_internal::FlagsHelpImpl(
-        out, flags_internal::GetUsageConfig().contains_helppackage_flags,
-        HelpFormat::kHumanReadable, program_usage_message);
+      return 1;
+    }
+    case HelpMode::kVersion:
+      if (flags_internal::GetUsageConfig().version_string)
+        out << flags_internal::GetUsageConfig().version_string();
+      // Unlike help, we may be asking for version in a script, so return 0
+      return 0;
 
-    out << "\nTry --helpfull to get a list of all flags.\n";
-
-    return 1;
-  }
-
-  if (absl::GetFlag(FLAGS_version)) {
-    if (flags_internal::GetUsageConfig().version_string)
-      out << flags_internal::GetUsageConfig().version_string();
-    // Unlike help, we may be asking for version in a script, so return 0
-    return 0;
-  }
-
-  if (absl::GetFlag(FLAGS_only_check_args)) {
-    return 0;
+    case HelpMode::kOnlyCheckArgs:
+      return 0;
   }
 
   return -1;
 }
 
+// --------------------------------------------------------------------
+// Globals representing usage reporting flags
+
+namespace {
+
+ABSL_CONST_INIT absl::Mutex help_attributes_guard(absl::kConstInit);
+ABSL_CONST_INIT std::string* match_substr
+    ABSL_GUARDED_BY(help_attributes_guard) = nullptr;
+ABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(help_attributes_guard) =
+    HelpMode::kNone;
+ABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(help_attributes_guard) =
+    HelpFormat::kHumanReadable;
+
+}  // namespace
+
+std::string GetFlagsHelpMatchSubstr() {
+  absl::MutexLock l(&help_attributes_guard);
+  if (match_substr == nullptr) return "";
+  return *match_substr;
+}
+
+void SetFlagsHelpMatchSubstr(absl::string_view substr) {
+  absl::MutexLock l(&help_attributes_guard);
+  if (match_substr == nullptr) match_substr = new std::string;
+  match_substr->assign(substr.data(), substr.size());
+}
+
+HelpMode GetFlagsHelpMode() {
+  absl::MutexLock l(&help_attributes_guard);
+  return help_mode;
+}
+
+void SetFlagsHelpMode(HelpMode mode) {
+  absl::MutexLock l(&help_attributes_guard);
+  help_mode = mode;
+}
+
+HelpFormat GetFlagsHelpFormat() {
+  absl::MutexLock l(&help_attributes_guard);
+  return help_format;
+}
+
+void SetFlagsHelpFormat(HelpFormat format) {
+  absl::MutexLock l(&help_attributes_guard);
+  help_format = format;
+}
+
+// Deduces usage flags from the input argument in a form --name=value or
+// --name. argument is already split into name and value before we call this
+// function.
+bool DeduceUsageFlags(absl::string_view name, absl::string_view value) {
+  if (absl::ConsumePrefix(&name, "help")) {
+    if (name == "") {
+      if (value.empty()) {
+        SetFlagsHelpMode(HelpMode::kImportant);
+      } else {
+        SetFlagsHelpMode(HelpMode::kMatch);
+        SetFlagsHelpMatchSubstr(value);
+      }
+      return true;
+    }
+
+    if (name == "match") {
+      SetFlagsHelpMode(HelpMode::kMatch);
+      SetFlagsHelpMatchSubstr(value);
+      return true;
+    }
+
+    if (name == "on") {
+      SetFlagsHelpMode(HelpMode::kMatch);
+      SetFlagsHelpMatchSubstr(absl::StrCat("/", value, "."));
+      return true;
+    }
+
+    if (name == "full") {
+      SetFlagsHelpMode(HelpMode::kFull);
+      return true;
+    }
+
+    if (name == "short") {
+      SetFlagsHelpMode(HelpMode::kShort);
+      return true;
+    }
+
+    if (name == "package") {
+      SetFlagsHelpMode(HelpMode::kPackage);
+      return true;
+    }
+
+    return false;
+  }
+
+  if (name == "version") {
+    SetFlagsHelpMode(HelpMode::kVersion);
+    return true;
+  }
+
+  if (name == "only_check_args") {
+    SetFlagsHelpMode(HelpMode::kOnlyCheckArgs);
+    return true;
+  }
+
+  return false;
+}
+
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/usage.h b/absl/flags/internal/usage.h
index 76075b0..c0bcac5 100644
--- a/absl/flags/internal/usage.h
+++ b/absl/flags/internal/usage.h
@@ -19,14 +19,16 @@
 #include <iosfwd>
 #include <string>
 
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
 #include "absl/flags/declare.h"
-#include "absl/flags/internal/commandlineflag.h"
 #include "absl/strings/string_view.h"
 
 // --------------------------------------------------------------------
 // Usage reporting interfaces
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 // The format to report the help messages in.
@@ -34,8 +36,9 @@
   kHumanReadable,
 };
 
-// Outputs the help message describing specific flag.
-void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag,
+// Streams the help message describing `flag` to `out`.
+// The default value for `flag` is included in the output.
+void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
               HelpFormat format = HelpFormat::kHumanReadable);
 
 // Produces the help messages for all flags matching the filter. A flag matches
@@ -63,16 +66,39 @@
 int HandleUsageFlags(std::ostream& out,
                      absl::string_view program_usage_message);
 
-}  // namespace flags_internal
-}  // namespace absl
+// --------------------------------------------------------------------
+// Globals representing usage reporting flags
 
-ABSL_DECLARE_FLAG(bool, help);
-ABSL_DECLARE_FLAG(bool, helpfull);
-ABSL_DECLARE_FLAG(bool, helpshort);
-ABSL_DECLARE_FLAG(bool, helppackage);
-ABSL_DECLARE_FLAG(bool, version);
-ABSL_DECLARE_FLAG(bool, only_check_args);
-ABSL_DECLARE_FLAG(std::string, helpon);
-ABSL_DECLARE_FLAG(std::string, helpmatch);
+enum class HelpMode {
+  kNone,
+  kImportant,
+  kShort,
+  kFull,
+  kPackage,
+  kMatch,
+  kVersion,
+  kOnlyCheckArgs
+};
+
+// Returns substring to filter help output (--help=substr argument)
+std::string GetFlagsHelpMatchSubstr();
+// Returns the requested help mode.
+HelpMode GetFlagsHelpMode();
+// Returns the requested help format.
+HelpFormat GetFlagsHelpFormat();
+
+// These are corresponding setters to the attributes above.
+void SetFlagsHelpMatchSubstr(absl::string_view);
+void SetFlagsHelpMode(HelpMode);
+void SetFlagsHelpFormat(HelpFormat);
+
+// Deduces usage flags from the input argument in a form --name=value or
+// --name. argument is already split into name and value before we call this
+// function.
+bool DeduceUsageFlags(absl::string_view name, absl::string_view value);
+
+}  // namespace flags_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_USAGE_H_
diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc
index d15e448..b5c2487 100644
--- a/absl/flags/internal/usage_test.cc
+++ b/absl/flags/internal/usage_test.cc
@@ -15,17 +15,21 @@
 
 #include "absl/flags/internal/usage.h"
 
+#include <stdint.h>
+
 #include <sstream>
+#include <string>
 
 #include "gtest/gtest.h"
 #include "absl/flags/flag.h"
+#include "absl/flags/internal/parse.h"
 #include "absl/flags/internal/path_util.h"
 #include "absl/flags/internal/program_name.h"
-#include "absl/flags/parse.h"
+#include "absl/flags/reflection.h"
 #include "absl/flags/usage.h"
 #include "absl/flags/usage_config.h"
-#include "absl/memory/memory.h"
 #include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
 
 ABSL_FLAG(int, usage_reporting_test_flag_01, 101,
           "usage_reporting_test_flag_01 help message");
@@ -83,9 +87,14 @@
     default_config.normalize_filename = &NormalizeFileName;
     absl::SetFlagsUsageConfig(default_config);
   }
+  ~UsageReportingTest() override {
+    flags::SetFlagsHelpMode(flags::HelpMode::kNone);
+    flags::SetFlagsHelpMatchSubstr("");
+    flags::SetFlagsHelpFormat(flags::HelpFormat::kHumanReadable);
+  }
 
  private:
-  flags::FlagSaver flag_saver_;
+  absl::FlagSaver flag_saver_;
 };
 
 // --------------------------------------------------------------------
@@ -97,69 +106,70 @@
 
 #ifndef _WIN32
   // TODO(rogeeff): figure out why this does not work on Windows.
-  EXPECT_DEATH(absl::SetProgramUsageMessage("custom usage message"),
-               ".*SetProgramUsageMessage\\(\\) called twice.*");
+  EXPECT_DEATH_IF_SUPPORTED(
+      absl::SetProgramUsageMessage("custom usage message"),
+      ".*SetProgramUsageMessage\\(\\) called twice.*");
 #endif
 }
 
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {
-  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_01");
+  const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_01");
   std::stringstream test_buf;
 
   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
   EXPECT_EQ(
       test_buf.str(),
-      R"(    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+      R"(    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
 )");
 }
 
 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
-  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_02");
+  const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_02");
   std::stringstream test_buf;
 
   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
   EXPECT_EQ(
       test_buf.str(),
-      R"(    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+      R"(    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
 )");
 }
 
 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {
-  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_03");
+  const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_03");
   std::stringstream test_buf;
 
   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
   EXPECT_EQ(
       test_buf.str(),
-      R"(    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+      R"(    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
 )");
 }
 
 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
-  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_04");
+  const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_04");
   std::stringstream test_buf;
 
   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
   EXPECT_EQ(
       test_buf.str(),
-      R"(    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+      R"(    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
 )");
 }
 
 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) {
-  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_05");
+  const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_05");
   std::stringstream test_buf;
 
   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
   EXPECT_EQ(
       test_buf.str(),
-      R"(    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+      R"(    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
 )");
 }
@@ -171,21 +181,25 @@
       R"(usage_test: Custom usage message
 
   Flags from absl/flags/internal/usage_test.cc:
-    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
-    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
-    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
-    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
-    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
-    -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
 
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )";
 
   std::stringstream test_buf_01;
@@ -209,7 +223,11 @@
   EXPECT_EQ(test_buf_04.str(),
             R"(usage_test: Custom usage message
 
-  No modules matched: use -helpfull
+No flags matched.
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 
   std::stringstream test_buf_05;
@@ -221,12 +239,8 @@
       absl::StartsWith(test_out_str, "usage_test: Custom usage message"));
   EXPECT_TRUE(absl::StrContains(
       test_out_str, "Flags from absl/flags/internal/usage_test.cc:"));
-  EXPECT_TRUE(absl::StrContains(test_out_str,
-                                "Flags from absl/flags/internal/usage.cc:"));
   EXPECT_TRUE(
       absl::StrContains(test_out_str, "-usage_reporting_test_flag_01 "));
-  EXPECT_TRUE(absl::StrContains(test_out_str, "-help (show help"))
-      << test_out_str;
 }
 
 // --------------------------------------------------------------------
@@ -239,7 +253,7 @@
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_helpshort) {
-  absl::SetFlag(&FLAGS_helpshort, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kShort);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -247,28 +261,32 @@
             R"(usage_test: Custom usage message
 
   Flags from absl/flags/internal/usage_test.cc:
-    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
-    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
-    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
-    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
-    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
-    -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
 
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }
 
 // --------------------------------------------------------------------
 
-TEST_F(UsageReportingTest, TestUsageFlag_help) {
-  absl::SetFlag(&FLAGS_help, true);
+TEST_F(UsageReportingTest, TestUsageFlag_help_simple) {
+  flags::SetFlagsHelpMode(flags::HelpMode::kImportant);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -276,30 +294,90 @@
             R"(usage_test: Custom usage message
 
   Flags from absl/flags/internal/usage_test.cc:
-    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
-    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
-    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
-    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
-    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
-    -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
 
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
 
-Try --helpfull to get a list of all flags.
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_help_one_flag) {
+  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+  flags::SetFlagsHelpMatchSubstr("usage_reporting_test_flag_06");
+
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+  EXPECT_EQ(test_buf.str(),
+            R"(usage_test: Custom usage message
+
+  Flags from absl/flags/internal/usage_test.cc:
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+      Some more help.
+      Even more long long long long long long long long long long long long help
+      message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) {
+  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+  flags::SetFlagsHelpMatchSubstr("test_flag");
+
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+  EXPECT_EQ(test_buf.str(),
+            R"(usage_test: Custom usage message
+
+  Flags from absl/flags/internal/usage_test.cc:
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+      default: 101;
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+      default: false;
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+      default: 1.03;
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+      default: 1000000000000004;
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+      default: UDT{};
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+      Some more help.
+      Even more long long long long long long long long long long long long help
+      message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }
 
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
-  absl::SetFlag(&FLAGS_helppackage, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kPackage);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -307,30 +385,32 @@
             R"(usage_test: Custom usage message
 
   Flags from absl/flags/internal/usage_test.cc:
-    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
-    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
-    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
-    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
-    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
-    -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
 
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
 
-Try --helpfull to get a list of all flags.
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }
 
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_version) {
-  absl::SetFlag(&FLAGS_version, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kVersion);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
@@ -344,7 +424,7 @@
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
-  absl::SetFlag(&FLAGS_only_check_args, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
@@ -354,17 +434,22 @@
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_helpon) {
-  absl::SetFlag(&FLAGS_helpon, "bla-bla");
+  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+  flags::SetFlagsHelpMatchSubstr("/bla-bla.");
 
   std::stringstream test_buf_01;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), 1);
   EXPECT_EQ(test_buf_01.str(),
             R"(usage_test: Custom usage message
 
-  No modules matched: use -helpfull
+No flags matched.
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 
-  absl::SetFlag(&FLAGS_helpon, "usage_test");
+  flags::SetFlagsHelpMatchSubstr("/usage_test.");
 
   std::stringstream test_buf_02;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1);
@@ -372,21 +457,25 @@
             R"(usage_test: Custom usage message
 
   Flags from absl/flags/internal/usage_test.cc:
-    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
-    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
-    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
-    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
-    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
-    -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
 
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }
 
diff --git a/absl/flags/marshalling.cc b/absl/flags/marshalling.cc
index f4ebe0e..81f9ceb 100644
--- a/absl/flags/marshalling.cc
+++ b/absl/flags/marshalling.cc
@@ -15,18 +15,28 @@
 
 #include "absl/flags/marshalling.h"
 
-#include <limits>
-#include <type_traits>
+#include <stddef.h>
 
+#include <cmath>
+#include <limits>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
 #include "absl/base/macros.h"
+#include "absl/strings/ascii.h"
 #include "absl/strings/match.h"
 #include "absl/strings/numbers.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_format.h"
 #include "absl/strings/str_join.h"
 #include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 // --------------------------------------------------------------------
@@ -64,15 +74,16 @@
 }
 
 template <typename IntType>
-inline bool ParseFlagImpl(absl::string_view text, IntType* dst) {
+inline bool ParseFlagImpl(absl::string_view text, IntType& dst) {
   text = absl::StripAsciiWhitespace(text);
 
-  return absl::numbers_internal::safe_strtoi_base(text, dst, NumericBase(text));
+  return absl::numbers_internal::safe_strtoi_base(text, &dst,
+                                                  NumericBase(text));
 }
 
 bool AbslParseFlag(absl::string_view text, short* dst, std::string*) {
   int val;
-  if (!ParseFlagImpl(text, &val)) return false;
+  if (!ParseFlagImpl(text, val)) return false;
   if (static_cast<short>(val) != val)  // worked, but number out of range
     return false;
   *dst = static_cast<short>(val);
@@ -81,7 +92,7 @@
 
 bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
   unsigned int val;
-  if (!ParseFlagImpl(text, &val)) return false;
+  if (!ParseFlagImpl(text, val)) return false;
   if (static_cast<unsigned short>(val) !=
       val)  // worked, but number out of range
     return false;
@@ -90,28 +101,28 @@
 }
 
 bool AbslParseFlag(absl::string_view text, int* dst, std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 bool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 bool AbslParseFlag(absl::string_view text, long* dst, std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 bool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 bool AbslParseFlag(absl::string_view text, long long* dst, std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 bool AbslParseFlag(absl::string_view text, unsigned long long* dst,
                    std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 // --------------------------------------------------------------------
@@ -162,7 +173,7 @@
 std::string Unparse(unsigned long long v) { return absl::StrCat(v); }
 template <typename T>
 std::string UnparseFloatingPointVal(T v) {
-  // digits10 is guaranteed to roundtrip correctly in std::string -> value -> std::string
+  // digits10 is guaranteed to roundtrip correctly in string -> value -> string
   // conversions, but may not be enough to represent all the values correctly.
   std::string digit10_str =
       absl::StrFormat("%.*g", std::numeric_limits<T>::digits10, v);
@@ -226,4 +237,5 @@
   return absl::UnparseFlag(static_cast<int>(v));
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/marshalling.h b/absl/flags/marshalling.h
index 6d39180..0b50335 100644
--- a/absl/flags/marshalling.h
+++ b/absl/flags/marshalling.h
@@ -33,16 +33,16 @@
 // * `double`
 // * `std::string`
 // * `std::vector<std::string>`
-// * `absl::LogSeverity` (provided here due to dependency ordering)
+// * `absl::LogSeverity` (provided natively for layering reasons)
 //
 // Note that support for integral types is implemented using overloads for
 // variable-width fundamental types (`short`, `int`, `long`, etc.). However,
 // you should prefer the fixed-width integral types (`int32_t`, `uint64_t`,
 // etc.) we've noted above within flag definitions.
-
 //
 // In addition, several Abseil libraries provide their own custom support for
-// Abseil flags.
+// Abseil flags. Documentation for these formats is provided in the type's
+// `AbslParseFlag()` definition.
 //
 // The Abseil time library provides the following support for civil time values:
 //
@@ -165,9 +165,11 @@
 #include <string>
 #include <vector>
 
+#include "absl/base/config.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 // Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types.
@@ -256,6 +258,7 @@
 bool AbslParseFlag(absl::string_view, absl::LogSeverity*, std::string*);
 std::string AbslUnparseFlag(absl::LogSeverity);
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_MARSHALLING_H_
diff --git a/absl/flags/marshalling_test.cc b/absl/flags/marshalling_test.cc
index 37cd194..4a64ce1 100644
--- a/absl/flags/marshalling_test.cc
+++ b/absl/flags/marshalling_test.cc
@@ -15,7 +15,12 @@
 
 #include "absl/flags/marshalling.h"
 
+#include <stdint.h>
+
 #include <cmath>
+#include <limits>
+#include <string>
+#include <vector>
 
 #include "gtest/gtest.h"
 
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
index 16c4d68..dd1a679 100644
--- a/absl/flags/parse.cc
+++ b/absl/flags/parse.cc
@@ -17,27 +17,45 @@
 
 #include <stdlib.h>
 
+#include <algorithm>
 #include <fstream>
 #include <iostream>
+#include <iterator>
+#include <string>
 #include <tuple>
+#include <utility>
+#include <vector>
 
 #ifdef _WIN32
 #include <windows.h>
 #endif
 
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/const_init.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/config.h"
 #include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/flag.h"
+#include "absl/flags/internal/parse.h"
+#include "absl/flags/internal/private_handle_accessor.h"
 #include "absl/flags/internal/program_name.h"
-#include "absl/flags/internal/registry.h"
 #include "absl/flags/internal/usage.h"
+#include "absl/flags/reflection.h"
 #include "absl/flags/usage.h"
 #include "absl/flags/usage_config.h"
+#include "absl/strings/ascii.h"
 #include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
 #include "absl/strings/strip.h"
 #include "absl/synchronization/mutex.h"
 
 // --------------------------------------------------------------------
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 namespace {
 
@@ -50,8 +68,25 @@
 ABSL_CONST_INIT bool tryfromenv_needs_processing
     ABSL_GUARDED_BY(processing_checks_guard) = false;
 
+ABSL_CONST_INIT absl::Mutex specified_flags_guard(absl::kConstInit);
+ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags
+    ABSL_GUARDED_BY(specified_flags_guard) = nullptr;
+
+struct SpecifiedFlagsCompare {
+  bool operator()(const CommandLineFlag* a, const CommandLineFlag* b) const {
+    return a->Name() < b->Name();
+  }
+  bool operator()(const CommandLineFlag* a, absl::string_view b) const {
+    return a->Name() < b;
+  }
+  bool operator()(absl::string_view a, const CommandLineFlag* b) const {
+    return a < b->Name();
+  }
+};
+
 }  // namespace
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 ABSL_FLAG(std::vector<std::string>, flagfile, {},
@@ -109,6 +144,7 @@
           "with that name");
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 namespace {
@@ -187,7 +223,7 @@
 // Reads the environment variable with name `name` and stores results in
 // `value`. If variable is not present in environment returns false, otherwise
 // returns true.
-bool GetEnvVar(const char* var_name, std::string* var_value) {
+bool GetEnvVar(const char* var_name, std::string& var_value) {
 #ifdef _WIN32
   char buf[1024];
   auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
@@ -199,14 +235,14 @@
     return false;
   }
 
-  *var_value = std::string(buf, get_res);
+  var_value = std::string(buf, get_res);
 #else
   const char* val = ::getenv(var_name);
   if (val == nullptr) {
     return false;
   }
 
-  *var_value = val;
+  var_value = val;
 #endif
 
   return true;
@@ -254,11 +290,11 @@
 //  found flag or nullptr
 //  is negative in case of --nofoo
 std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(flag_name);
+  CommandLineFlag* flag = absl::FindCommandLineFlag(flag_name);
   bool is_negative = false;
 
   if (!flag && absl::ConsumePrefix(&flag_name, "no")) {
-    flag = flags_internal::FindCommandLineFlag(flag_name);
+    flag = absl::FindCommandLineFlag(flag_name);
     is_negative = true;
   }
 
@@ -271,18 +307,17 @@
 // back.
 void CheckDefaultValuesParsingRoundtrip() {
 #ifndef NDEBUG
-  flags_internal::ForEachFlag([&](CommandLineFlag* flag) {
-    if (flag->IsRetired()) return;
+  flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+    if (flag.IsRetired()) return;
 
-#define IGNORE_TYPE(T) \
-  if (flag->IsOfType<T>()) return;
+#define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \
+  if (flag.IsOfType<T>()) return;
 
-    ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(IGNORE_TYPE)
-    IGNORE_TYPE(std::string)
-    IGNORE_TYPE(std::vector<std::string>)
-#undef IGNORE_TYPE
+    ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(ABSL_FLAGS_INTERNAL_IGNORE_TYPE)
+#undef ABSL_FLAGS_INTERNAL_IGNORE_TYPE
 
-    flag->CheckDefaultValueParsingRoundtrip();
+    flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
+        flag);
   });
 #endif
 }
@@ -295,13 +330,13 @@
 // the first flagfile in the input list are processed before the second flagfile
 // etc.
 bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
-                   std::vector<ArgsList>* input_args) {
+                   std::vector<ArgsList>& input_args) {
   bool success = true;
   for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) {
     ArgsList al;
 
     if (al.ReadFromFlagfile(*it)) {
-      input_args->push_back(al);
+      input_args.push_back(al);
     } else {
       success = false;
     }
@@ -316,7 +351,7 @@
 // `flag_name` is a string from the input flag_names list. If successful we
 // append a single ArgList at the end of the input_args.
 bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
-                      std::vector<ArgsList>* input_args,
+                      std::vector<ArgsList>& input_args,
                       bool fail_on_absent_in_env) {
   bool success = true;
   std::vector<std::string> args;
@@ -337,7 +372,7 @@
 
     const std::string envname = absl::StrCat("FLAGS_", flag_name);
     std::string envval;
-    if (!GetEnvVar(envname.c_str(), &envval)) {
+    if (!GetEnvVar(envname.c_str(), envval)) {
       if (fail_on_absent_in_env) {
         flags_internal::ReportUsageError(
             absl::StrCat(envname, " not found in environment"), true);
@@ -352,7 +387,7 @@
   }
 
   if (success) {
-    input_args->emplace_back(args);
+    input_args.emplace_back(args);
   }
 
   return success;
@@ -362,8 +397,8 @@
 
 // Returns success status, which is true if were able to handle all generator
 // flags (flagfile, fromenv, tryfromemv) successfully.
-bool HandleGeneratorFlags(std::vector<ArgsList>* input_args,
-                          std::vector<std::string>* flagfile_value) {
+bool HandleGeneratorFlags(std::vector<ArgsList>& input_args,
+                          std::vector<std::string>& flagfile_value) {
   bool success = true;
 
   absl::MutexLock l(&flags_internal::processing_checks_guard);
@@ -388,9 +423,9 @@
   if (flags_internal::flagfile_needs_processing) {
     auto flagfiles = absl::GetFlag(FLAGS_flagfile);
 
-    if (input_args->size() == 1) {
-      flagfile_value->insert(flagfile_value->end(), flagfiles.begin(),
-                             flagfiles.end());
+    if (input_args.size() == 1) {
+      flagfile_value.insert(flagfile_value.end(), flagfiles.begin(),
+                            flagfiles.end());
     }
 
     success &= ReadFlagfiles(flagfiles, input_args);
@@ -517,12 +552,12 @@
     curr_list->PopFront();
     value = curr_list->Front();
 
-    // Heuristic to detect the case where someone treats a std::string arg
+    // Heuristic to detect the case where someone treats a string arg
     // like a bool or just forgets to pass a value:
     // --my_string_var --foo=bar
-    // We look for a flag of std::string type, whose value begins with a
+    // We look for a flag of string type, whose value begins with a
     // dash and corresponds to known flag or standalone --.
-    if (value[0] == '-' && flag.IsOfType<std::string>()) {
+    if (!value.empty() && value[0] == '-' && flag.IsOfType<std::string>()) {
       auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1)));
 
       if (maybe_flag_name.empty() ||
@@ -559,12 +594,28 @@
 
 // --------------------------------------------------------------------
 
+bool WasPresentOnCommandLine(absl::string_view flag_name) {
+  absl::MutexLock l(&specified_flags_guard);
+  ABSL_INTERNAL_CHECK(specified_flags != nullptr,
+                      "ParseCommandLine is not invoked yet");
+
+  return std::binary_search(specified_flags->begin(), specified_flags->end(),
+                            flag_name, SpecifiedFlagsCompare{});
+}
+
+// --------------------------------------------------------------------
+
 std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
                                         ArgvListAction arg_list_act,
                                         UsageFlagsAction usage_flag_act,
                                         OnUndefinedFlag on_undef_flag) {
   ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
 
+  // Once parsing has started we will not have more flag registrations.
+  // If we did, they would be missing during parsing, which is a problem on
+  // itself.
+  flags_internal::FinalizeRegistry();
+
   // This routine does not return anything since we abort on failure.
   CheckDefaultValuesParsingRoundtrip();
 
@@ -589,13 +640,20 @@
   }
   output_args.push_back(argv[0]);
 
+  absl::MutexLock l(&specified_flags_guard);
+  if (specified_flags == nullptr) {
+    specified_flags = new std::vector<const CommandLineFlag*>;
+  } else {
+    specified_flags->clear();
+  }
+
   // Iterate through the list of the input arguments. First level are arguments
   // originated from argc/argv. Following levels are arguments originated from
   // recursive parsing of flagfile(s).
   bool success = true;
   while (!input_args.empty()) {
     // 10. First we process the built-in generator flags.
-    success &= HandleGeneratorFlags(&input_args, &flagfile_value);
+    success &= HandleGeneratorFlags(input_args, flagfile_value);
 
     // 30. Select top-most (most recent) arguments list. If it is empty drop it
     // and re-try.
@@ -630,7 +688,7 @@
 
     // 60. Split the current argument on '=' to figure out the argument
     // name and value. If flag name is empty it means we've got "--". value
-    // can be empty either if there were no '=' in argument std::string at all or
+    // can be empty either if there were no '=' in argument string at all or
     // an argument looked like "--foo=". In a latter case is_empty_value is
     // true.
     absl::string_view flag_name;
@@ -655,6 +713,11 @@
     std::tie(flag, is_negative) = LocateFlag(flag_name);
 
     if (flag == nullptr) {
+      // Usage flags are not modeled as Abseil flags. Locate them separately.
+      if (flags_internal::DeduceUsageFlags(flag_name, value)) {
+        continue;
+      }
+
       if (on_undef_flag != OnUndefinedFlag::kIgnoreUndefined) {
         undefined_flag_names.emplace_back(arg_from_argv,
                                           std::string(flag_name));
@@ -676,13 +739,17 @@
     }
 
     // 100. Set the located flag to a new new value, unless it is retired.
-    // Setting retired flag fails, but we ignoring it here.
-    if (flag->IsRetired()) continue;
-
+    // Setting retired flag fails, but we ignoring it here while also reporting
+    // access to retired flag.
     std::string error;
-    if (!flag->SetFromString(value, SET_FLAGS_VALUE, kCommandLine, &error)) {
+    if (!flags_internal::PrivateHandleAccessor::ParseFrom(
+            *flag, value, SET_FLAGS_VALUE, kCommandLine, error)) {
+      if (flag->IsRetired()) continue;
+
       flags_internal::ReportUsageError(error, true);
       success = false;
+    } else {
+      specified_flags->push_back(flag);
     }
   }
 
@@ -734,6 +801,10 @@
     }
   }
 
+  // Trim and sort the vector.
+  specified_flags->shrink_to_fit();
+  std::sort(specified_flags->begin(), specified_flags->end(),
+            SpecifiedFlagsCompare{});
   return output_args;
 }
 
@@ -748,4 +819,5 @@
       flags_internal::OnUndefinedFlag::kAbortIfUndefined);
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/parse.h b/absl/flags/parse.h
index dbb7510..929de2c 100644
--- a/absl/flags/parse.h
+++ b/absl/flags/parse.h
@@ -23,12 +23,13 @@
 #ifndef ABSL_FLAGS_PARSE_H_
 #define ABSL_FLAGS_PARSE_H_
 
-#include <string>
 #include <vector>
 
+#include "absl/base/config.h"
 #include "absl/flags/internal/parse.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // ParseCommandLine()
 //
@@ -53,6 +54,7 @@
 // help messages and then exits the program.
 std::vector<char*> ParseCommandLine(int argc, char* argv[]);
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_PARSE_H_
diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc
index 447a3bc..41bc0bc 100644
--- a/absl/flags/parse_test.cc
+++ b/absl/flags/parse_test.cc
@@ -15,14 +15,23 @@
 
 #include "absl/flags/parse.h"
 
+#include <stdlib.h>
+
 #include <fstream>
+#include <string>
+#include <vector>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/scoped_set_env.h"
+#include "absl/flags/declare.h"
 #include "absl/flags/flag.h"
+#include "absl/flags/internal/parse.h"
+#include "absl/flags/internal/usage.h"
+#include "absl/flags/reflection.h"
 #include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
 #include "absl/strings/substitute.h"
 #include "absl/types/span.h"
 
@@ -92,8 +101,11 @@
 
       auto len = GetTempPathA(MAX_PATH, temp_path_buffer);
       if (len < MAX_PATH && len != 0) {
-        std::string temp_dir_name = absl::StrCat(
-            temp_path_buffer, "\\parse_test.", GetCurrentProcessId());
+        std::string temp_dir_name = temp_path_buffer;
+        if (!absl::EndsWith(temp_dir_name, "\\")) {
+          temp_dir_name.push_back('\\');
+        }
+        absl::StrAppend(&temp_dir_name, "parse_test.", GetCurrentProcessId());
         if (CreateDirectoryA(temp_dir_name.c_str(), nullptr)) {
           *res = temp_dir_name;
         }
@@ -104,11 +116,11 @@
         *res = unique_name;
       }
 #endif
+    }
 
-      if (res->empty()) {
-        ABSL_INTERNAL_LOG(FATAL,
-                          "Failed to make temporary directory for data files");
-      }
+    if (res->empty()) {
+      ABSL_INTERNAL_LOG(FATAL,
+                        "Failed to make temporary directory for data files");
     }
 
 #ifdef _WIN32
@@ -160,8 +172,8 @@
 // temporary directory location. This way we can test inclusion of one flagfile
 // from another flagfile.
 const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
-                            std::string* flagfile_flag) {
-  *flagfile_flag = "--flagfile=";
+                            std::string& flagfile_flag) {
+  flagfile_flag = "--flagfile=";
   absl::string_view separator;
   for (const auto& flagfile_data : ffd) {
     std::string flagfile_name =
@@ -172,11 +184,11 @@
       flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n";
     }
 
-    absl::StrAppend(flagfile_flag, separator, flagfile_name);
+    absl::StrAppend(&flagfile_flag, separator, flagfile_name);
     separator = ",";
   }
 
-  return flagfile_flag->c_str();
+  return flagfile_flag.c_str();
 }
 
 }  // namespace
@@ -196,8 +208,11 @@
 using testing::ElementsAreArray;
 
 class ParseTest : public testing::Test {
+ public:
+  ~ParseTest() override { flags::SetFlagsHelpMode(flags::HelpMode::kNone); }
+
  private:
-  flags::FlagSaver flag_saver_;
+  absl::FlagSaver flag_saver_;
 };
 
 // --------------------------------------------------------------------
@@ -470,21 +485,22 @@
       "testbin",
       "--undefined_flag",
   };
-  EXPECT_DEATH(InvokeParse(in_args1),
-               "Unknown command line flag 'undefined_flag'");
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+                            "Unknown command line flag 'undefined_flag'");
 
   const char* in_args2[] = {
       "testbin",
       "--noprefixed_flag",
   };
-  EXPECT_DEATH(InvokeParse(in_args2),
-               "Unknown command line flag 'noprefixed_flag'");
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
+                            "Unknown command line flag 'noprefixed_flag'");
 
   const char* in_args3[] = {
       "testbin",
       "--Int_flag=1",
   };
-  EXPECT_DEATH(InvokeParse(in_args3), "Unknown command line flag 'Int_flag'");
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
+                            "Unknown command line flag 'Int_flag'");
 }
 
 // --------------------------------------------------------------------
@@ -494,7 +510,7 @@
       "testbin",
       "--bool_flag=",
   };
-  EXPECT_DEATH(
+  EXPECT_DEATH_IF_SUPPORTED(
       InvokeParse(in_args1),
       "Missing the value after assignment for the boolean flag 'bool_flag'");
 
@@ -502,7 +518,7 @@
       "testbin",
       "--nobool_flag=true",
   };
-  EXPECT_DEATH(InvokeParse(in_args2),
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
                "Negative form with assignment is not valid for the boolean "
                "flag 'bool_flag'");
 }
@@ -514,14 +530,14 @@
       "testbin",
       "--nostring_flag",
   };
-  EXPECT_DEATH(InvokeParse(in_args1),
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
                "Negative form is not valid for the flag 'string_flag'");
 
   const char* in_args2[] = {
       "testbin",
       "--int_flag",
   };
-  EXPECT_DEATH(InvokeParse(in_args2),
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
                "Missing the value for the flag 'int_flag'");
 }
 
@@ -532,7 +548,7 @@
       "testbin",
       "--udt_flag=1",
   };
-  EXPECT_DEATH(InvokeParse(in_args1),
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
                "Illegal value '1' specified for flag 'udt_flag'; Use values A, "
                "AAA instead");
 
@@ -541,7 +557,7 @@
       "--udt_flag",
       "AA",
   };
-  EXPECT_DEATH(InvokeParse(in_args2),
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
                "Illegal value 'AA' specified for flag 'udt_flag'; Use values "
                "A, AAA instead");
 }
@@ -576,14 +592,14 @@
   const char* in_args1[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
   TestParse(in_args1, -1, 0.1, "q2w2  ", true);
 
   const char* in_args2[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
   TestParse(in_args2, 100, 0.1, "q2w2  ", false);
 }
@@ -597,7 +613,7 @@
       "testbin",
       GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
                        {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
   TestParse(in_args1, -1, 0.1, "q2w2  ", true);
 }
@@ -610,7 +626,7 @@
   const char* in_args1[] = {
       "testbin", "--int_flag=3",
       GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
       "-double_flag=0.2"};
   TestParse(in_args1, -1, 0.2, "q2w2  ", true);
 }
@@ -625,10 +641,14 @@
       "--flagfile=$0/parse_test.ff2",
   };
 
+  GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
+                   {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
+                      flagfile_flag);
+
   const char* in_args1[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
   TestParse(in_args1, 100, 0.1, "q2w2  ", false);
 }
@@ -645,9 +665,9 @@
   const char* in_args1[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff4",
-                        absl::MakeConstSpan(ff4_data)}}, &flagfile_flag),
+                        absl::MakeConstSpan(ff4_data)}}, flagfile_flag),
   };
-  EXPECT_DEATH(InvokeParse(in_args1),
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
                "Unknown command line flag 'unknown_flag'");
 
   constexpr const char* const ff5_data[] = {
@@ -657,9 +677,9 @@
   const char* in_args2[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff5",
-                        absl::MakeConstSpan(ff5_data)}}, &flagfile_flag),
+                        absl::MakeConstSpan(ff5_data)}}, flagfile_flag),
   };
-  EXPECT_DEATH(InvokeParse(in_args2),
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
                "Unknown command line flag 'int_flag 10'");
 
   constexpr const char* const ff6_data[] = {
@@ -669,16 +689,17 @@
   const char* in_args3[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
-  EXPECT_DEATH(InvokeParse(in_args3),
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
                "Flagfile can't contain position arguments or --");
 
   const char* in_args4[] = {
       "testbin",
       "--flagfile=invalid_flag_file",
   };
-  EXPECT_DEATH(InvokeParse(in_args4), "Can't open flagfile invalid_flag_file");
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args4),
+                            "Can't open flagfile invalid_flag_file");
 
   constexpr const char* const ff7_data[] = {
       "--int_flag=10",
@@ -689,9 +710,9 @@
   const char* in_args5[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
-  EXPECT_DEATH(InvokeParse(in_args5),
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5),
                "Unexpected line in the flagfile .*: \\*bin\\*");
 }
 
@@ -713,7 +734,7 @@
 TEST_F(ParseDeathTest, TestReadingUnsetRequiredFlagsFromEnv) {
   const char* in_args1[] = {"testbin", "--fromenv=int_flag"};
 
-  EXPECT_DEATH(InvokeParse(in_args1),
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
                "FLAGS_int_flag not found in environment");
 }
 
@@ -724,7 +745,8 @@
 
   ScopedSetEnv set_tryfromenv("FLAGS_tryfromenv", "int_flag");
 
-  EXPECT_DEATH(InvokeParse(in_args1), "Infinite recursion on flag tryfromenv");
+  EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+                            "Infinite recursion on flag tryfromenv");
 }
 
 // --------------------------------------------------------------------
@@ -833,7 +855,7 @@
 
 // --------------------------------------------------------------------
 
-TEST_F(ParseDeathTest, TestHelpFlagHandling) {
+TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {
   const char* in_args1[] = {
       "testbin",
       "--help",
@@ -852,7 +874,56 @@
       flags::UsageFlagsAction::kIgnoreUsage,
       flags::OnUndefinedFlag::kAbortIfUndefined);
 
+  EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
 }
 
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestSubstringHelpFlagHandling) {
+  const char* in_args1[] = {
+      "testbin",
+      "--help=abcd",
+  };
+
+  auto out_args1 = flags::ParseCommandLineImpl(
+      2, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs,
+      flags::UsageFlagsAction::kIgnoreUsage,
+      flags::OnUndefinedFlag::kAbortIfUndefined);
+
+  EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kMatch);
+  EXPECT_EQ(flags::GetFlagsHelpMatchSubstr(), "abcd");
+
+  const char* in_args2[] = {"testbin", "--help", "some_positional_arg"};
+
+  auto out_args2 = flags::ParseCommandLineImpl(
+      3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs,
+      flags::UsageFlagsAction::kIgnoreUsage,
+      flags::OnUndefinedFlag::kAbortIfUndefined);
+
+  EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, WasPresentOnCommandLine) {
+  const char* in_args1[] = {
+      "testbin",        "arg1", "--bool_flag",
+      "--int_flag=211", "arg2", "--double_flag=1.1",
+      "--string_flag",  "asd",  "--",
+      "--some_flag",    "arg4",
+  };
+
+  InvokeParse(in_args1);
+
+  EXPECT_TRUE(flags::WasPresentOnCommandLine("bool_flag"));
+  EXPECT_TRUE(flags::WasPresentOnCommandLine("int_flag"));
+  EXPECT_TRUE(flags::WasPresentOnCommandLine("double_flag"));
+  EXPECT_TRUE(flags::WasPresentOnCommandLine("string_flag"));
+  EXPECT_FALSE(flags::WasPresentOnCommandLine("some_flag"));
+  EXPECT_FALSE(flags::WasPresentOnCommandLine("another_flag"));
+}
+
+// --------------------------------------------------------------------
+
 }  // namespace
diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc
new file mode 100644
index 0000000..c976d46
--- /dev/null
+++ b/absl/flags/reflection.cc
@@ -0,0 +1,337 @@
+//
+//  Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/reflection.h"
+
+#include <assert.h>
+
+#include <atomic>
+#include <map>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/private_handle_accessor.h"
+#include "absl/flags/internal/registry.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// --------------------------------------------------------------------
+// FlagRegistry
+//    A FlagRegistry singleton object holds all flag objects indexed by their
+//    names so that if you know a flag's name, you can access or set it. If the
+//    function is named FooLocked(), you must own the registry lock before
+//    calling the function; otherwise, you should *not* hold the lock, and the
+//    function will acquire it itself if needed.
+// --------------------------------------------------------------------
+
+class FlagRegistry {
+ public:
+  FlagRegistry() = default;
+  ~FlagRegistry() = default;
+
+  // Store a flag in this registry. Takes ownership of *flag.
+  void RegisterFlag(CommandLineFlag& flag);
+
+  void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); }
+  void Unlock() ABSL_UNLOCK_FUNCTION(lock_) { lock_.Unlock(); }
+
+  // Returns the flag object for the specified name, or nullptr if not found.
+  // Will emit a warning if a 'retired' flag is specified.
+  CommandLineFlag* FindFlag(absl::string_view name);
+
+  static FlagRegistry& GlobalRegistry();  // returns a singleton registry
+
+ private:
+  friend class flags_internal::FlagSaverImpl;  // reads all the flags in order
+                                               // to copy them
+  friend void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
+  friend void FinalizeRegistry();
+
+  // The map from name to flag, for FindFlag().
+  using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
+  using FlagIterator = FlagMap::iterator;
+  using FlagConstIterator = FlagMap::const_iterator;
+  FlagMap flags_;
+  std::vector<CommandLineFlag*> flat_flags_;
+  std::atomic<bool> finalized_flags_{false};
+
+  absl::Mutex lock_;
+
+  // Disallow
+  FlagRegistry(const FlagRegistry&);
+  FlagRegistry& operator=(const FlagRegistry&);
+};
+
+namespace {
+
+class FlagRegistryLock {
+ public:
+  explicit FlagRegistryLock(FlagRegistry& fr) : fr_(fr) { fr_.Lock(); }
+  ~FlagRegistryLock() { fr_.Unlock(); }
+
+ private:
+  FlagRegistry& fr_;
+};
+
+}  // namespace
+
+CommandLineFlag* FlagRegistry::FindFlag(absl::string_view name) {
+  if (finalized_flags_.load(std::memory_order_acquire)) {
+    // We could save some gcus here if we make `Name()` be non-virtual.
+    // We could move the `const char*` name to the base class.
+    auto it = std::partition_point(
+        flat_flags_.begin(), flat_flags_.end(),
+        [=](CommandLineFlag* f) { return f->Name() < name; });
+    if (it != flat_flags_.end() && (*it)->Name() == name) return *it;
+  }
+
+  FlagRegistryLock frl(*this);
+  auto it = flags_.find(name);
+  return it != flags_.end() ? it->second : nullptr;
+}
+
+void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
+  FlagRegistryLock registry_lock(*this);
+
+  std::pair<FlagIterator, bool> ins =
+      flags_.insert(FlagMap::value_type(flag.Name(), &flag));
+  if (ins.second == false) {  // means the name was already in the map
+    CommandLineFlag& old_flag = *ins.first->second;
+    if (flag.IsRetired() != old_flag.IsRetired()) {
+      // All registrations must agree on the 'retired' flag.
+      flags_internal::ReportUsageError(
+          absl::StrCat(
+              "Retired flag '", flag.Name(), "' was defined normally in file '",
+              (flag.IsRetired() ? old_flag.Filename() : flag.Filename()), "'."),
+          true);
+    } else if (flags_internal::PrivateHandleAccessor::TypeId(flag) !=
+               flags_internal::PrivateHandleAccessor::TypeId(old_flag)) {
+      flags_internal::ReportUsageError(
+          absl::StrCat("Flag '", flag.Name(),
+                       "' was defined more than once but with "
+                       "differing types. Defined in files '",
+                       old_flag.Filename(), "' and '", flag.Filename(), "'."),
+          true);
+    } else if (old_flag.IsRetired()) {
+      return;
+    } else if (old_flag.Filename() != flag.Filename()) {
+      flags_internal::ReportUsageError(
+          absl::StrCat("Flag '", flag.Name(),
+                       "' was defined more than once (in files '",
+                       old_flag.Filename(), "' and '", flag.Filename(), "')."),
+          true);
+    } else {
+      flags_internal::ReportUsageError(
+          absl::StrCat(
+              "Something is wrong with flag '", flag.Name(), "' in file '",
+              flag.Filename(), "'. One possibility: file '", flag.Filename(),
+              "' is being linked both statically and dynamically into this "
+              "executable. e.g. some files listed as srcs to a test and also "
+              "listed as srcs of some shared lib deps of the same test."),
+          true);
+    }
+    // All cases above are fatal, except for the retired flags.
+    std::exit(1);
+  }
+}
+
+FlagRegistry& FlagRegistry::GlobalRegistry() {
+  static FlagRegistry* global_registry = new FlagRegistry;
+  return *global_registry;
+}
+
+// --------------------------------------------------------------------
+
+void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {
+  FlagRegistry& registry = FlagRegistry::GlobalRegistry();
+
+  if (registry.finalized_flags_.load(std::memory_order_acquire)) {
+    for (const auto& i : registry.flat_flags_) visitor(*i);
+  }
+
+  FlagRegistryLock frl(registry);
+  for (const auto& i : registry.flags_) visitor(*i.second);
+}
+
+// --------------------------------------------------------------------
+
+bool RegisterCommandLineFlag(CommandLineFlag& flag) {
+  FlagRegistry::GlobalRegistry().RegisterFlag(flag);
+  return true;
+}
+
+void FinalizeRegistry() {
+  auto& registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  if (registry.finalized_flags_.load(std::memory_order_relaxed)) {
+    // Was already finalized. Ignore the second time.
+    return;
+  }
+  registry.flat_flags_.reserve(registry.flags_.size());
+  for (const auto& f : registry.flags_) {
+    registry.flat_flags_.push_back(f.second);
+  }
+  registry.flags_.clear();
+  registry.finalized_flags_.store(true, std::memory_order_release);
+}
+
+// --------------------------------------------------------------------
+
+namespace {
+
+class RetiredFlagObj final : public CommandLineFlag {
+ public:
+  constexpr RetiredFlagObj(const char* name, FlagFastTypeId type_id)
+      : name_(name), type_id_(type_id) {}
+
+ private:
+  absl::string_view Name() const override { return name_; }
+  std::string Filename() const override {
+    OnAccess();
+    return "RETIRED";
+  }
+  FlagFastTypeId TypeId() const override { return type_id_; }
+  std::string Help() const override {
+    OnAccess();
+    return "";
+  }
+  bool IsRetired() const override { return true; }
+  bool IsSpecifiedOnCommandLine() const override {
+    OnAccess();
+    return false;
+  }
+  std::string DefaultValue() const override {
+    OnAccess();
+    return "";
+  }
+  std::string CurrentValue() const override {
+    OnAccess();
+    return "";
+  }
+
+  // Any input is valid
+  bool ValidateInputValue(absl::string_view) const override {
+    OnAccess();
+    return true;
+  }
+
+  std::unique_ptr<flags_internal::FlagStateInterface> SaveState() override {
+    return nullptr;
+  }
+
+  bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode,
+                 flags_internal::ValueSource, std::string&) override {
+    OnAccess();
+    return false;
+  }
+
+  void CheckDefaultValueParsingRoundtrip() const override { OnAccess(); }
+
+  void Read(void*) const override { OnAccess(); }
+
+  void OnAccess() const {
+    flags_internal::ReportUsageError(
+        absl::StrCat("Accessing retired flag '", name_, "'"), false);
+  }
+
+  // Data members
+  const char* const name_;
+  const FlagFastTypeId type_id_;
+};
+
+}  // namespace
+
+void Retire(const char* name, FlagFastTypeId type_id, char* buf) {
+  static_assert(sizeof(RetiredFlagObj) == kRetiredFlagObjSize, "");
+  static_assert(alignof(RetiredFlagObj) == kRetiredFlagObjAlignment, "");
+  auto* flag = ::new (static_cast<void*>(buf))
+      flags_internal::RetiredFlagObj(name, type_id);
+  FlagRegistry::GlobalRegistry().RegisterFlag(*flag);
+}
+
+// --------------------------------------------------------------------
+
+class FlagSaverImpl {
+ public:
+  FlagSaverImpl() = default;
+  FlagSaverImpl(const FlagSaverImpl&) = delete;
+  void operator=(const FlagSaverImpl&) = delete;
+
+  // Saves the flag states from the flag registry into this object.
+  // It's an error to call this more than once.
+  void SaveFromRegistry() {
+    assert(backup_registry_.empty());  // call only once!
+    flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+      if (auto flag_state =
+              flags_internal::PrivateHandleAccessor::SaveState(flag)) {
+        backup_registry_.emplace_back(std::move(flag_state));
+      }
+    });
+  }
+
+  // Restores the saved flag states into the flag registry.
+  void RestoreToRegistry() {
+    for (const auto& flag_state : backup_registry_) {
+      flag_state->Restore();
+    }
+  }
+
+ private:
+  std::vector<std::unique_ptr<flags_internal::FlagStateInterface>>
+      backup_registry_;
+};
+
+}  // namespace flags_internal
+
+FlagSaver::FlagSaver() : impl_(new flags_internal::FlagSaverImpl) {
+  impl_->SaveFromRegistry();
+}
+
+FlagSaver::~FlagSaver() {
+  if (!impl_) return;
+
+  impl_->RestoreToRegistry();
+  delete impl_;
+}
+
+// --------------------------------------------------------------------
+
+CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
+  if (name.empty()) return nullptr;
+  flags_internal::FlagRegistry& registry =
+      flags_internal::FlagRegistry::GlobalRegistry();
+  return registry.FindFlag(name);
+}
+
+// --------------------------------------------------------------------
+
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags() {
+  absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> res;
+  flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+    if (!flag.IsRetired()) res.insert({flag.Name(), &flag});
+  });
+  return res;
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/flags/reflection.h b/absl/flags/reflection.h
new file mode 100644
index 0000000..e6baf5d
--- /dev/null
+++ b/absl/flags/reflection.h
@@ -0,0 +1,90 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: reflection.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the routines to access and operate on an Abseil Flag's
+// reflection handle.
+
+#ifndef ABSL_FLAGS_REFLECTION_H_
+#define ABSL_FLAGS_REFLECTION_H_
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+class FlagSaverImpl;
+}  // namespace flags_internal
+
+// FindCommandLineFlag()
+//
+// Returns the reflection handle of an Abseil flag of the specified name, or
+// `nullptr` if not found. This function will emit a warning if the name of a
+// 'retired' flag is specified.
+absl::CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+
+// Returns current state of the Flags registry in a form of mapping from flag
+// name to a flag reflection handle.
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags();
+
+//------------------------------------------------------------------------------
+// FlagSaver
+//------------------------------------------------------------------------------
+//
+// A FlagSaver object stores the state of flags in the scope where the FlagSaver
+// is defined, allowing modification of those flags within that scope and
+// automatic restoration of the flags to their previous state upon leaving the
+// scope.
+//
+// A FlagSaver can be used within tests to temporarily change the test
+// environment and restore the test case to its previous state.
+//
+// Example:
+//
+//   void MyFunc() {
+//    absl::FlagSaver fs;
+//    ...
+//    absl::SetFlag(&FLAGS_myFlag, otherValue);
+//    ...
+//  } // scope of FlagSaver left, flags return to previous state
+//
+// This class is thread-safe.
+
+class FlagSaver {
+ public:
+  FlagSaver();
+  ~FlagSaver();
+
+  FlagSaver(const FlagSaver&) = delete;
+  void operator=(const FlagSaver&) = delete;
+
+ private:
+  flags_internal::FlagSaverImpl* impl_;
+};
+
+//-----------------------------------------------------------------------------
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_REFLECTION_H_
diff --git a/absl/flags/reflection_test.cc b/absl/flags/reflection_test.cc
new file mode 100644
index 0000000..4c80900
--- /dev/null
+++ b/absl/flags/reflection_test.cc
@@ -0,0 +1,267 @@
+//
+//  Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/reflection.h"
+
+#include <memory>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+
+ABSL_FLAG(int, int_flag, 1, "int_flag help");
+ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
+ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+class ReflectionTest : public testing::Test {
+ protected:
+  void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
+  void TearDown() override { flag_saver_.reset(); }
+
+ private:
+  std::unique_ptr<absl::FlagSaver> flag_saver_;
+};
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestFindCommandLineFlag) {
+  auto* handle = absl::FindCommandLineFlag("some_flag");
+  EXPECT_EQ(handle, nullptr);
+
+  handle = absl::FindCommandLineFlag("int_flag");
+  EXPECT_NE(handle, nullptr);
+
+  handle = absl::FindCommandLineFlag("string_flag");
+  EXPECT_NE(handle, nullptr);
+
+  handle = absl::FindCommandLineFlag("bool_retired_flag");
+  EXPECT_NE(handle, nullptr);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestGetAllFlags) {
+  auto all_flags = absl::GetAllFlags();
+  EXPECT_NE(all_flags.find("int_flag"), all_flags.end());
+  EXPECT_EQ(all_flags.find("bool_retired_flag"), all_flags.end());
+  EXPECT_EQ(all_flags.find("some_undefined_flag"), all_flags.end());
+
+  std::vector<absl::string_view> flag_names_first_attempt;
+  auto all_flags_1 = absl::GetAllFlags();
+  for (auto f : all_flags_1) {
+    flag_names_first_attempt.push_back(f.first);
+  }
+
+  std::vector<absl::string_view> flag_names_second_attempt;
+  auto all_flags_2 = absl::GetAllFlags();
+  for (auto f : all_flags_2) {
+    flag_names_second_attempt.push_back(f.first);
+  }
+
+  EXPECT_THAT(flag_names_first_attempt,
+              ::testing::UnorderedElementsAreArray(flag_names_second_attempt));
+}
+
+// --------------------------------------------------------------------
+
+struct CustomUDT {
+  CustomUDT() : a(1), b(1) {}
+  CustomUDT(int a_, int b_) : a(a_), b(b_) {}
+
+  friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
+    return f1.a == f2.a && f1.b == f2.b;
+  }
+
+  int a;
+  int b;
+};
+bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
+  std::vector<absl::string_view> parts =
+      absl::StrSplit(in, ':', absl::SkipWhitespace());
+
+  if (parts.size() != 2) return false;
+
+  if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
+
+  if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
+
+  return true;
+}
+std::string AbslUnparseFlag(const CustomUDT& f) {
+  return absl::StrCat(f.a, ":", f.b);
+}
+
+}  // namespace
+
+// --------------------------------------------------------------------
+
+ABSL_FLAG(bool, test_flag_01, true, "");
+ABSL_FLAG(int, test_flag_02, 1234, "");
+ABSL_FLAG(int16_t, test_flag_03, -34, "");
+ABSL_FLAG(uint16_t, test_flag_04, 189, "");
+ABSL_FLAG(int32_t, test_flag_05, 10765, "");
+ABSL_FLAG(uint32_t, test_flag_06, 40000, "");
+ABSL_FLAG(int64_t, test_flag_07, -1234567, "");
+ABSL_FLAG(uint64_t, test_flag_08, 9876543, "");
+ABSL_FLAG(double, test_flag_09, -9.876e-50, "");
+ABSL_FLAG(float, test_flag_10, 1.234e12f, "");
+ABSL_FLAG(std::string, test_flag_11, "", "");
+ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "");
+static int counter = 0;
+ABSL_FLAG(int, test_flag_13, 200, "").OnUpdate([]() { counter++; });
+ABSL_FLAG(CustomUDT, test_flag_14, {}, "");
+
+namespace {
+
+TEST_F(ReflectionTest, TestFlagSaverInScope) {
+  {
+    absl::FlagSaver s;
+    counter = 0;
+    absl::SetFlag(&FLAGS_test_flag_01, false);
+    absl::SetFlag(&FLAGS_test_flag_02, -1021);
+    absl::SetFlag(&FLAGS_test_flag_03, 6009);
+    absl::SetFlag(&FLAGS_test_flag_04, 44);
+    absl::SetFlag(&FLAGS_test_flag_05, +800);
+    absl::SetFlag(&FLAGS_test_flag_06, -40978756);
+    absl::SetFlag(&FLAGS_test_flag_07, 23405);
+    absl::SetFlag(&FLAGS_test_flag_08, 975310);
+    absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
+    absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
+    absl::SetFlag(&FLAGS_test_flag_11, "asdf");
+    absl::SetFlag(&FLAGS_test_flag_12, absl::Hours(20));
+    absl::SetFlag(&FLAGS_test_flag_13, 4);
+    absl::SetFlag(&FLAGS_test_flag_14, CustomUDT{-1, -2});
+  }
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});
+  EXPECT_EQ(counter, 2);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestFlagSaverVsUpdateViaReflection) {
+  {
+    absl::FlagSaver s;
+    counter = 0;
+    std::string error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_01")->ParseFrom("false", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_02")->ParseFrom("-4536", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_03")->ParseFrom("111", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_04")->ParseFrom("909", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_05")->ParseFrom("-2004", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_06")->ParseFrom("1000023", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_07")->ParseFrom("69305", &error))
+        << error;
+    EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_08")
+                    ->ParseFrom("1000000001", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_09")->ParseFrom("2.09021", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_10")->ParseFrom("-33.1", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_11")->ParseFrom("ADD_FOO", &error))
+        << error;
+    EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_12")
+                    ->ParseFrom("3h11m16s", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_13")->ParseFrom("0", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_14")->ParseFrom("10:1", &error))
+        << error;
+  }
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});
+  EXPECT_EQ(counter, 2);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestMultipleFlagSaversInEnclosedScopes) {
+  {
+    absl::FlagSaver s;
+    absl::SetFlag(&FLAGS_test_flag_08, 10);
+    EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);
+    {
+      absl::FlagSaver s;
+      absl::SetFlag(&FLAGS_test_flag_08, 20);
+      EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);
+      {
+        absl::FlagSaver s;
+        absl::SetFlag(&FLAGS_test_flag_08, -200);
+        EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), -200);
+      }
+      EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);
+    }
+    EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);
+  }
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
+}
+
+}  // namespace
diff --git a/absl/flags/usage.cc b/absl/flags/usage.cc
index dff7a3d..452f667 100644
--- a/absl/flags/usage.cc
+++ b/absl/flags/usage.cc
@@ -14,12 +14,20 @@
 // limitations under the License.
 #include "absl/flags/usage.h"
 
+#include <stdlib.h>
+
 #include <string>
 
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/const_init.h"
+#include "absl/base/thread_annotations.h"
 #include "absl/flags/internal/usage.h"
+#include "absl/strings/string_view.h"
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 namespace {
 ABSL_CONST_INIT absl::Mutex usage_message_guard(absl::kConstInit);
@@ -53,4 +61,5 @@
              : "Warning: SetProgramUsageMessage() never called";
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/usage.h b/absl/flags/usage.h
index 3a12107..ad12ab7 100644
--- a/absl/flags/usage.h
+++ b/absl/flags/usage.h
@@ -16,12 +16,14 @@
 #ifndef ABSL_FLAGS_USAGE_H_
 #define ABSL_FLAGS_USAGE_H_
 
+#include "absl/base/config.h"
 #include "absl/strings/string_view.h"
 
 // --------------------------------------------------------------------
 // Usage reporting interfaces
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // Sets the "usage" message to be used by help reporting routines.
 // For example:
@@ -35,6 +37,7 @@
 // Returns the usage message set by SetProgramUsageMessage().
 absl::string_view ProgramUsageMessage();
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_USAGE_H_
diff --git a/absl/flags/usage_config.cc b/absl/flags/usage_config.cc
index f97bf30..ae2f548 100644
--- a/absl/flags/usage_config.cc
+++ b/absl/flags/usage_config.cc
@@ -15,13 +15,18 @@
 
 #include "absl/flags/usage_config.h"
 
+#include <functional>
 #include <iostream>
-#include <memory>
+#include <string>
 
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/const_init.h"
+#include "absl/base/thread_annotations.h"
 #include "absl/flags/internal/path_util.h"
 #include "absl/flags/internal/program_name.h"
-#include "absl/strings/str_cat.h"
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
 #include "absl/strings/strip.h"
 #include "absl/synchronization/mutex.h"
 
@@ -34,6 +39,7 @@
 }  // extern "C"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 namespace {
@@ -45,10 +51,15 @@
 bool ContainsHelpshortFlags(absl::string_view filename) {
   // By default we only want flags in binary's main. We expect the main
   // routine to reside in <program>.cc or <program>-main.cc or
-  // <program>_main.cc, where the <program> is the name of the binary.
+  // <program>_main.cc, where the <program> is the name of the binary
+  // (without .exe on Windows).
   auto suffix = flags_internal::Basename(filename);
-  if (!absl::ConsumePrefix(&suffix,
-                           flags_internal::ShortProgramInvocationName()))
+  auto program_name = flags_internal::ShortProgramInvocationName();
+  absl::string_view program_name_ref = program_name;
+#if defined(_WIN32)
+  absl::ConsumeSuffix(&program_name_ref, ".exe");
+#endif
+  if (!absl::ConsumePrefix(&suffix, program_name_ref))
     return false;
   return absl::StartsWith(suffix, ".") || absl::StartsWith(suffix, "-main.") ||
          absl::StartsWith(suffix, "_main.");
@@ -149,4 +160,5 @@
     flags_internal::custom_usage_config = new FlagsUsageConfig(usage_config);
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/usage_config.h b/absl/flags/usage_config.h
index bfd0eed..96eecea 100644
--- a/absl/flags/usage_config.h
+++ b/absl/flags/usage_config.h
@@ -27,6 +27,7 @@
 #include <functional>
 #include <string>
 
+#include "absl/base/config.h"
 #include "absl/strings/string_view.h"
 
 // -----------------------------------------------------------------------------
@@ -54,6 +55,7 @@
 //     Shows help on modules whose name contains the specified substring
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace flags_internal {
 using FlagKindFilter = std::function<bool (absl::string_view)>;
@@ -88,7 +90,7 @@
   // program output.
   flags_internal::FlagKindFilter contains_helppackage_flags;
 
-  // Generates std::string containing program version. This is the std::string reported
+  // Generates string containing program version. This is the string reported
   // when user specifies --version in a command line.
   std::function<std::string()> version_string;
 
@@ -118,6 +120,7 @@
 void ReportUsageError(absl::string_view msg, bool is_fatal);
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 extern "C" {
diff --git a/absl/flags/usage_config_test.cc b/absl/flags/usage_config_test.cc
index 3bde13a..e57a883 100644
--- a/absl/flags/usage_config_test.cc
+++ b/absl/flags/usage_config_test.cc
@@ -15,10 +15,13 @@
 
 #include "absl/flags/usage_config.h"
 
+#include <string>
+
 #include "gtest/gtest.h"
 #include "absl/flags/internal/path_util.h"
 #include "absl/flags/internal/program_name.h"
 #include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
 
 namespace {
 
@@ -81,7 +84,11 @@
 // --------------------------------------------------------------------
 
 TEST_F(FlagsUsageConfigTest, TestContainsHelpshortFlags) {
+#if defined(_WIN32)
+  flags::SetProgramInvocationName("usage_config_test.exe");
+#else
   flags::SetProgramInvocationName("usage_config_test");
+#endif
 
   auto config = flags::GetUsageConfig();
   EXPECT_TRUE(config.contains_helpshort_flags("adir/cd/usage_config_test.cc"));
diff --git a/absl/functional/BUILD.bazel b/absl/functional/BUILD.bazel
new file mode 100644
index 0000000..ebd9b99
--- /dev/null
+++ b/absl/functional/BUILD.bazel
@@ -0,0 +1,93 @@
+#
+# Copyright 2019 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load(
+    "//absl:copts/configure_copts.bzl",
+    "ABSL_DEFAULT_COPTS",
+    "ABSL_DEFAULT_LINKOPTS",
+    "ABSL_TEST_COPTS",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+cc_library(
+    name = "bind_front",
+    srcs = ["internal/front_binder.h"],
+    hdrs = ["bind_front.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:base_internal",
+        "//absl/container:compressed_tuple",
+        "//absl/meta:type_traits",
+        "//absl/utility",
+    ],
+)
+
+cc_test(
+    name = "bind_front_test",
+    srcs = ["bind_front_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":bind_front",
+        "//absl/memory",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "function_ref",
+    srcs = ["internal/function_ref.h"],
+    hdrs = ["function_ref.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:base_internal",
+        "//absl/meta:type_traits",
+    ],
+)
+
+cc_test(
+    name = "function_ref_test",
+    size = "small",
+    srcs = ["function_ref_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    deps = [
+        ":function_ref",
+        "//absl/container:test_instance_tracker",
+        "//absl/memory",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "function_ref_benchmark",
+    srcs = [
+        "function_ref_benchmark.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":function_ref",
+        "//absl/base:core_headers",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
diff --git a/absl/functional/CMakeLists.txt b/absl/functional/CMakeLists.txt
new file mode 100644
index 0000000..cda914f
--- /dev/null
+++ b/absl/functional/CMakeLists.txt
@@ -0,0 +1,72 @@
+#
+# Copyright 2019 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+absl_cc_library(
+  NAME
+    bind_front
+  SRCS
+    "internal/front_binder.h"
+  HDRS
+    "bind_front.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base_internal
+    absl::compressed_tuple
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    bind_front_test
+  SRCS
+    "bind_front_test.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::bind_front
+    absl::memory
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    function_ref
+  SRCS
+    "internal/function_ref.h"
+  HDRS
+    "function_ref.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base_internal
+    absl::meta
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    function_ref_test
+  SRCS
+    "function_ref_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::function_ref
+    absl::memory
+    absl::test_instance_tracker
+    gmock_main
+)
diff --git a/absl/functional/bind_front.h b/absl/functional/bind_front.h
new file mode 100644
index 0000000..5b47970
--- /dev/null
+++ b/absl/functional/bind_front.h
@@ -0,0 +1,184 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: bind_front.h
+// -----------------------------------------------------------------------------
+//
+// `absl::bind_front()` returns a functor by binding a number of arguments to
+// the front of a provided (usually more generic) functor. Unlike `std::bind`,
+// it does not require the use of argument placeholders. The simpler syntax of
+// `absl::bind_front()` allows you to avoid known misuses with `std::bind()`.
+//
+// `absl::bind_front()` is meant as a drop-in replacement for C++20's upcoming
+// `std::bind_front()`, which similarly resolves these issues with
+// `std::bind()`. Both `bind_front()` alternatives, unlike `std::bind()`, allow
+// partial function application. (See
+// https://en.wikipedia.org/wiki/Partial_application).
+
+#ifndef ABSL_FUNCTIONAL_BIND_FRONT_H_
+#define ABSL_FUNCTIONAL_BIND_FRONT_H_
+
+#include "absl/functional/internal/front_binder.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// bind_front()
+//
+// Binds the first N arguments of an invocable object and stores them by value.
+//
+// Like `std::bind()`, `absl::bind_front()` is implicitly convertible to
+// `std::function`.  In particular, it may be used as a simpler replacement for
+// `std::bind()` in most cases, as it does not require  placeholders to be
+// specified. More importantly, it provides more reliable correctness guarantees
+// than `std::bind()`; while `std::bind()` will silently ignore passing more
+// parameters than expected, for example, `absl::bind_front()` will report such
+// mis-uses as errors.
+//
+// absl::bind_front(a...) can be seen as storing the results of
+// std::make_tuple(a...).
+//
+// Example: Binding a free function.
+//
+//   int Minus(int a, int b) { return a - b; }
+//
+//   assert(absl::bind_front(Minus)(3, 2) == 3 - 2);
+//   assert(absl::bind_front(Minus, 3)(2) == 3 - 2);
+//   assert(absl::bind_front(Minus, 3, 2)() == 3 - 2);
+//
+// Example: Binding a member function.
+//
+//   struct Math {
+//     int Double(int a) const { return 2 * a; }
+//   };
+//
+//   Math math;
+//
+//   assert(absl::bind_front(&Math::Double)(&math, 3) == 2 * 3);
+//   // Stores a pointer to math inside the functor.
+//   assert(absl::bind_front(&Math::Double, &math)(3) == 2 * 3);
+//   // Stores a copy of math inside the functor.
+//   assert(absl::bind_front(&Math::Double, math)(3) == 2 * 3);
+//   // Stores std::unique_ptr<Math> inside the functor.
+//   assert(absl::bind_front(&Math::Double,
+//                           std::unique_ptr<Math>(new Math))(3) == 2 * 3);
+//
+// Example: Using `absl::bind_front()`, instead of `std::bind()`, with
+//          `std::function`.
+//
+//   class FileReader {
+//    public:
+//     void ReadFileAsync(const std::string& filename, std::string* content,
+//                        const std::function<void()>& done) {
+//       // Calls Executor::Schedule(std::function<void()>).
+//       Executor::DefaultExecutor()->Schedule(
+//           absl::bind_front(&FileReader::BlockingRead, this,
+//                            filename, content, done));
+//     }
+//
+//    private:
+//     void BlockingRead(const std::string& filename, std::string* content,
+//                       const std::function<void()>& done) {
+//       CHECK_OK(file::GetContents(filename, content, {}));
+//       done();
+//     }
+//   };
+//
+// `absl::bind_front()` stores bound arguments explicitly using the type passed
+// rather than implicitly based on the type accepted by its functor.
+//
+// Example: Binding arguments explicitly.
+//
+//   void LogStringView(absl::string_view sv) {
+//     LOG(INFO) << sv;
+//   }
+//
+//   Executor* e = Executor::DefaultExecutor();
+//   std::string s = "hello";
+//   absl::string_view sv = s;
+//
+//   // absl::bind_front(LogStringView, arg) makes a copy of arg and stores it.
+//   e->Schedule(absl::bind_front(LogStringView, sv)); // ERROR: dangling
+//                                                     // string_view.
+//
+//   e->Schedule(absl::bind_front(LogStringView, s));  // OK: stores a copy of
+//                                                     // s.
+//
+// To store some of the arguments passed to `absl::bind_front()` by reference,
+//  use std::ref()` and `std::cref()`.
+//
+// Example: Storing some of the bound arguments by reference.
+//
+//   class Service {
+//    public:
+//     void Serve(const Request& req, std::function<void()>* done) {
+//       // The request protocol buffer won't be deleted until done is called.
+//       // It's safe to store a reference to it inside the functor.
+//       Executor::DefaultExecutor()->Schedule(
+//           absl::bind_front(&Service::BlockingServe, this, std::cref(req),
+//           done));
+//     }
+//
+//    private:
+//     void BlockingServe(const Request& req, std::function<void()>* done);
+//   };
+//
+// Example: Storing bound arguments by reference.
+//
+//   void Print(const std::string& a, const std::string& b) {
+//     std::cerr << a << b;
+//   }
+//
+//   std::string hi = "Hello, ";
+//   std::vector<std::string> names = {"Chuk", "Gek"};
+//   // Doesn't copy hi.
+//   for_each(names.begin(), names.end(),
+//            absl::bind_front(Print, std::ref(hi)));
+//
+//   // DO NOT DO THIS: the functor may outlive "hi", resulting in
+//   // dangling references.
+//   foo->DoInFuture(absl::bind_front(Print, std::ref(hi), "Guest"));  // BAD!
+//   auto f = absl::bind_front(Print, std::ref(hi), "Guest"); // BAD!
+//
+// Example: Storing reference-like types.
+//
+//   void Print(absl::string_view a, const std::string& b) {
+//     std::cerr << a << b;
+//   }
+//
+//   std::string hi = "Hello, ";
+//   // Copies "hi".
+//   absl::bind_front(Print, hi)("Chuk");
+//
+//   // Compile error: std::reference_wrapper<const string> is not implicitly
+//   // convertible to string_view.
+//   // absl::bind_front(Print, std::cref(hi))("Chuk");
+//
+//   // Doesn't copy "hi".
+//   absl::bind_front(Print, absl::string_view(hi))("Chuk");
+//
+template <class F, class... BoundArgs>
+constexpr functional_internal::bind_front_t<F, BoundArgs...> bind_front(
+    F&& func, BoundArgs&&... args) {
+  return functional_internal::bind_front_t<F, BoundArgs...>(
+      absl::in_place, absl::forward<F>(func),
+      absl::forward<BoundArgs>(args)...);
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FUNCTIONAL_BIND_FRONT_H_
diff --git a/absl/functional/bind_front_test.cc b/absl/functional/bind_front_test.cc
new file mode 100644
index 0000000..4801a81
--- /dev/null
+++ b/absl/functional/bind_front_test.cc
@@ -0,0 +1,231 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/functional/bind_front.h"
+
+#include <stddef.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/memory/memory.h"
+
+namespace {
+
+char CharAt(const char* s, size_t index) { return s[index]; }
+
+TEST(BindTest, Basics) {
+  EXPECT_EQ('C', absl::bind_front(CharAt)("ABC", 2));
+  EXPECT_EQ('C', absl::bind_front(CharAt, "ABC")(2));
+  EXPECT_EQ('C', absl::bind_front(CharAt, "ABC", 2)());
+}
+
+TEST(BindTest, Lambda) {
+  auto lambda = [](int x, int y, int z) { return x + y + z; };
+  EXPECT_EQ(6, absl::bind_front(lambda)(1, 2, 3));
+  EXPECT_EQ(6, absl::bind_front(lambda, 1)(2, 3));
+  EXPECT_EQ(6, absl::bind_front(lambda, 1, 2)(3));
+  EXPECT_EQ(6, absl::bind_front(lambda, 1, 2, 3)());
+}
+
+struct Functor {
+  std::string operator()() & { return "&"; }
+  std::string operator()() const& { return "const&"; }
+  std::string operator()() && { return "&&"; }
+  std::string operator()() const&& { return "const&&"; }
+};
+
+TEST(BindTest, PerfectForwardingOfBoundArgs) {
+  auto f = absl::bind_front(Functor());
+  const auto& cf = f;
+  EXPECT_EQ("&", f());
+  EXPECT_EQ("const&", cf());
+  EXPECT_EQ("&&", std::move(f)());
+  EXPECT_EQ("const&&", std::move(cf)());
+}
+
+struct ArgDescribe {
+  std::string operator()(int&) const { return "&"; }             // NOLINT
+  std::string operator()(const int&) const { return "const&"; }  // NOLINT
+  std::string operator()(int&&) const { return "&&"; }
+  std::string operator()(const int&&) const { return "const&&"; }
+};
+
+TEST(BindTest, PerfectForwardingOfFreeArgs) {
+  ArgDescribe f;
+  int i;
+  EXPECT_EQ("&", absl::bind_front(f)(static_cast<int&>(i)));
+  EXPECT_EQ("const&", absl::bind_front(f)(static_cast<const int&>(i)));
+  EXPECT_EQ("&&", absl::bind_front(f)(static_cast<int&&>(i)));
+  EXPECT_EQ("const&&", absl::bind_front(f)(static_cast<const int&&>(i)));
+}
+
+struct NonCopyableFunctor {
+  NonCopyableFunctor() = default;
+  NonCopyableFunctor(const NonCopyableFunctor&) = delete;
+  NonCopyableFunctor& operator=(const NonCopyableFunctor&) = delete;
+  const NonCopyableFunctor* operator()() const { return this; }
+};
+
+TEST(BindTest, RefToFunctor) {
+  // It won't copy/move the functor and use the original object.
+  NonCopyableFunctor ncf;
+  auto bound_ncf = absl::bind_front(std::ref(ncf));
+  auto bound_ncf_copy = bound_ncf;
+  EXPECT_EQ(&ncf, bound_ncf_copy());
+}
+
+struct Struct {
+  std::string value;
+};
+
+TEST(BindTest, StoreByCopy) {
+  Struct s = {"hello"};
+  auto f = absl::bind_front(&Struct::value, s);
+  auto g = f;
+  EXPECT_EQ("hello", f());
+  EXPECT_EQ("hello", g());
+  EXPECT_NE(&s.value, &f());
+  EXPECT_NE(&s.value, &g());
+  EXPECT_NE(&g(), &f());
+}
+
+struct NonCopyable {
+  explicit NonCopyable(const std::string& s) : value(s) {}
+  NonCopyable(const NonCopyable&) = delete;
+  NonCopyable& operator=(const NonCopyable&) = delete;
+
+  std::string value;
+};
+
+const std::string& GetNonCopyableValue(const NonCopyable& n) { return n.value; }
+
+TEST(BindTest, StoreByRef) {
+  NonCopyable s("hello");
+  auto f = absl::bind_front(&GetNonCopyableValue, std::ref(s));
+  EXPECT_EQ("hello", f());
+  EXPECT_EQ(&s.value, &f());
+  auto g = std::move(f);  // NOLINT
+  EXPECT_EQ("hello", g());
+  EXPECT_EQ(&s.value, &g());
+  s.value = "goodbye";
+  EXPECT_EQ("goodbye", g());
+}
+
+TEST(BindTest, StoreByCRef) {
+  NonCopyable s("hello");
+  auto f = absl::bind_front(&GetNonCopyableValue, std::cref(s));
+  EXPECT_EQ("hello", f());
+  EXPECT_EQ(&s.value, &f());
+  auto g = std::move(f);  // NOLINT
+  EXPECT_EQ("hello", g());
+  EXPECT_EQ(&s.value, &g());
+  s.value = "goodbye";
+  EXPECT_EQ("goodbye", g());
+}
+
+const std::string& GetNonCopyableValueByWrapper(
+    std::reference_wrapper<NonCopyable> n) {
+  return n.get().value;
+}
+
+TEST(BindTest, StoreByRefInvokeByWrapper) {
+  NonCopyable s("hello");
+  auto f = absl::bind_front(GetNonCopyableValueByWrapper, std::ref(s));
+  EXPECT_EQ("hello", f());
+  EXPECT_EQ(&s.value, &f());
+  auto g = std::move(f);
+  EXPECT_EQ("hello", g());
+  EXPECT_EQ(&s.value, &g());
+  s.value = "goodbye";
+  EXPECT_EQ("goodbye", g());
+}
+
+TEST(BindTest, StoreByPointer) {
+  NonCopyable s("hello");
+  auto f = absl::bind_front(&NonCopyable::value, &s);
+  EXPECT_EQ("hello", f());
+  EXPECT_EQ(&s.value, &f());
+  auto g = std::move(f);
+  EXPECT_EQ("hello", g());
+  EXPECT_EQ(&s.value, &g());
+}
+
+int Sink(std::unique_ptr<int> p) {
+  return *p;
+}
+
+std::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); }
+
+TEST(BindTest, NonCopyableArg) {
+  EXPECT_EQ(42, absl::bind_front(Sink)(absl::make_unique<int>(42)));
+  EXPECT_EQ(42, absl::bind_front(Sink, absl::make_unique<int>(42))());
+}
+
+TEST(BindTest, NonCopyableResult) {
+  EXPECT_THAT(absl::bind_front(Factory)(42), ::testing::Pointee(42));
+  EXPECT_THAT(absl::bind_front(Factory, 42)(), ::testing::Pointee(42));
+}
+
+// is_copy_constructible<FalseCopyable<unique_ptr<T>> is true but an attempt to
+// instantiate the copy constructor leads to a compile error. This is similar
+// to how standard containers behave.
+template <class T>
+struct FalseCopyable {
+  FalseCopyable() {}
+  FalseCopyable(const FalseCopyable& other) : m(other.m) {}
+  FalseCopyable(FalseCopyable&& other) : m(std::move(other.m)) {}
+  T m;
+};
+
+int GetMember(FalseCopyable<std::unique_ptr<int>> x) { return *x.m; }
+
+TEST(BindTest, WrappedMoveOnly) {
+  FalseCopyable<std::unique_ptr<int>> x;
+  x.m = absl::make_unique<int>(42);
+  auto f = absl::bind_front(&GetMember, std::move(x));
+  EXPECT_EQ(42, std::move(f)());
+}
+
+int Plus(int a, int b) { return a + b; }
+
+TEST(BindTest, ConstExpr) {
+  constexpr auto f = absl::bind_front(CharAt);
+  EXPECT_EQ(f("ABC", 1), 'B');
+  static constexpr int five = 5;
+  constexpr auto plus5 = absl::bind_front(Plus, five);
+  EXPECT_EQ(plus5(1), 6);
+
+  // There seems to be a bug in MSVC dealing constexpr construction of
+  // char[]. Notice 'plus5' above; 'int' works just fine.
+#if !(defined(_MSC_VER) && _MSC_VER < 1910)
+  static constexpr char data[] = "DEF";
+  constexpr auto g = absl::bind_front(CharAt, data);
+  EXPECT_EQ(g(1), 'E');
+#endif
+}
+
+struct ManglingCall {
+  int operator()(int, double, std::string) const { return 0; }
+};
+
+TEST(BindTest, Mangling) {
+  // We just want to generate a particular instantiation to see its mangling.
+  absl::bind_front(ManglingCall{}, 1, 3.3)("A");
+}
+
+}  // namespace
diff --git a/absl/functional/function_ref.h b/absl/functional/function_ref.h
new file mode 100644
index 0000000..6e03ac2
--- /dev/null
+++ b/absl/functional/function_ref.h
@@ -0,0 +1,139 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: function_ref.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `absl::FunctionRef` type for holding a
+// non-owning reference to an object of any invocable type. This function
+// reference is typically most useful as a type-erased argument type for
+// accepting function types that neither take ownership nor copy the type; using
+// the reference type in this case avoids a copy and an allocation. Best
+// practices of other non-owning reference-like objects (such as
+// `absl::string_view`) apply here.
+//
+//  An `absl::FunctionRef` is similar in usage to a `std::function` but has the
+//  following differences:
+//
+//  * It doesn't own the underlying object.
+//  * It doesn't have a null or empty state.
+//  * It never performs deep copies or allocations.
+//  * It's much faster and cheaper to construct.
+//  * It's trivially copyable and destructable.
+//
+// Generally, `absl::FunctionRef` should not be used as a return value, data
+// member, or to initialize a `std::function`. Such usages will often lead to
+// problematic lifetime issues. Once you convert something to an
+// `absl::FunctionRef` you cannot make a deep copy later.
+//
+// This class is suitable for use wherever a "const std::function<>&"
+// would be used without making a copy. ForEach functions and other versions of
+// the visitor pattern are a good example of when this class should be used.
+//
+// This class is trivial to copy and should be passed by value.
+#ifndef ABSL_FUNCTIONAL_FUNCTION_REF_H_
+#define ABSL_FUNCTIONAL_FUNCTION_REF_H_
+
+#include <cassert>
+#include <functional>
+#include <type_traits>
+
+#include "absl/functional/internal/function_ref.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// FunctionRef
+//
+// Dummy class declaration to allow the partial specialization based on function
+// types below.
+template <typename T>
+class FunctionRef;
+
+// FunctionRef
+//
+// An `absl::FunctionRef` is a lightweight wrapper to any invokable object with
+// a compatible signature. Generally, an `absl::FunctionRef` should only be used
+// as an argument type and should be preferred as an argument over a const
+// reference to a `std::function`.
+//
+// Example:
+//
+//   // The following function takes a function callback by const reference
+//   bool Visitor(const std::function<void(my_proto&,
+//                                         absl::string_view)>& callback);
+//
+//   // Assuming that the function is not stored or otherwise copied, it can be
+//   // replaced by an `absl::FunctionRef`:
+//   bool Visitor(absl::FunctionRef<void(my_proto&, absl::string_view)>
+//                  callback);
+//
+// Note: the assignment operator within an `absl::FunctionRef` is intentionally
+// deleted to prevent misuse; because the `absl::FunctionRef` does not own the
+// underlying type, assignment likely indicates misuse.
+template <typename R, typename... Args>
+class FunctionRef<R(Args...)> {
+ private:
+  // Used to disable constructors for objects that are not compatible with the
+  // signature of this FunctionRef.
+  template <typename F,
+            typename FR = absl::base_internal::invoke_result_t<F, Args&&...>>
+  using EnableIfCompatible =
+      typename std::enable_if<std::is_void<R>::value ||
+                              std::is_convertible<FR, R>::value>::type;
+
+ public:
+  // Constructs a FunctionRef from any invokable type.
+  template <typename F, typename = EnableIfCompatible<const F&>>
+  FunctionRef(const F& f)  // NOLINT(runtime/explicit)
+      : invoker_(&absl::functional_internal::InvokeObject<F, R, Args...>) {
+    absl::functional_internal::AssertNonNull(f);
+    ptr_.obj = &f;
+  }
+
+  // Overload for function pointers. This eliminates a level of indirection that
+  // would happen if the above overload was used (it lets us store the pointer
+  // instead of a pointer to a pointer).
+  //
+  // This overload is also used for references to functions, since references to
+  // functions can decay to function pointers implicitly.
+  template <
+      typename F, typename = EnableIfCompatible<F*>,
+      absl::functional_internal::EnableIf<absl::is_function<F>::value> = 0>
+  FunctionRef(F* f)  // NOLINT(runtime/explicit)
+      : invoker_(&absl::functional_internal::InvokeFunction<F*, R, Args...>) {
+    assert(f != nullptr);
+    ptr_.fun = reinterpret_cast<decltype(ptr_.fun)>(f);
+  }
+
+  // To help prevent subtle lifetime bugs, FunctionRef is not assignable.
+  // Typically, it should only be used as an argument type.
+  FunctionRef& operator=(const FunctionRef& rhs) = delete;
+
+  // Call the underlying object.
+  R operator()(Args... args) const {
+    return invoker_(ptr_, std::forward<Args>(args)...);
+  }
+
+ private:
+  absl::functional_internal::VoidPtr ptr_;
+  absl::functional_internal::Invoker<R, Args...> invoker_;
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FUNCTIONAL_FUNCTION_REF_H_
diff --git a/absl/functional/function_ref_benchmark.cc b/absl/functional/function_ref_benchmark.cc
new file mode 100644
index 0000000..045305b
--- /dev/null
+++ b/absl/functional/function_ref_benchmark.cc
@@ -0,0 +1,142 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/functional/function_ref.h"
+
+#include <memory>
+
+#include "benchmark/benchmark.h"
+#include "absl/base/attributes.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+int dummy = 0;
+
+void FreeFunction() { benchmark::DoNotOptimize(dummy); }
+
+struct TrivialFunctor {
+  void operator()() const { benchmark::DoNotOptimize(dummy); }
+};
+
+struct LargeFunctor {
+  void operator()() const { benchmark::DoNotOptimize(this); }
+  std::string a, b, c;
+};
+
+template <typename Function, typename... Args>
+void ABSL_ATTRIBUTE_NOINLINE CallFunction(Function f, Args&&... args) {
+  f(std::forward<Args>(args)...);
+}
+
+template <typename Function, typename Callable, typename... Args>
+void ConstructAndCallFunctionBenchmark(benchmark::State& state,
+                                       const Callable& c, Args&&... args) {
+  for (auto _ : state) {
+    CallFunction<Function>(c, std::forward<Args>(args)...);
+  }
+}
+
+void BM_TrivialStdFunction(benchmark::State& state) {
+  ConstructAndCallFunctionBenchmark<std::function<void()>>(state,
+                                                           TrivialFunctor{});
+}
+BENCHMARK(BM_TrivialStdFunction);
+
+void BM_TrivialFunctionRef(benchmark::State& state) {
+  ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state,
+                                                         TrivialFunctor{});
+}
+BENCHMARK(BM_TrivialFunctionRef);
+
+void BM_LargeStdFunction(benchmark::State& state) {
+  ConstructAndCallFunctionBenchmark<std::function<void()>>(state,
+                                                           LargeFunctor{});
+}
+BENCHMARK(BM_LargeStdFunction);
+
+void BM_LargeFunctionRef(benchmark::State& state) {
+  ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, LargeFunctor{});
+}
+BENCHMARK(BM_LargeFunctionRef);
+
+void BM_FunPtrStdFunction(benchmark::State& state) {
+  ConstructAndCallFunctionBenchmark<std::function<void()>>(state, FreeFunction);
+}
+BENCHMARK(BM_FunPtrStdFunction);
+
+void BM_FunPtrFunctionRef(benchmark::State& state) {
+  ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, FreeFunction);
+}
+BENCHMARK(BM_FunPtrFunctionRef);
+
+// Doesn't include construction or copy overhead in the loop.
+template <typename Function, typename Callable, typename... Args>
+void CallFunctionBenchmark(benchmark::State& state, const Callable& c,
+                           Args... args) {
+  Function f = c;
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(&f);
+    f(args...);
+  }
+}
+
+struct FunctorWithTrivialArgs {
+  void operator()(int a, int b, int c) const {
+    benchmark::DoNotOptimize(a);
+    benchmark::DoNotOptimize(b);
+    benchmark::DoNotOptimize(c);
+  }
+};
+
+void BM_TrivialArgsStdFunction(benchmark::State& state) {
+  CallFunctionBenchmark<std::function<void(int, int, int)>>(
+      state, FunctorWithTrivialArgs{}, 1, 2, 3);
+}
+BENCHMARK(BM_TrivialArgsStdFunction);
+
+void BM_TrivialArgsFunctionRef(benchmark::State& state) {
+  CallFunctionBenchmark<FunctionRef<void(int, int, int)>>(
+      state, FunctorWithTrivialArgs{}, 1, 2, 3);
+}
+BENCHMARK(BM_TrivialArgsFunctionRef);
+
+struct FunctorWithNonTrivialArgs {
+  void operator()(std::string a, std::string b, std::string c) const {
+    benchmark::DoNotOptimize(&a);
+    benchmark::DoNotOptimize(&b);
+    benchmark::DoNotOptimize(&c);
+  }
+};
+
+void BM_NonTrivialArgsStdFunction(benchmark::State& state) {
+  std::string a, b, c;
+  CallFunctionBenchmark<
+      std::function<void(std::string, std::string, std::string)>>(
+      state, FunctorWithNonTrivialArgs{}, a, b, c);
+}
+BENCHMARK(BM_NonTrivialArgsStdFunction);
+
+void BM_NonTrivialArgsFunctionRef(benchmark::State& state) {
+  std::string a, b, c;
+  CallFunctionBenchmark<
+      FunctionRef<void(std::string, std::string, std::string)>>(
+      state, FunctorWithNonTrivialArgs{}, a, b, c);
+}
+BENCHMARK(BM_NonTrivialArgsFunctionRef);
+
+}  // namespace
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/functional/function_ref_test.cc b/absl/functional/function_ref_test.cc
new file mode 100644
index 0000000..3aa5974
--- /dev/null
+++ b/absl/functional/function_ref_test.cc
@@ -0,0 +1,257 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/functional/function_ref.h"
+
+#include <memory>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/container/internal/test_instance_tracker.h"
+#include "absl/memory/memory.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+void RunFun(FunctionRef<void()> f) { f(); }
+
+TEST(FunctionRefTest, Lambda) {
+  bool ran = false;
+  RunFun([&] { ran = true; });
+  EXPECT_TRUE(ran);
+}
+
+int Function() { return 1337; }
+
+TEST(FunctionRefTest, Function1) {
+  FunctionRef<int()> ref(&Function);
+  EXPECT_EQ(1337, ref());
+}
+
+TEST(FunctionRefTest, Function2) {
+  FunctionRef<int()> ref(Function);
+  EXPECT_EQ(1337, ref());
+}
+
+int NoExceptFunction() noexcept { return 1337; }
+
+// TODO(jdennett): Add a test for noexcept member functions.
+TEST(FunctionRefTest, NoExceptFunction) {
+  FunctionRef<int()> ref(NoExceptFunction);
+  EXPECT_EQ(1337, ref());
+}
+
+TEST(FunctionRefTest, ForwardsArgs) {
+  auto l = [](std::unique_ptr<int> i) { return *i; };
+  FunctionRef<int(std::unique_ptr<int>)> ref(l);
+  EXPECT_EQ(42, ref(absl::make_unique<int>(42)));
+}
+
+TEST(FunctionRef, ReturnMoveOnly) {
+  auto l = [] { return absl::make_unique<int>(29); };
+  FunctionRef<std::unique_ptr<int>()> ref(l);
+  EXPECT_EQ(29, *ref());
+}
+
+TEST(FunctionRef, ManyArgs) {
+  auto l = [](int a, int b, int c) { return a + b + c; };
+  FunctionRef<int(int, int, int)> ref(l);
+  EXPECT_EQ(6, ref(1, 2, 3));
+}
+
+TEST(FunctionRef, VoidResultFromNonVoidFunctor) {
+  bool ran = false;
+  auto l = [&]() -> int {
+    ran = true;
+    return 2;
+  };
+  FunctionRef<void()> ref(l);
+  ref();
+  EXPECT_TRUE(ran);
+}
+
+TEST(FunctionRef, CastFromDerived) {
+  struct Base {};
+  struct Derived : public Base {};
+
+  Derived d;
+  auto l1 = [&](Base* b) { EXPECT_EQ(&d, b); };
+  FunctionRef<void(Derived*)> ref1(l1);
+  ref1(&d);
+
+  auto l2 = [&]() -> Derived* { return &d; };
+  FunctionRef<Base*()> ref2(l2);
+  EXPECT_EQ(&d, ref2());
+}
+
+TEST(FunctionRef, VoidResultFromNonVoidFuncton) {
+  FunctionRef<void()> ref(Function);
+  ref();
+}
+
+TEST(FunctionRef, MemberPtr) {
+  struct S {
+    int i;
+  };
+
+  S s{1100111};
+  auto mem_ptr = &S::i;
+  FunctionRef<int(const S& s)> ref(mem_ptr);
+  EXPECT_EQ(1100111, ref(s));
+}
+
+TEST(FunctionRef, MemberFun) {
+  struct S {
+    int i;
+    int get_i() const { return i; }
+  };
+
+  S s{22};
+  auto mem_fun_ptr = &S::get_i;
+  FunctionRef<int(const S& s)> ref(mem_fun_ptr);
+  EXPECT_EQ(22, ref(s));
+}
+
+TEST(FunctionRef, MemberFunRefqualified) {
+  struct S {
+    int i;
+    int get_i() && { return i; }
+  };
+  auto mem_fun_ptr = &S::get_i;
+  S s{22};
+  FunctionRef<int(S && s)> ref(mem_fun_ptr);
+  EXPECT_EQ(22, ref(std::move(s)));
+}
+
+#if !defined(_WIN32) && defined(GTEST_HAS_DEATH_TEST)
+
+TEST(FunctionRef, MemberFunRefqualifiedNull) {
+  struct S {
+    int i;
+    int get_i() && { return i; }
+  };
+  auto mem_fun_ptr = &S::get_i;
+  mem_fun_ptr = nullptr;
+  EXPECT_DEBUG_DEATH({ FunctionRef<int(S && s)> ref(mem_fun_ptr); }, "");
+}
+
+TEST(FunctionRef, NullMemberPtrAssertFails) {
+  struct S {
+    int i;
+  };
+  using MemberPtr = int S::*;
+  MemberPtr mem_ptr = nullptr;
+  EXPECT_DEBUG_DEATH({ FunctionRef<int(const S& s)> ref(mem_ptr); }, "");
+}
+
+#endif  // GTEST_HAS_DEATH_TEST
+
+TEST(FunctionRef, CopiesAndMovesPerPassByValue) {
+  absl::test_internal::InstanceTracker tracker;
+  absl::test_internal::CopyableMovableInstance instance(0);
+  auto l = [](absl::test_internal::CopyableMovableInstance) {};
+  FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
+  ref(instance);
+  EXPECT_EQ(tracker.copies(), 1);
+  EXPECT_EQ(tracker.moves(), 1);
+}
+
+TEST(FunctionRef, CopiesAndMovesPerPassByRef) {
+  absl::test_internal::InstanceTracker tracker;
+  absl::test_internal::CopyableMovableInstance instance(0);
+  auto l = [](const absl::test_internal::CopyableMovableInstance&) {};
+  FunctionRef<void(const absl::test_internal::CopyableMovableInstance&)> ref(l);
+  ref(instance);
+  EXPECT_EQ(tracker.copies(), 0);
+  EXPECT_EQ(tracker.moves(), 0);
+}
+
+TEST(FunctionRef, CopiesAndMovesPerPassByValueCallByMove) {
+  absl::test_internal::InstanceTracker tracker;
+  absl::test_internal::CopyableMovableInstance instance(0);
+  auto l = [](absl::test_internal::CopyableMovableInstance) {};
+  FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
+  ref(std::move(instance));
+  EXPECT_EQ(tracker.copies(), 0);
+  EXPECT_EQ(tracker.moves(), 2);
+}
+
+TEST(FunctionRef, CopiesAndMovesPerPassByValueToRef) {
+  absl::test_internal::InstanceTracker tracker;
+  absl::test_internal::CopyableMovableInstance instance(0);
+  auto l = [](const absl::test_internal::CopyableMovableInstance&) {};
+  FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
+  ref(std::move(instance));
+  EXPECT_EQ(tracker.copies(), 0);
+  EXPECT_EQ(tracker.moves(), 1);
+}
+
+TEST(FunctionRef, PassByValueTypes) {
+  using absl::functional_internal::Invoker;
+  using absl::functional_internal::VoidPtr;
+  using absl::test_internal::CopyableMovableInstance;
+  struct Trivial {
+    void* p[2];
+  };
+  struct LargeTrivial {
+    void* p[3];
+  };
+
+  static_assert(std::is_same<Invoker<void, int>, void (*)(VoidPtr, int)>::value,
+                "Scalar types should be passed by value");
+  static_assert(
+      std::is_same<Invoker<void, Trivial>, void (*)(VoidPtr, Trivial)>::value,
+      "Small trivial types should be passed by value");
+  static_assert(std::is_same<Invoker<void, LargeTrivial>,
+                             void (*)(VoidPtr, LargeTrivial &&)>::value,
+                "Large trivial types should be passed by rvalue reference");
+  static_assert(
+      std::is_same<Invoker<void, CopyableMovableInstance>,
+                   void (*)(VoidPtr, CopyableMovableInstance &&)>::value,
+      "Types with copy/move ctor should be passed by rvalue reference");
+
+  // References are passed as references.
+  static_assert(
+      std::is_same<Invoker<void, int&>, void (*)(VoidPtr, int&)>::value,
+      "Reference types should be preserved");
+  static_assert(
+      std::is_same<Invoker<void, CopyableMovableInstance&>,
+                   void (*)(VoidPtr, CopyableMovableInstance&)>::value,
+      "Reference types should be preserved");
+  static_assert(
+      std::is_same<Invoker<void, CopyableMovableInstance&&>,
+                   void (*)(VoidPtr, CopyableMovableInstance &&)>::value,
+      "Reference types should be preserved");
+
+  // Make sure the address of an object received by reference is the same as the
+  // addess of the object passed by the caller.
+  {
+    LargeTrivial obj;
+    auto test = [&obj](LargeTrivial& input) { ASSERT_EQ(&input, &obj); };
+    absl::FunctionRef<void(LargeTrivial&)> ref(test);
+    ref(obj);
+  }
+
+  {
+    Trivial obj;
+    auto test = [&obj](Trivial& input) { ASSERT_EQ(&input, &obj); };
+    absl::FunctionRef<void(Trivial&)> ref(test);
+    ref(obj);
+  }
+}
+
+}  // namespace
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/functional/internal/front_binder.h b/absl/functional/internal/front_binder.h
new file mode 100644
index 0000000..45f52de
--- /dev/null
+++ b/absl/functional/internal/front_binder.h
@@ -0,0 +1,95 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Implementation details for `absl::bind_front()`.
+
+#ifndef ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_
+#define ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/internal/invoke.h"
+#include "absl/container/internal/compressed_tuple.h"
+#include "absl/meta/type_traits.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace functional_internal {
+
+// Invoke the method, expanding the tuple of bound arguments.
+template <class R, class Tuple, size_t... Idx, class... Args>
+R Apply(Tuple&& bound, absl::index_sequence<Idx...>, Args&&... free) {
+  return base_internal::invoke(
+      absl::forward<Tuple>(bound).template get<Idx>()...,
+      absl::forward<Args>(free)...);
+}
+
+template <class F, class... BoundArgs>
+class FrontBinder {
+  using BoundArgsT = absl::container_internal::CompressedTuple<F, BoundArgs...>;
+  using Idx = absl::make_index_sequence<sizeof...(BoundArgs) + 1>;
+
+  BoundArgsT bound_args_;
+
+ public:
+  template <class... Ts>
+  constexpr explicit FrontBinder(absl::in_place_t, Ts&&... ts)
+      : bound_args_(absl::forward<Ts>(ts)...) {}
+
+  template <class... FreeArgs, class R = base_internal::invoke_result_t<
+                                   F&, BoundArgs&..., FreeArgs&&...>>
+  R operator()(FreeArgs&&... free_args) & {
+    return functional_internal::Apply<R>(bound_args_, Idx(),
+                                         absl::forward<FreeArgs>(free_args)...);
+  }
+
+  template <class... FreeArgs,
+            class R = base_internal::invoke_result_t<
+                const F&, const BoundArgs&..., FreeArgs&&...>>
+  R operator()(FreeArgs&&... free_args) const& {
+    return functional_internal::Apply<R>(bound_args_, Idx(),
+                                         absl::forward<FreeArgs>(free_args)...);
+  }
+
+  template <class... FreeArgs, class R = base_internal::invoke_result_t<
+                                   F&&, BoundArgs&&..., FreeArgs&&...>>
+  R operator()(FreeArgs&&... free_args) && {
+    // This overload is called when *this is an rvalue. If some of the bound
+    // arguments are stored by value or rvalue reference, we move them.
+    return functional_internal::Apply<R>(absl::move(bound_args_), Idx(),
+                                         absl::forward<FreeArgs>(free_args)...);
+  }
+
+  template <class... FreeArgs,
+            class R = base_internal::invoke_result_t<
+                const F&&, const BoundArgs&&..., FreeArgs&&...>>
+  R operator()(FreeArgs&&... free_args) const&& {
+    // This overload is called when *this is an rvalue. If some of the bound
+    // arguments are stored by value or rvalue reference, we move them.
+    return functional_internal::Apply<R>(absl::move(bound_args_), Idx(),
+                                         absl::forward<FreeArgs>(free_args)...);
+  }
+};
+
+template <class F, class... BoundArgs>
+using bind_front_t = FrontBinder<decay_t<F>, absl::decay_t<BoundArgs>...>;
+
+}  // namespace functional_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_
diff --git a/absl/functional/internal/function_ref.h b/absl/functional/internal/function_ref.h
new file mode 100644
index 0000000..b5bb8b4
--- /dev/null
+++ b/absl/functional/internal/function_ref.h
@@ -0,0 +1,106 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
+#define ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
+
+#include <cassert>
+#include <functional>
+#include <type_traits>
+
+#include "absl/base/internal/invoke.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace functional_internal {
+
+// Like a void* that can handle function pointers as well. The standard does not
+// allow function pointers to round-trip through void*, but void(*)() is fine.
+//
+// Note: It's important that this class remains trivial and is the same size as
+// a pointer, since this allows the compiler to perform tail-call optimizations
+// when the underlying function is a callable object with a matching signature.
+union VoidPtr {
+  const void* obj;
+  void (*fun)();
+};
+
+// Chooses the best type for passing T as an argument.
+// Attempt to be close to SystemV AMD64 ABI. Objects with trivial copy ctor are
+// passed by value.
+template <typename T>
+constexpr bool PassByValue() {
+  return !std::is_lvalue_reference<T>::value &&
+         absl::is_trivially_copy_constructible<T>::value &&
+         absl::is_trivially_copy_assignable<
+             typename std::remove_cv<T>::type>::value &&
+         std::is_trivially_destructible<T>::value &&
+         sizeof(T) <= 2 * sizeof(void*);
+}
+
+template <typename T>
+struct ForwardT : std::conditional<PassByValue<T>(), T, T&&> {};
+
+// An Invoker takes a pointer to the type-erased invokable object, followed by
+// the arguments that the invokable object expects.
+//
+// Note: The order of arguments here is an optimization, since member functions
+// have an implicit "this" pointer as their first argument, putting VoidPtr
+// first allows the compiler to perform tail-call optimization in many cases.
+template <typename R, typename... Args>
+using Invoker = R (*)(VoidPtr, typename ForwardT<Args>::type...);
+
+//
+// InvokeObject and InvokeFunction provide static "Invoke" functions that can be
+// used as Invokers for objects or functions respectively.
+//
+// static_cast<R> handles the case the return type is void.
+template <typename Obj, typename R, typename... Args>
+R InvokeObject(VoidPtr ptr, typename ForwardT<Args>::type... args) {
+  auto o = static_cast<const Obj*>(ptr.obj);
+  return static_cast<R>(
+      absl::base_internal::invoke(*o, std::forward<Args>(args)...));
+}
+
+template <typename Fun, typename R, typename... Args>
+R InvokeFunction(VoidPtr ptr, typename ForwardT<Args>::type... args) {
+  auto f = reinterpret_cast<Fun>(ptr.fun);
+  return static_cast<R>(
+      absl::base_internal::invoke(f, std::forward<Args>(args)...));
+}
+
+template <typename Sig>
+void AssertNonNull(const std::function<Sig>& f) {
+  assert(f != nullptr);
+  (void)f;
+}
+
+template <typename F>
+void AssertNonNull(const F&) {}
+
+template <typename F, typename C>
+void AssertNonNull(F C::*f) {
+  assert(f != nullptr);
+  (void)f;
+}
+
+template <bool C>
+using EnableIf = typename ::std::enable_if<C, int>::type;
+
+}  // namespace functional_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
diff --git a/absl/hash/BUILD.bazel b/absl/hash/BUILD.bazel
index c51248a..90c6c8a 100644
--- a/absl/hash/BUILD.bazel
+++ b/absl/hash/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "hash",
@@ -37,6 +37,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":city",
+        ":wyhash",
         "//absl/base:core_headers",
         "//absl/base:endian",
         "//absl/container:fixed_array",
@@ -71,15 +72,35 @@
     deps = [
         ":hash",
         ":hash_testing",
+        ":spy_hash_state",
         "//absl/base:core_headers",
         "//absl/container:flat_hash_set",
-        "//absl/hash:spy_hash_state",
         "//absl/meta:type_traits",
         "//absl/numeric:int128",
+        "//absl/strings:cord_test_helpers",
         "@com_google_googletest//:gtest_main",
     ],
 )
 
+cc_binary(
+    name = "hash_benchmark",
+    testonly = 1,
+    srcs = ["hash_benchmark.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    tags = ["benchmark"],
+    visibility = ["//visibility:private"],
+    deps = [
+        ":hash",
+        "//absl/base:core_headers",
+        "//absl/random",
+        "//absl/strings",
+        "//absl/strings:cord",
+        "//absl/strings:cord_test_helpers",
+        "@com_github_google_benchmark//:benchmark_main",
+    ],
+)
+
 cc_library(
     name = "spy_hash_state",
     testonly = 1,
@@ -119,3 +140,30 @@
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_library(
+    name = "wyhash",
+    srcs = ["internal/wyhash.cc"],
+    hdrs = ["internal/wyhash.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        "//absl/base:config",
+        "//absl/base:endian",
+        "//absl/numeric:int128",
+    ],
+)
+
+cc_test(
+    name = "wyhash_test",
+    srcs = ["internal/wyhash_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":wyhash",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/hash/CMakeLists.txt b/absl/hash/CMakeLists.txt
index febc551..6d19877 100644
--- a/absl/hash/CMakeLists.txt
+++ b/absl/hash/CMakeLists.txt
@@ -24,7 +24,8 @@
     "internal/hash.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
-  DEPS
+    DEPS
+    absl::city
     absl::core_headers
     absl::endian
     absl::fixed_array
@@ -34,7 +35,7 @@
     absl::optional
     absl::variant
     absl::utility
-    absl::city
+    absl::wyhash
   PUBLIC
 )
 
@@ -62,6 +63,7 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::cord_test_helpers
     absl::hash
     absl::hash_testing
     absl::core_headers
@@ -113,3 +115,30 @@
     gmock_main
 )
 
+absl_cc_library(
+  NAME
+    wyhash
+  HDRS
+    "internal/wyhash.h"
+  SRCS
+    "internal/wyhash.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::config
+    absl::endian
+    absl::int128
+)
+
+absl_cc_test(
+  NAME
+    wyhash_test
+  SRCS
+    "internal/wyhash_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::wyhash
+    absl::strings
+    gmock_main
+)
diff --git a/absl/hash/hash.h b/absl/hash/hash.h
index 297dc9c..5de132c 100644
--- a/absl/hash/hash.h
+++ b/absl/hash/hash.h
@@ -37,8 +37,11 @@
 // types. Hashing of that combined state is separately done by `absl::Hash`.
 //
 // One should assume that a hash algorithm is chosen randomly at the start of
-// each process.  E.g., absl::Hash<int>()(9) in one process and
-// absl::Hash<int>()(9) in another process are likely to differ.
+// each process.  E.g., `absl::Hash<int>{}(9)` in one process and
+// `absl::Hash<int>{}(9)` in another process are likely to differ.
+//
+// `absl::Hash` is intended to strongly mix input bits with a target of passing
+// an [Avalanche Test](https://en.wikipedia.org/wiki/Avalanche_effect).
 //
 // Example:
 //
@@ -73,6 +76,7 @@
 #include "absl/hash/internal/hash.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // -----------------------------------------------------------------------------
 // `absl::Hash`
@@ -84,7 +88,6 @@
 //  * T is an arithmetic or pointer type
 //  * T defines an overload for `AbslHashValue(H, const T&)` for an arbitrary
 //    hash state `H`.
-//  - T defines a specialization of `HASH_NAMESPACE::hash<T>`
 //  - T defines a specialization of `std::hash<T>`
 //
 // `absl::Hash` intrinsically supports the following types:
@@ -97,6 +100,7 @@
 //   * std::tuple<Ts...>, if all the Ts... are hashable
 //   * std::unique_ptr and std::shared_ptr
 //   * All string-like types including:
+//     * absl::Cord
 //     * std::string
 //     * std::string_view (as well as any instance of std::basic_string that
 //       uses char and std::char_traits)
@@ -123,8 +127,6 @@
 //   * Natively supported types out of the box (see above)
 //   * Types for which an `AbslHashValue()` overload is provided (such as
 //     user-defined types). See "Adding Type Support to `absl::Hash`" below.
-//   * Types which define a `HASH_NAMESPACE::hash<T>` specialization (aka
-//     `__gnu_cxx::hash<T>` for gcc/Clang or `stdext::hash<T>` for MSVC)
 //   * Types which define a `std::hash<T>` specialization
 //
 // The fallback to legacy hash functions exists mainly for backwards
@@ -317,6 +319,7 @@
   void (*combine_contiguous_)(void*, const unsigned char*, size_t);
 };
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_HASH_HASH_H_
diff --git a/absl/hash/hash_benchmark.cc b/absl/hash/hash_benchmark.cc
new file mode 100644
index 0000000..d498ac2
--- /dev/null
+++ b/absl/hash/hash_benchmark.cc
@@ -0,0 +1,254 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string>
+#include <type_traits>
+#include <typeindex>
+#include <utility>
+#include <vector>
+
+#include "absl/base/attributes.h"
+#include "absl/hash/hash.h"
+#include "absl/random/random.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/cord_test_helpers.h"
+#include "absl/strings/string_view.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+using absl::Hash;
+
+template <template <typename> class H, typename T>
+void RunBenchmark(benchmark::State& state, T value) {
+  H<T> h;
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(value);
+    benchmark::DoNotOptimize(h(value));
+  }
+}
+
+}  // namespace
+
+template <typename T>
+using AbslHash = absl::Hash<T>;
+
+class TypeErasedInterface {
+ public:
+  virtual ~TypeErasedInterface() = default;
+
+  template <typename H>
+  friend H AbslHashValue(H state, const TypeErasedInterface& wrapper) {
+    state = H::combine(std::move(state), std::type_index(typeid(wrapper)));
+    wrapper.HashValue(absl::HashState::Create(&state));
+    return state;
+  }
+
+ private:
+  virtual void HashValue(absl::HashState state) const = 0;
+};
+
+template <typename T>
+struct TypeErasedAbslHash {
+  class Wrapper : public TypeErasedInterface {
+   public:
+    explicit Wrapper(const T& value) : value_(value) {}
+
+   private:
+    void HashValue(absl::HashState state) const override {
+      absl::HashState::combine(std::move(state), value_);
+    }
+
+    const T& value_;
+  };
+
+  size_t operator()(const T& value) {
+    return absl::Hash<Wrapper>{}(Wrapper(value));
+  }
+};
+
+template <typename FuncType>
+inline FuncType* ODRUseFunction(FuncType* ptr) {
+  volatile FuncType* dummy = ptr;
+  return dummy;
+}
+
+absl::Cord FlatCord(size_t size) {
+  absl::Cord result(std::string(size, 'a'));
+  result.Flatten();
+  return result;
+}
+
+absl::Cord FragmentedCord(size_t size) {
+  const size_t orig_size = size;
+  std::vector<std::string> chunks;
+  size_t chunk_size = std::max<size_t>(1, size / 10);
+  while (size > chunk_size) {
+    chunks.push_back(std::string(chunk_size, 'a'));
+    size -= chunk_size;
+  }
+  if (size > 0) {
+    chunks.push_back(std::string(size, 'a'));
+  }
+  absl::Cord result = absl::MakeFragmentedCord(chunks);
+  (void) orig_size;
+  assert(result.size() == orig_size);
+  return result;
+}
+
+// Generates a benchmark and a codegen method for the provided types.  The
+// codegen method provides a well known entrypoint for dumping assembly.
+#define MAKE_BENCHMARK(hash, name, ...)                          \
+  namespace {                                                    \
+  void BM_##hash##_##name(benchmark::State& state) {             \
+    RunBenchmark<hash>(state, __VA_ARGS__);                      \
+  }                                                              \
+  BENCHMARK(BM_##hash##_##name);                                 \
+  }                                                              \
+  size_t Codegen##hash##name(const decltype(__VA_ARGS__)& arg);  \
+  size_t Codegen##hash##name(const decltype(__VA_ARGS__)& arg) { \
+    return hash<decltype(__VA_ARGS__)>{}(arg);                   \
+  }                                                              \
+  bool absl_hash_test_odr_use##hash##name =                      \
+      ODRUseFunction(&Codegen##hash##name);
+
+MAKE_BENCHMARK(AbslHash, Int32, int32_t{});
+MAKE_BENCHMARK(AbslHash, Int64, int64_t{});
+MAKE_BENCHMARK(AbslHash, Double, 1.2);
+MAKE_BENCHMARK(AbslHash, DoubleZero, 0.0);
+MAKE_BENCHMARK(AbslHash, PairInt32Int32, std::pair<int32_t, int32_t>{});
+MAKE_BENCHMARK(AbslHash, PairInt64Int64, std::pair<int64_t, int64_t>{});
+MAKE_BENCHMARK(AbslHash, TupleInt32BoolInt64,
+               std::tuple<int32_t, bool, int64_t>{});
+MAKE_BENCHMARK(AbslHash, String_0, std::string());
+MAKE_BENCHMARK(AbslHash, String_10, std::string(10, 'a'));
+MAKE_BENCHMARK(AbslHash, String_30, std::string(30, 'a'));
+MAKE_BENCHMARK(AbslHash, String_90, std::string(90, 'a'));
+MAKE_BENCHMARK(AbslHash, String_200, std::string(200, 'a'));
+MAKE_BENCHMARK(AbslHash, String_5000, std::string(5000, 'a'));
+MAKE_BENCHMARK(AbslHash, Cord_Flat_0, absl::Cord());
+MAKE_BENCHMARK(AbslHash, Cord_Flat_10, FlatCord(10));
+MAKE_BENCHMARK(AbslHash, Cord_Flat_30, FlatCord(30));
+MAKE_BENCHMARK(AbslHash, Cord_Flat_90, FlatCord(90));
+MAKE_BENCHMARK(AbslHash, Cord_Flat_200, FlatCord(200));
+MAKE_BENCHMARK(AbslHash, Cord_Flat_5000, FlatCord(5000));
+MAKE_BENCHMARK(AbslHash, Cord_Fragmented_200, FragmentedCord(200));
+MAKE_BENCHMARK(AbslHash, Cord_Fragmented_5000, FragmentedCord(5000));
+MAKE_BENCHMARK(AbslHash, VectorInt64_10, std::vector<int64_t>(10));
+MAKE_BENCHMARK(AbslHash, VectorInt64_100, std::vector<int64_t>(100));
+MAKE_BENCHMARK(AbslHash, VectorDouble_10, std::vector<double>(10, 1.1));
+MAKE_BENCHMARK(AbslHash, VectorDouble_100, std::vector<double>(100, 1.1));
+MAKE_BENCHMARK(AbslHash, PairStringString_0,
+               std::make_pair(std::string(), std::string()));
+MAKE_BENCHMARK(AbslHash, PairStringString_10,
+               std::make_pair(std::string(10, 'a'), std::string(10, 'b')));
+MAKE_BENCHMARK(AbslHash, PairStringString_30,
+               std::make_pair(std::string(30, 'a'), std::string(30, 'b')));
+MAKE_BENCHMARK(AbslHash, PairStringString_90,
+               std::make_pair(std::string(90, 'a'), std::string(90, 'b')));
+MAKE_BENCHMARK(AbslHash, PairStringString_200,
+               std::make_pair(std::string(200, 'a'), std::string(200, 'b')));
+MAKE_BENCHMARK(AbslHash, PairStringString_5000,
+               std::make_pair(std::string(5000, 'a'), std::string(5000, 'b')));
+
+MAKE_BENCHMARK(TypeErasedAbslHash, Int32, int32_t{});
+MAKE_BENCHMARK(TypeErasedAbslHash, Int64, int64_t{});
+MAKE_BENCHMARK(TypeErasedAbslHash, PairInt32Int32,
+               std::pair<int32_t, int32_t>{});
+MAKE_BENCHMARK(TypeErasedAbslHash, PairInt64Int64,
+               std::pair<int64_t, int64_t>{});
+MAKE_BENCHMARK(TypeErasedAbslHash, TupleInt32BoolInt64,
+               std::tuple<int32_t, bool, int64_t>{});
+MAKE_BENCHMARK(TypeErasedAbslHash, String_0, std::string());
+MAKE_BENCHMARK(TypeErasedAbslHash, String_10, std::string(10, 'a'));
+MAKE_BENCHMARK(TypeErasedAbslHash, String_30, std::string(30, 'a'));
+MAKE_BENCHMARK(TypeErasedAbslHash, String_90, std::string(90, 'a'));
+MAKE_BENCHMARK(TypeErasedAbslHash, String_200, std::string(200, 'a'));
+MAKE_BENCHMARK(TypeErasedAbslHash, String_5000, std::string(5000, 'a'));
+MAKE_BENCHMARK(TypeErasedAbslHash, VectorDouble_10,
+               std::vector<double>(10, 1.1));
+MAKE_BENCHMARK(TypeErasedAbslHash, VectorDouble_100,
+               std::vector<double>(100, 1.1));
+
+// The latency benchmark attempts to model the speed of the hash function in
+// production. When a hash function is used for hashtable lookups it is rarely
+// used to hash N items in a tight loop nor on constant sized strings. Instead,
+// after hashing there is a potential equality test plus a (usually) large
+// amount of user code. To simulate this effectively we introduce a data
+// dependency between elements we hash by using the hash of the Nth element as
+// the selector of the N+1th element to hash. This isolates the hash function
+// code much like in production. As a bonus we use the hash to generate strings
+// of size [1,N] (instead of fixed N) to disable perfect branch predictions in
+// hash function implementations.
+namespace {
+// 16kb fits in L1 cache of most CPUs we care about. Keeping memory latency low
+// will allow us to attribute most time to CPU which means more accurate
+// measurements.
+static constexpr size_t kEntropySize = 16 << 10;
+static char entropy[kEntropySize + 1024];
+ABSL_ATTRIBUTE_UNUSED static const bool kInitialized = [] {
+  absl::BitGen gen;
+  static_assert(sizeof(entropy) % sizeof(uint64_t) == 0, "");
+  for (int i = 0; i != sizeof(entropy); i += sizeof(uint64_t)) {
+    auto rand = absl::Uniform<uint64_t>(gen);
+    memcpy(&entropy[i], &rand, sizeof(uint64_t));
+  }
+  return true;
+}();
+}  // namespace
+
+template <class T>
+struct PodRand {
+  static_assert(std::is_pod<T>::value, "");
+  static_assert(kEntropySize + sizeof(T) < sizeof(entropy), "");
+
+  T Get(size_t i) const {
+    T v;
+    memcpy(&v, &entropy[i % kEntropySize], sizeof(T));
+    return v;
+  }
+};
+
+template <size_t N>
+struct StringRand {
+  static_assert(kEntropySize + N < sizeof(entropy), "");
+
+  absl::string_view Get(size_t i) const {
+    // This has a small bias towards small numbers. Because max N is ~200 this
+    // is very small and prefer to be very fast instead of absolutely accurate.
+    // Also we pass N = 2^K+1 so that mod reduces to a bitand.
+    size_t s = (i % (N - 1)) + 1;
+    return {&entropy[i % kEntropySize], s};
+  }
+};
+
+#define MAKE_LATENCY_BENCHMARK(hash, name, ...)              \
+  namespace {                                                \
+  void BM_latency_##hash##_##name(benchmark::State& state) { \
+    __VA_ARGS__ r;                                           \
+    hash<decltype(r.Get(0))> h;                              \
+    size_t i = 871401241;                                    \
+    for (auto _ : state) {                                   \
+      benchmark::DoNotOptimize(i = h(r.Get(i)));             \
+    }                                                        \
+  }                                                          \
+  BENCHMARK(BM_latency_##hash##_##name);                     \
+  }  // namespace
+
+MAKE_LATENCY_BENCHMARK(AbslHash, Int32, PodRand<int32_t>);
+MAKE_LATENCY_BENCHMARK(AbslHash, Int64, PodRand<int64_t>);
+MAKE_LATENCY_BENCHMARK(AbslHash, String9, StringRand<9>);
+MAKE_LATENCY_BENCHMARK(AbslHash, String33, StringRand<33>);
+MAKE_LATENCY_BENCHMARK(AbslHash, String65, StringRand<65>);
+MAKE_LATENCY_BENCHMARK(AbslHash, String257, StringRand<257>);
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc
index 9a667ba..1d2e6cf 100644
--- a/absl/hash/hash_test.cc
+++ b/absl/hash/hash_test.cc
@@ -42,6 +42,7 @@
 #include "absl/hash/internal/spy_hash_state.h"
 #include "absl/meta/type_traits.h"
 #include "absl/numeric/int128.h"
+#include "absl/strings/cord_test_helpers.h"
 
 namespace {
 
@@ -81,8 +82,8 @@
 }
 
 REGISTER_TYPED_TEST_CASE_P(HashValueIntTest, BasicUsage, FastPath);
-using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t, uint32_t,
-                                uint64_t, size_t>;
+using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
+                                uint32_t, uint64_t, size_t>;
 INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueIntTest, IntTypes);
 
 enum LegacyEnum { kValue1, kValue2, kValue3 };
@@ -269,37 +270,84 @@
   }
 };
 
+absl::Cord FlatCord(absl::string_view sv) {
+  absl::Cord c(sv);
+  c.Flatten();
+  return c;
+}
+
+absl::Cord FragmentedCord(absl::string_view sv) {
+  if (sv.size() < 2) {
+    return absl::Cord(sv);
+  }
+  size_t halfway = sv.size() / 2;
+  std::vector<absl::string_view> parts = {sv.substr(0, halfway),
+                                          sv.substr(halfway)};
+  return absl::MakeFragmentedCord(parts);
+}
+
 TEST(HashValueTest, Strings) {
   EXPECT_TRUE((is_hashable<std::string>::value));
 
   const std::string small = "foo";
   const std::string dup = "foofoo";
-  const std::string large = "large";
-  const std::string huge = std::string(5000, 'a');
+  const std::string large = std::string(2048, 'x');  // multiple of chunk size
+  const std::string huge = std::string(5000, 'a');   // not a multiple
 
-  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
-      std::string(), absl::string_view(),
-      std::string(""), absl::string_view(""),
-      std::string(small), absl::string_view(small),
-      std::string(dup), absl::string_view(dup),
-      std::string(large), absl::string_view(large),
-      std::string(huge), absl::string_view(huge))));
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(  //
+      std::string(), absl::string_view(), absl::Cord(),                     //
+      std::string(""), absl::string_view(""), absl::Cord(""),               //
+      std::string(small), absl::string_view(small), absl::Cord(small),      //
+      std::string(dup), absl::string_view(dup), absl::Cord(dup),            //
+      std::string(large), absl::string_view(large), absl::Cord(large),      //
+      std::string(huge), absl::string_view(huge), FlatCord(huge),           //
+      FragmentedCord(huge))));
 
   // Also check that nested types maintain the same hash.
   const WrapInTuple t{};
-  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
-      t(std::string()), t(absl::string_view()),
-      t(std::string("")), t(absl::string_view("")),
-      t(std::string(small)), t(absl::string_view(small)),
-      t(std::string(dup)), t(absl::string_view(dup)),
-      t(std::string(large)), t(absl::string_view(large)),
-      t(std::string(huge)), t(absl::string_view(huge)))));
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(  //
+      t(std::string()), t(absl::string_view()), t(absl::Cord()),            //
+      t(std::string("")), t(absl::string_view("")), t(absl::Cord("")),      //
+      t(std::string(small)), t(absl::string_view(small)),                   //
+          t(absl::Cord(small)),                                             //
+      t(std::string(dup)), t(absl::string_view(dup)), t(absl::Cord(dup)),   //
+      t(std::string(large)), t(absl::string_view(large)),                   //
+          t(absl::Cord(large)),                                             //
+      t(std::string(huge)), t(absl::string_view(huge)),                     //
+          t(FlatCord(huge)), t(FragmentedCord(huge)))));
 
-  // Make sure that hashing a `const char*` does not use its std::string-value.
+  // Make sure that hashing a `const char*` does not use its string-value.
   EXPECT_NE(SpyHash(static_cast<const char*>("ABC")),
             SpyHash(absl::string_view("ABC")));
 }
 
+TEST(HashValueTest, WString) {
+  EXPECT_TRUE((is_hashable<std::wstring>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::wstring(), std::wstring(L"ABC"), std::wstring(L"ABC"),
+      std::wstring(L"Some other different string"),
+      std::wstring(L"Iñtërnâtiônàlizætiøn"))));
+}
+
+TEST(HashValueTest, U16String) {
+  EXPECT_TRUE((is_hashable<std::u16string>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::u16string(), std::u16string(u"ABC"), std::u16string(u"ABC"),
+      std::u16string(u"Some other different string"),
+      std::u16string(u"Iñtërnâtiônàlizætiøn"))));
+}
+
+TEST(HashValueTest, U32String) {
+  EXPECT_TRUE((is_hashable<std::u32string>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::u32string(), std::u32string(U"ABC"), std::u32string(U"ABC"),
+      std::u32string(U"Some other different string"),
+      std::u32string(U"Iñtërnâtiônàlizætiøn"))));
+}
+
 TEST(HashValueTest, StdArray) {
   EXPECT_TRUE((is_hashable<std::array<int, 3>>::value));
 
@@ -359,7 +407,7 @@
 INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueSequenceTest, IntSequenceTypes);
 
 // Private type that only supports AbslHashValue to make sure our chosen hash
-// implentation is recursive within absl::Hash.
+// implementation is recursive within absl::Hash.
 // It uses std::abs() on the value to provide different bitwise representations
 // of the same logical value.
 struct Private {
@@ -378,6 +426,116 @@
   }
 };
 
+// Test helper for combine_piecewise_buffer.  It holds a string_view to the
+// buffer-to-be-hashed.  Its AbslHashValue specialization will split up its
+// contents at the character offsets requested.
+class PiecewiseHashTester {
+ public:
+  // Create a hash view of a buffer to be hashed contiguously.
+  explicit PiecewiseHashTester(absl::string_view buf)
+      : buf_(buf), piecewise_(false), split_locations_() {}
+
+  // Create a hash view of a buffer to be hashed piecewise, with breaks at the
+  // given locations.
+  PiecewiseHashTester(absl::string_view buf, std::set<size_t> split_locations)
+      : buf_(buf),
+        piecewise_(true),
+        split_locations_(std::move(split_locations)) {}
+
+  template <typename H>
+  friend H AbslHashValue(H h, const PiecewiseHashTester& p) {
+    if (!p.piecewise_) {
+      return H::combine_contiguous(std::move(h), p.buf_.data(), p.buf_.size());
+    }
+    absl::hash_internal::PiecewiseCombiner combiner;
+    if (p.split_locations_.empty()) {
+      h = combiner.add_buffer(std::move(h), p.buf_.data(), p.buf_.size());
+      return combiner.finalize(std::move(h));
+    }
+    size_t begin = 0;
+    for (size_t next : p.split_locations_) {
+      absl::string_view chunk = p.buf_.substr(begin, next - begin);
+      h = combiner.add_buffer(std::move(h), chunk.data(), chunk.size());
+      begin = next;
+    }
+    absl::string_view last_chunk = p.buf_.substr(begin);
+    if (!last_chunk.empty()) {
+      h = combiner.add_buffer(std::move(h), last_chunk.data(),
+                              last_chunk.size());
+    }
+    return combiner.finalize(std::move(h));
+  }
+
+ private:
+  absl::string_view buf_;
+  bool piecewise_;
+  std::set<size_t> split_locations_;
+};
+
+// Dummy object that hashes as two distinct contiguous buffers, "foo" followed
+// by "bar"
+struct DummyFooBar {
+  template <typename H>
+  friend H AbslHashValue(H h, const DummyFooBar&) {
+    const char* foo = "foo";
+    const char* bar = "bar";
+    h = H::combine_contiguous(std::move(h), foo, 3);
+    h = H::combine_contiguous(std::move(h), bar, 3);
+    return h;
+  }
+};
+
+TEST(HashValueTest, CombinePiecewiseBuffer) {
+  absl::Hash<PiecewiseHashTester> hash;
+
+  // Check that hashing an empty buffer through the piecewise API works.
+  EXPECT_EQ(hash(PiecewiseHashTester("")), hash(PiecewiseHashTester("", {})));
+
+  // Similarly, small buffers should give consistent results
+  EXPECT_EQ(hash(PiecewiseHashTester("foobar")),
+            hash(PiecewiseHashTester("foobar", {})));
+  EXPECT_EQ(hash(PiecewiseHashTester("foobar")),
+            hash(PiecewiseHashTester("foobar", {3})));
+
+  // But hashing "foobar" in pieces gives a different answer than hashing "foo"
+  // contiguously, then "bar" contiguously.
+  EXPECT_NE(hash(PiecewiseHashTester("foobar", {3})),
+            absl::Hash<DummyFooBar>()(DummyFooBar{}));
+
+  // Test hashing a large buffer incrementally, broken up in several different
+  // ways.  Arrange for breaks on and near the stride boundaries to look for
+  // off-by-one errors in the implementation.
+  //
+  // This test is run on a buffer that is a multiple of the stride size, and one
+  // that isn't.
+  for (size_t big_buffer_size : {1024 * 2 + 512, 1024 * 3}) {
+    SCOPED_TRACE(big_buffer_size);
+    std::string big_buffer;
+    for (int i = 0; i < big_buffer_size; ++i) {
+      // Arbitrary string
+      big_buffer.push_back(32 + (i * (i / 3)) % 64);
+    }
+    auto big_buffer_hash = hash(PiecewiseHashTester(big_buffer));
+
+    const int possible_breaks = 9;
+    size_t breaks[possible_breaks] = {1,    512,  1023, 1024, 1025,
+                                      1536, 2047, 2048, 2049};
+    for (unsigned test_mask = 0; test_mask < (1u << possible_breaks);
+         ++test_mask) {
+      SCOPED_TRACE(test_mask);
+      std::set<size_t> break_locations;
+      for (int j = 0; j < possible_breaks; ++j) {
+        if (test_mask & (1u << j)) {
+          break_locations.insert(breaks[j]);
+        }
+      }
+      EXPECT_EQ(
+          hash(PiecewiseHashTester(big_buffer, std::move(break_locations))),
+          big_buffer_hash);
+    }
+  }
+}
+
 TEST(HashValueTest, PrivateSanity) {
   // Sanity check that Private is working as the tests below expect it to work.
   EXPECT_TRUE(is_hashable<Private>::value);
@@ -423,6 +581,24 @@
       MM{{1, "foo"}, {1, "foo"}, {43, "bar"}}, MM{{1, "foo"}, {43, "baz"}})));
 }
 
+TEST(HashValueTest, ReferenceWrapper) {
+  EXPECT_TRUE(is_hashable<std::reference_wrapper<Private>>::value);
+
+  Private p1{1}, p10{10};
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      p1, p10, std::ref(p1), std::ref(p10), std::cref(p1), std::cref(p10))));
+
+  EXPECT_TRUE(is_hashable<std::reference_wrapper<int>>::value);
+  int one = 1, ten = 10;
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      one, ten, std::ref(one), std::ref(ten), std::cref(one), std::cref(ten))));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(std::tuple<std::reference_wrapper<int>>(std::ref(one)),
+                      std::tuple<std::reference_wrapper<int>>(std::ref(ten)),
+                      std::tuple<int>(one), std::tuple<int>(ten))));
+}
+
 template <typename T, typename = void>
 struct IsHashCallable : std::false_type {};
 
@@ -458,7 +634,10 @@
   EXPECT_FALSE(absl::is_copy_assignable<absl::Hash<X>>::value);
   EXPECT_FALSE(absl::is_move_assignable<absl::Hash<X>>::value);
   EXPECT_FALSE(IsHashCallable<X>::value);
+#if !defined(__GNUC__) || __GNUC__ < 9
+  // This doesn't compile on GCC 9.
   EXPECT_FALSE(IsAggregateInitializable<absl::Hash<X>>::value);
+#endif
 }
 #endif  // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
 
@@ -544,6 +723,7 @@
 }  // namespace
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace hash_internal {
 template <InvokeTag... Tags>
 struct is_uniquely_represented<
@@ -551,6 +731,7 @@
     typename EnableIfContained<InvokeTag::kUniquelyRepresented, Tags...>::type>
     : std::true_type {};
 }  // namespace hash_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
@@ -638,8 +819,8 @@
 }
 
 REGISTER_TYPED_TEST_CASE_P(HashIntTest, BasicUsage);
-using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t, uint32_t,
-                                uint64_t, size_t>;
+using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
+                                uint32_t, uint64_t, size_t>;
 INSTANTIATE_TYPED_TEST_CASE_P(My, HashIntTest, IntTypes);
 
 struct StructWithPadding {
diff --git a/absl/hash/hash_testing.h b/absl/hash/hash_testing.h
index c45bc15..1e1c574 100644
--- a/absl/hash/hash_testing.h
+++ b/absl/hash/hash_testing.h
@@ -28,6 +28,7 @@
 #include "absl/types/variant.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // Run the absl::Hash algorithm over all the elements passed in and verify that
 // their hash expansion is congruent with their `==` operator.
@@ -371,6 +372,7 @@
       equals);
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_HASH_HASH_TESTING_H_
diff --git a/absl/hash/internal/city.cc b/absl/hash/internal/city.cc
index dc7650a..5460134 100644
--- a/absl/hash/internal/city.cc
+++ b/absl/hash/internal/city.cc
@@ -30,6 +30,7 @@
 #include "absl/base/optimization.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace hash_internal {
 
 #ifdef ABSL_IS_BIG_ENDIAN
@@ -199,10 +200,6 @@
 
 static uint64_t ShiftMix(uint64_t val) { return val ^ (val >> 47); }
 
-static uint64_t HashLen16(uint64_t u, uint64_t v) {
-  return Hash128to64(uint128(u, v));
-}
-
 static uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) {
   // Murmur-inspired hashing.
   uint64_t a = (u ^ v) * mul;
@@ -213,6 +210,11 @@
   return b;
 }
 
+static uint64_t HashLen16(uint64_t u, uint64_t v) {
+  const uint64_t kMul = 0x9ddfea08eb382d69ULL;
+  return HashLen16(u, v, kMul);
+}
+
 static uint64_t HashLen0to16(const char *s, size_t len) {
   if (len >= 8) {
     uint64_t mul = k2 + len * 2;
@@ -252,9 +254,8 @@
 
 // Return a 16-byte hash for 48 bytes.  Quick and dirty.
 // Callers do best to use "random-looking" values for a and b.
-static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(uint64_t w, uint64_t x,
-                                                        uint64_t y, uint64_t z,
-                                                        uint64_t a, uint64_t b) {
+static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(
+    uint64_t w, uint64_t x, uint64_t y, uint64_t z, uint64_t a, uint64_t b) {
   a += w;
   b = Rotate(b + a + z, 21);
   uint64_t c = a;
@@ -265,8 +266,9 @@
 }
 
 // Return a 16-byte hash for s[0] ... s[31], a, and b.  Quick and dirty.
-static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(const char *s, uint64_t a,
-                                                        uint64_t b) {
+static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(const char *s,
+                                                            uint64_t a,
+                                                            uint64_t b) {
   return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16),
                                 Fetch64(s + 24), a, b);
 }
@@ -309,8 +311,10 @@
   uint64_t x = Fetch64(s + len - 40);
   uint64_t y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
   uint64_t z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
-  std::pair<uint64_t, uint64_t> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
-  std::pair<uint64_t, uint64_t> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
+  std::pair<uint64_t, uint64_t> v =
+      WeakHashLen32WithSeeds(s + len - 64, len, z);
+  std::pair<uint64_t, uint64_t> w =
+      WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
   x = x * k1 + Fetch64(s);
 
   // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
@@ -336,9 +340,10 @@
 }
 
 uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
-                           uint64_t seed1) {
+                             uint64_t seed1) {
   return HashLen16(CityHash64(s, len) - seed0, seed1);
 }
 
 }  // namespace hash_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/hash/internal/city.h b/absl/hash/internal/city.h
index b43d340..393da0b 100644
--- a/absl/hash/internal/city.h
+++ b/absl/hash/internal/city.h
@@ -47,16 +47,15 @@
 
 #include <stdint.h>
 #include <stdlib.h>  // for size_t.
+
 #include <utility>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace hash_internal {
 
-typedef std::pair<uint64_t, uint64_t> uint128;
-
-inline uint64_t Uint128Low64(const uint128 &x) { return x.first; }
-inline uint64_t Uint128High64(const uint128 &x) { return x.second; }
-
 // Hash function for a byte array.
 uint64_t CityHash64(const char *s, size_t len);
 
@@ -67,25 +66,13 @@
 // Hash function for a byte array.  For convenience, two seeds are also
 // hashed into the result.
 uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
-                           uint64_t seed1);
+                             uint64_t seed1);
 
 // Hash function for a byte array.  Most useful in 32-bit binaries.
 uint32_t CityHash32(const char *s, size_t len);
 
-// Hash 128 input bits down to 64 bits of output.
-// This is intended to be a reasonably good hash function.
-inline uint64_t Hash128to64(const uint128 &x) {
-  // Murmur-inspired hashing.
-  const uint64_t kMul = 0x9ddfea08eb382d69ULL;
-  uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
-  a ^= (a >> 47);
-  uint64_t b = (Uint128High64(x) ^ a) * kMul;
-  b ^= (b >> 47);
-  b *= kMul;
-  return b;
-}
-
 }  // namespace hash_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_HASH_INTERNAL_CITY_H_
diff --git a/absl/hash/internal/city_test.cc b/absl/hash/internal/city_test.cc
index 71b4ecc..251d381 100644
--- a/absl/hash/internal/city_test.cc
+++ b/absl/hash/internal/city_test.cc
@@ -20,6 +20,7 @@
 #include "gtest/gtest.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace hash_internal {
 
 static const uint64_t k0 = 0xc3a5c85c97cb3127ULL;
@@ -590,4 +591,5 @@
 }
 
 }  // namespace hash_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/hash/internal/hash.cc b/absl/hash/internal/hash.cc
index 4ab7a9f..1433eb9 100644
--- a/absl/hash/internal/hash.cc
+++ b/absl/hash/internal/hash.cc
@@ -15,9 +15,56 @@
 #include "absl/hash/internal/hash.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace hash_internal {
 
-ABSL_CONST_INIT const void* const CityHashState::kSeed = &kSeed;
+uint64_t HashState::CombineLargeContiguousImpl32(uint64_t state,
+                                                 const unsigned char* first,
+                                                 size_t len) {
+  while (len >= PiecewiseChunkSize()) {
+    state =
+        Mix(state, absl::hash_internal::CityHash32(reinterpret_cast<const char*>(first),
+                                         PiecewiseChunkSize()));
+    len -= PiecewiseChunkSize();
+    first += PiecewiseChunkSize();
+  }
+  // Handle the remainder.
+  return CombineContiguousImpl(state, first, len,
+                               std::integral_constant<int, 4>{});
+}
+
+uint64_t HashState::CombineLargeContiguousImpl64(uint64_t state,
+                                                 const unsigned char* first,
+                                                 size_t len) {
+  while (len >= PiecewiseChunkSize()) {
+    state = Mix(state, Hash64(first, PiecewiseChunkSize()));
+    len -= PiecewiseChunkSize();
+    first += PiecewiseChunkSize();
+  }
+  // Handle the remainder.
+  return CombineContiguousImpl(state, first, len,
+                               std::integral_constant<int, 8>{});
+}
+
+ABSL_CONST_INIT const void* const HashState::kSeed = &kSeed;
+
+// The salt array used by Wyhash. This array is NOT the mechanism used to make
+// absl::Hash non-deterministic between program invocations.  See `Seed()` for
+// that mechanism.
+//
+// Any random values are fine. These values are just digits from the decimal
+// part of pi.
+// https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number
+constexpr uint64_t kWyhashSalt[5] = {
+    uint64_t{0x243F6A8885A308D3}, uint64_t{0x13198A2E03707344},
+    uint64_t{0xA4093822299F31D0}, uint64_t{0x082EFA98EC4E6C89},
+    uint64_t{0x452821E638D01377},
+};
+
+uint64_t HashState::WyhashImpl(const unsigned char* data, size_t len) {
+  return Wyhash(data, len, Seed(), kWyhashSalt);
+}
 
 }  // namespace hash_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index 4ff4a12..eb3471d 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -41,6 +41,7 @@
 #include "absl/base/internal/endian.h"
 #include "absl/base/port.h"
 #include "absl/container/fixed_array.h"
+#include "absl/hash/internal/wyhash.h"
 #include "absl/meta/type_traits.h"
 #include "absl/numeric/int128.h"
 #include "absl/strings/string_view.h"
@@ -50,8 +51,68 @@
 #include "absl/hash/internal/city.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace hash_internal {
 
+// Internal detail: Large buffers are hashed in smaller chunks.  This function
+// returns the size of these chunks.
+constexpr size_t PiecewiseChunkSize() { return 1024; }
+
+// PiecewiseCombiner
+//
+// PiecewiseCombiner is an internal-only helper class for hashing a piecewise
+// buffer of `char` or `unsigned char` as though it were contiguous.  This class
+// provides two methods:
+//
+//   H add_buffer(state, data, size)
+//   H finalize(state)
+//
+// `add_buffer` can be called zero or more times, followed by a single call to
+// `finalize`.  This will produce the same hash expansion as concatenating each
+// buffer piece into a single contiguous buffer, and passing this to
+// `H::combine_contiguous`.
+//
+//  Example usage:
+//    PiecewiseCombiner combiner;
+//    for (const auto& piece : pieces) {
+//      state = combiner.add_buffer(std::move(state), piece.data, piece.size);
+//    }
+//    return combiner.finalize(std::move(state));
+class PiecewiseCombiner {
+ public:
+  PiecewiseCombiner() : position_(0) {}
+  PiecewiseCombiner(const PiecewiseCombiner&) = delete;
+  PiecewiseCombiner& operator=(const PiecewiseCombiner&) = delete;
+
+  // PiecewiseCombiner::add_buffer()
+  //
+  // Appends the given range of bytes to the sequence to be hashed, which may
+  // modify the provided hash state.
+  template <typename H>
+  H add_buffer(H state, const unsigned char* data, size_t size);
+  template <typename H>
+  H add_buffer(H state, const char* data, size_t size) {
+    return add_buffer(std::move(state),
+                      reinterpret_cast<const unsigned char*>(data), size);
+  }
+
+  // PiecewiseCombiner::finalize()
+  //
+  // Finishes combining the hash sequence, which may may modify the provided
+  // hash state.
+  //
+  // Once finalize() is called, add_buffer() may no longer be called. The
+  // resulting hash state will be the same as if the pieces passed to
+  // add_buffer() were concatenated into a single flat buffer, and then provided
+  // to H::combine_contiguous().
+  template <typename H>
+  H finalize(H state);
+
+ private:
+  unsigned char buf_[PiecewiseChunkSize()];
+  size_t position_;
+};
+
 // HashStateBase
 //
 // A hash state object represents an intermediate state in the computation
@@ -68,7 +129,7 @@
 //
 //    `static H combine_contiguous(H state, const unsigned char*, size_t)`.
 //
-// `HashStateBase` will provide a complete implementations for a hash state
+// `HashStateBase` will provide a complete implementation for a hash state
 // object in terms of this method.
 //
 // Example:
@@ -117,6 +178,8 @@
   // for-loop instead.
   template <typename T>
   static H combine_contiguous(H state, const T* data, size_t size);
+
+  using AbslInternalPiecewiseCombiner = PiecewiseCombiner;
 };
 
 // is_uniquely_represented
@@ -348,6 +411,7 @@
 // All the string-like types supported here provide the same hash expansion for
 // the same character sequence. These types are:
 //
+//  - `absl::Cord`
 //  - `std::string` (and std::basic_string<char, std::char_traits<char>, A> for
 //      any allocator A)
 //  - `absl::string_view` and `std::string_view`
@@ -363,6 +427,19 @@
       str.size());
 }
 
+// Support std::wstring, std::u16string and std::u32string.
+template <typename Char, typename Alloc, typename H,
+          typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value ||
+                                       std::is_same<Char, char16_t>::value ||
+                                       std::is_same<Char, char32_t>::value>>
+H AbslHashValue(
+    H hash_state,
+    const std::basic_string<Char, std::char_traits<Char>, Alloc>& str) {
+  return H::combine(
+      H::combine_contiguous(std::move(hash_state), str.data(), str.size()),
+      str.size());
+}
+
 // -----------------------------------------------------------------------------
 // AbslHashValue for Sequence Containers
 // -----------------------------------------------------------------------------
@@ -475,6 +552,13 @@
 // AbslHashValue for Wrapper Types
 // -----------------------------------------------------------------------------
 
+// AbslHashValue for hashing std::reference_wrapper
+template <typename H, typename T>
+typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(
+    H hash_state, std::reference_wrapper<T> opt) {
+  return H::combine(std::move(hash_state), opt.get());
+}
+
 // AbslHashValue for hashing absl::optional
 template <typename H, typename T>
 typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(
@@ -629,8 +713,8 @@
 struct is_hashable
     : std::integral_constant<bool, HashSelect::template Apply<T>::value> {};
 
-// CityHashState
-class CityHashState : public HashStateBase<CityHashState> {
+// HashState
+class ABSL_DLL HashState : public HashStateBase<HashState> {
   // absl::uint128 is not an alias or a thin wrapper around the intrinsic.
   // We use the intrinsic when available to improve performance.
 #ifdef ABSL_HAVE_INTRINSIC_INT128
@@ -649,23 +733,22 @@
 
  public:
   // Move only
-  CityHashState(CityHashState&&) = default;
-  CityHashState& operator=(CityHashState&&) = default;
+  HashState(HashState&&) = default;
+  HashState& operator=(HashState&&) = default;
 
-  // CityHashState::combine_contiguous()
+  // HashState::combine_contiguous()
   //
   // Fundamental base case for hash recursion: mixes the given range of bytes
   // into the hash state.
-  static CityHashState combine_contiguous(CityHashState hash_state,
-                                          const unsigned char* first,
-                                          size_t size) {
-    return CityHashState(
+  static HashState combine_contiguous(HashState hash_state,
+                                      const unsigned char* first, size_t size) {
+    return HashState(
         CombineContiguousImpl(hash_state.state_, first, size,
                               std::integral_constant<int, sizeof(size_t)>{}));
   }
-  using CityHashState::HashStateBase::combine_contiguous;
+  using HashState::HashStateBase::combine_contiguous;
 
-  // CityHashState::hash()
+  // HashState::hash()
   //
   // For performance reasons in non-opt mode, we specialize this for
   // integral types.
@@ -677,24 +760,24 @@
     return static_cast<size_t>(Mix(Seed(), static_cast<uint64_t>(value)));
   }
 
-  // Overload of CityHashState::hash()
+  // Overload of HashState::hash()
   template <typename T, absl::enable_if_t<!IntegralFastPath<T>::value, int> = 0>
   static size_t hash(const T& value) {
-    return static_cast<size_t>(combine(CityHashState{}, value).state_);
+    return static_cast<size_t>(combine(HashState{}, value).state_);
   }
 
  private:
   // Invoked only once for a given argument; that plus the fact that this is
   // move-only ensures that there is only one non-moved-from object.
-  CityHashState() : state_(Seed()) {}
+  HashState() : state_(Seed()) {}
 
   // Workaround for MSVC bug.
   // We make the type copyable to fix the calling convention, even though we
   // never actually copy it. Keep it private to not affect the public API of the
   // type.
-  CityHashState(const CityHashState&) = default;
+  HashState(const HashState&) = default;
 
-  explicit CityHashState(uint64_t state) : state_(state) {}
+  explicit HashState(uint64_t state) : state_(state) {}
 
   // Implementation of the base case for combine_contiguous where we actually
   // mix the bytes into the state.
@@ -707,7 +790,18 @@
   static uint64_t CombineContiguousImpl(uint64_t state,
                                         const unsigned char* first, size_t len,
                                         std::integral_constant<int, 8>
-                                        /* sizeof_size_t*/);
+                                        /* sizeof_size_t */);
+
+
+  // Slow dispatch path for calls to CombineContiguousImpl with a size argument
+  // larger than PiecewiseChunkSize().  Has the same effect as calling
+  // CombineContiguousImpl() repeatedly with the chunk stride size.
+  static uint64_t CombineLargeContiguousImpl32(uint64_t state,
+                                               const unsigned char* first,
+                                               size_t len);
+  static uint64_t CombineLargeContiguousImpl64(uint64_t state,
+                                               const unsigned char* first,
+                                               size_t len);
 
   // Reads 9 to 16 bytes from p.
   // The first 8 bytes are in .first, the rest (zero padded) bytes are in
@@ -744,6 +838,19 @@
     return static_cast<uint64_t>(m ^ (m >> (sizeof(m) * 8 / 2)));
   }
 
+  // An extern to avoid bloat on a direct call to Wyhash() with fixed values for
+  // both the seed and salt parameters.
+  static uint64_t WyhashImpl(const unsigned char* data, size_t len);
+
+  ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Hash64(const unsigned char* data,
+                                                      size_t len) {
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+    return WyhashImpl(data, len);
+#else
+    return absl::hash_internal::CityHash64(reinterpret_cast<const char*>(data), len);
+#endif
+  }
+
   // Seed()
   //
   // A non-deterministic seed.
@@ -761,21 +868,31 @@
   // On other platforms this is still going to be non-deterministic but most
   // probably per-build and not per-process.
   ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Seed() {
+#if (!defined(__clang__) || __clang_major__ > 11) && \
+    !defined(__apple_build_version__)
+    return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&kSeed));
+#else
+    // Workaround the absence of
+    // https://github.com/llvm/llvm-project/commit/bc15bf66dcca76cc06fe71fca35b74dc4d521021.
     return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(kSeed));
+#endif
   }
   static const void* const kSeed;
 
   uint64_t state_;
 };
 
-// CityHashState::CombineContiguousImpl()
-inline uint64_t CityHashState::CombineContiguousImpl(
+// HashState::CombineContiguousImpl()
+inline uint64_t HashState::CombineContiguousImpl(
     uint64_t state, const unsigned char* first, size_t len,
     std::integral_constant<int, 4> /* sizeof_size_t */) {
   // For large values we use CityHash, for small ones we just use a
   // multiplicative hash.
   uint64_t v;
   if (len > 8) {
+    if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) {
+      return CombineLargeContiguousImpl32(state, first, len);
+    }
     v = absl::hash_internal::CityHash32(reinterpret_cast<const char*>(first), len);
   } else if (len >= 4) {
     v = Read4To8(first, len);
@@ -788,15 +905,18 @@
   return Mix(state, v);
 }
 
-// Overload of CityHashState::CombineContiguousImpl()
-inline uint64_t CityHashState::CombineContiguousImpl(
+// Overload of HashState::CombineContiguousImpl()
+inline uint64_t HashState::CombineContiguousImpl(
     uint64_t state, const unsigned char* first, size_t len,
     std::integral_constant<int, 8> /* sizeof_size_t */) {
-  // For large values we use CityHash, for small ones we just use a
-  // multiplicative hash.
+  // For large values we use Wyhash or CityHash depending on the platform, for
+  // small ones we just use a multiplicative hash.
   uint64_t v;
   if (len > 16) {
-    v = absl::hash_internal::CityHash64(reinterpret_cast<const char*>(first), len);
+    if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) {
+      return CombineLargeContiguousImpl64(state, first, len);
+    }
+    v = Hash64(first, len);
   } else if (len > 8) {
     auto p = Read9To16(first, len);
     state = Mix(state, p.first);
@@ -812,7 +932,6 @@
   return Mix(state, v);
 }
 
-
 struct AggregateBarrier {};
 
 // HashImpl
@@ -828,7 +947,7 @@
 
 template <typename T>
 struct HashImpl {
-  size_t operator()(const T& value) const { return CityHashState::hash(value); }
+  size_t operator()(const T& value) const { return HashState::hash(value); }
 };
 
 template <typename T>
@@ -849,7 +968,49 @@
 H HashStateBase<H>::combine_contiguous(H state, const T* data, size_t size) {
   return hash_internal::hash_range_or_bytes(std::move(state), data, size);
 }
+
+// HashStateBase::PiecewiseCombiner::add_buffer()
+template <typename H>
+H PiecewiseCombiner::add_buffer(H state, const unsigned char* data,
+                                size_t size) {
+  if (position_ + size < PiecewiseChunkSize()) {
+    // This partial chunk does not fill our existing buffer
+    memcpy(buf_ + position_, data, size);
+    position_ += size;
+    return state;
+  }
+
+  // If the buffer is partially filled we need to complete the buffer
+  // and hash it.
+  if (position_ != 0) {
+    const size_t bytes_needed = PiecewiseChunkSize() - position_;
+    memcpy(buf_ + position_, data, bytes_needed);
+    state = H::combine_contiguous(std::move(state), buf_, PiecewiseChunkSize());
+    data += bytes_needed;
+    size -= bytes_needed;
+  }
+
+  // Hash whatever chunks we can without copying
+  while (size >= PiecewiseChunkSize()) {
+    state = H::combine_contiguous(std::move(state), data, PiecewiseChunkSize());
+    data += PiecewiseChunkSize();
+    size -= PiecewiseChunkSize();
+  }
+  // Fill the buffer with the remainder
+  memcpy(buf_, data, size);
+  position_ = size;
+  return state;
+}
+
+// HashStateBase::PiecewiseCombiner::finalize()
+template <typename H>
+H PiecewiseCombiner::finalize(H state) {
+  // Hash the remainder left in the buffer, which may be empty
+  return H::combine_contiguous(std::move(state), buf_, position_);
+}
+
 }  // namespace hash_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_HASH_INTERNAL_HASH_H_
diff --git a/absl/hash/internal/spy_hash_state.h b/absl/hash/internal/spy_hash_state.h
index c4cc8d0..c083120 100644
--- a/absl/hash/internal/spy_hash_state.h
+++ b/absl/hash/internal/spy_hash_state.h
@@ -25,6 +25,7 @@
 #include "absl/strings/str_join.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace hash_internal {
 
 // SpyHashState is an implementation of the HashState API that simply
@@ -146,6 +147,19 @@
   static SpyHashStateImpl combine_contiguous(SpyHashStateImpl hash_state,
                                              const unsigned char* begin,
                                              size_t size) {
+    const size_t large_chunk_stride = PiecewiseChunkSize();
+    if (size > large_chunk_stride) {
+      // Combining a large contiguous buffer must have the same effect as
+      // doing it piecewise by the stride length, followed by the (possibly
+      // empty) remainder.
+      while (size >= large_chunk_stride) {
+        hash_state = SpyHashStateImpl::combine_contiguous(
+            std::move(hash_state), begin, large_chunk_stride);
+        begin += large_chunk_stride;
+        size -= large_chunk_stride;
+      }
+    }
+
     hash_state.hash_representation_.emplace_back(
         reinterpret_cast<const char*>(begin), size);
     return hash_state;
@@ -211,6 +225,7 @@
 using SpyHashState = SpyHashStateImpl<void>;
 
 }  // namespace hash_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_
diff --git a/absl/hash/internal/wyhash.cc b/absl/hash/internal/wyhash.cc
new file mode 100644
index 0000000..642bde4
--- /dev/null
+++ b/absl/hash/internal/wyhash.cc
@@ -0,0 +1,111 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/hash/internal/wyhash.h"
+
+#include "absl/base/internal/unaligned_access.h"
+#include "absl/numeric/int128.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace hash_internal {
+
+static uint64_t WyhashMix(uint64_t v0, uint64_t v1) {
+  absl::uint128 p = v0;
+  p *= v1;
+  return absl::Uint128Low64(p) ^ absl::Uint128High64(p);
+}
+
+uint64_t Wyhash(const void* data, size_t len, uint64_t seed,
+                const uint64_t salt[]) {
+  const uint8_t* ptr = static_cast<const uint8_t*>(data);
+  uint64_t starting_length = static_cast<uint64_t>(len);
+  uint64_t current_state = seed ^ salt[0];
+
+  if (len > 64) {
+    // If we have more than 64 bytes, we're going to handle chunks of 64
+    // bytes at a time. We're going to build up two separate hash states
+    // which we will then hash together.
+    uint64_t duplicated_state = current_state;
+
+    do {
+      uint64_t a = absl::base_internal::UnalignedLoad64(ptr);
+      uint64_t b = absl::base_internal::UnalignedLoad64(ptr + 8);
+      uint64_t c = absl::base_internal::UnalignedLoad64(ptr + 16);
+      uint64_t d = absl::base_internal::UnalignedLoad64(ptr + 24);
+      uint64_t e = absl::base_internal::UnalignedLoad64(ptr + 32);
+      uint64_t f = absl::base_internal::UnalignedLoad64(ptr + 40);
+      uint64_t g = absl::base_internal::UnalignedLoad64(ptr + 48);
+      uint64_t h = absl::base_internal::UnalignedLoad64(ptr + 56);
+
+      uint64_t cs0 = WyhashMix(a ^ salt[1], b ^ current_state);
+      uint64_t cs1 = WyhashMix(c ^ salt[2], d ^ current_state);
+      current_state = (cs0 ^ cs1);
+
+      uint64_t ds0 = WyhashMix(e ^ salt[3], f ^ duplicated_state);
+      uint64_t ds1 = WyhashMix(g ^ salt[4], h ^ duplicated_state);
+      duplicated_state = (ds0 ^ ds1);
+
+      ptr += 64;
+      len -= 64;
+    } while (len > 64);
+
+    current_state = current_state ^ duplicated_state;
+  }
+
+  // We now have a data `ptr` with at most 64 bytes and the current state
+  // of the hashing state machine stored in current_state.
+  while (len > 16) {
+    uint64_t a = absl::base_internal::UnalignedLoad64(ptr);
+    uint64_t b = absl::base_internal::UnalignedLoad64(ptr + 8);
+
+    current_state = WyhashMix(a ^ salt[1], b ^ current_state);
+
+    ptr += 16;
+    len -= 16;
+  }
+
+  // We now have a data `ptr` with at most 16 bytes.
+  uint64_t a = 0;
+  uint64_t b = 0;
+  if (len > 8) {
+    // When we have at least 9 and at most 16 bytes, set A to the first 64
+    // bits of the input and B to the last 64 bits of the input. Yes, they will
+    // overlap in the middle if we are working with less than the full 16
+    // bytes.
+    a = absl::base_internal::UnalignedLoad64(ptr);
+    b = absl::base_internal::UnalignedLoad64(ptr + len - 8);
+  } else if (len > 3) {
+    // If we have at least 4 and at most 8 bytes, set A to the first 32
+    // bits and B to the last 32 bits.
+    a = absl::base_internal::UnalignedLoad32(ptr);
+    b = absl::base_internal::UnalignedLoad32(ptr + len - 4);
+  } else if (len > 0) {
+    // If we have at least 1 and at most 3 bytes, read all of the provided
+    // bits into A, with some adjustments.
+    a = ((ptr[0] << 16) | (ptr[len >> 1] << 8) | ptr[len - 1]);
+    b = 0;
+  } else {
+    a = 0;
+    b = 0;
+  }
+
+  uint64_t w = WyhashMix(a ^ salt[1], b ^ current_state);
+  uint64_t z = salt[1] ^ starting_length;
+  return WyhashMix(w, z);
+}
+
+}  // namespace hash_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/hash/internal/wyhash.h b/absl/hash/internal/wyhash.h
new file mode 100644
index 0000000..4aff4e9
--- /dev/null
+++ b/absl/hash/internal/wyhash.h
@@ -0,0 +1,48 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This file provides the Google-internal implementation of the Wyhash
+// algorithm.
+//
+// Wyhash is a fast hash function for hash tables, the fastest we've currently
+// (late 2020) found that passes the SMHasher tests. The algorithm relies on
+// intrinsic 128-bit multiplication for speed. This is not meant to be secure -
+// just fast.
+
+#ifndef ABSL_HASH_INTERNAL_WYHASH_H_
+#define ABSL_HASH_INTERNAL_WYHASH_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace hash_internal {
+
+// Hash function for a byte array. A 64-bit seed and a set of five 64-bit
+// integers are hashed into the result.
+//
+// To allow all hashable types (including string_view and Span) to depend on
+// this algoritm, we keep the API low-level, with as few dependencies as
+// possible.
+uint64_t Wyhash(const void* data, size_t len, uint64_t seed,
+                const uint64_t salt[5]);
+
+}  // namespace hash_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_HASH_INTERNAL_WYHASH_H_
diff --git a/absl/hash/internal/wyhash_test.cc b/absl/hash/internal/wyhash_test.cc
new file mode 100644
index 0000000..30dc9e3
--- /dev/null
+++ b/absl/hash/internal/wyhash_test.cc
@@ -0,0 +1,486 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in cokSaltliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or ikSaltlied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/hash/internal/wyhash.h"
+
+#include "absl/strings/escaping.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+static const uint64_t kCurrentSeed = 0;
+static const uint64_t kSalt[5] = {0xa0761d6478bd642f, 0xe7037ed1a0b428dbl,
+                                  0x8ebc6af09c88c6e3, 0x589965cc75374cc3l,
+                                  0x1d8e4e27c47d124f};
+
+// Note: We don't account for endianness, so the values here are only correct if
+// you're also running on a little endian platform.
+
+TEST(WyhashTest, EmptyString) {
+  const std::string s = "";
+  EXPECT_EQ(
+      absl::hash_internal::Wyhash(s.c_str(), s.length(), kCurrentSeed, kSalt),
+      4808886099364463827);
+}
+
+TEST(WyhashTest, Spaces) {
+  const std::string s = "   ";
+  EXPECT_EQ(
+      absl::hash_internal::Wyhash(s.c_str(), s.length(), kCurrentSeed, kSalt),
+      1686201463024549249);
+}
+
+TEST(WyhashTest, RepeatingString) {
+  const std::string s = "aaaa";
+  EXPECT_EQ(
+      absl::hash_internal::Wyhash(s.c_str(), s.length(), kCurrentSeed, kSalt),
+      6646112255271966632);
+}
+
+TEST(WyhashTest, HexString) {
+  const std::string small = "\x01\x02\x03";
+  const std::string med = "\x01\x02\x03\x04";
+
+  EXPECT_EQ(absl::hash_internal::Wyhash(small.c_str(), small.length(),
+                                        kCurrentSeed, kSalt),
+            11989428023081740911ULL);
+  EXPECT_EQ(absl::hash_internal::Wyhash(med.c_str(), med.length(), kCurrentSeed,
+                                        kSalt),
+            9765997711188871556ULL);
+}
+
+TEST(WyhashTest, Words) {
+  const std::string s = "third_party|wyhash|64";
+  EXPECT_EQ(
+      absl::hash_internal::Wyhash(s.c_str(), s.length(), kCurrentSeed, kSalt),
+      3702018632387611330);
+}
+
+TEST(WyhashTest, LongString) {
+  const std::string s =
+      "AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMnOpQrStUvWxYz"
+      "0123456789AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMnOp"
+      "QrStUvWxYz0123456789AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEf"
+      "GhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMnOpQrStUvWxYz012345"
+      "6789AbCdEfGhIjKlMnOpQrStUvWxYz0123456789";
+
+  EXPECT_EQ(
+      absl::hash_internal::Wyhash(s.c_str(), s.length(), kCurrentSeed, kSalt),
+      9245411362605796064ULL);
+}
+
+TEST(WyhashTest, BigReference) {
+  struct ExpectedResult {
+    absl::string_view base64_data;
+    uint64_t seed;
+    uint64_t hash;
+  } expected_results[] = {
+      {"", uint64_t{0xec42b7ab404b8acb}, uint64_t{0xe5a40d39ab796423}},
+      {"Zw==", uint64_t{0xeeee074043a3ee0f}, uint64_t{0xa6564b468248c683}},
+      {"xmk=", uint64_t{0x857902089c393de}, uint64_t{0xef192f401b116e1c}},
+      {"c1H/", uint64_t{0x993df040024ca3af}, uint64_t{0xbe8dc0c54617639d}},
+      {"SuwpzQ==", uint64_t{0xc4e4c2acea740e96}, uint64_t{0x93d7f665b5521c8e}},
+      {"uqvy++M=", uint64_t{0x6a214b3db872d0cf}, uint64_t{0x646d70bb42445f28}},
+      {"RnzCVPgb", uint64_t{0x44343db6a89dba4d}, uint64_t{0x96a7b1e3cc9bd426}},
+      {"6OeNdlouYw==", uint64_t{0x77b5d6d1ae1dd483},
+       uint64_t{0x76020289ab0790c4}},
+      {"M5/JmmYyDbc=", uint64_t{0x89ab8ecb44d221f1},
+       uint64_t{0x39f842e4133b9b44}},
+      {"MVijWiVdBRdY", uint64_t{0x60244b17577ca81b},
+       uint64_t{0x2b8d7047be4bcaab}},
+      {"6V7Uq7LNxpu0VA==", uint64_t{0x59a08dcee0717067},
+       uint64_t{0x99628abef6716a97}},
+      {"EQ6CdEEhPdyHcOk=", uint64_t{0xf5f20db3ade57396},
+       uint64_t{0x4432e02ba42b2740}},
+      {"PqFB4fxnPgF+l+rc", uint64_t{0xbf8dee0751ad3efb},
+       uint64_t{0x74d810efcad7918a}},
+      {"a5aPOFwq7LA7+zKvPA==", uint64_t{0x6b7a06b268d63e30},
+       uint64_t{0x88c84e986002507f}},
+      {"VOwY21wCGv5D+/qqOvs=", uint64_t{0xb8c37f0ae0f54c82},
+       uint64_t{0x4f99acf193cf39b9}},
+      {"KdHmBTx8lHXYvmGJ+Vy7", uint64_t{0x9fcbed0c38e50eef},
+       uint64_t{0xd90e7a3655891e37}},
+      {"qJkPlbHr8bMF7/cA6aE65Q==", uint64_t{0x2af4bade1d8e3a1d},
+       uint64_t{0x3bb378b1d4df8fcf}},
+      {"ygvL0EhHZL0fIx6oHHtkxRQ=", uint64_t{0x714e3aa912da2f2c},
+       uint64_t{0xf78e94045c052d47}},
+      {"c1rFXkt5YztwZCQRngncqtSs", uint64_t{0xf5ee75e3cbb82c1c},
+       uint64_t{0x26da0b2130da6b40}},
+      {"8hsQrzszzeNQSEcVXLtvIhm6mw==", uint64_t{0x620e7007321b93b9},
+       uint64_t{0x30b4d426af8c6986}},
+      {"ffUL4RocfyP4KfikGxO1yk7omDI=", uint64_t{0xc08528cac2e551fc},
+       uint64_t{0x5413b4aaf3baaeae}},
+      {"OOB5TT00vF9Od/rLbAWshiErqhpV", uint64_t{0x6a1debf9cc3ad39},
+       uint64_t{0x756ab265370a1597}},
+      {"or5wtXM7BFzTNpSzr+Lw5J5PMhVJ/Q==", uint64_t{0x7e0a3c88111fc226},
+       uint64_t{0xdaf5f4b7d09814fb}},
+      {"gk6pCHDUsoopVEiaCrzVDhioRKxb844=", uint64_t{0x1301fef15df39edb},
+       uint64_t{0x8f874ae37742b75e}},
+      {"TNctmwlC5QbEM6/No4R/La3UdkfeMhzs", uint64_t{0x64e181f3d5817ab},
+       uint64_t{0x8fecd03956121ce8}},
+      {"SsQw9iAjhWz7sgcE9OwLuSC6hsM+BfHs2Q==", uint64_t{0xafafc44961078ecb},
+       uint64_t{0x229c292ea7a08285}},
+      {"ZzO3mVCj4xTT2TT3XqDyEKj2BZQBvrS8RHg=", uint64_t{0x4f7bb45549250094},
+       uint64_t{0xbb4bf0692d14bae}},
+      {"+klp5iPQGtppan5MflEls0iEUzqU+zGZkDJX", uint64_t{0xa30061abaa2818c},
+       uint64_t{0x207b24ca3bdac1db}},
+      {"RO6bvOnlJc8I9eniXlNgqtKy0IX6VNg16NRmgg==", uint64_t{0xd902ee3e44a5705f},
+       uint64_t{0x64f6cd6745d3825b}},
+      {"ZJjZqId1ZXBaij9igClE3nyliU5XWdNRrayGlYA=", uint64_t{0x316d36da516f583},
+       uint64_t{0xa2b2e1656b58df1e}},
+      {"7BfkhfGMDGbxfMB8uyL85GbaYQtjr2K8g7RpLzr/", uint64_t{0x402d83f9f834f616},
+       uint64_t{0xd01d30d9ee7a148}},
+      {"rycWk6wHH7htETQtje9PidS2YzXBx+Qkg2fY7ZYS7A==",
+       uint64_t{0x9c604164c016b72c}, uint64_t{0x1cb4cd00ab804e3b}},
+      {"RTkC2OUK+J13CdGllsH0H5WqgspsSa6QzRZouqx6pvI=",
+       uint64_t{0x3f4507e01f9e73ba}, uint64_t{0x4697f2637fd90999}},
+      {"tKjKmbLCNyrLCM9hycOAXm4DKNpM12oZ7dLTmUx5iwAi",
+       uint64_t{0xc3fe0d5be8d2c7c7}, uint64_t{0x8383a756b5688c07}},
+      {"VprUGNH+5NnNRaORxgH/ySrZFQFDL+4VAodhfBNinmn8cg==",
+       uint64_t{0x531858a40bfa7ea1}, uint64_t{0x695c29cb3696a975}},
+      {"gc1xZaY+q0nPcUvOOnWnT3bqfmT/geth/f7Dm2e/DemMfk4=",
+       uint64_t{0x86689478a7a7e8fa}, uint64_t{0xda2e5a5a5e971521}},
+      {"Mr35fIxqx1ukPAL0su1yFuzzAU3wABCLZ8+ZUFsXn47UmAph",
+       uint64_t{0x4ec948b8e7f27288}, uint64_t{0x7935d4befa056b2b}},
+      {"A9G8pw2+m7+rDtWYAdbl8tb2fT7FFo4hLi2vAsa5Y8mKH3CX3g==",
+       uint64_t{0xce46c7213c10032}, uint64_t{0x38dd541ca95420fe}},
+      {"DFaJGishGwEHDdj9ixbCoaTjz9KS0phLNWHVVdFsM93CvPft3hM=",
+       uint64_t{0xf63e96ee6f32a8b6}, uint64_t{0xcc06c7a4963f967f}},
+      {"7+Ugx+Kr3aRNgYgcUxru62YkTDt5Hqis+2po81hGBkcrJg4N0uuy",
+       uint64_t{0x1cfe85e65fc5225}, uint64_t{0xbf0f6f66e232fb20}},
+      {"H2w6O8BUKqu6Tvj2xxaecxEI2wRgIgqnTTG1WwOgDSINR13Nm4d4Vg==",
+       uint64_t{0x45c474f1cee1d2e8}, uint64_t{0xf7efb32d373fe71a}},
+      {"1XBMnIbqD5jy65xTDaf6WtiwtdtQwv1dCVoqpeKj+7cTR1SaMWMyI04=",
+       uint64_t{0x6e024e14015f329c}, uint64_t{0xe2e64634b1c12660}},
+      {"znZbdXG2TSFrKHEuJc83gPncYpzXGbAebUpP0XxzH0rpe8BaMQ17nDbt",
+       uint64_t{0x760c40502103ae1c}, uint64_t{0x285b8fd1638e306d}},
+      {"ylu8Atu13j1StlcC1MRMJJXIl7USgDDS22HgVv0WQ8hx/8pNtaiKB17hCQ==",
+       uint64_t{0x17fd05c3c560c320}, uint64_t{0x658e8a4e3b714d6c}},
+      {"M6ZVVzsd7vAvbiACSYHioH/440dp4xG2mLlBnxgiqEvI/aIEGpD0Sf4VS0g=",
+       uint64_t{0x8b34200a6f8e90d9}, uint64_t{0xf391fb968e0eb398}},
+      {"li3oFSXLXI+ubUVGJ4blP6mNinGKLHWkvGruun85AhVn6iuMtocbZPVhqxzn",
+       uint64_t{0x6be89e50818bdf69}, uint64_t{0x744a9ea0cc144bf2}},
+      {"kFuQHuUCqBF3Tc3hO4dgdIp223ShaCoog48d5Do5zMqUXOh5XpGK1t5XtxnfGA==",
+       uint64_t{0xfb389773315b47d8}, uint64_t{0x12636f2be11012f1}},
+      {"jWmOad0v0QhXVJd1OdGuBZtDYYS8wBVHlvOeTQx9ZZnm8wLEItPMeihj72E0nWY=",
+       uint64_t{0x4f2512a23f61efee}, uint64_t{0x29c57de825948f80}},
+      {"z+DHU52HaOQdW4JrZwDQAebEA6rm13Zg/9lPYA3txt3NjTBqFZlOMvTRnVzRbl23",
+       uint64_t{0x59ccd92fc16c6fda}, uint64_t{0x58c6f99ab0d1c021}},
+      {"MmBiGDfYeTayyJa/tVycg+rN7f9mPDFaDc+23j0TlW9094er0ADigsl4QX7V3gG/qw==",
+       uint64_t{0x25c5a7f5bd330919}, uint64_t{0x13e7b5a7b82fe3bb}},
+      {"774RK+9rOL4iFvs1q2qpo/JVc/I39buvNjqEFDtDvyoB0FXxPI2vXqOrk08VPfIHkmU=",
+       uint64_t{0x51df4174d34c97d7}, uint64_t{0x10fbc87901e02b63}},
+      {"+slatXiQ7/2lK0BkVUI1qzNxOOLP3I1iK6OfHaoxgqT63FpzbElwEXSwdsryq3UlHK0I",
+       uint64_t{0x80ce6d76f89cb57}, uint64_t{0xa24c9184901b748b}},
+      {"64mVTbQ47dHjHlOHGS/hjJwr/"
+       "K2frCNpn87exOqMzNUVYiPKmhCbfS7vBUce5tO6Ec9osQ==",
+       uint64_t{0x20961c911965f684}, uint64_t{0xcac4fd4c5080e581}},
+      {"fIsaG1r530SFrBqaDj1kqE0AJnvvK8MNEZbII2Yw1OK77v0V59xabIh0B5axaz/"
+       "+a2V5WpA=",
+       uint64_t{0x4e5b926ec83868e7}, uint64_t{0xc38bdb7483ba68e1}},
+      {"PGih0zDEOWCYGxuHGDFu9Ivbff/"
+       "iE7BNUq65tycTR2R76TerrXALRosnzaNYO5fjFhTi+CiS",
+       uint64_t{0x3927b30b922eecef}, uint64_t{0xdb2a8069b2ceaffa}},
+      {"RnpA/"
+       "zJnEnnLjmICORByRVb9bCOgxF44p3VMiW10G7PvW7IhwsWajlP9kIwNA9FjAD2GoQHk2Q="
+       "=",
+       uint64_t{0xbd0291284a49b61c}, uint64_t{0xdf9fe91d0d1c7887}},
+      {"qFklMceaTHqJpy2qavJE+EVBiNFOi6OxjOA3LeIcBop1K7w8xQi3TrDk+"
+       "BrWPRIbfprszSaPfrI=",
+       uint64_t{0x73a77c575bcc956}, uint64_t{0xe83f49e96e2e6a08}},
+      {"cLbfUtLl3EcQmITWoTskUR8da/VafRDYF/ylPYwk7/"
+       "zazk6ssyrzxMN3mmSyvrXR2yDGNZ3WDrTT",
+       uint64_t{0x766a0e2ade6d09a6}, uint64_t{0xc69e61b62ca2b62}},
+      {"s/"
+       "Jf1+"
+       "FbsbCpXWPTUSeWyMH6e4CvTFvPE5Fs6Z8hvFITGyr0dtukHzkI84oviVLxhM1xMxrMAy1db"
+       "w==",
+       uint64_t{0x2599f4f905115869}, uint64_t{0xb4a4f3f85f8298fe}},
+      {"FvyQ00+j7nmYZVQ8hI1Edxd0AWplhTfWuFGiu34AK5X8u2hLX1bE97sZM0CmeLe+"
+       "7LgoUT1fJ/axybE=",
+       uint64_t{0xd8256e5444d21e53}, uint64_t{0x167a1b39e1e95f41}},
+      {"L8ncxMaYLBH3g9buPu8hfpWZNlOF7nvWLNv9IozH07uQsIBWSKxoPy8+"
+       "LW4tTuzC6CIWbRGRRD1sQV/4",
+       uint64_t{0xf664a91333fb8dfd}, uint64_t{0xf8a2a5649855ee41}},
+      {"CDK0meI07yrgV2kQlZZ+"
+       "wuVqhc2NmzqeLH7bmcA6kchsRWFPeVF5Wqjjaj556ABeUoUr3yBmfU3kWOakkg==",
+       uint64_t{0x9625b859be372cd1}, uint64_t{0x27992565b595c498}},
+      {"d23/vc5ONh/"
+       "HkMiq+gYk4gaCNYyuFKwUkvn46t+dfVcKfBTYykr4kdvAPNXGYLjM4u1YkAEFpJP+"
+       "nX7eOvs=",
+       uint64_t{0x7b99940782e29898}, uint64_t{0x3e08cca5b71f9346}},
+      {"NUR3SRxBkxTSbtQORJpu/GdR6b/h6sSGfsMj/KFd99ahbh+9r7LSgSGmkGVB/"
+       "mGoT0pnMTQst7Lv2q6QN6Vm",
+       uint64_t{0x4fe12fa5383b51a8}, uint64_t{0xad406b10c770a6d2}},
+      {"2BOFlcI3Z0RYDtS9T9Ie9yJoXlOdigpPeeT+CRujb/"
+       "O39Ih5LPC9hP6RQk1kYESGyaLZZi3jtabHs7DiVx/VDg==",
+       uint64_t{0xe2ccb09ac0f5b4b6}, uint64_t{0xd1713ce6e552bcf2}},
+      {"FF2HQE1FxEvWBpg6Z9zAMH+Zlqx8S1JD/"
+       "wIlViL6ZDZY63alMDrxB0GJQahmAtjlm26RGLnjW7jmgQ4Ie3I+014=",
+       uint64_t{0x7d0a37adbd7b753b}, uint64_t{0x753b287194c73ad3}},
+      {"tHmO7mqVL/PX11nZrz50Hc+M17Poj5lpnqHkEN+4bpMx/"
+       "YGbkrGOaYjoQjgmt1X2QyypK7xClFrjeWrCMdlVYtbW",
+       uint64_t{0xd3ae96ef9f7185f2}, uint64_t{0x5ae41a95f600af1c}},
+      {"/WiHi9IQcxRImsudkA/KOTqGe8/"
+       "gXkhKIHkjddv5S9hi02M049dIK3EUyAEjkjpdGLUs+BN0QzPtZqjIYPOgwsYE9g==",
+       uint64_t{0x4fb88ea63f79a0d8}, uint64_t{0x4a61163b86a8bb4c}},
+      {"qds+1ExSnU11L4fTSDz/QE90g4Jh6ioqSh3KDOTOAo2pQGL1k/"
+       "9CCC7J23YF27dUTzrWsCQA2m4epXoCc3yPHb3xElA=",
+       uint64_t{0xed564e259bb5ebe9}, uint64_t{0x42eeaa79e760c7e4}},
+      {"8FVYHx40lSQPTHheh08Oq0/"
+       "pGm2OlG8BEf8ezvAxHuGGdgCkqpXIueJBF2mQJhTfDy5NncO8ntS7vaKs7sCNdDaNGOEi",
+       uint64_t{0x3e3256b60c428000}, uint64_t{0x698df622ef465b0a}},
+      {"4ZoEIrJtstiCkeew3oRzmyJHVt/pAs2pj0HgHFrBPztbQ10NsQ/"
+       "lM6DM439QVxpznnBSiHMgMQJhER+70l72LqFTO1JiIQ==",
+       uint64_t{0xfb05bad59ec8705}, uint64_t{0x157583111e1a6026}},
+      {"hQPtaYI+wJyxXgwD5n8jGIKFKaFA/"
+       "P83KqCKZfPthnjwdOFysqEOYwAaZuaaiv4cDyi9TyS8hk5cEbNP/jrI7q6pYGBLbsM=",
+       uint64_t{0xafdc251dbf97b5f8}, uint64_t{0xaa1388f078e793e0}},
+      {"S4gpMSKzMD7CWPsSfLeYyhSpfWOntyuVZdX1xSBjiGvsspwOZcxNKCRIOqAA0moUfOh3I5+"
+       "juQV4rsqYElMD/gWfDGpsWZKQ",
+       uint64_t{0x10ec9c92ddb5dcbc}, uint64_t{0xf10d68d0f3309360}},
+      {"oswxop+"
+       "bthuDLT4j0PcoSKby4LhF47ZKg8K17xxHf74UsGCzTBbOz0MM8hQEGlyqDT1iUiAYnaPaUp"
+       "L2mRK0rcIUYA4qLt5uOw==",
+       uint64_t{0x9a767d5822c7dac4}, uint64_t{0x2af056184457a3de}},
+      {"0II/"
+       "697p+"
+       "BtLSjxj5989OXI004TogEb94VUnDzOVSgMXie72cuYRvTFNIBgtXlKfkiUjeqVpd4a+"
+       "n5bxNOD1TGrjQtzKU5r7obo=",
+       uint64_t{0xee46254080d6e2db}, uint64_t{0x6d0058e1590b2489}},
+      {"E84YZW2qipAlMPmctrg7TKlwLZ68l4L+c0xRDUfyyFrA4MAti0q9sHq3TDFviH0Y+"
+       "Kq3tEE5srWFA8LM9oomtmvm5PYxoaarWPLc",
+       uint64_t{0xbbb669588d8bf398}, uint64_t{0x638f287f68817f12}},
+      {"x3pa4HIElyZG0Nj7Vdy9IdJIR4izLmypXw5PCmZB5y68QQ4uRaVVi3UthsoJROvbjDJkP2D"
+       "Q6L/eN8pFeLFzNPKBYzcmuMOb5Ull7w==",
+       uint64_t{0xdc2afaa529beef44}, uint64_t{0xc46b71fecefd5467}},
+      {"jVDKGYIuWOP/"
+       "QKLdd2wi8B2VJA8Wh0c8PwrXJVM8FOGM3voPDVPyDJOU6QsBDPseoR8uuKd19OZ/"
+       "zAvSCB+zlf6upAsBlheUKgCfKww=",
+       uint64_t{0xf1f67391d45013a8}, uint64_t{0x2c8e94679d964e0a}},
+      {"mkquunhmYe1aR2wmUz4vcvLEcKBoe6H+kjUok9VUn2+eTSkWs4oDDtJvNCWtY5efJwg/"
+       "j4PgjRYWtqnrCkhaqJaEvkkOwVfgMIwF3e+d",
+       uint64_t{0x16fce2b8c65a3429}, uint64_t{0x8612b797ce22503a}},
+      {"fRelvKYonTQ+s+rnnvQw+JzGfFoPixtna0vzcSjiDqX5s2Kg2//"
+       "UGrK+AVCyMUhO98WoB1DDbrsOYSw2QzrcPe0+3ck9sePvb+Q/IRaHbw==",
+       uint64_t{0xf4b096699f49fe67}, uint64_t{0x59f929babfba7170}},
+      {"DUwXFJzagljo44QeJ7/"
+       "6ZKw4QXV18lhkYT2jglMr8WB3CHUU4vdsytvw6AKv42ZcG6fRkZkq9fpnmXy6xG0aO3WPT1"
+       "eHuyFirAlkW+zKtwg=",
+       uint64_t{0xca584c4bc8198682}, uint64_t{0x9527556923fb49a0}},
+      {"cYmZCrOOBBongNTr7e4nYn52uQUy2mfe48s50JXx2AZ6cRAt/"
+       "xRHJ5QbEoEJOeOHsJyM4nbzwFm++SlT6gFZZHJpkXJ92JkR86uS/eV1hJUR",
+       uint64_t{0xed269fc3818b6aad}, uint64_t{0x1039ab644f5e150b}},
+      {"EXeHBDfhwzAKFhsMcH9+2RHwV+mJaN01+9oacF6vgm8mCXRd6jeN9U2oAb0of5c5cO4i+"
+       "Vb/LlHZSMI490SnHU0bejhSCC2gsC5d2K30ER3iNA==",
+       uint64_t{0x33f253cbb8fe66a8}, uint64_t{0x7816c83f3aa05e6d}},
+      {"FzkzRYoNjkxFhZDso94IHRZaJUP61nFYrh5MwDwv9FNoJ5jyNCY/"
+       "eazPZk+tbmzDyJIGw2h3GxaWZ9bSlsol/vK98SbkMKCQ/wbfrXRLcDzdd/8=",
+       uint64_t{0xd0b76b2c1523d99c}, uint64_t{0xf51d2f564518c619}},
+      {"Re4aXISCMlYY/XsX7zkIFR04ta03u4zkL9dVbLXMa/q6hlY/CImVIIYRN3VKP4pnd0AUr/"
+       "ugkyt36JcstAInb4h9rpAGQ7GMVOgBniiMBZ/MGU7H",
+       uint64_t{0xfd28f0811a2a237f}, uint64_t{0x67d494cff03ac004}},
+      {"ueLyMcqJXX+MhO4UApylCN9WlTQ+"
+       "ltJmItgG7vFUtqs2qNwBMjmAvr5u0sAKd8jpzV0dDPTwchbIeAW5zbtkA2NABJV6hFM48ib"
+       "4/J3A5mseA3cS8w==",
+       uint64_t{0x6261fb136482e84}, uint64_t{0x2802d636ced1cfbb}},
+      {"6Si7Yi11L+jZMkwaN+GUuzXMrlvEqviEkGOilNq0h8TdQyYKuFXzkYc/"
+       "q74gP3pVCyiwz9KpVGMM9vfnq36riMHRknkmhQutxLZs5fbmOgEO69HglCU=",
+       uint64_t{0x458efc750bca7c3a}, uint64_t{0xf64e20bad771cb12}},
+      {"Q6AbOofGuTJOegPh9Clm/"
+       "9crtUMQqylKrTc1fhfJo1tqvpXxhU4k08kntL1RG7woRnFrVh2UoMrL1kjin+s9CanT+"
+       "y4hHwLqRranl9FjvxfVKm3yvg68",
+       uint64_t{0xa7e69ff84e5e7c27}, uint64_t{0xb9a6cf84a83e15e}},
+      {"ieQEbIPvqY2YfIjHnqfJiO1/MIVRk0RoaG/WWi3kFrfIGiNLCczYoklgaecHMm/"
+       "1sZ96AjO+a5stQfZbJQwS7Sc1ODABEdJKcTsxeW2hbh9A6CFzpowP1A==",
+       uint64_t{0x3c59bfd0c29efe9e}, uint64_t{0x8da6630319609301}},
+      {"zQUv8hFB3zh2GGl3KTvCmnfzE+"
+       "SUgQPVaSVIELFX5H9cE3FuVFGmymkPQZJLAyzC90Cmi8GqYCvPqTuAAB//"
+       "XTJxy4bCcVArgZG9zJXpjowpNBfr3ngWrSE=",
+       uint64_t{0x10befacc6afd298d}, uint64_t{0x40946a86e2a996f3}},
+      {"US4hcC1+op5JKGC7eIs8CUgInjKWKlvKQkapulxW262E/"
+       "B2ye79QxOexf188u2mFwwe3WTISJHRZzS61IwljqAWAWoBAqkUnW8SHmIDwHUP31J0p5sGd"
+       "P47L",
+       uint64_t{0x41d5320b0a38efa7}, uint64_t{0xcab7f5997953fa76}},
+      {"9bHUWFna2LNaGF6fQLlkx1Hkt24nrkLE2CmFdWgTQV3FFbUe747SSqYw6ebpTa07MWSpWRP"
+       "sHesVo2B9tqHbe7eQmqYebPDFnNqrhSdZwFm9arLQVs+7a3Ic6A==",
+       uint64_t{0x58db1c7450fe17f3}, uint64_t{0x39129ca0e04fc465}},
+      {"Kb3DpHRUPhtyqgs3RuXjzA08jGb59hjKTOeFt1qhoINfYyfTt2buKhD6YVffRCPsgK9SeqZ"
+       "qRPJSyaqsa0ovyq1WnWW8jI/NhvAkZTVHUrX2pC+cD3OPYT05Dag=",
+       uint64_t{0x6098c055a335b7a6}, uint64_t{0x5238221fd685e1b8}},
+      {"gzxyMJIPlU+bJBwhFUCHSofZ/"
+       "319LxqMoqnt3+L6h2U2+ZXJCSsYpE80xmR0Ta77Jq54o92SMH87HV8dGOaCTuAYF+"
+       "lDL42SY1P316Cl0sZTS2ow3ZqwGbcPNs/1",
+       uint64_t{0x1bbacec67845a801}, uint64_t{0x175130c407dbcaab}},
+      {"uR7V0TW+FGVMpsifnaBAQ3IGlr1wx5sKd7TChuqRe6OvUXTlD4hKWy8S+"
+       "8yyOw8lQabism19vOQxfmocEOW/"
+       "vzY0pEa87qHrAZy4s9fH2Bltu8vaOIe+agYohhYORQ==",
+       uint64_t{0xc419cfc7442190}, uint64_t{0x2f20e7536c0b0df}},
+      {"1UR5eoo2aCwhacjZHaCh9bkOsITp6QunUxHQ2SfeHv0imHetzt/"
+       "Z70mhyWZBalv6eAx+YfWKCUib2SHDtz/"
+       "A2dc3hqUWX5VfAV7FQsghPUAtu6IiRatq4YSLpDvKZBQ=",
+       uint64_t{0xc95e510d94ba270c}, uint64_t{0x2742cb488a04ad56}},
+      {"opubR7H63BH7OtY+Avd7QyQ25UZ8kLBdFDsBTwZlY6gA/"
+       "u+x+"
+       "czC9AaZMgmQrUy15DH7YMGsvdXnviTtI4eVI4aF1H9Rl3NXMKZgwFOsdTfdcZeeHVRzBBKX"
+       "8jUfh1il",
+       uint64_t{0xff1ae05c98089c3f}, uint64_t{0xd6afb593879ff93b}},
+      {"DC0kXcSXtfQ9FbSRwirIn5tgPri0sbzHSa78aDZVDUKCMaBGyFU6BmrulywYX8yzvwprdLs"
+       "oOwTWN2wMjHlPDqrvVHNEjnmufRDblW+nSS+xtKNs3N5xsxXdv6JXDrAB/Q==",
+       uint64_t{0x90c02b8dceced493}, uint64_t{0xf50ad64caac0ca7f}},
+      {"BXRBk+3wEP3Lpm1y75wjoz+PgB0AMzLe8tQ1AYU2/"
+       "oqrQB2YMC6W+9QDbcOfkGbeH+b7IBkt/"
+       "gwCMw2HaQsRFEsurXtcQ3YwRuPz5XNaw5NAvrNa67Fm7eRzdE1+hWLKtA8=",
+       uint64_t{0x9f8a76697ab1aa36}, uint64_t{0x2ade95c4261364ae}},
+      {"RRBSvEGYnzR9E45Aps/+WSnpCo/X7gJLO4DRnUqFrJCV/kzWlusLE/"
+       "6ZU6RoUf2ROwcgEvUiXTGjLs7ts3t9SXnJHxC1KiOzxHdYLMhVvgNd3hVSAXODpKFSkVXND"
+       "55G2L1W",
+       uint64_t{0x6ba1bf3d811a531d}, uint64_t{0x5c4f3299faacd07a}},
+      {"jeh6Qazxmdi57pa9S3XSnnZFIRrnc6s8QLrah5OX3SB/V2ErSPoEAumavzQPkdKF1/"
+       "SfvmdL+qgF1C+Yawy562QaFqwVGq7+tW0yxP8FStb56ZRgNI4IOmI30s1Ei7iops9Uuw==",
+       uint64_t{0x6a418974109c67b4}, uint64_t{0xfffe3bff0ae5e9bc}},
+      {"6QO5nnDrY2/"
+       "wrUXpltlKy2dSBcmK15fOY092CR7KxAjNfaY+"
+       "aAmtWbbzQk3MjBg03x39afSUN1fkrWACdyQKRaGxgwq6MGNxI6W+8DLWJBHzIXrntrE/"
+       "ml6fnNXEpxplWJ1vEs4=",
+       uint64_t{0x8472f1c2b3d230a3}, uint64_t{0x1db785c0005166e4}},
+      {"0oPxeEHhqhcFuwonNfLd5jF3RNATGZS6NPoS0WklnzyokbTqcl4BeBkMn07+fDQv83j/"
+       "BpGUwcWO05f3+DYzocfnizpFjLJemFGsls3gxcBYxcbqWYev51tG3lN9EvRE+X9+Pwww",
+       uint64_t{0x5e06068f884e73a7}, uint64_t{0xea000d962ad18418}},
+      {"naSBSjtOKgAOg8XVbR5cHAW3Y+QL4Pb/JO9/"
+       "oy6L08wvVRZqo0BrssMwhzBP401Um7A4ppAupbQeJFdMrysY34AuSSNvtNUy5VxjNECwiNt"
+       "gwYHw7yakDUv8WvonctmnoSPKENegQg==",
+       uint64_t{0x55290b1a8f170f59}, uint64_t{0xe42aef38359362d9}},
+      {"vPyl8DxVeRe1OpilKb9KNwpGkQRtA94UpAHetNh+"
+       "95V7nIW38v7PpzhnTWIml5kw3So1Si0TXtIUPIbsu32BNhoH7QwFvLM+"
+       "JACgSpc5e3RjsL6Qwxxi11npwxRmRUqATDeMUfRAjxg=",
+       uint64_t{0x5501cfd83dfe706a}, uint64_t{0xc8e95657348a3891}},
+      {"QC9i2GjdTMuNC1xQJ74ngKfrlA4w3o58FhvNCltdIpuMhHP1YsDA78scQPLbZ3OCUgeQguY"
+       "f/vw6zAaVKSgwtaykqg5ka/4vhz4hYqWU5ficdXqClHl+zkWEY26slCNYOM5nnDlly8Cj",
+       uint64_t{0xe43ed13d13a66990}, uint64_t{0xc162eca864f238c6}},
+      {"7CNIgQhAHX27nxI0HeB5oUTnTdgKpRDYDKwRcXfSFGP1XeT9nQF6WKCMjL1tBV6x7KuJ91G"
+       "Zz11F4c+8s+MfqEAEpd4FHzamrMNjGcjCyrVtU6y+7HscMVzr7Q/"
+       "ODLcPEFztFnwjvCjmHw==",
+       uint64_t{0xdf43bc375cf5283f}, uint64_t{0xbe1fb373e20579ad}},
+      {"Qa/hC2RPXhANSospe+gUaPfjdK/yhQvfm4cCV6/pdvCYWPv8p1kMtKOX3h5/"
+       "8oZ31fsmx4Axphu5qXJokuhZKkBUJueuMpxRyXpwSWz2wELx5glxF7CM0Fn+"
+       "OevnkhUn5jsPlG2r5jYlVn8=",
+       uint64_t{0x8112b806d288d7b5}, uint64_t{0x628a1d4f40aa6ffd}},
+      {"kUw/0z4l3a89jTwN5jpG0SHY5km/"
+       "IVhTjgM5xCiPRLncg40aqWrJ5vcF891AOq5hEpSq0bUCJUMFXgct7kvnys905HjerV7Vs1G"
+       "y84tgVJ70/2+pAZTsB/PzNOE/G6sOj4+GbTzkQu819OLB",
+       uint64_t{0xd52a18abb001cb46}, uint64_t{0xa87bdb7456340f90}},
+      {"VDdfSDbO8Tdj3T5W0XM3EI7iHh5xpIutiM6dvcJ/fhe23V/srFEkDy5iZf/"
+       "VnA9kfi2C79ENnFnbOReeuZW1b3MUXB9lgC6U4pOTuC+"
+       "jHK3Qnpyiqzj7h3ISJSuo2pob7vY6VHZo6Fn7exEqHg==",
+       uint64_t{0xe12b76a2433a1236}, uint64_t{0x5960ef3ba982c801}},
+      {"Ldfvy3ORdquM/R2fIkhH/ONi69mcP1AEJ6n/"
+       "oropwecAsLJzQSgezSY8bEiEs0VnFTBBsW+RtZY6tDj03fnb3amNUOq1b7jbqyQkL9hpl+"
+       "2Z2J8IaVSeownWl+bQcsR5/xRktIMckC5AtF4YHfU=",
+       uint64_t{0x175bf7319cf1fa00}, uint64_t{0x5026586df9a431ec}},
+      {"BrbNpb42+"
+       "VzZAjJw6QLirXzhweCVRfwlczzZ0VX2xluskwBqyfnGovz5EuX79JJ31VNXa5hTkAyQat3l"
+       "YKRADTdAdwE5PqM1N7YaMqqsqoAAAeuYVXuk5eWCykYmClNdSspegwgCuT+403JigBzi",
+       uint64_t{0xd63d57b3f67525ae}, uint64_t{0xfe4b8a20fdf0840b}},
+      {"gB3NGHJJvVcuPyF0ZSvHwnWSIfmaI7La24VMPQVoIIWF7Z74NltPZZpx2f+cocESM+"
+       "ILzQW9p+BC8x5IWz7N4Str2WLGKMdgmaBfNkEhSHQDU0IJEOnpUt0HmjhFaBlx0/"
+       "LTmhua+rQ6Wup8ezLwfg==",
+       uint64_t{0x933faea858832b73}, uint64_t{0xdcb761867da7072f}},
+      {"hTKHlRxx6Pl4gjG+6ksvvj0CWFicUg3WrPdSJypDpq91LUWRni2KF6+"
+       "81ZoHBFhEBrCdogKqeK+hy9bLDnx7g6rAFUjtn1+cWzQ2YjiOpz4+"
+       "ROBB7lnwjyTGWzJD1rXtlso1g2qVH8XJVigC5M9AIxM=",
+       uint64_t{0x53d061e5f8e7c04f}, uint64_t{0xc10d4653667275b7}},
+      {"IWQBelSQnhrr0F3BhUpXUIDauhX6f95Qp+A0diFXiUK7irwPG1oqBiqHyK/SH/"
+       "9S+"
+       "rln9DlFROAmeFdH0OCJi2tFm4afxYzJTFR4HnR4cG4x12JqHaZLQx6iiu6CE3rtWBVz99oA"
+       "wCZUOEXIsLU24o2Y",
+       uint64_t{0xdb4124556dd515e0}, uint64_t{0x727720deec13110b}},
+      {"TKo+l+"
+       "1dOXdLvIrFqeLaHdm0HZnbcdEgOoLVcGRiCbAMR0j5pIFw8D36tefckAS1RCFOH5IgP8yiF"
+       "T0Gd0a2hI3+"
+       "fTKA7iK96NekxWeoeqzJyctc6QsoiyBlkZerRxs5RplrxoeNg29kKDTM0K94mnhD9g==",
+       uint64_t{0x4fb31a0dd681ee71}, uint64_t{0x710b009662858dc9}},
+      {"YU4e7G6EfQYvxCFoCrrT0EFgVLHFfOWRTJQJ5gxM3G2b+"
+       "1kJf9YPrpsxF6Xr6nYtS8reEEbDoZJYqnlk9lXSkVArm88Cqn6d25VCx3+"
+       "49MqC0trIlXtb7SXUUhwpJK16T0hJUfPH7s5cMZXc6YmmbFuBNPE=",
+       uint64_t{0x27cc72eefa138e4c}, uint64_t{0xfbf8f7a3ecac1eb7}},
+      {"/I/"
+       "eImMwPo1U6wekNFD1Jxjk9XQVi1D+"
+       "FPdqcHifYXQuP5aScNQfxMAmaPR2XhuOQhADV5tTVbBKwCDCX4E3jcDNHzCiPvViZF1W27t"
+       "xaf2BbFQdwKrNCmrtzcluBFYu0XZfc7RU1RmxK/RtnF1qHsq/O4pp",
+       uint64_t{0x44bc2dfba4bd3ced}, uint64_t{0xb6fc4fcd0722e3df}},
+      {"CJTT9WGcY2XykTdo8KodRIA29qsqY0iHzWZRjKHb9alwyJ7RZAE3V5Juv4MY3MeYEr1EPCC"
+       "MxO7yFXqT8XA8YTjaMp3bafRt17Pw8JC4iKJ1zN+WWKOESrj+"
+       "3aluGQqn8z1EzqY4PH7rLG575PYeWsP98BugdA==",
+       uint64_t{0x242da1e3a439bed8}, uint64_t{0x7cb86dcc55104aac}},
+      {"ZlhyQwLhXQyIUEnMH/"
+       "AEW27vh9xrbNKJxpWGtrEmKhd+nFqAfbeNBQjW0SfG1YI0xQkQMHXjuTt4P/"
+       "EpZRtA47ibZDVS8TtaxwyBjuIDwqcN09eCtpC+Ls+"
+       "vWDTLmBeDM3u4hmzz4DQAYsLiZYSJcldg9Q3wszw=",
+       uint64_t{0xdc559c746e35c139}, uint64_t{0x19e71e9b45c3a51e}},
+      {"v2KU8y0sCrBghmnm8lzGJlwo6D6ObccAxCf10heoDtYLosk4ztTpLlpSFEyu23MLA1tJkcg"
+       "Rko04h19QMG0mOw/"
+       "wc93EXAweriBqXfvdaP85sZABwiKO+6rtS9pacRVpYYhHJeVTQ5NzrvBvi1huxAr+"
+       "xswhVMfL",
+       uint64_t{0xd0b0350275b9989}, uint64_t{0x51de38573c2bea48}},
+      {"QhKlnIS6BuVCTQsnoE67E/"
+       "yrgogE8EwO7xLaEGei26m0gEU4OksefJgppDh3X0x0Cs78Dr9IHK5b977CmZlrTRmwhlP8p"
+       "M+UzXPNRNIZuN3ntOum/QhUWP8SGpirheXENWsXMQ/"
+       "nxtxakyEtrNkKk471Oov9juP8oQ==",
+       uint64_t{0xb04489e41d17730c}, uint64_t{0xa73ab6996d6df158}},
+      {"/ZRMgnoRt+Uo6fUPr9FqQvKX7syhgVqWu+"
+       "WUSsiQ68UlN0efSP6Eced5gJZL6tg9gcYJIkhjuQNITU0Q3TjVAnAcobgbJikCn6qZ6pRxK"
+       "BY4MTiAlfGD3T7R7hwJwx554MAy++Zb/YUFlnCaCJiwQMnowF7aQzwYFCo=",
+       uint64_t{0x2217285eb4572156}, uint64_t{0x55ef2b8c930817b2}},
+      {"NB7tU5fNE8nI+SXGfipc7sRkhnSkUF1krjeo6k+8FITaAtdyz+"
+       "o7mONgXmGLulBPH9bEwyYhKNVY0L+njNQrZ9YC2aXsFD3PdZsxAFaBT3VXEzh+"
+       "NGBTjDASNL3mXyS8Yv1iThGfHoY7T4aR0NYGJ+k+pR6f+KrPC96M",
+       uint64_t{0x12c2e8e68aede73b}, uint64_t{0xb2850bf5fae87157}},
+      {"8T6wrqCtEO6/rwxF6lvMeyuigVOLwPipX/FULvwyu+1wa5sQGav/"
+       "2FsLHUVn6cGSi0LlFwLewGHPFJDLR0u4t7ZUyM//"
+       "x6da0sWgOa5hzDqjsVGmjxEHXiaXKW3i4iSZNuxoNbMQkIbVML+"
+       "DkYu9ND0O2swg4itGeVSzXA==",
+       uint64_t{0x4d612125bdc4fd00}, uint64_t{0xecf3de1acd04651f}},
+      {"Ntf1bMRdondtMv1CYr3G80iDJ4WSAlKy5H34XdGruQiCrnRGDBa+"
+       "eUi7vKp4gp3BBcVGl8eYSasVQQjn7MLvb3BjtXx6c/"
+       "bCL7JtpzQKaDnPr9GWRxpBXVxKREgMM7d8lm35EODv0w+"
+       "hQLfVSh8OGs7fsBb68nNWPLeeSOo=",
+       uint64_t{0x81826b553954464e}, uint64_t{0xcc0a40552559ff32}},
+      {"VsSAw72Ro6xks02kaiLuiTEIWBC5bgqr4WDnmP8vglXzAhixk7td926rm9jNimL+"
+       "kroPSygZ9gl63aF5DCPOACXmsbmhDrAQuUzoh9ZKhWgElLQsrqo1KIjWoZT5b5QfVUXY9lS"
+       "IBg3U75SqORoTPq7HalxxoIT5diWOcJQi",
+       uint64_t{0xc2e5d345dc0ddd2d}, uint64_t{0xc385c374f20315b1}},
+      {"j+loZ+C87+"
+       "bJxNVebg94gU0mSLeDulcHs84tQT7BZM2rzDSLiCNxUedHr1ZWJ9ejTiBa0dqy2I2ABc++"
+       "xzOLcv+//YfibtjKtYggC6/3rv0XCc7xu6d/"
+       "O6xO+XOBhOWAQ+IHJVHf7wZnDxIXB8AUHsnjEISKj7823biqXjyP3g==",
+       uint64_t{0x3da6830a9e32631e}, uint64_t{0xb90208a4c7234183}},
+      {"f3LlpcPElMkspNtDq5xXyWU62erEaKn7RWKlo540gR6mZsNpK1czV/"
+       "sOmqaq8XAQLEn68LKj6/"
+       "cFkJukxRzCa4OF1a7cCAXYFp9+wZDu0bw4y63qbpjhdCl8GO6Z2lkcXy7KOzbPE01ukg7+"
+       "gN+7uKpoohgAhIwpAKQXmX5xtd0=",
+       uint64_t{0xc9ae5c8759b4877a}, uint64_t{0x58aa1ca7a4c075d9}},
+  };
+
+  for (const auto& expected_result : expected_results) {
+    std::string str;
+    ASSERT_TRUE(absl::Base64Unescape(expected_result.base64_data, &str));
+    EXPECT_EQ(absl::hash_internal::Wyhash(str.data(), str.size(),
+                                          expected_result.seed, kSalt),
+              expected_result.hash);
+  }
+}
+
+}  // namespace
diff --git a/absl/memory/BUILD.bazel b/absl/memory/BUILD.bazel
index 2ba9d7c..d2824a0 100644
--- a/absl/memory/BUILD.bazel
+++ b/absl/memory/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "memory",
diff --git a/absl/memory/memory.h b/absl/memory/memory.h
index 5a4a1a1..2b5ff62 100644
--- a/absl/memory/memory.h
+++ b/absl/memory/memory.h
@@ -34,6 +34,7 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // -----------------------------------------------------------------------------
 // Function Template: WrapUnique()
@@ -92,11 +93,12 @@
 
 }  // namespace memory_internal
 
-// gcc 4.8 has __cplusplus at 201301 but doesn't define make_unique.  Other
-// supported compilers either just define __cplusplus as 201103 but have
-// make_unique (msvc), or have make_unique whenever __cplusplus > 201103 (clang)
+// gcc 4.8 has __cplusplus at 201301 but the libstdc++ shipped with it doesn't
+// define make_unique.  Other supported compilers either just define __cplusplus
+// as 201103 but have make_unique (msvc), or have make_unique whenever
+// __cplusplus > 201103 (clang).
 #if (__cplusplus > 201103L || defined(_MSC_VER)) && \
-    !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8)
+    !(defined(__GLIBCXX__) && !defined(__cpp_lib_make_unique))
 using std::make_unique;
 #else
 // -----------------------------------------------------------------------------
@@ -418,6 +420,9 @@
 //
 // A C++11 compatible implementation of C++17's std::allocator_traits.
 //
+#if __cplusplus >= 201703L
+using std::allocator_traits;
+#else  // __cplusplus >= 201703L
 template <typename Alloc>
 struct allocator_traits {
   using allocator_type = Alloc;
@@ -607,6 +612,7 @@
     return a;
   }
 };
+#endif  // __cplusplus >= 201703L
 
 namespace memory_internal {
 
@@ -687,6 +693,7 @@
   }
 }
 }  // namespace memory_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_MEMORY_MEMORY_H_
diff --git a/absl/memory/memory_exception_safety_test.cc b/absl/memory/memory_exception_safety_test.cc
index 729507e..1df7261 100644
--- a/absl/memory/memory_exception_safety_test.cc
+++ b/absl/memory/memory_exception_safety_test.cc
@@ -22,13 +22,11 @@
 #include "absl/base/internal/exception_safety_testing.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 constexpr int kLength = 50;
 using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;
-using ThrowerStorage =
-    absl::aligned_storage_t<sizeof(Thrower), alignof(Thrower)>;
-using ThrowerList = std::array<ThrowerStorage, kLength>;
 
 TEST(MakeUnique, CheckForLeaks) {
   constexpr int kValue = 321;
@@ -53,6 +51,7 @@
 }
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_HAVE_EXCEPTIONS
diff --git a/absl/memory/memory_test.cc b/absl/memory/memory_test.cc
index c47820e..1990c7b 100644
--- a/absl/memory/memory_test.cc
+++ b/absl/memory/memory_test.cc
@@ -17,6 +17,7 @@
 #include "absl/memory/memory.h"
 
 #include <sys/types.h>
+
 #include <cstddef>
 #include <memory>
 #include <string>
@@ -36,10 +37,10 @@
 // been called, via the instance_count variable.
 class DestructorVerifier {
  public:
-  DestructorVerifier() { ++instance_count_;  }
+  DestructorVerifier() { ++instance_count_; }
   DestructorVerifier(const DestructorVerifier&) = delete;
   DestructorVerifier& operator=(const DestructorVerifier&) = delete;
-  ~DestructorVerifier() {  --instance_count_; }
+  ~DestructorVerifier() { --instance_count_; }
 
   // The number of instances of this class currently active.
   static int instance_count() { return instance_count_; }
@@ -156,9 +157,7 @@
     allocs().push_back(n);
     return ::operator new[](n);
   }
-  void operator delete[](void* p) {
-    return ::operator delete[](p);
-  }
+  void operator delete[](void* p) { return ::operator delete[](p); }
   static std::vector<size_t>& allocs() {
     static auto& v = *new std::vector<size_t>;
     return v;
@@ -171,8 +170,7 @@
   ArrayWatch::allocs().clear();
 
   auto p = absl::make_unique<ArrayWatch[]>(5);
-  static_assert(std::is_same<decltype(p),
-                             std::unique_ptr<ArrayWatch[]>>::value,
+  static_assert(std::is_same<decltype(p), std::unique_ptr<ArrayWatch[]>>::value,
                 "unexpected return type");
   EXPECT_THAT(ArrayWatch::allocs(), ElementsAre(5 * sizeof(ArrayWatch)));
 }
@@ -181,7 +179,7 @@
   // Ensure that absl::make_unique is not ambiguous with std::make_unique.
   // In C++14 mode, the below call to make_unique has both types as candidates.
   struct TakesStdType {
-    explicit TakesStdType(const std::vector<int> &vec) {}
+    explicit TakesStdType(const std::vector<int>& vec) {}
   };
   using absl::make_unique;
   (void)make_unique<TakesStdType>(std::vector<int>());
@@ -541,8 +539,8 @@
   MinimalMockAllocator(const MinimalMockAllocator& other)
       : value(other.value) {}
   using value_type = TestValue;
-  MOCK_METHOD1(allocate, value_type*(size_t));
-  MOCK_METHOD2(deallocate, void(value_type*, size_t));
+  MOCK_METHOD(value_type*, allocate, (size_t));
+  MOCK_METHOD(void, deallocate, (value_type*, size_t));
 
   int value;
 };
@@ -557,7 +555,7 @@
   EXPECT_CALL(mock, deallocate(&x, 7));
 
   EXPECT_EQ(&x, Traits::allocate(mock, 7));
-  Traits::allocate(mock, 7, static_cast<const void*>(&hint));
+  static_cast<void>(Traits::allocate(mock, 7, static_cast<const void*>(&hint)));
   EXPECT_EQ(&x, Traits::allocate(mock, 7, static_cast<const void*>(&hint)));
   Traits::deallocate(mock, &x, 7);
 
@@ -579,13 +577,14 @@
   explicit FullMockAllocator(int value) : value(value) {}
   FullMockAllocator(const FullMockAllocator& other) : value(other.value) {}
   using value_type = TestValue;
-  MOCK_METHOD1(allocate, value_type*(size_t));
-  MOCK_METHOD2(allocate, value_type*(size_t, const void*));
-  MOCK_METHOD2(construct, void(value_type*, int*));
-  MOCK_METHOD1(destroy, void(value_type*));
-  MOCK_CONST_METHOD0(max_size, size_t());
-  MOCK_CONST_METHOD0(select_on_container_copy_construction,
-                     FullMockAllocator());
+  MOCK_METHOD(value_type*, allocate, (size_t));
+  MOCK_METHOD(value_type*, allocate, (size_t, const void*));
+  MOCK_METHOD(void, construct, (value_type*, int*));
+  MOCK_METHOD(void, destroy, (value_type*));
+  MOCK_METHOD(size_t, max_size, (),
+              (const));
+  MOCK_METHOD(FullMockAllocator, select_on_container_copy_construction, (),
+              (const));
 
   int value;
 };
@@ -642,8 +641,7 @@
   struct CanThrowAllocator {
     using is_nothrow = std::false_type;
   };
-  struct UnspecifiedAllocator {
-  };
+  struct UnspecifiedAllocator {};
   EXPECT_TRUE(absl::allocator_is_nothrow<NoThrowAllocator>::value);
   EXPECT_FALSE(absl::allocator_is_nothrow<CanThrowAllocator>::value);
   EXPECT_FALSE(absl::allocator_is_nothrow<UnspecifiedAllocator>::value);
diff --git a/absl/meta/BUILD.bazel b/absl/meta/BUILD.bazel
index c06d2d9..5585fcc 100644
--- a/absl/meta/BUILD.bazel
+++ b/absl/meta/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "type_traits",
diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h
index 927244e..d5cb5f3 100644
--- a/absl/meta/type_traits.h
+++ b/absl/meta/type_traits.h
@@ -41,7 +41,18 @@
 
 #include "absl/base/config.h"
 
+// MSVC constructibility traits do not detect destructor properties and so our
+// implementations should not use them as a source-of-truth.
+#if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
+#define ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1
+#endif
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// Defined and documented later on in this file.
+template <typename T>
+struct is_trivially_destructible;
 
 // Defined and documented later on in this file.
 template <typename T>
@@ -66,6 +77,20 @@
 #endif  // defined(_MSC_VER) && !defined(__GNUC__)
 
 template <class T>
+struct IsTriviallyMoveConstructibleObject
+    : std::integral_constant<
+          bool, std::is_move_constructible<
+                    type_traits_internal::SingleMemberUnion<T>>::value &&
+                    absl::is_trivially_destructible<T>::value> {};
+
+template <class T>
+struct IsTriviallyCopyConstructibleObject
+    : std::integral_constant<
+          bool, std::is_copy_constructible<
+                    type_traits_internal::SingleMemberUnion<T>>::value &&
+                    absl::is_trivially_destructible<T>::value> {};
+
+template <class T>
 struct IsTriviallyMoveAssignableReference : std::false_type {};
 
 template <class T>
@@ -145,6 +170,18 @@
 
 }  // namespace type_traits_internal
 
+// MSVC 19.20 has a regression that causes our workarounds to fail, but their
+// std forms now appear to be compliant.
+#if defined(_MSC_VER) && !defined(__clang__) && (_MSC_VER >= 1920)
+
+template <typename T>
+using is_copy_assignable = std::is_copy_assignable<T>;
+
+template <typename T>
+using is_move_assignable = std::is_move_assignable<T>;
+
+#else
+
 template <typename T>
 struct is_copy_assignable : type_traits_internal::is_detected<
                                 type_traits_internal::IsCopyAssignableImpl, T> {
@@ -155,6 +192,8 @@
                                 type_traits_internal::IsMoveAssignableImpl, T> {
 };
 
+#endif
+
 // void_t()
 //
 // Ignores the type of any its arguments and returns `void`. In general, this
@@ -180,7 +219,7 @@
 // This metafunction is designed to be a drop-in replacement for the C++17
 // `std::conjunction` metafunction.
 template <typename... Ts>
-struct conjunction;
+struct conjunction : std::true_type {};
 
 template <typename T, typename... Ts>
 struct conjunction<T, Ts...>
@@ -189,9 +228,6 @@
 template <typename T>
 struct conjunction<T> : T {};
 
-template <>
-struct conjunction<> : std::true_type {};
-
 // disjunction
 //
 // Performs a compile-time logical OR operation on the passed types (which
@@ -202,7 +238,7 @@
 // This metafunction is designed to be a drop-in replacement for the C++17
 // `std::disjunction` metafunction.
 template <typename... Ts>
-struct disjunction;
+struct disjunction : std::false_type {};
 
 template <typename T, typename... Ts>
 struct disjunction<T, Ts...> :
@@ -211,9 +247,6 @@
 template <typename T>
 struct disjunction<T> : T {};
 
-template <>
-struct disjunction<> : std::false_type {};
-
 // negation
 //
 // Performs a compile-time logical NOT operation on the passed type (which
@@ -243,7 +276,7 @@
 
 // is_trivially_destructible()
 //
-// Determines whether the passed type `T` is trivially destructable.
+// Determines whether the passed type `T` is trivially destructible.
 //
 // This metafunction is designed to be a drop-in replacement for the C++11
 // `std::is_trivially_destructible()` metafunction for platforms that have
@@ -309,7 +342,9 @@
     : std::integral_constant<bool, __has_trivial_constructor(T) &&
                                    std::is_default_constructible<T>::value &&
                                    is_trivially_destructible<T>::value> {
-#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
+#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
+    !defined(                                            \
+        ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
  private:
   static constexpr bool compliant =
       std::is_trivially_default_constructible<T>::value ==
@@ -340,10 +375,11 @@
 struct is_trivially_move_constructible
     : std::conditional<
           std::is_object<T>::value && !std::is_array<T>::value,
-          std::is_move_constructible<
-              type_traits_internal::SingleMemberUnion<T>>,
+          type_traits_internal::IsTriviallyMoveConstructibleObject<T>,
           std::is_reference<T>>::type::type {
-#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
+#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
+    !defined(                                            \
+        ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
  private:
   static constexpr bool compliant =
       std::is_trivially_move_constructible<T>::value ==
@@ -374,10 +410,11 @@
 struct is_trivially_copy_constructible
     : std::conditional<
           std::is_object<T>::value && !std::is_array<T>::value,
-          std::is_copy_constructible<
-              type_traits_internal::SingleMemberUnion<T>>,
+          type_traits_internal::IsTriviallyCopyConstructibleObject<T>,
           std::is_lvalue_reference<T>>::type::type {
-#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
+#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
+    !defined(                                            \
+        ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
  private:
   static constexpr bool compliant =
       std::is_trivially_copy_constructible<T>::value ==
@@ -409,7 +446,8 @@
 template <typename T>
 struct is_trivially_move_assignable
     : std::conditional<
-          std::is_object<T>::value && !std::is_array<T>::value,
+          std::is_object<T>::value && !std::is_array<T>::value &&
+              std::is_move_assignable<T>::value,
           std::is_move_assignable<type_traits_internal::SingleMemberUnion<T>>,
           type_traits_internal::IsTriviallyMoveAssignableReference<T>>::type::
           type {
@@ -572,8 +610,22 @@
 template <typename T>
 using underlying_type_t = typename std::underlying_type<T>::type;
 
-template <typename T>
-using result_of_t = typename std::result_of<T>::type;
+
+namespace type_traits_internal {
+
+#if __cplusplus >= 201703L
+// std::result_of is deprecated (C++17) or removed (C++20)
+template<typename> struct result_of;
+template<typename F, typename... Args>
+struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
+#else
+template<typename F> using result_of = std::result_of<F>;
+#endif
+
+}  // namespace type_traits_internal
+
+template<typename F>
+using result_of_t = typename type_traits_internal::result_of<F>::type;
 
 namespace type_traits_internal {
 // In MSVC we can't probe std::hash or stdext::hash because it triggers a
@@ -709,6 +761,7 @@
 using swap_internal::StdSwapIsUnconstrained;
 
 }  // namespace type_traits_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_META_TYPE_TRAITS_H_
diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc
index 6fbb42f..1aafd0d 100644
--- a/absl/meta/type_traits_test.cc
+++ b/absl/meta/type_traits_test.cc
@@ -347,21 +347,6 @@
   virtual ~Base() {}
 };
 
-// In GCC/Clang, std::is_trivially_constructible requires that the destructor is
-// trivial. However, MSVC doesn't require that. This results in different
-// behavior when checking is_trivially_constructible on any type with
-// nontrivial destructor. Since absl::is_trivially_default_constructible and
-// absl::is_trivially_copy_constructible both follows Clang/GCC's interpretation
-// and check is_trivially_destructible, it results in inconsistency with
-// std::is_trivially_xxx_constructible on MSVC. This macro is used to work
-// around this issue in test. In practice, a trivially constructible type
-// should also be trivially destructible.
-// GCC bug 51452: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452
-// LWG issue 2116: http://cplusplus.github.io/LWG/lwg-active.html#2116
-#ifndef _MSC_VER
-#define ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE 1
-#endif
-
 // Old versions of libc++, around Clang 3.5 to 3.6, consider deleted destructors
 // as also being trivial. With the resolution of CWG 1928 and CWG 1734, this
 // is no longer considered true and has thus been amended.
@@ -499,11 +484,9 @@
   EXPECT_FALSE(
       absl::is_trivially_default_constructible<DeletedDefaultCtor>::value);
 
-#ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE
   // types with nontrivial destructor are nontrivial
   EXPECT_FALSE(
       absl::is_trivially_default_constructible<NontrivialDestructor>::value);
-#endif
 
   // types with vtables
   EXPECT_FALSE(absl::is_trivially_default_constructible<Base>::value);
@@ -607,11 +590,9 @@
   EXPECT_FALSE(
       absl::is_trivially_move_constructible<NonCopyableOrMovable>::value);
 
-#ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE
   // type with nontrivial destructor are nontrivial move construbtible
   EXPECT_FALSE(
       absl::is_trivially_move_constructible<NontrivialDestructor>::value);
-#endif
 
   // types with vtables
   EXPECT_FALSE(absl::is_trivially_move_constructible<Base>::value);
@@ -682,11 +663,9 @@
   EXPECT_FALSE(
       absl::is_trivially_copy_constructible<NonCopyableOrMovable>::value);
 
-#ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE
   // type with nontrivial destructor are nontrivial copy construbtible
   EXPECT_FALSE(
       absl::is_trivially_copy_constructible<NontrivialDestructor>::value);
-#endif
 
   // types with vtables
   EXPECT_FALSE(absl::is_trivially_copy_constructible<Base>::value);
diff --git a/absl/numeric/BUILD.bazel b/absl/numeric/BUILD.bazel
index e09e52d..5d7b185 100644
--- a/absl/numeric/BUILD.bazel
+++ b/absl/numeric/BUILD.bazel
@@ -22,7 +22,36 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
+
+cc_library(
+    name = "bits",
+    hdrs = [
+        "bits.h",
+        "internal/bits.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:config",
+        "//absl/base:core_headers",
+    ],
+)
+
+cc_test(
+    name = "bits_test",
+    size = "small",
+    srcs = [
+        "bits_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":bits",
+        "//absl/random",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
 
 cc_library(
     name = "int128",
@@ -35,6 +64,7 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":bits",
         "//absl/base:config",
         "//absl/base:core_headers",
     ],
diff --git a/absl/numeric/CMakeLists.txt b/absl/numeric/CMakeLists.txt
index 242889f..be94352 100644
--- a/absl/numeric/CMakeLists.txt
+++ b/absl/numeric/CMakeLists.txt
@@ -16,6 +16,33 @@
 
 absl_cc_library(
   NAME
+    bits
+  HDRS
+    "bits.h"
+    "internal/bits.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::core_headers
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    bits_test
+  SRCS
+    "bits_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::bits
+    absl::core_headers
+    absl::random_random
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
     int128
   HDRS
     "int128.h"
@@ -28,6 +55,7 @@
   DEPS
     absl::config
     absl::core_headers
+    absl::bits
   PUBLIC
 )
 
diff --git a/absl/numeric/bits.h b/absl/numeric/bits.h
new file mode 100644
index 0000000..52013ad
--- /dev/null
+++ b/absl/numeric/bits.h
@@ -0,0 +1,177 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: bits.h
+// -----------------------------------------------------------------------------
+//
+// This file contains implementations of C++20's bitwise math functions, as
+// defined by:
+//
+// P0553R4:
+//  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0553r4.html
+// P0556R3:
+//  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0556r3.html
+// P1355R2:
+//  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1355r2.html
+// P1956R1:
+//  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1956r1.pdf
+//
+// When using a standard library that implements these functions, we use the
+// standard library's implementation.
+
+#ifndef ABSL_NUMERIC_BITS_H_
+#define ABSL_NUMERIC_BITS_H_
+
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+#if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) || \
+    (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L)
+#include <bit>
+#endif
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/numeric/internal/bits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+#if !(defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L)
+// rotating
+template <class T>
+ABSL_MUST_USE_RESULT constexpr
+    typename std::enable_if<std::is_unsigned<T>::value, T>::type
+    rotl(T x, int s) noexcept {
+  return numeric_internal::RotateLeft(x, s);
+}
+
+template <class T>
+ABSL_MUST_USE_RESULT constexpr
+    typename std::enable_if<std::is_unsigned<T>::value, T>::type
+    rotr(T x, int s) noexcept {
+  return numeric_internal::RotateRight(x, s);
+}
+
+// Counting functions
+//
+// While these functions are typically constexpr, on some platforms, they may
+// not be marked as constexpr due to constraints of the compiler/available
+// intrinsics.
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+    typename std::enable_if<std::is_unsigned<T>::value, int>::type
+    countl_zero(T x) noexcept {
+  return numeric_internal::CountLeadingZeroes(x);
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+    typename std::enable_if<std::is_unsigned<T>::value, int>::type
+    countl_one(T x) noexcept {
+  // Avoid integer promotion to a wider type
+  return countl_zero(static_cast<T>(~x));
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CTZ inline
+    typename std::enable_if<std::is_unsigned<T>::value, int>::type
+    countr_zero(T x) noexcept {
+  return numeric_internal::CountTrailingZeroes(x);
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CTZ inline
+    typename std::enable_if<std::is_unsigned<T>::value, int>::type
+    countr_one(T x) noexcept {
+  // Avoid integer promotion to a wider type
+  return countr_zero(static_cast<T>(~x));
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline
+    typename std::enable_if<std::is_unsigned<T>::value, int>::type
+    popcount(T x) noexcept {
+  return numeric_internal::Popcount(x);
+}
+#else  // defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+
+using std::countl_one;
+using std::countl_zero;
+using std::countr_one;
+using std::countr_zero;
+using std::popcount;
+using std::rotl;
+using std::rotr;
+
+#endif
+
+#if !(defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L)
+// Returns: true if x is an integral power of two; false otherwise.
+template <class T>
+constexpr inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
+has_single_bit(T x) noexcept {
+  return x != 0 && (x & (x - 1)) == 0;
+}
+
+// Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any
+// fractional part discarded.
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+    typename std::enable_if<std::is_unsigned<T>::value, T>::type
+    bit_width(T x) noexcept {
+  return std::numeric_limits<T>::digits - countl_zero(x);
+}
+
+// Returns: If x == 0, 0; otherwise the maximal value y such that
+// has_single_bit(y) is true and y <= x.
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+    typename std::enable_if<std::is_unsigned<T>::value, T>::type
+    bit_floor(T x) noexcept {
+  return x == 0 ? 0 : T{1} << (bit_width(x) - 1);
+}
+
+// Returns: N, where N is the smallest power of 2 greater than or equal to x.
+//
+// Preconditions: N is representable as a value of type T.
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+    typename std::enable_if<std::is_unsigned<T>::value, T>::type
+    bit_ceil(T x) {
+  // If T is narrower than unsigned, T{1} << bit_width will be promoted.  We
+  // want to force it to wraparound so that bit_ceil of an invalid value are not
+  // core constant expressions.
+  //
+  // BitCeilNonPowerOf2 triggers an overflow in constexpr contexts if we would
+  // undergo promotion to unsigned but not fit the result into T without
+  // truncation.
+  return has_single_bit(x) ? T{1} << (bit_width(x) - 1)
+                           : numeric_internal::BitCeilNonPowerOf2(x);
+}
+#else  // defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
+
+using std::bit_ceil;
+using std::bit_floor;
+using std::bit_width;
+using std::has_single_bit;
+
+#endif
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_NUMERIC_BITS_H_
diff --git a/absl/numeric/bits_test.cc b/absl/numeric/bits_test.cc
new file mode 100644
index 0000000..8bf7bc9
--- /dev/null
+++ b/absl/numeric/bits_test.cc
@@ -0,0 +1,565 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/numeric/bits.h"
+
+#include <limits>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/random/random.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+TEST(Rotate, Left) {
+  static_assert(rotl(uint8_t{0x12}, 0) == uint8_t{0x12}, "");
+  static_assert(rotl(uint16_t{0x1234}, 0) == uint16_t{0x1234}, "");
+  static_assert(rotl(uint32_t{0x12345678UL}, 0) == uint32_t{0x12345678UL}, "");
+  static_assert(rotl(uint64_t{0x12345678ABCDEF01ULL}, 0) ==
+                    uint64_t{0x12345678ABCDEF01ULL},
+                "");
+
+  EXPECT_EQ(rotl(uint8_t{0x12}, 0), uint8_t{0x12});
+  EXPECT_EQ(rotl(uint16_t{0x1234}, 0), uint16_t{0x1234});
+  EXPECT_EQ(rotl(uint32_t{0x12345678UL}, 0), uint32_t{0x12345678UL});
+  EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, 0),
+            uint64_t{0x12345678ABCDEF01ULL});
+
+  EXPECT_EQ(rotl(uint8_t{0x12}, 8), uint8_t{0x12});
+  EXPECT_EQ(rotl(uint16_t{0x1234}, 16), uint16_t{0x1234});
+  EXPECT_EQ(rotl(uint32_t{0x12345678UL}, 32), uint32_t{0x12345678UL});
+  EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, 64),
+            uint64_t{0x12345678ABCDEF01ULL});
+
+  EXPECT_EQ(rotl(uint8_t{0x12}, -8), uint8_t{0x12});
+  EXPECT_EQ(rotl(uint16_t{0x1234}, -16), uint16_t{0x1234});
+  EXPECT_EQ(rotl(uint32_t{0x12345678UL}, -32), uint32_t{0x12345678UL});
+  EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, -64),
+            uint64_t{0x12345678ABCDEF01ULL});
+
+  EXPECT_EQ(rotl(uint8_t{0x12}, 4), uint8_t{0x21});
+  EXPECT_EQ(rotl(uint16_t{0x1234}, 4), uint16_t{0x2341});
+  EXPECT_EQ(rotl(uint32_t{0x12345678UL}, 4), uint32_t{0x23456781UL});
+  EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, 4),
+            uint64_t{0x2345678ABCDEF011ULL});
+
+  EXPECT_EQ(rotl(uint8_t{0x12}, -4), uint8_t{0x21});
+  EXPECT_EQ(rotl(uint16_t{0x1234}, -4), uint16_t{0x4123});
+  EXPECT_EQ(rotl(uint32_t{0x12345678UL}, -4), uint32_t{0x81234567UL});
+  EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, -4),
+            uint64_t{0x112345678ABCDEF0ULL});
+}
+
+TEST(Rotate, Right) {
+  static_assert(rotr(uint8_t{0x12}, 0) == uint8_t{0x12}, "");
+  static_assert(rotr(uint16_t{0x1234}, 0) == uint16_t{0x1234}, "");
+  static_assert(rotr(uint32_t{0x12345678UL}, 0) == uint32_t{0x12345678UL}, "");
+  static_assert(rotr(uint64_t{0x12345678ABCDEF01ULL}, 0) ==
+                    uint64_t{0x12345678ABCDEF01ULL},
+                "");
+
+  EXPECT_EQ(rotr(uint8_t{0x12}, 0), uint8_t{0x12});
+  EXPECT_EQ(rotr(uint16_t{0x1234}, 0), uint16_t{0x1234});
+  EXPECT_EQ(rotr(uint32_t{0x12345678UL}, 0), uint32_t{0x12345678UL});
+  EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, 0),
+            uint64_t{0x12345678ABCDEF01ULL});
+
+  EXPECT_EQ(rotr(uint8_t{0x12}, 8), uint8_t{0x12});
+  EXPECT_EQ(rotr(uint16_t{0x1234}, 16), uint16_t{0x1234});
+  EXPECT_EQ(rotr(uint32_t{0x12345678UL}, 32), uint32_t{0x12345678UL});
+  EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, 64),
+            uint64_t{0x12345678ABCDEF01ULL});
+
+  EXPECT_EQ(rotr(uint8_t{0x12}, -8), uint8_t{0x12});
+  EXPECT_EQ(rotr(uint16_t{0x1234}, -16), uint16_t{0x1234});
+  EXPECT_EQ(rotr(uint32_t{0x12345678UL}, -32), uint32_t{0x12345678UL});
+  EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, -64),
+            uint64_t{0x12345678ABCDEF01ULL});
+
+  EXPECT_EQ(rotr(uint8_t{0x12}, 4), uint8_t{0x21});
+  EXPECT_EQ(rotr(uint16_t{0x1234}, 4), uint16_t{0x4123});
+  EXPECT_EQ(rotr(uint32_t{0x12345678UL}, 4), uint32_t{0x81234567UL});
+  EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, 4),
+            uint64_t{0x112345678ABCDEF0ULL});
+
+  EXPECT_EQ(rotr(uint8_t{0x12}, -4), uint8_t{0x21});
+  EXPECT_EQ(rotr(uint16_t{0x1234}, -4), uint16_t{0x2341});
+  EXPECT_EQ(rotr(uint32_t{0x12345678UL}, -4), uint32_t{0x23456781UL});
+  EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, -4),
+            uint64_t{0x2345678ABCDEF011ULL});
+}
+
+TEST(Rotate, Symmetry) {
+  // rotr(x, s) is equivalent to rotl(x, -s)
+  absl::BitGen rng;
+  constexpr int kTrials = 100;
+
+  for (int i = 0; i < kTrials; ++i) {
+    uint8_t value = absl::Uniform(rng, std::numeric_limits<uint8_t>::min(),
+                                  std::numeric_limits<uint8_t>::max());
+    int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint8_t>::digits,
+                              2 * std::numeric_limits<uint8_t>::digits);
+
+    EXPECT_EQ(rotl(value, shift), rotr(value, -shift));
+  }
+
+  for (int i = 0; i < kTrials; ++i) {
+    uint16_t value = absl::Uniform(rng, std::numeric_limits<uint16_t>::min(),
+                                   std::numeric_limits<uint16_t>::max());
+    int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint16_t>::digits,
+                              2 * std::numeric_limits<uint16_t>::digits);
+
+    EXPECT_EQ(rotl(value, shift), rotr(value, -shift));
+  }
+
+  for (int i = 0; i < kTrials; ++i) {
+    uint32_t value = absl::Uniform(rng, std::numeric_limits<uint32_t>::min(),
+                                   std::numeric_limits<uint32_t>::max());
+    int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint32_t>::digits,
+                              2 * std::numeric_limits<uint32_t>::digits);
+
+    EXPECT_EQ(rotl(value, shift), rotr(value, -shift));
+  }
+
+  for (int i = 0; i < kTrials; ++i) {
+    uint64_t value = absl::Uniform(rng, std::numeric_limits<uint64_t>::min(),
+                                   std::numeric_limits<uint64_t>::max());
+    int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint64_t>::digits,
+                              2 * std::numeric_limits<uint64_t>::digits);
+
+    EXPECT_EQ(rotl(value, shift), rotr(value, -shift));
+  }
+}
+
+TEST(Counting, LeadingZeroes) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ
+  static_assert(countl_zero(uint8_t{}) == 8, "");
+  static_assert(countl_zero(static_cast<uint8_t>(-1)) == 0, "");
+  static_assert(countl_zero(uint16_t{}) == 16, "");
+  static_assert(countl_zero(static_cast<uint16_t>(-1)) == 0, "");
+  static_assert(countl_zero(uint32_t{}) == 32, "");
+  static_assert(countl_zero(~uint32_t{}) == 0, "");
+  static_assert(countl_zero(uint64_t{}) == 64, "");
+  static_assert(countl_zero(~uint64_t{}) == 0, "");
+#endif
+
+  EXPECT_EQ(countl_zero(uint8_t{}), 8);
+  EXPECT_EQ(countl_zero(static_cast<uint8_t>(-1)), 0);
+  EXPECT_EQ(countl_zero(uint16_t{}), 16);
+  EXPECT_EQ(countl_zero(static_cast<uint16_t>(-1)), 0);
+  EXPECT_EQ(countl_zero(uint32_t{}), 32);
+  EXPECT_EQ(countl_zero(~uint32_t{}), 0);
+  EXPECT_EQ(countl_zero(uint64_t{}), 64);
+  EXPECT_EQ(countl_zero(~uint64_t{}), 0);
+
+  for (int i = 0; i < 8; i++) {
+    EXPECT_EQ(countl_zero(static_cast<uint8_t>(1u << i)), 7 - i);
+  }
+
+  for (int i = 0; i < 16; i++) {
+    EXPECT_EQ(countl_zero(static_cast<uint16_t>(1u << i)), 15 - i);
+  }
+
+  for (int i = 0; i < 32; i++) {
+    EXPECT_EQ(countl_zero(uint32_t{1} << i), 31 - i);
+  }
+
+  for (int i = 0; i < 64; i++) {
+    EXPECT_EQ(countl_zero(uint64_t{1} << i), 63 - i);
+  }
+}
+
+TEST(Counting, LeadingOnes) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ
+  static_assert(countl_one(uint8_t{}) == 0, "");
+  static_assert(countl_one(static_cast<uint8_t>(-1)) == 8, "");
+  static_assert(countl_one(uint16_t{}) == 0, "");
+  static_assert(countl_one(static_cast<uint16_t>(-1)) == 16, "");
+  static_assert(countl_one(uint32_t{}) == 0, "");
+  static_assert(countl_one(~uint32_t{}) == 32, "");
+  static_assert(countl_one(uint64_t{}) == 0, "");
+  static_assert(countl_one(~uint64_t{}) == 64, "");
+#endif
+
+  EXPECT_EQ(countl_one(uint8_t{}), 0);
+  EXPECT_EQ(countl_one(static_cast<uint8_t>(-1)), 8);
+  EXPECT_EQ(countl_one(uint16_t{}), 0);
+  EXPECT_EQ(countl_one(static_cast<uint16_t>(-1)), 16);
+  EXPECT_EQ(countl_one(uint32_t{}), 0);
+  EXPECT_EQ(countl_one(~uint32_t{}), 32);
+  EXPECT_EQ(countl_one(uint64_t{}), 0);
+  EXPECT_EQ(countl_one(~uint64_t{}), 64);
+}
+
+TEST(Counting, TrailingZeroes) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CTZ
+  static_assert(countr_zero(uint8_t{}) == 8, "");
+  static_assert(countr_zero(static_cast<uint8_t>(-1)) == 0, "");
+  static_assert(countr_zero(uint16_t{}) == 16, "");
+  static_assert(countr_zero(static_cast<uint16_t>(-1)) == 0, "");
+  static_assert(countr_zero(uint32_t{}) == 32, "");
+  static_assert(countr_zero(~uint32_t{}) == 0, "");
+  static_assert(countr_zero(uint64_t{}) == 64, "");
+  static_assert(countr_zero(~uint64_t{}) == 0, "");
+#endif
+
+  EXPECT_EQ(countr_zero(uint8_t{}), 8);
+  EXPECT_EQ(countr_zero(static_cast<uint8_t>(-1)), 0);
+  EXPECT_EQ(countr_zero(uint16_t{}), 16);
+  EXPECT_EQ(countr_zero(static_cast<uint16_t>(-1)), 0);
+  EXPECT_EQ(countr_zero(uint32_t{}), 32);
+  EXPECT_EQ(countr_zero(~uint32_t{}), 0);
+  EXPECT_EQ(countr_zero(uint64_t{}), 64);
+  EXPECT_EQ(countr_zero(~uint64_t{}), 0);
+}
+
+TEST(Counting, TrailingOnes) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CTZ
+  static_assert(countr_one(uint8_t{}) == 0, "");
+  static_assert(countr_one(static_cast<uint8_t>(-1)) == 8, "");
+  static_assert(countr_one(uint16_t{}) == 0, "");
+  static_assert(countr_one(static_cast<uint16_t>(-1)) == 16, "");
+  static_assert(countr_one(uint32_t{}) == 0, "");
+  static_assert(countr_one(~uint32_t{}) == 32, "");
+  static_assert(countr_one(uint64_t{}) == 0, "");
+  static_assert(countr_one(~uint64_t{}) == 64, "");
+#endif
+
+  EXPECT_EQ(countr_one(uint8_t{}), 0);
+  EXPECT_EQ(countr_one(static_cast<uint8_t>(-1)), 8);
+  EXPECT_EQ(countr_one(uint16_t{}), 0);
+  EXPECT_EQ(countr_one(static_cast<uint16_t>(-1)), 16);
+  EXPECT_EQ(countr_one(uint32_t{}), 0);
+  EXPECT_EQ(countr_one(~uint32_t{}), 32);
+  EXPECT_EQ(countr_one(uint64_t{}), 0);
+  EXPECT_EQ(countr_one(~uint64_t{}), 64);
+}
+
+TEST(Counting, Popcount) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT
+  static_assert(popcount(uint8_t{}) == 0, "");
+  static_assert(popcount(uint8_t{1}) == 1, "");
+  static_assert(popcount(static_cast<uint8_t>(-1)) == 8, "");
+  static_assert(popcount(uint16_t{}) == 0, "");
+  static_assert(popcount(uint16_t{1}) == 1, "");
+  static_assert(popcount(static_cast<uint16_t>(-1)) == 16, "");
+  static_assert(popcount(uint32_t{}) == 0, "");
+  static_assert(popcount(uint32_t{1}) == 1, "");
+  static_assert(popcount(~uint32_t{}) == 32, "");
+  static_assert(popcount(uint64_t{}) == 0, "");
+  static_assert(popcount(uint64_t{1}) == 1, "");
+  static_assert(popcount(~uint64_t{}) == 64, "");
+#endif  // ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT
+
+  EXPECT_EQ(popcount(uint8_t{}), 0);
+  EXPECT_EQ(popcount(uint8_t{1}), 1);
+  EXPECT_EQ(popcount(static_cast<uint8_t>(-1)), 8);
+  EXPECT_EQ(popcount(uint16_t{}), 0);
+  EXPECT_EQ(popcount(uint16_t{1}), 1);
+  EXPECT_EQ(popcount(static_cast<uint16_t>(-1)), 16);
+  EXPECT_EQ(popcount(uint32_t{}), 0);
+  EXPECT_EQ(popcount(uint32_t{1}), 1);
+  EXPECT_EQ(popcount(~uint32_t{}), 32);
+  EXPECT_EQ(popcount(uint64_t{}), 0);
+  EXPECT_EQ(popcount(uint64_t{1}), 1);
+  EXPECT_EQ(popcount(~uint64_t{}), 64);
+
+  for (int i = 0; i < 8; i++) {
+    EXPECT_EQ(popcount(static_cast<uint8_t>(uint8_t{1} << i)), 1);
+    EXPECT_EQ(popcount(static_cast<uint8_t>(static_cast<uint8_t>(-1) ^
+                                            (uint8_t{1} << i))),
+              7);
+  }
+
+  for (int i = 0; i < 16; i++) {
+    EXPECT_EQ(popcount(static_cast<uint16_t>(uint16_t{1} << i)), 1);
+    EXPECT_EQ(popcount(static_cast<uint16_t>(static_cast<uint16_t>(-1) ^
+                                             (uint16_t{1} << i))),
+              15);
+  }
+
+  for (int i = 0; i < 32; i++) {
+    EXPECT_EQ(popcount(uint32_t{1} << i), 1);
+    EXPECT_EQ(popcount(static_cast<uint32_t>(-1) ^ (uint32_t{1} << i)), 31);
+  }
+
+  for (int i = 0; i < 64; i++) {
+    EXPECT_EQ(popcount(uint64_t{1} << i), 1);
+    EXPECT_EQ(popcount(static_cast<uint64_t>(-1) ^ (uint64_t{1} << i)), 63);
+  }
+}
+
+template <typename T>
+struct PopcountInput {
+  T value = 0;
+  int expected = 0;
+};
+
+template <typename T>
+PopcountInput<T> GeneratePopcountInput(absl::BitGen& gen) {
+  PopcountInput<T> ret;
+  for (int i = 0; i < std::numeric_limits<T>::digits; i++) {
+    bool coin = absl::Bernoulli(gen, 0.2);
+    if (coin) {
+      ret.value |= T{1} << i;
+      ret.expected++;
+    }
+  }
+  return ret;
+}
+
+TEST(Counting, PopcountFuzz) {
+  absl::BitGen rng;
+  constexpr int kTrials = 100;
+
+  for (int i = 0; i < kTrials; ++i) {
+    auto input = GeneratePopcountInput<uint8_t>(rng);
+    EXPECT_EQ(popcount(input.value), input.expected);
+  }
+
+  for (int i = 0; i < kTrials; ++i) {
+    auto input = GeneratePopcountInput<uint16_t>(rng);
+    EXPECT_EQ(popcount(input.value), input.expected);
+  }
+
+  for (int i = 0; i < kTrials; ++i) {
+    auto input = GeneratePopcountInput<uint32_t>(rng);
+    EXPECT_EQ(popcount(input.value), input.expected);
+  }
+
+  for (int i = 0; i < kTrials; ++i) {
+    auto input = GeneratePopcountInput<uint64_t>(rng);
+    EXPECT_EQ(popcount(input.value), input.expected);
+  }
+}
+
+TEST(IntegralPowersOfTwo, SingleBit) {
+  EXPECT_FALSE(has_single_bit(uint8_t{}));
+  EXPECT_FALSE(has_single_bit(static_cast<uint8_t>(-1)));
+  EXPECT_FALSE(has_single_bit(uint16_t{}));
+  EXPECT_FALSE(has_single_bit(static_cast<uint16_t>(-1)));
+  EXPECT_FALSE(has_single_bit(uint32_t{}));
+  EXPECT_FALSE(has_single_bit(~uint32_t{}));
+  EXPECT_FALSE(has_single_bit(uint64_t{}));
+  EXPECT_FALSE(has_single_bit(~uint64_t{}));
+
+  static_assert(!has_single_bit(0u), "");
+  static_assert(has_single_bit(1u), "");
+  static_assert(has_single_bit(2u), "");
+  static_assert(!has_single_bit(3u), "");
+  static_assert(has_single_bit(4u), "");
+  static_assert(!has_single_bit(1337u), "");
+  static_assert(has_single_bit(65536u), "");
+  static_assert(has_single_bit(uint32_t{1} << 30), "");
+  static_assert(has_single_bit(uint64_t{1} << 42), "");
+
+  EXPECT_FALSE(has_single_bit(0u));
+  EXPECT_TRUE(has_single_bit(1u));
+  EXPECT_TRUE(has_single_bit(2u));
+  EXPECT_FALSE(has_single_bit(3u));
+  EXPECT_TRUE(has_single_bit(4u));
+  EXPECT_FALSE(has_single_bit(1337u));
+  EXPECT_TRUE(has_single_bit(65536u));
+  EXPECT_TRUE(has_single_bit(uint32_t{1} << 30));
+  EXPECT_TRUE(has_single_bit(uint64_t{1} << 42));
+
+  EXPECT_TRUE(has_single_bit(
+      static_cast<uint8_t>(std::numeric_limits<uint8_t>::max() / 2 + 1)));
+  EXPECT_TRUE(has_single_bit(
+      static_cast<uint16_t>(std::numeric_limits<uint16_t>::max() / 2 + 1)));
+  EXPECT_TRUE(has_single_bit(
+      static_cast<uint32_t>(std::numeric_limits<uint32_t>::max() / 2 + 1)));
+  EXPECT_TRUE(has_single_bit(
+      static_cast<uint64_t>(std::numeric_limits<uint64_t>::max() / 2 + 1)));
+}
+
+template <typename T, T arg, T = bit_ceil(arg)>
+bool IsBitCeilConstantExpression(int) {
+  return true;
+}
+template <typename T, T arg>
+bool IsBitCeilConstantExpression(char) {
+  return false;
+}
+
+TEST(IntegralPowersOfTwo, Ceiling) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ
+  static_assert(bit_ceil(0u) == 1, "");
+  static_assert(bit_ceil(1u) == 1, "");
+  static_assert(bit_ceil(2u) == 2, "");
+  static_assert(bit_ceil(3u) == 4, "");
+  static_assert(bit_ceil(4u) == 4, "");
+  static_assert(bit_ceil(1337u) == 2048, "");
+  static_assert(bit_ceil(65536u) == 65536, "");
+  static_assert(bit_ceil(65536u - 1337u) == 65536, "");
+  static_assert(bit_ceil(uint32_t{0x80000000}) == uint32_t{0x80000000}, "");
+  static_assert(bit_ceil(uint64_t{0x40000000000}) == uint64_t{0x40000000000},
+                "");
+  static_assert(
+      bit_ceil(uint64_t{0x8000000000000000}) == uint64_t{0x8000000000000000},
+      "");
+
+  EXPECT_TRUE((IsBitCeilConstantExpression<uint8_t, uint8_t{0x0}>(0)));
+  EXPECT_TRUE((IsBitCeilConstantExpression<uint8_t, uint8_t{0x80}>(0)));
+  EXPECT_FALSE((IsBitCeilConstantExpression<uint8_t, uint8_t{0x81}>(0)));
+  EXPECT_FALSE((IsBitCeilConstantExpression<uint8_t, uint8_t{0xff}>(0)));
+
+  EXPECT_TRUE((IsBitCeilConstantExpression<uint16_t, uint16_t{0x0}>(0)));
+  EXPECT_TRUE((IsBitCeilConstantExpression<uint16_t, uint16_t{0x8000}>(0)));
+  EXPECT_FALSE((IsBitCeilConstantExpression<uint16_t, uint16_t{0x8001}>(0)));
+  EXPECT_FALSE((IsBitCeilConstantExpression<uint16_t, uint16_t{0xffff}>(0)));
+
+  EXPECT_TRUE((IsBitCeilConstantExpression<uint32_t, uint32_t{0x0}>(0)));
+  EXPECT_TRUE((IsBitCeilConstantExpression<uint32_t, uint32_t{0x80000000}>(0)));
+  EXPECT_FALSE(
+      (IsBitCeilConstantExpression<uint32_t, uint32_t{0x80000001}>(0)));
+  EXPECT_FALSE(
+      (IsBitCeilConstantExpression<uint32_t, uint32_t{0xffffffff}>(0)));
+
+  EXPECT_TRUE((IsBitCeilConstantExpression<uint64_t, uint64_t{0x0}>(0)));
+  EXPECT_TRUE(
+      (IsBitCeilConstantExpression<uint64_t, uint64_t{0x8000000000000000}>(0)));
+  EXPECT_FALSE(
+      (IsBitCeilConstantExpression<uint64_t, uint64_t{0x8000000000000001}>(0)));
+  EXPECT_FALSE(
+      (IsBitCeilConstantExpression<uint64_t, uint64_t{0xffffffffffffffff}>(0)));
+#endif
+
+  EXPECT_EQ(bit_ceil(0u), 1);
+  EXPECT_EQ(bit_ceil(1u), 1);
+  EXPECT_EQ(bit_ceil(2u), 2);
+  EXPECT_EQ(bit_ceil(3u), 4);
+  EXPECT_EQ(bit_ceil(4u), 4);
+  EXPECT_EQ(bit_ceil(1337u), 2048);
+  EXPECT_EQ(bit_ceil(65536u), 65536);
+  EXPECT_EQ(bit_ceil(65536u - 1337u), 65536);
+  EXPECT_EQ(bit_ceil(uint64_t{0x40000000000}), uint64_t{0x40000000000});
+}
+
+TEST(IntegralPowersOfTwo, Floor) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ
+  static_assert(bit_floor(0u) == 0, "");
+  static_assert(bit_floor(1u) == 1, "");
+  static_assert(bit_floor(2u) == 2, "");
+  static_assert(bit_floor(3u) == 2, "");
+  static_assert(bit_floor(4u) == 4, "");
+  static_assert(bit_floor(1337u) == 1024, "");
+  static_assert(bit_floor(65536u) == 65536, "");
+  static_assert(bit_floor(65536u - 1337u) == 32768, "");
+  static_assert(bit_floor(uint64_t{0x40000000000}) == uint64_t{0x40000000000},
+                "");
+#endif
+
+  EXPECT_EQ(bit_floor(0u), 0);
+  EXPECT_EQ(bit_floor(1u), 1);
+  EXPECT_EQ(bit_floor(2u), 2);
+  EXPECT_EQ(bit_floor(3u), 2);
+  EXPECT_EQ(bit_floor(4u), 4);
+  EXPECT_EQ(bit_floor(1337u), 1024);
+  EXPECT_EQ(bit_floor(65536u), 65536);
+  EXPECT_EQ(bit_floor(65536u - 1337u), 32768);
+  EXPECT_EQ(bit_floor(uint64_t{0x40000000000}), uint64_t{0x40000000000});
+
+  for (int i = 0; i < 8; i++) {
+    uint8_t input = uint8_t{1} << i;
+    EXPECT_EQ(bit_floor(input), input);
+    if (i > 0) {
+      EXPECT_EQ(bit_floor(static_cast<uint8_t>(input + 1)), input);
+    }
+  }
+
+  for (int i = 0; i < 16; i++) {
+    uint16_t input = uint16_t{1} << i;
+    EXPECT_EQ(bit_floor(input), input);
+    if (i > 0) {
+      EXPECT_EQ(bit_floor(static_cast<uint16_t>(input + 1)), input);
+    }
+  }
+
+  for (int i = 0; i < 32; i++) {
+    uint32_t input = uint32_t{1} << i;
+    EXPECT_EQ(bit_floor(input), input);
+    if (i > 0) {
+      EXPECT_EQ(bit_floor(input + 1), input);
+    }
+  }
+
+  for (int i = 0; i < 64; i++) {
+    uint64_t input = uint64_t{1} << i;
+    EXPECT_EQ(bit_floor(input), input);
+    if (i > 0) {
+      EXPECT_EQ(bit_floor(input + 1), input);
+    }
+  }
+}
+
+TEST(IntegralPowersOfTwo, Width) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ
+  static_assert(bit_width(uint8_t{}) == 0, "");
+  static_assert(bit_width(uint8_t{1}) == 1, "");
+  static_assert(bit_width(uint8_t{3}) == 2, "");
+  static_assert(bit_width(static_cast<uint8_t>(-1)) == 8, "");
+  static_assert(bit_width(uint16_t{}) == 0, "");
+  static_assert(bit_width(uint16_t{1}) == 1, "");
+  static_assert(bit_width(uint16_t{3}) == 2, "");
+  static_assert(bit_width(static_cast<uint16_t>(-1)) == 16, "");
+  static_assert(bit_width(uint32_t{}) == 0, "");
+  static_assert(bit_width(uint32_t{1}) == 1, "");
+  static_assert(bit_width(uint32_t{3}) == 2, "");
+  static_assert(bit_width(~uint32_t{}) == 32, "");
+  static_assert(bit_width(uint64_t{}) == 0, "");
+  static_assert(bit_width(uint64_t{1}) == 1, "");
+  static_assert(bit_width(uint64_t{3}) == 2, "");
+  static_assert(bit_width(~uint64_t{}) == 64, "");
+#endif
+
+  EXPECT_EQ(bit_width(uint8_t{}), 0);
+  EXPECT_EQ(bit_width(uint8_t{1}), 1);
+  EXPECT_EQ(bit_width(uint8_t{3}), 2);
+  EXPECT_EQ(bit_width(static_cast<uint8_t>(-1)), 8);
+  EXPECT_EQ(bit_width(uint16_t{}), 0);
+  EXPECT_EQ(bit_width(uint16_t{1}), 1);
+  EXPECT_EQ(bit_width(uint16_t{3}), 2);
+  EXPECT_EQ(bit_width(static_cast<uint16_t>(-1)), 16);
+  EXPECT_EQ(bit_width(uint32_t{}), 0);
+  EXPECT_EQ(bit_width(uint32_t{1}), 1);
+  EXPECT_EQ(bit_width(uint32_t{3}), 2);
+  EXPECT_EQ(bit_width(~uint32_t{}), 32);
+  EXPECT_EQ(bit_width(uint64_t{}), 0);
+  EXPECT_EQ(bit_width(uint64_t{1}), 1);
+  EXPECT_EQ(bit_width(uint64_t{3}), 2);
+  EXPECT_EQ(bit_width(~uint64_t{}), 64);
+
+  for (int i = 0; i < 8; i++) {
+    EXPECT_EQ(bit_width(static_cast<uint8_t>(uint8_t{1} << i)), i + 1);
+  }
+
+  for (int i = 0; i < 16; i++) {
+    EXPECT_EQ(bit_width(static_cast<uint16_t>(uint16_t{1} << i)), i + 1);
+  }
+
+  for (int i = 0; i < 32; i++) {
+    EXPECT_EQ(bit_width(uint32_t{1} << i), i + 1);
+  }
+
+  for (int i = 0; i < 64; i++) {
+    EXPECT_EQ(bit_width(uint64_t{1} << i), i + 1);
+  }
+}
+
+}  // namespace
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc
index 93b62c5..5160df7 100644
--- a/absl/numeric/int128.cc
+++ b/absl/numeric/int128.cc
@@ -15,6 +15,7 @@
 #include "absl/numeric/int128.h"
 
 #include <stddef.h>
+
 #include <cassert>
 #include <iomanip>
 #include <ostream>  // NOLINT(readability/streams)
@@ -22,52 +23,38 @@
 #include <string>
 #include <type_traits>
 
-namespace absl {
+#include "absl/base/optimization.h"
+#include "absl/numeric/bits.h"
 
-const uint128 kuint128max = MakeUint128(std::numeric_limits<uint64_t>::max(),
-                                        std::numeric_limits<uint64_t>::max());
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+ABSL_DLL const uint128 kuint128max = MakeUint128(
+    std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max());
 
 namespace {
 
 // Returns the 0-based position of the last set bit (i.e., most significant bit)
-// in the given uint64_t. The argument may not be 0.
+// in the given uint128. The argument is not 0.
 //
 // For example:
 //   Given: 5 (decimal) == 101 (binary)
 //   Returns: 2
-#define STEP(T, n, pos, sh)                   \
-  do {                                        \
-    if ((n) >= (static_cast<T>(1) << (sh))) { \
-      (n) = (n) >> (sh);                      \
-      (pos) |= (sh);                          \
-    }                                         \
-  } while (0)
-static inline int Fls64(uint64_t n) {
-  assert(n != 0);
-  int pos = 0;
-  STEP(uint64_t, n, pos, 0x20);
-  uint32_t n32 = static_cast<uint32_t>(n);
-  STEP(uint32_t, n32, pos, 0x10);
-  STEP(uint32_t, n32, pos, 0x08);
-  STEP(uint32_t, n32, pos, 0x04);
-  return pos + ((uint64_t{0x3333333322221100} >> (n32 << 2)) & 0x3);
-}
-#undef STEP
-
-// Like Fls64() above, but returns the 0-based position of the last set bit
-// (i.e., most significant bit) in the given uint128. The argument may not be 0.
-static inline int Fls128(uint128 n) {
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE int Fls128(uint128 n) {
   if (uint64_t hi = Uint128High64(n)) {
-    return Fls64(hi) + 64;
+    ABSL_INTERNAL_ASSUME(hi != 0);
+    return 127 - countl_zero(hi);
   }
-  return Fls64(Uint128Low64(n));
+  const uint64_t low = Uint128Low64(n);
+  ABSL_INTERNAL_ASSUME(low != 0);
+  return 63 - countl_zero(low);
 }
 
 // Long division/modulo for uint128 implemented using the shift-subtract
 // division algorithm adapted from:
 // https://stackoverflow.com/questions/5386377/division-without-using
-void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,
-                uint128* remainder_ret) {
+inline void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,
+                       uint128* remainder_ret) {
   assert(divisor != 0);
 
   if (divisor > dividend) {
@@ -244,6 +231,112 @@
   return os << rep;
 }
 
+namespace {
+
+uint128 UnsignedAbsoluteValue(int128 v) {
+  // Cast to uint128 before possibly negating because -Int128Min() is undefined.
+  return Int128High64(v) < 0 ? -uint128(v) : uint128(v);
+}
+
+}  // namespace
+
+#if !defined(ABSL_HAVE_INTRINSIC_INT128)
+namespace {
+
+template <typename T>
+int128 MakeInt128FromFloat(T v) {
+  // Conversion when v is NaN or cannot fit into int128 would be undefined
+  // behavior if using an intrinsic 128-bit integer.
+  assert(std::isfinite(v) && (std::numeric_limits<T>::max_exponent <= 127 ||
+                              (v >= -std::ldexp(static_cast<T>(1), 127) &&
+                               v < std::ldexp(static_cast<T>(1), 127))));
+
+  // We must convert the absolute value and then negate as needed, because
+  // floating point types are typically sign-magnitude. Otherwise, the
+  // difference between the high and low 64 bits when interpreted as two's
+  // complement overwhelms the precision of the mantissa.
+  uint128 result = v < 0 ? -MakeUint128FromFloat(-v) : MakeUint128FromFloat(v);
+  return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)),
+                    Uint128Low64(result));
+}
+
+}  // namespace
+
+int128::int128(float v) : int128(MakeInt128FromFloat(v)) {}
+int128::int128(double v) : int128(MakeInt128FromFloat(v)) {}
+int128::int128(long double v) : int128(MakeInt128FromFloat(v)) {}
+
+int128 operator/(int128 lhs, int128 rhs) {
+  assert(lhs != Int128Min() || rhs != -1);  // UB on two's complement.
+
+  uint128 quotient = 0;
+  uint128 remainder = 0;
+  DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs),
+             &quotient, &remainder);
+  if ((Int128High64(lhs) < 0) != (Int128High64(rhs) < 0)) quotient = -quotient;
+  return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(quotient)),
+                    Uint128Low64(quotient));
+}
+
+int128 operator%(int128 lhs, int128 rhs) {
+  assert(lhs != Int128Min() || rhs != -1);  // UB on two's complement.
+
+  uint128 quotient = 0;
+  uint128 remainder = 0;
+  DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs),
+             &quotient, &remainder);
+  if (Int128High64(lhs) < 0) remainder = -remainder;
+  return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(remainder)),
+                    Uint128Low64(remainder));
+}
+#endif  // ABSL_HAVE_INTRINSIC_INT128
+
+std::ostream& operator<<(std::ostream& os, int128 v) {
+  std::ios_base::fmtflags flags = os.flags();
+  std::string rep;
+
+  // Add the sign if needed.
+  bool print_as_decimal =
+      (flags & std::ios::basefield) == std::ios::dec ||
+      (flags & std::ios::basefield) == std::ios_base::fmtflags();
+  if (print_as_decimal) {
+    if (Int128High64(v) < 0) {
+      rep = "-";
+    } else if (flags & std::ios::showpos) {
+      rep = "+";
+    }
+  }
+
+  rep.append(Uint128ToFormattedString(
+      print_as_decimal ? UnsignedAbsoluteValue(v) : uint128(v), os.flags()));
+
+  // Add the requisite padding.
+  std::streamsize width = os.width(0);
+  if (static_cast<size_t>(width) > rep.size()) {
+    switch (flags & std::ios::adjustfield) {
+      case std::ios::left:
+        rep.append(width - rep.size(), os.fill());
+        break;
+      case std::ios::internal:
+        if (print_as_decimal && (rep[0] == '+' || rep[0] == '-')) {
+          rep.insert(1, width - rep.size(), os.fill());
+        } else if ((flags & std::ios::basefield) == std::ios::hex &&
+                   (flags & std::ios::showbase) && v != 0) {
+          rep.insert(2, width - rep.size(), os.fill());
+        } else {
+          rep.insert(0, width - rep.size(), os.fill());
+        }
+        break;
+      default:  // std::ios::right
+        rep.insert(0, width - rep.size(), os.fill());
+        break;
+    }
+  }
+
+  return os << rep;
+}
+
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 namespace std {
@@ -270,4 +363,28 @@
 constexpr int numeric_limits<absl::uint128>::max_exponent10;
 constexpr bool numeric_limits<absl::uint128>::traps;
 constexpr bool numeric_limits<absl::uint128>::tinyness_before;
+
+constexpr bool numeric_limits<absl::int128>::is_specialized;
+constexpr bool numeric_limits<absl::int128>::is_signed;
+constexpr bool numeric_limits<absl::int128>::is_integer;
+constexpr bool numeric_limits<absl::int128>::is_exact;
+constexpr bool numeric_limits<absl::int128>::has_infinity;
+constexpr bool numeric_limits<absl::int128>::has_quiet_NaN;
+constexpr bool numeric_limits<absl::int128>::has_signaling_NaN;
+constexpr float_denorm_style numeric_limits<absl::int128>::has_denorm;
+constexpr bool numeric_limits<absl::int128>::has_denorm_loss;
+constexpr float_round_style numeric_limits<absl::int128>::round_style;
+constexpr bool numeric_limits<absl::int128>::is_iec559;
+constexpr bool numeric_limits<absl::int128>::is_bounded;
+constexpr bool numeric_limits<absl::int128>::is_modulo;
+constexpr int numeric_limits<absl::int128>::digits;
+constexpr int numeric_limits<absl::int128>::digits10;
+constexpr int numeric_limits<absl::int128>::max_digits10;
+constexpr int numeric_limits<absl::int128>::radix;
+constexpr int numeric_limits<absl::int128>::min_exponent;
+constexpr int numeric_limits<absl::int128>::min_exponent10;
+constexpr int numeric_limits<absl::int128>::max_exponent;
+constexpr int numeric_limits<absl::int128>::max_exponent10;
+constexpr bool numeric_limits<absl::int128>::traps;
+constexpr bool numeric_limits<absl::int128>::tinyness_before;
 }  // namespace std
diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h
index 10be8ec..0dd814a 100644
--- a/absl/numeric/int128.h
+++ b/absl/numeric/int128.h
@@ -17,10 +17,7 @@
 // File: int128.h
 // -----------------------------------------------------------------------------
 //
-// This header file defines 128-bit integer types.
-//
-// Currently, this file defines `uint128`, an unsigned 128-bit integer;
-// a signed 128-bit integer is forthcoming.
+// This header file defines 128-bit integer types, `uint128` and `int128`.
 
 #ifndef ABSL_NUMERIC_INT128_H_
 #define ABSL_NUMERIC_INT128_H_
@@ -52,6 +49,9 @@
 #endif  // defined(_MSC_VER)
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+class int128;
 
 // uint128
 //
@@ -116,6 +116,7 @@
   constexpr uint128(__int128 v);           // NOLINT(runtime/explicit)
   constexpr uint128(unsigned __int128 v);  // NOLINT(runtime/explicit)
 #endif  // ABSL_HAVE_INTRINSIC_INT128
+  constexpr uint128(int128 v);  // NOLINT(runtime/explicit)
   explicit uint128(float v);
   explicit uint128(double v);
   explicit uint128(long double v);
@@ -131,6 +132,7 @@
   uint128& operator=(__int128 v);
   uint128& operator=(unsigned __int128 v);
 #endif  // ABSL_HAVE_INTRINSIC_INT128
+  uint128& operator=(int128 v);
 
   // Conversion operators to other arithmetic types
   constexpr explicit operator bool() const;
@@ -232,7 +234,7 @@
 // Prefer to use the constexpr `Uint128Max()`.
 //
 // TODO(absl-team) deprecate kuint128max once migration tool is released.
-extern const uint128 kuint128max;
+ABSL_DLL extern const uint128 kuint128max;
 
 // allow uint128 to be logged
 std::ostream& operator<<(std::ostream& os, uint128 v);
@@ -244,6 +246,7 @@
                  (std::numeric_limits<uint64_t>::max)());
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 // Specialized numeric_limits for uint128.
@@ -291,12 +294,246 @@
 };
 }  // namespace std
 
-// TODO(absl-team): Implement signed 128-bit type
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// int128
+//
+// A signed 128-bit integer type. The API is meant to mimic an intrinsic
+// integral type as closely as is practical, including exhibiting undefined
+// behavior in analogous cases (e.g. division by zero).
+//
+// An `int128` supports the following:
+//
+//   * Implicit construction from integral types
+//   * Explicit conversion to integral types
+//
+// However, an `int128` differs from intrinsic integral types in the following
+// ways:
+//
+//   * It is not implicitly convertible to other integral types.
+//   * Requires explicit construction from and conversion to floating point
+//     types.
+
+// Additionally, if your compiler supports `__int128`, `int128` is
+// interoperable with that type. (Abseil checks for this compatibility through
+// the `ABSL_HAVE_INTRINSIC_INT128` macro.)
+//
+// The design goal for `int128` is that it will be compatible with a future
+// `int128_t`, if that type becomes a part of the standard.
+//
+// Example:
+//
+//     float y = absl::int128(17);  // Error. int128 cannot be implicitly
+//                                  // converted to float.
+//
+//     absl::int128 v;
+//     int64_t i = v;                        // Error
+//     int64_t i = static_cast<int64_t>(v);  // OK
+//
+class int128 {
+ public:
+  int128() = default;
+
+  // Constructors from arithmetic types
+  constexpr int128(int v);                 // NOLINT(runtime/explicit)
+  constexpr int128(unsigned int v);        // NOLINT(runtime/explicit)
+  constexpr int128(long v);                // NOLINT(runtime/int)
+  constexpr int128(unsigned long v);       // NOLINT(runtime/int)
+  constexpr int128(long long v);           // NOLINT(runtime/int)
+  constexpr int128(unsigned long long v);  // NOLINT(runtime/int)
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+  constexpr int128(__int128 v);  // NOLINT(runtime/explicit)
+  constexpr explicit int128(unsigned __int128 v);
+#endif  // ABSL_HAVE_INTRINSIC_INT128
+  constexpr explicit int128(uint128 v);
+  explicit int128(float v);
+  explicit int128(double v);
+  explicit int128(long double v);
+
+  // Assignment operators from arithmetic types
+  int128& operator=(int v);
+  int128& operator=(unsigned int v);
+  int128& operator=(long v);                // NOLINT(runtime/int)
+  int128& operator=(unsigned long v);       // NOLINT(runtime/int)
+  int128& operator=(long long v);           // NOLINT(runtime/int)
+  int128& operator=(unsigned long long v);  // NOLINT(runtime/int)
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+  int128& operator=(__int128 v);
+#endif  // ABSL_HAVE_INTRINSIC_INT128
+
+  // Conversion operators to other arithmetic types
+  constexpr explicit operator bool() const;
+  constexpr explicit operator char() const;
+  constexpr explicit operator signed char() const;
+  constexpr explicit operator unsigned char() const;
+  constexpr explicit operator char16_t() const;
+  constexpr explicit operator char32_t() const;
+  constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;
+  constexpr explicit operator short() const;  // NOLINT(runtime/int)
+  // NOLINTNEXTLINE(runtime/int)
+  constexpr explicit operator unsigned short() const;
+  constexpr explicit operator int() const;
+  constexpr explicit operator unsigned int() const;
+  constexpr explicit operator long() const;  // NOLINT(runtime/int)
+  // NOLINTNEXTLINE(runtime/int)
+  constexpr explicit operator unsigned long() const;
+  // NOLINTNEXTLINE(runtime/int)
+  constexpr explicit operator long long() const;
+  // NOLINTNEXTLINE(runtime/int)
+  constexpr explicit operator unsigned long long() const;
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+  constexpr explicit operator __int128() const;
+  constexpr explicit operator unsigned __int128() const;
+#endif  // ABSL_HAVE_INTRINSIC_INT128
+  explicit operator float() const;
+  explicit operator double() const;
+  explicit operator long double() const;
+
+  // Trivial copy constructor, assignment operator and destructor.
+
+  // Arithmetic operators
+  int128& operator+=(int128 other);
+  int128& operator-=(int128 other);
+  int128& operator*=(int128 other);
+  int128& operator/=(int128 other);
+  int128& operator%=(int128 other);
+  int128 operator++(int);  // postfix increment: i++
+  int128 operator--(int);  // postfix decrement: i--
+  int128& operator++();    // prefix increment:  ++i
+  int128& operator--();    // prefix decrement:  --i
+  int128& operator&=(int128 other);
+  int128& operator|=(int128 other);
+  int128& operator^=(int128 other);
+  int128& operator<<=(int amount);
+  int128& operator>>=(int amount);
+
+  // Int128Low64()
+  //
+  // Returns the lower 64-bit value of a `int128` value.
+  friend constexpr uint64_t Int128Low64(int128 v);
+
+  // Int128High64()
+  //
+  // Returns the higher 64-bit value of a `int128` value.
+  friend constexpr int64_t Int128High64(int128 v);
+
+  // MakeInt128()
+  //
+  // Constructs a `int128` numeric value from two 64-bit integers. Note that
+  // signedness is conveyed in the upper `high` value.
+  //
+  //   (absl::int128(1) << 64) * high + low
+  //
+  // Note that this factory function is the only way to construct a `int128`
+  // from integer values greater than 2^64 or less than -2^64.
+  //
+  // Example:
+  //
+  //   absl::int128 big = absl::MakeInt128(1, 0);
+  //   absl::int128 big_n = absl::MakeInt128(-1, 0);
+  friend constexpr int128 MakeInt128(int64_t high, uint64_t low);
+
+  // Int128Max()
+  //
+  // Returns the maximum value for a 128-bit signed integer.
+  friend constexpr int128 Int128Max();
+
+  // Int128Min()
+  //
+  // Returns the minimum value for a 128-bit signed integer.
+  friend constexpr int128 Int128Min();
+
+  // Support for absl::Hash.
+  template <typename H>
+  friend H AbslHashValue(H h, int128 v) {
+    return H::combine(std::move(h), Int128High64(v), Int128Low64(v));
+  }
+
+ private:
+  constexpr int128(int64_t high, uint64_t low);
+
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+  __int128 v_;
+#else  // ABSL_HAVE_INTRINSIC_INT128
+#if defined(ABSL_IS_LITTLE_ENDIAN)
+  uint64_t lo_;
+  int64_t hi_;
+#elif defined(ABSL_IS_BIG_ENDIAN)
+  int64_t hi_;
+  uint64_t lo_;
+#else  // byte order
+#error "Unsupported byte order: must be little-endian or big-endian."
+#endif  // byte order
+#endif  // ABSL_HAVE_INTRINSIC_INT128
+};
+
+std::ostream& operator<<(std::ostream& os, int128 v);
+
+// TODO(absl-team) add operator>>(std::istream&, int128)
+
+constexpr int128 Int128Max() {
+  return int128((std::numeric_limits<int64_t>::max)(),
+                (std::numeric_limits<uint64_t>::max)());
+}
+
+constexpr int128 Int128Min() {
+  return int128((std::numeric_limits<int64_t>::min)(), 0);
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+// Specialized numeric_limits for int128.
+namespace std {
+template <>
+class numeric_limits<absl::int128> {
+ public:
+  static constexpr bool is_specialized = true;
+  static constexpr bool is_signed = true;
+  static constexpr bool is_integer = true;
+  static constexpr bool is_exact = true;
+  static constexpr bool has_infinity = false;
+  static constexpr bool has_quiet_NaN = false;
+  static constexpr bool has_signaling_NaN = false;
+  static constexpr float_denorm_style has_denorm = denorm_absent;
+  static constexpr bool has_denorm_loss = false;
+  static constexpr float_round_style round_style = round_toward_zero;
+  static constexpr bool is_iec559 = false;
+  static constexpr bool is_bounded = true;
+  static constexpr bool is_modulo = false;
+  static constexpr int digits = 127;
+  static constexpr int digits10 = 38;
+  static constexpr int max_digits10 = 0;
+  static constexpr int radix = 2;
+  static constexpr int min_exponent = 0;
+  static constexpr int min_exponent10 = 0;
+  static constexpr int max_exponent = 0;
+  static constexpr int max_exponent10 = 0;
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+  static constexpr bool traps = numeric_limits<__int128>::traps;
+#else   // ABSL_HAVE_INTRINSIC_INT128
+  static constexpr bool traps = numeric_limits<uint64_t>::traps;
+#endif  // ABSL_HAVE_INTRINSIC_INT128
+  static constexpr bool tinyness_before = false;
+
+  static constexpr absl::int128 (min)() { return absl::Int128Min(); }
+  static constexpr absl::int128 lowest() { return absl::Int128Min(); }
+  static constexpr absl::int128 (max)() { return absl::Int128Max(); }
+  static constexpr absl::int128 epsilon() { return 0; }
+  static constexpr absl::int128 round_error() { return 0; }
+  static constexpr absl::int128 infinity() { return 0; }
+  static constexpr absl::int128 quiet_NaN() { return 0; }
+  static constexpr absl::int128 signaling_NaN() { return 0; }
+  static constexpr absl::int128 denorm_min() { return 0; }
+};
+}  // namespace std
 
 // --------------------------------------------------------------------------
 //                      Implementation details follow
 // --------------------------------------------------------------------------
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 constexpr uint128 MakeUint128(uint64_t high, uint64_t low) {
   return uint128(high, low);
@@ -339,6 +576,10 @@
 }
 #endif  // ABSL_HAVE_INTRINSIC_INT128
 
+inline uint128& uint128::operator=(int128 v) {
+  return *this = uint128(v);
+}
+
 // Arithmetic operators.
 
 uint128 operator<<(uint128 lhs, int amount);
@@ -420,6 +661,9 @@
       hi_{static_cast<uint64_t>(v >> 64)} {}
 #endif  // ABSL_HAVE_INTRINSIC_INT128
 
+constexpr uint128::uint128(int128 v)
+    : lo_{Int128Low64(v)}, hi_{static_cast<uint64_t>(Int128High64(v))} {}
+
 #elif defined(ABSL_IS_BIG_ENDIAN)
 
 constexpr uint128::uint128(uint64_t high, uint64_t low)
@@ -450,6 +694,9 @@
       lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
 #endif  // ABSL_HAVE_INTRINSIC_INT128
 
+constexpr uint128::uint128(int128 v)
+    : hi_{static_cast<uint64_t>(Int128High64(v))}, lo_{Int128Low64(v)} {}
+
 #else  // byte order
 #error "Unsupported byte order: must be little-endian or big-endian."
 #endif  // byte order
@@ -545,28 +792,21 @@
 }
 
 inline bool operator<(uint128 lhs, uint128 rhs) {
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+  return static_cast<unsigned __int128>(lhs) <
+         static_cast<unsigned __int128>(rhs);
+#else
   return (Uint128High64(lhs) == Uint128High64(rhs))
              ? (Uint128Low64(lhs) < Uint128Low64(rhs))
              : (Uint128High64(lhs) < Uint128High64(rhs));
+#endif
 }
 
-inline bool operator>(uint128 lhs, uint128 rhs) {
-  return (Uint128High64(lhs) == Uint128High64(rhs))
-             ? (Uint128Low64(lhs) > Uint128Low64(rhs))
-             : (Uint128High64(lhs) > Uint128High64(rhs));
-}
+inline bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; }
 
-inline bool operator<=(uint128 lhs, uint128 rhs) {
-  return (Uint128High64(lhs) == Uint128High64(rhs))
-             ? (Uint128Low64(lhs) <= Uint128Low64(rhs))
-             : (Uint128High64(lhs) <= Uint128High64(rhs));
-}
+inline bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); }
 
-inline bool operator>=(uint128 lhs, uint128 rhs) {
-  return (Uint128High64(lhs) == Uint128High64(rhs))
-             ? (Uint128Low64(lhs) >= Uint128Low64(rhs))
-             : (Uint128High64(lhs) >= Uint128High64(rhs));
-}
+inline bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); }
 
 // Unary operators.
 
@@ -623,6 +863,9 @@
 // Arithmetic operators.
 
 inline uint128 operator<<(uint128 lhs, int amount) {
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+  return static_cast<unsigned __int128>(lhs) << amount;
+#else
   // uint64_t shifts of >= 64 are undefined, so we will need some
   // special-casing.
   if (amount < 64) {
@@ -634,9 +877,13 @@
     return lhs;
   }
   return MakeUint128(Uint128Low64(lhs) << (amount - 64), 0);
+#endif
 }
 
 inline uint128 operator>>(uint128 lhs, int amount) {
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+  return static_cast<unsigned __int128>(lhs) >> amount;
+#else
   // uint64_t shifts of >= 64 are undefined, so we will need some
   // special-casing.
   if (amount < 64) {
@@ -648,6 +895,7 @@
     return lhs;
   }
   return MakeUint128(0, Uint128High64(lhs) >> (amount - 64));
+#endif
 }
 
 inline uint128 operator+(uint128 lhs, uint128 rhs) {
@@ -719,12 +967,124 @@
   return *this;
 }
 
+constexpr int128 MakeInt128(int64_t high, uint64_t low) {
+  return int128(high, low);
+}
+
+// Assignment from integer types.
+inline int128& int128::operator=(int v) {
+  return *this = int128(v);
+}
+
+inline int128& int128::operator=(unsigned int v) {
+  return *this = int128(v);
+}
+
+inline int128& int128::operator=(long v) {  // NOLINT(runtime/int)
+  return *this = int128(v);
+}
+
+// NOLINTNEXTLINE(runtime/int)
+inline int128& int128::operator=(unsigned long v) {
+  return *this = int128(v);
+}
+
+// NOLINTNEXTLINE(runtime/int)
+inline int128& int128::operator=(long long v) {
+  return *this = int128(v);
+}
+
+// NOLINTNEXTLINE(runtime/int)
+inline int128& int128::operator=(unsigned long long v) {
+  return *this = int128(v);
+}
+
+// Arithmetic operators.
+
+int128 operator+(int128 lhs, int128 rhs);
+int128 operator-(int128 lhs, int128 rhs);
+int128 operator*(int128 lhs, int128 rhs);
+int128 operator/(int128 lhs, int128 rhs);
+int128 operator%(int128 lhs, int128 rhs);
+int128 operator|(int128 lhs, int128 rhs);
+int128 operator&(int128 lhs, int128 rhs);
+int128 operator^(int128 lhs, int128 rhs);
+int128 operator<<(int128 lhs, int amount);
+int128 operator>>(int128 lhs, int amount);
+
+inline int128& int128::operator+=(int128 other) {
+  *this = *this + other;
+  return *this;
+}
+
+inline int128& int128::operator-=(int128 other) {
+  *this = *this - other;
+  return *this;
+}
+
+inline int128& int128::operator*=(int128 other) {
+  *this = *this * other;
+  return *this;
+}
+
+inline int128& int128::operator/=(int128 other) {
+  *this = *this / other;
+  return *this;
+}
+
+inline int128& int128::operator%=(int128 other) {
+  *this = *this % other;
+  return *this;
+}
+
+inline int128& int128::operator|=(int128 other) {
+  *this = *this | other;
+  return *this;
+}
+
+inline int128& int128::operator&=(int128 other) {
+  *this = *this & other;
+  return *this;
+}
+
+inline int128& int128::operator^=(int128 other) {
+  *this = *this ^ other;
+  return *this;
+}
+
+inline int128& int128::operator<<=(int amount) {
+  *this = *this << amount;
+  return *this;
+}
+
+inline int128& int128::operator>>=(int amount) {
+  *this = *this >> amount;
+  return *this;
+}
+
+namespace int128_internal {
+
+// Casts from unsigned to signed while preserving the underlying binary
+// representation.
+constexpr int64_t BitCastToSigned(uint64_t v) {
+  // Casting an unsigned integer to a signed integer of the same
+  // width is implementation defined behavior if the source value would not fit
+  // in the destination type. We step around it with a roundtrip bitwise not
+  // operation to make sure this function remains constexpr. Clang, GCC, and
+  // MSVC optimize this to a no-op on x86-64.
+  return v & (uint64_t{1} << 63) ? ~static_cast<int64_t>(~v)
+                                 : static_cast<int64_t>(v);
+}
+
+}  // namespace int128_internal
+
 #if defined(ABSL_HAVE_INTRINSIC_INT128)
-#include "absl/numeric/int128_have_intrinsic.inc"
+#include "absl/numeric/int128_have_intrinsic.inc"  // IWYU pragma: export
 #else  // ABSL_HAVE_INTRINSIC_INT128
-#include "absl/numeric/int128_no_intrinsic.inc"
+#include "absl/numeric/int128_no_intrinsic.inc"  // IWYU pragma: export
 #endif  // ABSL_HAVE_INTRINSIC_INT128
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #undef ABSL_INTERNAL_WCHAR_T
diff --git a/absl/numeric/int128_benchmark.cc b/absl/numeric/int128_benchmark.cc
index a5502d9..eab1515 100644
--- a/absl/numeric/int128_benchmark.cc
+++ b/absl/numeric/int128_benchmark.cc
@@ -12,15 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/numeric/int128.h"
-
 #include <algorithm>
 #include <cstdint>
+#include <limits>
 #include <random>
 #include <vector>
 
 #include "benchmark/benchmark.h"
 #include "absl/base/config.h"
+#include "absl/numeric/int128.h"
 
 namespace {
 
@@ -32,57 +32,85 @@
   return std::mt19937(seed);
 }
 
-std::vector<std::pair<absl::uint128, absl::uint128>>
-GetRandomClass128SampleUniformDivisor() {
-  std::vector<std::pair<absl::uint128, absl::uint128>> values;
+template <typename T,
+          typename H = typename std::conditional<
+              std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type>
+std::vector<std::pair<T, T>> GetRandomClass128SampleUniformDivisor() {
+  std::vector<std::pair<T, T>> values;
   std::mt19937 random = MakeRandomEngine();
-  std::uniform_int_distribution<uint64_t> uniform_uint64;
+  std::uniform_int_distribution<H> uniform_h;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
-    absl::uint128 a =
-        absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
-    absl::uint128 b =
-        absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
-    values.emplace_back(std::max(a, b),
-                        std::max(absl::uint128(2), std::min(a, b)));
+    T a{absl::MakeUint128(uniform_h(random), uniform_h(random))};
+    T b{absl::MakeUint128(uniform_h(random), uniform_h(random))};
+    values.emplace_back(std::max(a, b), std::max(T(2), std::min(a, b)));
   }
   return values;
 }
 
+template <typename T>
 void BM_DivideClass128UniformDivisor(benchmark::State& state) {
-  auto values = GetRandomClass128SampleUniformDivisor();
+  auto values = GetRandomClass128SampleUniformDivisor<T>();
   while (state.KeepRunningBatch(values.size())) {
     for (const auto& pair : values) {
       benchmark::DoNotOptimize(pair.first / pair.second);
     }
   }
 }
-BENCHMARK(BM_DivideClass128UniformDivisor);
+BENCHMARK_TEMPLATE(BM_DivideClass128UniformDivisor, absl::uint128);
+BENCHMARK_TEMPLATE(BM_DivideClass128UniformDivisor, absl::int128);
 
-std::vector<std::pair<absl::uint128, uint64_t>>
-GetRandomClass128SampleSmallDivisor() {
-  std::vector<std::pair<absl::uint128, uint64_t>> values;
+template <typename T>
+void BM_RemainderClass128UniformDivisor(benchmark::State& state) {
+  auto values = GetRandomClass128SampleUniformDivisor<T>();
+  while (state.KeepRunningBatch(values.size())) {
+    for (const auto& pair : values) {
+      benchmark::DoNotOptimize(pair.first % pair.second);
+    }
+  }
+}
+BENCHMARK_TEMPLATE(BM_RemainderClass128UniformDivisor, absl::uint128);
+BENCHMARK_TEMPLATE(BM_RemainderClass128UniformDivisor, absl::int128);
+
+template <typename T,
+          typename H = typename std::conditional<
+              std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type>
+std::vector<std::pair<T, H>> GetRandomClass128SampleSmallDivisor() {
+  std::vector<std::pair<T, H>> values;
   std::mt19937 random = MakeRandomEngine();
-  std::uniform_int_distribution<uint64_t> uniform_uint64;
+  std::uniform_int_distribution<H> uniform_h;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
-    absl::uint128 a =
-        absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
-    uint64_t b = std::max(uint64_t{2}, uniform_uint64(random));
-    values.emplace_back(std::max(a, absl::uint128(b)), b);
+    T a{absl::MakeUint128(uniform_h(random), uniform_h(random))};
+    H b{std::max(H{2}, uniform_h(random))};
+    values.emplace_back(std::max(a, T(b)), b);
   }
   return values;
 }
 
+template <typename T>
 void BM_DivideClass128SmallDivisor(benchmark::State& state) {
-  auto values = GetRandomClass128SampleSmallDivisor();
+  auto values = GetRandomClass128SampleSmallDivisor<T>();
   while (state.KeepRunningBatch(values.size())) {
     for (const auto& pair : values) {
       benchmark::DoNotOptimize(pair.first / pair.second);
     }
   }
 }
-BENCHMARK(BM_DivideClass128SmallDivisor);
+BENCHMARK_TEMPLATE(BM_DivideClass128SmallDivisor, absl::uint128);
+BENCHMARK_TEMPLATE(BM_DivideClass128SmallDivisor, absl::int128);
+
+template <typename T>
+void BM_RemainderClass128SmallDivisor(benchmark::State& state) {
+  auto values = GetRandomClass128SampleSmallDivisor<T>();
+  while (state.KeepRunningBatch(values.size())) {
+    for (const auto& pair : values) {
+      benchmark::DoNotOptimize(pair.first % pair.second);
+    }
+  }
+}
+BENCHMARK_TEMPLATE(BM_RemainderClass128SmallDivisor, absl::uint128);
+BENCHMARK_TEMPLATE(BM_RemainderClass128SmallDivisor, absl::int128);
 
 std::vector<std::pair<absl::uint128, absl::uint128>> GetRandomClass128Sample() {
   std::vector<std::pair<absl::uint128, absl::uint128>> values;
@@ -121,74 +149,107 @@
 
 // Some implementations of <random> do not support __int128 when it is
 // available, so we make our own uniform_int_distribution-like type.
+template <typename T,
+          typename H = typename std::conditional<
+              std::is_same<T, __int128>::value, int64_t, uint64_t>::type>
 class UniformIntDistribution128 {
  public:
   // NOLINTNEXTLINE: mimicking std::uniform_int_distribution API
-  unsigned __int128 operator()(std::mt19937& generator) {
-    return (static_cast<unsigned __int128>(dist64_(generator)) << 64) |
-           dist64_(generator);
+  T operator()(std::mt19937& generator) {
+    return (static_cast<T>(dist64_(generator)) << 64) | dist64_(generator);
   }
 
  private:
-  std::uniform_int_distribution<uint64_t> dist64_;
+  std::uniform_int_distribution<H> dist64_;
 };
 
-std::vector<std::pair<unsigned __int128, unsigned __int128>>
-GetRandomIntrinsic128SampleUniformDivisor() {
-  std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
+template <typename T,
+          typename H = typename std::conditional<
+              std::is_same<T, __int128>::value, int64_t, uint64_t>::type>
+std::vector<std::pair<T, T>> GetRandomIntrinsic128SampleUniformDivisor() {
+  std::vector<std::pair<T, T>> values;
   std::mt19937 random = MakeRandomEngine();
-  UniformIntDistribution128 uniform_uint128;
+  UniformIntDistribution128<T> uniform_128;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
-    unsigned __int128 a = uniform_uint128(random);
-    unsigned __int128 b = uniform_uint128(random);
-    values.emplace_back(
-        std::max(a, b),
-        std::max(static_cast<unsigned __int128>(2), std::min(a, b)));
+    T a = uniform_128(random);
+    T b = uniform_128(random);
+    values.emplace_back(std::max(a, b),
+                        std::max(static_cast<T>(2), std::min(a, b)));
   }
   return values;
 }
 
+template <typename T>
 void BM_DivideIntrinsic128UniformDivisor(benchmark::State& state) {
-  auto values = GetRandomIntrinsic128SampleUniformDivisor();
+  auto values = GetRandomIntrinsic128SampleUniformDivisor<T>();
   while (state.KeepRunningBatch(values.size())) {
     for (const auto& pair : values) {
       benchmark::DoNotOptimize(pair.first / pair.second);
     }
   }
 }
-BENCHMARK(BM_DivideIntrinsic128UniformDivisor);
+BENCHMARK_TEMPLATE(BM_DivideIntrinsic128UniformDivisor, unsigned __int128);
+BENCHMARK_TEMPLATE(BM_DivideIntrinsic128UniformDivisor, __int128);
 
-std::vector<std::pair<unsigned __int128, uint64_t>>
-GetRandomIntrinsic128SampleSmallDivisor() {
-  std::vector<std::pair<unsigned __int128, uint64_t>> values;
+template <typename T>
+void BM_RemainderIntrinsic128UniformDivisor(benchmark::State& state) {
+  auto values = GetRandomIntrinsic128SampleUniformDivisor<T>();
+  while (state.KeepRunningBatch(values.size())) {
+    for (const auto& pair : values) {
+      benchmark::DoNotOptimize(pair.first % pair.second);
+    }
+  }
+}
+BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128UniformDivisor, unsigned __int128);
+BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128UniformDivisor, __int128);
+
+template <typename T,
+          typename H = typename std::conditional<
+              std::is_same<T, __int128>::value, int64_t, uint64_t>::type>
+std::vector<std::pair<T, H>> GetRandomIntrinsic128SampleSmallDivisor() {
+  std::vector<std::pair<T, H>> values;
   std::mt19937 random = MakeRandomEngine();
-  UniformIntDistribution128 uniform_uint128;
-  std::uniform_int_distribution<uint64_t> uniform_uint64;
+  UniformIntDistribution128<T> uniform_int128;
+  std::uniform_int_distribution<H> uniform_int64;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
-    unsigned __int128 a = uniform_uint128(random);
-    uint64_t b = std::max(uint64_t{2}, uniform_uint64(random));
-    values.emplace_back(std::max(a, static_cast<unsigned __int128>(b)), b);
+    T a = uniform_int128(random);
+    H b = std::max(H{2}, uniform_int64(random));
+    values.emplace_back(std::max(a, static_cast<T>(b)), b);
   }
   return values;
 }
 
+template <typename T>
 void BM_DivideIntrinsic128SmallDivisor(benchmark::State& state) {
-  auto values = GetRandomIntrinsic128SampleSmallDivisor();
+  auto values = GetRandomIntrinsic128SampleSmallDivisor<T>();
   while (state.KeepRunningBatch(values.size())) {
     for (const auto& pair : values) {
       benchmark::DoNotOptimize(pair.first / pair.second);
     }
   }
 }
-BENCHMARK(BM_DivideIntrinsic128SmallDivisor);
+BENCHMARK_TEMPLATE(BM_DivideIntrinsic128SmallDivisor, unsigned __int128);
+BENCHMARK_TEMPLATE(BM_DivideIntrinsic128SmallDivisor, __int128);
+
+template <typename T>
+void BM_RemainderIntrinsic128SmallDivisor(benchmark::State& state) {
+  auto values = GetRandomIntrinsic128SampleSmallDivisor<T>();
+  while (state.KeepRunningBatch(values.size())) {
+    for (const auto& pair : values) {
+      benchmark::DoNotOptimize(pair.first % pair.second);
+    }
+  }
+}
+BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, unsigned __int128);
+BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, __int128);
 
 std::vector<std::pair<unsigned __int128, unsigned __int128>>
       GetRandomIntrinsic128Sample() {
   std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
   std::mt19937 random = MakeRandomEngine();
-  UniformIntDistribution128 uniform_uint128;
+  UniformIntDistribution128<unsigned __int128> uniform_uint128;
   values.reserve(kSampleSize);
   for (size_t i = 0; i < kSampleSize; ++i) {
     values.emplace_back(uniform_uint128(random), uniform_uint128(random));
diff --git a/absl/numeric/int128_have_intrinsic.inc b/absl/numeric/int128_have_intrinsic.inc
index c7ea683..d6c76dd 100644
--- a/absl/numeric/int128_have_intrinsic.inc
+++ b/absl/numeric/int128_have_intrinsic.inc
@@ -16,3 +16,287 @@
 // This file contains :int128 implementation details that depend on internal
 // representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is
 // included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
+
+namespace int128_internal {
+
+// Casts from unsigned to signed while preserving the underlying binary
+// representation.
+constexpr __int128 BitCastToSigned(unsigned __int128 v) {
+  // Casting an unsigned integer to a signed integer of the same
+  // width is implementation defined behavior if the source value would not fit
+  // in the destination type. We step around it with a roundtrip bitwise not
+  // operation to make sure this function remains constexpr. Clang and GCC
+  // optimize this to a no-op on x86-64.
+  return v & (static_cast<unsigned __int128>(1) << 127)
+             ? ~static_cast<__int128>(~v)
+             : static_cast<__int128>(v);
+}
+
+}  // namespace int128_internal
+
+inline int128& int128::operator=(__int128 v) {
+  v_ = v;
+  return *this;
+}
+
+constexpr uint64_t Int128Low64(int128 v) {
+  return static_cast<uint64_t>(v.v_ & ~uint64_t{0});
+}
+
+constexpr int64_t Int128High64(int128 v) {
+  // Initially cast to unsigned to prevent a right shift on a negative value.
+  return int128_internal::BitCastToSigned(
+      static_cast<uint64_t>(static_cast<unsigned __int128>(v.v_) >> 64));
+}
+
+constexpr int128::int128(int64_t high, uint64_t low)
+    // Initially cast to unsigned to prevent a left shift that overflows.
+    : v_(int128_internal::BitCastToSigned(static_cast<unsigned __int128>(high)
+                                           << 64) |
+         low) {}
+
+
+constexpr int128::int128(int v) : v_{v} {}
+
+constexpr int128::int128(long v) : v_{v} {}       // NOLINT(runtime/int)
+
+constexpr int128::int128(long long v) : v_{v} {}  // NOLINT(runtime/int)
+
+constexpr int128::int128(__int128 v) : v_{v} {}
+
+constexpr int128::int128(unsigned int v) : v_{v} {}
+
+constexpr int128::int128(unsigned long v) : v_{v} {}  // NOLINT(runtime/int)
+
+// NOLINTNEXTLINE(runtime/int)
+constexpr int128::int128(unsigned long long v) : v_{v} {}
+
+constexpr int128::int128(unsigned __int128 v) : v_{static_cast<__int128>(v)} {}
+
+inline int128::int128(float v) {
+  v_ = static_cast<__int128>(v);
+}
+
+inline int128::int128(double v) {
+  v_ = static_cast<__int128>(v);
+}
+
+inline int128::int128(long double v) {
+  v_ = static_cast<__int128>(v);
+}
+
+constexpr int128::int128(uint128 v) : v_{static_cast<__int128>(v)} {}
+
+constexpr int128::operator bool() const { return static_cast<bool>(v_); }
+
+constexpr int128::operator char() const { return static_cast<char>(v_); }
+
+constexpr int128::operator signed char() const {
+  return static_cast<signed char>(v_);
+}
+
+constexpr int128::operator unsigned char() const {
+  return static_cast<unsigned char>(v_);
+}
+
+constexpr int128::operator char16_t() const {
+  return static_cast<char16_t>(v_);
+}
+
+constexpr int128::operator char32_t() const {
+  return static_cast<char32_t>(v_);
+}
+
+constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const {
+  return static_cast<ABSL_INTERNAL_WCHAR_T>(v_);
+}
+
+constexpr int128::operator short() const {  // NOLINT(runtime/int)
+  return static_cast<short>(v_);            // NOLINT(runtime/int)
+}
+
+constexpr int128::operator unsigned short() const {  // NOLINT(runtime/int)
+  return static_cast<unsigned short>(v_);            // NOLINT(runtime/int)
+}
+
+constexpr int128::operator int() const {
+  return static_cast<int>(v_);
+}
+
+constexpr int128::operator unsigned int() const {
+  return static_cast<unsigned int>(v_);
+}
+
+constexpr int128::operator long() const {  // NOLINT(runtime/int)
+  return static_cast<long>(v_);            // NOLINT(runtime/int)
+}
+
+constexpr int128::operator unsigned long() const {  // NOLINT(runtime/int)
+  return static_cast<unsigned long>(v_);            // NOLINT(runtime/int)
+}
+
+constexpr int128::operator long long() const {  // NOLINT(runtime/int)
+  return static_cast<long long>(v_);            // NOLINT(runtime/int)
+}
+
+constexpr int128::operator unsigned long long() const {  // NOLINT(runtime/int)
+  return static_cast<unsigned long long>(v_);            // NOLINT(runtime/int)
+}
+
+constexpr int128::operator __int128() const { return v_; }
+
+constexpr int128::operator unsigned __int128() const {
+  return static_cast<unsigned __int128>(v_);
+}
+
+// Clang on PowerPC sometimes produces incorrect __int128 to floating point
+// conversions. In that case, we do the conversion with a similar implementation
+// to the conversion operators in int128_no_intrinsic.inc.
+#if defined(__clang__) && !defined(__ppc64__)
+inline int128::operator float() const { return static_cast<float>(v_); }
+
+inline int128::operator double () const { return static_cast<double>(v_); }
+
+inline int128::operator long double() const {
+  return static_cast<long double>(v_);
+}
+
+#else  // Clang on PowerPC
+// Forward declaration for conversion operators to floating point types.
+int128 operator-(int128 v);
+bool operator!=(int128 lhs, int128 rhs);
+
+inline int128::operator float() const {
+  // We must convert the absolute value and then negate as needed, because
+  // floating point types are typically sign-magnitude. Otherwise, the
+  // difference between the high and low 64 bits when interpreted as two's
+  // complement overwhelms the precision of the mantissa.
+  //
+  // Also check to make sure we don't negate Int128Min()
+  return v_ < 0 && *this != Int128Min()
+             ? -static_cast<float>(-*this)
+             : static_cast<float>(Int128Low64(*this)) +
+                   std::ldexp(static_cast<float>(Int128High64(*this)), 64);
+}
+
+inline int128::operator double() const {
+  // See comment in int128::operator float() above.
+  return v_ < 0 && *this != Int128Min()
+             ? -static_cast<double>(-*this)
+             : static_cast<double>(Int128Low64(*this)) +
+                   std::ldexp(static_cast<double>(Int128High64(*this)), 64);
+}
+
+inline int128::operator long double() const {
+  // See comment in int128::operator float() above.
+  return v_ < 0 && *this != Int128Min()
+             ? -static_cast<long double>(-*this)
+             : static_cast<long double>(Int128Low64(*this)) +
+                   std::ldexp(static_cast<long double>(Int128High64(*this)),
+                              64);
+}
+#endif  // Clang on PowerPC
+
+// Comparison operators.
+
+inline bool operator==(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) == static_cast<__int128>(rhs);
+}
+
+inline bool operator!=(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) != static_cast<__int128>(rhs);
+}
+
+inline bool operator<(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) < static_cast<__int128>(rhs);
+}
+
+inline bool operator>(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) > static_cast<__int128>(rhs);
+}
+
+inline bool operator<=(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) <= static_cast<__int128>(rhs);
+}
+
+inline bool operator>=(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) >= static_cast<__int128>(rhs);
+}
+
+// Unary operators.
+
+inline int128 operator-(int128 v) {
+  return -static_cast<__int128>(v);
+}
+
+inline bool operator!(int128 v) {
+  return !static_cast<__int128>(v);
+}
+
+inline int128 operator~(int128 val) {
+  return ~static_cast<__int128>(val);
+}
+
+// Arithmetic operators.
+
+inline int128 operator+(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) + static_cast<__int128>(rhs);
+}
+
+inline int128 operator-(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) - static_cast<__int128>(rhs);
+}
+
+inline int128 operator*(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) * static_cast<__int128>(rhs);
+}
+
+inline int128 operator/(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) / static_cast<__int128>(rhs);
+}
+
+inline int128 operator%(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) % static_cast<__int128>(rhs);
+}
+
+inline int128 int128::operator++(int) {
+  int128 tmp(*this);
+  ++v_;
+  return tmp;
+}
+
+inline int128 int128::operator--(int) {
+  int128 tmp(*this);
+  --v_;
+  return tmp;
+}
+
+inline int128& int128::operator++() {
+  ++v_;
+  return *this;
+}
+
+inline int128& int128::operator--() {
+  --v_;
+  return *this;
+}
+
+inline int128 operator|(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) | static_cast<__int128>(rhs);
+}
+
+inline int128 operator&(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) & static_cast<__int128>(rhs);
+}
+
+inline int128 operator^(int128 lhs, int128 rhs) {
+  return static_cast<__int128>(lhs) ^ static_cast<__int128>(rhs);
+}
+
+inline int128 operator<<(int128 lhs, int amount) {
+  return static_cast<__int128>(lhs) << amount;
+}
+
+inline int128 operator>>(int128 lhs, int amount) {
+  return static_cast<__int128>(lhs) >> amount;
+}
diff --git a/absl/numeric/int128_no_intrinsic.inc b/absl/numeric/int128_no_intrinsic.inc
index 046cb9b..c753771 100644
--- a/absl/numeric/int128_no_intrinsic.inc
+++ b/absl/numeric/int128_no_intrinsic.inc
@@ -16,3 +16,293 @@
 // This file contains :int128 implementation details that depend on internal
 // representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file
 // is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
+
+constexpr uint64_t Int128Low64(int128 v) { return v.lo_; }
+
+constexpr int64_t Int128High64(int128 v) { return v.hi_; }
+
+#if defined(ABSL_IS_LITTLE_ENDIAN)
+
+constexpr int128::int128(int64_t high, uint64_t low) :
+    lo_(low), hi_(high) {}
+
+constexpr int128::int128(int v)
+    : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
+constexpr int128::int128(long v)  // NOLINT(runtime/int)
+    : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
+constexpr int128::int128(long long v)  // NOLINT(runtime/int)
+    : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
+
+constexpr int128::int128(unsigned int v) : lo_{v}, hi_{0} {}
+// NOLINTNEXTLINE(runtime/int)
+constexpr int128::int128(unsigned long v) : lo_{v}, hi_{0} {}
+// NOLINTNEXTLINE(runtime/int)
+constexpr int128::int128(unsigned long long v) : lo_{v}, hi_{0} {}
+
+constexpr int128::int128(uint128 v)
+    : lo_{Uint128Low64(v)}, hi_{static_cast<int64_t>(Uint128High64(v))} {}
+
+#elif defined(ABSL_IS_BIG_ENDIAN)
+
+constexpr int128::int128(int64_t high, uint64_t low) :
+    hi_{high}, lo_{low} {}
+
+constexpr int128::int128(int v)
+    : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
+constexpr int128::int128(long v)  // NOLINT(runtime/int)
+    : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
+constexpr int128::int128(long long v)  // NOLINT(runtime/int)
+    : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
+
+constexpr int128::int128(unsigned int v) : hi_{0}, lo_{v} {}
+// NOLINTNEXTLINE(runtime/int)
+constexpr int128::int128(unsigned long v) : hi_{0}, lo_{v} {}
+// NOLINTNEXTLINE(runtime/int)
+constexpr int128::int128(unsigned long long v) : hi_{0}, lo_{v} {}
+
+constexpr int128::int128(uint128 v)
+    : hi_{static_cast<int64_t>(Uint128High64(v))}, lo_{Uint128Low64(v)} {}
+
+#else  // byte order
+#error "Unsupported byte order: must be little-endian or big-endian."
+#endif  // byte order
+
+constexpr int128::operator bool() const { return lo_ || hi_; }
+
+constexpr int128::operator char() const {
+  // NOLINTNEXTLINE(runtime/int)
+  return static_cast<char>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator signed char() const {
+  // NOLINTNEXTLINE(runtime/int)
+  return static_cast<signed char>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned char() const {
+  return static_cast<unsigned char>(lo_);
+}
+
+constexpr int128::operator char16_t() const {
+  return static_cast<char16_t>(lo_);
+}
+
+constexpr int128::operator char32_t() const {
+  return static_cast<char32_t>(lo_);
+}
+
+constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const {
+  // NOLINTNEXTLINE(runtime/int)
+  return static_cast<ABSL_INTERNAL_WCHAR_T>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator short() const {  // NOLINT(runtime/int)
+  // NOLINTNEXTLINE(runtime/int)
+  return static_cast<short>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned short() const {  // NOLINT(runtime/int)
+  return static_cast<unsigned short>(lo_);           // NOLINT(runtime/int)
+}
+
+constexpr int128::operator int() const {
+  // NOLINTNEXTLINE(runtime/int)
+  return static_cast<int>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned int() const {
+  return static_cast<unsigned int>(lo_);
+}
+
+constexpr int128::operator long() const {  // NOLINT(runtime/int)
+  // NOLINTNEXTLINE(runtime/int)
+  return static_cast<long>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned long() const {  // NOLINT(runtime/int)
+  return static_cast<unsigned long>(lo_);           // NOLINT(runtime/int)
+}
+
+constexpr int128::operator long long() const {  // NOLINT(runtime/int)
+  // We don't bother checking the value of hi_. If *this < 0, lo_'s high bit
+  // must be set in order for the value to fit into a long long. Conversely, if
+  // lo_'s high bit is set, *this must be < 0 for the value to fit.
+  return int128_internal::BitCastToSigned(lo_);
+}
+
+constexpr int128::operator unsigned long long() const {  // NOLINT(runtime/int)
+  return static_cast<unsigned long long>(lo_);           // NOLINT(runtime/int)
+}
+
+// Forward declaration for conversion operators to floating point types.
+int128 operator-(int128 v);
+bool operator!=(int128 lhs, int128 rhs);
+
+inline int128::operator float() const {
+  // We must convert the absolute value and then negate as needed, because
+  // floating point types are typically sign-magnitude. Otherwise, the
+  // difference between the high and low 64 bits when interpreted as two's
+  // complement overwhelms the precision of the mantissa.
+  //
+  // Also check to make sure we don't negate Int128Min()
+  return hi_ < 0 && *this != Int128Min()
+             ? -static_cast<float>(-*this)
+             : static_cast<float>(lo_) +
+                   std::ldexp(static_cast<float>(hi_), 64);
+}
+
+inline int128::operator double() const {
+  // See comment in int128::operator float() above.
+  return hi_ < 0 && *this != Int128Min()
+             ? -static_cast<double>(-*this)
+             : static_cast<double>(lo_) +
+                   std::ldexp(static_cast<double>(hi_), 64);
+}
+
+inline int128::operator long double() const {
+  // See comment in int128::operator float() above.
+  return hi_ < 0 && *this != Int128Min()
+             ? -static_cast<long double>(-*this)
+             : static_cast<long double>(lo_) +
+                   std::ldexp(static_cast<long double>(hi_), 64);
+}
+
+// Comparison operators.
+
+inline bool operator==(int128 lhs, int128 rhs) {
+  return (Int128Low64(lhs) == Int128Low64(rhs) &&
+          Int128High64(lhs) == Int128High64(rhs));
+}
+
+inline bool operator!=(int128 lhs, int128 rhs) {
+  return !(lhs == rhs);
+}
+
+inline bool operator<(int128 lhs, int128 rhs) {
+  return (Int128High64(lhs) == Int128High64(rhs))
+             ? (Int128Low64(lhs) < Int128Low64(rhs))
+             : (Int128High64(lhs) < Int128High64(rhs));
+}
+
+inline bool operator>(int128 lhs, int128 rhs) {
+  return (Int128High64(lhs) == Int128High64(rhs))
+             ? (Int128Low64(lhs) > Int128Low64(rhs))
+             : (Int128High64(lhs) > Int128High64(rhs));
+}
+
+inline bool operator<=(int128 lhs, int128 rhs) {
+  return !(lhs > rhs);
+}
+
+inline bool operator>=(int128 lhs, int128 rhs) {
+  return !(lhs < rhs);
+}
+
+// Unary operators.
+
+inline int128 operator-(int128 v) {
+  int64_t hi = ~Int128High64(v);
+  uint64_t lo = ~Int128Low64(v) + 1;
+  if (lo == 0) ++hi;  // carry
+  return MakeInt128(hi, lo);
+}
+
+inline bool operator!(int128 v) {
+  return !Int128Low64(v) && !Int128High64(v);
+}
+
+inline int128 operator~(int128 val) {
+  return MakeInt128(~Int128High64(val), ~Int128Low64(val));
+}
+
+// Arithmetic operators.
+
+inline int128 operator+(int128 lhs, int128 rhs) {
+  int128 result = MakeInt128(Int128High64(lhs) + Int128High64(rhs),
+                             Int128Low64(lhs) + Int128Low64(rhs));
+  if (Int128Low64(result) < Int128Low64(lhs)) {  // check for carry
+    return MakeInt128(Int128High64(result) + 1, Int128Low64(result));
+  }
+  return result;
+}
+
+inline int128 operator-(int128 lhs, int128 rhs) {
+  int128 result = MakeInt128(Int128High64(lhs) - Int128High64(rhs),
+                             Int128Low64(lhs) - Int128Low64(rhs));
+  if (Int128Low64(lhs) < Int128Low64(rhs)) {  // check for carry
+    return MakeInt128(Int128High64(result) - 1, Int128Low64(result));
+  }
+  return result;
+}
+
+inline int128 operator*(int128 lhs, int128 rhs) {
+  uint128 result = uint128(lhs) * rhs;
+  return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)),
+                    Uint128Low64(result));
+}
+
+inline int128 int128::operator++(int) {
+  int128 tmp(*this);
+  *this += 1;
+  return tmp;
+}
+
+inline int128 int128::operator--(int) {
+  int128 tmp(*this);
+  *this -= 1;
+  return tmp;
+}
+
+inline int128& int128::operator++() {
+  *this += 1;
+  return *this;
+}
+
+inline int128& int128::operator--() {
+  *this -= 1;
+  return *this;
+}
+
+inline int128 operator|(int128 lhs, int128 rhs) {
+  return MakeInt128(Int128High64(lhs) | Int128High64(rhs),
+                    Int128Low64(lhs) | Int128Low64(rhs));
+}
+
+inline int128 operator&(int128 lhs, int128 rhs) {
+  return MakeInt128(Int128High64(lhs) & Int128High64(rhs),
+                    Int128Low64(lhs) & Int128Low64(rhs));
+}
+
+inline int128 operator^(int128 lhs, int128 rhs) {
+  return MakeInt128(Int128High64(lhs) ^ Int128High64(rhs),
+                    Int128Low64(lhs) ^ Int128Low64(rhs));
+}
+
+inline int128 operator<<(int128 lhs, int amount) {
+  // uint64_t shifts of >= 64 are undefined, so we need some special-casing.
+  if (amount < 64) {
+    if (amount != 0) {
+      return MakeInt128(
+          (Int128High64(lhs) << amount) |
+              static_cast<int64_t>(Int128Low64(lhs) >> (64 - amount)),
+          Int128Low64(lhs) << amount);
+    }
+    return lhs;
+  }
+  return MakeInt128(static_cast<int64_t>(Int128Low64(lhs) << (amount - 64)), 0);
+}
+
+inline int128 operator>>(int128 lhs, int amount) {
+  // uint64_t shifts of >= 64 are undefined, so we need some special-casing.
+  if (amount < 64) {
+    if (amount != 0) {
+      return MakeInt128(
+          Int128High64(lhs) >> amount,
+          (Int128Low64(lhs) >> amount) |
+              (static_cast<uint64_t>(Int128High64(lhs)) << (64 - amount)));
+    }
+    return lhs;
+  }
+  return MakeInt128(0,
+                    static_cast<uint64_t>(Int128High64(lhs) >> (amount - 64)));
+}
diff --git a/absl/numeric/int128_stream_test.cc b/absl/numeric/int128_stream_test.cc
index 3cfa9dc..479ad66 100644
--- a/absl/numeric/int128_stream_test.cc
+++ b/absl/numeric/int128_stream_test.cc
@@ -147,6 +147,735 @@
   }
 }
 
+struct Int128TestCase {
+  absl::int128 value;
+  std::ios_base::fmtflags flags;
+  std::streamsize width;
+  const char* expected;
+};
+
+void CheckInt128Case(const Int128TestCase& test_case) {
+  std::ostringstream os;
+  os.flags(test_case.flags);
+  os.width(test_case.width);
+  os.fill(kFill);
+  os << test_case.value;
+  SCOPED_TRACE(StreamFormatToString(test_case.flags, test_case.width));
+  EXPECT_EQ(test_case.expected, os.str());
+}
+
+TEST(Int128, OStreamValueTest) {
+  CheckInt128Case({1, kDec, /*width = */ 0, "1"});
+  CheckInt128Case({1, kOct, /*width = */ 0, "1"});
+  CheckInt128Case({1, kHex, /*width = */ 0, "1"});
+  CheckInt128Case({9, kDec, /*width = */ 0, "9"});
+  CheckInt128Case({9, kOct, /*width = */ 0, "11"});
+  CheckInt128Case({9, kHex, /*width = */ 0, "9"});
+  CheckInt128Case({12345, kDec, /*width = */ 0, "12345"});
+  CheckInt128Case({12345, kOct, /*width = */ 0, "30071"});
+  CheckInt128Case({12345, kHex, /*width = */ 0, "3039"});
+  CheckInt128Case(
+      {0x8000000000000000, kDec, /*width = */ 0, "9223372036854775808"});
+  CheckInt128Case(
+      {0x8000000000000000, kOct, /*width = */ 0, "1000000000000000000000"});
+  CheckInt128Case(
+      {0x8000000000000000, kHex, /*width = */ 0, "8000000000000000"});
+  CheckInt128Case({std::numeric_limits<uint64_t>::max(), kDec,
+                   /*width = */ 0, "18446744073709551615"});
+  CheckInt128Case({std::numeric_limits<uint64_t>::max(), kOct,
+                   /*width = */ 0, "1777777777777777777777"});
+  CheckInt128Case({std::numeric_limits<uint64_t>::max(), kHex,
+                   /*width = */ 0, "ffffffffffffffff"});
+  CheckInt128Case(
+      {absl::MakeInt128(1, 0), kDec, /*width = */ 0, "18446744073709551616"});
+  CheckInt128Case(
+      {absl::MakeInt128(1, 0), kOct, /*width = */ 0, "2000000000000000000000"});
+  CheckInt128Case(
+      {absl::MakeInt128(1, 0), kHex, /*width = */ 0, "10000000000000000"});
+  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(),
+                                    std::numeric_limits<uint64_t>::max()),
+                   std::ios::dec, /*width = */ 0,
+                   "170141183460469231731687303715884105727"});
+  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(),
+                                    std::numeric_limits<uint64_t>::max()),
+                   std::ios::oct, /*width = */ 0,
+                   "1777777777777777777777777777777777777777777"});
+  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(),
+                                    std::numeric_limits<uint64_t>::max()),
+                   std::ios::hex, /*width = */ 0,
+                   "7fffffffffffffffffffffffffffffff"});
+  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0),
+                   std::ios::dec, /*width = */ 0,
+                   "-170141183460469231731687303715884105728"});
+  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0),
+                   std::ios::oct, /*width = */ 0,
+                   "2000000000000000000000000000000000000000000"});
+  CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0),
+                   std::ios::hex, /*width = */ 0,
+                   "80000000000000000000000000000000"});
+  CheckInt128Case({-1, std::ios::dec, /*width = */ 0, "-1"});
+  CheckInt128Case({-1, std::ios::oct, /*width = */ 0,
+                   "3777777777777777777777777777777777777777777"});
+  CheckInt128Case(
+      {-1, std::ios::hex, /*width = */ 0, "ffffffffffffffffffffffffffffffff"});
+  CheckInt128Case({-12345, std::ios::dec, /*width = */ 0, "-12345"});
+  CheckInt128Case({-12345, std::ios::oct, /*width = */ 0,
+                   "3777777777777777777777777777777777777747707"});
+  CheckInt128Case({-12345, std::ios::hex, /*width = */ 0,
+                   "ffffffffffffffffffffffffffffcfc7"});
+}
+
+std::vector<Int128TestCase> GetInt128FormatCases();
+TEST(Int128, OStreamFormatTest) {
+  for (const Int128TestCase& test_case : GetInt128FormatCases()) {
+    CheckInt128Case(test_case);
+  }
+}
+
+std::vector<Int128TestCase> GetInt128FormatCases() {
+  return {
+      {0, std::ios_base::fmtflags(), /*width = */ 0, "0"},
+      {0, std::ios_base::fmtflags(), /*width = */ 6, "_____0"},
+      {0, kPos, /*width = */ 0, "+0"},
+      {0, kPos, /*width = */ 6, "____+0"},
+      {0, kBase, /*width = */ 0, "0"},
+      {0, kBase, /*width = */ 6, "_____0"},
+      {0, kBase | kPos, /*width = */ 0, "+0"},
+      {0, kBase | kPos, /*width = */ 6, "____+0"},
+      {0, kUpper, /*width = */ 0, "0"},
+      {0, kUpper, /*width = */ 6, "_____0"},
+      {0, kUpper | kPos, /*width = */ 0, "+0"},
+      {0, kUpper | kPos, /*width = */ 6, "____+0"},
+      {0, kUpper | kBase, /*width = */ 0, "0"},
+      {0, kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kUpper | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kUpper | kBase | kPos, /*width = */ 6, "____+0"},
+      {0, kLeft, /*width = */ 0, "0"},
+      {0, kLeft, /*width = */ 6, "0_____"},
+      {0, kLeft | kPos, /*width = */ 0, "+0"},
+      {0, kLeft | kPos, /*width = */ 6, "+0____"},
+      {0, kLeft | kBase, /*width = */ 0, "0"},
+      {0, kLeft | kBase, /*width = */ 6, "0_____"},
+      {0, kLeft | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kLeft | kBase | kPos, /*width = */ 6, "+0____"},
+      {0, kLeft | kUpper, /*width = */ 0, "0"},
+      {0, kLeft | kUpper, /*width = */ 6, "0_____"},
+      {0, kLeft | kUpper | kPos, /*width = */ 0, "+0"},
+      {0, kLeft | kUpper | kPos, /*width = */ 6, "+0____"},
+      {0, kLeft | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kLeft | kUpper | kBase, /*width = */ 6, "0_____"},
+      {0, kLeft | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kLeft | kUpper | kBase | kPos, /*width = */ 6, "+0____"},
+      {0, kInt, /*width = */ 0, "0"},
+      {0, kInt, /*width = */ 6, "_____0"},
+      {0, kInt | kPos, /*width = */ 0, "+0"},
+      {0, kInt | kPos, /*width = */ 6, "+____0"},
+      {0, kInt | kBase, /*width = */ 0, "0"},
+      {0, kInt | kBase, /*width = */ 6, "_____0"},
+      {0, kInt | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kInt | kBase | kPos, /*width = */ 6, "+____0"},
+      {0, kInt | kUpper, /*width = */ 0, "0"},
+      {0, kInt | kUpper, /*width = */ 6, "_____0"},
+      {0, kInt | kUpper | kPos, /*width = */ 0, "+0"},
+      {0, kInt | kUpper | kPos, /*width = */ 6, "+____0"},
+      {0, kInt | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kInt | kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kInt | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kInt | kUpper | kBase | kPos, /*width = */ 6, "+____0"},
+      {0, kRight, /*width = */ 0, "0"},
+      {0, kRight, /*width = */ 6, "_____0"},
+      {0, kRight | kPos, /*width = */ 0, "+0"},
+      {0, kRight | kPos, /*width = */ 6, "____+0"},
+      {0, kRight | kBase, /*width = */ 0, "0"},
+      {0, kRight | kBase, /*width = */ 6, "_____0"},
+      {0, kRight | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kRight | kBase | kPos, /*width = */ 6, "____+0"},
+      {0, kRight | kUpper, /*width = */ 0, "0"},
+      {0, kRight | kUpper, /*width = */ 6, "_____0"},
+      {0, kRight | kUpper | kPos, /*width = */ 0, "+0"},
+      {0, kRight | kUpper | kPos, /*width = */ 6, "____+0"},
+      {0, kRight | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kRight | kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kRight | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kRight | kUpper | kBase | kPos, /*width = */ 6, "____+0"},
+      {0, kDec, /*width = */ 0, "0"},
+      {0, kDec, /*width = */ 6, "_____0"},
+      {0, kDec | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kPos, /*width = */ 6, "____+0"},
+      {0, kDec | kBase, /*width = */ 0, "0"},
+      {0, kDec | kBase, /*width = */ 6, "_____0"},
+      {0, kDec | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kBase | kPos, /*width = */ 6, "____+0"},
+      {0, kDec | kUpper, /*width = */ 0, "0"},
+      {0, kDec | kUpper, /*width = */ 6, "_____0"},
+      {0, kDec | kUpper | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kUpper | kPos, /*width = */ 6, "____+0"},
+      {0, kDec | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kDec | kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kDec | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kUpper | kBase | kPos, /*width = */ 6, "____+0"},
+      {0, kDec | kLeft, /*width = */ 0, "0"},
+      {0, kDec | kLeft, /*width = */ 6, "0_____"},
+      {0, kDec | kLeft | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kLeft | kPos, /*width = */ 6, "+0____"},
+      {0, kDec | kLeft | kBase, /*width = */ 0, "0"},
+      {0, kDec | kLeft | kBase, /*width = */ 6, "0_____"},
+      {0, kDec | kLeft | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kLeft | kBase | kPos, /*width = */ 6, "+0____"},
+      {0, kDec | kLeft | kUpper, /*width = */ 0, "0"},
+      {0, kDec | kLeft | kUpper, /*width = */ 6, "0_____"},
+      {0, kDec | kLeft | kUpper | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kLeft | kUpper | kPos, /*width = */ 6, "+0____"},
+      {0, kDec | kLeft | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kDec | kLeft | kUpper | kBase, /*width = */ 6, "0_____"},
+      {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "+0____"},
+      {0, kDec | kInt, /*width = */ 0, "0"},
+      {0, kDec | kInt, /*width = */ 6, "_____0"},
+      {0, kDec | kInt | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kInt | kPos, /*width = */ 6, "+____0"},
+      {0, kDec | kInt | kBase, /*width = */ 0, "0"},
+      {0, kDec | kInt | kBase, /*width = */ 6, "_____0"},
+      {0, kDec | kInt | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kInt | kBase | kPos, /*width = */ 6, "+____0"},
+      {0, kDec | kInt | kUpper, /*width = */ 0, "0"},
+      {0, kDec | kInt | kUpper, /*width = */ 6, "_____0"},
+      {0, kDec | kInt | kUpper | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kInt | kUpper | kPos, /*width = */ 6, "+____0"},
+      {0, kDec | kInt | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kDec | kInt | kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "+____0"},
+      {0, kDec | kRight, /*width = */ 0, "0"},
+      {0, kDec | kRight, /*width = */ 6, "_____0"},
+      {0, kDec | kRight | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kRight | kPos, /*width = */ 6, "____+0"},
+      {0, kDec | kRight | kBase, /*width = */ 0, "0"},
+      {0, kDec | kRight | kBase, /*width = */ 6, "_____0"},
+      {0, kDec | kRight | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kRight | kBase | kPos, /*width = */ 6, "____+0"},
+      {0, kDec | kRight | kUpper, /*width = */ 0, "0"},
+      {0, kDec | kRight | kUpper, /*width = */ 6, "_____0"},
+      {0, kDec | kRight | kUpper | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kRight | kUpper | kPos, /*width = */ 6, "____+0"},
+      {0, kDec | kRight | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kDec | kRight | kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+      {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "____+0"},
+      {0, kOct, /*width = */ 0, "0"},
+      {0, kOct, /*width = */ 6, "_____0"},
+      {0, kOct | kPos, /*width = */ 0, "0"},
+      {0, kOct | kPos, /*width = */ 6, "_____0"},
+      {0, kOct | kBase, /*width = */ 0, "0"},
+      {0, kOct | kBase, /*width = */ 6, "_____0"},
+      {0, kOct | kBase | kPos, /*width = */ 0, "0"},
+      {0, kOct | kBase | kPos, /*width = */ 6, "_____0"},
+      {0, kOct | kUpper, /*width = */ 0, "0"},
+      {0, kOct | kUpper, /*width = */ 6, "_____0"},
+      {0, kOct | kUpper | kPos, /*width = */ 0, "0"},
+      {0, kOct | kUpper | kPos, /*width = */ 6, "_____0"},
+      {0, kOct | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kOct | kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kOct | kUpper | kBase | kPos, /*width = */ 0, "0"},
+      {0, kOct | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+      {0, kOct | kLeft, /*width = */ 0, "0"},
+      {0, kOct | kLeft, /*width = */ 6, "0_____"},
+      {0, kOct | kLeft | kPos, /*width = */ 0, "0"},
+      {0, kOct | kLeft | kPos, /*width = */ 6, "0_____"},
+      {0, kOct | kLeft | kBase, /*width = */ 0, "0"},
+      {0, kOct | kLeft | kBase, /*width = */ 6, "0_____"},
+      {0, kOct | kLeft | kBase | kPos, /*width = */ 0, "0"},
+      {0, kOct | kLeft | kBase | kPos, /*width = */ 6, "0_____"},
+      {0, kOct | kLeft | kUpper, /*width = */ 0, "0"},
+      {0, kOct | kLeft | kUpper, /*width = */ 6, "0_____"},
+      {0, kOct | kLeft | kUpper | kPos, /*width = */ 0, "0"},
+      {0, kOct | kLeft | kUpper | kPos, /*width = */ 6, "0_____"},
+      {0, kOct | kLeft | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kOct | kLeft | kUpper | kBase, /*width = */ 6, "0_____"},
+      {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"},
+      {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"},
+      {0, kOct | kInt, /*width = */ 0, "0"},
+      {0, kOct | kInt, /*width = */ 6, "_____0"},
+      {0, kOct | kInt | kPos, /*width = */ 0, "0"},
+      {0, kOct | kInt | kPos, /*width = */ 6, "_____0"},
+      {0, kOct | kInt | kBase, /*width = */ 0, "0"},
+      {0, kOct | kInt | kBase, /*width = */ 6, "_____0"},
+      {0, kOct | kInt | kBase | kPos, /*width = */ 0, "0"},
+      {0, kOct | kInt | kBase | kPos, /*width = */ 6, "_____0"},
+      {0, kOct | kInt | kUpper, /*width = */ 0, "0"},
+      {0, kOct | kInt | kUpper, /*width = */ 6, "_____0"},
+      {0, kOct | kInt | kUpper | kPos, /*width = */ 0, "0"},
+      {0, kOct | kInt | kUpper | kPos, /*width = */ 6, "_____0"},
+      {0, kOct | kInt | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kOct | kInt | kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, "0"},
+      {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+      {0, kOct | kRight, /*width = */ 0, "0"},
+      {0, kOct | kRight, /*width = */ 6, "_____0"},
+      {0, kOct | kRight | kPos, /*width = */ 0, "0"},
+      {0, kOct | kRight | kPos, /*width = */ 6, "_____0"},
+      {0, kOct | kRight | kBase, /*width = */ 0, "0"},
+      {0, kOct | kRight | kBase, /*width = */ 6, "_____0"},
+      {0, kOct | kRight | kBase | kPos, /*width = */ 0, "0"},
+      {0, kOct | kRight | kBase | kPos, /*width = */ 6, "_____0"},
+      {0, kOct | kRight | kUpper, /*width = */ 0, "0"},
+      {0, kOct | kRight | kUpper, /*width = */ 6, "_____0"},
+      {0, kOct | kRight | kUpper | kPos, /*width = */ 0, "0"},
+      {0, kOct | kRight | kUpper | kPos, /*width = */ 6, "_____0"},
+      {0, kOct | kRight | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kOct | kRight | kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, "0"},
+      {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+      {0, kHex, /*width = */ 0, "0"},
+      {0, kHex, /*width = */ 6, "_____0"},
+      {0, kHex | kPos, /*width = */ 0, "0"},
+      {0, kHex | kPos, /*width = */ 6, "_____0"},
+      {0, kHex | kBase, /*width = */ 0, "0"},
+      {0, kHex | kBase, /*width = */ 6, "_____0"},
+      {0, kHex | kBase | kPos, /*width = */ 0, "0"},
+      {0, kHex | kBase | kPos, /*width = */ 6, "_____0"},
+      {0, kHex | kUpper, /*width = */ 0, "0"},
+      {0, kHex | kUpper, /*width = */ 6, "_____0"},
+      {0, kHex | kUpper | kPos, /*width = */ 0, "0"},
+      {0, kHex | kUpper | kPos, /*width = */ 6, "_____0"},
+      {0, kHex | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kHex | kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kHex | kUpper | kBase | kPos, /*width = */ 0, "0"},
+      {0, kHex | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+      {0, kHex | kLeft, /*width = */ 0, "0"},
+      {0, kHex | kLeft, /*width = */ 6, "0_____"},
+      {0, kHex | kLeft | kPos, /*width = */ 0, "0"},
+      {0, kHex | kLeft | kPos, /*width = */ 6, "0_____"},
+      {0, kHex | kLeft | kBase, /*width = */ 0, "0"},
+      {0, kHex | kLeft | kBase, /*width = */ 6, "0_____"},
+      {0, kHex | kLeft | kBase | kPos, /*width = */ 0, "0"},
+      {0, kHex | kLeft | kBase | kPos, /*width = */ 6, "0_____"},
+      {0, kHex | kLeft | kUpper, /*width = */ 0, "0"},
+      {0, kHex | kLeft | kUpper, /*width = */ 6, "0_____"},
+      {0, kHex | kLeft | kUpper | kPos, /*width = */ 0, "0"},
+      {0, kHex | kLeft | kUpper | kPos, /*width = */ 6, "0_____"},
+      {0, kHex | kLeft | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kHex | kLeft | kUpper | kBase, /*width = */ 6, "0_____"},
+      {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"},
+      {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"},
+      {0, kHex | kInt, /*width = */ 0, "0"},
+      {0, kHex | kInt, /*width = */ 6, "_____0"},
+      {0, kHex | kInt | kPos, /*width = */ 0, "0"},
+      {0, kHex | kInt | kPos, /*width = */ 6, "_____0"},
+      {0, kHex | kInt | kBase, /*width = */ 0, "0"},
+      {0, kHex | kInt | kBase, /*width = */ 6, "_____0"},
+      {0, kHex | kInt | kBase | kPos, /*width = */ 0, "0"},
+      {0, kHex | kInt | kBase | kPos, /*width = */ 6, "_____0"},
+      {0, kHex | kInt | kUpper, /*width = */ 0, "0"},
+      {0, kHex | kInt | kUpper, /*width = */ 6, "_____0"},
+      {0, kHex | kInt | kUpper | kPos, /*width = */ 0, "0"},
+      {0, kHex | kInt | kUpper | kPos, /*width = */ 6, "_____0"},
+      {0, kHex | kInt | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kHex | kInt | kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, "0"},
+      {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+      {0, kHex | kRight, /*width = */ 0, "0"},
+      {0, kHex | kRight, /*width = */ 6, "_____0"},
+      {0, kHex | kRight | kPos, /*width = */ 0, "0"},
+      {0, kHex | kRight | kPos, /*width = */ 6, "_____0"},
+      {0, kHex | kRight | kBase, /*width = */ 0, "0"},
+      {0, kHex | kRight | kBase, /*width = */ 6, "_____0"},
+      {0, kHex | kRight | kBase | kPos, /*width = */ 0, "0"},
+      {0, kHex | kRight | kBase | kPos, /*width = */ 6, "_____0"},
+      {0, kHex | kRight | kUpper, /*width = */ 0, "0"},
+      {0, kHex | kRight | kUpper, /*width = */ 6, "_____0"},
+      {0, kHex | kRight | kUpper | kPos, /*width = */ 0, "0"},
+      {0, kHex | kRight | kUpper | kPos, /*width = */ 6, "_____0"},
+      {0, kHex | kRight | kUpper | kBase, /*width = */ 0, "0"},
+      {0, kHex | kRight | kUpper | kBase, /*width = */ 6, "_____0"},
+      {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, "0"},
+      {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+      {42, std::ios_base::fmtflags(), /*width = */ 0, "42"},
+      {42, std::ios_base::fmtflags(), /*width = */ 6, "____42"},
+      {42, kPos, /*width = */ 0, "+42"},
+      {42, kPos, /*width = */ 6, "___+42"},
+      {42, kBase, /*width = */ 0, "42"},
+      {42, kBase, /*width = */ 6, "____42"},
+      {42, kBase | kPos, /*width = */ 0, "+42"},
+      {42, kBase | kPos, /*width = */ 6, "___+42"},
+      {42, kUpper, /*width = */ 0, "42"},
+      {42, kUpper, /*width = */ 6, "____42"},
+      {42, kUpper | kPos, /*width = */ 0, "+42"},
+      {42, kUpper | kPos, /*width = */ 6, "___+42"},
+      {42, kUpper | kBase, /*width = */ 0, "42"},
+      {42, kUpper | kBase, /*width = */ 6, "____42"},
+      {42, kUpper | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kUpper | kBase | kPos, /*width = */ 6, "___+42"},
+      {42, kLeft, /*width = */ 0, "42"},
+      {42, kLeft, /*width = */ 6, "42____"},
+      {42, kLeft | kPos, /*width = */ 0, "+42"},
+      {42, kLeft | kPos, /*width = */ 6, "+42___"},
+      {42, kLeft | kBase, /*width = */ 0, "42"},
+      {42, kLeft | kBase, /*width = */ 6, "42____"},
+      {42, kLeft | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kLeft | kBase | kPos, /*width = */ 6, "+42___"},
+      {42, kLeft | kUpper, /*width = */ 0, "42"},
+      {42, kLeft | kUpper, /*width = */ 6, "42____"},
+      {42, kLeft | kUpper | kPos, /*width = */ 0, "+42"},
+      {42, kLeft | kUpper | kPos, /*width = */ 6, "+42___"},
+      {42, kLeft | kUpper | kBase, /*width = */ 0, "42"},
+      {42, kLeft | kUpper | kBase, /*width = */ 6, "42____"},
+      {42, kLeft | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kLeft | kUpper | kBase | kPos, /*width = */ 6, "+42___"},
+      {42, kInt, /*width = */ 0, "42"},
+      {42, kInt, /*width = */ 6, "____42"},
+      {42, kInt | kPos, /*width = */ 0, "+42"},
+      {42, kInt | kPos, /*width = */ 6, "+___42"},
+      {42, kInt | kBase, /*width = */ 0, "42"},
+      {42, kInt | kBase, /*width = */ 6, "____42"},
+      {42, kInt | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kInt | kBase | kPos, /*width = */ 6, "+___42"},
+      {42, kInt | kUpper, /*width = */ 0, "42"},
+      {42, kInt | kUpper, /*width = */ 6, "____42"},
+      {42, kInt | kUpper | kPos, /*width = */ 0, "+42"},
+      {42, kInt | kUpper | kPos, /*width = */ 6, "+___42"},
+      {42, kInt | kUpper | kBase, /*width = */ 0, "42"},
+      {42, kInt | kUpper | kBase, /*width = */ 6, "____42"},
+      {42, kInt | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kInt | kUpper | kBase | kPos, /*width = */ 6, "+___42"},
+      {42, kRight, /*width = */ 0, "42"},
+      {42, kRight, /*width = */ 6, "____42"},
+      {42, kRight | kPos, /*width = */ 0, "+42"},
+      {42, kRight | kPos, /*width = */ 6, "___+42"},
+      {42, kRight | kBase, /*width = */ 0, "42"},
+      {42, kRight | kBase, /*width = */ 6, "____42"},
+      {42, kRight | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kRight | kBase | kPos, /*width = */ 6, "___+42"},
+      {42, kRight | kUpper, /*width = */ 0, "42"},
+      {42, kRight | kUpper, /*width = */ 6, "____42"},
+      {42, kRight | kUpper | kPos, /*width = */ 0, "+42"},
+      {42, kRight | kUpper | kPos, /*width = */ 6, "___+42"},
+      {42, kRight | kUpper | kBase, /*width = */ 0, "42"},
+      {42, kRight | kUpper | kBase, /*width = */ 6, "____42"},
+      {42, kRight | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kRight | kUpper | kBase | kPos, /*width = */ 6, "___+42"},
+      {42, kDec, /*width = */ 0, "42"},
+      {42, kDec, /*width = */ 6, "____42"},
+      {42, kDec | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kPos, /*width = */ 6, "___+42"},
+      {42, kDec | kBase, /*width = */ 0, "42"},
+      {42, kDec | kBase, /*width = */ 6, "____42"},
+      {42, kDec | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kBase | kPos, /*width = */ 6, "___+42"},
+      {42, kDec | kUpper, /*width = */ 0, "42"},
+      {42, kDec | kUpper, /*width = */ 6, "____42"},
+      {42, kDec | kUpper | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kUpper | kPos, /*width = */ 6, "___+42"},
+      {42, kDec | kUpper | kBase, /*width = */ 0, "42"},
+      {42, kDec | kUpper | kBase, /*width = */ 6, "____42"},
+      {42, kDec | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kUpper | kBase | kPos, /*width = */ 6, "___+42"},
+      {42, kDec | kLeft, /*width = */ 0, "42"},
+      {42, kDec | kLeft, /*width = */ 6, "42____"},
+      {42, kDec | kLeft | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kLeft | kPos, /*width = */ 6, "+42___"},
+      {42, kDec | kLeft | kBase, /*width = */ 0, "42"},
+      {42, kDec | kLeft | kBase, /*width = */ 6, "42____"},
+      {42, kDec | kLeft | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kLeft | kBase | kPos, /*width = */ 6, "+42___"},
+      {42, kDec | kLeft | kUpper, /*width = */ 0, "42"},
+      {42, kDec | kLeft | kUpper, /*width = */ 6, "42____"},
+      {42, kDec | kLeft | kUpper | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kLeft | kUpper | kPos, /*width = */ 6, "+42___"},
+      {42, kDec | kLeft | kUpper | kBase, /*width = */ 0, "42"},
+      {42, kDec | kLeft | kUpper | kBase, /*width = */ 6, "42____"},
+      {42, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "+42___"},
+      {42, kDec | kInt, /*width = */ 0, "42"},
+      {42, kDec | kInt, /*width = */ 6, "____42"},
+      {42, kDec | kInt | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kInt | kPos, /*width = */ 6, "+___42"},
+      {42, kDec | kInt | kBase, /*width = */ 0, "42"},
+      {42, kDec | kInt | kBase, /*width = */ 6, "____42"},
+      {42, kDec | kInt | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kInt | kBase | kPos, /*width = */ 6, "+___42"},
+      {42, kDec | kInt | kUpper, /*width = */ 0, "42"},
+      {42, kDec | kInt | kUpper, /*width = */ 6, "____42"},
+      {42, kDec | kInt | kUpper | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kInt | kUpper | kPos, /*width = */ 6, "+___42"},
+      {42, kDec | kInt | kUpper | kBase, /*width = */ 0, "42"},
+      {42, kDec | kInt | kUpper | kBase, /*width = */ 6, "____42"},
+      {42, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "+___42"},
+      {42, kDec | kRight, /*width = */ 0, "42"},
+      {42, kDec | kRight, /*width = */ 6, "____42"},
+      {42, kDec | kRight | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kRight | kPos, /*width = */ 6, "___+42"},
+      {42, kDec | kRight | kBase, /*width = */ 0, "42"},
+      {42, kDec | kRight | kBase, /*width = */ 6, "____42"},
+      {42, kDec | kRight | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kRight | kBase | kPos, /*width = */ 6, "___+42"},
+      {42, kDec | kRight | kUpper, /*width = */ 0, "42"},
+      {42, kDec | kRight | kUpper, /*width = */ 6, "____42"},
+      {42, kDec | kRight | kUpper | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kRight | kUpper | kPos, /*width = */ 6, "___+42"},
+      {42, kDec | kRight | kUpper | kBase, /*width = */ 0, "42"},
+      {42, kDec | kRight | kUpper | kBase, /*width = */ 6, "____42"},
+      {42, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+      {42, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "___+42"},
+      {42, kOct, /*width = */ 0, "52"},
+      {42, kOct, /*width = */ 6, "____52"},
+      {42, kOct | kPos, /*width = */ 0, "52"},
+      {42, kOct | kPos, /*width = */ 6, "____52"},
+      {42, kOct | kBase, /*width = */ 0, "052"},
+      {42, kOct | kBase, /*width = */ 6, "___052"},
+      {42, kOct | kBase | kPos, /*width = */ 0, "052"},
+      {42, kOct | kBase | kPos, /*width = */ 6, "___052"},
+      {42, kOct | kUpper, /*width = */ 0, "52"},
+      {42, kOct | kUpper, /*width = */ 6, "____52"},
+      {42, kOct | kUpper | kPos, /*width = */ 0, "52"},
+      {42, kOct | kUpper | kPos, /*width = */ 6, "____52"},
+      {42, kOct | kUpper | kBase, /*width = */ 0, "052"},
+      {42, kOct | kUpper | kBase, /*width = */ 6, "___052"},
+      {42, kOct | kUpper | kBase | kPos, /*width = */ 0, "052"},
+      {42, kOct | kUpper | kBase | kPos, /*width = */ 6, "___052"},
+      {42, kOct | kLeft, /*width = */ 0, "52"},
+      {42, kOct | kLeft, /*width = */ 6, "52____"},
+      {42, kOct | kLeft | kPos, /*width = */ 0, "52"},
+      {42, kOct | kLeft | kPos, /*width = */ 6, "52____"},
+      {42, kOct | kLeft | kBase, /*width = */ 0, "052"},
+      {42, kOct | kLeft | kBase, /*width = */ 6, "052___"},
+      {42, kOct | kLeft | kBase | kPos, /*width = */ 0, "052"},
+      {42, kOct | kLeft | kBase | kPos, /*width = */ 6, "052___"},
+      {42, kOct | kLeft | kUpper, /*width = */ 0, "52"},
+      {42, kOct | kLeft | kUpper, /*width = */ 6, "52____"},
+      {42, kOct | kLeft | kUpper | kPos, /*width = */ 0, "52"},
+      {42, kOct | kLeft | kUpper | kPos, /*width = */ 6, "52____"},
+      {42, kOct | kLeft | kUpper | kBase, /*width = */ 0, "052"},
+      {42, kOct | kLeft | kUpper | kBase, /*width = */ 6, "052___"},
+      {42, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, "052"},
+      {42, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, "052___"},
+      {42, kOct | kInt, /*width = */ 0, "52"},
+      {42, kOct | kInt, /*width = */ 6, "____52"},
+      {42, kOct | kInt | kPos, /*width = */ 0, "52"},
+      {42, kOct | kInt | kPos, /*width = */ 6, "____52"},
+      {42, kOct | kInt | kBase, /*width = */ 0, "052"},
+      {42, kOct | kInt | kBase, /*width = */ 6, "___052"},
+      {42, kOct | kInt | kBase | kPos, /*width = */ 0, "052"},
+      {42, kOct | kInt | kBase | kPos, /*width = */ 6, "___052"},
+      {42, kOct | kInt | kUpper, /*width = */ 0, "52"},
+      {42, kOct | kInt | kUpper, /*width = */ 6, "____52"},
+      {42, kOct | kInt | kUpper | kPos, /*width = */ 0, "52"},
+      {42, kOct | kInt | kUpper | kPos, /*width = */ 6, "____52"},
+      {42, kOct | kInt | kUpper | kBase, /*width = */ 0, "052"},
+      {42, kOct | kInt | kUpper | kBase, /*width = */ 6, "___052"},
+      {42, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, "052"},
+      {42, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, "___052"},
+      {42, kOct | kRight, /*width = */ 0, "52"},
+      {42, kOct | kRight, /*width = */ 6, "____52"},
+      {42, kOct | kRight | kPos, /*width = */ 0, "52"},
+      {42, kOct | kRight | kPos, /*width = */ 6, "____52"},
+      {42, kOct | kRight | kBase, /*width = */ 0, "052"},
+      {42, kOct | kRight | kBase, /*width = */ 6, "___052"},
+      {42, kOct | kRight | kBase | kPos, /*width = */ 0, "052"},
+      {42, kOct | kRight | kBase | kPos, /*width = */ 6, "___052"},
+      {42, kOct | kRight | kUpper, /*width = */ 0, "52"},
+      {42, kOct | kRight | kUpper, /*width = */ 6, "____52"},
+      {42, kOct | kRight | kUpper | kPos, /*width = */ 0, "52"},
+      {42, kOct | kRight | kUpper | kPos, /*width = */ 6, "____52"},
+      {42, kOct | kRight | kUpper | kBase, /*width = */ 0, "052"},
+      {42, kOct | kRight | kUpper | kBase, /*width = */ 6, "___052"},
+      {42, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, "052"},
+      {42, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, "___052"},
+      {42, kHex, /*width = */ 0, "2a"},
+      {42, kHex, /*width = */ 6, "____2a"},
+      {42, kHex | kPos, /*width = */ 0, "2a"},
+      {42, kHex | kPos, /*width = */ 6, "____2a"},
+      {42, kHex | kBase, /*width = */ 0, "0x2a"},
+      {42, kHex | kBase, /*width = */ 6, "__0x2a"},
+      {42, kHex | kBase | kPos, /*width = */ 0, "0x2a"},
+      {42, kHex | kBase | kPos, /*width = */ 6, "__0x2a"},
+      {42, kHex | kUpper, /*width = */ 0, "2A"},
+      {42, kHex | kUpper, /*width = */ 6, "____2A"},
+      {42, kHex | kUpper | kPos, /*width = */ 0, "2A"},
+      {42, kHex | kUpper | kPos, /*width = */ 6, "____2A"},
+      {42, kHex | kUpper | kBase, /*width = */ 0, "0X2A"},
+      {42, kHex | kUpper | kBase, /*width = */ 6, "__0X2A"},
+      {42, kHex | kUpper | kBase | kPos, /*width = */ 0, "0X2A"},
+      {42, kHex | kUpper | kBase | kPos, /*width = */ 6, "__0X2A"},
+      {42, kHex | kLeft, /*width = */ 0, "2a"},
+      {42, kHex | kLeft, /*width = */ 6, "2a____"},
+      {42, kHex | kLeft | kPos, /*width = */ 0, "2a"},
+      {42, kHex | kLeft | kPos, /*width = */ 6, "2a____"},
+      {42, kHex | kLeft | kBase, /*width = */ 0, "0x2a"},
+      {42, kHex | kLeft | kBase, /*width = */ 6, "0x2a__"},
+      {42, kHex | kLeft | kBase | kPos, /*width = */ 0, "0x2a"},
+      {42, kHex | kLeft | kBase | kPos, /*width = */ 6, "0x2a__"},
+      {42, kHex | kLeft | kUpper, /*width = */ 0, "2A"},
+      {42, kHex | kLeft | kUpper, /*width = */ 6, "2A____"},
+      {42, kHex | kLeft | kUpper | kPos, /*width = */ 0, "2A"},
+      {42, kHex | kLeft | kUpper | kPos, /*width = */ 6, "2A____"},
+      {42, kHex | kLeft | kUpper | kBase, /*width = */ 0, "0X2A"},
+      {42, kHex | kLeft | kUpper | kBase, /*width = */ 6, "0X2A__"},
+      {42, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0X2A"},
+      {42, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0X2A__"},
+      {42, kHex | kInt, /*width = */ 0, "2a"},
+      {42, kHex | kInt, /*width = */ 6, "____2a"},
+      {42, kHex | kInt | kPos, /*width = */ 0, "2a"},
+      {42, kHex | kInt | kPos, /*width = */ 6, "____2a"},
+      {42, kHex | kInt | kBase, /*width = */ 0, "0x2a"},
+      {42, kHex | kInt | kBase, /*width = */ 6, "0x__2a"},
+      {42, kHex | kInt | kBase | kPos, /*width = */ 0, "0x2a"},
+      {42, kHex | kInt | kBase | kPos, /*width = */ 6, "0x__2a"},
+      {42, kHex | kInt | kUpper, /*width = */ 0, "2A"},
+      {42, kHex | kInt | kUpper, /*width = */ 6, "____2A"},
+      {42, kHex | kInt | kUpper | kPos, /*width = */ 0, "2A"},
+      {42, kHex | kInt | kUpper | kPos, /*width = */ 6, "____2A"},
+      {42, kHex | kInt | kUpper | kBase, /*width = */ 0, "0X2A"},
+      {42, kHex | kInt | kUpper | kBase, /*width = */ 6, "0X__2A"},
+      {42, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, "0X2A"},
+      {42, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, "0X__2A"},
+      {42, kHex | kRight, /*width = */ 0, "2a"},
+      {42, kHex | kRight, /*width = */ 6, "____2a"},
+      {42, kHex | kRight | kPos, /*width = */ 0, "2a"},
+      {42, kHex | kRight | kPos, /*width = */ 6, "____2a"},
+      {42, kHex | kRight | kBase, /*width = */ 0, "0x2a"},
+      {42, kHex | kRight | kBase, /*width = */ 6, "__0x2a"},
+      {42, kHex | kRight | kBase | kPos, /*width = */ 0, "0x2a"},
+      {42, kHex | kRight | kBase | kPos, /*width = */ 6, "__0x2a"},
+      {42, kHex | kRight | kUpper, /*width = */ 0, "2A"},
+      {42, kHex | kRight | kUpper, /*width = */ 6, "____2A"},
+      {42, kHex | kRight | kUpper | kPos, /*width = */ 0, "2A"},
+      {42, kHex | kRight | kUpper | kPos, /*width = */ 6, "____2A"},
+      {42, kHex | kRight | kUpper | kBase, /*width = */ 0, "0X2A"},
+      {42, kHex | kRight | kUpper | kBase, /*width = */ 6, "__0X2A"},
+      {42, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, "0X2A"},
+      {42, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, "__0X2A"},
+      {-321, std::ios_base::fmtflags(), /*width = */ 0, "-321"},
+      {-321, std::ios_base::fmtflags(), /*width = */ 6, "__-321"},
+      {-321, kPos, /*width = */ 0, "-321"},
+      {-321, kPos, /*width = */ 6, "__-321"},
+      {-321, kBase, /*width = */ 0, "-321"},
+      {-321, kBase, /*width = */ 6, "__-321"},
+      {-321, kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kBase | kPos, /*width = */ 6, "__-321"},
+      {-321, kUpper, /*width = */ 0, "-321"},
+      {-321, kUpper, /*width = */ 6, "__-321"},
+      {-321, kUpper | kPos, /*width = */ 0, "-321"},
+      {-321, kUpper | kPos, /*width = */ 6, "__-321"},
+      {-321, kUpper | kBase, /*width = */ 0, "-321"},
+      {-321, kUpper | kBase, /*width = */ 6, "__-321"},
+      {-321, kUpper | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kUpper | kBase | kPos, /*width = */ 6, "__-321"},
+      {-321, kLeft, /*width = */ 0, "-321"},
+      {-321, kLeft, /*width = */ 6, "-321__"},
+      {-321, kLeft | kPos, /*width = */ 0, "-321"},
+      {-321, kLeft | kPos, /*width = */ 6, "-321__"},
+      {-321, kLeft | kBase, /*width = */ 0, "-321"},
+      {-321, kLeft | kBase, /*width = */ 6, "-321__"},
+      {-321, kLeft | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kLeft | kBase | kPos, /*width = */ 6, "-321__"},
+      {-321, kLeft | kUpper, /*width = */ 0, "-321"},
+      {-321, kLeft | kUpper, /*width = */ 6, "-321__"},
+      {-321, kLeft | kUpper | kPos, /*width = */ 0, "-321"},
+      {-321, kLeft | kUpper | kPos, /*width = */ 6, "-321__"},
+      {-321, kLeft | kUpper | kBase, /*width = */ 0, "-321"},
+      {-321, kLeft | kUpper | kBase, /*width = */ 6, "-321__"},
+      {-321, kLeft | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kLeft | kUpper | kBase | kPos, /*width = */ 6, "-321__"},
+      {-321, kInt, /*width = */ 0, "-321"},
+      {-321, kInt, /*width = */ 6, "-__321"},
+      {-321, kInt | kPos, /*width = */ 0, "-321"},
+      {-321, kInt | kPos, /*width = */ 6, "-__321"},
+      {-321, kInt | kBase, /*width = */ 0, "-321"},
+      {-321, kInt | kBase, /*width = */ 6, "-__321"},
+      {-321, kInt | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kInt | kBase | kPos, /*width = */ 6, "-__321"},
+      {-321, kInt | kUpper, /*width = */ 0, "-321"},
+      {-321, kInt | kUpper, /*width = */ 6, "-__321"},
+      {-321, kInt | kUpper | kPos, /*width = */ 0, "-321"},
+      {-321, kInt | kUpper | kPos, /*width = */ 6, "-__321"},
+      {-321, kInt | kUpper | kBase, /*width = */ 0, "-321"},
+      {-321, kInt | kUpper | kBase, /*width = */ 6, "-__321"},
+      {-321, kInt | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kInt | kUpper | kBase | kPos, /*width = */ 6, "-__321"},
+      {-321, kRight, /*width = */ 0, "-321"},
+      {-321, kRight, /*width = */ 6, "__-321"},
+      {-321, kRight | kPos, /*width = */ 0, "-321"},
+      {-321, kRight | kPos, /*width = */ 6, "__-321"},
+      {-321, kRight | kBase, /*width = */ 0, "-321"},
+      {-321, kRight | kBase, /*width = */ 6, "__-321"},
+      {-321, kRight | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kRight | kBase | kPos, /*width = */ 6, "__-321"},
+      {-321, kRight | kUpper, /*width = */ 0, "-321"},
+      {-321, kRight | kUpper, /*width = */ 6, "__-321"},
+      {-321, kRight | kUpper | kPos, /*width = */ 0, "-321"},
+      {-321, kRight | kUpper | kPos, /*width = */ 6, "__-321"},
+      {-321, kRight | kUpper | kBase, /*width = */ 0, "-321"},
+      {-321, kRight | kUpper | kBase, /*width = */ 6, "__-321"},
+      {-321, kRight | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kRight | kUpper | kBase | kPos, /*width = */ 6, "__-321"},
+      {-321, kDec, /*width = */ 0, "-321"},
+      {-321, kDec, /*width = */ 6, "__-321"},
+      {-321, kDec | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kPos, /*width = */ 6, "__-321"},
+      {-321, kDec | kBase, /*width = */ 0, "-321"},
+      {-321, kDec | kBase, /*width = */ 6, "__-321"},
+      {-321, kDec | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kBase | kPos, /*width = */ 6, "__-321"},
+      {-321, kDec | kUpper, /*width = */ 0, "-321"},
+      {-321, kDec | kUpper, /*width = */ 6, "__-321"},
+      {-321, kDec | kUpper | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kUpper | kPos, /*width = */ 6, "__-321"},
+      {-321, kDec | kUpper | kBase, /*width = */ 0, "-321"},
+      {-321, kDec | kUpper | kBase, /*width = */ 6, "__-321"},
+      {-321, kDec | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kUpper | kBase | kPos, /*width = */ 6, "__-321"},
+      {-321, kDec | kLeft, /*width = */ 0, "-321"},
+      {-321, kDec | kLeft, /*width = */ 6, "-321__"},
+      {-321, kDec | kLeft | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kLeft | kPos, /*width = */ 6, "-321__"},
+      {-321, kDec | kLeft | kBase, /*width = */ 0, "-321"},
+      {-321, kDec | kLeft | kBase, /*width = */ 6, "-321__"},
+      {-321, kDec | kLeft | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kLeft | kBase | kPos, /*width = */ 6, "-321__"},
+      {-321, kDec | kLeft | kUpper, /*width = */ 0, "-321"},
+      {-321, kDec | kLeft | kUpper, /*width = */ 6, "-321__"},
+      {-321, kDec | kLeft | kUpper | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kLeft | kUpper | kPos, /*width = */ 6, "-321__"},
+      {-321, kDec | kLeft | kUpper | kBase, /*width = */ 0, "-321"},
+      {-321, kDec | kLeft | kUpper | kBase, /*width = */ 6, "-321__"},
+      {-321, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "-321__"},
+      {-321, kDec | kInt, /*width = */ 0, "-321"},
+      {-321, kDec | kInt, /*width = */ 6, "-__321"},
+      {-321, kDec | kInt | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kInt | kPos, /*width = */ 6, "-__321"},
+      {-321, kDec | kInt | kBase, /*width = */ 0, "-321"},
+      {-321, kDec | kInt | kBase, /*width = */ 6, "-__321"},
+      {-321, kDec | kInt | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kInt | kBase | kPos, /*width = */ 6, "-__321"},
+      {-321, kDec | kInt | kUpper, /*width = */ 0, "-321"},
+      {-321, kDec | kInt | kUpper, /*width = */ 6, "-__321"},
+      {-321, kDec | kInt | kUpper | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kInt | kUpper | kPos, /*width = */ 6, "-__321"},
+      {-321, kDec | kInt | kUpper | kBase, /*width = */ 0, "-321"},
+      {-321, kDec | kInt | kUpper | kBase, /*width = */ 6, "-__321"},
+      {-321, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "-__321"},
+      {-321, kDec | kRight, /*width = */ 0, "-321"},
+      {-321, kDec | kRight, /*width = */ 6, "__-321"},
+      {-321, kDec | kRight | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kRight | kPos, /*width = */ 6, "__-321"},
+      {-321, kDec | kRight | kBase, /*width = */ 0, "-321"},
+      {-321, kDec | kRight | kBase, /*width = */ 6, "__-321"},
+      {-321, kDec | kRight | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kRight | kBase | kPos, /*width = */ 6, "__-321"},
+      {-321, kDec | kRight | kUpper, /*width = */ 0, "-321"},
+      {-321, kDec | kRight | kUpper, /*width = */ 6, "__-321"},
+      {-321, kDec | kRight | kUpper | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kRight | kUpper | kPos, /*width = */ 6, "__-321"},
+      {-321, kDec | kRight | kUpper | kBase, /*width = */ 0, "-321"},
+      {-321, kDec | kRight | kUpper | kBase, /*width = */ 6, "__-321"},
+      {-321, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+      {-321, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "__-321"}};
+}
+
 std::vector<Uint128TestCase> GetUint128FormatCases() {
   return {
       {0, std::ios_base::fmtflags(), /*width = */ 0, "0"},
diff --git a/absl/numeric/int128_test.cc b/absl/numeric/int128_test.cc
index 5e1b5ec..bc86c71 100644
--- a/absl/numeric/int128_test.cc
+++ b/absl/numeric/int128_test.cc
@@ -479,4 +479,747 @@
   }));
 }
 
+
+TEST(Int128Uint128, ConversionTest) {
+  absl::int128 nonnegative_signed_values[] = {
+      0,
+      1,
+      0xffeeddccbbaa9988,
+      absl::MakeInt128(0x7766554433221100, 0),
+      absl::MakeInt128(0x1234567890abcdef, 0xfedcba0987654321),
+      absl::Int128Max()};
+  for (absl::int128 value : nonnegative_signed_values) {
+    EXPECT_EQ(value, absl::int128(absl::uint128(value)));
+
+    absl::uint128 assigned_value;
+    assigned_value = value;
+    EXPECT_EQ(value, absl::int128(assigned_value));
+  }
+
+  absl::int128 negative_values[] = {
+      -1, -0x1234567890abcdef,
+      absl::MakeInt128(-0x5544332211ffeedd, 0),
+      -absl::MakeInt128(0x76543210fedcba98, 0xabcdef0123456789)};
+  for (absl::int128 value : negative_values) {
+    EXPECT_EQ(absl::uint128(-value), -absl::uint128(value));
+
+    absl::uint128 assigned_value;
+    assigned_value = value;
+    EXPECT_EQ(absl::uint128(-value), -assigned_value);
+  }
+}
+
+template <typename T>
+class Int128IntegerTraitsTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE(Int128IntegerTraitsTest, IntegerTypes);
+
+TYPED_TEST(Int128IntegerTraitsTest, ConstructAssignTest) {
+  static_assert(std::is_constructible<absl::int128, TypeParam>::value,
+                "absl::int128 must be constructible from TypeParam");
+  static_assert(std::is_assignable<absl::int128&, TypeParam>::value,
+                "absl::int128 must be assignable from TypeParam");
+  static_assert(!std::is_assignable<TypeParam&, absl::int128>::value,
+                "TypeParam must not be assignable from absl::int128");
+}
+
+template <typename T>
+class Int128FloatTraitsTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE(Int128FloatTraitsTest, FloatingPointTypes);
+
+TYPED_TEST(Int128FloatTraitsTest, ConstructAssignTest) {
+  static_assert(std::is_constructible<absl::int128, TypeParam>::value,
+                "absl::int128 must be constructible from TypeParam");
+  static_assert(!std::is_assignable<absl::int128&, TypeParam>::value,
+                "absl::int128 must not be assignable from TypeParam");
+  static_assert(!std::is_assignable<TypeParam&, absl::int128>::value,
+                "TypeParam must not be assignable from absl::int128");
+}
+
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+// These type traits done separately as TYPED_TEST requires typeinfo, and not
+// all platforms have this for __int128 even though they define the type.
+TEST(Int128, IntrinsicTypeTraitsTest) {
+  static_assert(std::is_constructible<absl::int128, __int128>::value,
+                "absl::int128 must be constructible from __int128");
+  static_assert(std::is_assignable<absl::int128&, __int128>::value,
+                "absl::int128 must be assignable from __int128");
+  static_assert(!std::is_assignable<__int128&, absl::int128>::value,
+                "__int128 must not be assignable from absl::int128");
+
+  static_assert(std::is_constructible<absl::int128, unsigned __int128>::value,
+                "absl::int128 must be constructible from unsigned __int128");
+  static_assert(!std::is_assignable<absl::int128&, unsigned __int128>::value,
+                "absl::int128 must be assignable from unsigned __int128");
+  static_assert(!std::is_assignable<unsigned __int128&, absl::int128>::value,
+                "unsigned __int128 must not be assignable from absl::int128");
+}
+#endif  // ABSL_HAVE_INTRINSIC_INT128
+
+TEST(Int128, TrivialTraitsTest) {
+  static_assert(absl::is_trivially_default_constructible<absl::int128>::value,
+                "");
+  static_assert(absl::is_trivially_copy_constructible<absl::int128>::value, "");
+  static_assert(absl::is_trivially_copy_assignable<absl::int128>::value, "");
+  static_assert(std::is_trivially_destructible<absl::int128>::value, "");
+}
+
+TEST(Int128, BoolConversionTest) {
+  EXPECT_FALSE(absl::int128(0));
+  for (int i = 0; i < 64; ++i) {
+    EXPECT_TRUE(absl::MakeInt128(0, uint64_t{1} << i));
+  }
+  for (int i = 0; i < 63; ++i) {
+    EXPECT_TRUE(absl::MakeInt128(int64_t{1} << i, 0));
+  }
+  EXPECT_TRUE(absl::Int128Min());
+
+  EXPECT_EQ(absl::int128(1), absl::int128(true));
+  EXPECT_EQ(absl::int128(0), absl::int128(false));
+}
+
+template <typename T>
+class Int128IntegerConversionTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE(Int128IntegerConversionTest, IntegerTypes);
+
+TYPED_TEST(Int128IntegerConversionTest, RoundTripTest) {
+  EXPECT_EQ(TypeParam{0}, static_cast<TypeParam>(absl::int128(0)));
+  EXPECT_EQ(std::numeric_limits<TypeParam>::min(),
+            static_cast<TypeParam>(
+                absl::int128(std::numeric_limits<TypeParam>::min())));
+  EXPECT_EQ(std::numeric_limits<TypeParam>::max(),
+            static_cast<TypeParam>(
+                absl::int128(std::numeric_limits<TypeParam>::max())));
+}
+
+template <typename T>
+class Int128FloatConversionTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE(Int128FloatConversionTest, FloatingPointTypes);
+
+TYPED_TEST(Int128FloatConversionTest, ConstructAndCastTest) {
+  // Conversions where the floating point values should be exactly the same.
+  // 0x9f5b is a randomly chosen small value.
+  for (int i = 0; i < 110; ++i) {  // 110 = 126 - #bits in 0x9f5b
+    SCOPED_TRACE(::testing::Message() << "i = " << i);
+
+    TypeParam float_value = std::ldexp(static_cast<TypeParam>(0x9f5b), i);
+    absl::int128 int_value = absl::int128(0x9f5b) << i;
+
+    EXPECT_EQ(float_value, static_cast<TypeParam>(int_value));
+    EXPECT_EQ(-float_value, static_cast<TypeParam>(-int_value));
+    EXPECT_EQ(int_value, absl::int128(float_value));
+    EXPECT_EQ(-int_value, absl::int128(-float_value));
+  }
+
+  // Round trip conversions with a small sample of randomly generated uint64_t
+  // values (less than int64_t max so that value * 2^64 fits into int128).
+  uint64_t values[] = {0x6d4492c24fb86199, 0x26ead65e4cb359b5,
+                       0x2c43407433ba3fd1, 0x3b574ec668df6b55,
+                       0x1c750e55a29f4f0f};
+  for (uint64_t value : values) {
+    for (int i = 0; i <= 64; ++i) {
+      SCOPED_TRACE(::testing::Message()
+                   << "value = " << value << "; i = " << i);
+
+      TypeParam fvalue = std::ldexp(static_cast<TypeParam>(value), i);
+      EXPECT_DOUBLE_EQ(fvalue, static_cast<TypeParam>(absl::int128(fvalue)));
+      EXPECT_DOUBLE_EQ(-fvalue, static_cast<TypeParam>(-absl::int128(fvalue)));
+      EXPECT_DOUBLE_EQ(-fvalue, static_cast<TypeParam>(absl::int128(-fvalue)));
+      EXPECT_DOUBLE_EQ(fvalue, static_cast<TypeParam>(-absl::int128(-fvalue)));
+    }
+  }
+
+  // Round trip conversions with a small sample of random large positive values.
+  absl::int128 large_values[] = {
+      absl::MakeInt128(0x5b0640d96c7b3d9f, 0xb7a7189e51d18622),
+      absl::MakeInt128(0x34bed042c6f65270, 0x73b236570669a089),
+      absl::MakeInt128(0x43deba9e6da12724, 0xf7f0f83da686797d),
+      absl::MakeInt128(0x71e8d383be4e5589, 0x75c3f96fb00752b6)};
+  for (absl::int128 value : large_values) {
+    // Make value have as many significant bits as can be represented by
+    // the mantissa, also making sure the highest and lowest bit in the range
+    // are set.
+    value >>= (127 - std::numeric_limits<TypeParam>::digits);
+    value |= absl::int128(1) << (std::numeric_limits<TypeParam>::digits - 1);
+    value |= 1;
+    for (int i = 0; i < 127 - std::numeric_limits<TypeParam>::digits; ++i) {
+      absl::int128 int_value = value << i;
+      EXPECT_EQ(int_value,
+                static_cast<absl::int128>(static_cast<TypeParam>(int_value)));
+      EXPECT_EQ(-int_value,
+                static_cast<absl::int128>(static_cast<TypeParam>(-int_value)));
+    }
+  }
+
+  // Small sample of checks that rounding is toward zero
+  EXPECT_EQ(0, absl::int128(TypeParam(0.1)));
+  EXPECT_EQ(17, absl::int128(TypeParam(17.8)));
+  EXPECT_EQ(0, absl::int128(TypeParam(-0.8)));
+  EXPECT_EQ(-53, absl::int128(TypeParam(-53.1)));
+  EXPECT_EQ(0, absl::int128(TypeParam(0.5)));
+  EXPECT_EQ(0, absl::int128(TypeParam(-0.5)));
+  TypeParam just_lt_one = std::nexttoward(TypeParam(1), TypeParam(0));
+  EXPECT_EQ(0, absl::int128(just_lt_one));
+  TypeParam just_gt_minus_one = std::nexttoward(TypeParam(-1), TypeParam(0));
+  EXPECT_EQ(0, absl::int128(just_gt_minus_one));
+
+  // Check limits
+  EXPECT_DOUBLE_EQ(std::ldexp(static_cast<TypeParam>(1), 127),
+                   static_cast<TypeParam>(absl::Int128Max()));
+  EXPECT_DOUBLE_EQ(-std::ldexp(static_cast<TypeParam>(1), 127),
+                   static_cast<TypeParam>(absl::Int128Min()));
+}
+
+TEST(Int128, FactoryTest) {
+  EXPECT_EQ(absl::int128(-1), absl::MakeInt128(-1, -1));
+  EXPECT_EQ(absl::int128(-31), absl::MakeInt128(-1, -31));
+  EXPECT_EQ(absl::int128(std::numeric_limits<int64_t>::min()),
+            absl::MakeInt128(-1, std::numeric_limits<int64_t>::min()));
+  EXPECT_EQ(absl::int128(0), absl::MakeInt128(0, 0));
+  EXPECT_EQ(absl::int128(1), absl::MakeInt128(0, 1));
+  EXPECT_EQ(absl::int128(std::numeric_limits<int64_t>::max()),
+            absl::MakeInt128(0, std::numeric_limits<int64_t>::max()));
+}
+
+TEST(Int128, HighLowTest) {
+  struct HighLowPair {
+    int64_t high;
+    uint64_t low;
+  };
+  HighLowPair values[]{{0, 0}, {0, 1}, {1, 0}, {123, 456}, {-654, 321}};
+  for (const HighLowPair& pair : values) {
+    absl::int128 value = absl::MakeInt128(pair.high, pair.low);
+    EXPECT_EQ(pair.low, absl::Int128Low64(value));
+    EXPECT_EQ(pair.high, absl::Int128High64(value));
+  }
+}
+
+TEST(Int128, LimitsTest) {
+  EXPECT_EQ(absl::MakeInt128(0x7fffffffffffffff, 0xffffffffffffffff),
+            absl::Int128Max());
+  EXPECT_EQ(absl::Int128Max(), ~absl::Int128Min());
+}
+
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+TEST(Int128, IntrinsicConversionTest) {
+  __int128 intrinsic =
+      (static_cast<__int128>(0x3a5b76c209de76f6) << 64) + 0x1f25e1d63a2b46c5;
+  absl::int128 custom =
+      absl::MakeInt128(0x3a5b76c209de76f6, 0x1f25e1d63a2b46c5);
+
+  EXPECT_EQ(custom, absl::int128(intrinsic));
+  EXPECT_EQ(intrinsic, static_cast<__int128>(custom));
+}
+#endif  // ABSL_HAVE_INTRINSIC_INT128
+
+TEST(Int128, ConstexprTest) {
+  constexpr absl::int128 zero = absl::int128();
+  constexpr absl::int128 one = 1;
+  constexpr absl::int128 minus_two = -2;
+  constexpr absl::int128 min = absl::Int128Min();
+  constexpr absl::int128 max = absl::Int128Max();
+  EXPECT_EQ(zero, absl::int128(0));
+  EXPECT_EQ(one, absl::int128(1));
+  EXPECT_EQ(minus_two, absl::MakeInt128(-1, -2));
+  EXPECT_GT(max, one);
+  EXPECT_LT(min, minus_two);
+}
+
+TEST(Int128, ComparisonTest) {
+  struct TestCase {
+    absl::int128 smaller;
+    absl::int128 larger;
+  };
+  TestCase cases[] = {
+      {absl::int128(0), absl::int128(123)},
+      {absl::MakeInt128(-12, 34), absl::MakeInt128(12, 34)},
+      {absl::MakeInt128(1, 1000), absl::MakeInt128(1000, 1)},
+      {absl::MakeInt128(-1000, 1000), absl::MakeInt128(-1, 1)},
+  };
+  for (const TestCase& pair : cases) {
+    SCOPED_TRACE(::testing::Message() << "pair.smaller = " << pair.smaller
+                                      << "; pair.larger = " << pair.larger);
+
+    EXPECT_TRUE(pair.smaller == pair.smaller);  // NOLINT(readability/check)
+    EXPECT_TRUE(pair.larger == pair.larger);    // NOLINT(readability/check)
+    EXPECT_FALSE(pair.smaller == pair.larger);  // NOLINT(readability/check)
+
+    EXPECT_TRUE(pair.smaller != pair.larger);    // NOLINT(readability/check)
+    EXPECT_FALSE(pair.smaller != pair.smaller);  // NOLINT(readability/check)
+    EXPECT_FALSE(pair.larger != pair.larger);    // NOLINT(readability/check)
+
+    EXPECT_TRUE(pair.smaller < pair.larger);   // NOLINT(readability/check)
+    EXPECT_FALSE(pair.larger < pair.smaller);  // NOLINT(readability/check)
+
+    EXPECT_TRUE(pair.larger > pair.smaller);   // NOLINT(readability/check)
+    EXPECT_FALSE(pair.smaller > pair.larger);  // NOLINT(readability/check)
+
+    EXPECT_TRUE(pair.smaller <= pair.larger);   // NOLINT(readability/check)
+    EXPECT_FALSE(pair.larger <= pair.smaller);  // NOLINT(readability/check)
+    EXPECT_TRUE(pair.smaller <= pair.smaller);  // NOLINT(readability/check)
+    EXPECT_TRUE(pair.larger <= pair.larger);    // NOLINT(readability/check)
+
+    EXPECT_TRUE(pair.larger >= pair.smaller);   // NOLINT(readability/check)
+    EXPECT_FALSE(pair.smaller >= pair.larger);  // NOLINT(readability/check)
+    EXPECT_TRUE(pair.smaller >= pair.smaller);  // NOLINT(readability/check)
+    EXPECT_TRUE(pair.larger >= pair.larger);    // NOLINT(readability/check)
+  }
+}
+
+TEST(Int128, UnaryNegationTest) {
+  int64_t values64[] = {0, 1, 12345, 0x4000000000000000,
+                        std::numeric_limits<int64_t>::max()};
+  for (int64_t value : values64) {
+    SCOPED_TRACE(::testing::Message() << "value = " << value);
+
+    EXPECT_EQ(absl::int128(-value), -absl::int128(value));
+    EXPECT_EQ(absl::int128(value), -absl::int128(-value));
+    EXPECT_EQ(absl::MakeInt128(-value, 0), -absl::MakeInt128(value, 0));
+    EXPECT_EQ(absl::MakeInt128(value, 0), -absl::MakeInt128(-value, 0));
+  }
+}
+
+TEST(Int128, LogicalNotTest) {
+  EXPECT_TRUE(!absl::int128(0));
+  for (int i = 0; i < 64; ++i) {
+    EXPECT_FALSE(!absl::MakeInt128(0, uint64_t{1} << i));
+  }
+  for (int i = 0; i < 63; ++i) {
+    EXPECT_FALSE(!absl::MakeInt128(int64_t{1} << i, 0));
+  }
+}
+
+TEST(Int128, AdditionSubtractionTest) {
+  // 64 bit pairs that will not cause overflow / underflow. These test negative
+  // carry; positive carry must be checked separately.
+  std::pair<int64_t, int64_t> cases[]{
+      {0, 0},                              // 0, 0
+      {0, 2945781290834},                  // 0, +
+      {1908357619234, 0},                  // +, 0
+      {0, -1204895918245},                 // 0, -
+      {-2957928523560, 0},                 // -, 0
+      {89023982312461, 98346012567134},    // +, +
+      {-63454234568239, -23456235230773},  // -, -
+      {98263457263502, -21428561935925},   // +, -
+      {-88235237438467, 15923659234573},   // -, +
+  };
+  for (const auto& pair : cases) {
+    SCOPED_TRACE(::testing::Message()
+                 << "pair = {" << pair.first << ", " << pair.second << '}');
+
+    EXPECT_EQ(absl::int128(pair.first + pair.second),
+              absl::int128(pair.first) + absl::int128(pair.second));
+    EXPECT_EQ(absl::int128(pair.second + pair.first),
+              absl::int128(pair.second) += absl::int128(pair.first));
+
+    EXPECT_EQ(absl::int128(pair.first - pair.second),
+              absl::int128(pair.first) - absl::int128(pair.second));
+    EXPECT_EQ(absl::int128(pair.second - pair.first),
+              absl::int128(pair.second) -= absl::int128(pair.first));
+
+    EXPECT_EQ(
+        absl::MakeInt128(pair.second + pair.first, 0),
+        absl::MakeInt128(pair.second, 0) + absl::MakeInt128(pair.first, 0));
+    EXPECT_EQ(
+        absl::MakeInt128(pair.first + pair.second, 0),
+        absl::MakeInt128(pair.first, 0) += absl::MakeInt128(pair.second, 0));
+
+    EXPECT_EQ(
+        absl::MakeInt128(pair.second - pair.first, 0),
+        absl::MakeInt128(pair.second, 0) - absl::MakeInt128(pair.first, 0));
+    EXPECT_EQ(
+        absl::MakeInt128(pair.first - pair.second, 0),
+        absl::MakeInt128(pair.first, 0) -= absl::MakeInt128(pair.second, 0));
+  }
+
+  // check positive carry
+  EXPECT_EQ(absl::MakeInt128(31, 0),
+            absl::MakeInt128(20, 1) +
+                absl::MakeInt128(10, std::numeric_limits<uint64_t>::max()));
+}
+
+TEST(Int128, IncrementDecrementTest) {
+  absl::int128 value = 0;
+  EXPECT_EQ(0, value++);
+  EXPECT_EQ(1, value);
+  EXPECT_EQ(1, value--);
+  EXPECT_EQ(0, value);
+  EXPECT_EQ(-1, --value);
+  EXPECT_EQ(-1, value);
+  EXPECT_EQ(0, ++value);
+  EXPECT_EQ(0, value);
+}
+
+TEST(Int128, MultiplicationTest) {
+  // 1 bit x 1 bit, and negative combinations
+  for (int i = 0; i < 64; ++i) {
+    for (int j = 0; j < 127 - i; ++j) {
+      SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+      absl::int128 a = absl::int128(1) << i;
+      absl::int128 b = absl::int128(1) << j;
+      absl::int128 c = absl::int128(1) << (i + j);
+
+      EXPECT_EQ(c, a * b);
+      EXPECT_EQ(-c, -a * b);
+      EXPECT_EQ(-c, a * -b);
+      EXPECT_EQ(c, -a * -b);
+
+      EXPECT_EQ(c, absl::int128(a) *= b);
+      EXPECT_EQ(-c, absl::int128(-a) *= b);
+      EXPECT_EQ(-c, absl::int128(a) *= -b);
+      EXPECT_EQ(c, absl::int128(-a) *= -b);
+    }
+  }
+
+  // Pairs of random values that will not overflow signed 64-bit multiplication
+  std::pair<int64_t, int64_t> small_values[] = {
+      {0x5e61, 0xf29f79ca14b4},    // +, +
+      {0x3e033b, -0x612c0ee549},   // +, -
+      {-0x052ce7e8, 0x7c728f0f},   // -, +
+      {-0x3af7054626, -0xfb1e1d},  // -, -
+  };
+  for (const std::pair<int64_t, int64_t>& pair : small_values) {
+    SCOPED_TRACE(::testing::Message()
+                 << "pair = {" << pair.first << ", " << pair.second << '}');
+
+    EXPECT_EQ(absl::int128(pair.first * pair.second),
+              absl::int128(pair.first) * absl::int128(pair.second));
+    EXPECT_EQ(absl::int128(pair.first * pair.second),
+              absl::int128(pair.first) *= absl::int128(pair.second));
+
+    EXPECT_EQ(absl::MakeInt128(pair.first * pair.second, 0),
+              absl::MakeInt128(pair.first, 0) * absl::int128(pair.second));
+    EXPECT_EQ(absl::MakeInt128(pair.first * pair.second, 0),
+              absl::MakeInt128(pair.first, 0) *= absl::int128(pair.second));
+  }
+
+  // Pairs of positive random values that will not overflow 64-bit
+  // multiplication and can be left shifted by 32 without overflow
+  std::pair<int64_t, int64_t> small_values2[] = {
+      {0x1bb0a110, 0x31487671},
+      {0x4792784e, 0x28add7d7},
+      {0x7b66553a, 0x11dff8ef},
+  };
+  for (const std::pair<int64_t, int64_t>& pair : small_values2) {
+    SCOPED_TRACE(::testing::Message()
+                 << "pair = {" << pair.first << ", " << pair.second << '}');
+
+    absl::int128 a = absl::int128(pair.first << 32);
+    absl::int128 b = absl::int128(pair.second << 32);
+    absl::int128 c = absl::MakeInt128(pair.first * pair.second, 0);
+
+    EXPECT_EQ(c, a * b);
+    EXPECT_EQ(-c, -a * b);
+    EXPECT_EQ(-c, a * -b);
+    EXPECT_EQ(c, -a * -b);
+
+    EXPECT_EQ(c, absl::int128(a) *= b);
+    EXPECT_EQ(-c, absl::int128(-a) *= b);
+    EXPECT_EQ(-c, absl::int128(a) *= -b);
+    EXPECT_EQ(c, absl::int128(-a) *= -b);
+  }
+
+  // check 0, 1, and -1 behavior with large values
+  absl::int128 large_values[] = {
+      {absl::MakeInt128(0xd66f061af02d0408, 0x727d2846cb475b53)},
+      {absl::MakeInt128(0x27b8d5ed6104452d, 0x03f8a33b0ee1df4f)},
+      {-absl::MakeInt128(0x621b6626b9e8d042, 0x27311ac99df00938)},
+      {-absl::MakeInt128(0x34e0656f1e95fb60, 0x4281cfd731257a47)},
+  };
+  for (absl::int128 value : large_values) {
+    EXPECT_EQ(0, 0 * value);
+    EXPECT_EQ(0, value * 0);
+    EXPECT_EQ(0, absl::int128(0) *= value);
+    EXPECT_EQ(0, value *= 0);
+
+    EXPECT_EQ(value, 1 * value);
+    EXPECT_EQ(value, value * 1);
+    EXPECT_EQ(value, absl::int128(1) *= value);
+    EXPECT_EQ(value, value *= 1);
+
+    EXPECT_EQ(-value, -1 * value);
+    EXPECT_EQ(-value, value * -1);
+    EXPECT_EQ(-value, absl::int128(-1) *= value);
+    EXPECT_EQ(-value, value *= -1);
+  }
+
+  // Manually calculated random large value cases
+  EXPECT_EQ(absl::MakeInt128(0xcd0efd3442219bb, 0xde47c05bcd9df6e1),
+            absl::MakeInt128(0x7c6448, 0x3bc4285c47a9d253) * 0x1a6037537b);
+  EXPECT_EQ(-absl::MakeInt128(0x1f8f149850b1e5e6, 0x1e50d6b52d272c3e),
+            -absl::MakeInt128(0x23, 0x2e68a513ca1b8859) * 0xe5a434cd14866e);
+  EXPECT_EQ(-absl::MakeInt128(0x55cae732029d1fce, 0xca6474b6423263e4),
+            0xa9b98a8ddf66bc * -absl::MakeInt128(0x81, 0x672e58231e2469d7));
+  EXPECT_EQ(absl::MakeInt128(0x19c8b7620b507dc4, 0xfec042b71a5f29a4),
+            -0x3e39341147 * -absl::MakeInt128(0x6a14b2, 0x5ed34cca42327b3c));
+
+  EXPECT_EQ(absl::MakeInt128(0xcd0efd3442219bb, 0xde47c05bcd9df6e1),
+            absl::MakeInt128(0x7c6448, 0x3bc4285c47a9d253) *= 0x1a6037537b);
+  EXPECT_EQ(-absl::MakeInt128(0x1f8f149850b1e5e6, 0x1e50d6b52d272c3e),
+            -absl::MakeInt128(0x23, 0x2e68a513ca1b8859) *= 0xe5a434cd14866e);
+  EXPECT_EQ(-absl::MakeInt128(0x55cae732029d1fce, 0xca6474b6423263e4),
+            absl::int128(0xa9b98a8ddf66bc) *=
+            -absl::MakeInt128(0x81, 0x672e58231e2469d7));
+  EXPECT_EQ(absl::MakeInt128(0x19c8b7620b507dc4, 0xfec042b71a5f29a4),
+            absl::int128(-0x3e39341147) *=
+            -absl::MakeInt128(0x6a14b2, 0x5ed34cca42327b3c));
+}
+
+TEST(Int128, DivisionAndModuloTest) {
+  // Check against 64 bit division and modulo operators with a sample of
+  // randomly generated pairs.
+  std::pair<int64_t, int64_t> small_pairs[] = {
+      {0x15f2a64138, 0x67da05},    {0x5e56d194af43045f, 0xcf1543fb99},
+      {0x15e61ed052036a, -0xc8e6}, {0x88125a341e85, -0xd23fb77683},
+      {-0xc06e20, 0x5a},           {-0x4f100219aea3e85d, 0xdcc56cb4efe993},
+      {-0x168d629105, -0xa7},      {-0x7b44e92f03ab2375, -0x6516},
+  };
+  for (const std::pair<int64_t, int64_t>& pair : small_pairs) {
+    SCOPED_TRACE(::testing::Message()
+                 << "pair = {" << pair.first << ", " << pair.second << '}');
+
+    absl::int128 dividend = pair.first;
+    absl::int128 divisor = pair.second;
+    int64_t quotient = pair.first / pair.second;
+    int64_t remainder = pair.first % pair.second;
+
+    EXPECT_EQ(quotient, dividend / divisor);
+    EXPECT_EQ(quotient, absl::int128(dividend) /= divisor);
+    EXPECT_EQ(remainder, dividend % divisor);
+    EXPECT_EQ(remainder, absl::int128(dividend) %= divisor);
+  }
+
+  // Test behavior with 0, 1, and -1 with a sample of randomly generated large
+  // values.
+  absl::int128 values[] = {
+      absl::MakeInt128(0x63d26ee688a962b2, 0x9e1411abda5c1d70),
+      absl::MakeInt128(0x152f385159d6f986, 0xbf8d48ef63da395d),
+      -absl::MakeInt128(0x3098d7567030038c, 0x14e7a8a098dc2164),
+      -absl::MakeInt128(0x49a037aca35c809f, 0xa6a87525480ef330),
+  };
+  for (absl::int128 value : values) {
+    SCOPED_TRACE(::testing::Message() << "value = " << value);
+
+    EXPECT_EQ(0, 0 / value);
+    EXPECT_EQ(0, absl::int128(0) /= value);
+    EXPECT_EQ(0, 0 % value);
+    EXPECT_EQ(0, absl::int128(0) %= value);
+
+    EXPECT_EQ(value, value / 1);
+    EXPECT_EQ(value, absl::int128(value) /= 1);
+    EXPECT_EQ(0, value % 1);
+    EXPECT_EQ(0, absl::int128(value) %= 1);
+
+    EXPECT_EQ(-value, value / -1);
+    EXPECT_EQ(-value, absl::int128(value) /= -1);
+    EXPECT_EQ(0, value % -1);
+    EXPECT_EQ(0, absl::int128(value) %= -1);
+  }
+
+  // Min and max values
+  EXPECT_EQ(0, absl::Int128Max() / absl::Int128Min());
+  EXPECT_EQ(absl::Int128Max(), absl::Int128Max() % absl::Int128Min());
+  EXPECT_EQ(-1, absl::Int128Min() / absl::Int128Max());
+  EXPECT_EQ(-1, absl::Int128Min() % absl::Int128Max());
+
+  // Power of two division and modulo of random large dividends
+  absl::int128 positive_values[] = {
+      absl::MakeInt128(0x21e1a1cc69574620, 0xe7ac447fab2fc869),
+      absl::MakeInt128(0x32c2ff3ab89e66e8, 0x03379a613fd1ce74),
+      absl::MakeInt128(0x6f32ca786184dcaf, 0x046f9c9ecb3a9ce1),
+      absl::MakeInt128(0x1aeb469dd990e0ee, 0xda2740f243cd37eb),
+  };
+  for (absl::int128 value : positive_values) {
+    for (int i = 0; i < 127; ++i) {
+      SCOPED_TRACE(::testing::Message()
+                   << "value = " << value << "; i = " << i);
+      absl::int128 power_of_two = absl::int128(1) << i;
+
+      EXPECT_EQ(value >> i, value / power_of_two);
+      EXPECT_EQ(value >> i, absl::int128(value) /= power_of_two);
+      EXPECT_EQ(value & (power_of_two - 1), value % power_of_two);
+      EXPECT_EQ(value & (power_of_two - 1),
+                absl::int128(value) %= power_of_two);
+    }
+  }
+
+  // Manually calculated cases with random large dividends
+  struct DivisionModCase {
+    absl::int128 dividend;
+    absl::int128 divisor;
+    absl::int128 quotient;
+    absl::int128 remainder;
+  };
+  DivisionModCase manual_cases[] = {
+      {absl::MakeInt128(0x6ada48d489007966, 0x3c9c5c98150d5d69),
+       absl::MakeInt128(0x8bc308fb, 0x8cb9cc9a3b803344), 0xc3b87e08,
+       absl::MakeInt128(0x1b7db5e1, 0xd9eca34b7af04b49)},
+      {absl::MakeInt128(0xd6946511b5b, 0x4886c5c96546bf5f),
+       -absl::MakeInt128(0x263b, 0xfd516279efcfe2dc), -0x59cbabf0,
+       absl::MakeInt128(0x622, 0xf462909155651d1f)},
+      {-absl::MakeInt128(0x33db734f9e8d1399, 0x8447ac92482bca4d), 0x37495078240,
+       -absl::MakeInt128(0xf01f1, 0xbc0368bf9a77eae8), -0x21a508f404d},
+      {-absl::MakeInt128(0x13f837b409a07e7d, 0x7fc8e248a7d73560), -0x1b9f,
+       absl::MakeInt128(0xb9157556d724, 0xb14f635714d7563e), -0x1ade},
+  };
+  for (const DivisionModCase test_case : manual_cases) {
+    EXPECT_EQ(test_case.quotient, test_case.dividend / test_case.divisor);
+    EXPECT_EQ(test_case.quotient,
+              absl::int128(test_case.dividend) /= test_case.divisor);
+    EXPECT_EQ(test_case.remainder, test_case.dividend % test_case.divisor);
+    EXPECT_EQ(test_case.remainder,
+              absl::int128(test_case.dividend) %= test_case.divisor);
+  }
+}
+
+TEST(Int128, BitwiseLogicTest) {
+  EXPECT_EQ(absl::int128(-1), ~absl::int128(0));
+
+  absl::int128 values[]{
+      0, -1, 0xde400bee05c3ff6b, absl::MakeInt128(0x7f32178dd81d634a, 0),
+      absl::MakeInt128(0xaf539057055613a9, 0x7d104d7d946c2e4d)};
+  for (absl::int128 value : values) {
+    EXPECT_EQ(value, ~~value);
+
+    EXPECT_EQ(value, value | value);
+    EXPECT_EQ(value, value & value);
+    EXPECT_EQ(0, value ^ value);
+
+    EXPECT_EQ(value, absl::int128(value) |= value);
+    EXPECT_EQ(value, absl::int128(value) &= value);
+    EXPECT_EQ(0, absl::int128(value) ^= value);
+
+    EXPECT_EQ(value, value | 0);
+    EXPECT_EQ(0, value & 0);
+    EXPECT_EQ(value, value ^ 0);
+
+    EXPECT_EQ(absl::int128(-1), value | absl::int128(-1));
+    EXPECT_EQ(value, value & absl::int128(-1));
+    EXPECT_EQ(~value, value ^ absl::int128(-1));
+  }
+
+  // small sample of randomly generated int64_t's
+  std::pair<int64_t, int64_t> pairs64[]{
+      {0x7f86797f5e991af4, 0x1ee30494fb007c97},
+      {0x0b278282bacf01af, 0x58780e0a57a49e86},
+      {0x059f266ccb93a666, 0x3d5b731bae9286f5},
+      {0x63c0c4820f12108c, 0x58166713c12e1c3a},
+      {0x381488bb2ed2a66e, 0x2220a3eb76a3698c},
+      {0x2a0a0dfb81e06f21, 0x4b60585927f5523c},
+      {0x555b1c3a03698537, 0x25478cd19d8e53cb},
+      {0x4750f6f27d779225, 0x16397553c6ff05fc},
+  };
+  for (const std::pair<int64_t, int64_t>& pair : pairs64) {
+    SCOPED_TRACE(::testing::Message()
+                 << "pair = {" << pair.first << ", " << pair.second << '}');
+
+    EXPECT_EQ(absl::MakeInt128(~pair.first, ~pair.second),
+              ~absl::MakeInt128(pair.first, pair.second));
+
+    EXPECT_EQ(absl::int128(pair.first & pair.second),
+              absl::int128(pair.first) & absl::int128(pair.second));
+    EXPECT_EQ(absl::int128(pair.first | pair.second),
+              absl::int128(pair.first) | absl::int128(pair.second));
+    EXPECT_EQ(absl::int128(pair.first ^ pair.second),
+              absl::int128(pair.first) ^ absl::int128(pair.second));
+
+    EXPECT_EQ(absl::int128(pair.first & pair.second),
+              absl::int128(pair.first) &= absl::int128(pair.second));
+    EXPECT_EQ(absl::int128(pair.first | pair.second),
+              absl::int128(pair.first) |= absl::int128(pair.second));
+    EXPECT_EQ(absl::int128(pair.first ^ pair.second),
+              absl::int128(pair.first) ^= absl::int128(pair.second));
+
+    EXPECT_EQ(
+        absl::MakeInt128(pair.first & pair.second, 0),
+        absl::MakeInt128(pair.first, 0) & absl::MakeInt128(pair.second, 0));
+    EXPECT_EQ(
+        absl::MakeInt128(pair.first | pair.second, 0),
+        absl::MakeInt128(pair.first, 0) | absl::MakeInt128(pair.second, 0));
+    EXPECT_EQ(
+        absl::MakeInt128(pair.first ^ pair.second, 0),
+        absl::MakeInt128(pair.first, 0) ^ absl::MakeInt128(pair.second, 0));
+
+    EXPECT_EQ(
+        absl::MakeInt128(pair.first & pair.second, 0),
+        absl::MakeInt128(pair.first, 0) &= absl::MakeInt128(pair.second, 0));
+    EXPECT_EQ(
+        absl::MakeInt128(pair.first | pair.second, 0),
+        absl::MakeInt128(pair.first, 0) |= absl::MakeInt128(pair.second, 0));
+    EXPECT_EQ(
+        absl::MakeInt128(pair.first ^ pair.second, 0),
+        absl::MakeInt128(pair.first, 0) ^= absl::MakeInt128(pair.second, 0));
+  }
+}
+
+TEST(Int128, BitwiseShiftTest) {
+  for (int i = 0; i < 64; ++i) {
+    for (int j = 0; j <= i; ++j) {
+      // Left shift from j-th bit to i-th bit.
+      SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+      EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) << (i - j));
+      EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) <<= (i - j));
+    }
+  }
+  for (int i = 0; i < 63; ++i) {
+    for (int j = 0; j < 64; ++j) {
+      // Left shift from j-th bit to (i + 64)-th bit.
+      SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+                absl::int128(uint64_t{1} << j) << (i + 64 - j));
+      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+                absl::int128(uint64_t{1} << j) <<= (i + 64 - j));
+    }
+    for (int j = 0; j <= i; ++j) {
+      // Left shift from (j + 64)-th bit to (i + 64)-th bit.
+      SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+                absl::MakeInt128(uint64_t{1} << j, 0) << (i - j));
+      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+                absl::MakeInt128(uint64_t{1} << j, 0) <<= (i - j));
+    }
+  }
+
+  for (int i = 0; i < 64; ++i) {
+    for (int j = i; j < 64; ++j) {
+      // Right shift from j-th bit to i-th bit.
+      SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+      EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) >> (j - i));
+      EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) >>= (j - i));
+    }
+    for (int j = 0; j < 63; ++j) {
+      // Right shift from (j + 64)-th bit to i-th bit.
+      SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+      EXPECT_EQ(uint64_t{1} << i,
+                absl::MakeInt128(uint64_t{1} << j, 0) >> (j + 64 - i));
+      EXPECT_EQ(uint64_t{1} << i,
+                absl::MakeInt128(uint64_t{1} << j, 0) >>= (j + 64 - i));
+    }
+  }
+  for (int i = 0; i < 63; ++i) {
+    for (int j = i; j < 63; ++j) {
+      // Right shift from (j + 64)-th bit to (i + 64)-th bit.
+      SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+                absl::MakeInt128(uint64_t{1} << j, 0) >> (j - i));
+      EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+                absl::MakeInt128(uint64_t{1} << j, 0) >>= (j - i));
+    }
+  }
+}
+
+TEST(Int128, NumericLimitsTest) {
+  static_assert(std::numeric_limits<absl::int128>::is_specialized, "");
+  static_assert(std::numeric_limits<absl::int128>::is_signed, "");
+  static_assert(std::numeric_limits<absl::int128>::is_integer, "");
+  EXPECT_EQ(static_cast<int>(127 * std::log10(2)),
+            std::numeric_limits<absl::int128>::digits10);
+  EXPECT_EQ(absl::Int128Min(), std::numeric_limits<absl::int128>::min());
+  EXPECT_EQ(absl::Int128Min(), std::numeric_limits<absl::int128>::lowest());
+  EXPECT_EQ(absl::Int128Max(), std::numeric_limits<absl::int128>::max());
+}
+
 }  // namespace
diff --git a/absl/numeric/internal/bits.h b/absl/numeric/internal/bits.h
new file mode 100644
index 0000000..af45700
--- /dev/null
+++ b/absl/numeric/internal/bits.h
@@ -0,0 +1,349 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_NUMERIC_INTERNAL_BITS_H_
+#define ABSL_NUMERIC_INTERNAL_BITS_H_
+
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+// Clang on Windows has __builtin_clzll; otherwise we need to use the
+// windows intrinsic functions.
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <intrin.h>
+#endif
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+
+#if ABSL_HAVE_BUILTIN(__builtin_popcountl) && \
+    ABSL_HAVE_BUILTIN(__builtin_popcountll)
+#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT constexpr
+#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 1
+#else
+#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT
+#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 0
+#endif
+
+#if ABSL_HAVE_BUILTIN(__builtin_clz) && ABSL_HAVE_BUILTIN(__builtin_clzll)
+#define ABSL_INTERNAL_CONSTEXPR_CLZ constexpr
+#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 1
+#else
+#define ABSL_INTERNAL_CONSTEXPR_CLZ
+#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 0
+#endif
+
+#if ABSL_HAVE_BUILTIN(__builtin_ctz) && ABSL_HAVE_BUILTIN(__builtin_ctzll)
+#define ABSL_INTERNAL_CONSTEXPR_CTZ constexpr
+#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 1
+#else
+#define ABSL_INTERNAL_CONSTEXPR_CTZ
+#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 0
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace numeric_internal {
+
+constexpr bool IsPowerOf2(unsigned int x) noexcept {
+  return x != 0 && (x & (x - 1)) == 0;
+}
+
+template <class T>
+ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateRight(
+    T x, int s) noexcept {
+  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+                "T must have a power-of-2 size");
+
+  return static_cast<T>(x >> (s & (std::numeric_limits<T>::digits - 1))) |
+         static_cast<T>(x << ((-s) & (std::numeric_limits<T>::digits - 1)));
+}
+
+template <class T>
+ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateLeft(
+    T x, int s) noexcept {
+  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+                "T must have a power-of-2 size");
+
+  return static_cast<T>(x << (s & (std::numeric_limits<T>::digits - 1))) |
+         static_cast<T>(x >> ((-s) & (std::numeric_limits<T>::digits - 1)));
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
+Popcount32(uint32_t x) noexcept {
+#if ABSL_HAVE_BUILTIN(__builtin_popcount)
+  static_assert(sizeof(unsigned int) == sizeof(x),
+                "__builtin_popcount does not take 32-bit arg");
+  return __builtin_popcount(x);
+#else
+  x -= ((x >> 1) & 0x55555555);
+  x = ((x >> 2) & 0x33333333) + (x & 0x33333333);
+  return static_cast<int>((((x + (x >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24);
+#endif
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
+Popcount64(uint64_t x) noexcept {
+#if ABSL_HAVE_BUILTIN(__builtin_popcountll)
+  static_assert(sizeof(unsigned long long) == sizeof(x),  // NOLINT(runtime/int)
+                "__builtin_popcount does not take 64-bit arg");
+  return __builtin_popcountll(x);
+#else
+  x -= (x >> 1) & 0x5555555555555555ULL;
+  x = ((x >> 2) & 0x3333333333333333ULL) + (x & 0x3333333333333333ULL);
+  return static_cast<int>(
+      (((x + (x >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56);
+#endif
+}
+
+template <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
+Popcount(T x) noexcept {
+  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+                "T must have a power-of-2 size");
+  static_assert(sizeof(x) <= sizeof(uint64_t), "T is too large");
+  return sizeof(x) <= sizeof(uint32_t) ? Popcount32(x) : Popcount64(x);
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
+CountLeadingZeroes32(uint32_t x) {
+#if ABSL_HAVE_BUILTIN(__builtin_clz)
+  // Use __builtin_clz, which uses the following instructions:
+  //  x86: bsr, lzcnt
+  //  ARM64: clz
+  //  PPC: cntlzd
+
+  static_assert(sizeof(unsigned int) == sizeof(x),
+                "__builtin_clz does not take 32-bit arg");
+  // Handle 0 as a special case because __builtin_clz(0) is undefined.
+  return x == 0 ? 32 : __builtin_clz(x);
+#elif defined(_MSC_VER) && !defined(__clang__)
+  unsigned long result = 0;  // NOLINT(runtime/int)
+  if (_BitScanReverse(&result, x)) {
+    return 31 - result;
+  }
+  return 32;
+#else
+  int zeroes = 28;
+  if (x >> 16) {
+    zeroes -= 16;
+    x >>= 16;
+  }
+  if (x >> 8) {
+    zeroes -= 8;
+    x >>= 8;
+  }
+  if (x >> 4) {
+    zeroes -= 4;
+    x >>= 4;
+  }
+  return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes;
+#endif
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
+CountLeadingZeroes16(uint16_t x) {
+#if ABSL_HAVE_BUILTIN(__builtin_clzs)
+  static_assert(sizeof(unsigned short) == sizeof(x),  // NOLINT(runtime/int)
+                "__builtin_clzs does not take 16-bit arg");
+  return x == 0 ? 16 : __builtin_clzs(x);
+#else
+  return CountLeadingZeroes32(x) - 16;
+#endif
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
+CountLeadingZeroes64(uint64_t x) {
+#if ABSL_HAVE_BUILTIN(__builtin_clzll)
+  // Use __builtin_clzll, which uses the following instructions:
+  //  x86: bsr, lzcnt
+  //  ARM64: clz
+  //  PPC: cntlzd
+  static_assert(sizeof(unsigned long long) == sizeof(x),  // NOLINT(runtime/int)
+                "__builtin_clzll does not take 64-bit arg");
+
+  // Handle 0 as a special case because __builtin_clzll(0) is undefined.
+  return x == 0 ? 64 : __builtin_clzll(x);
+#elif defined(_MSC_VER) && !defined(__clang__) && \
+    (defined(_M_X64) || defined(_M_ARM64))
+  // MSVC does not have __buitin_clzll. Use _BitScanReverse64.
+  unsigned long result = 0;  // NOLINT(runtime/int)
+  if (_BitScanReverse64(&result, x)) {
+    return 63 - result;
+  }
+  return 64;
+#elif defined(_MSC_VER) && !defined(__clang__)
+  // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse
+  unsigned long result = 0;  // NOLINT(runtime/int)
+  if ((x >> 32) &&
+      _BitScanReverse(&result, static_cast<unsigned long>(x >> 32))) {
+    return 31 - result;
+  }
+  if (_BitScanReverse(&result, static_cast<unsigned long>(x))) {
+    return 63 - result;
+  }
+  return 64;
+#else
+  int zeroes = 60;
+  if (x >> 32) {
+    zeroes -= 32;
+    x >>= 32;
+  }
+  if (x >> 16) {
+    zeroes -= 16;
+    x >>= 16;
+  }
+  if (x >> 8) {
+    zeroes -= 8;
+    x >>= 8;
+  }
+  if (x >> 4) {
+    zeroes -= 4;
+    x >>= 4;
+  }
+  return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes;
+#endif
+}
+
+template <typename T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
+CountLeadingZeroes(T x) {
+  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+                "T must have a power-of-2 size");
+  static_assert(sizeof(T) <= sizeof(uint64_t), "T too large");
+  return sizeof(T) <= sizeof(uint16_t)
+             ? CountLeadingZeroes16(static_cast<uint16_t>(x)) -
+                   (std::numeric_limits<uint16_t>::digits -
+                    std::numeric_limits<T>::digits)
+             : (sizeof(T) <= sizeof(uint32_t)
+                    ? CountLeadingZeroes32(static_cast<uint32_t>(x)) -
+                          (std::numeric_limits<uint32_t>::digits -
+                           std::numeric_limits<T>::digits)
+                    : CountLeadingZeroes64(x));
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
+CountTrailingZeroesNonzero32(uint32_t x) {
+#if ABSL_HAVE_BUILTIN(__builtin_ctz)
+  static_assert(sizeof(unsigned int) == sizeof(x),
+                "__builtin_ctz does not take 32-bit arg");
+  return __builtin_ctz(x);
+#elif defined(_MSC_VER) && !defined(__clang__)
+  unsigned long result = 0;  // NOLINT(runtime/int)
+  _BitScanForward(&result, x);
+  return result;
+#else
+  int c = 31;
+  x &= ~x + 1;
+  if (x & 0x0000FFFF) c -= 16;
+  if (x & 0x00FF00FF) c -= 8;
+  if (x & 0x0F0F0F0F) c -= 4;
+  if (x & 0x33333333) c -= 2;
+  if (x & 0x55555555) c -= 1;
+  return c;
+#endif
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
+CountTrailingZeroesNonzero64(uint64_t x) {
+#if ABSL_HAVE_BUILTIN(__builtin_ctzll)
+  static_assert(sizeof(unsigned long long) == sizeof(x),  // NOLINT(runtime/int)
+                "__builtin_ctzll does not take 64-bit arg");
+  return __builtin_ctzll(x);
+#elif defined(_MSC_VER) && !defined(__clang__) && \
+    (defined(_M_X64) || defined(_M_ARM64))
+  unsigned long result = 0;  // NOLINT(runtime/int)
+  _BitScanForward64(&result, x);
+  return result;
+#elif defined(_MSC_VER) && !defined(__clang__)
+  unsigned long result = 0;  // NOLINT(runtime/int)
+  if (static_cast<uint32_t>(x) == 0) {
+    _BitScanForward(&result, static_cast<unsigned long>(x >> 32));
+    return result + 32;
+  }
+  _BitScanForward(&result, static_cast<unsigned long>(x));
+  return result;
+#else
+  int c = 63;
+  x &= ~x + 1;
+  if (x & 0x00000000FFFFFFFF) c -= 32;
+  if (x & 0x0000FFFF0000FFFF) c -= 16;
+  if (x & 0x00FF00FF00FF00FF) c -= 8;
+  if (x & 0x0F0F0F0F0F0F0F0F) c -= 4;
+  if (x & 0x3333333333333333) c -= 2;
+  if (x & 0x5555555555555555) c -= 1;
+  return c;
+#endif
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
+CountTrailingZeroesNonzero16(uint16_t x) {
+#if ABSL_HAVE_BUILTIN(__builtin_ctzs)
+  static_assert(sizeof(unsigned short) == sizeof(x),  // NOLINT(runtime/int)
+                "__builtin_ctzs does not take 16-bit arg");
+  return __builtin_ctzs(x);
+#else
+  return CountTrailingZeroesNonzero32(x);
+#endif
+}
+
+template <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
+CountTrailingZeroes(T x) noexcept {
+  static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+  static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+                "T must have a power-of-2 size");
+  static_assert(sizeof(T) <= sizeof(uint64_t), "T too large");
+  return x == 0 ? std::numeric_limits<T>::digits
+                : (sizeof(T) <= sizeof(uint16_t)
+                       ? CountTrailingZeroesNonzero16(static_cast<uint16_t>(x))
+                       : (sizeof(T) <= sizeof(uint32_t)
+                              ? CountTrailingZeroesNonzero32(
+                                    static_cast<uint32_t>(x))
+                              : CountTrailingZeroesNonzero64(x)));
+}
+
+// If T is narrower than unsigned, T{1} << bit_width will be promoted.  We
+// want to force it to wraparound so that bit_ceil of an invalid value are not
+// core constant expressions.
+template <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline
+    typename std::enable_if<std::is_unsigned<T>::value, T>::type
+    BitCeilPromotionHelper(T x, T promotion) {
+  return (T{1} << (x + promotion)) >> promotion;
+}
+
+template <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline
+    typename std::enable_if<std::is_unsigned<T>::value, T>::type
+    BitCeilNonPowerOf2(T x) {
+  // If T is narrower than unsigned, it undergoes promotion to unsigned when we
+  // shift.  We calcualte the number of bits added by the wider type.
+  return BitCeilPromotionHelper(
+      static_cast<T>(std::numeric_limits<T>::digits - CountLeadingZeroes(x)),
+      T{sizeof(T) >= sizeof(unsigned) ? 0
+                                      : std::numeric_limits<unsigned>::digits -
+                                            std::numeric_limits<T>::digits});
+}
+
+}  // namespace numeric_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_NUMERIC_INTERNAL_BITS_H_
diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel
index c904618..d97b2c4 100644
--- a/absl/random/BUILD.bazel
+++ b/absl/random/BUILD.bazel
@@ -26,7 +26,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "random",
@@ -53,7 +53,6 @@
         "bernoulli_distribution.h",
         "beta_distribution.h",
         "discrete_distribution.h",
-        "distribution_format_traits.h",
         "distributions.h",
         "exponential_distribution.h",
         "gaussian_distribution.h",
@@ -67,17 +66,19 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         "//absl/base:base_internal",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/meta:type_traits",
-        "//absl/random/internal:distribution_impl",
-        "//absl/random/internal:distributions",
+        "//absl/numeric:bits",
+        "//absl/random/internal:distribution_caller",
         "//absl/random/internal:fast_uniform_bits",
         "//absl/random/internal:fastmath",
+        "//absl/random/internal:generate_real",
         "//absl/random/internal:iostream_state_saver",
         "//absl/random/internal:traits",
         "//absl/random/internal:uniform_helper",
+        "//absl/random/internal:wide_multiply",
         "//absl/strings",
-        "//absl/types:span",
     ],
 )
 
@@ -109,6 +110,56 @@
     ],
 )
 
+cc_library(
+    name = "bit_gen_ref",
+    hdrs = ["bit_gen_ref.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":random",
+        "//absl/base:core_headers",
+        "//absl/base:fast_type_id",
+        "//absl/meta:type_traits",
+        "//absl/random/internal:distribution_caller",
+        "//absl/random/internal:fast_uniform_bits",
+    ],
+)
+
+cc_library(
+    name = "mock_distributions",
+    testonly = 1,
+    hdrs = ["mock_distributions.h"],
+    deps = [
+        ":distributions",
+        ":mocking_bit_gen",
+        "//absl/meta:type_traits",
+        "//absl/random/internal:mock_overload_set",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+cc_library(
+    name = "mocking_bit_gen",
+    testonly = 1,
+    hdrs = [
+        "mocking_bit_gen.h",
+    ],
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":distributions",
+        ":random",
+        "//absl/base:fast_type_id",
+        "//absl/container:flat_hash_map",
+        "//absl/meta:type_traits",
+        "//absl/random/internal:distribution_caller",
+        "//absl/strings",
+        "//absl/types:span",
+        "//absl/types:variant",
+        "//absl/utility",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
 cc_test(
     name = "bernoulli_distribution_test",
     size = "small",
@@ -119,6 +170,7 @@
     deps = [
         ":distributions",
         ":random",
+        "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "@com_google_googletest//:gtest_main",
     ],
@@ -130,12 +182,14 @@
     timeout = "eternal",  # Android can take a very long time
     srcs = ["beta_distribution_test.cc"],
     copts = ABSL_TEST_COPTS,
+    flaky = 1,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":distributions",
         ":random",
         "//absl/base:raw_logging_internal",
         "//absl/random/internal:distribution_test_util",
+        "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "//absl/strings:str_format",
@@ -146,6 +200,7 @@
 cc_test(
     name = "distributions_test",
     size = "small",
+    timeout = "moderate",
     srcs = [
         "distributions_test.cc",
     ],
@@ -183,9 +238,9 @@
     deps = [
         ":distributions",
         ":random",
-        "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
         "//absl/random/internal:distribution_test_util",
+        "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "//absl/strings:str_format",
@@ -206,6 +261,7 @@
         ":random",
         "//absl/base:raw_logging_internal",
         "//absl/random/internal:distribution_test_util",
+        "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
@@ -233,6 +289,7 @@
         "//absl/base:raw_logging_internal",
         "//absl/container:flat_hash_map",
         "//absl/random/internal:distribution_test_util",
+        "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "//absl/strings:str_format",
@@ -252,6 +309,7 @@
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
         "//absl/random/internal:distribution_test_util",
+        "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "//absl/strings:str_format",
@@ -295,6 +353,7 @@
         ":random",
         "//absl/base:raw_logging_internal",
         "//absl/random/internal:distribution_test_util",
+        "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
@@ -319,6 +378,7 @@
         ":random",
         "//absl/base:raw_logging_internal",
         "//absl/random/internal:distribution_test_util",
+        "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
@@ -338,6 +398,7 @@
         ":random",
         "//absl/base:raw_logging_internal",
         "//absl/random/internal:distribution_test_util",
+        "//absl/random/internal:pcg_engine",
         "//absl/random/internal:sequence_urbg",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
@@ -345,6 +406,50 @@
 )
 
 cc_test(
+    name = "bit_gen_ref_test",
+    size = "small",
+    srcs = ["bit_gen_ref_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":bit_gen_ref",
+        ":random",
+        "//absl/base:fast_type_id",
+        "//absl/random/internal:sequence_urbg",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "mocking_bit_gen_test",
+    size = "small",
+    srcs = ["mocking_bit_gen_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":bit_gen_ref",
+        ":mock_distributions",
+        ":mocking_bit_gen",
+        ":random",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "mock_distributions_test",
+    size = "small",
+    srcs = ["mock_distributions_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":mock_distributions",
+        ":mocking_bit_gen",
+        ":random",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
     name = "examples_test",
     size = "small",
     srcs = ["examples_test.cc"],
diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt
index 151cefa..7d7bec8 100644
--- a/absl/random/CMakeLists.txt
+++ b/absl/random/CMakeLists.txt
@@ -34,6 +34,131 @@
 
 absl_cc_library(
   NAME
+    random_bit_gen_ref
+  HDRS
+    "bit_gen_ref.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::core_headers
+    absl::random_internal_distribution_caller
+    absl::random_internal_fast_uniform_bits
+    absl::type_traits
+)
+
+absl_cc_test(
+  NAME
+    random_bit_gen_ref_test
+  SRCS
+    "bit_gen_ref_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::random_bit_gen_ref
+    absl::random_random
+    absl::random_internal_sequence_urbg
+    absl::fast_type_id
+    gmock
+    gtest_main
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    random_internal_mock_helpers
+  HDRS
+    "internal/mock_helpers.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::fast_type_id
+    absl::optional
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    random_internal_mock_overload_set
+  HDRS
+    "internal/mock_overload_set.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::random_mocking_bit_gen
+    absl::random_internal_mock_helpers
+  TESTONLY
+)
+
+absl_cc_library(
+  NAME
+    random_mocking_bit_gen
+  HDRS
+    "mock_distributions.h"
+    "mocking_bit_gen.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::flat_hash_map
+    absl::raw_logging_internal
+    absl::random_distributions
+    absl::random_internal_distribution_caller
+    absl::random_internal_mock_overload_set
+    absl::random_random
+    absl::strings
+    absl::span
+    absl::type_traits
+    absl::utility
+    absl::variant
+    gmock
+    gtest
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
+    random_mock_distributions_test
+  SRCS
+    "mock_distributions_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::random_mocking_bit_gen
+    absl::random_random
+    gmock
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    random_mocking_bit_gen_test
+  SRCS
+    "mocking_bit_gen_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::random_bit_gen_ref
+    absl::random_mocking_bit_gen
+    absl::random_random
+    gmock
+    gtest_main
+)
+
+absl_cc_library(
+  NAME
     random_distributions
   SRCS
     "discrete_distribution.cc"
@@ -42,7 +167,6 @@
     "bernoulli_distribution.h"
     "beta_distribution.h"
     "discrete_distribution.h"
-    "distribution_format_traits.h"
     "distributions.h"
     "exponential_distribution.h"
     "gaussian_distribution.h"
@@ -57,16 +181,17 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::base_internal
+    absl::config
     absl::core_headers
-    absl::random_internal_distribution_impl
-    absl::random_internal_distributions
+    absl::random_internal_generate_real
+    absl::random_internal_distribution_caller
     absl::random_internal_fast_uniform_bits
     absl::random_internal_fastmath
     absl::random_internal_iostream_state_saver
     absl::random_internal_traits
     absl::random_internal_uniform_helper
+    absl::random_internal_wide_multiply
     absl::strings
-    absl::span
     absl::type_traits
 )
 
@@ -119,6 +244,7 @@
     absl::random_distributions
     absl::random_random
     absl::random_internal_sequence_urbg
+    absl::random_internal_pcg_engine
     gmock
     gtest_main
 )
@@ -137,6 +263,7 @@
     absl::random_random
     absl::random_internal_distribution_test_util
     absl::random_internal_sequence_urbg
+    absl::random_internal_pcg_engine
     absl::raw_logging_internal
     absl::strings
     absl::str_format
@@ -186,9 +313,9 @@
     ${ABSL_TEST_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
-    absl::core_headers
     absl::random_distributions
     absl::random_internal_distribution_test_util
+    absl::random_internal_pcg_engine
     absl::random_internal_sequence_urbg
     absl::random_random
     absl::raw_logging_internal
@@ -210,6 +337,7 @@
   DEPS
     absl::random_distributions
     absl::random_internal_distribution_test_util
+    absl::random_internal_pcg_engine
     absl::random_internal_sequence_urbg
     absl::random_random
     absl::raw_logging_internal
@@ -233,6 +361,7 @@
     absl::core_headers
     absl::flat_hash_map
     absl::random_internal_distribution_test_util
+    absl::random_internal_pcg_engine
     absl::random_internal_sequence_urbg
     absl::raw_logging_internal
     absl::strings
@@ -254,6 +383,7 @@
     absl::core_headers
     absl::random_distributions
     absl::random_internal_distribution_test_util
+    absl::random_internal_pcg_engine
     absl::random_internal_sequence_urbg
     absl::random_random
     absl::raw_logging_internal
@@ -297,6 +427,7 @@
   DEPS
     absl::random_distributions
     absl::random_internal_distribution_test_util
+    absl::random_internal_pcg_engine
     absl::random_internal_sequence_urbg
     absl::random_random
     absl::raw_logging_internal
@@ -317,6 +448,7 @@
   DEPS
     absl::random_distributions
     absl::random_internal_distribution_test_util
+    absl::random_internal_pcg_engine
     absl::random_internal_sequence_urbg
     absl::random_random
     absl::strings
@@ -336,6 +468,7 @@
   DEPS
     absl::random_distributions
     absl::random_internal_distribution_test_util
+    absl::random_internal_pcg_engine
     absl::random_internal_sequence_urbg
     absl::random_random
     absl::raw_logging_internal
@@ -399,27 +532,10 @@
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
-)
-
-# Internal-only target, do not depend on directly.
-absl_cc_library(
-  NAME
-    random_internal_distributions
-  HDRS
-    "internal/distributions.h"
-  COPTS
-    ${ABSL_DEFAULT_COPTS}
-  LINKOPTS
-    ${ABSL_DEFAULT_LINKOPTS}
   DEPS
-    absl::random_internal_distribution_caller
-    absl::random_internal_fast_uniform_bits
-    absl::random_internal_fastmath
-    absl::random_internal_traits
-    absl::random_internal_uniform_helper
-    absl::span
-    absl::strings
-    absl::type_traits
+    absl::config
+    absl::utility
+    absl::fast_type_id
 )
 
 # Internal-only target, do not depend on directly.
@@ -432,6 +548,8 @@
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
 )
 
 # Internal-only target, do not depend on directly.
@@ -446,6 +564,7 @@
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
+    $<$<BOOL:${MINGW}>:"bcrypt">
   DEPS
     absl::core_headers
     absl::optional
@@ -490,6 +609,8 @@
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
   TESTONLY
 )
 
@@ -503,6 +624,8 @@
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
   TESTONLY
 )
 
@@ -542,9 +665,26 @@
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
-    random_internal_distribution_impl
+    random_internal_generate_real
   HDRS
-    "internal/distribution_impl.h"
+    "internal/generate_real.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::bits
+    absl::random_internal_fastmath
+    absl::random_internal_traits
+    absl::type_traits
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    random_internal_wide_multiply
+  HDRS
+    "internal/wide_multiply.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
@@ -553,8 +693,6 @@
     absl::bits
     absl::config
     absl::int128
-    absl::random_internal_fastmath
-    absl::random_internal_traits
 )
 
 # Internal-only target, do not depend on directly.
@@ -588,7 +726,6 @@
     absl::random_internal_salted_seed_seq
     absl::random_internal_seed_material
     absl::span
-    absl::strings
     absl::type_traits
 )
 
@@ -633,12 +770,15 @@
     random_internal_platform
   HDRS
     "internal/randen_traits.h"
-    "internal/randen-keys.inc"
     "internal/platform.h"
+  SRCS
+    "internal/randen_round_keys.cc"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
 )
 
 # Internal-only target, do not depend on directly.
@@ -673,6 +813,7 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::random_internal_platform
+    absl::config
 )
 
 # Internal-only target, do not depend on directly.
@@ -692,6 +833,7 @@
   DEPS
     absl::random_internal_platform
     absl::random_internal_randen_hwaes_impl
+    absl::config
 )
 
 # Internal-only target, do not depend on directly.
@@ -708,6 +850,7 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::random_internal_platform
+    absl::config
 )
 
 # Internal-only target, do not depend on directly.
@@ -725,6 +868,7 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
+    absl::config
     absl::core_headers
     absl::raw_logging_internal
     absl::strings
@@ -750,9 +894,9 @@
 # Internal-only target, do not depend on directly.
 absl_cc_test(
   NAME
-    random_internal_distribution_impl_test
+    random_internal_generate_real_test
   SRCS
-    "internal/distribution_impl_test.cc"
+    "internal/generate_real_test.cc"
   COPTS
     ${ABSL_TEST_COPTS}
   LINKOPTS
@@ -760,8 +904,7 @@
   DEPS
     absl::bits
     absl::flags
-    absl::int128
-    absl::random_internal_distribution_impl
+    absl::random_internal_generate_real
     gtest_main
 )
 
@@ -1011,10 +1154,7 @@
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
-    absl::core_headers
-    absl::random_internal_distribution_impl
-    absl::random_internal_fast_uniform_bits
-    absl::random_internal_iostream_state_saver
+    absl::config
     absl::random_internal_traits
     absl::type_traits
 )
@@ -1022,6 +1162,21 @@
 # Internal-only target, do not depend on directly.
 absl_cc_test(
   NAME
+    random_internal_uniform_helper_test
+  SRCS
+    "internal/uniform_helper_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::random_internal_uniform_helper
+    gtest_main
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_test(
+  NAME
     random_internal_iostream_state_saver_test
   SRCS
     "internal/iostream_state_saver_test.cc"
@@ -1033,3 +1188,20 @@
     absl::random_internal_iostream_state_saver
     gtest_main
 )
+
+# Internal-only target, do not depend on directly.
+absl_cc_test(
+  NAME
+    random_internal_wide_multiply_test
+  SRCS
+      internal/wide_multiply_test.cc
+  COPTS
+    ${ABSL_TEST_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::random_internal_wide_multiply
+    absl::bits
+    absl::int128
+    gtest_main
+)
diff --git a/absl/random/bernoulli_distribution.h b/absl/random/bernoulli_distribution.h
index 326fcb6..25bd0d5 100644
--- a/absl/random/bernoulli_distribution.h
+++ b/absl/random/bernoulli_distribution.h
@@ -24,6 +24,7 @@
 #include "absl/random/internal/iostream_state_saver.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // absl::bernoulli_distribution is a drop in replacement for
 // std::bernoulli_distribution. It guarantees that (given a perfect
@@ -193,6 +194,7 @@
   }
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_
diff --git a/absl/random/bernoulli_distribution_test.cc b/absl/random/bernoulli_distribution_test.cc
index f2c3b99..b250f87 100644
--- a/absl/random/bernoulli_distribution_test.cc
+++ b/absl/random/bernoulli_distribution_test.cc
@@ -21,6 +21,7 @@
 #include <utility>
 
 #include "gtest/gtest.h"
+#include "absl/random/internal/pcg_engine.h"
 #include "absl/random/internal/sequence_urbg.h"
 #include "absl/random/random.h"
 
@@ -63,7 +64,10 @@
   size_t trials = para.second;
   double p = para.first;
 
-  absl::InsecureBitGen rng;
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6);
 
   size_t yes = 0;
   absl::bernoulli_distribution dist(p);
@@ -131,7 +135,7 @@
       0x275b0dc7e0a18acfull, 0x36cebe0d2653682eull, 0x0361e9b23861596bull,
   });
 
-  // Generate a std::string of '0' and '1' for the distribution output.
+  // Generate a string of '0' and '1' for the distribution output.
   auto generate = [&urbg](absl::bernoulli_distribution& dist) {
     std::string output;
     output.reserve(36);
@@ -176,7 +180,7 @@
        0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
        0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
 
-  // Generate a std::string of '0' and '1' for the distribution output.
+  // Generate a string of '0' and '1' for the distribution output.
   auto generate = [&urbg](absl::bernoulli_distribution& dist) {
     std::string output;
     output.reserve(13);
diff --git a/absl/random/beta_distribution.h b/absl/random/beta_distribution.h
index e29894f..c154066 100644
--- a/absl/random/beta_distribution.h
+++ b/absl/random/beta_distribution.h
@@ -22,12 +22,14 @@
 #include <ostream>
 #include <type_traits>
 
-#include "absl/random/internal/distribution_impl.h"
+#include "absl/meta/type_traits.h"
 #include "absl/random/internal/fast_uniform_bits.h"
 #include "absl/random/internal/fastmath.h"
+#include "absl/random/internal/generate_real.h"
 #include "absl/random/internal/iostream_state_saver.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // absl::beta_distribution:
 // Generate a floating-point variate conforming to a Beta distribution:
@@ -275,15 +277,21 @@
 beta_distribution<RealType>::AlgorithmJoehnk(
     URBG& g,  // NOLINT(runtime/references)
     const param_type& p) {
+  using random_internal::GeneratePositiveTag;
+  using random_internal::GenerateRealFromBits;
+  using real_type =
+      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+
   // Based on Joehnk, M. D. Erzeugung von betaverteilten und gammaverteilten
   // Zufallszahlen. Metrika 8.1 (1964): 5-15.
   // This method is described in Knuth, Vol 2 (Third Edition), pp 134.
-  using RandU64ToReal = typename random_internal::RandU64ToReal<result_type>;
-  using random_internal::PositiveValueT;
+
   result_type u, v, x, y, z;
   for (;;) {
-    u = RandU64ToReal::template Value<PositiveValueT, false>(fast_u64_(g));
-    v = RandU64ToReal::template Value<PositiveValueT, false>(fast_u64_(g));
+    u = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
+        fast_u64_(g));
+    v = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
+        fast_u64_(g));
 
     // Direct method. std::pow is slow for float, so rely on the optimizer to
     // remove the std::pow() path for that case.
@@ -327,12 +335,14 @@
 beta_distribution<RealType>::AlgorithmCheng(
     URBG& g,  // NOLINT(runtime/references)
     const param_type& p) {
+  using random_internal::GeneratePositiveTag;
+  using random_internal::GenerateRealFromBits;
+  using real_type =
+      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+
   // Based on Cheng, Russell CH. Generating beta variates with nonintegral
   // shape parameters. Communications of the ACM 21.4 (1978): 317-322.
   // (https://dl.acm.org/citation.cfm?id=359482).
-  using RandU64ToReal = typename random_internal::RandU64ToReal<result_type>;
-  using random_internal::PositiveValueT;
-
   static constexpr result_type kLogFour =
       result_type(1.3862943611198906188344642429163531361);  // log(4)
   static constexpr result_type kS =
@@ -341,8 +351,10 @@
   const bool use_algorithm_ba = (p.method_ == param_type::CHENG_BA);
   result_type u1, u2, v, w, z, r, s, t, bw_inv, lhs;
   for (;;) {
-    u1 = RandU64ToReal::template Value<PositiveValueT, false>(fast_u64_(g));
-    u2 = RandU64ToReal::template Value<PositiveValueT, false>(fast_u64_(g));
+    u1 = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
+        fast_u64_(g));
+    u2 = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
+        fast_u64_(g));
     v = p.y_ * std::log(u1 / (1 - u1));
     w = p.a_ * std::exp(v);
     bw_inv = result_type(1) / (p.b_ + w);
@@ -409,6 +421,7 @@
   return is;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_BETA_DISTRIBUTION_H_
diff --git a/absl/random/beta_distribution_test.cc b/absl/random/beta_distribution_test.cc
index 966ad08..277e4dc 100644
--- a/absl/random/beta_distribution_test.cc
+++ b/absl/random/beta_distribution_test.cc
@@ -29,6 +29,7 @@
 #include "absl/base/internal/raw_logging.h"
 #include "absl/random/internal/chi_square.h"
 #include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
 #include "absl/random/internal/sequence_urbg.h"
 #include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
@@ -92,7 +93,7 @@
   for (TypeParam alpha : kValues) {
     for (TypeParam beta : kValues) {
       ABSL_INTERNAL_LOG(
-          INFO, absl::StrFormat("Smoke test for Beta(%f, %f)", alpha, beta));
+          INFO, absl::StrFormat("Smoke test for Beta(%a, %a)", alpha, beta));
 
       param_type param(alpha, beta);
       absl::beta_distribution<TypeParam> before(alpha, beta);
@@ -159,8 +160,12 @@
 }
 
 TYPED_TEST(BetaDistributionInterfaceTest, DegenerateCases) {
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6);
+
   // Extreme cases when the params are abnormal.
-  absl::InsecureBitGen gen;
   constexpr int kCount = 1000;
   const TypeParam kSmallValues[] = {
       std::numeric_limits<TypeParam>::min(),
@@ -186,7 +191,7 @@
         int ones = 0;
         absl::beta_distribution<TypeParam> d(alpha, beta);
         for (int i = 0; i < kCount; ++i) {
-          TypeParam x = d(gen);
+          TypeParam x = d(rng);
           if (x == 0.0) {
             zeros++;
           } else if (x == 1.0) {
@@ -212,7 +217,7 @@
       for (TypeParam beta : kLargeValues) {
         absl::beta_distribution<TypeParam> d(alpha, beta);
         for (int i = 0; i < kCount; ++i) {
-          EXPECT_EQ(d(gen), 0.0);
+          EXPECT_EQ(d(rng), 0.0);
         }
       }
     }
@@ -227,7 +232,7 @@
       for (TypeParam beta : kSmallValues) {
         absl::beta_distribution<TypeParam> d(alpha, beta);
         for (int i = 0; i < kCount; ++i) {
-          EXPECT_EQ(d(gen), 1.0);
+          EXPECT_EQ(d(rng), 1.0);
         }
       }
     }
@@ -237,7 +242,7 @@
     absl::beta_distribution<TypeParam> d(std::numeric_limits<TypeParam>::max(),
                                          std::numeric_limits<TypeParam>::max());
     for (int i = 0; i < kCount; ++i) {
-      EXPECT_EQ(d(gen), 0.5);
+      EXPECT_EQ(d(rng), 0.5);
     }
   }
   {
@@ -246,7 +251,7 @@
         std::numeric_limits<TypeParam>::max(),
         std::numeric_limits<TypeParam>::max() * 0.9999);
     for (int i = 0; i < kCount; ++i) {
-      TypeParam x = d(gen);
+      TypeParam x = d(rng);
       EXPECT_NE(x, 0.5f);
       EXPECT_FLOAT_EQ(x, 0.500025f);
     }
diff --git a/absl/random/bit_gen_ref.h b/absl/random/bit_gen_ref.h
new file mode 100644
index 0000000..9555460
--- /dev/null
+++ b/absl/random/bit_gen_ref.h
@@ -0,0 +1,181 @@
+//
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: bit_gen_ref.h
+// -----------------------------------------------------------------------------
+//
+// This header defines a bit generator "reference" class, for use in interfaces
+// that take both Abseil (e.g. `absl::BitGen`) and standard library (e.g.
+// `std::mt19937`) bit generators.
+
+#ifndef ABSL_RANDOM_BIT_GEN_REF_H_
+#define ABSL_RANDOM_BIT_GEN_REF_H_
+
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/base/macros.h"
+#include "absl/meta/type_traits.h"
+#include "absl/random/internal/distribution_caller.h"
+#include "absl/random/internal/fast_uniform_bits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+template <typename URBG, typename = void, typename = void, typename = void>
+struct is_urbg : std::false_type {};
+
+template <typename URBG>
+struct is_urbg<
+    URBG,
+    absl::enable_if_t<std::is_same<
+        typename URBG::result_type,
+        typename std::decay<decltype((URBG::min)())>::type>::value>,
+    absl::enable_if_t<std::is_same<
+        typename URBG::result_type,
+        typename std::decay<decltype((URBG::max)())>::type>::value>,
+    absl::enable_if_t<std::is_same<
+        typename URBG::result_type,
+        typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
+    : std::true_type {};
+
+template <typename>
+struct DistributionCaller;
+class MockHelpers;
+
+}  // namespace random_internal
+
+// -----------------------------------------------------------------------------
+// absl::BitGenRef
+// -----------------------------------------------------------------------------
+//
+// `absl::BitGenRef` is a type-erasing class that provides a generator-agnostic
+// non-owning "reference" interface for use in place of any specific uniform
+// random bit generator (URBG). This class may be used for both Abseil
+// (e.g. `absl::BitGen`, `absl::InsecureBitGen`) and Standard library (e.g
+// `std::mt19937`, `std::minstd_rand`) bit generators.
+//
+// Like other reference classes, `absl::BitGenRef` does not own the
+// underlying bit generator, and the underlying instance must outlive the
+// `absl::BitGenRef`.
+//
+// `absl::BitGenRef` is particularly useful when used with an
+// `absl::MockingBitGen` to test specific paths in functions which use random
+// values.
+//
+// Example:
+//    void TakesBitGenRef(absl::BitGenRef gen) {
+//      int x = absl::Uniform<int>(gen, 0, 1000);
+//    }
+//
+class BitGenRef {
+  // SFINAE to detect whether the URBG type includes a member matching
+  // bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
+  //
+  // These live inside BitGenRef so that they have friend access
+  // to MockingBitGen. (see similar methods in DistributionCaller).
+  template <template <class...> class Trait, class AlwaysVoid, class... Args>
+  struct detector : std::false_type {};
+  template <template <class...> class Trait, class... Args>
+  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
+      : std::true_type {};
+
+  template <class T>
+  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
+      std::declval<base_internal::FastTypeIdType>(), std::declval<void*>(),
+      std::declval<void*>()));
+
+  template <typename T>
+  using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;
+
+ public:
+  BitGenRef(const BitGenRef&) = default;
+  BitGenRef(BitGenRef&&) = default;
+  BitGenRef& operator=(const BitGenRef&) = default;
+  BitGenRef& operator=(BitGenRef&&) = default;
+
+  template <typename URBG, typename absl::enable_if_t<
+                               (!std::is_same<URBG, BitGenRef>::value &&
+                                random_internal::is_urbg<URBG>::value &&
+                                !HasInvokeMock<URBG>::value)>* = nullptr>
+  BitGenRef(URBG& gen)  // NOLINT
+      : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
+        mock_call_(NotAMock),
+        generate_impl_fn_(ImplFn<URBG>) {}
+
+  template <typename URBG,
+            typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
+                                        random_internal::is_urbg<URBG>::value &&
+                                        HasInvokeMock<URBG>::value)>* = nullptr>
+  BitGenRef(URBG& gen)  // NOLINT
+      : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
+        mock_call_(&MockCall<URBG>),
+        generate_impl_fn_(ImplFn<URBG>) {}
+
+  using result_type = uint64_t;
+
+  static constexpr result_type(min)() {
+    return (std::numeric_limits<result_type>::min)();
+  }
+
+  static constexpr result_type(max)() {
+    return (std::numeric_limits<result_type>::max)();
+  }
+
+  result_type operator()() { return generate_impl_fn_(t_erased_gen_ptr_); }
+
+ private:
+  using impl_fn = result_type (*)(uintptr_t);
+  using mock_call_fn = bool (*)(uintptr_t, base_internal::FastTypeIdType, void*,
+                                void*);
+
+  template <typename URBG>
+  static result_type ImplFn(uintptr_t ptr) {
+    // Ensure that the return values from operator() fill the entire
+    // range promised by result_type, min() and max().
+    absl::random_internal::FastUniformBits<result_type> fast_uniform_bits;
+    return fast_uniform_bits(*reinterpret_cast<URBG*>(ptr));
+  }
+
+  // Get a type-erased InvokeMock pointer.
+  template <typename URBG>
+  static bool MockCall(uintptr_t gen_ptr, base_internal::FastTypeIdType type,
+                       void* result, void* arg_tuple) {
+    return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(type, result,
+                                                        arg_tuple);
+  }
+  static bool NotAMock(uintptr_t, base_internal::FastTypeIdType, void*, void*) {
+    return false;
+  }
+
+  inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
+                         void* result) {
+    if (mock_call_ == NotAMock) return false;  // avoids an indirect call.
+    return mock_call_(t_erased_gen_ptr_, type, args_tuple, result);
+  }
+
+  uintptr_t t_erased_gen_ptr_;
+  mock_call_fn mock_call_;
+  impl_fn generate_impl_fn_;
+
+  template <typename>
+  friend struct ::absl::random_internal::DistributionCaller;  // for InvokeMock
+  friend class ::absl::random_internal::MockHelpers;          // for InvokeMock
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_RANDOM_BIT_GEN_REF_H_
diff --git a/absl/random/bit_gen_ref_test.cc b/absl/random/bit_gen_ref_test.cc
new file mode 100644
index 0000000..1135cf2
--- /dev/null
+++ b/absl/random/bit_gen_ref_test.cc
@@ -0,0 +1,102 @@
+//
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "absl/random/bit_gen_ref.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+class ConstBitGen {
+ public:
+  // URBG interface
+  using result_type = absl::BitGen::result_type;
+
+  static constexpr result_type(min)() { return (absl::BitGen::min)(); }
+  static constexpr result_type(max)() { return (absl::BitGen::max)(); }
+  result_type operator()() { return 1; }
+
+  // InvokeMock method
+  bool InvokeMock(base_internal::FastTypeIdType index, void*, void* result) {
+    *static_cast<int*>(result) = 42;
+    return true;
+  }
+};
+
+namespace {
+
+int FnTest(absl::BitGenRef gen_ref) { return absl::Uniform(gen_ref, 1, 7); }
+
+template <typename T>
+class BitGenRefTest : public testing::Test {};
+
+using BitGenTypes =
+    ::testing::Types<absl::BitGen, absl::InsecureBitGen, std::mt19937,
+                     std::mt19937_64, std::minstd_rand>;
+TYPED_TEST_SUITE(BitGenRefTest, BitGenTypes);
+
+TYPED_TEST(BitGenRefTest, BasicTest) {
+  TypeParam gen;
+  auto x = FnTest(gen);
+  EXPECT_NEAR(x, 4, 3);
+}
+
+TYPED_TEST(BitGenRefTest, Copyable) {
+  TypeParam gen;
+  absl::BitGenRef gen_ref(gen);
+  FnTest(gen_ref);  // Copy
+}
+
+TEST(BitGenRefTest, PassThroughEquivalence) {
+  // sequence_urbg returns 64-bit results.
+  absl::random_internal::sequence_urbg urbg(
+      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+  std::vector<uint64_t> output(12);
+
+  {
+    absl::BitGenRef view(urbg);
+    for (auto& v : output) {
+      v = view();
+    }
+  }
+
+  std::vector<uint64_t> expected(
+      {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+       0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+       0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+       0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+  EXPECT_THAT(output, testing::Eq(expected));
+}
+
+TEST(BitGenRefTest, MockingBitGenBaseOverrides) {
+  ConstBitGen const_gen;
+  EXPECT_EQ(FnTest(const_gen), 42);
+
+  absl::BitGenRef gen_ref(const_gen);
+  EXPECT_EQ(FnTest(gen_ref), 42);  // Copy
+}
+}  // namespace
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/random/discrete_distribution.cc b/absl/random/discrete_distribution.cc
index e6c09c5..081acce 100644
--- a/absl/random/discrete_distribution.cc
+++ b/absl/random/discrete_distribution.cc
@@ -15,6 +15,7 @@
 #include "absl/random/discrete_distribution.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // Initializes the distribution table for Walker's Aliasing algorithm, described
@@ -93,4 +94,5 @@
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/discrete_distribution.h b/absl/random/discrete_distribution.h
index 1560f03..171aa11 100644
--- a/absl/random/discrete_distribution.h
+++ b/absl/random/discrete_distribution.h
@@ -29,6 +29,7 @@
 #include "absl/random/uniform_int_distribution.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // absl::discrete_distribution
 //
@@ -240,6 +241,7 @@
   return is;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_
diff --git a/absl/random/discrete_distribution_test.cc b/absl/random/discrete_distribution_test.cc
index 7296f0a..6d00700 100644
--- a/absl/random/discrete_distribution_test.cc
+++ b/absl/random/discrete_distribution_test.cc
@@ -29,6 +29,7 @@
 #include "absl/base/internal/raw_logging.h"
 #include "absl/random/internal/chi_square.h"
 #include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
 #include "absl/random/internal/sequence_urbg.h"
 #include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
@@ -156,7 +157,10 @@
   std::iota(std::begin(weights), std::end(weights), 1);
   absl::discrete_distribution<int> dist(std::begin(weights), std::end(weights));
 
-  absl::InsecureBitGen rng;
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6);
 
   std::vector<int32_t> counts(kBuckets, 0);
   for (size_t i = 0; i < kTrials; i++) {
diff --git a/absl/random/distribution_format_traits.h b/absl/random/distribution_format_traits.h
deleted file mode 100644
index 3298c2c..0000000
--- a/absl/random/distribution_format_traits.h
+++ /dev/null
@@ -1,288 +0,0 @@
-//
-// Copyright 2018 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#ifndef ABSL_RANDOM_DISTRIBUTION_FORMAT_TRAITS_H_
-#define ABSL_RANDOM_DISTRIBUTION_FORMAT_TRAITS_H_
-
-#include <string>
-#include <tuple>
-#include <typeinfo>
-
-#include "absl/meta/type_traits.h"
-#include "absl/random/bernoulli_distribution.h"
-#include "absl/random/beta_distribution.h"
-#include "absl/random/exponential_distribution.h"
-#include "absl/random/gaussian_distribution.h"
-#include "absl/random/log_uniform_int_distribution.h"
-#include "absl/random/poisson_distribution.h"
-#include "absl/random/uniform_int_distribution.h"
-#include "absl/random/uniform_real_distribution.h"
-#include "absl/random/zipf_distribution.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/str_join.h"
-#include "absl/strings/string_view.h"
-#include "absl/types/span.h"
-
-namespace absl {
-
-struct IntervalClosedClosedTag;
-struct IntervalClosedOpenTag;
-struct IntervalOpenClosedTag;
-struct IntervalOpenOpenTag;
-
-namespace random_internal {
-
-// ScalarTypeName defines a preferred hierarchy of preferred type names for
-// scalars, and is evaluated at compile time for the specific type
-// specialization.
-template <typename T>
-constexpr const char* ScalarTypeName() {
-  static_assert(std::is_integral<T>() || std::is_floating_point<T>(), "");
-  // clang-format off
-    return
-        std::is_same<T, float>::value ? "float" :
-        std::is_same<T, double>::value ? "double" :
-        std::is_same<T, long double>::value ? "long double" :
-        std::is_same<T, bool>::value ? "bool" :
-        std::is_signed<T>::value && sizeof(T) == 1 ? "int8_t" :
-        std::is_signed<T>::value && sizeof(T) == 2 ? "int16_t" :
-        std::is_signed<T>::value && sizeof(T) == 4 ? "int32_t" :
-        std::is_signed<T>::value && sizeof(T) == 8 ? "int64_t" :
-        std::is_unsigned<T>::value && sizeof(T) == 1 ? "uint8_t" :
-        std::is_unsigned<T>::value && sizeof(T) == 2 ? "uint16_t" :
-        std::is_unsigned<T>::value && sizeof(T) == 4 ? "uint32_t" :
-        std::is_unsigned<T>::value && sizeof(T) == 8 ? "uint64_t" :
-            "undefined";
-  // clang-format on
-
-  // NOTE: It would be nice to use typeid(T).name(), but that's an
-  // implementation-defined attribute which does not necessarily
-  // correspond to a name. We could potentially demangle it
-  // using, e.g. abi::__cxa_demangle.
-}
-
-// Distribution traits used by DistributionCaller and internal implementation
-// details of the mocking framework.
-/*
-struct DistributionFormatTraits {
-   // Returns the parameterized name of the distribution function.
-   static constexpr const char* FunctionName()
-   // Format DistrT parameters.
-   static std::string FormatArgs(DistrT& dist);
-   // Format DistrT::result_type results.
-   static std::string FormatResults(DistrT& dist);
-};
-*/
-template <typename DistrT>
-struct DistributionFormatTraits;
-
-template <typename R>
-struct DistributionFormatTraits<absl::uniform_int_distribution<R>> {
-  using distribution_t = absl::uniform_int_distribution<R>;
-  using result_t = typename distribution_t::result_type;
-
-  static constexpr const char* Name() { return "Uniform"; }
-
-  static std::string FunctionName() {
-    return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
-  }
-  static std::string FormatArgs(const distribution_t& d) {
-    return absl::StrCat("absl::IntervalClosedClosed, ", (d.min)(), ", ",
-                        (d.max)());
-  }
-  static std::string FormatResults(absl::Span<const result_t> results) {
-    return absl::StrJoin(results, ", ");
-  }
-};
-
-template <typename R>
-struct DistributionFormatTraits<absl::uniform_real_distribution<R>> {
-  using distribution_t = absl::uniform_real_distribution<R>;
-  using result_t = typename distribution_t::result_type;
-
-  static constexpr const char* Name() { return "Uniform"; }
-
-  static std::string FunctionName() {
-    return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
-  }
-  static std::string FormatArgs(const distribution_t& d) {
-    return absl::StrCat((d.min)(), ", ", (d.max)());
-  }
-  static std::string FormatResults(absl::Span<const result_t> results) {
-    return absl::StrJoin(results, ", ");
-  }
-};
-
-template <typename R>
-struct DistributionFormatTraits<absl::exponential_distribution<R>> {
-  using distribution_t = absl::exponential_distribution<R>;
-  using result_t = typename distribution_t::result_type;
-
-  static constexpr const char* Name() { return "Exponential"; }
-
-  static std::string FunctionName() {
-    return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
-  }
-  static std::string FormatArgs(const distribution_t& d) {
-    return absl::StrCat(d.lambda());
-  }
-  static std::string FormatResults(absl::Span<const result_t> results) {
-    return absl::StrJoin(results, ", ");
-  }
-};
-
-template <typename R>
-struct DistributionFormatTraits<absl::poisson_distribution<R>> {
-  using distribution_t = absl::poisson_distribution<R>;
-  using result_t = typename distribution_t::result_type;
-
-  static constexpr const char* Name() { return "Poisson"; }
-
-  static std::string FunctionName() {
-    return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
-  }
-  static std::string FormatArgs(const distribution_t& d) {
-    return absl::StrCat(d.mean());
-  }
-  static std::string FormatResults(absl::Span<const result_t> results) {
-    return absl::StrJoin(results, ", ");
-  }
-};
-
-template <>
-struct DistributionFormatTraits<absl::bernoulli_distribution> {
-  using distribution_t = absl::bernoulli_distribution;
-  using result_t = typename distribution_t::result_type;
-
-  static constexpr const char* Name() { return "Bernoulli"; }
-
-  static constexpr const char* FunctionName() { return Name(); }
-  static std::string FormatArgs(const distribution_t& d) {
-    return absl::StrCat(d.p());
-  }
-  static std::string FormatResults(absl::Span<const result_t> results) {
-    return absl::StrJoin(results, ", ");
-  }
-};
-
-template <typename R>
-struct DistributionFormatTraits<absl::beta_distribution<R>> {
-  using distribution_t = absl::beta_distribution<R>;
-  using result_t = typename distribution_t::result_type;
-
-  static constexpr const char* Name() { return "Beta"; }
-
-  static std::string FunctionName() {
-    return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
-  }
-  static std::string FormatArgs(const distribution_t& d) {
-    return absl::StrCat(d.alpha(), ", ", d.beta());
-  }
-  static std::string FormatResults(absl::Span<const result_t> results) {
-    return absl::StrJoin(results, ", ");
-  }
-};
-
-template <typename R>
-struct DistributionFormatTraits<absl::zipf_distribution<R>> {
-  using distribution_t = absl::zipf_distribution<R>;
-  using result_t = typename distribution_t::result_type;
-
-  static constexpr const char* Name() { return "Zipf"; }
-
-  static std::string FunctionName() {
-    return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
-  }
-  static std::string FormatArgs(const distribution_t& d) {
-    return absl::StrCat(d.k(), ", ", d.v(), ", ", d.q());
-  }
-  static std::string FormatResults(absl::Span<const result_t> results) {
-    return absl::StrJoin(results, ", ");
-  }
-};
-
-template <typename R>
-struct DistributionFormatTraits<absl::gaussian_distribution<R>> {
-  using distribution_t = absl::gaussian_distribution<R>;
-  using result_t = typename distribution_t::result_type;
-
-  static constexpr const char* Name() { return "Gaussian"; }
-
-  static std::string FunctionName() {
-    return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
-  }
-  static std::string FormatArgs(const distribution_t& d) {
-    return absl::StrJoin(std::make_tuple(d.mean(), d.stddev()), ", ");
-  }
-  static std::string FormatResults(absl::Span<const result_t> results) {
-    return absl::StrJoin(results, ", ");
-  }
-};
-
-template <typename R>
-struct DistributionFormatTraits<absl::log_uniform_int_distribution<R>> {
-  using distribution_t = absl::log_uniform_int_distribution<R>;
-  using result_t = typename distribution_t::result_type;
-
-  static constexpr const char* Name() { return "LogUniform"; }
-
-  static std::string FunctionName() {
-    return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
-  }
-  static std::string FormatArgs(const distribution_t& d) {
-    return absl::StrJoin(std::make_tuple((d.min)(), (d.max)(), d.base()), ", ");
-  }
-  static std::string FormatResults(absl::Span<const result_t> results) {
-    return absl::StrJoin(results, ", ");
-  }
-};
-
-template <typename TagType, typename NumType>
-struct UniformDistributionWrapper;
-
-template <typename TagType, typename NumType>
-struct DistributionFormatTraits<UniformDistributionWrapper<TagType, NumType>> {
-  using distribution_t = UniformDistributionWrapper<TagType, NumType>;
-  using result_t = NumType;
-
-  static constexpr const char* Name() { return "Uniform"; }
-
-  static std::string FunctionName() {
-    return absl::StrCat(Name(), "<", ScalarTypeName<NumType>(), ">");
-  }
-  static std::string FormatArgs(const distribution_t& d) {
-    absl::string_view tag;
-    if (std::is_same<TagType, IntervalClosedClosedTag>::value) {
-      tag = "IntervalClosedClosed";
-    } else if (std::is_same<TagType, IntervalClosedOpenTag>::value) {
-      tag = "IntervalClosedOpen";
-    } else if (std::is_same<TagType, IntervalOpenClosedTag>::value) {
-      tag = "IntervalOpenClosed";
-    } else if (std::is_same<TagType, IntervalOpenOpenTag>::value) {
-      tag = "IntervalOpenOpen";
-    } else {
-      tag = "[[unknown tag type]]";
-    }
-    return absl::StrCat(tag, ", ", (d.min)(), ", ", (d.max)());
-  }
-  static std::string FormatResults(absl::Span<const result_t> results) {
-    return absl::StrJoin(results, ", ");
-  }
-};
-
-}  // namespace random_internal
-}  // namespace absl
-
-#endif  // ABSL_RANDOM_DISTRIBUTION_FORMAT_TRAITS_H_
diff --git a/absl/random/distributions.h b/absl/random/distributions.h
index 18ff248..31c7969 100644
--- a/absl/random/distributions.h
+++ b/absl/random/distributions.h
@@ -55,10 +55,9 @@
 #include "absl/base/internal/inline_variable.h"
 #include "absl/random/bernoulli_distribution.h"
 #include "absl/random/beta_distribution.h"
-#include "absl/random/distribution_format_traits.h"
 #include "absl/random/exponential_distribution.h"
 #include "absl/random/gaussian_distribution.h"
-#include "absl/random/internal/distributions.h"  // IWYU pragma: export
+#include "absl/random/internal/distribution_caller.h"  // IWYU pragma: export
 #include "absl/random/internal/uniform_helper.h"  // IWYU pragma: export
 #include "absl/random/log_uniform_int_distribution.h"
 #include "absl/random/poisson_distribution.h"
@@ -67,6 +66,7 @@
 #include "absl/random/zipf_distribution.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosedClosed,
                                {});
@@ -96,7 +96,7 @@
 // the return type based on the provided endpoint arguments {A lo, B hi}.
 // Given these endpoints, one of {A, B} will be chosen as the return type, if
 // a type can be implicitly converted into the other in a lossless way. The
-// lack of any such implcit conversion between {A, B} will produce a
+// lack of any such implicit conversion between {A, B} will produce a
 // compile-time error
 //
 // See https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)
@@ -124,7 +124,14 @@
         URBG&& urbg,  // NOLINT(runtime/references)
         R lo, R hi) {
   using gen_t = absl::decay_t<URBG>;
-  return random_internal::UniformImpl<R, TagType, gen_t>(tag, urbg, lo, hi);
+  using distribution_t = random_internal::UniformDistributionWrapper<R>;
+
+  auto a = random_internal::uniform_lower_bound(tag, lo, hi);
+  auto b = random_internal::uniform_upper_bound(tag, lo, hi);
+  if (!random_internal::is_uniform_range_valid(a, b)) return lo;
+
+  return random_internal::DistributionCaller<gen_t>::template Call<
+      distribution_t>(&urbg, tag, lo, hi);
 }
 
 // absl::Uniform<T>(bitgen, lo, hi)
@@ -135,11 +142,16 @@
 typename absl::enable_if_t<!std::is_same<R, void>::value, R>  //
 Uniform(URBG&& urbg,  // NOLINT(runtime/references)
         R lo, R hi) {
-  constexpr auto tag = absl::IntervalClosedOpen;
-  using tag_t = decltype(tag);
   using gen_t = absl::decay_t<URBG>;
+  using distribution_t = random_internal::UniformDistributionWrapper<R>;
+  constexpr auto tag = absl::IntervalClosedOpen;
 
-  return random_internal::UniformImpl<R, tag_t, gen_t>(tag, urbg, lo, hi);
+  auto a = random_internal::uniform_lower_bound(tag, lo, hi);
+  auto b = random_internal::uniform_upper_bound(tag, lo, hi);
+  if (!random_internal::is_uniform_range_valid(a, b)) return lo;
+
+  return random_internal::DistributionCaller<gen_t>::template Call<
+      distribution_t>(&urbg, lo, hi);
 }
 
 // absl::Uniform(tag, bitgen, lo, hi)
@@ -156,9 +168,15 @@
         A lo, B hi) {
   using gen_t = absl::decay_t<URBG>;
   using return_t = typename random_internal::uniform_inferred_return_t<A, B>;
+  using distribution_t = random_internal::UniformDistributionWrapper<return_t>;
 
-  return random_internal::UniformImpl<return_t, TagType, gen_t>(tag, urbg, lo,
-                                                                hi);
+  auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);
+  auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi);
+  if (!random_internal::is_uniform_range_valid(a, b)) return lo;
+
+  return random_internal::DistributionCaller<gen_t>::template Call<
+      distribution_t>(&urbg, tag, static_cast<return_t>(lo),
+                                static_cast<return_t>(hi));
 }
 
 // absl::Uniform(bitgen, lo, hi)
@@ -171,13 +189,18 @@
                            random_internal::uniform_inferred_return_t<A, B>>
 Uniform(URBG&& urbg,  // NOLINT(runtime/references)
         A lo, B hi) {
-  constexpr auto tag = absl::IntervalClosedOpen;
-  using tag_t = decltype(tag);
   using gen_t = absl::decay_t<URBG>;
   using return_t = typename random_internal::uniform_inferred_return_t<A, B>;
+  using distribution_t = random_internal::UniformDistributionWrapper<return_t>;
 
-  return random_internal::UniformImpl<return_t, tag_t, gen_t>(tag, urbg, lo,
-                                                              hi);
+  constexpr auto tag = absl::IntervalClosedOpen;
+  auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);
+  auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi);
+  if (!random_internal::is_uniform_range_valid(a, b)) return lo;
+
+  return random_internal::DistributionCaller<gen_t>::template Call<
+      distribution_t>(&urbg, static_cast<return_t>(lo),
+                                static_cast<return_t>(hi));
 }
 
 // absl::Uniform<unsigned T>(bitgen)
@@ -187,13 +210,11 @@
 template <typename R, typename URBG>
 typename absl::enable_if_t<!std::is_signed<R>::value, R>  //
 Uniform(URBG&& urbg) {  // NOLINT(runtime/references)
-  constexpr auto tag = absl::IntervalClosedClosed;
-  constexpr auto lo = std::numeric_limits<R>::lowest();
-  constexpr auto hi = (std::numeric_limits<R>::max)();
-  using tag_t = decltype(tag);
   using gen_t = absl::decay_t<URBG>;
+  using distribution_t = random_internal::UniformDistributionWrapper<R>;
 
-  return random_internal::UniformImpl<R, tag_t, gen_t>(tag, urbg, lo, hi);
+  return random_internal::DistributionCaller<gen_t>::template Call<
+      distribution_t>(&urbg);
 }
 
 // -----------------------------------------------------------------------------
@@ -221,10 +242,9 @@
                double p) {
   using gen_t = absl::decay_t<URBG>;
   using distribution_t = absl::bernoulli_distribution;
-  using format_t = random_internal::DistributionFormatTraits<distribution_t>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
-      distribution_t, format_t>(&urbg, p);
+      distribution_t>(&urbg, p);
 }
 
 // -----------------------------------------------------------------------------
@@ -254,20 +274,19 @@
 
   using gen_t = absl::decay_t<URBG>;
   using distribution_t = typename absl::beta_distribution<RealType>;
-  using format_t = random_internal::DistributionFormatTraits<distribution_t>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
-      distribution_t, format_t>(&urbg, alpha, beta);
+      distribution_t>(&urbg, alpha, beta);
 }
 
 // -----------------------------------------------------------------------------
 // absl::Exponential<T>(bitgen, lambda = 1)
 // -----------------------------------------------------------------------------
 //
-// `absl::Exponential` produces a floating point number for discrete
-// distributions of events occurring continuously and independently at a
-// constant average rate. `T` must be a floating point type, but may be inferred
-// from the type of `lambda`.
+// `absl::Exponential` produces a floating point number representing the
+// distance (time) between two consecutive events in a point process of events
+// occurring continuously and independently at a constant average rate. `T` must
+// be a floating point type, but may be inferred from the type of `lambda`.
 //
 // See https://en.wikipedia.org/wiki/Exponential_distribution.
 //
@@ -287,10 +306,9 @@
 
   using gen_t = absl::decay_t<URBG>;
   using distribution_t = typename absl::exponential_distribution<RealType>;
-  using format_t = random_internal::DistributionFormatTraits<distribution_t>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
-      distribution_t, format_t>(&urbg, lambda);
+      distribution_t>(&urbg, lambda);
 }
 
 // -----------------------------------------------------------------------------
@@ -319,10 +337,9 @@
 
   using gen_t = absl::decay_t<URBG>;
   using distribution_t = typename absl::gaussian_distribution<RealType>;
-  using format_t = random_internal::DistributionFormatTraits<distribution_t>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
-      distribution_t, format_t>(&urbg, mean, stddev);
+      distribution_t>(&urbg, mean, stddev);
 }
 
 // -----------------------------------------------------------------------------
@@ -362,10 +379,9 @@
 
   using gen_t = absl::decay_t<URBG>;
   using distribution_t = typename absl::log_uniform_int_distribution<IntType>;
-  using format_t = random_internal::DistributionFormatTraits<distribution_t>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
-      distribution_t, format_t>(&urbg, lo, hi, base);
+      distribution_t>(&urbg, lo, hi, base);
 }
 
 // -----------------------------------------------------------------------------
@@ -393,10 +409,9 @@
 
   using gen_t = absl::decay_t<URBG>;
   using distribution_t = typename absl::poisson_distribution<IntType>;
-  using format_t = random_internal::DistributionFormatTraits<distribution_t>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
-      distribution_t, format_t>(&urbg, mean);
+      distribution_t>(&urbg, mean);
 }
 
 // -----------------------------------------------------------------------------
@@ -426,12 +441,12 @@
 
   using gen_t = absl::decay_t<URBG>;
   using distribution_t = typename absl::zipf_distribution<IntType>;
-  using format_t = random_internal::DistributionFormatTraits<distribution_t>;
 
   return random_internal::DistributionCaller<gen_t>::template Call<
-      distribution_t, format_t>(&urbg, hi, q, v);
+      distribution_t>(&urbg, hi, q, v);
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_DISTRIBUTIONS_H_
diff --git a/absl/random/distributions_test.cc b/absl/random/distributions_test.cc
index 2d92723..5866a07 100644
--- a/absl/random/distributions_test.cc
+++ b/absl/random/distributions_test.cc
@@ -29,94 +29,6 @@
 
 class RandomDistributionsTest : public testing::Test {};
 
-TEST_F(RandomDistributionsTest, UniformBoundFunctions) {
-  using absl::IntervalClosedClosed;
-  using absl::IntervalClosedOpen;
-  using absl::IntervalOpenClosed;
-  using absl::IntervalOpenOpen;
-  using absl::random_internal::uniform_lower_bound;
-  using absl::random_internal::uniform_upper_bound;
-
-  // absl::uniform_int_distribution natively assumes IntervalClosedClosed
-  // absl::uniform_real_distribution natively assumes IntervalClosedOpen
-
-  EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, 0, 100), 1);
-  EXPECT_EQ(uniform_lower_bound(IntervalOpenOpen, 0, 100), 1);
-  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenClosed, 0, 1.0), 0);
-  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenOpen, 0, 1.0), 0);
-  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenClosed, 0, 1.0), 0);
-  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenOpen, 0, 1.0), 0);
-
-  EXPECT_EQ(uniform_lower_bound(IntervalClosedClosed, 0, 100), 0);
-  EXPECT_EQ(uniform_lower_bound(IntervalClosedOpen, 0, 100), 0);
-  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedClosed, 0, 1.0), 0);
-  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedOpen, 0, 1.0), 0);
-  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedClosed, 0, 1.0), 0);
-  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedOpen, 0, 1.0), 0);
-
-  EXPECT_EQ(uniform_upper_bound(IntervalOpenOpen, 0, 100), 99);
-  EXPECT_EQ(uniform_upper_bound(IntervalClosedOpen, 0, 100), 99);
-  EXPECT_EQ(uniform_upper_bound<float>(IntervalOpenOpen, 0, 1.0), 1.0);
-  EXPECT_EQ(uniform_upper_bound<float>(IntervalClosedOpen, 0, 1.0), 1.0);
-  EXPECT_EQ(uniform_upper_bound<double>(IntervalOpenOpen, 0, 1.0), 1.0);
-  EXPECT_EQ(uniform_upper_bound<double>(IntervalClosedOpen, 0, 1.0), 1.0);
-
-  EXPECT_EQ(uniform_upper_bound(IntervalOpenClosed, 0, 100), 100);
-  EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, 0, 100), 100);
-  EXPECT_GT(uniform_upper_bound<float>(IntervalOpenClosed, 0, 1.0), 1.0);
-  EXPECT_GT(uniform_upper_bound<float>(IntervalClosedClosed, 0, 1.0), 1.0);
-  EXPECT_GT(uniform_upper_bound<double>(IntervalOpenClosed, 0, 1.0), 1.0);
-  EXPECT_GT(uniform_upper_bound<double>(IntervalClosedClosed, 0, 1.0), 1.0);
-
-  // Negative value tests
-  EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, -100, -1), -99);
-  EXPECT_EQ(uniform_lower_bound(IntervalOpenOpen, -100, -1), -99);
-  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenClosed, -2.0, -1.0), -2.0);
-  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenOpen, -2.0, -1.0), -2.0);
-  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenClosed, -2.0, -1.0), -2.0);
-  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenOpen, -2.0, -1.0), -2.0);
-
-  EXPECT_EQ(uniform_lower_bound(IntervalClosedClosed, -100, -1), -100);
-  EXPECT_EQ(uniform_lower_bound(IntervalClosedOpen, -100, -1), -100);
-  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedClosed, -2.0, -1.0), -2.0);
-  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedOpen, -2.0, -1.0), -2.0);
-  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedClosed, -2.0, -1.0),
-            -2.0);
-  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedOpen, -2.0, -1.0), -2.0);
-
-  EXPECT_EQ(uniform_upper_bound(IntervalOpenOpen, -100, -1), -2);
-  EXPECT_EQ(uniform_upper_bound(IntervalClosedOpen, -100, -1), -2);
-  EXPECT_EQ(uniform_upper_bound<float>(IntervalOpenOpen, -2.0, -1.0), -1.0);
-  EXPECT_EQ(uniform_upper_bound<float>(IntervalClosedOpen, -2.0, -1.0), -1.0);
-  EXPECT_EQ(uniform_upper_bound<double>(IntervalOpenOpen, -2.0, -1.0), -1.0);
-  EXPECT_EQ(uniform_upper_bound<double>(IntervalClosedOpen, -2.0, -1.0), -1.0);
-
-  EXPECT_EQ(uniform_upper_bound(IntervalOpenClosed, -100, -1), -1);
-  EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, -100, -1), -1);
-  EXPECT_GT(uniform_upper_bound<float>(IntervalOpenClosed, -2.0, -1.0), -1.0);
-  EXPECT_GT(uniform_upper_bound<float>(IntervalClosedClosed, -2.0, -1.0), -1.0);
-  EXPECT_GT(uniform_upper_bound<double>(IntervalOpenClosed, -2.0, -1.0), -1.0);
-  EXPECT_GT(uniform_upper_bound<double>(IntervalClosedClosed, -2.0, -1.0),
-            -1.0);
-
-  // Edge cases: the next value toward itself is itself.
-  const double d = 1.0;
-  const float f = 1.0;
-  EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, d, d), d);
-  EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, f, f), f);
-
-  EXPECT_GT(uniform_lower_bound(IntervalOpenClosed, 1.0, 2.0), 1.0);
-  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, +0.0), 1.0);
-  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, -0.0), 1.0);
-  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, -1.0), 1.0);
-
-  EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, 0.0f,
-                                std::numeric_limits<float>::max()),
-            std::numeric_limits<float>::max());
-  EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, 0.0,
-                                std::numeric_limits<double>::max()),
-            std::numeric_limits<double>::max());
-}
 
 struct Invalid {};
 
@@ -284,7 +196,9 @@
 
   // Properly promotes float.
   CheckArgsInferType<float, double, double>();
+}
 
+TEST_F(RandomDistributionsTest, UniformExamples) {
   // Examples.
   absl::InsecureBitGen gen;
   EXPECT_NE(1, absl::Uniform(gen, static_cast<uint16_t>(0), 1.0f));
@@ -307,6 +221,58 @@
   absl::Uniform<uint64_t>(gen);
 }
 
+TEST_F(RandomDistributionsTest, UniformNonsenseRanges) {
+  // The ranges used in this test are undefined behavior.
+  // The results are arbitrary and subject to future changes.
+  absl::InsecureBitGen gen;
+
+  // <uint>
+  EXPECT_EQ(0, absl::Uniform<uint64_t>(gen, 0, 0));
+  EXPECT_EQ(1, absl::Uniform<uint64_t>(gen, 1, 0));
+  EXPECT_EQ(0, absl::Uniform<uint64_t>(absl::IntervalOpenOpen, gen, 0, 0));
+  EXPECT_EQ(1, absl::Uniform<uint64_t>(absl::IntervalOpenOpen, gen, 1, 0));
+
+  constexpr auto m = (std::numeric_limits<uint64_t>::max)();
+
+  EXPECT_EQ(m, absl::Uniform(gen, m, m));
+  EXPECT_EQ(m, absl::Uniform(gen, m, m - 1));
+  EXPECT_EQ(m - 1, absl::Uniform(gen, m - 1, m));
+  EXPECT_EQ(m, absl::Uniform(absl::IntervalOpenOpen, gen, m, m));
+  EXPECT_EQ(m, absl::Uniform(absl::IntervalOpenOpen, gen, m, m - 1));
+  EXPECT_EQ(m - 1, absl::Uniform(absl::IntervalOpenOpen, gen, m - 1, m));
+
+  // <int>
+  EXPECT_EQ(0, absl::Uniform<int64_t>(gen, 0, 0));
+  EXPECT_EQ(1, absl::Uniform<int64_t>(gen, 1, 0));
+  EXPECT_EQ(0, absl::Uniform<int64_t>(absl::IntervalOpenOpen, gen, 0, 0));
+  EXPECT_EQ(1, absl::Uniform<int64_t>(absl::IntervalOpenOpen, gen, 1, 0));
+
+  constexpr auto l = (std::numeric_limits<int64_t>::min)();
+  constexpr auto r = (std::numeric_limits<int64_t>::max)();
+
+  EXPECT_EQ(l, absl::Uniform(gen, l, l));
+  EXPECT_EQ(r, absl::Uniform(gen, r, r));
+  EXPECT_EQ(r, absl::Uniform(gen, r, r - 1));
+  EXPECT_EQ(r - 1, absl::Uniform(gen, r - 1, r));
+  EXPECT_EQ(l, absl::Uniform(absl::IntervalOpenOpen, gen, l, l));
+  EXPECT_EQ(r, absl::Uniform(absl::IntervalOpenOpen, gen, r, r));
+  EXPECT_EQ(r, absl::Uniform(absl::IntervalOpenOpen, gen, r, r - 1));
+  EXPECT_EQ(r - 1, absl::Uniform(absl::IntervalOpenOpen, gen, r - 1, r));
+
+  // <double>
+  const double e = std::nextafter(1.0, 2.0);  // 1 + epsilon
+  const double f = std::nextafter(1.0, 0.0);  // 1 - epsilon
+  const double g = std::numeric_limits<double>::denorm_min();
+
+  EXPECT_EQ(1.0, absl::Uniform(gen, 1.0, e));
+  EXPECT_EQ(1.0, absl::Uniform(gen, 1.0, f));
+  EXPECT_EQ(0.0, absl::Uniform(gen, 0.0, g));
+
+  EXPECT_EQ(e, absl::Uniform(absl::IntervalOpenOpen, gen, 1.0, e));
+  EXPECT_EQ(f, absl::Uniform(absl::IntervalOpenOpen, gen, 1.0, f));
+  EXPECT_EQ(g, absl::Uniform(absl::IntervalOpenOpen, gen, 0.0, g));
+}
+
 // TODO(lar): Validate properties of non-default interval-semantics.
 TEST_F(RandomDistributionsTest, UniformReal) {
   std::vector<double> values(kSize);
diff --git a/absl/random/exponential_distribution.h b/absl/random/exponential_distribution.h
index c8af197..b5caf8a 100644
--- a/absl/random/exponential_distribution.h
+++ b/absl/random/exponential_distribution.h
@@ -21,11 +21,13 @@
 #include <limits>
 #include <type_traits>
 
-#include "absl/random/internal/distribution_impl.h"
+#include "absl/meta/type_traits.h"
 #include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/random/internal/generate_real.h"
 #include "absl/random/internal/iostream_state_saver.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // absl::exponential_distribution:
 // Generates a number conforming to an exponential distribution and is
@@ -118,9 +120,14 @@
 exponential_distribution<RealType>::operator()(
     URBG& g,  // NOLINT(runtime/references)
     const param_type& p) {
-  using random_internal::NegativeValueT;
-  const result_type u = random_internal::RandU64ToReal<
-      result_type>::template Value<NegativeValueT, false>(fast_u64_(g));
+  using random_internal::GenerateNegativeTag;
+  using random_internal::GenerateRealFromBits;
+  using real_type =
+      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+
+  const result_type u = GenerateRealFromBits<real_type, GenerateNegativeTag,
+                                             false>(fast_u64_(g));  // U(-1, 0)
+
   // log1p(-x) is mathematically equivalent to log(1 - x) but has more
   // accuracy for x near zero.
   return p.neg_inv_lambda_ * std::log1p(u);
@@ -152,6 +159,7 @@
   return is;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_
diff --git a/absl/random/exponential_distribution_test.cc b/absl/random/exponential_distribution_test.cc
index dc49044..5a8afde 100644
--- a/absl/random/exponential_distribution_test.cc
+++ b/absl/random/exponential_distribution_test.cc
@@ -32,6 +32,7 @@
 #include "absl/base/macros.h"
 #include "absl/random/internal/chi_square.h"
 #include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
 #include "absl/random/internal/sequence_urbg.h"
 #include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
@@ -201,7 +202,10 @@
   template <typename D>
   double SingleChiSquaredTest();
 
-  absl::InsecureBitGen rng_;
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
 };
 
 template <typename D>
diff --git a/absl/random/gaussian_distribution.cc b/absl/random/gaussian_distribution.cc
index 5dd8461..c7a72cb 100644
--- a/absl/random/gaussian_distribution.cc
+++ b/absl/random/gaussian_distribution.cc
@@ -4,6 +4,7 @@
 #include "absl/random/gaussian_distribution.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 const gaussian_distribution_base::Tables
@@ -96,6 +97,7 @@
      0.9362826816850632339, 0.9635996931270905952, 1}};
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 // clang-format on
diff --git a/absl/random/gaussian_distribution.h b/absl/random/gaussian_distribution.h
index 1d1347b..4b07a5c 100644
--- a/absl/random/gaussian_distribution.h
+++ b/absl/random/gaussian_distribution.h
@@ -28,11 +28,13 @@
 #include <limits>
 #include <type_traits>
 
-#include "absl/random/internal/distribution_impl.h"
+#include "absl/base/config.h"
 #include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/random/internal/generate_real.h"
 #include "absl/random/internal/iostream_state_saver.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // absl::gaussian_distribution_base implements the underlying ziggurat algorithm
@@ -42,7 +44,7 @@
 // The specific algorithm has some of the improvements suggested by the
 // 2005 paper, "An Improved Ziggurat Method to Generate Normal Random Samples",
 // Jurgen A Doornik.  (https://www.doornik.com/research/ziggurat.pdf)
-class gaussian_distribution_base {
+class ABSL_DLL gaussian_distribution_base {
  public:
   template <typename URBG>
   inline double zignor(URBG& g);  // NOLINT(runtime/references)
@@ -207,12 +209,18 @@
 
 template <typename URBG>
 inline double gaussian_distribution_base::zignor_fallback(URBG& g, bool neg) {
+  using random_internal::GeneratePositiveTag;
+  using random_internal::GenerateRealFromBits;
+
   // This fallback path happens approximately 0.05% of the time.
   double x, y;
   do {
     // kRInv = 1/r, U(0, 1)
-    x = kRInv * std::log(RandU64ToDouble<PositiveValueT, false>(fast_u64_(g)));
-    y = -std::log(RandU64ToDouble<PositiveValueT, false>(fast_u64_(g)));
+    x = kRInv *
+        std::log(GenerateRealFromBits<double, GeneratePositiveTag, false>(
+            fast_u64_(g)));
+    y = -std::log(
+        GenerateRealFromBits<double, GeneratePositiveTag, false>(fast_u64_(g)));
   } while ((y + y) < (x * x));
   return neg ? (x - kR) : (kR - x);
 }
@@ -220,6 +228,10 @@
 template <typename URBG>
 inline double gaussian_distribution_base::zignor(
     URBG& g) {  // NOLINT(runtime/references)
+  using random_internal::GeneratePositiveTag;
+  using random_internal::GenerateRealFromBits;
+  using random_internal::GenerateSignedTag;
+
   while (true) {
     // We use a single uint64_t to generate both a double and a strip.
     // These bits are unused when the generated double is > 1/2^5.
@@ -227,7 +239,8 @@
     // values (those smaller than 1/2^5, which all end up on the left tail).
     uint64_t bits = fast_u64_(g);
     int i = static_cast<int>(bits & kMask);  // pick a random strip
-    double j = RandU64ToDouble<SignedValueT, false>(bits);  // U(-1, 1)
+    double j = GenerateRealFromBits<double, GenerateSignedTag, false>(
+        bits);  // U(-1, 1)
     const double x = j * zg_.x[i];
 
     // Retangular box. Handles >97% of all cases.
@@ -244,7 +257,8 @@
     }
 
     // i > 0: Wedge samples using precomputed values.
-    double v = RandU64ToDouble<PositiveValueT, false>(fast_u64_(g));  // U(0, 1)
+    double v = GenerateRealFromBits<double, GeneratePositiveTag, false>(
+        fast_u64_(g));  // U(0, 1)
     if ((zg_.f[i + 1] + v * (zg_.f[i] - zg_.f[i + 1])) <
         std::exp(-0.5 * x * x)) {
       return x;
@@ -255,6 +269,7 @@
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_
diff --git a/absl/random/gaussian_distribution_test.cc b/absl/random/gaussian_distribution_test.cc
index 49c0751..2aa7caf 100644
--- a/absl/random/gaussian_distribution_test.cc
+++ b/absl/random/gaussian_distribution_test.cc
@@ -213,7 +213,10 @@
   template <typename D>
   double SingleChiSquaredTest();
 
-  absl::InsecureBitGen rng_;
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
 };
 
 template <typename D>
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index cd50982..2c1a5f4 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -30,16 +30,13 @@
     "//absl/random:__pkg__",
 ])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "traits",
     hdrs = ["traits.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl/random:__pkg__",
-    ],
     deps = ["//absl/base:config"],
 )
 
@@ -48,23 +45,10 @@
     hdrs = ["distribution_caller.h"],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl/random:__pkg__",
-    ],
-)
-
-cc_library(
-    name = "distributions",
-    hdrs = ["distributions.h"],
-    copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        ":distribution_caller",
-        ":traits",
-        ":uniform_helper",
-        "//absl/base",
-        "//absl/meta:type_traits",
-        "//absl/strings",
+        "//absl/base:config",
+        "//absl/base:fast_type_id",
+        "//absl/utility",
     ],
 )
 
@@ -75,8 +59,9 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl/random:__pkg__",
+    deps = [
+        "//absl/base:config",
+        "//absl/meta:type_traits",
     ],
 )
 
@@ -89,7 +74,10 @@
         "seed_material.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS + select({
+        "//absl:windows": ["-DEFAULTLIB:bcrypt.lib"],
+        "//conditions:default": [],
+    }),
     deps = [
         ":fast_uniform_bits",
         "//absl/base:core_headers",
@@ -111,6 +99,7 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = select({
         "//absl:windows": [],
+        "//absl:wasm": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
@@ -135,6 +124,7 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = ["//absl/base:config"],
 )
 
 cc_library(
@@ -145,6 +135,7 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = ["//absl/base:config"],
 )
 
 cc_library(
@@ -175,18 +166,17 @@
 )
 
 cc_library(
-    name = "distribution_impl",
+    name = "generate_real",
     hdrs = [
-        "distribution_impl.h",
+        "generate_real.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":fastmath",
         ":traits",
-        "//absl/base:bits",
-        "//absl/base:config",
-        "//absl/numeric:int128",
+        "//absl/meta:type_traits",
+        "//absl/numeric:bits",
     ],
 )
 
@@ -197,7 +187,20 @@
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    deps = ["//absl/base:bits"],
+    deps = ["//absl/numeric:bits"],
+)
+
+cc_library(
+    name = "wide_multiply",
+    hdrs = ["wide_multiply.h"],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":traits",
+        "//absl/base:config",
+        "//absl/numeric:bits",
+        "//absl/numeric:int128",
+    ],
 )
 
 cc_library(
@@ -211,7 +214,6 @@
         ":seed_material",
         "//absl/base:core_headers",
         "//absl/meta:type_traits",
-        "//absl/strings",
         "//absl/types:optional",
         "//absl/types:span",
     ],
@@ -227,6 +229,7 @@
         ":iostream_state_saver",
         "//absl/base:config",
         "//absl/meta:type_traits",
+        "//absl/numeric:bits",
         "//absl/numeric:int128",
     ],
 )
@@ -245,15 +248,18 @@
 
 cc_library(
     name = "platform",
+    srcs = [
+        "randen_round_keys.cc",
+    ],
     hdrs = [
         "randen_traits.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     textual_hdrs = [
-        "randen-keys.inc",
         "platform.h",
     ],
+    deps = ["//absl/base:config"],
 )
 
 cc_library(
@@ -282,6 +288,8 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":platform",
+        "//absl/base:config",
+        "//absl/base:core_headers",
     ],
 )
 
@@ -301,6 +309,7 @@
     deps = [
         ":platform",
         ":randen_hwaes_impl",
+        "//absl/base:config",
     ],
 )
 
@@ -315,13 +324,10 @@
         "//absl:windows": [],
         "//conditions:default": ["-Wno-pass-failed"],
     }),
-    # copts in RANDEN_HWAES_COPTS can make this target unusable as a module
-    # leading to a Clang diagnostic. Furthermore, it only has a private header
-    # anyway and thus there wouldn't be any gain from using it as a module.
-    features = ["-header_modules"],
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":platform",
+        "//absl/base:config",
         "//absl/base:core_headers",
     ],
 )
@@ -352,6 +358,7 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
         "//absl/strings",
@@ -385,16 +392,17 @@
 )
 
 cc_test(
-    name = "distribution_impl_test",
+    name = "generate_real_test",
     size = "small",
-    srcs = ["distribution_impl_test.cc"],
+    srcs = [
+        "generate_real_test.cc",
+    ],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        ":distribution_impl",
-        "//absl/base:bits",
+        ":generate_real",
         "//absl/flags:flag",
-        "//absl/numeric:int128",
+        "//absl/numeric:bits",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -477,6 +485,26 @@
     ],
 )
 
+cc_library(
+    name = "mock_helpers",
+    hdrs = ["mock_helpers.h"],
+    deps = [
+        "//absl/base:fast_type_id",
+        "//absl/types:optional",
+    ],
+)
+
+cc_library(
+    name = "mock_overload_set",
+    testonly = 1,
+    hdrs = ["mock_overload_set.h"],
+    deps = [
+        ":mock_helpers",
+        "//absl/random:mocking_bit_gen",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
 cc_test(
     name = "nonsecure_base_test",
     size = "small",
@@ -576,6 +604,7 @@
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":platform",
         ":randen_slow",
         "@com_google_googletest//:gtest_main",
     ],
@@ -598,6 +627,20 @@
     ],
 )
 
+cc_test(
+    name = "wide_multiply_test",
+    size = "small",
+    srcs = ["wide_multiply_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":wide_multiply",
+        "//absl/numeric:bits",
+        "//absl/numeric:int128",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
 cc_library(
     name = "nanobenchmark",
     srcs = ["nanobenchmark.cc"],
@@ -606,6 +649,8 @@
     deps = [
         ":platform",
         ":randen_engine",
+        "//absl/base:config",
+        "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
     ],
 )
@@ -616,6 +661,8 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":traits",
+        "//absl/base:config",
         "//absl/meta:type_traits",
     ],
 )
@@ -641,6 +688,7 @@
 cc_test(
     name = "randen_benchmarks",
     size = "medium",
+    timeout = "long",
     srcs = ["randen_benchmarks.cc"],
     copts = ABSL_TEST_COPTS + ABSL_RANDOM_RANDEN_COPTS,
     flaky = 1,
@@ -669,3 +717,15 @@
         "@com_google_googletest//:gtest_main",
     ],
 )
+
+cc_test(
+    name = "uniform_helper_test",
+    size = "small",
+    srcs = ["uniform_helper_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":uniform_helper",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/random/internal/chi_square.cc b/absl/random/internal/chi_square.cc
index c0acc94..640d48c 100644
--- a/absl/random/internal/chi_square.cc
+++ b/absl/random/internal/chi_square.cc
@@ -19,6 +19,7 @@
 #include "absl/random/internal/distribution_test_util.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 namespace {
 
@@ -227,4 +228,5 @@
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/internal/chi_square.h b/absl/random/internal/chi_square.h
index fa8646f..07f4fbe 100644
--- a/absl/random/internal/chi_square.h
+++ b/absl/random/internal/chi_square.h
@@ -26,7 +26,10 @@
 
 #include <cassert>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 constexpr const char kChiSquared[] = "chi-squared";
@@ -80,6 +83,7 @@
 double ChiSquarePValue(double chi_square, int dof);
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_CHI_SQUARE_H_
diff --git a/absl/random/internal/distribution_caller.h b/absl/random/internal/distribution_caller.h
index 0318e1f..fc81b78 100644
--- a/absl/random/internal/distribution_caller.h
+++ b/absl/random/internal/distribution_caller.h
@@ -19,7 +19,12 @@
 
 #include <utility>
 
+#include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/utility/utility.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // DistributionCaller provides an opportunity to overload the general
@@ -27,30 +32,61 @@
 // to intercept such calls.
 template <typename URBG>
 struct DistributionCaller {
-  // Call the provided distribution type. The parameters are expected
-  // to be explicitly specified.
-  // DistrT is the distribution type.
-  // FormatT is the formatter type:
+  // SFINAE to detect whether the URBG type includes a member matching
+  // bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
   //
-  // struct FormatT {
-  //   using result_type = distribution_t::result_type;
-  //   static std::string FormatCall(
-  //       const distribution_t& distr,
-  //       absl::Span<const result_type>);
-  //
-  //   static std::string FormatExpectation(
-  //       absl::string_view match_args,
-  //       absl::Span<const result_t> results);
-  // }
-  //
-  template <typename DistrT, typename FormatT, typename... Args>
-  static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
+  // These live inside BitGenRef so that they have friend access
+  // to MockingBitGen. (see similar methods in DistributionCaller).
+  template <template <class...> class Trait, class AlwaysVoid, class... Args>
+  struct detector : std::false_type {};
+  template <template <class...> class Trait, class... Args>
+  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
+      : std::true_type {};
+
+  template <class T>
+  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
+      std::declval<::absl::base_internal::FastTypeIdType>(),
+      std::declval<void*>(), std::declval<void*>()));
+
+  using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type;
+
+  // Default implementation of distribution caller.
+  template <typename DistrT, typename... Args>
+  static typename DistrT::result_type Impl(std::false_type, URBG* urbg,
+                                           Args&&... args) {
     DistrT dist(std::forward<Args>(args)...);
     return dist(*urbg);
   }
+
+  // Mock implementation of distribution caller.
+  // The underlying KeyT must match the KeyT constructed by MockOverloadSet.
+  template <typename DistrT, typename... Args>
+  static typename DistrT::result_type Impl(std::true_type, URBG* urbg,
+                                           Args&&... args) {
+    using ResultT = typename DistrT::result_type;
+    using ArgTupleT = std::tuple<absl::decay_t<Args>...>;
+    using KeyT = ResultT(DistrT, ArgTupleT);
+
+    ArgTupleT arg_tuple(std::forward<Args>(args)...);
+    ResultT result;
+    if (!urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
+                          &result)) {
+      auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
+      result = dist(*urbg);
+    }
+    return result;
+  }
+
+  // Default implementation of distribution caller.
+  template <typename DistrT, typename... Args>
+  static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
+    return Impl<DistrT, Args...>(HasInvokeMock{}, urbg,
+                                 std::forward<Args>(args)...);
+  }
 };
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
diff --git a/absl/random/internal/distribution_impl.h b/absl/random/internal/distribution_impl.h
deleted file mode 100644
index 9b6ffb0..0000000
--- a/absl/random/internal/distribution_impl.h
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTION_IMPL_H_
-#define ABSL_RANDOM_INTERNAL_DISTRIBUTION_IMPL_H_
-
-// This file contains some implementation details which are used by one or more
-// of the absl random number distributions.
-
-#include <cfloat>
-#include <cstddef>
-#include <cstdint>
-#include <cstring>
-#include <limits>
-#include <type_traits>
-
-#if (defined(_WIN32) || defined(_WIN64)) && defined(_M_IA64)
-#include <intrin.h>  // NOLINT(build/include_order)
-#pragma intrinsic(_umul128)
-#define ABSL_INTERNAL_USE_UMUL128 1
-#endif
-
-#include "absl/base/config.h"
-#include "absl/base/internal/bits.h"
-#include "absl/numeric/int128.h"
-#include "absl/random/internal/fastmath.h"
-#include "absl/random/internal/traits.h"
-
-namespace absl {
-namespace random_internal {
-
-// Creates a double from `bits`, with the template fields controlling the
-// output.
-//
-// RandU64To is both more efficient and generates more unique values in the
-// result interval than known implementations of std::generate_canonical().
-//
-// The `Signed` parameter controls whether positive, negative, or both are
-// returned (thus affecting the output interval).
-//   When Signed == SignedValueT, range is U(-1, 1)
-//   When Signed == NegativeValueT, range is U(-1, 0)
-//   When Signed == PositiveValueT, range is U(0, 1)
-//
-// When the `IncludeZero` parameter is true, the function may return 0 for some
-// inputs, otherwise it never returns 0.
-//
-// The `ExponentBias` parameter determines the scale of the output range by
-// adjusting the exponent.
-//
-// When a value in U(0,1) is required, use:
-//   RandU64ToDouble<PositiveValueT, true, 0>();
-//
-// When a value in U(-1,1) is required, use:
-//   RandU64ToDouble<SignedValueT, false, 0>() => U(-1, 1)
-// This generates more distinct values than the mathematically equivalent
-// expression `U(0, 1) * 2.0 - 1.0`, and is preferable.
-//
-// Scaling the result by powers of 2 (and avoiding a multiply) is also possible:
-//   RandU64ToDouble<PositiveValueT, false, 1>();  => U(0, 2)
-//   RandU64ToDouble<PositiveValueT, false, -1>();  => U(0, 0.5)
-//
-
-// Tristate types controlling the output.
-struct PositiveValueT {};
-struct NegativeValueT {};
-struct SignedValueT {};
-
-// RandU64ToDouble is the double-result variant of RandU64To, described above.
-template <typename Signed, bool IncludeZero, int ExponentBias = 0>
-inline double RandU64ToDouble(uint64_t bits) {
-  static_assert(std::is_same<Signed, PositiveValueT>::value ||
-                    std::is_same<Signed, NegativeValueT>::value ||
-                    std::is_same<Signed, SignedValueT>::value,
-                "");
-
-  // Maybe use the left-most bit for a sign bit.
-  uint64_t sign = std::is_same<Signed, NegativeValueT>::value
-                      ? 0x8000000000000000ull
-                      : 0;  // Sign bits.
-
-  if (std::is_same<Signed, SignedValueT>::value) {
-    sign = bits & 0x8000000000000000ull;
-    bits = bits & 0x7FFFFFFFFFFFFFFFull;
-  }
-  if (IncludeZero) {
-    if (bits == 0u) return 0;
-  }
-
-  // Number of leading zeros is mapped to the exponent: 2^-clz
-  int clz = base_internal::CountLeadingZeros64(bits);
-  // Shift number left to erase leading zeros.
-  bits <<= IncludeZero ? clz : (clz & 63);
-
-  // Shift number right to remove bits that overflow double mantissa.  The
-  // direction of the shift depends on `clz`.
-  bits >>= (64 - DBL_MANT_DIG);
-
-  // Compute IEEE 754 double exponent.
-  // In the Signed case, bits is a 63-bit number with a 0 msb.  Adjust the
-  // exponent to account for that.
-  const uint64_t exp =
-      (std::is_same<Signed, SignedValueT>::value ? 1023U : 1022U) +
-      static_cast<uint64_t>(ExponentBias - clz);
-  constexpr int kExp = DBL_MANT_DIG - 1;
-  // Construct IEEE 754 double from exponent and mantissa.
-  const uint64_t val = sign | (exp << kExp) | (bits & ((1ULL << kExp) - 1U));
-
-  double res;
-  static_assert(sizeof(res) == sizeof(val), "double is not 64 bit");
-  // Memcpy value from "val" to "res" to avoid aliasing problems.  Assumes that
-  // endian-ness is same for double and uint64_t.
-  std::memcpy(&res, &val, sizeof(res));
-
-  return res;
-}
-
-// RandU64ToFloat is the float-result variant of RandU64To, described above.
-template <typename Signed, bool IncludeZero, int ExponentBias = 0>
-inline float RandU64ToFloat(uint64_t bits) {
-  static_assert(std::is_same<Signed, PositiveValueT>::value ||
-                    std::is_same<Signed, NegativeValueT>::value ||
-                    std::is_same<Signed, SignedValueT>::value,
-                "");
-
-  // Maybe use the left-most bit for a sign bit.
-  uint64_t sign = std::is_same<Signed, NegativeValueT>::value
-                      ? 0x80000000ul
-                      : 0;  // Sign bits.
-
-  if (std::is_same<Signed, SignedValueT>::value) {
-    uint64_t a = bits & 0x8000000000000000ull;
-    sign = static_cast<uint32_t>(a >> 32);
-    bits = bits & 0x7FFFFFFFFFFFFFFFull;
-  }
-  if (IncludeZero) {
-    if (bits == 0u) return 0;
-  }
-
-  // Number of leading zeros is mapped to the exponent: 2^-clz
-  int clz = base_internal::CountLeadingZeros64(bits);
-  // Shift number left to erase leading zeros.
-  bits <<= IncludeZero ? clz : (clz & 63);
-  // Shift number right to remove bits that overflow double mantissa.  The
-  // direction of the shift depends on `clz`.
-  bits >>= (64 - FLT_MANT_DIG);
-
-  // Construct IEEE 754 float exponent.
-  // In the Signed case, bits is a 63-bit number with a 0 msb.  Adjust the
-  // exponent to account for that.
-  const uint32_t exp =
-      (std::is_same<Signed, SignedValueT>::value ? 127U : 126U) +
-      static_cast<uint32_t>(ExponentBias - clz);
-  constexpr int kExp = FLT_MANT_DIG - 1;
-  const uint32_t val = sign | (exp << kExp) | (bits & ((1U << kExp) - 1U));
-
-  float res;
-  static_assert(sizeof(res) == sizeof(val), "float is not 32 bit");
-  // Assumes that endian-ness is same for float and uint32_t.
-  std::memcpy(&res, &val, sizeof(res));
-
-  return res;
-}
-
-template <typename Result>
-struct RandU64ToReal {
-  template <typename Signed, bool IncludeZero, int ExponentBias = 0>
-  static inline Result Value(uint64_t bits) {
-    return RandU64ToDouble<Signed, IncludeZero, ExponentBias>(bits);
-  }
-};
-
-template <>
-struct RandU64ToReal<float> {
-  template <typename Signed, bool IncludeZero, int ExponentBias = 0>
-  static inline float Value(uint64_t bits) {
-    return RandU64ToFloat<Signed, IncludeZero, ExponentBias>(bits);
-  }
-};
-
-inline uint128 MultiplyU64ToU128(uint64_t a, uint64_t b) {
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
-  return uint128(static_cast<__uint128_t>(a) * b);
-#elif defined(ABSL_INTERNAL_USE_UMUL128)
-  // uint64_t * uint64_t => uint128 multiply using imul intrinsic on MSVC.
-  uint64_t high = 0;
-  const uint64_t low = _umul128(a, b, &high);
-  return absl::MakeUint128(high, low);
-#else
-  // uint128(a) * uint128(b) in emulated mode computes a full 128-bit x 128-bit
-  // multiply.  However there are many cases where that is not necessary, and it
-  // is only necessary to support a 64-bit x 64-bit = 128-bit multiply.  This is
-  // for those cases.
-  const uint64_t a00 = static_cast<uint32_t>(a);
-  const uint64_t a32 = a >> 32;
-  const uint64_t b00 = static_cast<uint32_t>(b);
-  const uint64_t b32 = b >> 32;
-
-  const uint64_t c00 = a00 * b00;
-  const uint64_t c32a = a00 * b32;
-  const uint64_t c32b = a32 * b00;
-  const uint64_t c64 = a32 * b32;
-
-  const uint32_t carry =
-      static_cast<uint32_t>(((c00 >> 32) + static_cast<uint32_t>(c32a) +
-                             static_cast<uint32_t>(c32b)) >>
-                            32);
-
-  return absl::MakeUint128(c64 + (c32a >> 32) + (c32b >> 32) + carry,
-                           c00 + (c32a << 32) + (c32b << 32));
-#endif
-}
-
-// wide_multiply<T> multiplies two N-bit values to a 2N-bit result.
-template <typename UIntType>
-struct wide_multiply {
-  static constexpr size_t kN = std::numeric_limits<UIntType>::digits;
-  using input_type = UIntType;
-  using result_type = typename random_internal::unsigned_bits<kN * 2>::type;
-
-  static result_type multiply(input_type a, input_type b) {
-    return static_cast<result_type>(a) * b;
-  }
-
-  static input_type hi(result_type r) { return r >> kN; }
-  static input_type lo(result_type r) { return r; }
-
-  static_assert(std::is_unsigned<UIntType>::value,
-                "Class-template wide_multiply<> argument must be unsigned.");
-};
-
-#ifndef ABSL_HAVE_INTRINSIC_INT128
-template <>
-struct wide_multiply<uint64_t> {
-  using input_type = uint64_t;
-  using result_type = uint128;
-
-  static result_type multiply(uint64_t a, uint64_t b) {
-    return MultiplyU64ToU128(a, b);
-  }
-
-  static uint64_t hi(result_type r) { return Uint128High64(r); }
-  static uint64_t lo(result_type r) { return Uint128Low64(r); }
-};
-#endif
-
-}  // namespace random_internal
-}  // namespace absl
-
-#endif  // ABSL_RANDOM_INTERNAL_DISTRIBUTION_IMPL_H_
diff --git a/absl/random/internal/distribution_test_util.cc b/absl/random/internal/distribution_test_util.cc
index 85c8d59..e900565 100644
--- a/absl/random/internal/distribution_test_util.cc
+++ b/absl/random/internal/distribution_test_util.cc
@@ -25,6 +25,7 @@
 #include "absl/strings/str_format.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 namespace {
 
@@ -413,4 +414,5 @@
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/internal/distribution_test_util.h b/absl/random/internal/distribution_test_util.h
index b5ba49f..6d94cf6 100644
--- a/absl/random/internal/distribution_test_util.h
+++ b/absl/random/internal/distribution_test_util.h
@@ -26,6 +26,7 @@
 // non-test code.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // http://webspace.ship.edu/pgmarr/Geo441/Lectures/Lec%205%20-%20Normality%20Testing.pdf
@@ -106,6 +107,7 @@
 double BetaIncompleteInv(double p, double q, double alpha);
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_
diff --git a/absl/random/internal/distributions.h b/absl/random/internal/distributions.h
deleted file mode 100644
index 96f8bae..0000000
--- a/absl/random/internal/distributions.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
-#define ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
-
-#include <type_traits>
-
-#include "absl/meta/type_traits.h"
-#include "absl/random/internal/distribution_caller.h"
-#include "absl/random/internal/traits.h"
-#include "absl/random/internal/uniform_helper.h"
-
-namespace absl {
-namespace random_internal {
-template <typename D>
-struct DistributionFormatTraits;
-
-// UniformImpl implements the core logic of the Uniform<T> call, which is to
-// select the correct distribution type, compute the bounds based on the
-// interval tag, and then generate a value.
-template <typename NumType, typename TagType, typename URBG>
-NumType UniformImpl(TagType tag,
-                    URBG& urbg,  // NOLINT(runtime/references)
-                    NumType lo, NumType hi) {
-  static_assert(
-      std::is_arithmetic<NumType>::value,
-      "absl::Uniform<T>() must use an integer or real parameter type.");
-
-  using distribution_t =
-      UniformDistributionWrapper<absl::decay_t<TagType>, NumType>;
-  using format_t = random_internal::DistributionFormatTraits<distribution_t>;
-  auto a = uniform_lower_bound(tag, lo, hi);
-  auto b = uniform_upper_bound(tag, lo, hi);
-
-  // TODO(lar): it doesn't make a lot of sense to ask for a random number in an
-  // empty range.  Right now we just return a boundary--even though that
-  // boundary is not an acceptable value!  Is there something better we can do
-  // here?
-  if (a > b) return a;
-
-  using gen_t = absl::decay_t<URBG>;
-  return DistributionCaller<gen_t>::template Call<distribution_t, format_t>(
-      &urbg, tag, lo, hi);
-}
-
-// In the absence of an explicitly provided return-type, the template
-// "uniform_inferred_return_t<A, B>" is used to derive a suitable type, based on
-// the data-types of the endpoint-arguments {A lo, B hi}.
-//
-// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the
-// return-type, if one type can be implicitly converted into the other, in a
-// lossless way. The template "is_widening_convertible" implements the
-// compile-time logic for deciding if such a conversion is possible.
-//
-// If no such conversion between {A, B} exists, then the overload for
-// absl::Uniform() will be discarded, and the call will be ill-formed.
-// Return-type for absl::Uniform() when the return-type is inferred.
-template <typename A, typename B>
-using uniform_inferred_return_t =
-    absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>,
-                                        is_widening_convertible<B, A>>::value,
-                      typename std::conditional<
-                          is_widening_convertible<A, B>::value, B, A>::type>;
-
-}  // namespace random_internal
-}  // namespace absl
-
-#endif  // ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
diff --git a/absl/random/internal/explicit_seed_seq.h b/absl/random/internal/explicit_seed_seq.h
index b660ece..6a743ea 100644
--- a/absl/random/internal/explicit_seed_seq.h
+++ b/absl/random/internal/explicit_seed_seq.h
@@ -22,7 +22,10 @@
 #include <iterator>
 #include <vector>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // This class conforms to the C++ Standard "Seed Sequence" concept
@@ -82,6 +85,7 @@
 };
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_EXPLICIT_SEED_SEQ_H_
diff --git a/absl/random/internal/fast_uniform_bits.h b/absl/random/internal/fast_uniform_bits.h
index e8df92f..425aaf7 100644
--- a/absl/random/internal/fast_uniform_bits.h
+++ b/absl/random/internal/fast_uniform_bits.h
@@ -20,7 +20,11 @@
 #include <limits>
 #include <type_traits>
 
+#include "absl/base/config.h"
+#include "absl/meta/type_traits.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 // Returns true if the input value is zero or a power of two. Useful for
 // determining if the range of output values in a URBG
@@ -35,28 +39,17 @@
 template <typename URBG>
 constexpr typename URBG::result_type RangeSize() {
   using result_type = typename URBG::result_type;
+  static_assert((URBG::max)() != (URBG::min)(), "URBG range cannot be 0.");
   return ((URBG::max)() == (std::numeric_limits<result_type>::max)() &&
           (URBG::min)() == std::numeric_limits<result_type>::lowest())
              ? result_type{0}
-             : (URBG::max)() - (URBG::min)() + result_type{1};
-}
-
-template <typename UIntType>
-constexpr UIntType LargestPowerOfTwoLessThanOrEqualTo(UIntType n) {
-  return n < 2 ? n : 2 * LargestPowerOfTwoLessThanOrEqualTo(n / 2);
-}
-
-// Given a URBG generating values in the closed interval [Lo, Hi], returns the
-// largest power of two less than or equal to `Hi - Lo + 1`.
-template <typename URBG>
-constexpr typename URBG::result_type PowerOfTwoSubRangeSize() {
-  return LargestPowerOfTwoLessThanOrEqualTo(RangeSize<URBG>());
+             : ((URBG::max)() - (URBG::min)() + result_type{1});
 }
 
 // Computes the floor of the log. (i.e., std::floor(std::log2(N));
 template <typename UIntType>
 constexpr UIntType IntegerLog2(UIntType n) {
-  return (n <= 1) ? 0 : 1 + IntegerLog2(n / 2);
+  return (n <= 1) ? 0 : 1 + IntegerLog2(n >> 1);
 }
 
 // Returns the number of bits of randomness returned through
@@ -65,18 +58,23 @@
 constexpr size_t NumBits() {
   return RangeSize<URBG>() == 0
              ? std::numeric_limits<typename URBG::result_type>::digits
-             : IntegerLog2(PowerOfTwoSubRangeSize<URBG>());
+             : IntegerLog2(RangeSize<URBG>());
 }
 
 // Given a shift value `n`, constructs a mask with exactly the low `n` bits set.
 // If `n == 0`, all bits are set.
 template <typename UIntType>
-constexpr UIntType MaskFromShift(UIntType n) {
+constexpr UIntType MaskFromShift(size_t n) {
   return ((n % std::numeric_limits<UIntType>::digits) == 0)
              ? ~UIntType{0}
              : (UIntType{1} << n) - UIntType{1};
 }
 
+// Tags used to dispatch FastUniformBits::generate to the simple or more complex
+// entropy extraction algorithm.
+struct SimplifiedLoopTag {};
+struct RejectionLoopTag {};
+
 // FastUniformBits implements a fast path to acquire uniform independent bits
 // from a type which conforms to the [rand.req.urbg] concept.
 // Parameterized by:
@@ -104,50 +102,16 @@
                 "Class-template FastUniformBits<> must be parameterized using "
                 "an unsigned type.");
 
-  // PowerOfTwoVariate() generates a single random variate, always returning a
-  // value in the half-open interval `[0, PowerOfTwoSubRangeSize<URBG>())`. If
-  // the URBG already generates values in a power-of-two range, the generator
-  // itself is used. Otherwise, we use rejection sampling on the largest
-  // possible power-of-two-sized subrange.
-  struct PowerOfTwoTag {};
-  struct RejectionSamplingTag {};
-  template <typename URBG>
-  static typename URBG::result_type PowerOfTwoVariate(
-      URBG& g) {  // NOLINT(runtime/references)
-    using tag =
-        typename std::conditional<IsPowerOfTwoOrZero(RangeSize<URBG>()),
-                                  PowerOfTwoTag, RejectionSamplingTag>::type;
-    return PowerOfTwoVariate(g, tag{});
-  }
-
-  template <typename URBG>
-  static typename URBG::result_type PowerOfTwoVariate(
-      URBG& g,  // NOLINT(runtime/references)
-      PowerOfTwoTag) {
-    return g() - (URBG::min)();
-  }
-
-  template <typename URBG>
-  static typename URBG::result_type PowerOfTwoVariate(
-      URBG& g,  // NOLINT(runtime/references)
-      RejectionSamplingTag) {
-    // Use rejection sampling to ensure uniformity across the range.
-    typename URBG::result_type u;
-    do {
-      u = g() - (URBG::min)();
-    } while (u >= PowerOfTwoSubRangeSize<URBG>());
-    return u;
-  }
-
   // Generate() generates a random value, dispatched on whether
-  // the underlying URBG must loop over multiple calls or not.
+  // the underlying URBG must use rejection sampling to generate a value,
+  // or whether a simplified loop will suffice.
   template <typename URBG>
   result_type Generate(URBG& g,  // NOLINT(runtime/references)
-                       std::true_type /* avoid_looping */);
+                       SimplifiedLoopTag);
 
   template <typename URBG>
   result_type Generate(URBG& g,  // NOLINT(runtime/references)
-                       std::false_type /* avoid_looping */);
+                       RejectionLoopTag);
 };
 
 template <typename UIntType>
@@ -159,31 +123,47 @@
   // Y = (2 ^ kRange) - 1
   static_assert((URBG::max)() > (URBG::min)(),
                 "URBG::max and URBG::min may not be equal.");
+
+  using tag = absl::conditional_t<IsPowerOfTwoOrZero(RangeSize<URBG>()),
+                                  SimplifiedLoopTag, RejectionLoopTag>;
+  return Generate(g, tag{});
+}
+
+template <typename UIntType>
+template <typename URBG>
+typename FastUniformBits<UIntType>::result_type
+FastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)
+                                    SimplifiedLoopTag) {
+  // The simplified version of FastUniformBits works only on URBGs that have
+  // a range that is a power of 2. In this case we simply loop and shift without
+  // attempting to balance the bits across calls.
+  static_assert(IsPowerOfTwoOrZero(RangeSize<URBG>()),
+                "incorrect Generate tag for URBG instance");
+
+  static constexpr size_t kResultBits =
+      std::numeric_limits<result_type>::digits;
+  static constexpr size_t kUrbgBits = NumBits<URBG>();
+  static constexpr size_t kIters =
+      (kResultBits / kUrbgBits) + (kResultBits % kUrbgBits != 0);
+  static constexpr size_t kShift = (kIters == 1) ? 0 : kUrbgBits;
+  static constexpr auto kMin = (URBG::min)();
+
+  result_type r = static_cast<result_type>(g() - kMin);
+  for (size_t n = 1; n < kIters; ++n) {
+    r = (r << kShift) + static_cast<result_type>(g() - kMin);
+  }
+  return r;
+}
+
+template <typename UIntType>
+template <typename URBG>
+typename FastUniformBits<UIntType>::result_type
+FastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)
+                                    RejectionLoopTag) {
+  static_assert(!IsPowerOfTwoOrZero(RangeSize<URBG>()),
+                "incorrect Generate tag for URBG instance");
   using urbg_result_type = typename URBG::result_type;
-  constexpr urbg_result_type kRangeMask =
-      RangeSize<URBG>() == 0
-          ? (std::numeric_limits<urbg_result_type>::max)()
-          : static_cast<urbg_result_type>(PowerOfTwoSubRangeSize<URBG>() - 1);
-  return Generate(g, std::integral_constant<bool, (kRangeMask >= (max)())>{});
-}
 
-template <typename UIntType>
-template <typename URBG>
-typename FastUniformBits<UIntType>::result_type
-FastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)
-                                    std::true_type /* avoid_looping */) {
-  // The width of the result_type is less than than the width of the random bits
-  // provided by URBG.  Thus, generate a single value and then simply mask off
-  // the required bits.
-
-  return PowerOfTwoVariate(g) & (max)();
-}
-
-template <typename UIntType>
-template <typename URBG>
-typename FastUniformBits<UIntType>::result_type
-FastUniformBits<UIntType>::Generate(URBG& g,  // NOLINT(runtime/references)
-                                    std::false_type /* avoid_looping */) {
   // See [rand.adapt.ibits] for more details on the constants calculated below.
   //
   // It is preferable to use roughly the same number of bits from each generator
@@ -196,21 +176,44 @@
   // `kSmallIters` and `kLargeIters` times respectively such
   // that
   //
-  //    `kTotalWidth == kSmallIters * kSmallWidth
-  //                    + kLargeIters * kLargeWidth`
+  //    `kResultBits == kSmallIters * kSmallBits
+  //                    + kLargeIters * kLargeBits`
   //
-  // where `kTotalWidth` is the total number of bits in `result_type`.
+  // where `kResultBits` is the total number of bits in `result_type`.
   //
-  constexpr size_t kTotalWidth = std::numeric_limits<result_type>::digits;
-  constexpr size_t kUrbgWidth = NumBits<URBG>();
-  constexpr size_t kTotalIters =
-      kTotalWidth / kUrbgWidth + (kTotalWidth % kUrbgWidth != 0);
-  constexpr size_t kSmallWidth = kTotalWidth / kTotalIters;
-  constexpr size_t kLargeWidth = kSmallWidth + 1;
+  static constexpr size_t kResultBits =
+      std::numeric_limits<result_type>::digits;                      // w
+  static constexpr urbg_result_type kUrbgRange = RangeSize<URBG>();  // R
+  static constexpr size_t kUrbgBits = NumBits<URBG>();               // m
+
+  // compute the initial estimate of the bits used.
+  // [rand.adapt.ibits] 2 (c)
+  static constexpr size_t kA =  // ceil(w/m)
+      (kResultBits / kUrbgBits) + ((kResultBits % kUrbgBits) != 0);  // n'
+
+  static constexpr size_t kABits = kResultBits / kA;  // w0'
+  static constexpr urbg_result_type kARejection =
+      ((kUrbgRange >> kABits) << kABits);  // y0'
+
+  // refine the selection to reduce the rejection frequency.
+  static constexpr size_t kTotalIters =
+      ((kUrbgRange - kARejection) <= (kARejection / kA)) ? kA : (kA + 1);  // n
+
+  // [rand.adapt.ibits] 2 (b)
+  static constexpr size_t kSmallIters =
+      kTotalIters - (kResultBits % kTotalIters);                   // n0
+  static constexpr size_t kSmallBits = kResultBits / kTotalIters;  // w0
+  static constexpr urbg_result_type kSmallRejection =
+      ((kUrbgRange >> kSmallBits) << kSmallBits);  // y0
+
+  static constexpr size_t kLargeBits = kSmallBits + 1;  // w0+1
+  static constexpr urbg_result_type kLargeRejection =
+      ((kUrbgRange >> kLargeBits) << kLargeBits);  // y1
+
   //
-  // Because `kLargeWidth == kSmallWidth + 1`, it follows that
+  // Because `kLargeBits == kSmallBits + 1`, it follows that
   //
-  //     `kTotalWidth == kTotalIters * kSmallWidth + kLargeIters`
+  //     `kResultBits == kSmallIters * kSmallBits + kLargeIters`
   //
   // and therefore
   //
@@ -221,40 +224,45 @@
   // mentioned above, if the URBG width is a divisor of `kTotalWidth`, then
   // there would be no need for any large iterations (i.e., one loop would
   // suffice), and indeed, in this case, `kLargeIters` would be zero.
-  constexpr size_t kLargeIters = kTotalWidth % kSmallWidth;
-  constexpr size_t kSmallIters =
-      (kTotalWidth - (kLargeWidth * kLargeIters)) / kSmallWidth;
+  static_assert(kResultBits == kSmallIters * kSmallBits +
+                                   (kTotalIters - kSmallIters) * kLargeBits,
+                "Error in looping constant calculations.");
 
-  static_assert(
-      kTotalWidth == kSmallIters * kSmallWidth + kLargeIters * kLargeWidth,
-      "Error in looping constant calculations.");
+  // The small shift is essentially small bits, but due to the potential
+  // of generating a smaller result_type from a larger urbg type, the actual
+  // shift might be 0.
+  static constexpr size_t kSmallShift = kSmallBits % kResultBits;
+  static constexpr auto kSmallMask =
+      MaskFromShift<urbg_result_type>(kSmallShift);
+  static constexpr size_t kLargeShift = kLargeBits % kResultBits;
+  static constexpr auto kLargeMask =
+      MaskFromShift<urbg_result_type>(kLargeShift);
+
+  static constexpr auto kMin = (URBG::min)();
 
   result_type s = 0;
-
-  constexpr size_t kSmallShift = kSmallWidth % kTotalWidth;
-  constexpr result_type kSmallMask = MaskFromShift(result_type{kSmallShift});
   for (size_t n = 0; n < kSmallIters; ++n) {
-    s = (s << kSmallShift) +
-        (static_cast<result_type>(PowerOfTwoVariate(g)) & kSmallMask);
+    urbg_result_type v;
+    do {
+      v = g() - kMin;
+    } while (v >= kSmallRejection);
+
+    s = (s << kSmallShift) + static_cast<result_type>(v & kSmallMask);
   }
 
-  constexpr size_t kLargeShift = kLargeWidth % kTotalWidth;
-  constexpr result_type kLargeMask = MaskFromShift(result_type{kLargeShift});
-  for (size_t n = 0; n < kLargeIters; ++n) {
-    s = (s << kLargeShift) +
-        (static_cast<result_type>(PowerOfTwoVariate(g)) & kLargeMask);
+  for (size_t n = kSmallIters; n < kTotalIters; ++n) {
+    urbg_result_type v;
+    do {
+      v = g() - kMin;
+    } while (v >= kLargeRejection);
+
+    s = (s << kLargeShift) + static_cast<result_type>(v & kLargeMask);
   }
-
-  static_assert(
-      kLargeShift == kSmallShift + 1 ||
-          (kLargeShift == 0 &&
-           kSmallShift == std::numeric_limits<result_type>::digits - 1),
-      "Error in looping constant calculations");
-
   return s;
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_
diff --git a/absl/random/internal/fast_uniform_bits_test.cc b/absl/random/internal/fast_uniform_bits_test.cc
index 9f2e826..cee702d 100644
--- a/absl/random/internal/fast_uniform_bits_test.cc
+++ b/absl/random/internal/fast_uniform_bits_test.cc
@@ -19,6 +19,7 @@
 #include "gtest/gtest.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 namespace {
 
@@ -33,8 +34,8 @@
   using Limits = std::numeric_limits<TypeParam>;
   using FastBits = FastUniformBits<TypeParam>;
 
-  EXPECT_EQ(0, FastBits::min());
-  EXPECT_EQ(Limits::max(), FastBits::max());
+  EXPECT_EQ(0, (FastBits::min)());
+  EXPECT_EQ((Limits::max)(), (FastBits::max)());
 
   constexpr int kIters = 10000;
   std::random_device rd;
@@ -42,8 +43,8 @@
   FastBits fast;
   for (int i = 0; i < kIters; i++) {
     const auto v = fast(gen);
-    EXPECT_LE(v, FastBits::max());
-    EXPECT_GE(v, FastBits::min());
+    EXPECT_LE(v, (FastBits::max)());
+    EXPECT_GE(v, (FastBits::min)());
   }
 }
 
@@ -51,21 +52,26 @@
 struct FakeUrbg {
   using result_type = UIntType;
 
+  FakeUrbg() = default;
+  explicit FakeUrbg(bool r) : reject(r) {}
+
   static constexpr result_type(max)() { return Hi; }
   static constexpr result_type(min)() { return Lo; }
-  result_type operator()() { return Val; }
-};
+  result_type operator()() {
+    // when reject is set, return Hi half the time.
+    return ((++calls % 2) == 1 && reject) ? Hi : Val;
+  }
 
-using UrngOddbits = FakeUrbg<uint8_t, 1, 0xfe, 0x73>;
-using Urng4bits = FakeUrbg<uint8_t, 1, 0x10, 2>;
-using Urng31bits = FakeUrbg<uint32_t, 1, 0xfffffffe, 0x60070f03>;
-using Urng32bits = FakeUrbg<uint32_t, 0, 0xffffffff, 0x74010f01>;
+  bool reject = false;
+  size_t calls = 0;
+};
 
 TEST(FastUniformBitsTest, IsPowerOfTwoOrZero) {
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{0}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{1}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{2}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{3}));
+  EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{4}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{16}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{17}));
   EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint8_t>::max)()));
@@ -74,6 +80,7 @@
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{1}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{2}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{3}));
+  EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{4}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{16}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{17}));
   EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint16_t>::max)()));
@@ -90,183 +97,240 @@
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{1}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{2}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{3}));
+  EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{4}));
   EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{64}));
   EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{17}));
   EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint64_t>::max)()));
 }
 
 TEST(FastUniformBitsTest, IntegerLog2) {
-  EXPECT_EQ(IntegerLog2(uint16_t{0}), 0);
-  EXPECT_EQ(IntegerLog2(uint16_t{1}), 0);
-  EXPECT_EQ(IntegerLog2(uint16_t{2}), 1);
-  EXPECT_EQ(IntegerLog2(uint16_t{3}), 1);
-  EXPECT_EQ(IntegerLog2(uint16_t{4}), 2);
-  EXPECT_EQ(IntegerLog2(uint16_t{5}), 2);
-  EXPECT_EQ(IntegerLog2(std::numeric_limits<uint64_t>::max()), 63);
+  EXPECT_EQ(0, IntegerLog2(uint16_t{0}));
+  EXPECT_EQ(0, IntegerLog2(uint16_t{1}));
+  EXPECT_EQ(1, IntegerLog2(uint16_t{2}));
+  EXPECT_EQ(1, IntegerLog2(uint16_t{3}));
+  EXPECT_EQ(2, IntegerLog2(uint16_t{4}));
+  EXPECT_EQ(2, IntegerLog2(uint16_t{5}));
+  EXPECT_EQ(2, IntegerLog2(uint16_t{7}));
+  EXPECT_EQ(3, IntegerLog2(uint16_t{8}));
+  EXPECT_EQ(63, IntegerLog2((std::numeric_limits<uint64_t>::max)()));
 }
 
 TEST(FastUniformBitsTest, RangeSize) {
-  EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 0, 3>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 2>>()), 1);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 5>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 6>>()), 5);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 10>>()), 9);
+  EXPECT_EQ(2, (RangeSize<FakeUrbg<uint8_t, 0, 1>>()));
+  EXPECT_EQ(3, (RangeSize<FakeUrbg<uint8_t, 0, 2>>()));
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint8_t, 0, 3>>()));
+  //  EXPECT_EQ(0, (RangeSize<FakeUrbg<uint8_t, 2, 2>>()));
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint8_t, 2, 5>>()));
+  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint8_t, 2, 6>>()));
+  EXPECT_EQ(9, (RangeSize<FakeUrbg<uint8_t, 2, 10>>()));
   EXPECT_EQ(
-      (RangeSize<FakeUrbg<uint8_t, 0, std::numeric_limits<uint8_t>::max()>>()),
-      0);
+      0, (RangeSize<
+             FakeUrbg<uint8_t, 0, (std::numeric_limits<uint8_t>::max)()>>()));
 
-  EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 0, 3>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 2, 2>>()), 1);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 2, 5>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 2, 6>>()), 5);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 1000, 1017>>()), 18);
-  EXPECT_EQ((RangeSize<
-                FakeUrbg<uint16_t, 0, std::numeric_limits<uint16_t>::max()>>()),
-            0);
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint16_t, 0, 3>>()));
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint16_t, 2, 5>>()));
+  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint16_t, 2, 6>>()));
+  EXPECT_EQ(18, (RangeSize<FakeUrbg<uint16_t, 1000, 1017>>()));
+  EXPECT_EQ(
+      0, (RangeSize<
+             FakeUrbg<uint16_t, 0, (std::numeric_limits<uint16_t>::max)()>>()));
 
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 0, 3>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 2>>()), 1);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 5>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 6>>()), 5);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 1000, 1017>>()), 18);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 0, 0xffffffff>>()), 0);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 1, 0xffffffff>>()), 0xffffffff);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 1, 0xfffffffe>>()), 0xfffffffe);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 0xfffffffe>>()), 0xfffffffd);
-  EXPECT_EQ((RangeSize<
-                FakeUrbg<uint32_t, 0, std::numeric_limits<uint32_t>::max()>>()),
-            0);
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint32_t, 0, 3>>()));
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint32_t, 2, 5>>()));
+  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint32_t, 2, 6>>()));
+  EXPECT_EQ(18, (RangeSize<FakeUrbg<uint32_t, 1000, 1017>>()));
+  EXPECT_EQ(0, (RangeSize<FakeUrbg<uint32_t, 0, 0xffffffff>>()));
+  EXPECT_EQ(0xffffffff, (RangeSize<FakeUrbg<uint32_t, 1, 0xffffffff>>()));
+  EXPECT_EQ(0xfffffffe, (RangeSize<FakeUrbg<uint32_t, 1, 0xfffffffe>>()));
+  EXPECT_EQ(0xfffffffd, (RangeSize<FakeUrbg<uint32_t, 2, 0xfffffffe>>()));
+  EXPECT_EQ(
+      0, (RangeSize<
+             FakeUrbg<uint32_t, 0, (std::numeric_limits<uint32_t>::max)()>>()));
 
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 0, 3>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 2>>()), 1);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 5>>()), 4);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 6>>()), 5);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1000, 1017>>()), 18);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 0, 0xffffffff>>()), 0x100000000ull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xffffffff>>()), 0xffffffffull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffe>>()), 0xfffffffeull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffe>>()), 0xfffffffdull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 0, 0xffffffffffffffffull>>()), 0ull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xffffffffffffffffull>>()),
-            0xffffffffffffffffull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffffffffffeull>>()),
-            0xfffffffffffffffeull);
-  EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffffffffffeull>>()),
-            0xfffffffffffffffdull);
-  EXPECT_EQ((RangeSize<
-                FakeUrbg<uint64_t, 0, std::numeric_limits<uint64_t>::max()>>()),
-            0);
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint64_t, 0, 3>>()));
+  EXPECT_EQ(4, (RangeSize<FakeUrbg<uint64_t, 2, 5>>()));
+  EXPECT_EQ(5, (RangeSize<FakeUrbg<uint64_t, 2, 6>>()));
+  EXPECT_EQ(18, (RangeSize<FakeUrbg<uint64_t, 1000, 1017>>()));
+  EXPECT_EQ(0x100000000, (RangeSize<FakeUrbg<uint64_t, 0, 0xffffffff>>()));
+  EXPECT_EQ(0xffffffff, (RangeSize<FakeUrbg<uint64_t, 1, 0xffffffff>>()));
+  EXPECT_EQ(0xfffffffe, (RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffe>>()));
+  EXPECT_EQ(0xfffffffd, (RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffe>>()));
+  EXPECT_EQ(0, (RangeSize<FakeUrbg<uint64_t, 0, 0xffffffffffffffff>>()));
+  EXPECT_EQ(0xffffffffffffffff,
+            (RangeSize<FakeUrbg<uint64_t, 1, 0xffffffffffffffff>>()));
+  EXPECT_EQ(0xfffffffffffffffe,
+            (RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffffffffffe>>()));
+  EXPECT_EQ(0xfffffffffffffffd,
+            (RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffffffffffe>>()));
+  EXPECT_EQ(
+      0, (RangeSize<
+             FakeUrbg<uint64_t, 0, (std::numeric_limits<uint64_t>::max)()>>()));
 }
 
-TEST(FastUniformBitsTest, PowerOfTwoSubRangeSize) {
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 0, 3>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 2>>()), 1);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 5>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 6>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 10>>()), 8);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<
-                FakeUrbg<uint8_t, 0, std::numeric_limits<uint8_t>::max()>>()),
-            0);
+// The constants need to be choosen so that an infinite rejection loop doesn't
+// happen...
+using Urng1_5bit = FakeUrbg<uint8_t, 0, 2, 0>;  // ~1.5 bits (range 3)
+using Urng4bits = FakeUrbg<uint8_t, 1, 0x10, 2>;
+using Urng22bits = FakeUrbg<uint32_t, 0, 0x3fffff, 0x301020>;
+using Urng31bits = FakeUrbg<uint32_t, 1, 0xfffffffe, 0x60070f03>;  // ~31.9 bits
+using Urng32bits = FakeUrbg<uint32_t, 0, 0xffffffff, 0x74010f01>;
+using Urng33bits =
+    FakeUrbg<uint64_t, 1, 0x1ffffffff, 0x013301033>;  // ~32.9 bits
+using Urng63bits = FakeUrbg<uint64_t, 1, 0xfffffffffffffffe,
+                            0xfedcba9012345678>;  // ~63.9 bits
+using Urng64bits =
+    FakeUrbg<uint64_t, 0, 0xffffffffffffffff, 0x123456780fedcba9>;
 
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 0, 3>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 2, 2>>()), 1);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 2, 5>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 2, 6>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 1000, 1017>>()), 16);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<
-                FakeUrbg<uint16_t, 0, std::numeric_limits<uint16_t>::max()>>()),
-            0);
-
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 0, 3>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 2, 2>>()), 1);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 2, 5>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 2, 6>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 1000, 1017>>()), 16);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 0, 0xffffffff>>()), 0);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 1, 0xffffffff>>()),
-            0x80000000);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 1, 0xfffffffe>>()),
-            0x80000000);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<
-                FakeUrbg<uint32_t, 0, std::numeric_limits<uint32_t>::max()>>()),
-            0);
-
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 0, 3>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 2, 2>>()), 1);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 2, 5>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 2, 6>>()), 4);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1000, 1017>>()), 16);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 0, 0xffffffff>>()),
-            0x100000000ull);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xffffffff>>()),
-            0x80000000ull);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xfffffffe>>()),
-            0x80000000ull);
-  EXPECT_EQ(
-      (PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 0, 0xffffffffffffffffull>>()),
-      0);
-  EXPECT_EQ(
-      (PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xffffffffffffffffull>>()),
-      0x8000000000000000ull);
-  EXPECT_EQ(
-      (PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xfffffffffffffffeull>>()),
-      0x8000000000000000ull);
-  EXPECT_EQ((PowerOfTwoSubRangeSize<
-                FakeUrbg<uint64_t, 0, std::numeric_limits<uint64_t>::max()>>()),
-            0);
-}
-
-TEST(FastUniformBitsTest, Urng4_VariousOutputs) {
+TEST(FastUniformBitsTest, OutputsUpTo32Bits) {
   // Tests that how values are composed; the single-bit deltas should be spread
   // across each invocation.
+  Urng1_5bit urng1_5;
   Urng4bits urng4;
+  Urng22bits urng22;
   Urng31bits urng31;
   Urng32bits urng32;
+  Urng33bits urng33;
+  Urng63bits urng63;
+  Urng64bits urng64;
 
   // 8-bit types
   {
     FastUniformBits<uint8_t> fast8;
+    EXPECT_EQ(0x0, fast8(urng1_5));
     EXPECT_EQ(0x11, fast8(urng4));
+    EXPECT_EQ(0x20, fast8(urng22));
     EXPECT_EQ(0x2, fast8(urng31));
     EXPECT_EQ(0x1, fast8(urng32));
+    EXPECT_EQ(0x32, fast8(urng33));
+    EXPECT_EQ(0x77, fast8(urng63));
+    EXPECT_EQ(0xa9, fast8(urng64));
   }
 
   // 16-bit types
   {
     FastUniformBits<uint16_t> fast16;
+    EXPECT_EQ(0x0, fast16(urng1_5));
     EXPECT_EQ(0x1111, fast16(urng4));
-    EXPECT_EQ(0xf02, fast16(urng31));
-    EXPECT_EQ(0xf01, fast16(urng32));
+    EXPECT_EQ(0x1020, fast16(urng22));
+    EXPECT_EQ(0x0f02, fast16(urng31));
+    EXPECT_EQ(0x0f01, fast16(urng32));
+    EXPECT_EQ(0x1032, fast16(urng33));
+    EXPECT_EQ(0x5677, fast16(urng63));
+    EXPECT_EQ(0xcba9, fast16(urng64));
   }
 
   // 32-bit types
   {
     FastUniformBits<uint32_t> fast32;
+    EXPECT_EQ(0x0, fast32(urng1_5));
     EXPECT_EQ(0x11111111, fast32(urng4));
+    EXPECT_EQ(0x08301020, fast32(urng22));
     EXPECT_EQ(0x0f020f02, fast32(urng31));
     EXPECT_EQ(0x74010f01, fast32(urng32));
+    EXPECT_EQ(0x13301032, fast32(urng33));
+    EXPECT_EQ(0x12345677, fast32(urng63));
+    EXPECT_EQ(0x0fedcba9, fast32(urng64));
+  }
+}
+
+TEST(FastUniformBitsTest, Outputs64Bits) {
+  // Tests that how values are composed; the single-bit deltas should be spread
+  // across each invocation.
+  FastUniformBits<uint64_t> fast64;
+
+  {
+    FakeUrbg<uint8_t, 0, 1, 0> urng0;
+    FakeUrbg<uint8_t, 0, 1, 1> urng1;
+    Urng4bits urng4;
+    Urng22bits urng22;
+    Urng31bits urng31;
+    Urng32bits urng32;
+    Urng33bits urng33;
+    Urng63bits urng63;
+    Urng64bits urng64;
+
+    // somewhat degenerate cases only create a single bit.
+    EXPECT_EQ(0x0, fast64(urng0));
+    EXPECT_EQ(64, urng0.calls);
+    EXPECT_EQ(0xffffffffffffffff, fast64(urng1));
+    EXPECT_EQ(64, urng1.calls);
+
+    // less degenerate cases.
+    EXPECT_EQ(0x1111111111111111, fast64(urng4));
+    EXPECT_EQ(16, urng4.calls);
+    EXPECT_EQ(0x01020c0408301020, fast64(urng22));
+    EXPECT_EQ(3, urng22.calls);
+    EXPECT_EQ(0x387811c3c0870f02, fast64(urng31));
+    EXPECT_EQ(3, urng31.calls);
+    EXPECT_EQ(0x74010f0174010f01, fast64(urng32));
+    EXPECT_EQ(2, urng32.calls);
+    EXPECT_EQ(0x808194040cb01032, fast64(urng33));
+    EXPECT_EQ(3, urng33.calls);
+    EXPECT_EQ(0x1234567712345677, fast64(urng63));
+    EXPECT_EQ(2, urng63.calls);
+    EXPECT_EQ(0x123456780fedcba9, fast64(urng64));
+    EXPECT_EQ(1, urng64.calls);
   }
 
-  // 64-bit types
+  // The 1.5 bit case is somewhat interesting in that the algorithm refinement
+  // causes one extra small sample. Comments here reference the names used in
+  // [rand.adapt.ibits] that correspond to this case.
   {
-    FastUniformBits<uint64_t> fast64;
-    EXPECT_EQ(0x1111111111111111, fast64(urng4));
+    Urng1_5bit urng1_5;
+
+    // w = 64
+    // R = 3
+    // m = 1
+    // n' = 64
+    // w0' = 1
+    // y0' = 2
+    // n = (1 <= 0) > 64 : 65 = 65
+    // n0 = 65 - (64%65) = 1
+    // n1 = 64
+    // w0 = 0
+    // y0 = 3
+    // w1 = 1
+    // y1 = 2
+    EXPECT_EQ(0x0, fast64(urng1_5));
+    EXPECT_EQ(65, urng1_5.calls);
+  }
+
+  // Validate rejections for non-power-of-2 cases.
+  {
+    Urng1_5bit urng1_5(true);
+    Urng31bits urng31(true);
+    Urng33bits urng33(true);
+    Urng63bits urng63(true);
+
+    // For 1.5 bits, there would be 1+2*64, except the first
+    // value was accepted and shifted off the end.
+    EXPECT_EQ(0, fast64(urng1_5));
+    EXPECT_EQ(128, urng1_5.calls);
     EXPECT_EQ(0x387811c3c0870f02, fast64(urng31));
-    EXPECT_EQ(0x74010f0174010f01, fast64(urng32));
+    EXPECT_EQ(6, urng31.calls);
+    EXPECT_EQ(0x808194040cb01032, fast64(urng33));
+    EXPECT_EQ(6, urng33.calls);
+    EXPECT_EQ(0x1234567712345677, fast64(urng63));
+    EXPECT_EQ(4, urng63.calls);
   }
 }
 
 TEST(FastUniformBitsTest, URBG32bitRegression) {
   // Validate with deterministic 32-bit std::minstd_rand
   // to ensure that operator() performs as expected.
+
+  EXPECT_EQ(2147483646, RangeSize<std::minstd_rand>());
+  EXPECT_EQ(30, IntegerLog2(RangeSize<std::minstd_rand>()));
+
   std::minstd_rand gen(1);
   FastUniformBits<uint64_t> fast64;
 
-  EXPECT_EQ(0x05e47095f847c122ull, fast64(gen));
-  EXPECT_EQ(0x8f82c1ba30b64d22ull, fast64(gen));
-  EXPECT_EQ(0x3b971a3558155039ull, fast64(gen));
+  EXPECT_EQ(0x05e47095f8791f45, fast64(gen));
+  EXPECT_EQ(0x028be17e3c07c122, fast64(gen));
+  EXPECT_EQ(0x55d2847c1626e8c2, fast64(gen));
 }
 
 }  // namespace
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/internal/fastmath.h b/absl/random/internal/fastmath.h
index 4bd1841..963b769 100644
--- a/absl/random/internal/fastmath.h
+++ b/absl/random/internal/fastmath.h
@@ -22,26 +22,22 @@
 #include <cmath>
 #include <cstdint>
 
-#include "absl/base/internal/bits.h"
+#include "absl/numeric/bits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
-// Returns the position of the first bit set.
-inline int LeadingSetBit(uint64_t n) {
-  return 64 - base_internal::CountLeadingZeros64(n);
-}
-
 // Compute log2(n) using integer operations.
 // While std::log2 is more accurate than std::log(n) / std::log(2), for
 // very large numbers--those close to std::numeric_limits<uint64_t>::max() - 2,
 // for instance--std::log2 rounds up rather than down, which introduces
 // definite skew in the results.
 inline int IntLog2Floor(uint64_t n) {
-  return (n <= 1) ? 0 : (63 - base_internal::CountLeadingZeros64(n));
+  return (n <= 1) ? 0 : (63 - countl_zero(n));
 }
 inline int IntLog2Ceil(uint64_t n) {
-  return (n <= 1) ? 0 : (64 - base_internal::CountLeadingZeros64(n - 1));
+  return (n <= 1) ? 0 : (64 - countl_zero(n - 1));
 }
 
 inline double StirlingLogFactorial(double n) {
@@ -54,19 +50,8 @@
          (1.0 / 360.0) * ninv * ninv * ninv;
 }
 
-// Rotate value right.
-//
-// We only implement the uint32_t / uint64_t versions because
-// 1) those are the only ones we use, and
-// 2) those are the only ones where clang detects the rotate idiom correctly.
-inline constexpr uint32_t rotr(uint32_t value, uint8_t bits) {
-  return (value >> (bits & 31)) | (value << ((-bits) & 31));
-}
-inline constexpr uint64_t rotr(uint64_t value, uint8_t bits) {
-  return (value >> (bits & 63)) | (value << ((-bits) & 63));
-}
-
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_FASTMATH_H_
diff --git a/absl/random/internal/fastmath_test.cc b/absl/random/internal/fastmath_test.cc
index 65859c2..0d6f9dc 100644
--- a/absl/random/internal/fastmath_test.cc
+++ b/absl/random/internal/fastmath_test.cc
@@ -27,19 +27,6 @@
 
 namespace {
 
-TEST(DistributionImplTest, LeadingSetBit) {
-  using absl::random_internal::LeadingSetBit;
-  constexpr uint64_t kZero = 0;
-  EXPECT_EQ(0, LeadingSetBit(kZero));
-  EXPECT_EQ(64, LeadingSetBit(~kZero));
-
-  for (int index = 0; index < 64; index++) {
-    uint64_t x = static_cast<uint64_t>(1) << index;
-    EXPECT_EQ(index + 1, LeadingSetBit(x)) << index;
-    EXPECT_EQ(index + 1, LeadingSetBit(x + x - 1)) << index;
-  }
-}
-
 TEST(FastMathTest, IntLog2FloorTest) {
   using absl::random_internal::IntLog2Floor;
   constexpr uint64_t kZero = 0;
diff --git a/absl/random/internal/gaussian_distribution_gentables.cc b/absl/random/internal/gaussian_distribution_gentables.cc
index 16a23cb..a95333d 100644
--- a/absl/random/internal/gaussian_distribution_gentables.cc
+++ b/absl/random/internal/gaussian_distribution_gentables.cc
@@ -27,6 +27,7 @@
 #include "absl/base/macros.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 namespace {
 
@@ -110,12 +111,9 @@
          "\n"
          "#include \"absl/random/gaussian_distribution.h\"\n"
          "\n"
-         // "namespace " and "absl" are broken apart so as not to conflict with
-         // script that adds the LTS inline namespace.
-         "namespace "
-         "absl {\n"
-         "namespace "
-         "random_internal {\n"
+         "namespace absl {\n"
+         "ABSL_NAMESPACE_BEGIN\n"
+         "namespace random_internal {\n"
          "\n"
          "const gaussian_distribution_base::Tables\n"
          "    gaussian_distribution_base::zg_ = {\n";
@@ -124,10 +122,9 @@
   FormatArrayContents(os, tables_.f);
   *os << "};\n"
          "\n"
-         "}  // namespace "
-         "random_internal\n"
-         "}  // namespace "
-         "absl\n"
+         "}  // namespace random_internal\n"
+         "ABSL_NAMESPACE_END\n"
+         "}  // namespace absl\n"
          "\n"
          "// clang-format on\n"
          "// END GENERATED CODE";
@@ -135,6 +132,7 @@
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 int main(int, char**) {
diff --git a/absl/random/internal/generate_real.h b/absl/random/internal/generate_real.h
new file mode 100644
index 0000000..4f62873
--- /dev/null
+++ b/absl/random/internal/generate_real.h
@@ -0,0 +1,146 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_
+#define ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_
+
+// This file contains some implementation details which are used by one or more
+// of the absl random number distributions.
+
+#include <cstdint>
+#include <cstring>
+#include <limits>
+#include <type_traits>
+
+#include "absl/meta/type_traits.h"
+#include "absl/numeric/bits.h"
+#include "absl/random/internal/fastmath.h"
+#include "absl/random/internal/traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// Tristate tag types controlling the output of GenerateRealFromBits.
+struct GeneratePositiveTag {};
+struct GenerateNegativeTag {};
+struct GenerateSignedTag {};
+
+// GenerateRealFromBits generates a single real value from a single 64-bit
+// `bits` with template fields controlling the output.
+//
+// The `SignedTag` parameter controls whether positive, negative,
+// or either signed/unsigned may be returned.
+//   When SignedTag == GeneratePositiveTag, range is U(0, 1)
+//   When SignedTag == GenerateNegativeTag, range is U(-1, 0)
+//   When SignedTag == GenerateSignedTag, range is U(-1, 1)
+//
+// When the `IncludeZero` parameter is true, the function may return 0 for some
+// inputs, otherwise it never returns 0.
+//
+// When a value in U(0,1) is required, use:
+//   Uniform64ToReal<double, PositiveValueT, true>;
+//
+// When a value in U(-1,1) is required, use:
+//   Uniform64ToReal<double, SignedValueT, false>;
+//
+//   This generates more distinct values than the mathematical equivalent
+//   `U(0, 1) * 2.0 - 1.0`.
+//
+// Scaling the result by powers of 2 (and avoiding a multiply) is also possible:
+//   GenerateRealFromBits<double>(..., -1);  => U(0, 0.5)
+//   GenerateRealFromBits<double>(..., 1);   => U(0, 2)
+//
+template <typename RealType,  // Real type, either float or double.
+          typename SignedTag = GeneratePositiveTag,  // Whether a positive,
+                                                     // negative, or signed
+                                                     // value is generated.
+          bool IncludeZero = true>
+inline RealType GenerateRealFromBits(uint64_t bits, int exp_bias = 0) {
+  using real_type = RealType;
+  using uint_type = absl::conditional_t<std::is_same<real_type, float>::value,
+                                        uint32_t, uint64_t>;
+
+  static_assert(
+      (std::is_same<double, real_type>::value ||
+       std::is_same<float, real_type>::value),
+      "GenerateRealFromBits must be parameterized by either float or double.");
+
+  static_assert(sizeof(uint_type) == sizeof(real_type),
+                "Mismatched unsinged and real types.");
+
+  static_assert((std::numeric_limits<real_type>::is_iec559 &&
+                 std::numeric_limits<real_type>::radix == 2),
+                "RealType representation is not IEEE 754 binary.");
+
+  static_assert((std::is_same<SignedTag, GeneratePositiveTag>::value ||
+                 std::is_same<SignedTag, GenerateNegativeTag>::value ||
+                 std::is_same<SignedTag, GenerateSignedTag>::value),
+                "");
+
+  static constexpr int kExp = std::numeric_limits<real_type>::digits - 1;
+  static constexpr uint_type kMask = (static_cast<uint_type>(1) << kExp) - 1u;
+  static constexpr int kUintBits = sizeof(uint_type) * 8;
+
+  int exp = exp_bias + int{std::numeric_limits<real_type>::max_exponent - 2};
+
+  // Determine the sign bit.
+  // Depending on the SignedTag, this may use the left-most bit
+  // or it may be a constant value.
+  uint_type sign = std::is_same<SignedTag, GenerateNegativeTag>::value
+                       ? (static_cast<uint_type>(1) << (kUintBits - 1))
+                       : 0;
+  if (std::is_same<SignedTag, GenerateSignedTag>::value) {
+    if (std::is_same<uint_type, uint64_t>::value) {
+      sign = bits & uint64_t{0x8000000000000000};
+    }
+    if (std::is_same<uint_type, uint32_t>::value) {
+      const uint64_t tmp = bits & uint64_t{0x8000000000000000};
+      sign = static_cast<uint32_t>(tmp >> 32);
+    }
+    // adjust the bits and the exponent to account for removing
+    // the leading bit.
+    bits = bits & uint64_t{0x7FFFFFFFFFFFFFFF};
+    exp++;
+  }
+  if (IncludeZero) {
+    if (bits == 0u) return 0;
+  }
+
+  // Number of leading zeros is mapped to the exponent: 2^-clz
+  // bits is 0..01xxxxxx. After shifting, we're left with 1xxx...0..0
+  int clz = countl_zero(bits);
+  bits <<= (IncludeZero ? clz : (clz & 63));  // remove 0-bits.
+  exp -= clz;                                 // set the exponent.
+  bits >>= (63 - kExp);
+
+  // Construct the 32-bit or 64-bit IEEE 754 floating-point value from
+  // the individual fields: sign, exp, mantissa(bits).
+  uint_type val =
+      (std::is_same<SignedTag, GeneratePositiveTag>::value ? 0u : sign) |
+      (static_cast<uint_type>(exp) << kExp) |
+      (static_cast<uint_type>(bits) & kMask);
+
+  // bit_cast to the output-type
+  real_type result;
+  memcpy(static_cast<void*>(&result), static_cast<const void*>(&val),
+         sizeof(result));
+  return result;
+}
+
+}  // namespace random_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_
diff --git a/absl/random/internal/distribution_impl_test.cc b/absl/random/internal/generate_real_test.cc
similarity index 79%
rename from absl/random/internal/distribution_impl_test.cc
rename to absl/random/internal/generate_real_test.cc
index 09e7a31..b099dbf 100644
--- a/absl/random/internal/distribution_impl_test.cc
+++ b/absl/random/internal/generate_real_test.cc
@@ -12,57 +12,74 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/random/internal/distribution_impl.h"
+#include "absl/random/internal/generate_real.h"
+
+#include <cfloat>
+#include <cstddef>
+#include <cstdint>
+#include <string>
 
 #include "gtest/gtest.h"
-#include "absl/base/internal/bits.h"
 #include "absl/flags/flag.h"
-#include "absl/numeric/int128.h"
+#include "absl/numeric/bits.h"
 
 ABSL_FLAG(int64_t, absl_random_test_trials, 50000,
           "Number of trials for the probability tests.");
 
-using absl::random_internal::NegativeValueT;
-using absl::random_internal::PositiveValueT;
-using absl::random_internal::RandU64ToDouble;
-using absl::random_internal::RandU64ToFloat;
-using absl::random_internal::SignedValueT;
+using absl::random_internal::GenerateNegativeTag;
+using absl::random_internal::GeneratePositiveTag;
+using absl::random_internal::GenerateRealFromBits;
+using absl::random_internal::GenerateSignedTag;
 
 namespace {
 
-TEST(DistributionImplTest, U64ToFloat_Positive_NoZero_Test) {
+TEST(GenerateRealTest, U64ToFloat_Positive_NoZero_Test) {
   auto ToFloat = [](uint64_t a) {
-    return RandU64ToFloat<PositiveValueT, false>(a);
+    return GenerateRealFromBits<float, GeneratePositiveTag, false>(a);
   };
   EXPECT_EQ(ToFloat(0x0000000000000000), 2.710505431e-20f);
   EXPECT_EQ(ToFloat(0x0000000000000001), 5.421010862e-20f);
   EXPECT_EQ(ToFloat(0x8000000000000000), 0.5);
+  EXPECT_EQ(ToFloat(0x8000000000000001), 0.5);
   EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 0.9999999404f);
 }
 
-TEST(DistributionImplTest, U64ToFloat_Positive_Zero_Test) {
+TEST(GenerateRealTest, U64ToFloat_Positive_Zero_Test) {
   auto ToFloat = [](uint64_t a) {
-    return RandU64ToFloat<PositiveValueT, true>(a);
+    return GenerateRealFromBits<float, GeneratePositiveTag, true>(a);
   };
   EXPECT_EQ(ToFloat(0x0000000000000000), 0.0);
   EXPECT_EQ(ToFloat(0x0000000000000001), 5.421010862e-20f);
   EXPECT_EQ(ToFloat(0x8000000000000000), 0.5);
+  EXPECT_EQ(ToFloat(0x8000000000000001), 0.5);
   EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 0.9999999404f);
 }
 
-TEST(DistributionImplTest, U64ToFloat_Negative_NoZero_Test) {
+TEST(GenerateRealTest, U64ToFloat_Negative_NoZero_Test) {
   auto ToFloat = [](uint64_t a) {
-    return RandU64ToFloat<NegativeValueT, false>(a);
+    return GenerateRealFromBits<float, GenerateNegativeTag, false>(a);
   };
   EXPECT_EQ(ToFloat(0x0000000000000000), -2.710505431e-20f);
   EXPECT_EQ(ToFloat(0x0000000000000001), -5.421010862e-20f);
   EXPECT_EQ(ToFloat(0x8000000000000000), -0.5);
+  EXPECT_EQ(ToFloat(0x8000000000000001), -0.5);
   EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);
 }
 
-TEST(DistributionImplTest, U64ToFloat_Signed_NoZero_Test) {
+TEST(GenerateRealTest, U64ToFloat_Negative_Zero_Test) {
   auto ToFloat = [](uint64_t a) {
-    return RandU64ToFloat<SignedValueT, false>(a);
+    return GenerateRealFromBits<float, GenerateNegativeTag, true>(a);
+  };
+  EXPECT_EQ(ToFloat(0x0000000000000000), 0.0);
+  EXPECT_EQ(ToFloat(0x0000000000000001), -5.421010862e-20f);
+  EXPECT_EQ(ToFloat(0x8000000000000000), -0.5);
+  EXPECT_EQ(ToFloat(0x8000000000000001), -0.5);
+  EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);
+}
+
+TEST(GenerateRealTest, U64ToFloat_Signed_NoZero_Test) {
+  auto ToFloat = [](uint64_t a) {
+    return GenerateRealFromBits<float, GenerateSignedTag, false>(a);
   };
   EXPECT_EQ(ToFloat(0x0000000000000000), 5.421010862e-20f);
   EXPECT_EQ(ToFloat(0x0000000000000001), 1.084202172e-19f);
@@ -72,9 +89,9 @@
   EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);
 }
 
-TEST(DistributionImplTest, U64ToFloat_Signed_Zero_Test) {
+TEST(GenerateRealTest, U64ToFloat_Signed_Zero_Test) {
   auto ToFloat = [](uint64_t a) {
-    return RandU64ToFloat<SignedValueT, true>(a);
+    return GenerateRealFromBits<float, GenerateSignedTag, true>(a);
   };
   EXPECT_EQ(ToFloat(0x0000000000000000), 0);
   EXPECT_EQ(ToFloat(0x0000000000000001), 1.084202172e-19f);
@@ -84,9 +101,9 @@
   EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);
 }
 
-TEST(DistributionImplTest, U64ToFloat_Signed_Bias_Test) {
+TEST(GenerateRealTest, U64ToFloat_Signed_Bias_Test) {
   auto ToFloat = [](uint64_t a) {
-    return RandU64ToFloat<SignedValueT, true, 1>(a);
+    return GenerateRealFromBits<float, GenerateSignedTag, true>(a, 1);
   };
   EXPECT_EQ(ToFloat(0x0000000000000000), 0);
   EXPECT_EQ(ToFloat(0x0000000000000001), 2 * 1.084202172e-19f);
@@ -96,9 +113,9 @@
   EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 2 * -0.9999999404f);
 }
 
-TEST(DistributionImplTest, U64ToFloatTest) {
+TEST(GenerateRealTest, U64ToFloatTest) {
   auto ToFloat = [](uint64_t a) -> float {
-    return RandU64ToFloat<PositiveValueT, true>(a);
+    return GenerateRealFromBits<float, GeneratePositiveTag, true>(a);
   };
 
   EXPECT_EQ(ToFloat(0x0000000000000000), 0.0f);
@@ -150,44 +167,60 @@
   }
 }
 
-TEST(DistributionImplTest, U64ToDouble_Positive_NoZero_Test) {
+TEST(GenerateRealTest, U64ToDouble_Positive_NoZero_Test) {
   auto ToDouble = [](uint64_t a) {
-    return RandU64ToDouble<PositiveValueT, false>(a);
+    return GenerateRealFromBits<double, GeneratePositiveTag, false>(a);
   };
 
   EXPECT_EQ(ToDouble(0x0000000000000000), 2.710505431213761085e-20);
   EXPECT_EQ(ToDouble(0x0000000000000001), 5.42101086242752217004e-20);
   EXPECT_EQ(ToDouble(0x0000000000000002), 1.084202172485504434e-19);
   EXPECT_EQ(ToDouble(0x8000000000000000), 0.5);
+  EXPECT_EQ(ToDouble(0x8000000000000001), 0.5);
   EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), 0.999999999999999888978);
 }
 
-TEST(DistributionImplTest, U64ToDouble_Positive_Zero_Test) {
+TEST(GenerateRealTest, U64ToDouble_Positive_Zero_Test) {
   auto ToDouble = [](uint64_t a) {
-    return RandU64ToDouble<PositiveValueT, true>(a);
+    return GenerateRealFromBits<double, GeneratePositiveTag, true>(a);
   };
 
   EXPECT_EQ(ToDouble(0x0000000000000000), 0.0);
   EXPECT_EQ(ToDouble(0x0000000000000001), 5.42101086242752217004e-20);
   EXPECT_EQ(ToDouble(0x8000000000000000), 0.5);
+  EXPECT_EQ(ToDouble(0x8000000000000001), 0.5);
   EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), 0.999999999999999888978);
 }
 
-TEST(DistributionImplTest, U64ToDouble_Negative_NoZero_Test) {
+TEST(GenerateRealTest, U64ToDouble_Negative_NoZero_Test) {
   auto ToDouble = [](uint64_t a) {
-    return RandU64ToDouble<NegativeValueT, false>(a);
+    return GenerateRealFromBits<double, GenerateNegativeTag, false>(a);
   };
 
   EXPECT_EQ(ToDouble(0x0000000000000000), -2.710505431213761085e-20);
   EXPECT_EQ(ToDouble(0x0000000000000001), -5.42101086242752217004e-20);
   EXPECT_EQ(ToDouble(0x0000000000000002), -1.084202172485504434e-19);
   EXPECT_EQ(ToDouble(0x8000000000000000), -0.5);
+  EXPECT_EQ(ToDouble(0x8000000000000001), -0.5);
   EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);
 }
 
-TEST(DistributionImplTest, U64ToDouble_Signed_NoZero_Test) {
+TEST(GenerateRealTest, U64ToDouble_Negative_Zero_Test) {
   auto ToDouble = [](uint64_t a) {
-    return RandU64ToDouble<SignedValueT, false>(a);
+    return GenerateRealFromBits<double, GenerateNegativeTag, true>(a);
+  };
+
+  EXPECT_EQ(ToDouble(0x0000000000000000), 0.0);
+  EXPECT_EQ(ToDouble(0x0000000000000001), -5.42101086242752217004e-20);
+  EXPECT_EQ(ToDouble(0x0000000000000002), -1.084202172485504434e-19);
+  EXPECT_EQ(ToDouble(0x8000000000000000), -0.5);
+  EXPECT_EQ(ToDouble(0x8000000000000001), -0.5);
+  EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);
+}
+
+TEST(GenerateRealTest, U64ToDouble_Signed_NoZero_Test) {
+  auto ToDouble = [](uint64_t a) {
+    return GenerateRealFromBits<double, GenerateSignedTag, false>(a);
   };
 
   EXPECT_EQ(ToDouble(0x0000000000000000), 5.42101086242752217004e-20);
@@ -198,9 +231,9 @@
   EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);
 }
 
-TEST(DistributionImplTest, U64ToDouble_Signed_Zero_Test) {
+TEST(GenerateRealTest, U64ToDouble_Signed_Zero_Test) {
   auto ToDouble = [](uint64_t a) {
-    return RandU64ToDouble<SignedValueT, true>(a);
+    return GenerateRealFromBits<double, GenerateSignedTag, true>(a);
   };
   EXPECT_EQ(ToDouble(0x0000000000000000), 0);
   EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19);
@@ -210,9 +243,9 @@
   EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);
 }
 
-TEST(DistributionImplTest, U64ToDouble_Signed_Bias_Test) {
+TEST(GenerateRealTest, U64ToDouble_GenerateSignedTag_Bias_Test) {
   auto ToDouble = [](uint64_t a) {
-    return RandU64ToDouble<SignedValueT, true, -1>(a);
+    return GenerateRealFromBits<double, GenerateSignedTag, true>(a, -1);
   };
   EXPECT_EQ(ToDouble(0x0000000000000000), 0);
   EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19 / 2);
@@ -222,9 +255,9 @@
   EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978 / 2);
 }
 
-TEST(DistributionImplTest, U64ToDoubleTest) {
+TEST(GenerateRealTest, U64ToDoubleTest) {
   auto ToDouble = [](uint64_t a) {
-    return RandU64ToDouble<PositiveValueT, true>(a);
+    return GenerateRealFromBits<double, GeneratePositiveTag, true>(a);
   };
 
   EXPECT_EQ(ToDouble(0x0000000000000000), 0.0);
@@ -296,9 +329,9 @@
   }
 }
 
-TEST(DistributionImplTest, U64ToDoubleSignedTest) {
+TEST(GenerateRealTest, U64ToDoubleSignedTest) {
   auto ToDouble = [](uint64_t a) {
-    return RandU64ToDouble<SignedValueT, false>(a);
+    return GenerateRealFromBits<double, GenerateSignedTag, false>(a);
   };
 
   EXPECT_EQ(ToDouble(0x0000000000000000), 5.42101086242752217004e-20);
@@ -379,15 +412,14 @@
   }
 }
 
-TEST(DistributionImplTest, ExhaustiveFloat) {
-  using absl::base_internal::CountLeadingZeros64;
+TEST(GenerateRealTest, ExhaustiveFloat) {
   auto ToFloat = [](uint64_t a) {
-    return RandU64ToFloat<PositiveValueT, true>(a);
+    return GenerateRealFromBits<float, GeneratePositiveTag, true>(a);
   };
 
   // Rely on RandU64ToFloat generating values from greatest to least when
-  // supplied with uint64_t values from greatest (0xfff...) to least (0x0).  Thus,
-  // this algorithm stores the previous value, and if the new value is at
+  // supplied with uint64_t values from greatest (0xfff...) to least (0x0).
+  // Thus, this algorithm stores the previous value, and if the new value is at
   // greater than or equal to the previous value, then there is a collision in
   // the generation algorithm.
   //
@@ -431,7 +463,7 @@
 
     // Adjust decrement and check value based on how many leading 0
     // bits are set in the current value.
-    const int clz = CountLeadingZeros64(x);
+    const int clz = absl::countl_zero(x);
     if (clz < kDig) {
       dec <<= (kDig - clz);
       chk = (~uint64_t(0)) >> (clz + 1);
@@ -461,46 +493,4 @@
   }
 }
 
-TEST(DistributionImplTest, MultiplyU64ToU128Test) {
-  using absl::random_internal::MultiplyU64ToU128;
-  constexpr uint64_t k1 = 1;
-  constexpr uint64_t kMax = ~static_cast<uint64_t>(0);
-
-  EXPECT_EQ(absl::uint128(0), MultiplyU64ToU128(0, 0));
-
-  // Max uint64
-  EXPECT_EQ(MultiplyU64ToU128(kMax, kMax),
-            absl::MakeUint128(0xfffffffffffffffe, 0x0000000000000001));
-  EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(kMax, 1));
-  EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(1, kMax));
-  for (int i = 0; i < 64; ++i) {
-    EXPECT_EQ(absl::MakeUint128(0, kMax) << i,
-              MultiplyU64ToU128(kMax, k1 << i));
-    EXPECT_EQ(absl::MakeUint128(0, kMax) << i,
-              MultiplyU64ToU128(k1 << i, kMax));
-  }
-
-  // 1-bit x 1-bit.
-  for (int i = 0; i < 64; ++i) {
-    for (int j = 0; j < 64; ++j) {
-      EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j),
-                MultiplyU64ToU128(k1 << i, k1 << j));
-      EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j),
-                MultiplyU64ToU128(k1 << i, k1 << j));
-    }
-  }
-
-  // Verified multiplies
-  EXPECT_EQ(MultiplyU64ToU128(0xffffeeeeddddcccc, 0xbbbbaaaa99998888),
-            absl::MakeUint128(0xbbbb9e2692c5dddc, 0xc28f7531048d2c60));
-  EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfedcba9876543210),
-            absl::MakeUint128(0x0121fa00ad77d742, 0x2236d88fe5618cf0));
-  EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfdb97531eca86420),
-            absl::MakeUint128(0x0120ae99d26725fc, 0xce197f0ecac319e0));
-  EXPECT_EQ(MultiplyU64ToU128(0x97a87f4f261ba3f2, 0xfedcba9876543210),
-            absl::MakeUint128(0x96fbf1a8ae78d0ba, 0x5a6dd4b71f278320));
-  EXPECT_EQ(MultiplyU64ToU128(0xfedcba9876543210, 0xfdb97531eca86420),
-            absl::MakeUint128(0xfc98c6981a413e22, 0x342d0bbf48948200));
-}
-
 }  // namespace
diff --git a/absl/random/internal/iostream_state_saver.h b/absl/random/internal/iostream_state_saver.h
index df88fa7..e6e242e 100644
--- a/absl/random/internal/iostream_state_saver.h
+++ b/absl/random/internal/iostream_state_saver.h
@@ -24,6 +24,7 @@
 #include "absl/numeric/int128.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // The null_state_saver does nothing.
@@ -191,8 +192,8 @@
 
   template <typename OStream>
   inline void write(absl::uint128 val, OStream& out) {
-    uint64_t h = Uint128High64(val);
-    uint64_t l = Uint128Low64(val);
+    uint64_t h = absl::Uint128High64(val);
+    uint64_t l = absl::Uint128Low64(val);
     out << h << out.fill() << l;
   }
 };
@@ -238,6 +239,7 @@
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_
diff --git a/absl/random/internal/iostream_state_saver_test.cc b/absl/random/internal/iostream_state_saver_test.cc
index 2ecbaac..6e66266 100644
--- a/absl/random/internal/iostream_state_saver_test.cc
+++ b/absl/random/internal/iostream_state_saver_test.cc
@@ -14,6 +14,9 @@
 
 #include "absl/random/internal/iostream_state_saver.h"
 
+#include <errno.h>
+#include <stdio.h>
+
 #include <sstream>
 #include <string>
 
@@ -196,8 +199,8 @@
     EXPECT_EQ(-d, StreamRoundTrip<double>(-d));
 
     // Avoid undefined behavior (overflow/underflow).
-    if (d <= std::numeric_limits<int64_t>::max() &&
-        d >= std::numeric_limits<int64_t>::lowest()) {
+    if (f <= static_cast<float>(std::numeric_limits<int64_t>::max()) &&
+        f >= static_cast<float>(std::numeric_limits<int64_t>::lowest())) {
       int64_t x = static_cast<int64_t>(f);
       EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
     }
@@ -264,8 +267,8 @@
     }
 
     // Avoid undefined behavior (overflow/underflow).
-    if (d <= std::numeric_limits<int64_t>::max() &&
-        d >= std::numeric_limits<int64_t>::lowest()) {
+    if (d <= static_cast<double>(std::numeric_limits<int64_t>::max()) &&
+        d >= static_cast<double>(std::numeric_limits<int64_t>::lowest())) {
       int64_t x = static_cast<int64_t>(d);
       EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
     }
diff --git a/absl/random/internal/mock_helpers.h b/absl/random/internal/mock_helpers.h
new file mode 100644
index 0000000..9af27ab
--- /dev/null
+++ b/absl/random/internal/mock_helpers.h
@@ -0,0 +1,127 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
+#define ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
+
+#include <tuple>
+#include <type_traits>
+
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// MockHelpers works in conjunction with MockOverloadSet, MockingBitGen, and
+// BitGenRef to enable the mocking capability for absl distribution functions.
+//
+// MockingBitGen registers mocks based on the typeid of a mock signature, KeyT,
+// which is used to generate a unique id.
+//
+// KeyT is a signature of the form:
+//   result_type(discriminator_type, std::tuple<args...>)
+// The mocked function signature will be composed from KeyT as:
+//   result_type(args...)
+//
+class MockHelpers {
+  using IdType = ::absl::base_internal::FastTypeIdType;
+
+  // Given a key signature type used to index the mock, extract the components.
+  // KeyT is expected to have the form:
+  //   result_type(discriminator_type, arg_tuple_type)
+  template <typename KeyT>
+  struct KeySignature;
+
+  template <typename ResultT, typename DiscriminatorT, typename ArgTupleT>
+  struct KeySignature<ResultT(DiscriminatorT, ArgTupleT)> {
+    using result_type = ResultT;
+    using discriminator_type = DiscriminatorT;
+    using arg_tuple_type = ArgTupleT;
+  };
+
+  // Detector for InvokeMock.
+  template <class T>
+  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
+      std::declval<IdType>(), std::declval<void*>(), std::declval<void*>()));
+
+  // Empty implementation of InvokeMock.
+  template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
+            typename... Args>
+  static absl::optional<ReturnT> InvokeMockImpl(char, URBG*, Args&&...) {
+    return absl::nullopt;
+  }
+
+  // Non-empty implementation of InvokeMock.
+  template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
+            typename = invoke_mock_t<URBG>, typename... Args>
+  static absl::optional<ReturnT> InvokeMockImpl(int, URBG* urbg,
+                                                Args&&... args) {
+    ArgTupleT arg_tuple(std::forward<Args>(args)...);
+    ReturnT result;
+    if (urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
+                         &result)) {
+      return result;
+    }
+    return absl::nullopt;
+  }
+
+ public:
+  // Invoke a mock for the KeyT (may or may not be a signature).
+  //
+  // KeyT is used to generate a typeid-based lookup key for the mock.
+  // KeyT is a signature of the form:
+  //   result_type(discriminator_type, std::tuple<args...>)
+  // The mocked function signature will be composed from KeyT as:
+  //   result_type(args...)
+  //
+  // An instance of arg_tuple_type must be constructable from Args..., since
+  // the underlying mechanism requires a pointer to an argument tuple.
+  template <typename KeyT, typename URBG, typename... Args>
+  static auto MaybeInvokeMock(URBG* urbg, Args&&... args)
+      -> absl::optional<typename KeySignature<KeyT>::result_type> {
+    // Use function overloading to dispatch to the implemenation since
+    // more modern patterns (e.g. require + constexpr) are not supported in all
+    // compiler configurations.
+    return InvokeMockImpl<KeyT, typename KeySignature<KeyT>::result_type,
+                          typename KeySignature<KeyT>::arg_tuple_type, URBG>(
+        0, urbg, std::forward<Args>(args)...);
+  }
+
+  // Acquire a mock for the KeyT (may or may not be a signature).
+  //
+  // KeyT is used to generate a typeid-based lookup for the mock.
+  // KeyT is a signature of the form:
+  //   result_type(discriminator_type, std::tuple<args...>)
+  // The mocked function signature will be composed from KeyT as:
+  //   result_type(args...)
+  template <typename KeyT, typename MockURBG>
+  static auto MockFor(MockURBG& m) -> decltype(
+      std::declval<MockURBG>()
+          .template RegisterMock<typename KeySignature<KeyT>::result_type,
+                                 typename KeySignature<KeyT>::arg_tuple_type>(
+              std::declval<IdType>())) {
+    return m.template RegisterMock<typename KeySignature<KeyT>::result_type,
+                                   typename KeySignature<KeyT>::arg_tuple_type>(
+        ::absl::base_internal::FastTypeId<KeyT>());
+  }
+};
+
+}  // namespace random_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
diff --git a/absl/random/internal/mock_overload_set.h b/absl/random/internal/mock_overload_set.h
new file mode 100644
index 0000000..dccc6ce
--- /dev/null
+++ b/absl/random/internal/mock_overload_set.h
@@ -0,0 +1,97 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_
+#define ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_
+
+#include <type_traits>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/random/internal/mock_helpers.h"
+#include "absl/random/mocking_bit_gen.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+template <typename DistrT, typename Fn>
+struct MockSingleOverload;
+
+// MockSingleOverload
+//
+// MockSingleOverload hooks in to gMock's `ON_CALL` and `EXPECT_CALL` macros.
+// EXPECT_CALL(mock_single_overload, Call(...))` will expand to a call to
+// `mock_single_overload.gmock_Call(...)`. Because expectations are stored on
+// the MockingBitGen (an argument passed inside `Call(...)`), this forwards to
+// arguments to MockingBitGen::Register.
+//
+// The underlying KeyT must match the KeyT constructed by DistributionCaller.
+template <typename DistrT, typename Ret, typename... Args>
+struct MockSingleOverload<DistrT, Ret(MockingBitGen&, Args...)> {
+  static_assert(std::is_same<typename DistrT::result_type, Ret>::value,
+                "Overload signature must have return type matching the "
+                "distribution result_type.");
+  using KeyT = Ret(DistrT, std::tuple<Args...>);
+  auto gmock_Call(
+      absl::MockingBitGen& gen,  // NOLINT(google-runtime-references)
+      const ::testing::Matcher<Args>&... matchers)
+      -> decltype(MockHelpers::MockFor<KeyT>(gen).gmock_Call(matchers...)) {
+    return MockHelpers::MockFor<KeyT>(gen).gmock_Call(matchers...);
+  }
+};
+
+template <typename DistrT, typename Ret, typename Arg, typename... Args>
+struct MockSingleOverload<DistrT, Ret(Arg, MockingBitGen&, Args...)> {
+  static_assert(std::is_same<typename DistrT::result_type, Ret>::value,
+                "Overload signature must have return type matching the "
+                "distribution result_type.");
+  using KeyT = Ret(DistrT, std::tuple<Arg, Args...>);
+  auto gmock_Call(
+      const ::testing::Matcher<Arg>& matcher,
+      absl::MockingBitGen& gen,  // NOLINT(google-runtime-references)
+      const ::testing::Matcher<Args>&... matchers)
+      -> decltype(MockHelpers::MockFor<KeyT>(gen).gmock_Call(matcher,
+                                                             matchers...)) {
+    return MockHelpers::MockFor<KeyT>(gen).gmock_Call(matcher, matchers...);
+  }
+};
+
+// MockOverloadSet
+//
+// MockOverloadSet takes a distribution and a collection of signatures and
+// performs overload resolution amongst all the overloads. This makes
+// `EXPECT_CALL(mock_overload_set, Call(...))` expand and do overload resolution
+// correctly.
+template <typename DistrT, typename... Signatures>
+struct MockOverloadSet;
+
+template <typename DistrT, typename Sig>
+struct MockOverloadSet<DistrT, Sig> : public MockSingleOverload<DistrT, Sig> {
+  using MockSingleOverload<DistrT, Sig>::gmock_Call;
+};
+
+template <typename DistrT, typename FirstSig, typename... Rest>
+struct MockOverloadSet<DistrT, FirstSig, Rest...>
+    : public MockSingleOverload<DistrT, FirstSig>,
+      public MockOverloadSet<DistrT, Rest...> {
+  using MockSingleOverload<DistrT, FirstSig>::gmock_Call;
+  using MockOverloadSet<DistrT, Rest...>::gmock_Call;
+};
+
+}  // namespace random_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+#endif  // ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_
diff --git a/absl/random/internal/nanobenchmark.cc b/absl/random/internal/nanobenchmark.cc
index 7f37800..c918181 100644
--- a/absl/random/internal/nanobenchmark.cc
+++ b/absl/random/internal/nanobenchmark.cc
@@ -27,6 +27,7 @@
 #include <utility>
 #include <vector>
 
+#include "absl/base/attributes.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/random/internal/platform.h"
 #include "absl/random/internal/randen_engine.h"
@@ -59,15 +60,6 @@
 #include <time.h>  // NOLINT
 #endif
 
-// ABSL_HAVE_ATTRIBUTE
-#if !defined(ABSL_HAVE_ATTRIBUTE)
-#ifdef __has_attribute
-#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x)
-#else
-#define ABSL_HAVE_ATTRIBUTE(x) 0
-#endif
-#endif
-
 // ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE prevents inlining of the method.
 #if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__))
 #define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE __attribute__((noinline))
@@ -78,6 +70,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal_nanobenchmark {
 namespace {
 
@@ -108,7 +101,7 @@
   char brand_string[49];
   uint32_t abcd[4];
 
-  // Check if brand std::string is supported (it is on all reasonable Intel/AMD)
+  // Check if brand string is supported (it is on all reasonable Intel/AMD)
   Cpuid(0x80000000U, 0, abcd);
   if (abcd[0] < 0x80000004U) {
     return std::string();
@@ -807,4 +800,5 @@
 }
 
 }  // namespace random_internal_nanobenchmark
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/internal/nanobenchmark.h b/absl/random/internal/nanobenchmark.h
index c2b650d..a5097ba 100644
--- a/absl/random/internal/nanobenchmark.h
+++ b/absl/random/internal/nanobenchmark.h
@@ -50,7 +50,10 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal_nanobenchmark {
 
 // Input influencing the function being measured (e.g. number of bytes to copy).
@@ -163,6 +166,7 @@
 }
 
 }  // namespace random_internal_nanobenchmark
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_NANOBENCHMARK_H_
diff --git a/absl/random/internal/nanobenchmark_test.cc b/absl/random/internal/nanobenchmark_test.cc
index 383345a..f1571e2 100644
--- a/absl/random/internal/nanobenchmark_test.cc
+++ b/absl/random/internal/nanobenchmark_test.cc
@@ -18,6 +18,7 @@
 #include "absl/strings/numbers.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal_nanobenchmark {
 namespace {
 
@@ -52,7 +53,7 @@
   // Avoid migrating between cores - important on multi-socket systems.
   int cpu = -1;
   if (argc == 2) {
-    if (!SimpleAtoi(argv[1], &cpu)) {
+    if (!absl::SimpleAtoi(argv[1], &cpu)) {
       ABSL_RAW_LOG(FATAL, "The optional argument must be a CPU number >= 0.\n");
     }
   }
@@ -67,6 +68,7 @@
 
 }  // namespace
 }  // namespace random_internal_nanobenchmark
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 int main(int argc, char* argv[]) {
diff --git a/absl/random/internal/nonsecure_base.h b/absl/random/internal/nonsecure_base.h
index 8847e74..730fa2e 100644
--- a/absl/random/internal/nonsecure_base.h
+++ b/absl/random/internal/nonsecure_base.h
@@ -33,6 +33,7 @@
 #include "absl/types/span.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // Each instance of NonsecureURBGBase<URBG> will be seeded by variates produced
@@ -143,6 +144,7 @@
 };
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_
diff --git a/absl/random/internal/nonsecure_base_test.cc b/absl/random/internal/nonsecure_base_test.cc
index d9de990..698027f 100644
--- a/absl/random/internal/nonsecure_base_test.cc
+++ b/absl/random/internal/nonsecure_base_test.cc
@@ -154,9 +154,10 @@
 TEST(NonsecureURBGBase, CompatibleWithStdDistributions) {
   ExampleNonsecureURBG rbg;
 
-  std::uniform_int_distribution<uint32_t>(0, 100)(rbg);
-  std::uniform_real_distribution<float>()(rbg);
-  std::bernoulli_distribution(0.2)(rbg);
+  // Cast to void to suppress [[nodiscard]] warnings
+  static_cast<void>(std::uniform_int_distribution<uint32_t>(0, 100)(rbg));
+  static_cast<void>(std::uniform_real_distribution<float>()(rbg));
+  static_cast<void>(std::bernoulli_distribution(0.2)(rbg));
 }
 
 TEST(NonsecureURBGBase, ConsecutiveDefaultInstancesYieldUniqueVariates) {
diff --git a/absl/random/internal/pcg_engine.h b/absl/random/internal/pcg_engine.h
index b5df4ea..8efaf2e 100644
--- a/absl/random/internal/pcg_engine.h
+++ b/absl/random/internal/pcg_engine.h
@@ -19,11 +19,13 @@
 
 #include "absl/base/config.h"
 #include "absl/meta/type_traits.h"
+#include "absl/numeric/bits.h"
 #include "absl/numeric/int128.h"
 #include "absl/random/internal/fastmath.h"
 #include "absl/random/internal/iostream_state_saver.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // pcg_engine is a simplified implementation of Melissa O'Neil's PCG engine in
@@ -260,7 +262,7 @@
     uint64_t rotate = h >> 58u;
     uint64_t s = Uint128Low64(state) ^ h;
 #endif
-    return random_internal::rotr(s, rotate);
+    return rotr(s, rotate);
   }
 };
 
@@ -280,8 +282,8 @@
   using state_type = uint64_t;
   using result_type = uint32_t;
   inline uint32_t operator()(uint64_t state) {
-    return random_internal::rotr(
-        static_cast<uint32_t>(((state >> 18) ^ state) >> 27), state >> 59);
+    return rotr(static_cast<uint32_t>(((state >> 18) ^ state) >> 27),
+                state >> 59);
   }
 };
 
@@ -300,6 +302,7 @@
     random_internal::pcg_xsh_rr_64_32>;
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_
diff --git a/absl/random/internal/platform.h b/absl/random/internal/platform.h
index a5a42cb..bbdb4e6 100644
--- a/absl/random/internal/platform.h
+++ b/absl/random/internal/platform.h
@@ -162,7 +162,8 @@
 // iOS does not support dispatch, even on x86, since applications
 // should be bundled as fat binaries, with a different build tailored for
 // each specific supported platform/architecture.
-#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_OS_IPHONE_SIMULATOR)
+#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
+    (defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR)
 #undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
 #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
 #endif
diff --git a/absl/random/internal/pool_urbg.cc b/absl/random/internal/pool_urbg.cc
index f2e1c1f..5bee530 100644
--- a/absl/random/internal/pool_urbg.cc
+++ b/absl/random/internal/pool_urbg.cc
@@ -37,6 +37,7 @@
 using absl::base_internal::SpinLockHolder;
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 namespace {
 
@@ -249,4 +250,5 @@
 template class RandenPool<uint64_t>;
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/internal/pool_urbg.h b/absl/random/internal/pool_urbg.h
index 9b2dd4b..0572192 100644
--- a/absl/random/internal/pool_urbg.h
+++ b/absl/random/internal/pool_urbg.h
@@ -22,6 +22,7 @@
 #include "absl/types/span.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // RandenPool is a thread-safe random number generator [random.req.urbg] that
@@ -124,6 +125,7 @@
 };
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_POOL_URBG_H_
diff --git a/absl/random/internal/randen-keys.inc b/absl/random/internal/randen-keys.inc
deleted file mode 100644
index fa4b166..0000000
--- a/absl/random/internal/randen-keys.inc
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_RANDOM_INTERNAL_RANDEN_KEYS_INC_
-#define ABSL_RANDOM_INTERNAL_RANDEN_KEYS_INC_
-
-// Textual header to include the randen_keys where necessary.
-// REQUIRES: struct u64x2{}
-//
-// PROVIDES: kKeys
-// PROVIDES: round_keys[]
-
-// "Nothing up my sleeve" numbers from the first hex digits of Pi, obtained
-// from http://hexpi.sourceforge.net/. The array was generated by following
-// Python script:
-/*
-python << EOF
-"""Generates Randen round keys array from pi-hex.62500.txt file."""
-import binascii
-
-KEYS = 136
-
-def chunks(l, n):
-    """Yield successive n-sized chunks from l."""
-    for i in range(0, len(l), n):
-        yield l[i:i + n]
-
-def pairwise(t):
-    """Transforms sequence into sequence of pairs."""
-    it = iter(t)
-    return zip(it,it)
-
-def digits_from_pi():
-  """Reads digits from hexpi.sourceforge.net file."""
-  with open("pi-hex.62500.txt") as file:
-    return file.read()
-
-def digits_from_urandom():
-  """Reads digits from /dev/urandom."""
-  with open("/dev/urandom") as file:
-    return binascii.hexlify(file.read(KEYS * 16))
-
-digits = digits_from_pi()
-print("static constexpr const size_t kRoundKeys = {0};\n".format(KEYS))
-print("alignas(16) constexpr const u64x2 round_keys[kRoundKeys] = {")
-
-for i, (hi, lo) in zip(range(KEYS), pairwise(chunks(digits, 16))):
-  hi = "0x{0}ull".format(hi)
-  lo = "0x{0}ull".format(lo)
-  print("  u64x2({0}, {1}){2}".format(hi, lo, ',' if i+1 < KEYS else ''))
-
-print("};")
-EOF
-*/
-
-static constexpr const size_t kRoundKeys = 136;
-
-alignas(16) constexpr u64x2 round_keys[kRoundKeys] = {
-    u64x2(0x243F6A8885A308D3ull, 0x13198A2E03707344ull),
-    u64x2(0xA4093822299F31D0ull, 0x082EFA98EC4E6C89ull),
-    u64x2(0x452821E638D01377ull, 0xBE5466CF34E90C6Cull),
-    u64x2(0xC0AC29B7C97C50DDull, 0x3F84D5B5B5470917ull),
-    u64x2(0x9216D5D98979FB1Bull, 0xD1310BA698DFB5ACull),
-    u64x2(0x2FFD72DBD01ADFB7ull, 0xB8E1AFED6A267E96ull),
-    u64x2(0xBA7C9045F12C7F99ull, 0x24A19947B3916CF7ull),
-    u64x2(0x0801F2E2858EFC16ull, 0x636920D871574E69ull),
-    u64x2(0xA458FEA3F4933D7Eull, 0x0D95748F728EB658ull),
-    u64x2(0x718BCD5882154AEEull, 0x7B54A41DC25A59B5ull),
-    u64x2(0x9C30D5392AF26013ull, 0xC5D1B023286085F0ull),
-    u64x2(0xCA417918B8DB38EFull, 0x8E79DCB0603A180Eull),
-    u64x2(0x6C9E0E8BB01E8A3Eull, 0xD71577C1BD314B27ull),
-    u64x2(0x78AF2FDA55605C60ull, 0xE65525F3AA55AB94ull),
-    u64x2(0x5748986263E81440ull, 0x55CA396A2AAB10B6ull),
-    u64x2(0xB4CC5C341141E8CEull, 0xA15486AF7C72E993ull),
-    u64x2(0xB3EE1411636FBC2Aull, 0x2BA9C55D741831F6ull),
-    u64x2(0xCE5C3E169B87931Eull, 0xAFD6BA336C24CF5Cull),
-    u64x2(0x7A32538128958677ull, 0x3B8F48986B4BB9AFull),
-    u64x2(0xC4BFE81B66282193ull, 0x61D809CCFB21A991ull),
-    u64x2(0x487CAC605DEC8032ull, 0xEF845D5DE98575B1ull),
-    u64x2(0xDC262302EB651B88ull, 0x23893E81D396ACC5ull),
-    u64x2(0x0F6D6FF383F44239ull, 0x2E0B4482A4842004ull),
-    u64x2(0x69C8F04A9E1F9B5Eull, 0x21C66842F6E96C9Aull),
-    u64x2(0x670C9C61ABD388F0ull, 0x6A51A0D2D8542F68ull),
-    u64x2(0x960FA728AB5133A3ull, 0x6EEF0B6C137A3BE4ull),
-    u64x2(0xBA3BF0507EFB2A98ull, 0xA1F1651D39AF0176ull),
-    u64x2(0x66CA593E82430E88ull, 0x8CEE8619456F9FB4ull),
-    u64x2(0x7D84A5C33B8B5EBEull, 0xE06F75D885C12073ull),
-    u64x2(0x401A449F56C16AA6ull, 0x4ED3AA62363F7706ull),
-    u64x2(0x1BFEDF72429B023Dull, 0x37D0D724D00A1248ull),
-    u64x2(0xDB0FEAD349F1C09Bull, 0x075372C980991B7Bull),
-    u64x2(0x25D479D8F6E8DEF7ull, 0xE3FE501AB6794C3Bull),
-    u64x2(0x976CE0BD04C006BAull, 0xC1A94FB6409F60C4ull),
-    u64x2(0x5E5C9EC2196A2463ull, 0x68FB6FAF3E6C53B5ull),
-    u64x2(0x1339B2EB3B52EC6Full, 0x6DFC511F9B30952Cull),
-    u64x2(0xCC814544AF5EBD09ull, 0xBEE3D004DE334AFDull),
-    u64x2(0x660F2807192E4BB3ull, 0xC0CBA85745C8740Full),
-    u64x2(0xD20B5F39B9D3FBDBull, 0x5579C0BD1A60320Aull),
-    u64x2(0xD6A100C6402C7279ull, 0x679F25FEFB1FA3CCull),
-    u64x2(0x8EA5E9F8DB3222F8ull, 0x3C7516DFFD616B15ull),
-    u64x2(0x2F501EC8AD0552ABull, 0x323DB5FAFD238760ull),
-    u64x2(0x53317B483E00DF82ull, 0x9E5C57BBCA6F8CA0ull),
-    u64x2(0x1A87562EDF1769DBull, 0xD542A8F6287EFFC3ull),
-    u64x2(0xAC6732C68C4F5573ull, 0x695B27B0BBCA58C8ull),
-    u64x2(0xE1FFA35DB8F011A0ull, 0x10FA3D98FD2183B8ull),
-    u64x2(0x4AFCB56C2DD1D35Bull, 0x9A53E479B6F84565ull),
-    u64x2(0xD28E49BC4BFB9790ull, 0xE1DDF2DAA4CB7E33ull),
-    u64x2(0x62FB1341CEE4C6E8ull, 0xEF20CADA36774C01ull),
-    u64x2(0xD07E9EFE2BF11FB4ull, 0x95DBDA4DAE909198ull),
-    u64x2(0xEAAD8E716B93D5A0ull, 0xD08ED1D0AFC725E0ull),
-    u64x2(0x8E3C5B2F8E7594B7ull, 0x8FF6E2FBF2122B64ull),
-    u64x2(0x8888B812900DF01Cull, 0x4FAD5EA0688FC31Cull),
-    u64x2(0xD1CFF191B3A8C1ADull, 0x2F2F2218BE0E1777ull),
-    u64x2(0xEA752DFE8B021FA1ull, 0xE5A0CC0FB56F74E8ull),
-    u64x2(0x18ACF3D6CE89E299ull, 0xB4A84FE0FD13E0B7ull),
-    u64x2(0x7CC43B81D2ADA8D9ull, 0x165FA26680957705ull),
-    u64x2(0x93CC7314211A1477ull, 0xE6AD206577B5FA86ull),
-    u64x2(0xC75442F5FB9D35CFull, 0xEBCDAF0C7B3E89A0ull),
-    u64x2(0xD6411BD3AE1E7E49ull, 0x00250E2D2071B35Eull),
-    u64x2(0x226800BB57B8E0AFull, 0x2464369BF009B91Eull),
-    u64x2(0x5563911D59DFA6AAull, 0x78C14389D95A537Full),
-    u64x2(0x207D5BA202E5B9C5ull, 0x832603766295CFA9ull),
-    u64x2(0x11C819684E734A41ull, 0xB3472DCA7B14A94Aull),
-    u64x2(0x1B5100529A532915ull, 0xD60F573FBC9BC6E4ull),
-    u64x2(0x2B60A47681E67400ull, 0x08BA6FB5571BE91Full),
-    u64x2(0xF296EC6B2A0DD915ull, 0xB6636521E7B9F9B6ull),
-    u64x2(0xFF34052EC5855664ull, 0x53B02D5DA99F8FA1ull),
-    u64x2(0x08BA47996E85076Aull, 0x4B7A70E9B5B32944ull),
-    u64x2(0xDB75092EC4192623ull, 0xAD6EA6B049A7DF7Dull),
-    u64x2(0x9CEE60B88FEDB266ull, 0xECAA8C71699A18FFull),
-    u64x2(0x5664526CC2B19EE1ull, 0x193602A575094C29ull),
-    u64x2(0xA0591340E4183A3Eull, 0x3F54989A5B429D65ull),
-    u64x2(0x6B8FE4D699F73FD6ull, 0xA1D29C07EFE830F5ull),
-    u64x2(0x4D2D38E6F0255DC1ull, 0x4CDD20868470EB26ull),
-    u64x2(0x6382E9C6021ECC5Eull, 0x09686B3F3EBAEFC9ull),
-    u64x2(0x3C9718146B6A70A1ull, 0x687F358452A0E286ull),
-    u64x2(0xB79C5305AA500737ull, 0x3E07841C7FDEAE5Cull),
-    u64x2(0x8E7D44EC5716F2B8ull, 0xB03ADA37F0500C0Dull),
-    u64x2(0xF01C1F040200B3FFull, 0xAE0CF51A3CB574B2ull),
-    u64x2(0x25837A58DC0921BDull, 0xD19113F97CA92FF6ull),
-    u64x2(0x9432477322F54701ull, 0x3AE5E58137C2DADCull),
-    u64x2(0xC8B576349AF3DDA7ull, 0xA94461460FD0030Eull),
-    u64x2(0xECC8C73EA4751E41ull, 0xE238CD993BEA0E2Full),
-    u64x2(0x3280BBA1183EB331ull, 0x4E548B384F6DB908ull),
-    u64x2(0x6F420D03F60A04BFull, 0x2CB8129024977C79ull),
-    u64x2(0x5679B072BCAF89AFull, 0xDE9A771FD9930810ull),
-    u64x2(0xB38BAE12DCCF3F2Eull, 0x5512721F2E6B7124ull),
-    u64x2(0x501ADDE69F84CD87ull, 0x7A5847187408DA17ull),
-    u64x2(0xBC9F9ABCE94B7D8Cull, 0xEC7AEC3ADB851DFAull),
-    u64x2(0x63094366C464C3D2ull, 0xEF1C18473215D808ull),
-    u64x2(0xDD433B3724C2BA16ull, 0x12A14D432A65C451ull),
-    u64x2(0x50940002133AE4DDull, 0x71DFF89E10314E55ull),
-    u64x2(0x81AC77D65F11199Bull, 0x043556F1D7A3C76Bull),
-    u64x2(0x3C11183B5924A509ull, 0xF28FE6ED97F1FBFAull),
-    u64x2(0x9EBABF2C1E153C6Eull, 0x86E34570EAE96FB1ull),
-    u64x2(0x860E5E0A5A3E2AB3ull, 0x771FE71C4E3D06FAull),
-    u64x2(0x2965DCB999E71D0Full, 0x803E89D65266C825ull),
-    u64x2(0x2E4CC9789C10B36Aull, 0xC6150EBA94E2EA78ull),
-    u64x2(0xA6FC3C531E0A2DF4ull, 0xF2F74EA7361D2B3Dull),
-    u64x2(0x1939260F19C27960ull, 0x5223A708F71312B6ull),
-    u64x2(0xEBADFE6EEAC31F66ull, 0xE3BC4595A67BC883ull),
-    u64x2(0xB17F37D1018CFF28ull, 0xC332DDEFBE6C5AA5ull),
-    u64x2(0x6558218568AB9702ull, 0xEECEA50FDB2F953Bull),
-    u64x2(0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull),
-    u64x2(0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull),
-    u64x2(0x0334FE1EAA0363CFull, 0xB5735C904C70A239ull),
-    u64x2(0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull),
-    u64x2(0x9CAB5CABB2F3846Eull, 0x648B1EAF19BDF0CAull),
-    u64x2(0xA02369B9655ABB50ull, 0x40685A323C2AB4B3ull),
-    u64x2(0x319EE9D5C021B8F7ull, 0x9B540B19875FA099ull),
-    u64x2(0x95F7997E623D7DA8ull, 0xF837889A97E32D77ull),
-    u64x2(0x11ED935F16681281ull, 0x0E358829C7E61FD6ull),
-    u64x2(0x96DEDFA17858BA99ull, 0x57F584A51B227263ull),
-    u64x2(0x9B83C3FF1AC24696ull, 0xCDB30AEB532E3054ull),
-    u64x2(0x8FD948E46DBC3128ull, 0x58EBF2EF34C6FFEAull),
-    u64x2(0xFE28ED61EE7C3C73ull, 0x5D4A14D9E864B7E3ull),
-    u64x2(0x42105D14203E13E0ull, 0x45EEE2B6A3AAABEAull),
-    u64x2(0xDB6C4F15FACB4FD0ull, 0xC742F442EF6ABBB5ull),
-    u64x2(0x654F3B1D41CD2105ull, 0xD81E799E86854DC7ull),
-    u64x2(0xE44B476A3D816250ull, 0xCF62A1F25B8D2646ull),
-    u64x2(0xFC8883A0C1C7B6A3ull, 0x7F1524C369CB7492ull),
-    u64x2(0x47848A0B5692B285ull, 0x095BBF00AD19489Dull),
-    u64x2(0x1462B17423820D00ull, 0x58428D2A0C55F5EAull),
-    u64x2(0x1DADF43E233F7061ull, 0x3372F0928D937E41ull),
-    u64x2(0xD65FECF16C223BDBull, 0x7CDE3759CBEE7460ull),
-    u64x2(0x4085F2A7CE77326Eull, 0xA607808419F8509Eull),
-    u64x2(0xE8EFD85561D99735ull, 0xA969A7AAC50C06C2ull),
-    u64x2(0x5A04ABFC800BCADCull, 0x9E447A2EC3453484ull),
-    u64x2(0xFDD567050E1E9EC9ull, 0xDB73DBD3105588CDull),
-    u64x2(0x675FDA79E3674340ull, 0xC5C43465713E38D8ull),
-    u64x2(0x3D28F89EF16DFF20ull, 0x153E21E78FB03D4Aull),
-    u64x2(0xE6E39F2BDB83ADF7ull, 0xE93D5A68948140F7ull),
-    u64x2(0xF64C261C94692934ull, 0x411520F77602D4F7ull),
-    u64x2(0xBCF46B2ED4A10068ull, 0xD40824713320F46Aull),
-    u64x2(0x43B7D4B7500061AFull, 0x1E39F62E97244546ull)};
-
-#endif  // ABSL_RANDOM_INTERNAL_RANDEN_KEYS_INC_
diff --git a/absl/random/internal/randen.cc b/absl/random/internal/randen.cc
index bab8075..c1bc044 100644
--- a/absl/random/internal/randen.cc
+++ b/absl/random/internal/randen.cc
@@ -17,7 +17,7 @@
 #include "absl/base/internal/raw_logging.h"
 #include "absl/random/internal/randen_detect.h"
 
-// RANDen = RANDom generator or beetroots in Swiss German.
+// RANDen = RANDom generator or beetroots in Swiss High German.
 // 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
 // generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
 //
@@ -41,6 +41,7 @@
 // structured/low-entropy counters to digits of Pi.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 namespace {
 
@@ -86,4 +87,5 @@
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/internal/randen.h b/absl/random/internal/randen.h
index a4ff254..9a3840b 100644
--- a/absl/random/internal/randen.h
+++ b/absl/random/internal/randen.h
@@ -23,9 +23,10 @@
 #include "absl/random/internal/randen_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
-// RANDen = RANDom generator or beetroots in Swiss German.
+// RANDen = RANDom generator or beetroots in Swiss High German.
 // 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
 // generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
 //
@@ -95,6 +96,7 @@
 };
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_RANDEN_H_
diff --git a/absl/random/internal/randen_detect.cc b/absl/random/internal/randen_detect.cc
index d5946b2..bbe7b96 100644
--- a/absl/random/internal/randen_detect.cc
+++ b/absl/random/internal/randen_detect.cc
@@ -1,13 +1,13 @@
 // Copyright 2017 The Abseil Authors.
 //
-// Licensed under the Apache License, Version 2.0 (the"License");
+// Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
 //      https://www.apache.org/licenses/LICENSE-2.0
 //
 // 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,
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
@@ -95,6 +95,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // The default return at the end of the function might be unreachable depending
@@ -216,4 +217,5 @@
 #endif
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/internal/randen_detect.h b/absl/random/internal/randen_detect.h
index 44c5c66..f283f43 100644
--- a/absl/random/internal/randen_detect.h
+++ b/absl/random/internal/randen_detect.h
@@ -15,7 +15,10 @@
 #ifndef ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_
 #define ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // Returns whether the current CPU supports RandenHwAes implementation.
@@ -24,6 +27,7 @@
 bool CPUSupportsRandenHwAes();
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_
diff --git a/absl/random/internal/randen_engine.h b/absl/random/internal/randen_engine.h
index 02212a1..6b33731 100644
--- a/absl/random/internal/randen_engine.h
+++ b/absl/random/internal/randen_engine.h
@@ -28,6 +28,7 @@
 #include "absl/random/internal/randen.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // Deterministic pseudorandom byte generator with backtracking resistance
@@ -223,6 +224,7 @@
 };
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_
diff --git a/absl/random/internal/randen_hwaes.cc b/absl/random/internal/randen_hwaes.cc
index 7d5b2b7..b5a3f90 100644
--- a/absl/random/internal/randen_hwaes.cc
+++ b/absl/random/internal/randen_hwaes.cc
@@ -24,6 +24,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/random/internal/platform.h"
+#include "absl/random/internal/randen_traits.h"
 
 // ABSL_RANDEN_HWAES_IMPL indicates whether this file will contain
 // a hardware accelerated implementation of randen, or whether it
@@ -75,6 +76,7 @@
 #include <cstdlib>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // No accelerated implementation.
@@ -106,6 +108,7 @@
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #else  // defined(ABSL_RANDEN_HWAES_IMPL)
@@ -113,8 +116,16 @@
 // Accelerated implementations are supported.
 // We need the per-architecture includes and defines.
 //
+namespace {
 
-#include "absl/random/internal/randen_traits.h"
+using absl::random_internal::RandenTraits;
+
+// Randen operates on 128-bit vectors.
+struct alignas(16) u64x2 {
+  uint64_t data[2];
+};
+
+}  // namespace
 
 // TARGET_CRYPTO defines a crypto attribute for each architecture.
 //
@@ -139,6 +150,7 @@
 #include <altivec.h>
 // <altivec.h> #defines vector __vector; in C++, this is bad form.
 #undef vector
+#undef bool
 
 // Rely on the PowerPC AltiVec vector operations for accelerated AES
 // instructions. GCC support of the PPC vector types is described in:
@@ -148,7 +160,6 @@
 using Vector128 = __vector unsigned long long;  // NOLINT(runtime/int)
 
 namespace {
-
 inline ABSL_TARGET_CRYPTO Vector128 ReverseBytes(const Vector128& v) {
   // Reverses the bytes of the vector.
   const __vector unsigned char perm = {15, 14, 13, 12, 11, 10, 9, 8,
@@ -159,13 +170,11 @@
 // WARNING: these load/store in native byte order. It is OK to load and then
 // store an unchanged vector, but interpreting the bits as a number or input
 // to AES will have undefined results.
-inline ABSL_TARGET_CRYPTO Vector128
-Vector128Load(const void* ABSL_RANDOM_INTERNAL_RESTRICT from) {
+inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
   return vec_vsx_ld(0, reinterpret_cast<const Vector128*>(from));
 }
 
-inline ABSL_TARGET_CRYPTO void Vector128Store(
-    const Vector128& v, void* ABSL_RANDOM_INTERNAL_RESTRICT to) {
+inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
   vec_vsx_st(v, 0, reinterpret_cast<Vector128*>(to));
 }
 
@@ -177,15 +186,9 @@
 }
 
 // Enables native loads in the round loop by pre-swapping.
-inline ABSL_TARGET_CRYPTO void SwapEndian(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state) {
-  using absl::random_internal::RandenTraits;
-  constexpr size_t kLanes = 2;
-  constexpr size_t kFeistelBlocks = RandenTraits::kFeistelBlocks;
-
-  for (uint32_t branch = 0; branch < kFeistelBlocks; ++branch) {
-    const Vector128 v = ReverseBytes(Vector128Load(state + kLanes * branch));
-    Vector128Store(v, state + kLanes * branch);
+inline ABSL_TARGET_CRYPTO void SwapEndian(u64x2* state) {
+  for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) {
+    Vector128Store(ReverseBytes(Vector128Load(state + block)), state + block);
   }
 }
 
@@ -230,13 +233,11 @@
 
 namespace {
 
-inline ABSL_TARGET_CRYPTO Vector128
-Vector128Load(const void* ABSL_RANDOM_INTERNAL_RESTRICT from) {
+inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
   return vld1q_u8(reinterpret_cast<const uint8_t*>(from));
 }
 
-inline ABSL_TARGET_CRYPTO void Vector128Store(
-    const Vector128& v, void* ABSL_RANDOM_INTERNAL_RESTRICT to) {
+inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
   vst1q_u8(reinterpret_cast<uint8_t*>(to), v);
 }
 
@@ -254,8 +255,7 @@
   return vaesmcq_u8(vaeseq_u8(state, uint8x16_t{})) ^ round_key;
 }
 
-inline ABSL_TARGET_CRYPTO void SwapEndian(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT) {}
+inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}
 
 }  // namespace
 
@@ -283,15 +283,12 @@
   __m128i data_;
 };
 
-inline ABSL_TARGET_CRYPTO Vector128
-Vector128Load(const void* ABSL_RANDOM_INTERNAL_RESTRICT from) {
+inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
   return Vector128(_mm_load_si128(reinterpret_cast<const __m128i*>(from)));
 }
 
-inline ABSL_TARGET_CRYPTO void Vector128Store(
-    const Vector128& v, void* ABSL_RANDOM_INTERNAL_RESTRICT to) {
-  _mm_store_si128(reinterpret_cast<__m128i * ABSL_RANDOM_INTERNAL_RESTRICT>(to),
-                  v.data());
+inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
+  _mm_store_si128(reinterpret_cast<__m128i*>(to), v.data());
 }
 
 // One round of AES. "round_key" is a public constant for breaking the
@@ -304,40 +301,12 @@
   return Vector128(_mm_aesenc_si128(state.data(), round_key.data()));
 }
 
-inline ABSL_TARGET_CRYPTO void SwapEndian(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT) {}
+inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}
 
 }  // namespace
 
 #endif
 
-namespace {
-
-// u64x2 is a 128-bit, (2 x uint64_t lanes) struct used to store
-// the randen_keys.
-struct alignas(16) u64x2 {
-  constexpr u64x2(uint64_t hi, uint64_t lo)
-#if defined(ABSL_ARCH_PPC)
-      // This has been tested with PPC running in little-endian mode;
-      // We byte-swap the u64x2 structure from little-endian to big-endian
-      // because altivec always runs in big-endian mode.
-      : v{__builtin_bswap64(hi), __builtin_bswap64(lo)} {
-#else
-      : v{lo, hi} {
-#endif
-  }
-
-  constexpr bool operator==(const u64x2& other) const {
-    return v[0] == other.v[0] && v[1] == other.v[1];
-  }
-
-  constexpr bool operator!=(const u64x2& other) const {
-    return !(*this == other);
-  }
-
-  uint64_t v[2];
-};  // namespace
-
 #ifdef __clang__
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wunknown-pragmas"
@@ -346,7 +315,6 @@
 // At this point, all of the platform-specific features have been defined /
 // implemented.
 //
-// REQUIRES: using u64x2 = ...
 // REQUIRES: using Vector128 = ...
 // REQUIRES: Vector128 Vector128Load(void*) {...}
 // REQUIRES: void Vector128Store(Vector128, void*) {...}
@@ -355,95 +323,50 @@
 //
 // PROVIDES: absl::random_internal::RandenHwAes::Absorb
 // PROVIDES: absl::random_internal::RandenHwAes::Generate
-
-// RANDen = RANDom generator or beetroots in Swiss German.
-// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
-// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
-//
-// High-level summary:
-// 1) Reverie (see "A Robust and Sponge-Like PRNG with Improved Efficiency") is
-//    a sponge-like random generator that requires a cryptographic permutation.
-//    It improves upon "Provably Robust Sponge-Based PRNGs and KDFs" by
-//    achieving backtracking resistance with only one Permute() per buffer.
-//
-// 2) "Simpira v2: A Family of Efficient Permutations Using the AES Round
-//    Function" constructs up to 1024-bit permutations using an improved
-//    Generalized Feistel network with 2-round AES-128 functions. This Feistel
-//    block shuffle achieves diffusion faster and is less vulnerable to
-//    sliced-biclique attacks than the Type-2 cyclic shuffle.
-//
-// 3) "Improving the Generalized Feistel" and "New criterion for diffusion
-//    property" extends the same kind of improved Feistel block shuffle to 16
-//    branches, which enables a 2048-bit permutation.
-//
-// We combine these three ideas and also change Simpira's subround keys from
-// structured/low-entropy counters to digits of Pi.
-
-// Randen constants.
-using absl::random_internal::RandenTraits;
-constexpr size_t kStateBytes = RandenTraits::kStateBytes;
-constexpr size_t kCapacityBytes = RandenTraits::kCapacityBytes;
-constexpr size_t kFeistelBlocks = RandenTraits::kFeistelBlocks;
-constexpr size_t kFeistelRounds = RandenTraits::kFeistelRounds;
-constexpr size_t kFeistelFunctions = RandenTraits::kFeistelFunctions;
-
-// Independent keys (272 = 2.1 KiB) for the first AES subround of each function.
-constexpr size_t kKeys = kFeistelRounds * kFeistelFunctions;
-
-// INCLUDE keys.
-#include "absl/random/internal/randen-keys.inc"
-
-static_assert(kKeys == kRoundKeys, "kKeys and kRoundKeys must be equal");
-static_assert(round_keys[kKeys - 1] != u64x2(0, 0),
-              "Too few round_keys initializers");
-
-// Number of uint64_t lanes per 128-bit vector;
-constexpr size_t kLanes = 2;
+namespace {
 
 // Block shuffles applies a shuffle to the entire state between AES rounds.
 // Improved odd-even shuffle from "New criterion for diffusion property".
-inline ABSL_TARGET_CRYPTO void BlockShuffle(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state) {
-  static_assert(kFeistelBlocks == 16, "Expecting 16 FeistelBlocks.");
+inline ABSL_TARGET_CRYPTO void BlockShuffle(u64x2* state) {
+  static_assert(RandenTraits::kFeistelBlocks == 16,
+                "Expecting 16 FeistelBlocks.");
 
-  constexpr size_t shuffle[kFeistelBlocks] = {7,  2, 13, 4,  11, 8,  3, 6,
-                                              15, 0, 9,  10, 1,  14, 5, 12};
+  constexpr size_t shuffle[RandenTraits::kFeistelBlocks] = {
+      7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12};
 
-  // The fully unrolled loop without the memcpy improves the speed by about
-  // 30% over the equivalent loop.
-  const Vector128 v0 = Vector128Load(state + kLanes * shuffle[0]);
-  const Vector128 v1 = Vector128Load(state + kLanes * shuffle[1]);
-  const Vector128 v2 = Vector128Load(state + kLanes * shuffle[2]);
-  const Vector128 v3 = Vector128Load(state + kLanes * shuffle[3]);
-  const Vector128 v4 = Vector128Load(state + kLanes * shuffle[4]);
-  const Vector128 v5 = Vector128Load(state + kLanes * shuffle[5]);
-  const Vector128 v6 = Vector128Load(state + kLanes * shuffle[6]);
-  const Vector128 v7 = Vector128Load(state + kLanes * shuffle[7]);
-  const Vector128 w0 = Vector128Load(state + kLanes * shuffle[8]);
-  const Vector128 w1 = Vector128Load(state + kLanes * shuffle[9]);
-  const Vector128 w2 = Vector128Load(state + kLanes * shuffle[10]);
-  const Vector128 w3 = Vector128Load(state + kLanes * shuffle[11]);
-  const Vector128 w4 = Vector128Load(state + kLanes * shuffle[12]);
-  const Vector128 w5 = Vector128Load(state + kLanes * shuffle[13]);
-  const Vector128 w6 = Vector128Load(state + kLanes * shuffle[14]);
-  const Vector128 w7 = Vector128Load(state + kLanes * shuffle[15]);
+  const Vector128 v0 = Vector128Load(state + shuffle[0]);
+  const Vector128 v1 = Vector128Load(state + shuffle[1]);
+  const Vector128 v2 = Vector128Load(state + shuffle[2]);
+  const Vector128 v3 = Vector128Load(state + shuffle[3]);
+  const Vector128 v4 = Vector128Load(state + shuffle[4]);
+  const Vector128 v5 = Vector128Load(state + shuffle[5]);
+  const Vector128 v6 = Vector128Load(state + shuffle[6]);
+  const Vector128 v7 = Vector128Load(state + shuffle[7]);
+  const Vector128 w0 = Vector128Load(state + shuffle[8]);
+  const Vector128 w1 = Vector128Load(state + shuffle[9]);
+  const Vector128 w2 = Vector128Load(state + shuffle[10]);
+  const Vector128 w3 = Vector128Load(state + shuffle[11]);
+  const Vector128 w4 = Vector128Load(state + shuffle[12]);
+  const Vector128 w5 = Vector128Load(state + shuffle[13]);
+  const Vector128 w6 = Vector128Load(state + shuffle[14]);
+  const Vector128 w7 = Vector128Load(state + shuffle[15]);
 
-  Vector128Store(v0, state + kLanes * 0);
-  Vector128Store(v1, state + kLanes * 1);
-  Vector128Store(v2, state + kLanes * 2);
-  Vector128Store(v3, state + kLanes * 3);
-  Vector128Store(v4, state + kLanes * 4);
-  Vector128Store(v5, state + kLanes * 5);
-  Vector128Store(v6, state + kLanes * 6);
-  Vector128Store(v7, state + kLanes * 7);
-  Vector128Store(w0, state + kLanes * 8);
-  Vector128Store(w1, state + kLanes * 9);
-  Vector128Store(w2, state + kLanes * 10);
-  Vector128Store(w3, state + kLanes * 11);
-  Vector128Store(w4, state + kLanes * 12);
-  Vector128Store(w5, state + kLanes * 13);
-  Vector128Store(w6, state + kLanes * 14);
-  Vector128Store(w7, state + kLanes * 15);
+  Vector128Store(v0, state + 0);
+  Vector128Store(v1, state + 1);
+  Vector128Store(v2, state + 2);
+  Vector128Store(v3, state + 3);
+  Vector128Store(v4, state + 4);
+  Vector128Store(v5, state + 5);
+  Vector128Store(v6, state + 6);
+  Vector128Store(v7, state + 7);
+  Vector128Store(w0, state + 8);
+  Vector128Store(w1, state + 9);
+  Vector128Store(w2, state + 10);
+  Vector128Store(w3, state + 11);
+  Vector128Store(w4, state + 12);
+  Vector128Store(w5, state + 13);
+  Vector128Store(w6, state + 14);
+  Vector128Store(w7, state + 15);
 }
 
 // Feistel round function using two AES subrounds. Very similar to F()
@@ -452,28 +375,28 @@
 // parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel
 // XORs are 'free' (included in the second AES instruction).
 inline ABSL_TARGET_CRYPTO const u64x2* FeistelRound(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state,
-    const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
-  static_assert(kFeistelBlocks == 16, "Expecting 16 FeistelBlocks.");
+    u64x2* state, const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
+  static_assert(RandenTraits::kFeistelBlocks == 16,
+                "Expecting 16 FeistelBlocks.");
 
   // MSVC does a horrible job at unrolling loops.
   // So we unroll the loop by hand to improve the performance.
-  const Vector128 s0 = Vector128Load(state + kLanes * 0);
-  const Vector128 s1 = Vector128Load(state + kLanes * 1);
-  const Vector128 s2 = Vector128Load(state + kLanes * 2);
-  const Vector128 s3 = Vector128Load(state + kLanes * 3);
-  const Vector128 s4 = Vector128Load(state + kLanes * 4);
-  const Vector128 s5 = Vector128Load(state + kLanes * 5);
-  const Vector128 s6 = Vector128Load(state + kLanes * 6);
-  const Vector128 s7 = Vector128Load(state + kLanes * 7);
-  const Vector128 s8 = Vector128Load(state + kLanes * 8);
-  const Vector128 s9 = Vector128Load(state + kLanes * 9);
-  const Vector128 s10 = Vector128Load(state + kLanes * 10);
-  const Vector128 s11 = Vector128Load(state + kLanes * 11);
-  const Vector128 s12 = Vector128Load(state + kLanes * 12);
-  const Vector128 s13 = Vector128Load(state + kLanes * 13);
-  const Vector128 s14 = Vector128Load(state + kLanes * 14);
-  const Vector128 s15 = Vector128Load(state + kLanes * 15);
+  const Vector128 s0 = Vector128Load(state + 0);
+  const Vector128 s1 = Vector128Load(state + 1);
+  const Vector128 s2 = Vector128Load(state + 2);
+  const Vector128 s3 = Vector128Load(state + 3);
+  const Vector128 s4 = Vector128Load(state + 4);
+  const Vector128 s5 = Vector128Load(state + 5);
+  const Vector128 s6 = Vector128Load(state + 6);
+  const Vector128 s7 = Vector128Load(state + 7);
+  const Vector128 s8 = Vector128Load(state + 8);
+  const Vector128 s9 = Vector128Load(state + 9);
+  const Vector128 s10 = Vector128Load(state + 10);
+  const Vector128 s11 = Vector128Load(state + 11);
+  const Vector128 s12 = Vector128Load(state + 12);
+  const Vector128 s13 = Vector128Load(state + 13);
+  const Vector128 s14 = Vector128Load(state + 14);
+  const Vector128 s15 = Vector128Load(state + 15);
 
   // Encode even blocks with keys.
   const Vector128 e0 = AesRound(s0, Vector128Load(keys + 0));
@@ -496,14 +419,14 @@
   const Vector128 o15 = AesRound(e14, s15);
 
   // Store odd blocks. (These will be shuffled later).
-  Vector128Store(o1, state + kLanes * 1);
-  Vector128Store(o3, state + kLanes * 3);
-  Vector128Store(o5, state + kLanes * 5);
-  Vector128Store(o7, state + kLanes * 7);
-  Vector128Store(o9, state + kLanes * 9);
-  Vector128Store(o11, state + kLanes * 11);
-  Vector128Store(o13, state + kLanes * 13);
-  Vector128Store(o15, state + kLanes * 15);
+  Vector128Store(o1, state + 1);
+  Vector128Store(o3, state + 3);
+  Vector128Store(o5, state + 5);
+  Vector128Store(o7, state + 7);
+  Vector128Store(o9, state + 9);
+  Vector128Store(o11, state + 11);
+  Vector128Store(o13, state + 13);
+  Vector128Store(o15, state + 15);
 
   return keys + 8;
 }
@@ -513,17 +436,13 @@
 // 2^64 queries if the round function is a PRF. This is similar to the b=8 case
 // of Simpira v2, but more efficient than its generic construction for b=16.
 inline ABSL_TARGET_CRYPTO void Permute(
-    const void* ABSL_RANDOM_INTERNAL_RESTRICT keys,
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state) {
-  const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys128 =
-      static_cast<const u64x2*>(keys);
-
+    u64x2* state, const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
   // (Successfully unrolled; the first iteration jumps into the second half)
 #ifdef __clang__
 #pragma clang loop unroll_count(2)
 #endif
-  for (size_t round = 0; round < kFeistelRounds; ++round) {
-    keys128 = FeistelRound(state, keys128);
+  for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) {
+    keys = FeistelRound(state, keys);
     BlockShuffle(state);
   }
 }
@@ -531,6 +450,7 @@
 }  // namespace
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 bool HasRandenHwAesImplementation() { return true; }
@@ -538,99 +458,101 @@
 const void* ABSL_TARGET_CRYPTO RandenHwAes::GetKeys() {
   // Round keys for one AES per Feistel round and branch.
   // The canonical implementation uses first digits of Pi.
-  return round_keys;
+#if defined(ABSL_ARCH_PPC)
+  return kRandenRoundKeysBE;
+#else
+  return kRandenRoundKeys;
+#endif
 }
 
 // NOLINTNEXTLINE
 void ABSL_TARGET_CRYPTO RandenHwAes::Absorb(const void* seed_void,
                                             void* state_void) {
-  uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state =
-      reinterpret_cast<uint64_t*>(state_void);
-  const uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT seed =
-      reinterpret_cast<const uint64_t*>(seed_void);
+  static_assert(RandenTraits::kCapacityBytes / sizeof(Vector128) == 1,
+                "Unexpected Randen kCapacityBlocks");
+  static_assert(RandenTraits::kStateBytes / sizeof(Vector128) == 16,
+                "Unexpected Randen kStateBlocks");
 
-  constexpr size_t kCapacityBlocks = kCapacityBytes / sizeof(Vector128);
-  constexpr size_t kStateBlocks = kStateBytes / sizeof(Vector128);
+  auto* state =
+      reinterpret_cast<u64x2 * ABSL_RANDOM_INTERNAL_RESTRICT>(state_void);
+  const auto* seed =
+      reinterpret_cast<const u64x2 * ABSL_RANDOM_INTERNAL_RESTRICT>(seed_void);
 
-  static_assert(kCapacityBlocks * sizeof(Vector128) == kCapacityBytes,
-                "Not i*V");
-  static_assert(kCapacityBlocks == 1, "Unexpected Randen kCapacityBlocks");
-  static_assert(kStateBlocks == 16, "Unexpected Randen kStateBlocks");
+  Vector128 b1 = Vector128Load(state + 1);
+  b1 ^= Vector128Load(seed + 0);
+  Vector128Store(b1, state + 1);
 
-  Vector128 b1 = Vector128Load(state + kLanes * 1);
-  b1 ^= Vector128Load(seed + kLanes * 0);
-  Vector128Store(b1, state + kLanes * 1);
+  Vector128 b2 = Vector128Load(state + 2);
+  b2 ^= Vector128Load(seed + 1);
+  Vector128Store(b2, state + 2);
 
-  Vector128 b2 = Vector128Load(state + kLanes * 2);
-  b2 ^= Vector128Load(seed + kLanes * 1);
-  Vector128Store(b2, state + kLanes * 2);
+  Vector128 b3 = Vector128Load(state + 3);
+  b3 ^= Vector128Load(seed + 2);
+  Vector128Store(b3, state + 3);
 
-  Vector128 b3 = Vector128Load(state + kLanes * 3);
-  b3 ^= Vector128Load(seed + kLanes * 2);
-  Vector128Store(b3, state + kLanes * 3);
+  Vector128 b4 = Vector128Load(state + 4);
+  b4 ^= Vector128Load(seed + 3);
+  Vector128Store(b4, state + 4);
 
-  Vector128 b4 = Vector128Load(state + kLanes * 4);
-  b4 ^= Vector128Load(seed + kLanes * 3);
-  Vector128Store(b4, state + kLanes * 4);
+  Vector128 b5 = Vector128Load(state + 5);
+  b5 ^= Vector128Load(seed + 4);
+  Vector128Store(b5, state + 5);
 
-  Vector128 b5 = Vector128Load(state + kLanes * 5);
-  b5 ^= Vector128Load(seed + kLanes * 4);
-  Vector128Store(b5, state + kLanes * 5);
+  Vector128 b6 = Vector128Load(state + 6);
+  b6 ^= Vector128Load(seed + 5);
+  Vector128Store(b6, state + 6);
 
-  Vector128 b6 = Vector128Load(state + kLanes * 6);
-  b6 ^= Vector128Load(seed + kLanes * 5);
-  Vector128Store(b6, state + kLanes * 6);
+  Vector128 b7 = Vector128Load(state + 7);
+  b7 ^= Vector128Load(seed + 6);
+  Vector128Store(b7, state + 7);
 
-  Vector128 b7 = Vector128Load(state + kLanes * 7);
-  b7 ^= Vector128Load(seed + kLanes * 6);
-  Vector128Store(b7, state + kLanes * 7);
+  Vector128 b8 = Vector128Load(state + 8);
+  b8 ^= Vector128Load(seed + 7);
+  Vector128Store(b8, state + 8);
 
-  Vector128 b8 = Vector128Load(state + kLanes * 8);
-  b8 ^= Vector128Load(seed + kLanes * 7);
-  Vector128Store(b8, state + kLanes * 8);
+  Vector128 b9 = Vector128Load(state + 9);
+  b9 ^= Vector128Load(seed + 8);
+  Vector128Store(b9, state + 9);
 
-  Vector128 b9 = Vector128Load(state + kLanes * 9);
-  b9 ^= Vector128Load(seed + kLanes * 8);
-  Vector128Store(b9, state + kLanes * 9);
+  Vector128 b10 = Vector128Load(state + 10);
+  b10 ^= Vector128Load(seed + 9);
+  Vector128Store(b10, state + 10);
 
-  Vector128 b10 = Vector128Load(state + kLanes * 10);
-  b10 ^= Vector128Load(seed + kLanes * 9);
-  Vector128Store(b10, state + kLanes * 10);
+  Vector128 b11 = Vector128Load(state + 11);
+  b11 ^= Vector128Load(seed + 10);
+  Vector128Store(b11, state + 11);
 
-  Vector128 b11 = Vector128Load(state + kLanes * 11);
-  b11 ^= Vector128Load(seed + kLanes * 10);
-  Vector128Store(b11, state + kLanes * 11);
+  Vector128 b12 = Vector128Load(state + 12);
+  b12 ^= Vector128Load(seed + 11);
+  Vector128Store(b12, state + 12);
 
-  Vector128 b12 = Vector128Load(state + kLanes * 12);
-  b12 ^= Vector128Load(seed + kLanes * 11);
-  Vector128Store(b12, state + kLanes * 12);
+  Vector128 b13 = Vector128Load(state + 13);
+  b13 ^= Vector128Load(seed + 12);
+  Vector128Store(b13, state + 13);
 
-  Vector128 b13 = Vector128Load(state + kLanes * 13);
-  b13 ^= Vector128Load(seed + kLanes * 12);
-  Vector128Store(b13, state + kLanes * 13);
+  Vector128 b14 = Vector128Load(state + 14);
+  b14 ^= Vector128Load(seed + 13);
+  Vector128Store(b14, state + 14);
 
-  Vector128 b14 = Vector128Load(state + kLanes * 14);
-  b14 ^= Vector128Load(seed + kLanes * 13);
-  Vector128Store(b14, state + kLanes * 14);
-
-  Vector128 b15 = Vector128Load(state + kLanes * 15);
-  b15 ^= Vector128Load(seed + kLanes * 14);
-  Vector128Store(b15, state + kLanes * 15);
+  Vector128 b15 = Vector128Load(state + 15);
+  b15 ^= Vector128Load(seed + 14);
+  Vector128Store(b15, state + 15);
 }
 
 // NOLINTNEXTLINE
-void ABSL_TARGET_CRYPTO RandenHwAes::Generate(const void* keys,
+void ABSL_TARGET_CRYPTO RandenHwAes::Generate(const void* keys_void,
                                               void* state_void) {
-  static_assert(kCapacityBytes == sizeof(Vector128), "Capacity mismatch");
+  static_assert(RandenTraits::kCapacityBytes == sizeof(Vector128),
+                "Capacity mismatch");
 
-  uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state =
-      reinterpret_cast<uint64_t*>(state_void);
+  auto* state = reinterpret_cast<u64x2*>(state_void);
+  const auto* keys = reinterpret_cast<const u64x2*>(keys_void);
 
   const Vector128 prev_inner = Vector128Load(state);
 
   SwapEndian(state);
 
-  Permute(keys, state);
+  Permute(state, keys);
 
   SwapEndian(state);
 
@@ -645,6 +567,7 @@
 #endif
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // (ABSL_RANDEN_HWAES_IMPL)
diff --git a/absl/random/internal/randen_hwaes.h b/absl/random/internal/randen_hwaes.h
index d8e6055..71a7f69 100644
--- a/absl/random/internal/randen_hwaes.h
+++ b/absl/random/internal/randen_hwaes.h
@@ -15,15 +15,18 @@
 #ifndef ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_
 #define ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_
 
+#include "absl/base/config.h"
+
 // HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
 // symbols from arbitrary system and other headers, since it may be built
 // with different flags from other targets, using different levels of
 // optimization, potentially introducing ODR violations.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
-// RANDen = RANDom generator or beetroots in Swiss German.
+// RANDen = RANDom generator or beetroots in Swiss High German.
 // 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
 // generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
 //
@@ -41,6 +44,7 @@
 bool HasRandenHwAesImplementation();
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_
diff --git a/absl/random/internal/randen_hwaes_test.cc b/absl/random/internal/randen_hwaes_test.cc
index a7cbd46..66ddb43 100644
--- a/absl/random/internal/randen_hwaes_test.cc
+++ b/absl/random/internal/randen_hwaes_test.cc
@@ -27,12 +27,14 @@
 using absl::random_internal::RandenHwAes;
 using absl::random_internal::RandenTraits;
 
-struct randen {
-  static constexpr size_t kStateSizeT =
-      RandenTraits::kStateBytes / sizeof(uint64_t);
+// Local state parameters.
+constexpr size_t kSeedBytes =
+    RandenTraits::kStateBytes - RandenTraits::kCapacityBytes;
+constexpr size_t kStateSizeT = RandenTraits::kStateBytes / sizeof(uint64_t);
+constexpr size_t kSeedSizeT = kSeedBytes / sizeof(uint32_t);
+
+struct alignas(16) randen {
   uint64_t state[kStateSizeT];
-  static constexpr size_t kSeedSizeT =
-      RandenTraits::kSeedBytes / sizeof(uint32_t);
   uint32_t seed[kSeedSizeT];
 };
 
diff --git a/absl/random/internal/randen_round_keys.cc b/absl/random/internal/randen_round_keys.cc
new file mode 100644
index 0000000..5fb3ca5
--- /dev/null
+++ b/absl/random/internal/randen_round_keys.cc
@@ -0,0 +1,462 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/random/internal/randen_traits.h"
+
+// This file contains only the round keys for randen.
+//
+// "Nothing up my sleeve" numbers from the first hex digits of Pi, obtained
+// from http://hexpi.sourceforge.net/. The array was generated by following
+// Python script:
+
+/*
+python >tmp.cc << EOF
+"""Generates Randen round keys array from pi-hex.62500.txt file."""
+import binascii
+
+KEYS = 17 * 8
+
+def chunks(l, n):
+    """Yield successive n-sized chunks from l."""
+    for i in range(0, len(l), n):
+        yield l[i:i + n]
+
+def pairwise(t):
+    """Transforms sequence into sequence of pairs."""
+    it = iter(t)
+    return zip(it,it)
+
+def digits_from_pi():
+  """Reads digits from hexpi.sourceforge.net file."""
+  with open("pi-hex.62500.txt") as file:
+    return file.read()
+
+def digits_from_urandom():
+  """Reads digits from /dev/urandom."""
+  with open("/dev/urandom") as file:
+    return binascii.hexlify(file.read(KEYS * 16))
+
+def print_row(b)
+  print("  0x{0}, 0x{1}, 0x{2}, 0x{3}, 0x{4}, 0x{5}, 0x{6}, 0x{7}, 0x{8}, 0x{9},
+0x{10}, 0x{11}, 0x{12}, 0x{13}, 0x{14}, 0x{15},".format(*b))
+
+
+digits = digits_from_pi()
+#digits = digits_from_urandom()
+
+print("namespace {")
+print("static constexpr size_t kKeyBytes = {0};\n".format(KEYS * 16))
+print("}")
+
+print("alignas(16) const unsigned char kRandenRoundKeysBE[kKeyBytes] = {")
+
+for i, u16 in zip(range(KEYS), chunks(digits, 32)):
+  b = list(chunks(u16, 2))
+  print_row(b)
+
+print("};")
+
+print("alignas(16) const unsigned char kRandenRoundKeys[kKeyBytes] = {")
+
+for i, u16 in zip(range(KEYS), chunks(digits, 32)):
+  b = list(chunks(u16, 2))
+  b.reverse()
+  print_row(b)
+
+print("};")
+
+EOF
+
+*/
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+namespace {
+static constexpr size_t kKeyBytes = 2176;
+}
+
+alignas(16) const unsigned char kRandenRoundKeysBE[kKeyBytes] = {
+    0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E,
+    0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
+    0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, 0x45, 0x28, 0x21, 0xE6,
+    0x38, 0xD0, 0x13, 0x77, 0xBE, 0x54, 0x66, 0xCF, 0x34, 0xE9, 0x0C, 0x6C,
+    0xC0, 0xAC, 0x29, 0xB7, 0xC9, 0x7C, 0x50, 0xDD, 0x3F, 0x84, 0xD5, 0xB5,
+    0xB5, 0x47, 0x09, 0x17, 0x92, 0x16, 0xD5, 0xD9, 0x89, 0x79, 0xFB, 0x1B,
+    0xD1, 0x31, 0x0B, 0xA6, 0x98, 0xDF, 0xB5, 0xAC, 0x2F, 0xFD, 0x72, 0xDB,
+    0xD0, 0x1A, 0xDF, 0xB7, 0xB8, 0xE1, 0xAF, 0xED, 0x6A, 0x26, 0x7E, 0x96,
+    0xBA, 0x7C, 0x90, 0x45, 0xF1, 0x2C, 0x7F, 0x99, 0x24, 0xA1, 0x99, 0x47,
+    0xB3, 0x91, 0x6C, 0xF7, 0x08, 0x01, 0xF2, 0xE2, 0x85, 0x8E, 0xFC, 0x16,
+    0x63, 0x69, 0x20, 0xD8, 0x71, 0x57, 0x4E, 0x69, 0xA4, 0x58, 0xFE, 0xA3,
+    0xF4, 0x93, 0x3D, 0x7E, 0x0D, 0x95, 0x74, 0x8F, 0x72, 0x8E, 0xB6, 0x58,
+    0x71, 0x8B, 0xCD, 0x58, 0x82, 0x15, 0x4A, 0xEE, 0x7B, 0x54, 0xA4, 0x1D,
+    0xC2, 0x5A, 0x59, 0xB5, 0x9C, 0x30, 0xD5, 0x39, 0x2A, 0xF2, 0x60, 0x13,
+    0xC5, 0xD1, 0xB0, 0x23, 0x28, 0x60, 0x85, 0xF0, 0xCA, 0x41, 0x79, 0x18,
+    0xB8, 0xDB, 0x38, 0xEF, 0x8E, 0x79, 0xDC, 0xB0, 0x60, 0x3A, 0x18, 0x0E,
+    0x6C, 0x9E, 0x0E, 0x8B, 0xB0, 0x1E, 0x8A, 0x3E, 0xD7, 0x15, 0x77, 0xC1,
+    0xBD, 0x31, 0x4B, 0x27, 0x78, 0xAF, 0x2F, 0xDA, 0x55, 0x60, 0x5C, 0x60,
+    0xE6, 0x55, 0x25, 0xF3, 0xAA, 0x55, 0xAB, 0x94, 0x57, 0x48, 0x98, 0x62,
+    0x63, 0xE8, 0x14, 0x40, 0x55, 0xCA, 0x39, 0x6A, 0x2A, 0xAB, 0x10, 0xB6,
+    0xB4, 0xCC, 0x5C, 0x34, 0x11, 0x41, 0xE8, 0xCE, 0xA1, 0x54, 0x86, 0xAF,
+    0x7C, 0x72, 0xE9, 0x93, 0xB3, 0xEE, 0x14, 0x11, 0x63, 0x6F, 0xBC, 0x2A,
+    0x2B, 0xA9, 0xC5, 0x5D, 0x74, 0x18, 0x31, 0xF6, 0xCE, 0x5C, 0x3E, 0x16,
+    0x9B, 0x87, 0x93, 0x1E, 0xAF, 0xD6, 0xBA, 0x33, 0x6C, 0x24, 0xCF, 0x5C,
+    0x7A, 0x32, 0x53, 0x81, 0x28, 0x95, 0x86, 0x77, 0x3B, 0x8F, 0x48, 0x98,
+    0x6B, 0x4B, 0xB9, 0xAF, 0xC4, 0xBF, 0xE8, 0x1B, 0x66, 0x28, 0x21, 0x93,
+    0x61, 0xD8, 0x09, 0xCC, 0xFB, 0x21, 0xA9, 0x91, 0x48, 0x7C, 0xAC, 0x60,
+    0x5D, 0xEC, 0x80, 0x32, 0xEF, 0x84, 0x5D, 0x5D, 0xE9, 0x85, 0x75, 0xB1,
+    0xDC, 0x26, 0x23, 0x02, 0xEB, 0x65, 0x1B, 0x88, 0x23, 0x89, 0x3E, 0x81,
+    0xD3, 0x96, 0xAC, 0xC5, 0x0F, 0x6D, 0x6F, 0xF3, 0x83, 0xF4, 0x42, 0x39,
+    0x2E, 0x0B, 0x44, 0x82, 0xA4, 0x84, 0x20, 0x04, 0x69, 0xC8, 0xF0, 0x4A,
+    0x9E, 0x1F, 0x9B, 0x5E, 0x21, 0xC6, 0x68, 0x42, 0xF6, 0xE9, 0x6C, 0x9A,
+    0x67, 0x0C, 0x9C, 0x61, 0xAB, 0xD3, 0x88, 0xF0, 0x6A, 0x51, 0xA0, 0xD2,
+    0xD8, 0x54, 0x2F, 0x68, 0x96, 0x0F, 0xA7, 0x28, 0xAB, 0x51, 0x33, 0xA3,
+    0x6E, 0xEF, 0x0B, 0x6C, 0x13, 0x7A, 0x3B, 0xE4, 0xBA, 0x3B, 0xF0, 0x50,
+    0x7E, 0xFB, 0x2A, 0x98, 0xA1, 0xF1, 0x65, 0x1D, 0x39, 0xAF, 0x01, 0x76,
+    0x66, 0xCA, 0x59, 0x3E, 0x82, 0x43, 0x0E, 0x88, 0x8C, 0xEE, 0x86, 0x19,
+    0x45, 0x6F, 0x9F, 0xB4, 0x7D, 0x84, 0xA5, 0xC3, 0x3B, 0x8B, 0x5E, 0xBE,
+    0xE0, 0x6F, 0x75, 0xD8, 0x85, 0xC1, 0x20, 0x73, 0x40, 0x1A, 0x44, 0x9F,
+    0x56, 0xC1, 0x6A, 0xA6, 0x4E, 0xD3, 0xAA, 0x62, 0x36, 0x3F, 0x77, 0x06,
+    0x1B, 0xFE, 0xDF, 0x72, 0x42, 0x9B, 0x02, 0x3D, 0x37, 0xD0, 0xD7, 0x24,
+    0xD0, 0x0A, 0x12, 0x48, 0xDB, 0x0F, 0xEA, 0xD3, 0x49, 0xF1, 0xC0, 0x9B,
+    0x07, 0x53, 0x72, 0xC9, 0x80, 0x99, 0x1B, 0x7B, 0x25, 0xD4, 0x79, 0xD8,
+    0xF6, 0xE8, 0xDE, 0xF7, 0xE3, 0xFE, 0x50, 0x1A, 0xB6, 0x79, 0x4C, 0x3B,
+    0x97, 0x6C, 0xE0, 0xBD, 0x04, 0xC0, 0x06, 0xBA, 0xC1, 0xA9, 0x4F, 0xB6,
+    0x40, 0x9F, 0x60, 0xC4, 0x5E, 0x5C, 0x9E, 0xC2, 0x19, 0x6A, 0x24, 0x63,
+    0x68, 0xFB, 0x6F, 0xAF, 0x3E, 0x6C, 0x53, 0xB5, 0x13, 0x39, 0xB2, 0xEB,
+    0x3B, 0x52, 0xEC, 0x6F, 0x6D, 0xFC, 0x51, 0x1F, 0x9B, 0x30, 0x95, 0x2C,
+    0xCC, 0x81, 0x45, 0x44, 0xAF, 0x5E, 0xBD, 0x09, 0xBE, 0xE3, 0xD0, 0x04,
+    0xDE, 0x33, 0x4A, 0xFD, 0x66, 0x0F, 0x28, 0x07, 0x19, 0x2E, 0x4B, 0xB3,
+    0xC0, 0xCB, 0xA8, 0x57, 0x45, 0xC8, 0x74, 0x0F, 0xD2, 0x0B, 0x5F, 0x39,
+    0xB9, 0xD3, 0xFB, 0xDB, 0x55, 0x79, 0xC0, 0xBD, 0x1A, 0x60, 0x32, 0x0A,
+    0xD6, 0xA1, 0x00, 0xC6, 0x40, 0x2C, 0x72, 0x79, 0x67, 0x9F, 0x25, 0xFE,
+    0xFB, 0x1F, 0xA3, 0xCC, 0x8E, 0xA5, 0xE9, 0xF8, 0xDB, 0x32, 0x22, 0xF8,
+    0x3C, 0x75, 0x16, 0xDF, 0xFD, 0x61, 0x6B, 0x15, 0x2F, 0x50, 0x1E, 0xC8,
+    0xAD, 0x05, 0x52, 0xAB, 0x32, 0x3D, 0xB5, 0xFA, 0xFD, 0x23, 0x87, 0x60,
+    0x53, 0x31, 0x7B, 0x48, 0x3E, 0x00, 0xDF, 0x82, 0x9E, 0x5C, 0x57, 0xBB,
+    0xCA, 0x6F, 0x8C, 0xA0, 0x1A, 0x87, 0x56, 0x2E, 0xDF, 0x17, 0x69, 0xDB,
+    0xD5, 0x42, 0xA8, 0xF6, 0x28, 0x7E, 0xFF, 0xC3, 0xAC, 0x67, 0x32, 0xC6,
+    0x8C, 0x4F, 0x55, 0x73, 0x69, 0x5B, 0x27, 0xB0, 0xBB, 0xCA, 0x58, 0xC8,
+    0xE1, 0xFF, 0xA3, 0x5D, 0xB8, 0xF0, 0x11, 0xA0, 0x10, 0xFA, 0x3D, 0x98,
+    0xFD, 0x21, 0x83, 0xB8, 0x4A, 0xFC, 0xB5, 0x6C, 0x2D, 0xD1, 0xD3, 0x5B,
+    0x9A, 0x53, 0xE4, 0x79, 0xB6, 0xF8, 0x45, 0x65, 0xD2, 0x8E, 0x49, 0xBC,
+    0x4B, 0xFB, 0x97, 0x90, 0xE1, 0xDD, 0xF2, 0xDA, 0xA4, 0xCB, 0x7E, 0x33,
+    0x62, 0xFB, 0x13, 0x41, 0xCE, 0xE4, 0xC6, 0xE8, 0xEF, 0x20, 0xCA, 0xDA,
+    0x36, 0x77, 0x4C, 0x01, 0xD0, 0x7E, 0x9E, 0xFE, 0x2B, 0xF1, 0x1F, 0xB4,
+    0x95, 0xDB, 0xDA, 0x4D, 0xAE, 0x90, 0x91, 0x98, 0xEA, 0xAD, 0x8E, 0x71,
+    0x6B, 0x93, 0xD5, 0xA0, 0xD0, 0x8E, 0xD1, 0xD0, 0xAF, 0xC7, 0x25, 0xE0,
+    0x8E, 0x3C, 0x5B, 0x2F, 0x8E, 0x75, 0x94, 0xB7, 0x8F, 0xF6, 0xE2, 0xFB,
+    0xF2, 0x12, 0x2B, 0x64, 0x88, 0x88, 0xB8, 0x12, 0x90, 0x0D, 0xF0, 0x1C,
+    0x4F, 0xAD, 0x5E, 0xA0, 0x68, 0x8F, 0xC3, 0x1C, 0xD1, 0xCF, 0xF1, 0x91,
+    0xB3, 0xA8, 0xC1, 0xAD, 0x2F, 0x2F, 0x22, 0x18, 0xBE, 0x0E, 0x17, 0x77,
+    0xEA, 0x75, 0x2D, 0xFE, 0x8B, 0x02, 0x1F, 0xA1, 0xE5, 0xA0, 0xCC, 0x0F,
+    0xB5, 0x6F, 0x74, 0xE8, 0x18, 0xAC, 0xF3, 0xD6, 0xCE, 0x89, 0xE2, 0x99,
+    0xB4, 0xA8, 0x4F, 0xE0, 0xFD, 0x13, 0xE0, 0xB7, 0x7C, 0xC4, 0x3B, 0x81,
+    0xD2, 0xAD, 0xA8, 0xD9, 0x16, 0x5F, 0xA2, 0x66, 0x80, 0x95, 0x77, 0x05,
+    0x93, 0xCC, 0x73, 0x14, 0x21, 0x1A, 0x14, 0x77, 0xE6, 0xAD, 0x20, 0x65,
+    0x77, 0xB5, 0xFA, 0x86, 0xC7, 0x54, 0x42, 0xF5, 0xFB, 0x9D, 0x35, 0xCF,
+    0xEB, 0xCD, 0xAF, 0x0C, 0x7B, 0x3E, 0x89, 0xA0, 0xD6, 0x41, 0x1B, 0xD3,
+    0xAE, 0x1E, 0x7E, 0x49, 0x00, 0x25, 0x0E, 0x2D, 0x20, 0x71, 0xB3, 0x5E,
+    0x22, 0x68, 0x00, 0xBB, 0x57, 0xB8, 0xE0, 0xAF, 0x24, 0x64, 0x36, 0x9B,
+    0xF0, 0x09, 0xB9, 0x1E, 0x55, 0x63, 0x91, 0x1D, 0x59, 0xDF, 0xA6, 0xAA,
+    0x78, 0xC1, 0x43, 0x89, 0xD9, 0x5A, 0x53, 0x7F, 0x20, 0x7D, 0x5B, 0xA2,
+    0x02, 0xE5, 0xB9, 0xC5, 0x83, 0x26, 0x03, 0x76, 0x62, 0x95, 0xCF, 0xA9,
+    0x11, 0xC8, 0x19, 0x68, 0x4E, 0x73, 0x4A, 0x41, 0xB3, 0x47, 0x2D, 0xCA,
+    0x7B, 0x14, 0xA9, 0x4A, 0x1B, 0x51, 0x00, 0x52, 0x9A, 0x53, 0x29, 0x15,
+    0xD6, 0x0F, 0x57, 0x3F, 0xBC, 0x9B, 0xC6, 0xE4, 0x2B, 0x60, 0xA4, 0x76,
+    0x81, 0xE6, 0x74, 0x00, 0x08, 0xBA, 0x6F, 0xB5, 0x57, 0x1B, 0xE9, 0x1F,
+    0xF2, 0x96, 0xEC, 0x6B, 0x2A, 0x0D, 0xD9, 0x15, 0xB6, 0x63, 0x65, 0x21,
+    0xE7, 0xB9, 0xF9, 0xB6, 0xFF, 0x34, 0x05, 0x2E, 0xC5, 0x85, 0x56, 0x64,
+    0x53, 0xB0, 0x2D, 0x5D, 0xA9, 0x9F, 0x8F, 0xA1, 0x08, 0xBA, 0x47, 0x99,
+    0x6E, 0x85, 0x07, 0x6A, 0x4B, 0x7A, 0x70, 0xE9, 0xB5, 0xB3, 0x29, 0x44,
+    0xDB, 0x75, 0x09, 0x2E, 0xC4, 0x19, 0x26, 0x23, 0xAD, 0x6E, 0xA6, 0xB0,
+    0x49, 0xA7, 0xDF, 0x7D, 0x9C, 0xEE, 0x60, 0xB8, 0x8F, 0xED, 0xB2, 0x66,
+    0xEC, 0xAA, 0x8C, 0x71, 0x69, 0x9A, 0x18, 0xFF, 0x56, 0x64, 0x52, 0x6C,
+    0xC2, 0xB1, 0x9E, 0xE1, 0x19, 0x36, 0x02, 0xA5, 0x75, 0x09, 0x4C, 0x29,
+    0xA0, 0x59, 0x13, 0x40, 0xE4, 0x18, 0x3A, 0x3E, 0x3F, 0x54, 0x98, 0x9A,
+    0x5B, 0x42, 0x9D, 0x65, 0x6B, 0x8F, 0xE4, 0xD6, 0x99, 0xF7, 0x3F, 0xD6,
+    0xA1, 0xD2, 0x9C, 0x07, 0xEF, 0xE8, 0x30, 0xF5, 0x4D, 0x2D, 0x38, 0xE6,
+    0xF0, 0x25, 0x5D, 0xC1, 0x4C, 0xDD, 0x20, 0x86, 0x84, 0x70, 0xEB, 0x26,
+    0x63, 0x82, 0xE9, 0xC6, 0x02, 0x1E, 0xCC, 0x5E, 0x09, 0x68, 0x6B, 0x3F,
+    0x3E, 0xBA, 0xEF, 0xC9, 0x3C, 0x97, 0x18, 0x14, 0x6B, 0x6A, 0x70, 0xA1,
+    0x68, 0x7F, 0x35, 0x84, 0x52, 0xA0, 0xE2, 0x86, 0xB7, 0x9C, 0x53, 0x05,
+    0xAA, 0x50, 0x07, 0x37, 0x3E, 0x07, 0x84, 0x1C, 0x7F, 0xDE, 0xAE, 0x5C,
+    0x8E, 0x7D, 0x44, 0xEC, 0x57, 0x16, 0xF2, 0xB8, 0xB0, 0x3A, 0xDA, 0x37,
+    0xF0, 0x50, 0x0C, 0x0D, 0xF0, 0x1C, 0x1F, 0x04, 0x02, 0x00, 0xB3, 0xFF,
+    0xAE, 0x0C, 0xF5, 0x1A, 0x3C, 0xB5, 0x74, 0xB2, 0x25, 0x83, 0x7A, 0x58,
+    0xDC, 0x09, 0x21, 0xBD, 0xD1, 0x91, 0x13, 0xF9, 0x7C, 0xA9, 0x2F, 0xF6,
+    0x94, 0x32, 0x47, 0x73, 0x22, 0xF5, 0x47, 0x01, 0x3A, 0xE5, 0xE5, 0x81,
+    0x37, 0xC2, 0xDA, 0xDC, 0xC8, 0xB5, 0x76, 0x34, 0x9A, 0xF3, 0xDD, 0xA7,
+    0xA9, 0x44, 0x61, 0x46, 0x0F, 0xD0, 0x03, 0x0E, 0xEC, 0xC8, 0xC7, 0x3E,
+    0xA4, 0x75, 0x1E, 0x41, 0xE2, 0x38, 0xCD, 0x99, 0x3B, 0xEA, 0x0E, 0x2F,
+    0x32, 0x80, 0xBB, 0xA1, 0x18, 0x3E, 0xB3, 0x31, 0x4E, 0x54, 0x8B, 0x38,
+    0x4F, 0x6D, 0xB9, 0x08, 0x6F, 0x42, 0x0D, 0x03, 0xF6, 0x0A, 0x04, 0xBF,
+    0x2C, 0xB8, 0x12, 0x90, 0x24, 0x97, 0x7C, 0x79, 0x56, 0x79, 0xB0, 0x72,
+    0xBC, 0xAF, 0x89, 0xAF, 0xDE, 0x9A, 0x77, 0x1F, 0xD9, 0x93, 0x08, 0x10,
+    0xB3, 0x8B, 0xAE, 0x12, 0xDC, 0xCF, 0x3F, 0x2E, 0x55, 0x12, 0x72, 0x1F,
+    0x2E, 0x6B, 0x71, 0x24, 0x50, 0x1A, 0xDD, 0xE6, 0x9F, 0x84, 0xCD, 0x87,
+    0x7A, 0x58, 0x47, 0x18, 0x74, 0x08, 0xDA, 0x17, 0xBC, 0x9F, 0x9A, 0xBC,
+    0xE9, 0x4B, 0x7D, 0x8C, 0xEC, 0x7A, 0xEC, 0x3A, 0xDB, 0x85, 0x1D, 0xFA,
+    0x63, 0x09, 0x43, 0x66, 0xC4, 0x64, 0xC3, 0xD2, 0xEF, 0x1C, 0x18, 0x47,
+    0x32, 0x15, 0xD8, 0x08, 0xDD, 0x43, 0x3B, 0x37, 0x24, 0xC2, 0xBA, 0x16,
+    0x12, 0xA1, 0x4D, 0x43, 0x2A, 0x65, 0xC4, 0x51, 0x50, 0x94, 0x00, 0x02,
+    0x13, 0x3A, 0xE4, 0xDD, 0x71, 0xDF, 0xF8, 0x9E, 0x10, 0x31, 0x4E, 0x55,
+    0x81, 0xAC, 0x77, 0xD6, 0x5F, 0x11, 0x19, 0x9B, 0x04, 0x35, 0x56, 0xF1,
+    0xD7, 0xA3, 0xC7, 0x6B, 0x3C, 0x11, 0x18, 0x3B, 0x59, 0x24, 0xA5, 0x09,
+    0xF2, 0x8F, 0xE6, 0xED, 0x97, 0xF1, 0xFB, 0xFA, 0x9E, 0xBA, 0xBF, 0x2C,
+    0x1E, 0x15, 0x3C, 0x6E, 0x86, 0xE3, 0x45, 0x70, 0xEA, 0xE9, 0x6F, 0xB1,
+    0x86, 0x0E, 0x5E, 0x0A, 0x5A, 0x3E, 0x2A, 0xB3, 0x77, 0x1F, 0xE7, 0x1C,
+    0x4E, 0x3D, 0x06, 0xFA, 0x29, 0x65, 0xDC, 0xB9, 0x99, 0xE7, 0x1D, 0x0F,
+    0x80, 0x3E, 0x89, 0xD6, 0x52, 0x66, 0xC8, 0x25, 0x2E, 0x4C, 0xC9, 0x78,
+    0x9C, 0x10, 0xB3, 0x6A, 0xC6, 0x15, 0x0E, 0xBA, 0x94, 0xE2, 0xEA, 0x78,
+    0xA6, 0xFC, 0x3C, 0x53, 0x1E, 0x0A, 0x2D, 0xF4, 0xF2, 0xF7, 0x4E, 0xA7,
+    0x36, 0x1D, 0x2B, 0x3D, 0x19, 0x39, 0x26, 0x0F, 0x19, 0xC2, 0x79, 0x60,
+    0x52, 0x23, 0xA7, 0x08, 0xF7, 0x13, 0x12, 0xB6, 0xEB, 0xAD, 0xFE, 0x6E,
+    0xEA, 0xC3, 0x1F, 0x66, 0xE3, 0xBC, 0x45, 0x95, 0xA6, 0x7B, 0xC8, 0x83,
+    0xB1, 0x7F, 0x37, 0xD1, 0x01, 0x8C, 0xFF, 0x28, 0xC3, 0x32, 0xDD, 0xEF,
+    0xBE, 0x6C, 0x5A, 0xA5, 0x65, 0x58, 0x21, 0x85, 0x68, 0xAB, 0x97, 0x02,
+    0xEE, 0xCE, 0xA5, 0x0F, 0xDB, 0x2F, 0x95, 0x3B, 0x2A, 0xEF, 0x7D, 0xAD,
+    0x5B, 0x6E, 0x2F, 0x84, 0x15, 0x21, 0xB6, 0x28, 0x29, 0x07, 0x61, 0x70,
+    0xEC, 0xDD, 0x47, 0x75, 0x61, 0x9F, 0x15, 0x10, 0x13, 0xCC, 0xA8, 0x30,
+    0xEB, 0x61, 0xBD, 0x96, 0x03, 0x34, 0xFE, 0x1E, 0xAA, 0x03, 0x63, 0xCF,
+    0xB5, 0x73, 0x5C, 0x90, 0x4C, 0x70, 0xA2, 0x39, 0xD5, 0x9E, 0x9E, 0x0B,
+    0xCB, 0xAA, 0xDE, 0x14, 0xEE, 0xCC, 0x86, 0xBC, 0x60, 0x62, 0x2C, 0xA7,
+    0x9C, 0xAB, 0x5C, 0xAB, 0xB2, 0xF3, 0x84, 0x6E, 0x64, 0x8B, 0x1E, 0xAF,
+    0x19, 0xBD, 0xF0, 0xCA, 0xA0, 0x23, 0x69, 0xB9, 0x65, 0x5A, 0xBB, 0x50,
+    0x40, 0x68, 0x5A, 0x32, 0x3C, 0x2A, 0xB4, 0xB3, 0x31, 0x9E, 0xE9, 0xD5,
+    0xC0, 0x21, 0xB8, 0xF7, 0x9B, 0x54, 0x0B, 0x19, 0x87, 0x5F, 0xA0, 0x99,
+    0x95, 0xF7, 0x99, 0x7E, 0x62, 0x3D, 0x7D, 0xA8, 0xF8, 0x37, 0x88, 0x9A,
+    0x97, 0xE3, 0x2D, 0x77, 0x11, 0xED, 0x93, 0x5F, 0x16, 0x68, 0x12, 0x81,
+    0x0E, 0x35, 0x88, 0x29, 0xC7, 0xE6, 0x1F, 0xD6, 0x96, 0xDE, 0xDF, 0xA1,
+    0x78, 0x58, 0xBA, 0x99, 0x57, 0xF5, 0x84, 0xA5, 0x1B, 0x22, 0x72, 0x63,
+    0x9B, 0x83, 0xC3, 0xFF, 0x1A, 0xC2, 0x46, 0x96, 0xCD, 0xB3, 0x0A, 0xEB,
+    0x53, 0x2E, 0x30, 0x54, 0x8F, 0xD9, 0x48, 0xE4, 0x6D, 0xBC, 0x31, 0x28,
+    0x58, 0xEB, 0xF2, 0xEF, 0x34, 0xC6, 0xFF, 0xEA, 0xFE, 0x28, 0xED, 0x61,
+    0xEE, 0x7C, 0x3C, 0x73, 0x5D, 0x4A, 0x14, 0xD9, 0xE8, 0x64, 0xB7, 0xE3,
+    0x42, 0x10, 0x5D, 0x14, 0x20, 0x3E, 0x13, 0xE0, 0x45, 0xEE, 0xE2, 0xB6,
+    0xA3, 0xAA, 0xAB, 0xEA, 0xDB, 0x6C, 0x4F, 0x15, 0xFA, 0xCB, 0x4F, 0xD0,
+    0xC7, 0x42, 0xF4, 0x42, 0xEF, 0x6A, 0xBB, 0xB5, 0x65, 0x4F, 0x3B, 0x1D,
+    0x41, 0xCD, 0x21, 0x05, 0xD8, 0x1E, 0x79, 0x9E, 0x86, 0x85, 0x4D, 0xC7,
+    0xE4, 0x4B, 0x47, 0x6A, 0x3D, 0x81, 0x62, 0x50, 0xCF, 0x62, 0xA1, 0xF2,
+    0x5B, 0x8D, 0x26, 0x46, 0xFC, 0x88, 0x83, 0xA0, 0xC1, 0xC7, 0xB6, 0xA3,
+    0x7F, 0x15, 0x24, 0xC3, 0x69, 0xCB, 0x74, 0x92, 0x47, 0x84, 0x8A, 0x0B,
+    0x56, 0x92, 0xB2, 0x85, 0x09, 0x5B, 0xBF, 0x00, 0xAD, 0x19, 0x48, 0x9D,
+    0x14, 0x62, 0xB1, 0x74, 0x23, 0x82, 0x0D, 0x00, 0x58, 0x42, 0x8D, 0x2A,
+    0x0C, 0x55, 0xF5, 0xEA, 0x1D, 0xAD, 0xF4, 0x3E, 0x23, 0x3F, 0x70, 0x61,
+    0x33, 0x72, 0xF0, 0x92, 0x8D, 0x93, 0x7E, 0x41, 0xD6, 0x5F, 0xEC, 0xF1,
+    0x6C, 0x22, 0x3B, 0xDB, 0x7C, 0xDE, 0x37, 0x59, 0xCB, 0xEE, 0x74, 0x60,
+    0x40, 0x85, 0xF2, 0xA7, 0xCE, 0x77, 0x32, 0x6E, 0xA6, 0x07, 0x80, 0x84,
+    0x19, 0xF8, 0x50, 0x9E, 0xE8, 0xEF, 0xD8, 0x55, 0x61, 0xD9, 0x97, 0x35,
+    0xA9, 0x69, 0xA7, 0xAA, 0xC5, 0x0C, 0x06, 0xC2, 0x5A, 0x04, 0xAB, 0xFC,
+    0x80, 0x0B, 0xCA, 0xDC, 0x9E, 0x44, 0x7A, 0x2E, 0xC3, 0x45, 0x34, 0x84,
+    0xFD, 0xD5, 0x67, 0x05, 0x0E, 0x1E, 0x9E, 0xC9, 0xDB, 0x73, 0xDB, 0xD3,
+    0x10, 0x55, 0x88, 0xCD, 0x67, 0x5F, 0xDA, 0x79, 0xE3, 0x67, 0x43, 0x40,
+    0xC5, 0xC4, 0x34, 0x65, 0x71, 0x3E, 0x38, 0xD8, 0x3D, 0x28, 0xF8, 0x9E,
+    0xF1, 0x6D, 0xFF, 0x20, 0x15, 0x3E, 0x21, 0xE7, 0x8F, 0xB0, 0x3D, 0x4A,
+    0xE6, 0xE3, 0x9F, 0x2B, 0xDB, 0x83, 0xAD, 0xF7, 0xE9, 0x3D, 0x5A, 0x68,
+    0x94, 0x81, 0x40, 0xF7, 0xF6, 0x4C, 0x26, 0x1C, 0x94, 0x69, 0x29, 0x34,
+    0x41, 0x15, 0x20, 0xF7, 0x76, 0x02, 0xD4, 0xF7, 0xBC, 0xF4, 0x6B, 0x2E,
+    0xD4, 0xA1, 0x00, 0x68, 0xD4, 0x08, 0x24, 0x71, 0x33, 0x20, 0xF4, 0x6A,
+    0x43, 0xB7, 0xD4, 0xB7, 0x50, 0x00, 0x61, 0xAF, 0x1E, 0x39, 0xF6, 0x2E,
+    0x97, 0x24, 0x45, 0x46,
+};
+
+alignas(16) const unsigned char kRandenRoundKeys[kKeyBytes] = {
+    0x44, 0x73, 0x70, 0x03, 0x2E, 0x8A, 0x19, 0x13, 0xD3, 0x08, 0xA3, 0x85,
+    0x88, 0x6A, 0x3F, 0x24, 0x89, 0x6C, 0x4E, 0xEC, 0x98, 0xFA, 0x2E, 0x08,
+    0xD0, 0x31, 0x9F, 0x29, 0x22, 0x38, 0x09, 0xA4, 0x6C, 0x0C, 0xE9, 0x34,
+    0xCF, 0x66, 0x54, 0xBE, 0x77, 0x13, 0xD0, 0x38, 0xE6, 0x21, 0x28, 0x45,
+    0x17, 0x09, 0x47, 0xB5, 0xB5, 0xD5, 0x84, 0x3F, 0xDD, 0x50, 0x7C, 0xC9,
+    0xB7, 0x29, 0xAC, 0xC0, 0xAC, 0xB5, 0xDF, 0x98, 0xA6, 0x0B, 0x31, 0xD1,
+    0x1B, 0xFB, 0x79, 0x89, 0xD9, 0xD5, 0x16, 0x92, 0x96, 0x7E, 0x26, 0x6A,
+    0xED, 0xAF, 0xE1, 0xB8, 0xB7, 0xDF, 0x1A, 0xD0, 0xDB, 0x72, 0xFD, 0x2F,
+    0xF7, 0x6C, 0x91, 0xB3, 0x47, 0x99, 0xA1, 0x24, 0x99, 0x7F, 0x2C, 0xF1,
+    0x45, 0x90, 0x7C, 0xBA, 0x69, 0x4E, 0x57, 0x71, 0xD8, 0x20, 0x69, 0x63,
+    0x16, 0xFC, 0x8E, 0x85, 0xE2, 0xF2, 0x01, 0x08, 0x58, 0xB6, 0x8E, 0x72,
+    0x8F, 0x74, 0x95, 0x0D, 0x7E, 0x3D, 0x93, 0xF4, 0xA3, 0xFE, 0x58, 0xA4,
+    0xB5, 0x59, 0x5A, 0xC2, 0x1D, 0xA4, 0x54, 0x7B, 0xEE, 0x4A, 0x15, 0x82,
+    0x58, 0xCD, 0x8B, 0x71, 0xF0, 0x85, 0x60, 0x28, 0x23, 0xB0, 0xD1, 0xC5,
+    0x13, 0x60, 0xF2, 0x2A, 0x39, 0xD5, 0x30, 0x9C, 0x0E, 0x18, 0x3A, 0x60,
+    0xB0, 0xDC, 0x79, 0x8E, 0xEF, 0x38, 0xDB, 0xB8, 0x18, 0x79, 0x41, 0xCA,
+    0x27, 0x4B, 0x31, 0xBD, 0xC1, 0x77, 0x15, 0xD7, 0x3E, 0x8A, 0x1E, 0xB0,
+    0x8B, 0x0E, 0x9E, 0x6C, 0x94, 0xAB, 0x55, 0xAA, 0xF3, 0x25, 0x55, 0xE6,
+    0x60, 0x5C, 0x60, 0x55, 0xDA, 0x2F, 0xAF, 0x78, 0xB6, 0x10, 0xAB, 0x2A,
+    0x6A, 0x39, 0xCA, 0x55, 0x40, 0x14, 0xE8, 0x63, 0x62, 0x98, 0x48, 0x57,
+    0x93, 0xE9, 0x72, 0x7C, 0xAF, 0x86, 0x54, 0xA1, 0xCE, 0xE8, 0x41, 0x11,
+    0x34, 0x5C, 0xCC, 0xB4, 0xF6, 0x31, 0x18, 0x74, 0x5D, 0xC5, 0xA9, 0x2B,
+    0x2A, 0xBC, 0x6F, 0x63, 0x11, 0x14, 0xEE, 0xB3, 0x5C, 0xCF, 0x24, 0x6C,
+    0x33, 0xBA, 0xD6, 0xAF, 0x1E, 0x93, 0x87, 0x9B, 0x16, 0x3E, 0x5C, 0xCE,
+    0xAF, 0xB9, 0x4B, 0x6B, 0x98, 0x48, 0x8F, 0x3B, 0x77, 0x86, 0x95, 0x28,
+    0x81, 0x53, 0x32, 0x7A, 0x91, 0xA9, 0x21, 0xFB, 0xCC, 0x09, 0xD8, 0x61,
+    0x93, 0x21, 0x28, 0x66, 0x1B, 0xE8, 0xBF, 0xC4, 0xB1, 0x75, 0x85, 0xE9,
+    0x5D, 0x5D, 0x84, 0xEF, 0x32, 0x80, 0xEC, 0x5D, 0x60, 0xAC, 0x7C, 0x48,
+    0xC5, 0xAC, 0x96, 0xD3, 0x81, 0x3E, 0x89, 0x23, 0x88, 0x1B, 0x65, 0xEB,
+    0x02, 0x23, 0x26, 0xDC, 0x04, 0x20, 0x84, 0xA4, 0x82, 0x44, 0x0B, 0x2E,
+    0x39, 0x42, 0xF4, 0x83, 0xF3, 0x6F, 0x6D, 0x0F, 0x9A, 0x6C, 0xE9, 0xF6,
+    0x42, 0x68, 0xC6, 0x21, 0x5E, 0x9B, 0x1F, 0x9E, 0x4A, 0xF0, 0xC8, 0x69,
+    0x68, 0x2F, 0x54, 0xD8, 0xD2, 0xA0, 0x51, 0x6A, 0xF0, 0x88, 0xD3, 0xAB,
+    0x61, 0x9C, 0x0C, 0x67, 0xE4, 0x3B, 0x7A, 0x13, 0x6C, 0x0B, 0xEF, 0x6E,
+    0xA3, 0x33, 0x51, 0xAB, 0x28, 0xA7, 0x0F, 0x96, 0x76, 0x01, 0xAF, 0x39,
+    0x1D, 0x65, 0xF1, 0xA1, 0x98, 0x2A, 0xFB, 0x7E, 0x50, 0xF0, 0x3B, 0xBA,
+    0xB4, 0x9F, 0x6F, 0x45, 0x19, 0x86, 0xEE, 0x8C, 0x88, 0x0E, 0x43, 0x82,
+    0x3E, 0x59, 0xCA, 0x66, 0x73, 0x20, 0xC1, 0x85, 0xD8, 0x75, 0x6F, 0xE0,
+    0xBE, 0x5E, 0x8B, 0x3B, 0xC3, 0xA5, 0x84, 0x7D, 0x06, 0x77, 0x3F, 0x36,
+    0x62, 0xAA, 0xD3, 0x4E, 0xA6, 0x6A, 0xC1, 0x56, 0x9F, 0x44, 0x1A, 0x40,
+    0x48, 0x12, 0x0A, 0xD0, 0x24, 0xD7, 0xD0, 0x37, 0x3D, 0x02, 0x9B, 0x42,
+    0x72, 0xDF, 0xFE, 0x1B, 0x7B, 0x1B, 0x99, 0x80, 0xC9, 0x72, 0x53, 0x07,
+    0x9B, 0xC0, 0xF1, 0x49, 0xD3, 0xEA, 0x0F, 0xDB, 0x3B, 0x4C, 0x79, 0xB6,
+    0x1A, 0x50, 0xFE, 0xE3, 0xF7, 0xDE, 0xE8, 0xF6, 0xD8, 0x79, 0xD4, 0x25,
+    0xC4, 0x60, 0x9F, 0x40, 0xB6, 0x4F, 0xA9, 0xC1, 0xBA, 0x06, 0xC0, 0x04,
+    0xBD, 0xE0, 0x6C, 0x97, 0xB5, 0x53, 0x6C, 0x3E, 0xAF, 0x6F, 0xFB, 0x68,
+    0x63, 0x24, 0x6A, 0x19, 0xC2, 0x9E, 0x5C, 0x5E, 0x2C, 0x95, 0x30, 0x9B,
+    0x1F, 0x51, 0xFC, 0x6D, 0x6F, 0xEC, 0x52, 0x3B, 0xEB, 0xB2, 0x39, 0x13,
+    0xFD, 0x4A, 0x33, 0xDE, 0x04, 0xD0, 0xE3, 0xBE, 0x09, 0xBD, 0x5E, 0xAF,
+    0x44, 0x45, 0x81, 0xCC, 0x0F, 0x74, 0xC8, 0x45, 0x57, 0xA8, 0xCB, 0xC0,
+    0xB3, 0x4B, 0x2E, 0x19, 0x07, 0x28, 0x0F, 0x66, 0x0A, 0x32, 0x60, 0x1A,
+    0xBD, 0xC0, 0x79, 0x55, 0xDB, 0xFB, 0xD3, 0xB9, 0x39, 0x5F, 0x0B, 0xD2,
+    0xCC, 0xA3, 0x1F, 0xFB, 0xFE, 0x25, 0x9F, 0x67, 0x79, 0x72, 0x2C, 0x40,
+    0xC6, 0x00, 0xA1, 0xD6, 0x15, 0x6B, 0x61, 0xFD, 0xDF, 0x16, 0x75, 0x3C,
+    0xF8, 0x22, 0x32, 0xDB, 0xF8, 0xE9, 0xA5, 0x8E, 0x60, 0x87, 0x23, 0xFD,
+    0xFA, 0xB5, 0x3D, 0x32, 0xAB, 0x52, 0x05, 0xAD, 0xC8, 0x1E, 0x50, 0x2F,
+    0xA0, 0x8C, 0x6F, 0xCA, 0xBB, 0x57, 0x5C, 0x9E, 0x82, 0xDF, 0x00, 0x3E,
+    0x48, 0x7B, 0x31, 0x53, 0xC3, 0xFF, 0x7E, 0x28, 0xF6, 0xA8, 0x42, 0xD5,
+    0xDB, 0x69, 0x17, 0xDF, 0x2E, 0x56, 0x87, 0x1A, 0xC8, 0x58, 0xCA, 0xBB,
+    0xB0, 0x27, 0x5B, 0x69, 0x73, 0x55, 0x4F, 0x8C, 0xC6, 0x32, 0x67, 0xAC,
+    0xB8, 0x83, 0x21, 0xFD, 0x98, 0x3D, 0xFA, 0x10, 0xA0, 0x11, 0xF0, 0xB8,
+    0x5D, 0xA3, 0xFF, 0xE1, 0x65, 0x45, 0xF8, 0xB6, 0x79, 0xE4, 0x53, 0x9A,
+    0x5B, 0xD3, 0xD1, 0x2D, 0x6C, 0xB5, 0xFC, 0x4A, 0x33, 0x7E, 0xCB, 0xA4,
+    0xDA, 0xF2, 0xDD, 0xE1, 0x90, 0x97, 0xFB, 0x4B, 0xBC, 0x49, 0x8E, 0xD2,
+    0x01, 0x4C, 0x77, 0x36, 0xDA, 0xCA, 0x20, 0xEF, 0xE8, 0xC6, 0xE4, 0xCE,
+    0x41, 0x13, 0xFB, 0x62, 0x98, 0x91, 0x90, 0xAE, 0x4D, 0xDA, 0xDB, 0x95,
+    0xB4, 0x1F, 0xF1, 0x2B, 0xFE, 0x9E, 0x7E, 0xD0, 0xE0, 0x25, 0xC7, 0xAF,
+    0xD0, 0xD1, 0x8E, 0xD0, 0xA0, 0xD5, 0x93, 0x6B, 0x71, 0x8E, 0xAD, 0xEA,
+    0x64, 0x2B, 0x12, 0xF2, 0xFB, 0xE2, 0xF6, 0x8F, 0xB7, 0x94, 0x75, 0x8E,
+    0x2F, 0x5B, 0x3C, 0x8E, 0x1C, 0xC3, 0x8F, 0x68, 0xA0, 0x5E, 0xAD, 0x4F,
+    0x1C, 0xF0, 0x0D, 0x90, 0x12, 0xB8, 0x88, 0x88, 0x77, 0x17, 0x0E, 0xBE,
+    0x18, 0x22, 0x2F, 0x2F, 0xAD, 0xC1, 0xA8, 0xB3, 0x91, 0xF1, 0xCF, 0xD1,
+    0xE8, 0x74, 0x6F, 0xB5, 0x0F, 0xCC, 0xA0, 0xE5, 0xA1, 0x1F, 0x02, 0x8B,
+    0xFE, 0x2D, 0x75, 0xEA, 0xB7, 0xE0, 0x13, 0xFD, 0xE0, 0x4F, 0xA8, 0xB4,
+    0x99, 0xE2, 0x89, 0xCE, 0xD6, 0xF3, 0xAC, 0x18, 0x05, 0x77, 0x95, 0x80,
+    0x66, 0xA2, 0x5F, 0x16, 0xD9, 0xA8, 0xAD, 0xD2, 0x81, 0x3B, 0xC4, 0x7C,
+    0x86, 0xFA, 0xB5, 0x77, 0x65, 0x20, 0xAD, 0xE6, 0x77, 0x14, 0x1A, 0x21,
+    0x14, 0x73, 0xCC, 0x93, 0xA0, 0x89, 0x3E, 0x7B, 0x0C, 0xAF, 0xCD, 0xEB,
+    0xCF, 0x35, 0x9D, 0xFB, 0xF5, 0x42, 0x54, 0xC7, 0x5E, 0xB3, 0x71, 0x20,
+    0x2D, 0x0E, 0x25, 0x00, 0x49, 0x7E, 0x1E, 0xAE, 0xD3, 0x1B, 0x41, 0xD6,
+    0x1E, 0xB9, 0x09, 0xF0, 0x9B, 0x36, 0x64, 0x24, 0xAF, 0xE0, 0xB8, 0x57,
+    0xBB, 0x00, 0x68, 0x22, 0x7F, 0x53, 0x5A, 0xD9, 0x89, 0x43, 0xC1, 0x78,
+    0xAA, 0xA6, 0xDF, 0x59, 0x1D, 0x91, 0x63, 0x55, 0xA9, 0xCF, 0x95, 0x62,
+    0x76, 0x03, 0x26, 0x83, 0xC5, 0xB9, 0xE5, 0x02, 0xA2, 0x5B, 0x7D, 0x20,
+    0x4A, 0xA9, 0x14, 0x7B, 0xCA, 0x2D, 0x47, 0xB3, 0x41, 0x4A, 0x73, 0x4E,
+    0x68, 0x19, 0xC8, 0x11, 0xE4, 0xC6, 0x9B, 0xBC, 0x3F, 0x57, 0x0F, 0xD6,
+    0x15, 0x29, 0x53, 0x9A, 0x52, 0x00, 0x51, 0x1B, 0x1F, 0xE9, 0x1B, 0x57,
+    0xB5, 0x6F, 0xBA, 0x08, 0x00, 0x74, 0xE6, 0x81, 0x76, 0xA4, 0x60, 0x2B,
+    0xB6, 0xF9, 0xB9, 0xE7, 0x21, 0x65, 0x63, 0xB6, 0x15, 0xD9, 0x0D, 0x2A,
+    0x6B, 0xEC, 0x96, 0xF2, 0xA1, 0x8F, 0x9F, 0xA9, 0x5D, 0x2D, 0xB0, 0x53,
+    0x64, 0x56, 0x85, 0xC5, 0x2E, 0x05, 0x34, 0xFF, 0x44, 0x29, 0xB3, 0xB5,
+    0xE9, 0x70, 0x7A, 0x4B, 0x6A, 0x07, 0x85, 0x6E, 0x99, 0x47, 0xBA, 0x08,
+    0x7D, 0xDF, 0xA7, 0x49, 0xB0, 0xA6, 0x6E, 0xAD, 0x23, 0x26, 0x19, 0xC4,
+    0x2E, 0x09, 0x75, 0xDB, 0xFF, 0x18, 0x9A, 0x69, 0x71, 0x8C, 0xAA, 0xEC,
+    0x66, 0xB2, 0xED, 0x8F, 0xB8, 0x60, 0xEE, 0x9C, 0x29, 0x4C, 0x09, 0x75,
+    0xA5, 0x02, 0x36, 0x19, 0xE1, 0x9E, 0xB1, 0xC2, 0x6C, 0x52, 0x64, 0x56,
+    0x65, 0x9D, 0x42, 0x5B, 0x9A, 0x98, 0x54, 0x3F, 0x3E, 0x3A, 0x18, 0xE4,
+    0x40, 0x13, 0x59, 0xA0, 0xF5, 0x30, 0xE8, 0xEF, 0x07, 0x9C, 0xD2, 0xA1,
+    0xD6, 0x3F, 0xF7, 0x99, 0xD6, 0xE4, 0x8F, 0x6B, 0x26, 0xEB, 0x70, 0x84,
+    0x86, 0x20, 0xDD, 0x4C, 0xC1, 0x5D, 0x25, 0xF0, 0xE6, 0x38, 0x2D, 0x4D,
+    0xC9, 0xEF, 0xBA, 0x3E, 0x3F, 0x6B, 0x68, 0x09, 0x5E, 0xCC, 0x1E, 0x02,
+    0xC6, 0xE9, 0x82, 0x63, 0x86, 0xE2, 0xA0, 0x52, 0x84, 0x35, 0x7F, 0x68,
+    0xA1, 0x70, 0x6A, 0x6B, 0x14, 0x18, 0x97, 0x3C, 0x5C, 0xAE, 0xDE, 0x7F,
+    0x1C, 0x84, 0x07, 0x3E, 0x37, 0x07, 0x50, 0xAA, 0x05, 0x53, 0x9C, 0xB7,
+    0x0D, 0x0C, 0x50, 0xF0, 0x37, 0xDA, 0x3A, 0xB0, 0xB8, 0xF2, 0x16, 0x57,
+    0xEC, 0x44, 0x7D, 0x8E, 0xB2, 0x74, 0xB5, 0x3C, 0x1A, 0xF5, 0x0C, 0xAE,
+    0xFF, 0xB3, 0x00, 0x02, 0x04, 0x1F, 0x1C, 0xF0, 0xF6, 0x2F, 0xA9, 0x7C,
+    0xF9, 0x13, 0x91, 0xD1, 0xBD, 0x21, 0x09, 0xDC, 0x58, 0x7A, 0x83, 0x25,
+    0xDC, 0xDA, 0xC2, 0x37, 0x81, 0xE5, 0xE5, 0x3A, 0x01, 0x47, 0xF5, 0x22,
+    0x73, 0x47, 0x32, 0x94, 0x0E, 0x03, 0xD0, 0x0F, 0x46, 0x61, 0x44, 0xA9,
+    0xA7, 0xDD, 0xF3, 0x9A, 0x34, 0x76, 0xB5, 0xC8, 0x2F, 0x0E, 0xEA, 0x3B,
+    0x99, 0xCD, 0x38, 0xE2, 0x41, 0x1E, 0x75, 0xA4, 0x3E, 0xC7, 0xC8, 0xEC,
+    0x08, 0xB9, 0x6D, 0x4F, 0x38, 0x8B, 0x54, 0x4E, 0x31, 0xB3, 0x3E, 0x18,
+    0xA1, 0xBB, 0x80, 0x32, 0x79, 0x7C, 0x97, 0x24, 0x90, 0x12, 0xB8, 0x2C,
+    0xBF, 0x04, 0x0A, 0xF6, 0x03, 0x0D, 0x42, 0x6F, 0x10, 0x08, 0x93, 0xD9,
+    0x1F, 0x77, 0x9A, 0xDE, 0xAF, 0x89, 0xAF, 0xBC, 0x72, 0xB0, 0x79, 0x56,
+    0x24, 0x71, 0x6B, 0x2E, 0x1F, 0x72, 0x12, 0x55, 0x2E, 0x3F, 0xCF, 0xDC,
+    0x12, 0xAE, 0x8B, 0xB3, 0x17, 0xDA, 0x08, 0x74, 0x18, 0x47, 0x58, 0x7A,
+    0x87, 0xCD, 0x84, 0x9F, 0xE6, 0xDD, 0x1A, 0x50, 0xFA, 0x1D, 0x85, 0xDB,
+    0x3A, 0xEC, 0x7A, 0xEC, 0x8C, 0x7D, 0x4B, 0xE9, 0xBC, 0x9A, 0x9F, 0xBC,
+    0x08, 0xD8, 0x15, 0x32, 0x47, 0x18, 0x1C, 0xEF, 0xD2, 0xC3, 0x64, 0xC4,
+    0x66, 0x43, 0x09, 0x63, 0x51, 0xC4, 0x65, 0x2A, 0x43, 0x4D, 0xA1, 0x12,
+    0x16, 0xBA, 0xC2, 0x24, 0x37, 0x3B, 0x43, 0xDD, 0x55, 0x4E, 0x31, 0x10,
+    0x9E, 0xF8, 0xDF, 0x71, 0xDD, 0xE4, 0x3A, 0x13, 0x02, 0x00, 0x94, 0x50,
+    0x6B, 0xC7, 0xA3, 0xD7, 0xF1, 0x56, 0x35, 0x04, 0x9B, 0x19, 0x11, 0x5F,
+    0xD6, 0x77, 0xAC, 0x81, 0xFA, 0xFB, 0xF1, 0x97, 0xED, 0xE6, 0x8F, 0xF2,
+    0x09, 0xA5, 0x24, 0x59, 0x3B, 0x18, 0x11, 0x3C, 0xB1, 0x6F, 0xE9, 0xEA,
+    0x70, 0x45, 0xE3, 0x86, 0x6E, 0x3C, 0x15, 0x1E, 0x2C, 0xBF, 0xBA, 0x9E,
+    0xFA, 0x06, 0x3D, 0x4E, 0x1C, 0xE7, 0x1F, 0x77, 0xB3, 0x2A, 0x3E, 0x5A,
+    0x0A, 0x5E, 0x0E, 0x86, 0x25, 0xC8, 0x66, 0x52, 0xD6, 0x89, 0x3E, 0x80,
+    0x0F, 0x1D, 0xE7, 0x99, 0xB9, 0xDC, 0x65, 0x29, 0x78, 0xEA, 0xE2, 0x94,
+    0xBA, 0x0E, 0x15, 0xC6, 0x6A, 0xB3, 0x10, 0x9C, 0x78, 0xC9, 0x4C, 0x2E,
+    0x3D, 0x2B, 0x1D, 0x36, 0xA7, 0x4E, 0xF7, 0xF2, 0xF4, 0x2D, 0x0A, 0x1E,
+    0x53, 0x3C, 0xFC, 0xA6, 0xB6, 0x12, 0x13, 0xF7, 0x08, 0xA7, 0x23, 0x52,
+    0x60, 0x79, 0xC2, 0x19, 0x0F, 0x26, 0x39, 0x19, 0x83, 0xC8, 0x7B, 0xA6,
+    0x95, 0x45, 0xBC, 0xE3, 0x66, 0x1F, 0xC3, 0xEA, 0x6E, 0xFE, 0xAD, 0xEB,
+    0xA5, 0x5A, 0x6C, 0xBE, 0xEF, 0xDD, 0x32, 0xC3, 0x28, 0xFF, 0x8C, 0x01,
+    0xD1, 0x37, 0x7F, 0xB1, 0x3B, 0x95, 0x2F, 0xDB, 0x0F, 0xA5, 0xCE, 0xEE,
+    0x02, 0x97, 0xAB, 0x68, 0x85, 0x21, 0x58, 0x65, 0x70, 0x61, 0x07, 0x29,
+    0x28, 0xB6, 0x21, 0x15, 0x84, 0x2F, 0x6E, 0x5B, 0xAD, 0x7D, 0xEF, 0x2A,
+    0x96, 0xBD, 0x61, 0xEB, 0x30, 0xA8, 0xCC, 0x13, 0x10, 0x15, 0x9F, 0x61,
+    0x75, 0x47, 0xDD, 0xEC, 0x39, 0xA2, 0x70, 0x4C, 0x90, 0x5C, 0x73, 0xB5,
+    0xCF, 0x63, 0x03, 0xAA, 0x1E, 0xFE, 0x34, 0x03, 0xA7, 0x2C, 0x62, 0x60,
+    0xBC, 0x86, 0xCC, 0xEE, 0x14, 0xDE, 0xAA, 0xCB, 0x0B, 0x9E, 0x9E, 0xD5,
+    0xCA, 0xF0, 0xBD, 0x19, 0xAF, 0x1E, 0x8B, 0x64, 0x6E, 0x84, 0xF3, 0xB2,
+    0xAB, 0x5C, 0xAB, 0x9C, 0xB3, 0xB4, 0x2A, 0x3C, 0x32, 0x5A, 0x68, 0x40,
+    0x50, 0xBB, 0x5A, 0x65, 0xB9, 0x69, 0x23, 0xA0, 0x99, 0xA0, 0x5F, 0x87,
+    0x19, 0x0B, 0x54, 0x9B, 0xF7, 0xB8, 0x21, 0xC0, 0xD5, 0xE9, 0x9E, 0x31,
+    0x77, 0x2D, 0xE3, 0x97, 0x9A, 0x88, 0x37, 0xF8, 0xA8, 0x7D, 0x3D, 0x62,
+    0x7E, 0x99, 0xF7, 0x95, 0xD6, 0x1F, 0xE6, 0xC7, 0x29, 0x88, 0x35, 0x0E,
+    0x81, 0x12, 0x68, 0x16, 0x5F, 0x93, 0xED, 0x11, 0x63, 0x72, 0x22, 0x1B,
+    0xA5, 0x84, 0xF5, 0x57, 0x99, 0xBA, 0x58, 0x78, 0xA1, 0xDF, 0xDE, 0x96,
+    0x54, 0x30, 0x2E, 0x53, 0xEB, 0x0A, 0xB3, 0xCD, 0x96, 0x46, 0xC2, 0x1A,
+    0xFF, 0xC3, 0x83, 0x9B, 0xEA, 0xFF, 0xC6, 0x34, 0xEF, 0xF2, 0xEB, 0x58,
+    0x28, 0x31, 0xBC, 0x6D, 0xE4, 0x48, 0xD9, 0x8F, 0xE3, 0xB7, 0x64, 0xE8,
+    0xD9, 0x14, 0x4A, 0x5D, 0x73, 0x3C, 0x7C, 0xEE, 0x61, 0xED, 0x28, 0xFE,
+    0xEA, 0xAB, 0xAA, 0xA3, 0xB6, 0xE2, 0xEE, 0x45, 0xE0, 0x13, 0x3E, 0x20,
+    0x14, 0x5D, 0x10, 0x42, 0xB5, 0xBB, 0x6A, 0xEF, 0x42, 0xF4, 0x42, 0xC7,
+    0xD0, 0x4F, 0xCB, 0xFA, 0x15, 0x4F, 0x6C, 0xDB, 0xC7, 0x4D, 0x85, 0x86,
+    0x9E, 0x79, 0x1E, 0xD8, 0x05, 0x21, 0xCD, 0x41, 0x1D, 0x3B, 0x4F, 0x65,
+    0x46, 0x26, 0x8D, 0x5B, 0xF2, 0xA1, 0x62, 0xCF, 0x50, 0x62, 0x81, 0x3D,
+    0x6A, 0x47, 0x4B, 0xE4, 0x92, 0x74, 0xCB, 0x69, 0xC3, 0x24, 0x15, 0x7F,
+    0xA3, 0xB6, 0xC7, 0xC1, 0xA0, 0x83, 0x88, 0xFC, 0x9D, 0x48, 0x19, 0xAD,
+    0x00, 0xBF, 0x5B, 0x09, 0x85, 0xB2, 0x92, 0x56, 0x0B, 0x8A, 0x84, 0x47,
+    0xEA, 0xF5, 0x55, 0x0C, 0x2A, 0x8D, 0x42, 0x58, 0x00, 0x0D, 0x82, 0x23,
+    0x74, 0xB1, 0x62, 0x14, 0x41, 0x7E, 0x93, 0x8D, 0x92, 0xF0, 0x72, 0x33,
+    0x61, 0x70, 0x3F, 0x23, 0x3E, 0xF4, 0xAD, 0x1D, 0x60, 0x74, 0xEE, 0xCB,
+    0x59, 0x37, 0xDE, 0x7C, 0xDB, 0x3B, 0x22, 0x6C, 0xF1, 0xEC, 0x5F, 0xD6,
+    0x9E, 0x50, 0xF8, 0x19, 0x84, 0x80, 0x07, 0xA6, 0x6E, 0x32, 0x77, 0xCE,
+    0xA7, 0xF2, 0x85, 0x40, 0xC2, 0x06, 0x0C, 0xC5, 0xAA, 0xA7, 0x69, 0xA9,
+    0x35, 0x97, 0xD9, 0x61, 0x55, 0xD8, 0xEF, 0xE8, 0x84, 0x34, 0x45, 0xC3,
+    0x2E, 0x7A, 0x44, 0x9E, 0xDC, 0xCA, 0x0B, 0x80, 0xFC, 0xAB, 0x04, 0x5A,
+    0xCD, 0x88, 0x55, 0x10, 0xD3, 0xDB, 0x73, 0xDB, 0xC9, 0x9E, 0x1E, 0x0E,
+    0x05, 0x67, 0xD5, 0xFD, 0xD8, 0x38, 0x3E, 0x71, 0x65, 0x34, 0xC4, 0xC5,
+    0x40, 0x43, 0x67, 0xE3, 0x79, 0xDA, 0x5F, 0x67, 0x4A, 0x3D, 0xB0, 0x8F,
+    0xE7, 0x21, 0x3E, 0x15, 0x20, 0xFF, 0x6D, 0xF1, 0x9E, 0xF8, 0x28, 0x3D,
+    0xF7, 0x40, 0x81, 0x94, 0x68, 0x5A, 0x3D, 0xE9, 0xF7, 0xAD, 0x83, 0xDB,
+    0x2B, 0x9F, 0xE3, 0xE6, 0xF7, 0xD4, 0x02, 0x76, 0xF7, 0x20, 0x15, 0x41,
+    0x34, 0x29, 0x69, 0x94, 0x1C, 0x26, 0x4C, 0xF6, 0x6A, 0xF4, 0x20, 0x33,
+    0x71, 0x24, 0x08, 0xD4, 0x68, 0x00, 0xA1, 0xD4, 0x2E, 0x6B, 0xF4, 0xBC,
+    0x46, 0x45, 0x24, 0x97, 0x2E, 0xF6, 0x39, 0x1E, 0xAF, 0x61, 0x00, 0x50,
+    0xB7, 0xD4, 0xB7, 0x43,
+};
+
+}  // namespace random_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/random/internal/randen_slow.cc b/absl/random/internal/randen_slow.cc
index 7a2e2da..4e5f3dc 100644
--- a/absl/random/internal/randen_slow.cc
+++ b/absl/random/internal/randen_slow.cc
@@ -18,16 +18,9 @@
 #include <cstdint>
 #include <cstring>
 
+#include "absl/base/attributes.h"
 #include "absl/random/internal/platform.h"
-
-// ABSL_HAVE_ATTRIBUTE
-#if !defined(ABSL_HAVE_ATTRIBUTE)
-#ifdef __has_attribute
-#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x)
-#else
-#define ABSL_HAVE_ATTRIBUTE(x) 0
-#endif
-#endif
+#include "absl/random/internal/randen_traits.h"
 
 #if ABSL_HAVE_ATTRIBUTE(always_inline) || \
     (defined(__GNUC__) && !defined(__clang__))
@@ -233,35 +226,16 @@
     0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c,
 };
 
-struct alignas(16) u64x2 {
-  constexpr u64x2() : v{0, 0} {};
-  constexpr u64x2(uint64_t hi, uint64_t lo) : v{lo, hi} {}
-
-  uint64_t v[2];
-};
-
 // Software implementation of the Vector128 class, using uint32_t
 // as an underlying vector register.
-//
-struct Vector128 {
-  inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128& operator^=(
-      const Vector128& other) {
-    s[0] ^= other.s[0];
-    s[1] ^= other.s[1];
-    s[2] ^= other.s[2];
-    s[3] ^= other.s[3];
-    return *this;
-  }
-
+struct alignas(16) Vector128 {
   uint32_t s[4];
 };
 
 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128
-Vector128Load(const void* ABSL_RANDOM_INTERNAL_RESTRICT from) {
+Vector128Load(const void* from) {
   Vector128 result;
-  const uint8_t* ABSL_RANDOM_INTERNAL_RESTRICT src =
-      reinterpret_cast<const uint8_t*>(from);
-
+  const uint8_t* src = reinterpret_cast<const uint8_t*>(from);
   result.s[0] = static_cast<uint32_t>(src[0]) << 24 |
                 static_cast<uint32_t>(src[1]) << 16 |
                 static_cast<uint32_t>(src[2]) << 8 |
@@ -282,7 +256,7 @@
 }
 
 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Vector128Store(
-    const Vector128& v, void* ABSL_RANDOM_INTERNAL_RESTRICT to) {
+    const Vector128& v, void* to) {
   uint8_t* dst = reinterpret_cast<uint8_t*>(to);
   dst[0] = static_cast<uint8_t>(v.s[0] >> 24);
   dst[1] = static_cast<uint8_t>(v.s[0] >> 16);
@@ -306,91 +280,57 @@
 // symmetry of AES (ensures previously equal columns differ afterwards).
 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128
 AesRound(const Vector128& state, const Vector128& round_key) {
-  // clang-format off
   Vector128 result;
-  result.s[0] = round_key.s[0] ^
-                te0[uint8_t(state.s[0] >> 24)] ^
-                te1[uint8_t(state.s[1] >> 16)] ^
-                te2[uint8_t(state.s[2] >> 8)] ^
+  result.s[0] = round_key.s[0] ^                  //
+                te0[uint8_t(state.s[0] >> 24)] ^  //
+                te1[uint8_t(state.s[1] >> 16)] ^  //
+                te2[uint8_t(state.s[2] >> 8)] ^   //
                 te3[uint8_t(state.s[3])];
-  result.s[1] = round_key.s[1] ^
-                te0[uint8_t(state.s[1] >> 24)] ^
-                te1[uint8_t(state.s[2] >> 16)] ^
-                te2[uint8_t(state.s[3] >> 8)] ^
+  result.s[1] = round_key.s[1] ^                  //
+                te0[uint8_t(state.s[1] >> 24)] ^  //
+                te1[uint8_t(state.s[2] >> 16)] ^  //
+                te2[uint8_t(state.s[3] >> 8)] ^   //
                 te3[uint8_t(state.s[0])];
-  result.s[2] = round_key.s[2] ^
-                te0[uint8_t(state.s[2] >> 24)] ^
-                te1[uint8_t(state.s[3] >> 16)] ^
-                te2[uint8_t(state.s[0] >> 8)] ^
+  result.s[2] = round_key.s[2] ^                  //
+                te0[uint8_t(state.s[2] >> 24)] ^  //
+                te1[uint8_t(state.s[3] >> 16)] ^  //
+                te2[uint8_t(state.s[0] >> 8)] ^   //
                 te3[uint8_t(state.s[1])];
-  result.s[3] = round_key.s[3] ^
-                te0[uint8_t(state.s[3] >> 24)] ^
-                te1[uint8_t(state.s[0] >> 16)] ^
-                te2[uint8_t(state.s[1] >> 8)] ^
+  result.s[3] = round_key.s[3] ^                  //
+                te0[uint8_t(state.s[3] >> 24)] ^  //
+                te1[uint8_t(state.s[0] >> 16)] ^  //
+                te2[uint8_t(state.s[1] >> 8)] ^   //
                 te3[uint8_t(state.s[2])];
   return result;
-  // clang-format on
 }
 
-// RANDen = RANDom generator or beetroots in Swiss German.
-// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
-// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
-//
-// High-level summary:
-// 1) Reverie (see "A Robust and Sponge-Like PRNG with Improved Efficiency") is
-//    a sponge-like random generator that requires a cryptographic permutation.
-//    It improves upon "Provably Robust Sponge-Based PRNGs and KDFs" by
-//    achieving backtracking resistance with only one Permute() per buffer.
-//
-// 2) "Simpira v2: A Family of Efficient Permutations Using the AES Round
-//    Function" constructs up to 1024-bit permutations using an improved
-//    Generalized Feistel network with 2-round AES-128 functions. This Feistel
-//    block shuffle achieves diffusion faster and is less vulnerable to
-//    sliced-biclique attacks than the Type-2 cyclic shuffle.
-//
-// 3) "Improving the Generalized Feistel" and "New criterion for diffusion
-//    property" extends the same kind of improved Feistel block shuffle to 16
-//    branches, which enables a 2048-bit permutation.
-//
-// Combine these three ideas and also change Simpira's subround keys from
-// structured/low-entropy counters to digits of Pi.
+using ::absl::random_internal::RandenTraits;
 
-// Randen constants.
-constexpr size_t kFeistelBlocks = 16;
-constexpr size_t kFeistelFunctions = kFeistelBlocks / 2;  // = 8
-constexpr size_t kFeistelRounds = 16 + 1;  // > 4 * log2(kFeistelBlocks)
-constexpr size_t kKeys = kFeistelRounds * kFeistelFunctions;
-
-// INCLUDE keys.
-#include "absl/random/internal/randen-keys.inc"
-
-static_assert(kKeys == kRoundKeys, "kKeys and kRoundKeys must be equal");
-
-// 2 uint64_t lanes per Vector128
-static constexpr size_t kLanes = 2;
+// Randen operates on 128-bit vectors.
+struct alignas(16) u64x2 {
+  uint64_t data[2];
+};
 
 // The improved Feistel block shuffle function for 16 blocks.
 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void BlockShuffle(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state_u64) {
-  static_assert(kFeistelBlocks == 16,
+    u64x2* state) {
+  static_assert(RandenTraits::kFeistelBlocks == 16,
                 "Feistel block shuffle only works for 16 blocks.");
 
-  constexpr size_t shuffle[kFeistelBlocks] = {7,  2, 13, 4,  11, 8,  3, 6,
-                                              15, 0, 9,  10, 1,  14, 5, 12};
-
-  u64x2* ABSL_RANDOM_INTERNAL_RESTRICT state =
-      reinterpret_cast<u64x2*>(state_u64);
+  constexpr size_t shuffle[RandenTraits::kFeistelBlocks] = {
+      7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12};
 
   // The fully unrolled loop without the memcpy improves the speed by about
-  // 30% over the equivalent (leaving code here as a comment):
-  if (false) {
-    u64x2 source[kFeistelBlocks];
-    std::memcpy(source, state, sizeof(source));
-    for (size_t i = 0; i < kFeistelBlocks; i++) {
-      const u64x2 v0 = source[shuffle[i]];
-      state[i] = v0;
-    }
+  // 30% over the equivalent:
+#if 0
+  u64x2 source[RandenTraits::kFeistelBlocks];
+  std::memcpy(source, state, sizeof(source));
+  for (size_t i = 0; i < RandenTraits::kFeistelBlocks; i++) {
+    const u64x2 v0 = source[shuffle[i]];
+    state[i] = v0;
   }
+  return;
+#endif
 
   const u64x2 v0 = state[shuffle[0]];
   const u64x2 v1 = state[shuffle[1]];
@@ -432,23 +372,23 @@
 // parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel
 // XORs are 'free' (included in the second AES instruction).
 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE const u64x2* FeistelRound(
-    uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state,
+    u64x2* ABSL_RANDOM_INTERNAL_RESTRICT state,
     const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
-  for (size_t branch = 0; branch < kFeistelBlocks; branch += 4) {
-    const Vector128 s0 = Vector128Load(state + kLanes * branch);
-    const Vector128 s1 = Vector128Load(state + kLanes * (branch + 1));
+  for (size_t branch = 0; branch < RandenTraits::kFeistelBlocks; branch += 4) {
+    const Vector128 s0 = Vector128Load(state + branch);
+    const Vector128 s1 = Vector128Load(state + branch + 1);
     const Vector128 f0 = AesRound(s0, Vector128Load(keys));
     keys++;
     const Vector128 o1 = AesRound(f0, s1);
-    Vector128Store(o1, state + kLanes * (branch + 1));
+    Vector128Store(o1, state + branch + 1);
 
     // Manually unroll this loop once. about 10% better than not unrolled.
-    const Vector128 s2 = Vector128Load(state + kLanes * (branch + 2));
-    const Vector128 s3 = Vector128Load(state + kLanes * (branch + 3));
+    const Vector128 s2 = Vector128Load(state + branch + 2);
+    const Vector128 s3 = Vector128Load(state + branch + 3);
     const Vector128 f2 = AesRound(s2, Vector128Load(keys));
     keys++;
     const Vector128 o3 = AesRound(f2, s3);
-    Vector128Store(o3, state + kLanes * (branch + 3));
+    Vector128Store(o3, state + branch + 3);
   }
   return keys;
 }
@@ -458,11 +398,9 @@
 // 2^64 queries if the round function is a PRF. This is similar to the b=8 case
 // of Simpira v2, but more efficient than its generic construction for b=16.
 inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Permute(
-    const void* keys, uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state) {
-  const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys128 =
-      static_cast<const u64x2*>(keys);
-  for (size_t round = 0; round < kFeistelRounds; ++round) {
-    keys128 = FeistelRound(state, keys128);
+    u64x2* state, const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
+  for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) {
+    keys = FeistelRound(state, keys);
     BlockShuffle(state);
   }
 }
@@ -470,43 +408,50 @@
 }  // namespace
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 const void* RandenSlow::GetKeys() {
   // Round keys for one AES per Feistel round and branch.
   // The canonical implementation uses first digits of Pi.
-  return round_keys;
+  return kRandenRoundKeys;
 }
 
 void RandenSlow::Absorb(const void* seed_void, void* state_void) {
-  uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state =
-      reinterpret_cast<uint64_t*>(state_void);
-  const uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT seed =
-      reinterpret_cast<const uint64_t*>(seed_void);
+  auto* state =
+      reinterpret_cast<uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>(state_void);
+  const auto* seed =
+      reinterpret_cast<const uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>(
+          seed_void);
 
-  constexpr size_t kCapacityBlocks = kCapacityBytes / sizeof(uint64_t);
-  static_assert(kCapacityBlocks * sizeof(uint64_t) == kCapacityBytes,
-                "Not i*V");
-  for (size_t i = kCapacityBlocks; i < kStateBytes / sizeof(uint64_t); ++i) {
+  constexpr size_t kCapacityBlocks =
+      RandenTraits::kCapacityBytes / sizeof(uint64_t);
+  static_assert(
+      kCapacityBlocks * sizeof(uint64_t) == RandenTraits::kCapacityBytes,
+      "Not i*V");
+
+  for (size_t i = kCapacityBlocks;
+       i < RandenTraits::kStateBytes / sizeof(uint64_t); ++i) {
     state[i] ^= seed[i - kCapacityBlocks];
   }
 }
 
-void RandenSlow::Generate(const void* keys, void* state_void) {
-  static_assert(kCapacityBytes == sizeof(Vector128), "Capacity mismatch");
+void RandenSlow::Generate(const void* keys_void, void* state_void) {
+  static_assert(RandenTraits::kCapacityBytes == sizeof(u64x2),
+                "Capacity mismatch");
 
-  uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state =
-      reinterpret_cast<uint64_t*>(state_void);
+  auto* state = reinterpret_cast<u64x2*>(state_void);
+  const auto* keys = reinterpret_cast<const u64x2*>(keys_void);
 
-  const Vector128 prev_inner = Vector128Load(state);
+  const u64x2 prev_inner = state[0];
 
-  Permute(keys, state);
+  Permute(state, keys);
 
   // Ensure backtracking resistance.
-  Vector128 inner = Vector128Load(state);
-  inner ^= prev_inner;
-  Vector128Store(inner, state);
+  state[0].data[0] ^= prev_inner.data[0];
+  state[0].data[1] ^= prev_inner.data[1];
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/internal/randen_slow.h b/absl/random/internal/randen_slow.h
index 3058613..532c3a8 100644
--- a/absl/random/internal/randen_slow.h
+++ b/absl/random/internal/randen_slow.h
@@ -17,27 +17,24 @@
 
 #include <cstddef>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
-// RANDen = RANDom generator or beetroots in Swiss German.
+// RANDen = RANDom generator or beetroots in Swiss High German.
 // RandenSlow implements the basic state manipulation methods for
 // architectures lacking AES hardware acceleration intrinsics.
 class RandenSlow {
  public:
-  // Size of the entire sponge / state for the randen PRNG.
-  static constexpr size_t kStateBytes = 256;  // 2048-bit
-
-  // Size of the 'inner' (inaccessible) part of the sponge. Larger values would
-  // require more frequent calls to RandenGenerate.
-  static constexpr size_t kCapacityBytes = 16;  // 128-bit
-
   static void Generate(const void* keys, void* state_void);
   static void Absorb(const void* seed_void, void* state_void);
   static const void* GetKeys();
 };
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_
diff --git a/absl/random/internal/randen_slow_test.cc b/absl/random/internal/randen_slow_test.cc
index c07155d..4a53583 100644
--- a/absl/random/internal/randen_slow_test.cc
+++ b/absl/random/internal/randen_slow_test.cc
@@ -17,18 +17,20 @@
 #include <cstring>
 
 #include "gtest/gtest.h"
+#include "absl/random/internal/randen_traits.h"
 
 namespace {
 
 using absl::random_internal::RandenSlow;
+using absl::random_internal::RandenTraits;
 
 // Local state parameters.
 constexpr size_t kSeedBytes =
-    RandenSlow::kStateBytes - RandenSlow::kCapacityBytes;
-constexpr size_t kStateSizeT = RandenSlow::kStateBytes / sizeof(uint64_t);
+    RandenTraits::kStateBytes - RandenTraits::kCapacityBytes;
+constexpr size_t kStateSizeT = RandenTraits::kStateBytes / sizeof(uint64_t);
 constexpr size_t kSeedSizeT = kSeedBytes / sizeof(uint32_t);
 
-struct randen {
+struct alignas(16) randen {
   uint64_t state[kStateSizeT];
   uint32_t seed[kSeedSizeT];
 };
diff --git a/absl/random/internal/randen_traits.h b/absl/random/internal/randen_traits.h
index 4f1f408..120022c 100644
--- a/absl/random/internal/randen_traits.h
+++ b/absl/random/internal/randen_traits.h
@@ -22,13 +22,35 @@
 
 #include <cstddef>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
-// RANDen = RANDom generator or beetroots in Swiss German.
+// RANDen = RANDom generator or beetroots in Swiss High German.
 // 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
 // generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
 //
+// High-level summary:
+// 1) Reverie (see "A Robust and Sponge-Like PRNG with Improved Efficiency") is
+//    a sponge-like random generator that requires a cryptographic permutation.
+//    It improves upon "Provably Robust Sponge-Based PRNGs and KDFs" by
+//    achieving backtracking resistance with only one Permute() per buffer.
+//
+// 2) "Simpira v2: A Family of Efficient Permutations Using the AES Round
+//    Function" constructs up to 1024-bit permutations using an improved
+//    Generalized Feistel network with 2-round AES-128 functions. This Feistel
+//    block shuffle achieves diffusion faster and is less vulnerable to
+//    sliced-biclique attacks than the Type-2 cyclic shuffle.
+//
+// 3) "Improving the Generalized Feistel" and "New criterion for diffusion
+//    property" extends the same kind of improved Feistel block shuffle to 16
+//    branches, which enables a 2048-bit permutation.
+//
+// Combine these three ideas and also change Simpira's subround keys from
+// structured/low-entropy counters to digits of Pi (or other random source).
+
 // RandenTraits contains the basic algorithm traits, such as the size of the
 // state, seed, sponge, etc.
 struct RandenTraits {
@@ -42,18 +64,25 @@
   // Size of the default seed consumed by the sponge.
   static constexpr size_t kSeedBytes = kStateBytes - kCapacityBytes;
 
+  // Assuming 128-bit blocks, the number of blocks in the state.
   // Largest size for which security proofs are known.
   static constexpr size_t kFeistelBlocks = 16;
 
-  // Type-2 generalized Feistel => one round function for every two blocks.
-  static constexpr size_t kFeistelFunctions = kFeistelBlocks / 2;  // = 8
-
   // Ensures SPRP security and two full subblock diffusions.
   // Must be > 4 * log2(kFeistelBlocks).
   static constexpr size_t kFeistelRounds = 16 + 1;
+
+  // Size of the key. A 128-bit key block is used for every-other
+  // feistel block (Type-2 generalized Feistel network) in each round.
+  static constexpr size_t kKeyBytes = 16 * kFeistelRounds * kFeistelBlocks / 2;
 };
 
+// Randen key arrays. In randen_round_keys.cc
+extern const unsigned char kRandenRoundKeys[RandenTraits::kKeyBytes];
+extern const unsigned char kRandenRoundKeysBE[RandenTraits::kKeyBytes];
+
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_
diff --git a/absl/random/internal/salted_seed_seq.h b/absl/random/internal/salted_seed_seq.h
index 8648700..5953a09 100644
--- a/absl/random/internal/salted_seed_seq.h
+++ b/absl/random/internal/salted_seed_seq.h
@@ -30,6 +30,7 @@
 #include "absl/types/span.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // This class conforms to the C++ Standard "Seed Sequence" concept
@@ -160,6 +161,7 @@
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_
diff --git a/absl/random/internal/seed_material.cc b/absl/random/internal/seed_material.cc
index 85dd535..4d38a57 100644
--- a/absl/random/internal/seed_material.cc
+++ b/absl/random/internal/seed_material.cc
@@ -45,6 +45,9 @@
 #define ABSL_RANDOM_USE_BCRYPT 1
 #pragma comment(lib, "bcrypt.lib")
 
+#elif defined(__Fuchsia__)
+#include <zircon/syscalls.h>
+
 #endif
 
 #if defined(ABSL_RANDOM_USE_BCRYPT)
@@ -58,6 +61,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 namespace {
 
@@ -107,6 +111,15 @@
   return true;
 }
 
+#elif defined(__Fuchsia__)
+
+bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
+  auto buffer = reinterpret_cast<uint8_t*>(values.data());
+  size_t buffer_size = sizeof(uint32_t) * values.size();
+  zx_cprng_draw(buffer, buffer_size);
+  return true;
+}
+
 #else
 
 // On *nix, read entropy from /dev/urandom.
@@ -202,4 +215,5 @@
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/internal/seed_material.h b/absl/random/internal/seed_material.h
index 57de8a2..4be10e9 100644
--- a/absl/random/internal/seed_material.h
+++ b/absl/random/internal/seed_material.h
@@ -27,6 +27,7 @@
 #include "absl/types/span.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // Returns the number of 32-bit blocks needed to contain the given number of
@@ -97,6 +98,7 @@
 absl::optional<uint32_t> GetSaltMaterial();
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_
diff --git a/absl/random/internal/seed_salting_sequence_generator.cc b/absl/random/internal/seed_salting_sequence_generator.cc
deleted file mode 100644
index 31fdcfe..0000000
--- a/absl/random/internal/seed_salting_sequence_generator.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <iostream>
-#include <random>
-
-#include "absl/random/random.h"
-
-// This program is used in integration tests.
-
-int main() {
-  std::seed_seq seed_seq{1234};
-  absl::BitGen rng(seed_seq);
-  constexpr size_t kSequenceLength = 8;
-  for (size_t i = 0; i < kSequenceLength; i++) {
-    std::cout << rng() << "\n";
-  }
-  return 0;
-}
diff --git a/absl/random/internal/sequence_urbg.h b/absl/random/internal/sequence_urbg.h
index 9a9b577..bc96a12 100644
--- a/absl/random/internal/sequence_urbg.h
+++ b/absl/random/internal/sequence_urbg.h
@@ -21,7 +21,10 @@
 #include <type_traits>
 #include <vector>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // `sequence_urbg` is a simple random number generator which meets the
@@ -51,6 +54,7 @@
 };
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_SEQUENCE_URBG_H_
diff --git a/absl/random/internal/traits.h b/absl/random/internal/traits.h
index 40eb011..75772bd 100644
--- a/absl/random/internal/traits.h
+++ b/absl/random/internal/traits.h
@@ -22,6 +22,7 @@
 #include "absl/base/config.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
 // random_internal::is_widening_convertible<A, B>
@@ -94,6 +95,7 @@
 };
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_TRAITS_H_
diff --git a/absl/random/internal/uniform_helper.h b/absl/random/internal/uniform_helper.h
index 2929407..1243bc1 100644
--- a/absl/random/internal/uniform_helper.h
+++ b/absl/random/internal/uniform_helper.h
@@ -19,9 +19,13 @@
 #include <limits>
 #include <type_traits>
 
+#include "absl/base/config.h"
 #include "absl/meta/type_traits.h"
+#include "absl/random/internal/traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
+
 template <typename IntType>
 class uniform_int_distribution;
 
@@ -57,6 +61,26 @@
     : public random_internal::TagTypeCompare<IntervalOpenOpenTag> {};
 
 namespace random_internal {
+
+// In the absence of an explicitly provided return-type, the template
+// "uniform_inferred_return_t<A, B>" is used to derive a suitable type, based on
+// the data-types of the endpoint-arguments {A lo, B hi}.
+//
+// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the
+// return-type, if one type can be implicitly converted into the other, in a
+// lossless way. The template "is_widening_convertible" implements the
+// compile-time logic for deciding if such a conversion is possible.
+//
+// If no such conversion between {A, B} exists, then the overload for
+// absl::Uniform() will be discarded, and the call will be ill-formed.
+// Return-type for absl::Uniform() when the return-type is inferred.
+template <typename A, typename B>
+using uniform_inferred_return_t =
+    absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>,
+                                        is_widening_convertible<B, A>>::value,
+                      typename std::conditional<
+                          is_widening_convertible<A, B>::value, B, A>::type>;
+
 // The functions
 //    uniform_lower_bound(tag, a, b)
 // and
@@ -81,7 +105,7 @@
                           std::is_same<Tag, IntervalOpenOpenTag>>>::value,
     IntType>
 uniform_lower_bound(Tag, IntType a, IntType) {
-  return a + 1;
+  return a < (std::numeric_limits<IntType>::max)() ? (a + 1) : a;
 }
 
 template <typename FloatType, typename Tag>
@@ -112,7 +136,7 @@
                           std::is_same<Tag, IntervalOpenOpenTag>>>::value,
     IntType>
 uniform_upper_bound(Tag, IntType, IntType b) {
-  return b - 1;
+  return b > (std::numeric_limits<IntType>::min)() ? (b - 1) : b;
 }
 
 template <typename FloatType, typename Tag>
@@ -148,21 +172,73 @@
   return std::nextafter(b, (std::numeric_limits<FloatType>::max)());
 }
 
+// Returns whether the bounds are valid for the underlying distribution.
+// Inputs must have already been resolved via uniform_*_bound calls.
+//
+// The c++ standard constraints in [rand.dist.uni.int] are listed as:
+//    requires: lo <= hi.
+//
+// In the uniform_int_distrubtion, {lo, hi} are closed, closed. Thus:
+// [0, 0] is legal.
+// [0, 0) is not legal, but [0, 1) is, which translates to [0, 0].
+// (0, 1) is not legal, but (0, 2) is, which translates to [1, 1].
+// (0, 0] is not legal, but (0, 1] is, which translates to [1, 1].
+//
+// The c++ standard constraints in [rand.dist.uni.real] are listed as:
+//    requires: lo <= hi.
+//    requires: (hi - lo) <= numeric_limits<T>::max()
+//
+// In the uniform_real_distribution, {lo, hi} are closed, open, Thus:
+// [0, 0] is legal, which is [0, 0+epsilon).
+// [0, 0) is legal.
+// (0, 0) is not legal, but (0-epsilon, 0+epsilon) is.
+// (0, 0] is not legal, but (0, 0+epsilon] is.
+//
+template <typename FloatType>
+absl::enable_if_t<std::is_floating_point<FloatType>::value, bool>
+is_uniform_range_valid(FloatType a, FloatType b) {
+  return a <= b && std::isfinite(b - a);
+}
+
+template <typename IntType>
+absl::enable_if_t<std::is_integral<IntType>::value, bool>
+is_uniform_range_valid(IntType a, IntType b) {
+  return a <= b;
+}
+
+// UniformDistribution selects either absl::uniform_int_distribution
+// or absl::uniform_real_distribution depending on the NumType parameter.
 template <typename NumType>
 using UniformDistribution =
     typename std::conditional<std::is_integral<NumType>::value,
                               absl::uniform_int_distribution<NumType>,
                               absl::uniform_real_distribution<NumType>>::type;
 
-template <typename TagType, typename NumType>
+// UniformDistributionWrapper is used as the underlying distribution type
+// by the absl::Uniform template function. It selects the proper Abseil
+// uniform distribution and provides constructor overloads that match the
+// expected parameter order as well as adjusting distribtuion bounds based
+// on the tag.
+template <typename NumType>
 struct UniformDistributionWrapper : public UniformDistribution<NumType> {
+  template <typename TagType>
   explicit UniformDistributionWrapper(TagType, NumType lo, NumType hi)
       : UniformDistribution<NumType>(
             uniform_lower_bound<NumType>(TagType{}, lo, hi),
             uniform_upper_bound<NumType>(TagType{}, lo, hi)) {}
+
+  explicit UniformDistributionWrapper(NumType lo, NumType hi)
+      : UniformDistribution<NumType>(
+            uniform_lower_bound<NumType>(IntervalClosedOpenTag(), lo, hi),
+            uniform_upper_bound<NumType>(IntervalClosedOpenTag(), lo, hi)) {}
+
+  explicit UniformDistributionWrapper()
+      : UniformDistribution<NumType>(std::numeric_limits<NumType>::lowest(),
+                                     (std::numeric_limits<NumType>::max)()) {}
 };
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_
diff --git a/absl/random/internal/uniform_helper_test.cc b/absl/random/internal/uniform_helper_test.cc
new file mode 100644
index 0000000..173c49b
--- /dev/null
+++ b/absl/random/internal/uniform_helper_test.cc
@@ -0,0 +1,279 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/random/internal/uniform_helper.h"
+
+#include <cmath>
+#include <cstdint>
+#include <random>
+
+#include "gtest/gtest.h"
+
+namespace {
+
+using absl::IntervalClosedClosedTag;
+using absl::IntervalClosedOpenTag;
+using absl::IntervalOpenClosedTag;
+using absl::IntervalOpenOpenTag;
+using absl::random_internal::uniform_inferred_return_t;
+using absl::random_internal::uniform_lower_bound;
+using absl::random_internal::uniform_upper_bound;
+
+class UniformHelperTest : public testing::Test {};
+
+TEST_F(UniformHelperTest, UniformBoundFunctionsGeneral) {
+  constexpr IntervalClosedClosedTag IntervalClosedClosed;
+  constexpr IntervalClosedOpenTag IntervalClosedOpen;
+  constexpr IntervalOpenClosedTag IntervalOpenClosed;
+  constexpr IntervalOpenOpenTag IntervalOpenOpen;
+
+  // absl::uniform_int_distribution natively assumes IntervalClosedClosed
+  // absl::uniform_real_distribution natively assumes IntervalClosedOpen
+
+  EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, 0, 100), 1);
+  EXPECT_EQ(uniform_lower_bound(IntervalOpenOpen, 0, 100), 1);
+  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenClosed, 0, 1.0), 0);
+  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenOpen, 0, 1.0), 0);
+  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenClosed, 0, 1.0), 0);
+  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenOpen, 0, 1.0), 0);
+
+  EXPECT_EQ(uniform_lower_bound(IntervalClosedClosed, 0, 100), 0);
+  EXPECT_EQ(uniform_lower_bound(IntervalClosedOpen, 0, 100), 0);
+  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedClosed, 0, 1.0), 0);
+  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedOpen, 0, 1.0), 0);
+  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedClosed, 0, 1.0), 0);
+  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedOpen, 0, 1.0), 0);
+
+  EXPECT_EQ(uniform_upper_bound(IntervalOpenOpen, 0, 100), 99);
+  EXPECT_EQ(uniform_upper_bound(IntervalClosedOpen, 0, 100), 99);
+  EXPECT_EQ(uniform_upper_bound<float>(IntervalOpenOpen, 0, 1.0), 1.0);
+  EXPECT_EQ(uniform_upper_bound<float>(IntervalClosedOpen, 0, 1.0), 1.0);
+  EXPECT_EQ(uniform_upper_bound<double>(IntervalOpenOpen, 0, 1.0), 1.0);
+  EXPECT_EQ(uniform_upper_bound<double>(IntervalClosedOpen, 0, 1.0), 1.0);
+
+  EXPECT_EQ(uniform_upper_bound(IntervalOpenClosed, 0, 100), 100);
+  EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, 0, 100), 100);
+  EXPECT_GT(uniform_upper_bound<float>(IntervalOpenClosed, 0, 1.0), 1.0);
+  EXPECT_GT(uniform_upper_bound<float>(IntervalClosedClosed, 0, 1.0), 1.0);
+  EXPECT_GT(uniform_upper_bound<double>(IntervalOpenClosed, 0, 1.0), 1.0);
+  EXPECT_GT(uniform_upper_bound<double>(IntervalClosedClosed, 0, 1.0), 1.0);
+
+  // Negative value tests
+  EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, -100, -1), -99);
+  EXPECT_EQ(uniform_lower_bound(IntervalOpenOpen, -100, -1), -99);
+  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenClosed, -2.0, -1.0), -2.0);
+  EXPECT_GT(uniform_lower_bound<float>(IntervalOpenOpen, -2.0, -1.0), -2.0);
+  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenClosed, -2.0, -1.0), -2.0);
+  EXPECT_GT(uniform_lower_bound<double>(IntervalOpenOpen, -2.0, -1.0), -2.0);
+
+  EXPECT_EQ(uniform_lower_bound(IntervalClosedClosed, -100, -1), -100);
+  EXPECT_EQ(uniform_lower_bound(IntervalClosedOpen, -100, -1), -100);
+  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedClosed, -2.0, -1.0), -2.0);
+  EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedOpen, -2.0, -1.0), -2.0);
+  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedClosed, -2.0, -1.0),
+            -2.0);
+  EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedOpen, -2.0, -1.0), -2.0);
+
+  EXPECT_EQ(uniform_upper_bound(IntervalOpenOpen, -100, -1), -2);
+  EXPECT_EQ(uniform_upper_bound(IntervalClosedOpen, -100, -1), -2);
+  EXPECT_EQ(uniform_upper_bound<float>(IntervalOpenOpen, -2.0, -1.0), -1.0);
+  EXPECT_EQ(uniform_upper_bound<float>(IntervalClosedOpen, -2.0, -1.0), -1.0);
+  EXPECT_EQ(uniform_upper_bound<double>(IntervalOpenOpen, -2.0, -1.0), -1.0);
+  EXPECT_EQ(uniform_upper_bound<double>(IntervalClosedOpen, -2.0, -1.0), -1.0);
+
+  EXPECT_EQ(uniform_upper_bound(IntervalOpenClosed, -100, -1), -1);
+  EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, -100, -1), -1);
+  EXPECT_GT(uniform_upper_bound<float>(IntervalOpenClosed, -2.0, -1.0), -1.0);
+  EXPECT_GT(uniform_upper_bound<float>(IntervalClosedClosed, -2.0, -1.0), -1.0);
+  EXPECT_GT(uniform_upper_bound<double>(IntervalOpenClosed, -2.0, -1.0), -1.0);
+  EXPECT_GT(uniform_upper_bound<double>(IntervalClosedClosed, -2.0, -1.0),
+            -1.0);
+
+  EXPECT_GT(uniform_lower_bound(IntervalOpenClosed, 1.0, 2.0), 1.0);
+  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, +0.0), 1.0);
+  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, -0.0), 1.0);
+  EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, -1.0), 1.0);
+}
+
+TEST_F(UniformHelperTest, UniformBoundFunctionsIntBounds) {
+  // Verifies the saturating nature of uniform_lower_bound and
+  // uniform_upper_bound
+  constexpr IntervalOpenOpenTag IntervalOpenOpen;
+
+  // uint max.
+  constexpr auto m = (std::numeric_limits<uint64_t>::max)();
+
+  EXPECT_EQ(1, uniform_lower_bound(IntervalOpenOpen, 0u, 0u));
+  EXPECT_EQ(m, uniform_lower_bound(IntervalOpenOpen, m, m));
+  EXPECT_EQ(m, uniform_lower_bound(IntervalOpenOpen, m - 1, m - 1));
+  EXPECT_EQ(0, uniform_upper_bound(IntervalOpenOpen, 0u, 0u));
+  EXPECT_EQ(m - 1, uniform_upper_bound(IntervalOpenOpen, m, m));
+
+  // int min/max
+  constexpr auto l = (std::numeric_limits<int64_t>::min)();
+  constexpr auto r = (std::numeric_limits<int64_t>::max)();
+  EXPECT_EQ(1, uniform_lower_bound(IntervalOpenOpen, 0, 0));
+  EXPECT_EQ(l + 1, uniform_lower_bound(IntervalOpenOpen, l, l));
+  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenOpen, r - 1, r - 1));
+  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenOpen, r, r));
+  EXPECT_EQ(-1, uniform_upper_bound(IntervalOpenOpen, 0, 0));
+  EXPECT_EQ(l, uniform_upper_bound(IntervalOpenOpen, l, l));
+  EXPECT_EQ(r - 1, uniform_upper_bound(IntervalOpenOpen, r, r));
+}
+
+TEST_F(UniformHelperTest, UniformBoundFunctionsRealBounds) {
+  // absl::uniform_real_distribution natively assumes IntervalClosedOpen;
+  // use the inverse here so each bound has to change.
+  constexpr IntervalOpenClosedTag IntervalOpenClosed;
+
+  // Edge cases: the next value toward itself is itself.
+  EXPECT_EQ(1.0, uniform_lower_bound(IntervalOpenClosed, 1.0, 1.0));
+  EXPECT_EQ(1.0f, uniform_lower_bound(IntervalOpenClosed, 1.0f, 1.0f));
+
+  // rightmost and leftmost finite values.
+  constexpr auto r = (std::numeric_limits<double>::max)();
+  const auto re = std::nexttoward(r, 0.0);
+  constexpr auto l = -r;
+  const auto le = std::nexttoward(l, 0.0);
+
+  EXPECT_EQ(l, uniform_lower_bound(IntervalOpenClosed, l, l));     // (l,l)
+  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenClosed, r, r));     // (r,r)
+  EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, r));    // (l,r)
+  EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, 0.0));  // (l, 0)
+  EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, le));   // (l, le)
+  EXPECT_EQ(r, uniform_lower_bound(IntervalOpenClosed, re, r));    // (re, r)
+
+  EXPECT_EQ(le, uniform_upper_bound(IntervalOpenClosed, l, l));   // (l,l)
+  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, r, r));    // (r,r)
+  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, l, r));    // (l,r)
+  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, l, re));   // (l,re)
+  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, 0.0, r));  // (0, r)
+  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, re, r));   // (re, r)
+  EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, le, re));  // (le, re)
+
+  const double e = std::nextafter(1.0, 2.0);  // 1 + epsilon
+  const double f = std::nextafter(1.0, 0.0);  // 1 - epsilon
+
+  // (1.0, 1.0 + epsilon)
+  EXPECT_EQ(e, uniform_lower_bound(IntervalOpenClosed, 1.0, e));
+  EXPECT_EQ(std::nextafter(e, 2.0),
+            uniform_upper_bound(IntervalOpenClosed, 1.0, e));
+
+  // (1.0-epsilon, 1.0)
+  EXPECT_EQ(1.0, uniform_lower_bound(IntervalOpenClosed, f, 1.0));
+  EXPECT_EQ(e, uniform_upper_bound(IntervalOpenClosed, f, 1.0));
+
+  // denorm cases.
+  const double g = std::numeric_limits<double>::denorm_min();
+  const double h = std::nextafter(g, 1.0);
+
+  // (0, denorm_min)
+  EXPECT_EQ(g, uniform_lower_bound(IntervalOpenClosed, 0.0, g));
+  EXPECT_EQ(h, uniform_upper_bound(IntervalOpenClosed, 0.0, g));
+
+  // (denorm_min, 1.0)
+  EXPECT_EQ(h, uniform_lower_bound(IntervalOpenClosed, g, 1.0));
+  EXPECT_EQ(e, uniform_upper_bound(IntervalOpenClosed, g, 1.0));
+
+  // Edge cases: invalid bounds.
+  EXPECT_EQ(f, uniform_lower_bound(IntervalOpenClosed, 1.0, -1.0));
+}
+
+struct Invalid {};
+
+template <typename A, typename B>
+auto InferredUniformReturnT(int) -> uniform_inferred_return_t<A, B>;
+
+template <typename, typename>
+Invalid InferredUniformReturnT(...);
+
+// Given types <A, B, Expect>, CheckArgsInferType() verifies that
+//
+//   uniform_inferred_return_t<A, B> and
+//   uniform_inferred_return_t<B, A>
+//
+// returns the type "Expect".
+//
+// This interface can also be used to assert that a given inferred return types
+// are invalid. Writing:
+//
+//   CheckArgsInferType<float, int, Invalid>()
+//
+// will assert that this overload does not exist.
+template <typename A, typename B, typename Expect>
+void CheckArgsInferType() {
+  static_assert(
+      absl::conjunction<
+          std::is_same<Expect, decltype(InferredUniformReturnT<A, B>(0))>,
+          std::is_same<Expect,
+                       decltype(InferredUniformReturnT<B, A>(0))>>::value,
+      "");
+}
+
+TEST_F(UniformHelperTest, UniformTypeInference) {
+  // Infers common types.
+  CheckArgsInferType<uint16_t, uint16_t, uint16_t>();
+  CheckArgsInferType<uint32_t, uint32_t, uint32_t>();
+  CheckArgsInferType<uint64_t, uint64_t, uint64_t>();
+  CheckArgsInferType<int16_t, int16_t, int16_t>();
+  CheckArgsInferType<int32_t, int32_t, int32_t>();
+  CheckArgsInferType<int64_t, int64_t, int64_t>();
+  CheckArgsInferType<float, float, float>();
+  CheckArgsInferType<double, double, double>();
+
+  // Properly promotes uint16_t.
+  CheckArgsInferType<uint16_t, uint32_t, uint32_t>();
+  CheckArgsInferType<uint16_t, uint64_t, uint64_t>();
+  CheckArgsInferType<uint16_t, int32_t, int32_t>();
+  CheckArgsInferType<uint16_t, int64_t, int64_t>();
+  CheckArgsInferType<uint16_t, float, float>();
+  CheckArgsInferType<uint16_t, double, double>();
+
+  // Properly promotes int16_t.
+  CheckArgsInferType<int16_t, int32_t, int32_t>();
+  CheckArgsInferType<int16_t, int64_t, int64_t>();
+  CheckArgsInferType<int16_t, float, float>();
+  CheckArgsInferType<int16_t, double, double>();
+
+  // Invalid (u)int16_t-pairings do not compile.
+  // See "CheckArgsInferType" comments above, for how this is achieved.
+  CheckArgsInferType<uint16_t, int16_t, Invalid>();
+  CheckArgsInferType<int16_t, uint32_t, Invalid>();
+  CheckArgsInferType<int16_t, uint64_t, Invalid>();
+
+  // Properly promotes uint32_t.
+  CheckArgsInferType<uint32_t, uint64_t, uint64_t>();
+  CheckArgsInferType<uint32_t, int64_t, int64_t>();
+  CheckArgsInferType<uint32_t, double, double>();
+
+  // Properly promotes int32_t.
+  CheckArgsInferType<int32_t, int64_t, int64_t>();
+  CheckArgsInferType<int32_t, double, double>();
+
+  // Invalid (u)int32_t-pairings do not compile.
+  CheckArgsInferType<uint32_t, int32_t, Invalid>();
+  CheckArgsInferType<int32_t, uint64_t, Invalid>();
+  CheckArgsInferType<int32_t, float, Invalid>();
+  CheckArgsInferType<uint32_t, float, Invalid>();
+
+  // Invalid (u)int64_t-pairings do not compile.
+  CheckArgsInferType<uint64_t, int64_t, Invalid>();
+  CheckArgsInferType<int64_t, float, Invalid>();
+  CheckArgsInferType<int64_t, double, Invalid>();
+
+  // Properly promotes float.
+  CheckArgsInferType<float, double, double>();
+}
+
+}  // namespace
diff --git a/absl/random/internal/wide_multiply.h b/absl/random/internal/wide_multiply.h
new file mode 100644
index 0000000..b6e6c4b
--- /dev/null
+++ b/absl/random/internal/wide_multiply.h
@@ -0,0 +1,111 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
+#define ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
+
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+#if (defined(_WIN32) || defined(_WIN64)) && defined(_M_IA64)
+#include <intrin.h>  // NOLINT(build/include_order)
+#pragma intrinsic(_umul128)
+#define ABSL_INTERNAL_USE_UMUL128 1
+#endif
+
+#include "absl/base/config.h"
+#include "absl/numeric/bits.h"
+#include "absl/numeric/int128.h"
+#include "absl/random/internal/traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// Helper object to multiply two 64-bit values to a 128-bit value.
+// MultiplyU64ToU128 multiplies two 64-bit values to a 128-bit value.
+// If an intrinsic is available, it is used, otherwise use native 32-bit
+// multiplies to construct the result.
+inline absl::uint128 MultiplyU64ToU128(uint64_t a, uint64_t b) {
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+  return absl::uint128(static_cast<__uint128_t>(a) * b);
+#elif defined(ABSL_INTERNAL_USE_UMUL128)
+  // uint64_t * uint64_t => uint128 multiply using imul intrinsic on MSVC.
+  uint64_t high = 0;
+  const uint64_t low = _umul128(a, b, &high);
+  return absl::MakeUint128(high, low);
+#else
+  // uint128(a) * uint128(b) in emulated mode computes a full 128-bit x 128-bit
+  // multiply.  However there are many cases where that is not necessary, and it
+  // is only necessary to support a 64-bit x 64-bit = 128-bit multiply.  This is
+  // for those cases.
+  const uint64_t a00 = static_cast<uint32_t>(a);
+  const uint64_t a32 = a >> 32;
+  const uint64_t b00 = static_cast<uint32_t>(b);
+  const uint64_t b32 = b >> 32;
+
+  const uint64_t c00 = a00 * b00;
+  const uint64_t c32a = a00 * b32;
+  const uint64_t c32b = a32 * b00;
+  const uint64_t c64 = a32 * b32;
+
+  const uint32_t carry =
+      static_cast<uint32_t>(((c00 >> 32) + static_cast<uint32_t>(c32a) +
+                             static_cast<uint32_t>(c32b)) >>
+                            32);
+
+  return absl::MakeUint128(c64 + (c32a >> 32) + (c32b >> 32) + carry,
+                           c00 + (c32a << 32) + (c32b << 32));
+#endif
+}
+
+// wide_multiply<T> multiplies two N-bit values to a 2N-bit result.
+template <typename UIntType>
+struct wide_multiply {
+  static constexpr size_t kN = std::numeric_limits<UIntType>::digits;
+  using input_type = UIntType;
+  using result_type = typename random_internal::unsigned_bits<kN * 2>::type;
+
+  static result_type multiply(input_type a, input_type b) {
+    return static_cast<result_type>(a) * b;
+  }
+
+  static input_type hi(result_type r) { return r >> kN; }
+  static input_type lo(result_type r) { return r; }
+
+  static_assert(std::is_unsigned<UIntType>::value,
+                "Class-template wide_multiply<> argument must be unsigned.");
+};
+
+#ifndef ABSL_HAVE_INTRINSIC_INT128
+template <>
+struct wide_multiply<uint64_t> {
+  using input_type = uint64_t;
+  using result_type = absl::uint128;
+
+  static result_type multiply(uint64_t a, uint64_t b) {
+    return MultiplyU64ToU128(a, b);
+  }
+
+  static uint64_t hi(result_type r) { return absl::Uint128High64(r); }
+  static uint64_t lo(result_type r) { return absl::Uint128Low64(r); }
+};
+#endif
+
+}  // namespace random_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
diff --git a/absl/random/internal/wide_multiply_test.cc b/absl/random/internal/wide_multiply_test.cc
new file mode 100644
index 0000000..e276cb5
--- /dev/null
+++ b/absl/random/internal/wide_multiply_test.cc
@@ -0,0 +1,65 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/random/internal/wide_multiply.h"
+
+#include "gtest/gtest.h"
+#include "absl/numeric/int128.h"
+
+using absl::random_internal::MultiplyU64ToU128;
+
+namespace {
+
+TEST(WideMultiplyTest, MultiplyU64ToU128Test) {
+  constexpr uint64_t k1 = 1;
+  constexpr uint64_t kMax = ~static_cast<uint64_t>(0);
+
+  EXPECT_EQ(absl::uint128(0), MultiplyU64ToU128(0, 0));
+
+  // Max uint64_t
+  EXPECT_EQ(MultiplyU64ToU128(kMax, kMax),
+            absl::MakeUint128(0xfffffffffffffffe, 0x0000000000000001));
+  EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(kMax, 1));
+  EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(1, kMax));
+  for (int i = 0; i < 64; ++i) {
+    EXPECT_EQ(absl::MakeUint128(0, kMax) << i,
+              MultiplyU64ToU128(kMax, k1 << i));
+    EXPECT_EQ(absl::MakeUint128(0, kMax) << i,
+              MultiplyU64ToU128(k1 << i, kMax));
+  }
+
+  // 1-bit x 1-bit.
+  for (int i = 0; i < 64; ++i) {
+    for (int j = 0; j < 64; ++j) {
+      EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j),
+                MultiplyU64ToU128(k1 << i, k1 << j));
+      EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j),
+                MultiplyU64ToU128(k1 << i, k1 << j));
+    }
+  }
+
+  // Verified multiplies
+  EXPECT_EQ(MultiplyU64ToU128(0xffffeeeeddddcccc, 0xbbbbaaaa99998888),
+            absl::MakeUint128(0xbbbb9e2692c5dddc, 0xc28f7531048d2c60));
+  EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfedcba9876543210),
+            absl::MakeUint128(0x0121fa00ad77d742, 0x2236d88fe5618cf0));
+  EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfdb97531eca86420),
+            absl::MakeUint128(0x0120ae99d26725fc, 0xce197f0ecac319e0));
+  EXPECT_EQ(MultiplyU64ToU128(0x97a87f4f261ba3f2, 0xfedcba9876543210),
+            absl::MakeUint128(0x96fbf1a8ae78d0ba, 0x5a6dd4b71f278320));
+  EXPECT_EQ(MultiplyU64ToU128(0xfedcba9876543210, 0xfdb97531eca86420),
+            absl::MakeUint128(0xfc98c6981a413e22, 0x342d0bbf48948200));
+}
+
+}  // namespace
diff --git a/absl/random/log_uniform_int_distribution.h b/absl/random/log_uniform_int_distribution.h
index ac43416..43e1011 100644
--- a/absl/random/log_uniform_int_distribution.h
+++ b/absl/random/log_uniform_int_distribution.h
@@ -23,13 +23,15 @@
 #include <ostream>
 #include <type_traits>
 
-#include "absl/random/internal/distribution_impl.h"
+#include "absl/numeric/bits.h"
 #include "absl/random/internal/fastmath.h"
+#include "absl/random/internal/generate_real.h"
 #include "absl/random/internal/iostream_state_saver.h"
 #include "absl/random/internal/traits.h"
 #include "absl/random/uniform_int_distribution.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // log_uniform_int_distribution:
 //
@@ -67,8 +69,10 @@
       if (base_ == 2) {
         // Determine where the first set bit is on range(), giving a log2(range)
         // value which can be used to construct bounds.
-        log_range_ = (std::min)(random_internal::LeadingSetBit(range()),
-                                std::numeric_limits<unsigned_type>::digits);
+        log_range_ =
+            (std::min)(bit_width(range()),
+                       static_cast<unsigned_type>(
+                           std::numeric_limits<unsigned_type>::digits));
       } else {
         // NOTE: Computing the logN(x) introduces error from 2 sources:
         // 1. Conversion of int to double loses precision for values >=
@@ -192,13 +196,15 @@
     const double r = std::pow(p.base(), d);
     const double s = (r * p.base()) - 1.0;
 
-    base_e = (r > (std::numeric_limits<unsigned_type>::max)())
-                 ? (std::numeric_limits<unsigned_type>::max)()
-                 : static_cast<unsigned_type>(r);
+    base_e =
+        (r > static_cast<double>((std::numeric_limits<unsigned_type>::max)()))
+            ? (std::numeric_limits<unsigned_type>::max)()
+            : static_cast<unsigned_type>(r);
 
-    top_e = (s > (std::numeric_limits<unsigned_type>::max)())
-                ? (std::numeric_limits<unsigned_type>::max)()
-                : static_cast<unsigned_type>(s);
+    top_e =
+        (s > static_cast<double>((std::numeric_limits<unsigned_type>::max)()))
+            ? (std::numeric_limits<unsigned_type>::max)()
+            : static_cast<unsigned_type>(s);
   }
 
   const unsigned_type lo = (base_e >= p.range()) ? p.range() : base_e;
@@ -245,6 +251,7 @@
   return is;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_
diff --git a/absl/random/log_uniform_int_distribution_test.cc b/absl/random/log_uniform_int_distribution_test.cc
index 5270531..5e780d9 100644
--- a/absl/random/log_uniform_int_distribution_test.cc
+++ b/absl/random/log_uniform_int_distribution_test.cc
@@ -27,6 +27,7 @@
 #include "absl/base/internal/raw_logging.h"
 #include "absl/random/internal/chi_square.h"
 #include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
 #include "absl/random/internal/sequence_urbg.h"
 #include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
@@ -121,7 +122,10 @@
   // data generated by the log-uniform-int distribution.
   double ChiSquaredTestImpl();
 
-  absl::InsecureBitGen rng_;
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
 };
 
 double LogUniformIntChiSquaredTest::ChiSquaredTestImpl() {
@@ -194,7 +198,6 @@
 
 TEST_P(LogUniformIntChiSquaredTest, MultiTest) {
   const int kTrials = 5;
-
   int failures = 0;
   for (int i = 0; i < kTrials; i++) {
     double p_value = ChiSquaredTestImpl();
diff --git a/absl/random/mock_distributions.h b/absl/random/mock_distributions.h
new file mode 100644
index 0000000..764ab37
--- /dev/null
+++ b/absl/random/mock_distributions.h
@@ -0,0 +1,266 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: mock_distributions.h
+// -----------------------------------------------------------------------------
+//
+// This file contains mock distribution functions for use alongside an
+// `absl::MockingBitGen` object within the Googletest testing framework. Such
+// mocks are useful to provide deterministic values as return values within
+// (otherwise random) Abseil distribution functions.
+//
+// The return type of each function is a mock expectation object which
+// is used to set the match result.
+//
+// More information about the Googletest testing framework is available at
+// https://github.com/google/googletest
+//
+// EXPECT_CALL and ON_CALL need to be made within the same DLL component as
+// the call to absl::Uniform and related methods, otherwise mocking will fail
+// since the  underlying implementation creates a type-specific pointer which
+// will be distinct across different DLL boundaries.
+//
+// Example:
+//
+//   absl::MockingBitGen mock;
+//   EXPECT_CALL(absl::MockUniform<int>(), Call(mock, 1, 1000))
+//     .WillRepeatedly(testing::ReturnRoundRobin({20, 40}));
+//
+//   EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 20);
+//   EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 40);
+//   EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 20);
+//   EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 40);
+
+#ifndef ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_
+#define ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_
+
+#include <limits>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+#include "absl/random/distributions.h"
+#include "absl/random/internal/mock_overload_set.h"
+#include "absl/random/mocking_bit_gen.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// -----------------------------------------------------------------------------
+// absl::MockUniform
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Uniform.
+//
+// `absl::MockUniform` is a class template used in conjunction with Googletest's
+// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
+// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
+// same way one would define mocks on a Googletest `MockFunction()`.
+//
+// Example:
+//
+//  absl::MockingBitGen mock;
+//  EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(mock))
+//     .WillOnce(Return(123456));
+//  auto x = absl::Uniform<uint32_t>(mock);
+//  assert(x == 123456)
+//
+template <typename R>
+using MockUniform = random_internal::MockOverloadSet<
+    random_internal::UniformDistributionWrapper<R>,
+    R(IntervalClosedOpenTag, MockingBitGen&, R, R),
+    R(IntervalClosedClosedTag, MockingBitGen&, R, R),
+    R(IntervalOpenOpenTag, MockingBitGen&, R, R),
+    R(IntervalOpenClosedTag, MockingBitGen&, R, R), R(MockingBitGen&, R, R),
+    R(MockingBitGen&)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockBernoulli
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Bernoulli.
+//
+// `absl::MockBernoulli` is a class used in conjunction with Googletest's
+// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
+// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
+// same way one would define mocks on a Googletest `MockFunction()`.
+//
+// Example:
+//
+//  absl::MockingBitGen mock;
+//  EXPECT_CALL(absl::MockBernoulli(), Call(mock, testing::_))
+//     .WillOnce(Return(false));
+//  assert(absl::Bernoulli(mock, 0.5) == false);
+//
+using MockBernoulli =
+    random_internal::MockOverloadSet<absl::bernoulli_distribution,
+                                     bool(MockingBitGen&, double)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockBeta
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Beta.
+//
+// `absl::MockBeta` is a class used in conjunction with Googletest's `ON_CALL()`
+// and `EXPECT_CALL()` macros. To use it, default-construct an instance of it
+// inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the same way one
+// would define mocks on a Googletest `MockFunction()`.
+//
+// Example:
+//
+//  absl::MockingBitGen mock;
+//  EXPECT_CALL(absl::MockBeta(), Call(mock, 3.0, 2.0))
+//     .WillOnce(Return(0.567));
+//  auto x = absl::Beta<double>(mock, 3.0, 2.0);
+//  assert(x == 0.567);
+//
+template <typename RealType>
+using MockBeta =
+    random_internal::MockOverloadSet<absl::beta_distribution<RealType>,
+                                     RealType(MockingBitGen&, RealType,
+                                              RealType)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockExponential
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Exponential.
+//
+// `absl::MockExponential` is a class template used in conjunction with
+// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,
+// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,
+// and use `Call(...)` the same way one would define mocks on a
+// Googletest `MockFunction()`.
+//
+// Example:
+//
+//  absl::MockingBitGen mock;
+//  EXPECT_CALL(absl::MockExponential<double>(), Call(mock, 0.5))
+//     .WillOnce(Return(12.3456789));
+//  auto x = absl::Exponential<double>(mock, 0.5);
+//  assert(x == 12.3456789)
+//
+template <typename RealType>
+using MockExponential =
+    random_internal::MockOverloadSet<absl::exponential_distribution<RealType>,
+                                     RealType(MockingBitGen&, RealType)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockGaussian
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Gaussian.
+//
+// `absl::MockGaussian` is a class template used in conjunction with
+// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,
+// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,
+// and use `Call(...)` the same way one would define mocks on a
+// Googletest `MockFunction()`.
+//
+// Example:
+//
+//  absl::MockingBitGen mock;
+//  EXPECT_CALL(absl::MockGaussian<double>(), Call(mock, 16.3, 3.3))
+//     .WillOnce(Return(12.3456789));
+//  auto x = absl::Gaussian<double>(mock, 16.3, 3.3);
+//  assert(x == 12.3456789)
+//
+template <typename RealType>
+using MockGaussian =
+    random_internal::MockOverloadSet<absl::gaussian_distribution<RealType>,
+                                     RealType(MockingBitGen&, RealType,
+                                              RealType)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockLogUniform
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::LogUniform.
+//
+// `absl::MockLogUniform` is a class template used in conjunction with
+// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,
+// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,
+// and use `Call(...)` the same way one would define mocks on a
+// Googletest `MockFunction()`.
+//
+// Example:
+//
+//  absl::MockingBitGen mock;
+//  EXPECT_CALL(absl::MockLogUniform<int>(), Call(mock, 10, 10000, 10))
+//     .WillOnce(Return(1221));
+//  auto x = absl::LogUniform<int>(mock, 10, 10000, 10);
+//  assert(x == 1221)
+//
+template <typename IntType>
+using MockLogUniform = random_internal::MockOverloadSet<
+    absl::log_uniform_int_distribution<IntType>,
+    IntType(MockingBitGen&, IntType, IntType, IntType)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockPoisson
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Poisson.
+//
+// `absl::MockPoisson` is a class template used in conjunction with Googletest's
+// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
+// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
+// same way one would define mocks on a Googletest `MockFunction()`.
+//
+// Example:
+//
+//  absl::MockingBitGen mock;
+//  EXPECT_CALL(absl::MockPoisson<int>(), Call(mock, 2.0))
+//     .WillOnce(Return(1221));
+//  auto x = absl::Poisson<int>(mock, 2.0);
+//  assert(x == 1221)
+//
+template <typename IntType>
+using MockPoisson =
+    random_internal::MockOverloadSet<absl::poisson_distribution<IntType>,
+                                     IntType(MockingBitGen&, double)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockZipf
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Zipf.
+//
+// `absl::MockZipf` is a class template used in conjunction with Googletest's
+// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
+// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
+// same way one would define mocks on a Googletest `MockFunction()`.
+//
+// Example:
+//
+//  absl::MockingBitGen mock;
+//  EXPECT_CALL(absl::MockZipf<int>(), Call(mock, 1000000, 2.0, 1.0))
+//     .WillOnce(Return(1221));
+//  auto x = absl::Zipf<int>(mock, 1000000, 2.0, 1.0);
+//  assert(x == 1221)
+//
+template <typename IntType>
+using MockZipf =
+    random_internal::MockOverloadSet<absl::zipf_distribution<IntType>,
+                                     IntType(MockingBitGen&, IntType, double,
+                                             double)>;
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_
diff --git a/absl/random/mock_distributions_test.cc b/absl/random/mock_distributions_test.cc
new file mode 100644
index 0000000..de23baf
--- /dev/null
+++ b/absl/random/mock_distributions_test.cc
@@ -0,0 +1,72 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/random/mock_distributions.h"
+
+#include "gtest/gtest.h"
+#include "absl/random/mocking_bit_gen.h"
+#include "absl/random/random.h"
+
+namespace {
+using ::testing::Return;
+
+TEST(MockDistributions, Examples) {
+  absl::MockingBitGen gen;
+
+  EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);
+  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
+      .WillOnce(Return(20));
+  EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);
+
+  EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+  EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))
+      .WillOnce(Return(5.0));
+  EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+
+  EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);
+  EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
+      .WillOnce(Return(42));
+  EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);
+
+  EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);
+  EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(500));
+  EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);
+
+  EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);
+  EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.000001))
+      .WillOnce(Return(true));
+  EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);
+
+  EXPECT_NE(absl::Beta<double>(gen, 3.0, 2.0), 0.567);
+  EXPECT_CALL(absl::MockBeta<double>(), Call(gen, 3.0, 2.0))
+      .WillOnce(Return(0.567));
+  EXPECT_EQ(absl::Beta<double>(gen, 3.0, 2.0), 0.567);
+
+  EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+  EXPECT_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
+      .WillOnce(Return(1221));
+  EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+
+  EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+  EXPECT_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))
+      .WillOnce(Return(0.001));
+  EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+
+  EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
+  EXPECT_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))
+      .WillOnce(Return(2040));
+  EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
+}
+
+}  // namespace
diff --git a/absl/random/mocking_bit_gen.h b/absl/random/mocking_bit_gen.h
new file mode 100644
index 0000000..6d2f2c8
--- /dev/null
+++ b/absl/random/mocking_bit_gen.h
@@ -0,0 +1,228 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// mocking_bit_gen.h
+// -----------------------------------------------------------------------------
+//
+// This file includes an `absl::MockingBitGen` class to use as a mock within the
+// Googletest testing framework. Such a mock is useful to provide deterministic
+// values as return values within (otherwise random) Abseil distribution
+// functions. Such determinism within a mock is useful within testing frameworks
+// to test otherwise indeterminate APIs.
+//
+// More information about the Googletest testing framework is available at
+// https://github.com/google/googletest
+
+#ifndef ABSL_RANDOM_MOCKING_BIT_GEN_H_
+#define ABSL_RANDOM_MOCKING_BIT_GEN_H_
+
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/meta/type_traits.h"
+#include "absl/random/distributions.h"
+#include "absl/random/internal/distribution_caller.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
+#include "absl/types/span.h"
+#include "absl/types/variant.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace random_internal {
+template <typename>
+struct DistributionCaller;
+class MockHelpers;
+
+}  // namespace random_internal
+class BitGenRef;
+
+// MockingBitGen
+//
+// `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class
+// which can act in place of an `absl::BitGen` URBG within tests using the
+// Googletest testing framework.
+//
+// Usage:
+//
+// Use an `absl::MockingBitGen` along with a mock distribution object (within
+// mock_distributions.h) inside Googletest constructs such as ON_CALL(),
+// EXPECT_TRUE(), etc. to produce deterministic results conforming to the
+// distribution's API contract.
+//
+// Example:
+//
+//  // Mock a call to an `absl::Bernoulli` distribution using Googletest
+//   absl::MockingBitGen bitgen;
+//
+//   ON_CALL(absl::MockBernoulli(), Call(bitgen, 0.5))
+//       .WillByDefault(testing::Return(true));
+//   EXPECT_TRUE(absl::Bernoulli(bitgen, 0.5));
+//
+//  // Mock a call to an `absl::Uniform` distribution within Googletest
+//  absl::MockingBitGen bitgen;
+//
+//   ON_CALL(absl::MockUniform<int>(), Call(bitgen, testing::_, testing::_))
+//       .WillByDefault([] (int low, int high) {
+//           return (low + high) / 2;
+//       });
+//
+//   EXPECT_EQ(absl::Uniform<int>(gen, 0, 10), 5);
+//   EXPECT_EQ(absl::Uniform<int>(gen, 30, 40), 35);
+//
+// At this time, only mock distributions supplied within the Abseil random
+// library are officially supported.
+//
+// EXPECT_CALL and ON_CALL need to be made within the same DLL component as
+// the call to absl::Uniform and related methods, otherwise mocking will fail
+// since the  underlying implementation creates a type-specific pointer which
+// will be distinct across different DLL boundaries.
+//
+class MockingBitGen {
+ public:
+  MockingBitGen() = default;
+
+  ~MockingBitGen() {
+    for (const auto& del : deleters_) del();
+  }
+
+  // URBG interface
+  using result_type = absl::BitGen::result_type;
+
+  static constexpr result_type(min)() { return (absl::BitGen::min)(); }
+  static constexpr result_type(max)() { return (absl::BitGen::max)(); }
+  result_type operator()() { return gen_(); }
+
+ private:
+  using match_impl_fn = void (*)(void* mock_fn, void* t_erased_arg_tuple,
+                                 void* t_erased_result);
+
+  struct MockData {
+    void* mock_fn = nullptr;
+    match_impl_fn match_impl = nullptr;
+  };
+
+  // GetMockFnType returns the testing::MockFunction for a result and tuple.
+  // This method only exists for type deduction and is otherwise unimplemented.
+  template <typename ResultT, typename... Args>
+  static auto GetMockFnType(ResultT, std::tuple<Args...>)
+      -> ::testing::MockFunction<ResultT(Args...)>;
+
+  // MockFnCaller is a helper method for use with absl::apply to
+  // apply an ArgTupleT to a compatible MockFunction.
+  // NOTE: MockFnCaller is essentially equivalent to the lambda:
+  // [fn](auto... args) { return fn->Call(std::move(args)...)}
+  // however that fails to build on some supported platforms.
+  template <typename ResultT, typename MockFnType, typename Tuple>
+  struct MockFnCaller;
+  // specialization for std::tuple.
+  template <typename ResultT, typename MockFnType, typename... Args>
+  struct MockFnCaller<ResultT, MockFnType, std::tuple<Args...>> {
+    MockFnType* fn;
+    inline ResultT operator()(Args... args) {
+      return fn->Call(std::move(args)...);
+    }
+  };
+
+  // MockingBitGen::RegisterMock
+  //
+  // RegisterMock<ResultT, ArgTupleT>(FastTypeIdType) is the main extension
+  // point for extending the MockingBitGen framework. It provides a mechanism to
+  // install a mock expectation for a function like ResultT(Args...) keyed by
+  // type_idex onto the MockingBitGen context. The key is that the type_index
+  // used to register must match the type index used to call the mock.
+  //
+  // The returned MockFunction<...> type can be used to setup additional
+  // distribution parameters of the expectation.
+  template <typename ResultT, typename ArgTupleT>
+  auto RegisterMock(base_internal::FastTypeIdType type)
+      -> decltype(GetMockFnType(std::declval<ResultT>(),
+                                std::declval<ArgTupleT>()))& {
+    using MockFnType = decltype(
+        GetMockFnType(std::declval<ResultT>(), std::declval<ArgTupleT>()));
+    auto& mock = mocks_[type];
+    if (!mock.mock_fn) {
+      auto* mock_fn = new MockFnType;
+      mock.mock_fn = mock_fn;
+      mock.match_impl = &MatchImpl<ResultT, ArgTupleT>;
+      deleters_.emplace_back([mock_fn] { delete mock_fn; });
+    }
+    return *static_cast<MockFnType*>(mock.mock_fn);
+  }
+
+  // MockingBitGen::MatchImpl<> is a dispatch function which converts the
+  // generic type-erased parameters into a specific mock invocation call.
+  // Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...>
+  // used to invoke the mock function.
+  // Requires result to point to a ResultT, which is the result of the call.
+  template <typename ResultT, typename ArgTupleT>
+  static void MatchImpl(/*MockFnType<ResultT, Args...>*/ void* mock_fn,
+                        /*ArgTupleT*/ void* args_tuple,
+                        /*ResultT*/ void* result) {
+    using MockFnType = decltype(
+        GetMockFnType(std::declval<ResultT>(), std::declval<ArgTupleT>()));
+    *static_cast<ResultT*>(result) = absl::apply(
+        MockFnCaller<ResultT, MockFnType, ArgTupleT>{
+            static_cast<MockFnType*>(mock_fn)},
+        *static_cast<ArgTupleT*>(args_tuple));
+  }
+
+  // MockingBitGen::InvokeMock
+  //
+  // InvokeMock(FastTypeIdType, args, result) is the entrypoint for invoking
+  // mocks registered on MockingBitGen.
+  //
+  // When no mocks are registered on the provided FastTypeIdType, returns false.
+  // Otherwise attempts to invoke the mock function ResultT(Args...) that
+  // was previously registered via the type_index.
+  // Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...>
+  // used to invoke the mock function.
+  // Requires result to point to a ResultT, which is the result of the call.
+  inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
+                         void* result) {
+    // Trigger a mock, if there exists one that matches `param`.
+    auto it = mocks_.find(type);
+    if (it == mocks_.end()) return false;
+    auto* mock_data = static_cast<MockData*>(&it->second);
+    mock_data->match_impl(mock_data->mock_fn, args_tuple, result);
+    return true;
+  }
+
+  absl::flat_hash_map<base_internal::FastTypeIdType, MockData> mocks_;
+  std::vector<std::function<void()>> deleters_;
+  absl::BitGen gen_;
+
+  template <typename>
+  friend struct ::absl::random_internal::DistributionCaller;  // for InvokeMock
+  friend class ::absl::BitGenRef;                             // for InvokeMock
+  friend class ::absl::random_internal::MockHelpers;  // for RegisterMock,
+                                                      // InvokeMock
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_RANDOM_MOCKING_BIT_GEN_H_
diff --git a/absl/random/mocking_bit_gen_test.cc b/absl/random/mocking_bit_gen_test.cc
new file mode 100644
index 0000000..f0ffc9a
--- /dev/null
+++ b/absl/random/mocking_bit_gen_test.cc
@@ -0,0 +1,347 @@
+//
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "absl/random/mocking_bit_gen.h"
+
+#include <numeric>
+#include <random>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+#include "absl/random/bit_gen_ref.h"
+#include "absl/random/mock_distributions.h"
+#include "absl/random/random.h"
+
+namespace {
+using ::testing::Ne;
+using ::testing::Return;
+
+TEST(BasicMocking, AllDistributionsAreOverridable) {
+  absl::MockingBitGen gen;
+
+  EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);
+  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
+      .WillOnce(Return(20));
+  EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);
+
+  EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+  EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))
+      .WillOnce(Return(5.0));
+  EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+
+  EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);
+  EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
+      .WillOnce(Return(42));
+  EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);
+
+  EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);
+  EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(500));
+  EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);
+
+  EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);
+  EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.000001))
+      .WillOnce(Return(true));
+  EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);
+
+  EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+  EXPECT_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
+      .WillOnce(Return(1221));
+  EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+
+  EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+  EXPECT_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))
+      .WillOnce(Return(0.001));
+  EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+
+  EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 500000);
+  EXPECT_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))
+      .WillOnce(Return(500000));
+  EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 500000);
+}
+
+TEST(BasicMocking, OnDistribution) {
+  absl::MockingBitGen gen;
+
+  EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);
+  ON_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
+      .WillByDefault(Return(20));
+  EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);
+
+  EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+  ON_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))
+      .WillByDefault(Return(5.0));
+  EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+
+  EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);
+  ON_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
+      .WillByDefault(Return(42));
+  EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);
+
+  EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);
+  ON_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillByDefault(Return(500));
+  EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);
+
+  EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);
+  ON_CALL(absl::MockBernoulli(), Call(gen, 0.000001))
+      .WillByDefault(Return(true));
+  EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);
+
+  EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+  ON_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
+      .WillByDefault(Return(1221));
+  EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+
+  EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+  ON_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))
+      .WillByDefault(Return(0.001));
+  EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+
+  EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
+  ON_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))
+      .WillByDefault(Return(2040));
+  EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
+}
+
+TEST(BasicMocking, GMockMatchers) {
+  absl::MockingBitGen gen;
+
+  EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+  ON_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
+      .WillByDefault(Return(1221));
+  EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+}
+
+TEST(BasicMocking, OverridesWithMultipleGMockExpectations) {
+  absl::MockingBitGen gen;
+
+  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 10000))
+      .WillOnce(Return(20))
+      .WillOnce(Return(40))
+      .WillOnce(Return(60));
+  EXPECT_EQ(absl::Uniform(gen, 1, 10000), 20);
+  EXPECT_EQ(absl::Uniform(gen, 1, 10000), 40);
+  EXPECT_EQ(absl::Uniform(gen, 1, 10000), 60);
+}
+
+TEST(BasicMocking, DefaultArgument) {
+  absl::MockingBitGen gen;
+
+  ON_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
+      .WillByDefault(Return(200));
+
+  EXPECT_EQ(absl::Exponential<double>(gen), 200);
+  EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 200);
+}
+
+TEST(BasicMocking, MultipleGenerators) {
+  auto get_value = [](absl::BitGenRef gen_ref) {
+    return absl::Uniform(gen_ref, 1, 1000000);
+  };
+  absl::MockingBitGen unmocked_generator;
+  absl::MockingBitGen mocked_with_3;
+  absl::MockingBitGen mocked_with_11;
+
+  EXPECT_CALL(absl::MockUniform<int>(), Call(mocked_with_3, 1, 1000000))
+      .WillOnce(Return(3))
+      .WillRepeatedly(Return(17));
+  EXPECT_CALL(absl::MockUniform<int>(), Call(mocked_with_11, 1, 1000000))
+      .WillOnce(Return(11))
+      .WillRepeatedly(Return(17));
+
+  // Ensure that unmocked generator generates neither value.
+  int unmocked_value = get_value(unmocked_generator);
+  EXPECT_NE(unmocked_value, 3);
+  EXPECT_NE(unmocked_value, 11);
+  // Mocked generators should generate their mocked values.
+  EXPECT_EQ(get_value(mocked_with_3), 3);
+  EXPECT_EQ(get_value(mocked_with_11), 11);
+  // Ensure that the mocks have expired.
+  EXPECT_NE(get_value(mocked_with_3), 3);
+  EXPECT_NE(get_value(mocked_with_11), 11);
+}
+
+TEST(BasicMocking, MocksNotTrigeredForIncorrectTypes) {
+  absl::MockingBitGen gen;
+  EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(gen)).WillOnce(Return(42));
+
+  EXPECT_NE(absl::Uniform<uint16_t>(gen), 42);  // Not mocked
+  EXPECT_EQ(absl::Uniform<uint32_t>(gen), 42);  // Mock triggered
+}
+
+TEST(BasicMocking, FailsOnUnsatisfiedMocks) {
+  EXPECT_NONFATAL_FAILURE(
+      []() {
+        absl::MockingBitGen gen;
+        EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
+            .WillOnce(Return(3.0));
+        // Does not call absl::Exponential().
+      }(),
+      "unsatisfied and active");
+}
+
+TEST(OnUniform, RespectsUniformIntervalSemantics) {
+  absl::MockingBitGen gen;
+
+  EXPECT_CALL(absl::MockUniform<int>(),
+              Call(absl::IntervalClosed, gen, 1, 1000000))
+      .WillOnce(Return(301));
+  EXPECT_NE(absl::Uniform(gen, 1, 1000000), 301);  // Not mocked
+  EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 1, 1000000), 301);
+}
+
+TEST(OnUniform, RespectsNoArgUnsignedShorthand) {
+  absl::MockingBitGen gen;
+  EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(gen)).WillOnce(Return(42));
+  EXPECT_EQ(absl::Uniform<uint32_t>(gen), 42);
+}
+
+TEST(RepeatedlyModifier, ForceSnakeEyesForManyDice) {
+  auto roll_some_dice = [](absl::BitGenRef gen_ref) {
+    std::vector<int> results(16);
+    for (auto& r : results) {
+      r = absl::Uniform(absl::IntervalClosed, gen_ref, 1, 6);
+    }
+    return results;
+  };
+  std::vector<int> results;
+  absl::MockingBitGen gen;
+
+  // Without any mocked calls, not all dice roll a "6".
+  results = roll_some_dice(gen);
+  EXPECT_LT(std::accumulate(std::begin(results), std::end(results), 0),
+            results.size() * 6);
+
+  // Verify that we can force all "6"-rolls, with mocking.
+  ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalClosed, gen, 1, 6))
+      .WillByDefault(Return(6));
+  results = roll_some_dice(gen);
+  EXPECT_EQ(std::accumulate(std::begin(results), std::end(results), 0),
+            results.size() * 6);
+}
+
+TEST(WillOnce, DistinctCounters) {
+  absl::MockingBitGen gen;
+  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
+      .Times(3)
+      .WillRepeatedly(Return(0));
+  EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1000001, 2000000))
+      .Times(3)
+      .WillRepeatedly(Return(1));
+  EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1);
+  EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0);
+  EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1);
+  EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0);
+  EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1);
+  EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0);
+}
+
+TEST(TimesModifier, ModifierSaturatesAndExpires) {
+  EXPECT_NONFATAL_FAILURE(
+      []() {
+        absl::MockingBitGen gen;
+        EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
+            .Times(3)
+            .WillRepeatedly(Return(15))
+            .RetiresOnSaturation();
+
+        EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15);
+        EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15);
+        EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15);
+        // Times(3) has expired - Should get a different value now.
+
+        EXPECT_NE(absl::Uniform(gen, 1, 1000000), 15);
+      }(),
+      "");
+}
+
+TEST(TimesModifier, Times0) {
+  absl::MockingBitGen gen;
+  EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.0)).Times(0);
+  EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).Times(0);
+}
+
+TEST(AnythingMatcher, MatchesAnyArgument) {
+  using testing::_;
+
+  {
+    absl::MockingBitGen gen;
+    ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalClosed, gen, _, 1000))
+        .WillByDefault(Return(11));
+    ON_CALL(absl::MockUniform<int>(),
+            Call(absl::IntervalClosed, gen, _, Ne(1000)))
+        .WillByDefault(Return(99));
+
+    EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 10, 1000000), 99);
+    EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 10, 1000), 11);
+  }
+
+  {
+    absl::MockingBitGen gen;
+    ON_CALL(absl::MockUniform<int>(), Call(gen, 1, _))
+        .WillByDefault(Return(25));
+    ON_CALL(absl::MockUniform<int>(), Call(gen, Ne(1), _))
+        .WillByDefault(Return(99));
+    EXPECT_EQ(absl::Uniform(gen, 3, 1000000), 99);
+    EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 25);
+  }
+
+  {
+    absl::MockingBitGen gen;
+    ON_CALL(absl::MockUniform<int>(), Call(gen, _, _))
+        .WillByDefault(Return(145));
+    EXPECT_EQ(absl::Uniform(gen, 1, 1000), 145);
+    EXPECT_EQ(absl::Uniform(gen, 10, 1000), 145);
+    EXPECT_EQ(absl::Uniform(gen, 100, 1000), 145);
+  }
+}
+
+TEST(AnythingMatcher, WithWillByDefault) {
+  using testing::_;
+  absl::MockingBitGen gen;
+  std::vector<int> values = {11, 22, 33, 44, 55, 66, 77, 88, 99, 1010};
+
+  ON_CALL(absl::MockUniform<size_t>(), Call(gen, 0, _))
+      .WillByDefault(Return(0));
+  for (int i = 0; i < 100; i++) {
+    auto& elem = values[absl::Uniform(gen, 0u, values.size())];
+    EXPECT_EQ(elem, 11);
+  }
+}
+
+TEST(BasicMocking, WillByDefaultWithArgs) {
+  using testing::_;
+
+  absl::MockingBitGen gen;
+  ON_CALL(absl::MockPoisson<int>(), Call(gen, _))
+      .WillByDefault(
+          [](double lambda) { return static_cast<int>(lambda * 10); });
+  EXPECT_EQ(absl::Poisson<int>(gen, 1.7), 17);
+  EXPECT_EQ(absl::Poisson<int>(gen, 0.03), 0);
+}
+
+TEST(MockingBitGen, InSequenceSucceedsInOrder) {
+  absl::MockingBitGen gen;
+
+  testing::InSequence seq;
+
+  EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(3));
+  EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 2.0)).WillOnce(Return(4));
+
+  EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 3);
+  EXPECT_EQ(absl::Poisson<int>(gen, 2.0), 4);
+}
+
+}  // namespace
diff --git a/absl/random/poisson_distribution.h b/absl/random/poisson_distribution.h
index 7750b1c..cb5f5d5 100644
--- a/absl/random/poisson_distribution.h
+++ b/absl/random/poisson_distribution.h
@@ -22,12 +22,13 @@
 #include <ostream>
 #include <type_traits>
 
-#include "absl/random/internal/distribution_impl.h"
 #include "absl/random/internal/fast_uniform_bits.h"
 #include "absl/random/internal/fastmath.h"
+#include "absl/random/internal/generate_real.h"
 #include "absl/random/internal/iostream_state_saver.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // absl::poisson_distribution:
 // Generates discrete variates conforming to a Poisson distribution.
@@ -164,9 +165,9 @@
 poisson_distribution<IntType>::operator()(
     URBG& g,  // NOLINT(runtime/references)
     const param_type& p) {
-  using random_internal::PositiveValueT;
-  using random_internal::RandU64ToDouble;
-  using random_internal::SignedValueT;
+  using random_internal::GeneratePositiveTag;
+  using random_internal::GenerateRealFromBits;
+  using random_internal::GenerateSignedTag;
 
   if (p.split_ != 0) {
     // Use Knuth's algorithm with range splitting to avoid floating-point
@@ -186,7 +187,8 @@
     for (int split = p.split_; split > 0; --split) {
       double r = 1.0;
       do {
-        r *= RandU64ToDouble<PositiveValueT, true>(fast_u64_(g));
+        r *= GenerateRealFromBits<double, GeneratePositiveTag, true>(
+            fast_u64_(g));  // U(-1, 0)
         ++n;
       } while (r > p.emu_);
       --n;
@@ -205,10 +207,11 @@
   // and k = max(f).
   const double a = p.mean_ + 0.5;
   for (;;) {
-    const double u =
-        RandU64ToDouble<PositiveValueT, false>(fast_u64_(g));  // (0, 1)
-    const double v =
-        RandU64ToDouble<SignedValueT, false>(fast_u64_(g));  // (-1, 1)
+    const double u = GenerateRealFromBits<double, GeneratePositiveTag, false>(
+        fast_u64_(g));  // U(0, 1)
+    const double v = GenerateRealFromBits<double, GenerateSignedTag, false>(
+        fast_u64_(g));  // U(-1, 1)
+
     const double x = std::floor(p.s_ * v / u + a);
     if (x < 0) continue;  // f(negative) = 0
     const double rhs = x * p.lmu_;
@@ -249,6 +252,7 @@
   return is;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_POISSON_DISTRIBUTION_H_
diff --git a/absl/random/poisson_distribution_test.cc b/absl/random/poisson_distribution_test.cc
index 9d215fb..8baabd1 100644
--- a/absl/random/poisson_distribution_test.cc
+++ b/absl/random/poisson_distribution_test.cc
@@ -30,6 +30,7 @@
 #include "absl/container/flat_hash_map.h"
 #include "absl/random/internal/chi_square.h"
 #include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
 #include "absl/random/internal/sequence_urbg.h"
 #include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
@@ -257,7 +258,10 @@
   template <typename D>
   bool SingleZTest(const double p, const size_t samples);
 
-  absl::InsecureBitGen rng_;
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
 };
 
 template <typename D>
@@ -357,9 +361,13 @@
  private:
   void InitChiSquaredTest(const double buckets);
 
-  absl::InsecureBitGen rng_;
   std::vector<size_t> cutoffs_;
   std::vector<double> expected_;
+
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
 };
 
 void PoissonDistributionChiSquaredTest::InitChiSquaredTest(
diff --git a/absl/random/random.h b/absl/random/random.h
index dc6852f..71b6309 100644
--- a/absl/random/random.h
+++ b/absl/random/random.h
@@ -41,6 +41,7 @@
 #include "absl/random/seed_sequences.h"  // IWYU pragma: export
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // -----------------------------------------------------------------------------
 // absl::BitGen
@@ -108,7 +109,7 @@
 
 // absl::BitGen::max()
 //
-// Returns the largest possible value from this bit generator., and
+// Returns the largest possible value from this bit generator.
 
 // absl::BitGen::discard(num)
 //
@@ -182,6 +183,7 @@
 // discards the intermediate results.
 // ---------------------------------------------------------------------------
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_RANDOM_H_
diff --git a/absl/random/seed_gen_exception.cc b/absl/random/seed_gen_exception.cc
index e4271ba..fdcb54a 100644
--- a/absl/random/seed_gen_exception.cc
+++ b/absl/random/seed_gen_exception.cc
@@ -19,6 +19,7 @@
 #include "absl/base/config.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 static constexpr const char kExceptionMessage[] =
     "Failed generating seed-material for URBG.";
@@ -41,4 +42,5 @@
 }
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/seed_gen_exception.h b/absl/random/seed_gen_exception.h
index b464d52..5353900 100644
--- a/absl/random/seed_gen_exception.h
+++ b/absl/random/seed_gen_exception.h
@@ -28,7 +28,10 @@
 
 #include <exception>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 //------------------------------------------------------------------------------
 // SeedGenException
@@ -46,6 +49,7 @@
 [[noreturn]] void ThrowSeedGenException();
 
 }  // namespace random_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_SEED_GEN_EXCEPTION_H_
diff --git a/absl/random/seed_sequences.cc b/absl/random/seed_sequences.cc
index 9f31961..426eafd 100644
--- a/absl/random/seed_sequences.cc
+++ b/absl/random/seed_sequences.cc
@@ -17,6 +17,7 @@
 #include "absl/random/internal/pool_urbg.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 SeedSeq MakeSeedSeq() {
   SeedSeq::result_type seed_material[8];
@@ -24,4 +25,5 @@
   return SeedSeq(std::begin(seed_material), std::end(seed_material));
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/seed_sequences.h b/absl/random/seed_sequences.h
index 631d1ec..ff1340c 100644
--- a/absl/random/seed_sequences.h
+++ b/absl/random/seed_sequences.h
@@ -34,6 +34,7 @@
 #include "absl/types/span.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // -----------------------------------------------------------------------------
 // absl::SeedSeq
@@ -103,6 +104,7 @@
 //
 SeedSeq MakeSeedSeq();
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_SEED_SEQUENCES_H_
diff --git a/absl/random/seed_sequences_test.cc b/absl/random/seed_sequences_test.cc
index 2cc8b0e..fe1100b 100644
--- a/absl/random/seed_sequences_test.cc
+++ b/absl/random/seed_sequences_test.cc
@@ -96,7 +96,6 @@
 void TestReproducibleVariateSequencesForNonsecureURBG() {
   const size_t kNumVariates = 1000;
 
-  // Master RNG instance.
   URBG rng;
   // Reused for both RNG instances.
   auto reusable_seed = absl::CreateSeedSeqFrom(&rng);
diff --git a/absl/random/uniform_int_distribution.h b/absl/random/uniform_int_distribution.h
index 4970486..c1f54cc 100644
--- a/absl/random/uniform_int_distribution.h
+++ b/absl/random/uniform_int_distribution.h
@@ -34,12 +34,13 @@
 #include <type_traits>
 
 #include "absl/base/optimization.h"
-#include "absl/random/internal/distribution_impl.h"
 #include "absl/random/internal/fast_uniform_bits.h"
 #include "absl/random/internal/iostream_state_saver.h"
 #include "absl/random/internal/traits.h"
+#include "absl/random/internal/wide_multiply.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // absl::uniform_int_distribution<T>
 //
@@ -195,7 +196,7 @@
 uniform_int_distribution<IntType>::Generate(
     URBG& g,  // NOLINT(runtime/references)
     typename random_internal::make_unsigned_bits<IntType>::type R) {
-    random_internal::FastUniformBits<unsigned_type> fast_bits;
+  random_internal::FastUniformBits<unsigned_type> fast_bits;
   unsigned_type bits = fast_bits(g);
   const unsigned_type Lim = R + 1;
   if ((R & Lim) == 0) {
@@ -268,6 +269,7 @@
   return helper::hi(product);
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_
diff --git a/absl/random/uniform_int_distribution_test.cc b/absl/random/uniform_int_distribution_test.cc
index aacff88..276d72a 100644
--- a/absl/random/uniform_int_distribution_test.cc
+++ b/absl/random/uniform_int_distribution_test.cc
@@ -26,6 +26,7 @@
 #include "absl/base/internal/raw_logging.h"
 #include "absl/random/internal/chi_square.h"
 #include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
 #include "absl/random/internal/sequence_urbg.h"
 #include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
@@ -123,7 +124,7 @@
   absl::uniform_int_distribution<TypeParam> dist(10, 1);
   auto x = dist(gen);
 
-  // Any value will generate a non-empty std::string.
+  // Any value will generate a non-empty string.
   EXPECT_FALSE(absl::StrCat(+x).empty()) << x;
 #endif  // NDEBUG
 }
@@ -134,7 +135,11 @@
   using param_type =
       typename absl::uniform_int_distribution<TypeParam>::param_type;
 
-  absl::InsecureBitGen rng;
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};
+
   std::vector<double> values(kSize);
   for (const auto& param :
        {param_type(0, Limits::max()), param_type(13, 127)}) {
@@ -178,7 +183,11 @@
   const TypeParam min = std::is_unsigned<TypeParam>::value ? 37 : -37;
   const TypeParam max = min + kBuckets;
 
-  absl::InsecureBitGen rng;
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};
+
   absl::uniform_int_distribution<TypeParam> dist(min, max);
 
   std::vector<int32_t> counts(kBuckets + 1, 0);
diff --git a/absl/random/uniform_real_distribution.h b/absl/random/uniform_real_distribution.h
index 600f915..5ba17b2 100644
--- a/absl/random/uniform_real_distribution.h
+++ b/absl/random/uniform_real_distribution.h
@@ -39,11 +39,13 @@
 #include <limits>
 #include <type_traits>
 
-#include "absl/random/internal/distribution_impl.h"
+#include "absl/meta/type_traits.h"
 #include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/random/internal/generate_real.h"
 #include "absl/random/internal/iostream_state_saver.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // absl::uniform_real_distribution<T>
 //
@@ -56,7 +58,7 @@
 //
 //   // Use the distribution to produce a value between 0.0 (inclusive)
 //   // and 1.0 (exclusive).
-//   int value = absl::uniform_real_distribution<double>(0, 1)(gen);
+//   double value = absl::uniform_real_distribution<double>(0, 1)(gen);
 //
 template <typename RealType = double>
 class uniform_real_distribution {
@@ -76,6 +78,7 @@
       // is not possible, so value generation cannot use the full range of the
       // real type.
       assert(range_ <= (std::numeric_limits<result_type>::max)());
+      assert(std::isfinite(range_));
     }
 
     result_type a() const { return lo_; }
@@ -151,10 +154,15 @@
 typename uniform_real_distribution<RealType>::result_type
 uniform_real_distribution<RealType>::operator()(
     URBG& gen, const param_type& p) {  // NOLINT(runtime/references)
-  using random_internal::PositiveValueT;
+  using random_internal::GeneratePositiveTag;
+  using random_internal::GenerateRealFromBits;
+  using real_type =
+      absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+
   while (true) {
-    const result_type sample = random_internal::RandU64ToReal<
-        result_type>::template Value<PositiveValueT, true>(fast_u64_(gen));
+    const result_type sample =
+        GenerateRealFromBits<real_type, GeneratePositiveTag, true>(
+            fast_u64_(gen));
     const result_type res = p.a() + (sample * p.range_);
     if (res < p.b() || p.range_ <= 0 || !std::isfinite(p.range_)) {
       return res;
@@ -188,6 +196,7 @@
   }
   return is;
 }
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_
diff --git a/absl/random/uniform_real_distribution_test.cc b/absl/random/uniform_real_distribution_test.cc
index 597f0ee..8cf874d 100644
--- a/absl/random/uniform_real_distribution_test.cc
+++ b/absl/random/uniform_real_distribution_test.cc
@@ -27,6 +27,7 @@
 #include "absl/base/internal/raw_logging.h"
 #include "absl/random/internal/chi_square.h"
 #include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
 #include "absl/random/internal/sequence_urbg.h"
 #include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
@@ -55,6 +56,7 @@
 class UniformRealDistributionTest : public ::testing::Test {};
 
 using RealTypes = ::testing::Types<float, double, long double>;
+
 TYPED_TEST_SUITE(UniformRealDistributionTest, RealTypes);
 
 TYPED_TEST(UniformRealDistributionTest, ParamSerializeTest) {
@@ -156,6 +158,10 @@
   }
 }
 
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4756)  // Constant arithmetic overflow.
+#endif
 TYPED_TEST(UniformRealDistributionTest, ViolatesPreconditionsDeathTest) {
 #if GTEST_HAS_DEATH_TEST
   // Hi < Lo
@@ -190,12 +196,19 @@
   }
 #endif  // NDEBUG
 }
+#ifdef _MSC_VER
+#pragma warning(pop)  // warning(disable:4756)
+#endif
 
 TYPED_TEST(UniformRealDistributionTest, TestMoments) {
   constexpr int kSize = 1000000;
   std::vector<double> values(kSize);
 
-  absl::InsecureBitGen rng;
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};
+
   absl::uniform_real_distribution<TypeParam> dist;
   for (int i = 0; i < kSize; i++) {
     values[i] = dist(rng);
@@ -225,7 +238,11 @@
   const int kThreshold =
       absl::random_internal::ChiSquareValue(kBuckets - 1, 0.999999);
 
-  absl::InsecureBitGen rng;
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};
+
   for (const auto& param : {param_type(0, 1), param_type(5, 12),
                             param_type(-5, 13), param_type(-5, -2)}) {
     const double min_val = param.a();
diff --git a/absl/random/zipf_distribution.h b/absl/random/zipf_distribution.h
index d7b4ac3..22ebc75 100644
--- a/absl/random/zipf_distribution.h
+++ b/absl/random/zipf_distribution.h
@@ -26,6 +26,7 @@
 #include "absl/random/uniform_real_distribution.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // absl::zipf_distribution produces random integer-values in the range [0, k],
 // distributed according to the discrete probability function:
@@ -264,6 +265,7 @@
   return is;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_RANDOM_ZIPF_DISTRIBUTION_H_
diff --git a/absl/random/zipf_distribution_test.cc b/absl/random/zipf_distribution_test.cc
index 4d4a0fc..f8cf70e 100644
--- a/absl/random/zipf_distribution_test.cc
+++ b/absl/random/zipf_distribution_test.cc
@@ -27,6 +27,7 @@
 #include "gtest/gtest.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/random/internal/chi_square.h"
+#include "absl/random/internal/pcg_engine.h"
 #include "absl/random/internal/sequence_urbg.h"
 #include "absl/random/random.h"
 #include "absl/strings/str_cat.h"
@@ -213,7 +214,10 @@
  public:
   ZipfTest() : ZipfModel(GetParam().k(), GetParam().q(), GetParam().v()) {}
 
-  absl::InsecureBitGen rng_;
+  // We use a fixed bit generator for distribution accuracy tests.  This allows
+  // these tests to be deterministic, while still testing the qualify of the
+  // implementation.
+  absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
 };
 
 TEST_P(ZipfTest, ChiSquaredTest) {
diff --git a/absl/status/BUILD.bazel b/absl/status/BUILD.bazel
new file mode 100644
index 0000000..189bd73
--- /dev/null
+++ b/absl/status/BUILD.bazel
@@ -0,0 +1,103 @@
+#
+# Copyright 2017 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This package contains `absl::Status`.
+# It will expand later to have utilities around `Status` like `StatusOr`,
+# `StatusBuilder` and macros.
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load(
+    "//absl:copts/configure_copts.bzl",
+    "ABSL_DEFAULT_COPTS",
+    "ABSL_TEST_COPTS",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+cc_library(
+    name = "status",
+    srcs = [
+        "internal/status_internal.h",
+        "status.cc",
+        "status_payload_printer.cc",
+    ],
+    hdrs = [
+        "status.h",
+        "status_payload_printer.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        "//absl/base:atomic_hook",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:raw_logging_internal",
+        "//absl/container:inlined_vector",
+        "//absl/debugging:stacktrace",
+        "//absl/debugging:symbolize",
+        "//absl/strings",
+        "//absl/strings:cord",
+        "//absl/strings:str_format",
+        "//absl/types:optional",
+    ],
+)
+
+cc_test(
+    name = "status_test",
+    srcs = ["status_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    deps = [
+        ":status",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "statusor",
+    srcs = [
+        "internal/statusor_internal.h",
+        "statusor.cc",
+    ],
+    hdrs = [
+        "statusor.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        ":status",
+        "//absl/base:core_headers",
+        "//absl/base:raw_logging_internal",
+        "//absl/meta:type_traits",
+        "//absl/strings",
+        "//absl/types:variant",
+        "//absl/utility",
+    ],
+)
+
+cc_test(
+    name = "statusor_test",
+    size = "small",
+    srcs = ["statusor_test.cc"],
+    deps = [
+        ":status",
+        ":statusor",
+        "//absl/base",
+        "//absl/memory",
+        "//absl/types:any",
+        "//absl/utility",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
diff --git a/absl/status/CMakeLists.txt b/absl/status/CMakeLists.txt
new file mode 100644
index 0000000..f0d798a
--- /dev/null
+++ b/absl/status/CMakeLists.txt
@@ -0,0 +1,88 @@
+#
+# Copyright 2020 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+absl_cc_library(
+  NAME
+    status
+  HDRS
+    "status.h"
+  SRCS
+    "internal/status_internal.h"
+    "status.cc"
+    "status_payload_printer.h"
+    "status_payload_printer.cc"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::atomic_hook
+    absl::config
+    absl::core_headers
+    absl::raw_logging_internal
+    absl::inlined_vector
+    absl::stacktrace
+    absl::symbolize
+    absl::strings
+    absl::cord
+    absl::str_format
+    absl::optional
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    status_test
+  SRCS
+   "status_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::status
+    absl::strings
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
+    statusor
+  HDRS
+    "statusor.h"
+  SRCS
+    "statusor.cc"
+    "internal/statusor_internal.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::status
+    absl::core_headers
+    absl::raw_logging_internal
+    absl::type_traits
+    absl::strings
+    absl::utility
+    absl::variant
+  PUBLIC
+)
+
+absl_cc_test(
+  NAME
+    statusor_test
+  SRCS
+   "statusor_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::status
+    absl::statusor
+    gmock_main
+)
diff --git a/absl/status/internal/status_internal.h b/absl/status/internal/status_internal.h
new file mode 100644
index 0000000..279f8f5
--- /dev/null
+++ b/absl/status/internal/status_internal.h
@@ -0,0 +1,58 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
+#define ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
+
+#include <string>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/cord.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+enum class StatusCode : int;
+
+namespace status_internal {
+
+// Container for status payloads.
+struct Payload {
+  std::string type_url;
+  absl::Cord payload;
+};
+
+using Payloads = absl::InlinedVector<Payload, 1>;
+
+// Reference-counted representation of Status data.
+struct StatusRep {
+  StatusRep(absl::StatusCode code, std::string message,
+            std::unique_ptr<status_internal::Payloads> payloads)
+      : ref(int32_t{1}),
+        code(code),
+        message(std::move(message)),
+        payloads(std::move(payloads)) {}
+
+  std::atomic<int32_t> ref;
+  absl::StatusCode code;
+  std::string message;
+  std::unique_ptr<status_internal::Payloads> payloads;
+};
+
+absl::StatusCode MapToLocalCode(int value);
+}  // namespace status_internal
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
diff --git a/absl/status/internal/statusor_internal.h b/absl/status/internal/statusor_internal.h
new file mode 100644
index 0000000..eaac2c0
--- /dev/null
+++ b/absl/status/internal/statusor_internal.h
@@ -0,0 +1,396 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
+#define ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
+
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/meta/type_traits.h"
+#include "absl/status/status.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+template <typename T>
+class ABSL_MUST_USE_RESULT StatusOr;
+
+namespace internal_statusor {
+
+// Detects whether `U` has conversion operator to `StatusOr<T>`, i.e. `operator
+// StatusOr<T>()`.
+template <typename T, typename U, typename = void>
+struct HasConversionOperatorToStatusOr : std::false_type {};
+
+template <typename T, typename U>
+void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]);
+
+template <typename T, typename U>
+struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
+    : std::true_type {};
+
+// Detects whether `T` is constructible or convertible from `StatusOr<U>`.
+template <typename T, typename U>
+using IsConstructibleOrConvertibleFromStatusOr =
+    absl::disjunction<std::is_constructible<T, StatusOr<U>&>,
+                      std::is_constructible<T, const StatusOr<U>&>,
+                      std::is_constructible<T, StatusOr<U>&&>,
+                      std::is_constructible<T, const StatusOr<U>&&>,
+                      std::is_convertible<StatusOr<U>&, T>,
+                      std::is_convertible<const StatusOr<U>&, T>,
+                      std::is_convertible<StatusOr<U>&&, T>,
+                      std::is_convertible<const StatusOr<U>&&, T>>;
+
+// Detects whether `T` is constructible or convertible or assignable from
+// `StatusOr<U>`.
+template <typename T, typename U>
+using IsConstructibleOrConvertibleOrAssignableFromStatusOr =
+    absl::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>,
+                      std::is_assignable<T&, StatusOr<U>&>,
+                      std::is_assignable<T&, const StatusOr<U>&>,
+                      std::is_assignable<T&, StatusOr<U>&&>,
+                      std::is_assignable<T&, const StatusOr<U>&&>>;
+
+// Detects whether direct initializing `StatusOr<T>` from `U` is ambiguous, i.e.
+// when `U` is `StatusOr<V>` and `T` is constructible or convertible from `V`.
+template <typename T, typename U>
+struct IsDirectInitializationAmbiguous
+    : public absl::conditional_t<
+          std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                       U>::value,
+          std::false_type,
+          IsDirectInitializationAmbiguous<
+              T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
+
+template <typename T, typename V>
+struct IsDirectInitializationAmbiguous<T, absl::StatusOr<V>>
+    : public IsConstructibleOrConvertibleFromStatusOr<T, V> {};
+
+// Checks against the constraints of the direction initialization, i.e. when
+// `StatusOr<T>::StatusOr(U&&)` should participate in overload resolution.
+template <typename T, typename U>
+using IsDirectInitializationValid = absl::disjunction<
+    // Short circuits if T is basically U.
+    std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
+    absl::negation<absl::disjunction<
+        std::is_same<absl::StatusOr<T>,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::Status,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::in_place_t,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        IsDirectInitializationAmbiguous<T, U>>>>;
+
+// This trait detects whether `StatusOr<T>::operator=(U&&)` is ambiguous, which
+// is equivalent to whether all the following conditions are met:
+// 1. `U` is `StatusOr<V>`.
+// 2. `T` is constructible and assignable from `V`.
+// 3. `T` is constructible and assignable from `U` (i.e. `StatusOr<V>`).
+// For example, the following code is considered ambiguous:
+// (`T` is `bool`, `U` is `StatusOr<bool>`, `V` is `bool`)
+//   StatusOr<bool> s1 = true;  // s1.ok() && s1.ValueOrDie() == true
+//   StatusOr<bool> s2 = false;  // s2.ok() && s2.ValueOrDie() == false
+//   s1 = s2;  // ambiguous, `s1 = s2.ValueOrDie()` or `s1 = bool(s2)`?
+template <typename T, typename U>
+struct IsForwardingAssignmentAmbiguous
+    : public absl::conditional_t<
+          std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                       U>::value,
+          std::false_type,
+          IsForwardingAssignmentAmbiguous<
+              T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
+
+template <typename T, typename U>
+struct IsForwardingAssignmentAmbiguous<T, absl::StatusOr<U>>
+    : public IsConstructibleOrConvertibleOrAssignableFromStatusOr<T, U> {};
+
+// Checks against the constraints of the forwarding assignment, i.e. whether
+// `StatusOr<T>::operator(U&&)` should participate in overload resolution.
+template <typename T, typename U>
+using IsForwardingAssignmentValid = absl::disjunction<
+    // Short circuits if T is basically U.
+    std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
+    absl::negation<absl::disjunction<
+        std::is_same<absl::StatusOr<T>,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::Status,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        std::is_same<absl::in_place_t,
+                     absl::remove_cv_t<absl::remove_reference_t<U>>>,
+        IsForwardingAssignmentAmbiguous<T, U>>>>;
+
+class Helper {
+ public:
+  // Move type-agnostic error handling to the .cc.
+  static void HandleInvalidStatusCtorArg(Status*);
+  ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status);
+};
+
+// Construct an instance of T in `p` through placement new, passing Args... to
+// the constructor.
+// This abstraction is here mostly for the gcc performance fix.
+template <typename T, typename... Args>
+ABSL_ATTRIBUTE_NONNULL(1) void PlacementNew(void* p, Args&&... args) {
+  new (p) T(std::forward<Args>(args)...);
+}
+
+// Helper base class to hold the data and all operations.
+// We move all this to a base class to allow mixing with the appropriate
+// TraitsBase specialization.
+template <typename T>
+class StatusOrData {
+  template <typename U>
+  friend class StatusOrData;
+
+ public:
+  StatusOrData() = delete;
+
+  StatusOrData(const StatusOrData& other) {
+    if (other.ok()) {
+      MakeValue(other.data_);
+      MakeStatus();
+    } else {
+      MakeStatus(other.status_);
+    }
+  }
+
+  StatusOrData(StatusOrData&& other) noexcept {
+    if (other.ok()) {
+      MakeValue(std::move(other.data_));
+      MakeStatus();
+    } else {
+      MakeStatus(std::move(other.status_));
+    }
+  }
+
+  template <typename U>
+  explicit StatusOrData(const StatusOrData<U>& other) {
+    if (other.ok()) {
+      MakeValue(other.data_);
+      MakeStatus();
+    } else {
+      MakeStatus(other.status_);
+    }
+  }
+
+  template <typename U>
+  explicit StatusOrData(StatusOrData<U>&& other) {
+    if (other.ok()) {
+      MakeValue(std::move(other.data_));
+      MakeStatus();
+    } else {
+      MakeStatus(std::move(other.status_));
+    }
+  }
+
+  template <typename... Args>
+  explicit StatusOrData(absl::in_place_t, Args&&... args)
+      : data_(std::forward<Args>(args)...) {
+    MakeStatus();
+  }
+
+  explicit StatusOrData(const T& value) : data_(value) {
+    MakeStatus();
+  }
+  explicit StatusOrData(T&& value) : data_(std::move(value)) {
+    MakeStatus();
+  }
+
+  template <typename U,
+            absl::enable_if_t<std::is_constructible<absl::Status, U&&>::value,
+                              int> = 0>
+  explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) {
+    EnsureNotOk();
+  }
+
+  StatusOrData& operator=(const StatusOrData& other) {
+    if (this == &other) return *this;
+    if (other.ok())
+      Assign(other.data_);
+    else
+      AssignStatus(other.status_);
+    return *this;
+  }
+
+  StatusOrData& operator=(StatusOrData&& other) {
+    if (this == &other) return *this;
+    if (other.ok())
+      Assign(std::move(other.data_));
+    else
+      AssignStatus(std::move(other.status_));
+    return *this;
+  }
+
+  ~StatusOrData() {
+    if (ok()) {
+      status_.~Status();
+      data_.~T();
+    } else {
+      status_.~Status();
+    }
+  }
+
+  template <typename U>
+  void Assign(U&& value) {
+    if (ok()) {
+      data_ = std::forward<U>(value);
+    } else {
+      MakeValue(std::forward<U>(value));
+      status_ = OkStatus();
+    }
+  }
+
+  template <typename U>
+  void AssignStatus(U&& v) {
+    Clear();
+    status_ = static_cast<absl::Status>(std::forward<U>(v));
+    EnsureNotOk();
+  }
+
+  bool ok() const { return status_.ok(); }
+
+ protected:
+  // status_ will always be active after the constructor.
+  // We make it a union to be able to initialize exactly how we need without
+  // waste.
+  // Eg. in the copy constructor we use the default constructor of Status in
+  // the ok() path to avoid an extra Ref call.
+  union {
+    Status status_;
+  };
+
+  // data_ is active iff status_.ok()==true
+  struct Dummy {};
+  union {
+    // When T is const, we need some non-const object we can cast to void* for
+    // the placement new. dummy_ is that object.
+    Dummy dummy_;
+    T data_;
+  };
+
+  void Clear() {
+    if (ok()) data_.~T();
+  }
+
+  void EnsureOk() const {
+    if (ABSL_PREDICT_FALSE(!ok())) Helper::Crash(status_);
+  }
+
+  void EnsureNotOk() {
+    if (ABSL_PREDICT_FALSE(ok())) Helper::HandleInvalidStatusCtorArg(&status_);
+  }
+
+  // Construct the value (ie. data_) through placement new with the passed
+  // argument.
+  template <typename... Arg>
+  void MakeValue(Arg&&... arg) {
+    internal_statusor::PlacementNew<T>(&dummy_, std::forward<Arg>(arg)...);
+  }
+
+  // Construct the status (ie. status_) through placement new with the passed
+  // argument.
+  template <typename... Args>
+  void MakeStatus(Args&&... args) {
+    internal_statusor::PlacementNew<Status>(&status_,
+                                            std::forward<Args>(args)...);
+  }
+};
+
+// Helper base classes to allow implicitly deleted constructors and assignment
+// operators in `StatusOr`. For example, `CopyCtorBase` will explicitly delete
+// the copy constructor when T is not copy constructible and `StatusOr` will
+// inherit that behavior implicitly.
+template <typename T, bool = std::is_copy_constructible<T>::value>
+struct CopyCtorBase {
+  CopyCtorBase() = default;
+  CopyCtorBase(const CopyCtorBase&) = default;
+  CopyCtorBase(CopyCtorBase&&) = default;
+  CopyCtorBase& operator=(const CopyCtorBase&) = default;
+  CopyCtorBase& operator=(CopyCtorBase&&) = default;
+};
+
+template <typename T>
+struct CopyCtorBase<T, false> {
+  CopyCtorBase() = default;
+  CopyCtorBase(const CopyCtorBase&) = delete;
+  CopyCtorBase(CopyCtorBase&&) = default;
+  CopyCtorBase& operator=(const CopyCtorBase&) = default;
+  CopyCtorBase& operator=(CopyCtorBase&&) = default;
+};
+
+template <typename T, bool = std::is_move_constructible<T>::value>
+struct MoveCtorBase {
+  MoveCtorBase() = default;
+  MoveCtorBase(const MoveCtorBase&) = default;
+  MoveCtorBase(MoveCtorBase&&) = default;
+  MoveCtorBase& operator=(const MoveCtorBase&) = default;
+  MoveCtorBase& operator=(MoveCtorBase&&) = default;
+};
+
+template <typename T>
+struct MoveCtorBase<T, false> {
+  MoveCtorBase() = default;
+  MoveCtorBase(const MoveCtorBase&) = default;
+  MoveCtorBase(MoveCtorBase&&) = delete;
+  MoveCtorBase& operator=(const MoveCtorBase&) = default;
+  MoveCtorBase& operator=(MoveCtorBase&&) = default;
+};
+
+template <typename T, bool = std::is_copy_constructible<T>::value&&
+                          std::is_copy_assignable<T>::value>
+struct CopyAssignBase {
+  CopyAssignBase() = default;
+  CopyAssignBase(const CopyAssignBase&) = default;
+  CopyAssignBase(CopyAssignBase&&) = default;
+  CopyAssignBase& operator=(const CopyAssignBase&) = default;
+  CopyAssignBase& operator=(CopyAssignBase&&) = default;
+};
+
+template <typename T>
+struct CopyAssignBase<T, false> {
+  CopyAssignBase() = default;
+  CopyAssignBase(const CopyAssignBase&) = default;
+  CopyAssignBase(CopyAssignBase&&) = default;
+  CopyAssignBase& operator=(const CopyAssignBase&) = delete;
+  CopyAssignBase& operator=(CopyAssignBase&&) = default;
+};
+
+template <typename T, bool = std::is_move_constructible<T>::value&&
+                          std::is_move_assignable<T>::value>
+struct MoveAssignBase {
+  MoveAssignBase() = default;
+  MoveAssignBase(const MoveAssignBase&) = default;
+  MoveAssignBase(MoveAssignBase&&) = default;
+  MoveAssignBase& operator=(const MoveAssignBase&) = default;
+  MoveAssignBase& operator=(MoveAssignBase&&) = default;
+};
+
+template <typename T>
+struct MoveAssignBase<T, false> {
+  MoveAssignBase() = default;
+  MoveAssignBase(const MoveAssignBase&) = default;
+  MoveAssignBase(MoveAssignBase&&) = default;
+  MoveAssignBase& operator=(const MoveAssignBase&) = default;
+  MoveAssignBase& operator=(MoveAssignBase&&) = delete;
+};
+
+ABSL_ATTRIBUTE_NORETURN void ThrowBadStatusOrAccess(absl::Status status);
+
+}  // namespace internal_statusor
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
diff --git a/absl/status/status.cc b/absl/status/status.cc
new file mode 100644
index 0000000..c71de84
--- /dev/null
+++ b/absl/status/status.cc
@@ -0,0 +1,442 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "absl/status/status.h"
+
+#include <cassert>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/debugging/stacktrace.h"
+#include "absl/debugging/symbolize.h"
+#include "absl/status/status_payload_printer.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_split.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+std::string StatusCodeToString(StatusCode code) {
+  switch (code) {
+    case StatusCode::kOk:
+      return "OK";
+    case StatusCode::kCancelled:
+      return "CANCELLED";
+    case StatusCode::kUnknown:
+      return "UNKNOWN";
+    case StatusCode::kInvalidArgument:
+      return "INVALID_ARGUMENT";
+    case StatusCode::kDeadlineExceeded:
+      return "DEADLINE_EXCEEDED";
+    case StatusCode::kNotFound:
+      return "NOT_FOUND";
+    case StatusCode::kAlreadyExists:
+      return "ALREADY_EXISTS";
+    case StatusCode::kPermissionDenied:
+      return "PERMISSION_DENIED";
+    case StatusCode::kUnauthenticated:
+      return "UNAUTHENTICATED";
+    case StatusCode::kResourceExhausted:
+      return "RESOURCE_EXHAUSTED";
+    case StatusCode::kFailedPrecondition:
+      return "FAILED_PRECONDITION";
+    case StatusCode::kAborted:
+      return "ABORTED";
+    case StatusCode::kOutOfRange:
+      return "OUT_OF_RANGE";
+    case StatusCode::kUnimplemented:
+      return "UNIMPLEMENTED";
+    case StatusCode::kInternal:
+      return "INTERNAL";
+    case StatusCode::kUnavailable:
+      return "UNAVAILABLE";
+    case StatusCode::kDataLoss:
+      return "DATA_LOSS";
+    default:
+      return "";
+  }
+}
+
+std::ostream& operator<<(std::ostream& os, StatusCode code) {
+  return os << StatusCodeToString(code);
+}
+
+namespace status_internal {
+
+static int FindPayloadIndexByUrl(const Payloads* payloads,
+                                 absl::string_view type_url) {
+  if (payloads == nullptr) return -1;
+
+  for (size_t i = 0; i < payloads->size(); ++i) {
+    if ((*payloads)[i].type_url == type_url) return i;
+  }
+
+  return -1;
+}
+
+// Convert canonical code to a value known to this binary.
+absl::StatusCode MapToLocalCode(int value) {
+  absl::StatusCode code = static_cast<absl::StatusCode>(value);
+  switch (code) {
+    case absl::StatusCode::kOk:
+    case absl::StatusCode::kCancelled:
+    case absl::StatusCode::kUnknown:
+    case absl::StatusCode::kInvalidArgument:
+    case absl::StatusCode::kDeadlineExceeded:
+    case absl::StatusCode::kNotFound:
+    case absl::StatusCode::kAlreadyExists:
+    case absl::StatusCode::kPermissionDenied:
+    case absl::StatusCode::kResourceExhausted:
+    case absl::StatusCode::kFailedPrecondition:
+    case absl::StatusCode::kAborted:
+    case absl::StatusCode::kOutOfRange:
+    case absl::StatusCode::kUnimplemented:
+    case absl::StatusCode::kInternal:
+    case absl::StatusCode::kUnavailable:
+    case absl::StatusCode::kDataLoss:
+    case absl::StatusCode::kUnauthenticated:
+      return code;
+    default:
+      return absl::StatusCode::kUnknown;
+  }
+}
+}  // namespace status_internal
+
+absl::optional<absl::Cord> Status::GetPayload(
+    absl::string_view type_url) const {
+  const auto* payloads = GetPayloads();
+  int index = status_internal::FindPayloadIndexByUrl(payloads, type_url);
+  if (index != -1) return (*payloads)[index].payload;
+
+  return absl::nullopt;
+}
+
+void Status::SetPayload(absl::string_view type_url, absl::Cord payload) {
+  if (ok()) return;
+
+  PrepareToModify();
+
+  status_internal::StatusRep* rep = RepToPointer(rep_);
+  if (!rep->payloads) {
+    rep->payloads = absl::make_unique<status_internal::Payloads>();
+  }
+
+  int index =
+      status_internal::FindPayloadIndexByUrl(rep->payloads.get(), type_url);
+  if (index != -1) {
+    (*rep->payloads)[index].payload = std::move(payload);
+    return;
+  }
+
+  rep->payloads->push_back({std::string(type_url), std::move(payload)});
+}
+
+bool Status::ErasePayload(absl::string_view type_url) {
+  int index = status_internal::FindPayloadIndexByUrl(GetPayloads(), type_url);
+  if (index != -1) {
+    PrepareToModify();
+    GetPayloads()->erase(GetPayloads()->begin() + index);
+    if (GetPayloads()->empty() && message().empty()) {
+      // Special case: If this can be represented inlined, it MUST be
+      // inlined (EqualsSlow depends on this behavior).
+      StatusCode c = static_cast<StatusCode>(raw_code());
+      Unref(rep_);
+      rep_ = CodeToInlinedRep(c);
+    }
+    return true;
+  }
+
+  return false;
+}
+
+void Status::ForEachPayload(
+    const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
+    const {
+  if (auto* payloads = GetPayloads()) {
+    bool in_reverse =
+        payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6;
+
+    for (size_t index = 0; index < payloads->size(); ++index) {
+      const auto& elem =
+          (*payloads)[in_reverse ? payloads->size() - 1 - index : index];
+
+#ifdef NDEBUG
+      visitor(elem.type_url, elem.payload);
+#else
+      // In debug mode invalidate the type url to prevent users from relying on
+      // this string lifetime.
+
+      // NOLINTNEXTLINE intentional extra conversion to force temporary.
+      visitor(std::string(elem.type_url), elem.payload);
+#endif  // NDEBUG
+    }
+  }
+}
+
+const std::string* Status::EmptyString() {
+  static std::string* empty_string = new std::string();
+  return empty_string;
+}
+
+constexpr const char Status::kMovedFromString[];
+
+const std::string* Status::MovedFromString() {
+  static std::string* moved_from_string = new std::string(kMovedFromString);
+  return moved_from_string;
+}
+
+void Status::UnrefNonInlined(uintptr_t rep) {
+  status_internal::StatusRep* r = RepToPointer(rep);
+  // Fast path: if ref==1, there is no need for a RefCountDec (since
+  // this is the only reference and therefore no other thread is
+  // allowed to be mucking with r).
+  if (r->ref.load(std::memory_order_acquire) == 1 ||
+      r->ref.fetch_sub(1, std::memory_order_acq_rel) - 1 == 0) {
+    delete r;
+  }
+}
+
+uintptr_t Status::NewRep(absl::StatusCode code, absl::string_view msg,
+                         std::unique_ptr<status_internal::Payloads> payloads) {
+  status_internal::StatusRep* rep = new status_internal::StatusRep(
+      code, std::string(msg.data(), msg.size()), std::move(payloads));
+  return PointerToRep(rep);
+}
+
+Status::Status(absl::StatusCode code, absl::string_view msg)
+    : rep_(CodeToInlinedRep(code)) {
+  if (code != absl::StatusCode::kOk && !msg.empty()) {
+    rep_ = NewRep(code, msg, nullptr);
+  }
+}
+
+int Status::raw_code() const {
+  if (IsInlined(rep_)) {
+    return static_cast<int>(InlinedRepToCode(rep_));
+  }
+  status_internal::StatusRep* rep = RepToPointer(rep_);
+  return static_cast<int>(rep->code);
+}
+
+absl::StatusCode Status::code() const {
+  return status_internal::MapToLocalCode(raw_code());
+}
+
+void Status::PrepareToModify() {
+  ABSL_RAW_CHECK(!ok(), "PrepareToModify shouldn't be called on OK status.");
+  if (IsInlined(rep_)) {
+    rep_ = NewRep(static_cast<absl::StatusCode>(raw_code()),
+                  absl::string_view(), nullptr);
+    return;
+  }
+
+  uintptr_t rep_i = rep_;
+  status_internal::StatusRep* rep = RepToPointer(rep_);
+  if (rep->ref.load(std::memory_order_acquire) != 1) {
+    std::unique_ptr<status_internal::Payloads> payloads;
+    if (rep->payloads) {
+      payloads = absl::make_unique<status_internal::Payloads>(*rep->payloads);
+    }
+    rep_ = NewRep(rep->code, message(), std::move(payloads));
+    UnrefNonInlined(rep_i);
+  }
+}
+
+bool Status::EqualsSlow(const absl::Status& a, const absl::Status& b) {
+  if (IsInlined(a.rep_) != IsInlined(b.rep_)) return false;
+  if (a.message() != b.message()) return false;
+  if (a.raw_code() != b.raw_code()) return false;
+  if (a.GetPayloads() == b.GetPayloads()) return true;
+
+  const status_internal::Payloads no_payloads;
+  const status_internal::Payloads* larger_payloads =
+      a.GetPayloads() ? a.GetPayloads() : &no_payloads;
+  const status_internal::Payloads* smaller_payloads =
+      b.GetPayloads() ? b.GetPayloads() : &no_payloads;
+  if (larger_payloads->size() < smaller_payloads->size()) {
+    std::swap(larger_payloads, smaller_payloads);
+  }
+  if ((larger_payloads->size() - smaller_payloads->size()) > 1) return false;
+  // Payloads can be ordered differently, so we can't just compare payload
+  // vectors.
+  for (const auto& payload : *larger_payloads) {
+
+    bool found = false;
+    for (const auto& other_payload : *smaller_payloads) {
+      if (payload.type_url == other_payload.type_url) {
+        if (payload.payload != other_payload.payload) {
+          return false;
+        }
+        found = true;
+        break;
+      }
+    }
+    if (!found) return false;
+  }
+  return true;
+}
+
+std::string Status::ToStringSlow() const {
+  std::string text;
+  absl::StrAppend(&text, absl::StatusCodeToString(code()), ": ", message());
+  status_internal::StatusPayloadPrinter printer =
+      status_internal::GetStatusPayloadPrinter();
+  this->ForEachPayload([&](absl::string_view type_url,
+                           const absl::Cord& payload) {
+    absl::optional<std::string> result;
+    if (printer) result = printer(type_url, payload);
+    absl::StrAppend(
+        &text, " [", type_url, "='",
+        result.has_value() ? *result : absl::CHexEscape(std::string(payload)),
+        "']");
+  });
+
+  return text;
+}
+
+std::ostream& operator<<(std::ostream& os, const Status& x) {
+  os << x.ToString();
+  return os;
+}
+
+Status AbortedError(absl::string_view message) {
+  return Status(absl::StatusCode::kAborted, message);
+}
+
+Status AlreadyExistsError(absl::string_view message) {
+  return Status(absl::StatusCode::kAlreadyExists, message);
+}
+
+Status CancelledError(absl::string_view message) {
+  return Status(absl::StatusCode::kCancelled, message);
+}
+
+Status DataLossError(absl::string_view message) {
+  return Status(absl::StatusCode::kDataLoss, message);
+}
+
+Status DeadlineExceededError(absl::string_view message) {
+  return Status(absl::StatusCode::kDeadlineExceeded, message);
+}
+
+Status FailedPreconditionError(absl::string_view message) {
+  return Status(absl::StatusCode::kFailedPrecondition, message);
+}
+
+Status InternalError(absl::string_view message) {
+  return Status(absl::StatusCode::kInternal, message);
+}
+
+Status InvalidArgumentError(absl::string_view message) {
+  return Status(absl::StatusCode::kInvalidArgument, message);
+}
+
+Status NotFoundError(absl::string_view message) {
+  return Status(absl::StatusCode::kNotFound, message);
+}
+
+Status OutOfRangeError(absl::string_view message) {
+  return Status(absl::StatusCode::kOutOfRange, message);
+}
+
+Status PermissionDeniedError(absl::string_view message) {
+  return Status(absl::StatusCode::kPermissionDenied, message);
+}
+
+Status ResourceExhaustedError(absl::string_view message) {
+  return Status(absl::StatusCode::kResourceExhausted, message);
+}
+
+Status UnauthenticatedError(absl::string_view message) {
+  return Status(absl::StatusCode::kUnauthenticated, message);
+}
+
+Status UnavailableError(absl::string_view message) {
+  return Status(absl::StatusCode::kUnavailable, message);
+}
+
+Status UnimplementedError(absl::string_view message) {
+  return Status(absl::StatusCode::kUnimplemented, message);
+}
+
+Status UnknownError(absl::string_view message) {
+  return Status(absl::StatusCode::kUnknown, message);
+}
+
+bool IsAborted(const Status& status) {
+  return status.code() == absl::StatusCode::kAborted;
+}
+
+bool IsAlreadyExists(const Status& status) {
+  return status.code() == absl::StatusCode::kAlreadyExists;
+}
+
+bool IsCancelled(const Status& status) {
+  return status.code() == absl::StatusCode::kCancelled;
+}
+
+bool IsDataLoss(const Status& status) {
+  return status.code() == absl::StatusCode::kDataLoss;
+}
+
+bool IsDeadlineExceeded(const Status& status) {
+  return status.code() == absl::StatusCode::kDeadlineExceeded;
+}
+
+bool IsFailedPrecondition(const Status& status) {
+  return status.code() == absl::StatusCode::kFailedPrecondition;
+}
+
+bool IsInternal(const Status& status) {
+  return status.code() == absl::StatusCode::kInternal;
+}
+
+bool IsInvalidArgument(const Status& status) {
+  return status.code() == absl::StatusCode::kInvalidArgument;
+}
+
+bool IsNotFound(const Status& status) {
+  return status.code() == absl::StatusCode::kNotFound;
+}
+
+bool IsOutOfRange(const Status& status) {
+  return status.code() == absl::StatusCode::kOutOfRange;
+}
+
+bool IsPermissionDenied(const Status& status) {
+  return status.code() == absl::StatusCode::kPermissionDenied;
+}
+
+bool IsResourceExhausted(const Status& status) {
+  return status.code() == absl::StatusCode::kResourceExhausted;
+}
+
+bool IsUnauthenticated(const Status& status) {
+  return status.code() == absl::StatusCode::kUnauthenticated;
+}
+
+bool IsUnavailable(const Status& status) {
+  return status.code() == absl::StatusCode::kUnavailable;
+}
+
+bool IsUnimplemented(const Status& status) {
+  return status.code() == absl::StatusCode::kUnimplemented;
+}
+
+bool IsUnknown(const Status& status) {
+  return status.code() == absl::StatusCode::kUnknown;
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/status/status.h b/absl/status/status.h
new file mode 100644
index 0000000..08d3e80
--- /dev/null
+++ b/absl/status/status.h
@@ -0,0 +1,820 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: status.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the Abseil `status` library, consisting of:
+//
+//   * An `absl::Status` class for holding error handling information
+//   * A set of canonical `absl::StatusCode` error codes, and associated
+//     utilities for generating and propagating status codes.
+//   * A set of helper functions for creating status codes and checking their
+//     values
+//
+// Within Google, `absl::Status` is the primary mechanism for gracefully
+// handling errors across API boundaries (and in particular across RPC
+// boundaries). Some of these errors may be recoverable, but others may not.
+// Most functions that can produce a recoverable error should be designed to
+// return an `absl::Status` (or `absl::StatusOr`).
+//
+// Example:
+//
+// absl::Status myFunction(absl::string_view fname, ...) {
+//   ...
+//   // encounter error
+//   if (error condition) {
+//     return absl::InvalidArgumentError("bad mode");
+//   }
+//   // else, return OK
+//   return absl::OkStatus();
+// }
+//
+// An `absl::Status` is designed to either return "OK" or one of a number of
+// different error codes, corresponding to typical error conditions.
+// In almost all cases, when using `absl::Status` you should use the canonical
+// error codes (of type `absl::StatusCode`) enumerated in this header file.
+// These canonical codes are understood across the codebase and will be
+// accepted across all API and RPC boundaries.
+#ifndef ABSL_STATUS_STATUS_H_
+#define ABSL_STATUS_STATUS_H_
+
+#include <iostream>
+#include <string>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/status/internal/status_internal.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::StatusCode
+//
+// An `absl::StatusCode` is an enumerated type indicating either no error ("OK")
+// or an error condition. In most cases, an `absl::Status` indicates a
+// recoverable error, and the purpose of signalling an error is to indicate what
+// action to take in response to that error. These error codes map to the proto
+// RPC error codes indicated in https://cloud.google.com/apis/design/errors.
+//
+// The errors listed below are the canonical errors associated with
+// `absl::Status` and are used throughout the codebase. As a result, these
+// error codes are somewhat generic.
+//
+// In general, try to return the most specific error that applies if more than
+// one error may pertain. For example, prefer `kOutOfRange` over
+// `kFailedPrecondition` if both codes apply. Similarly prefer `kNotFound` or
+// `kAlreadyExists` over `kFailedPrecondition`.
+//
+// Because these errors may travel RPC boundaries, these codes are tied to the
+// `google.rpc.Code` definitions within
+// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
+// The string value of these RPC codes is denoted within each enum below.
+//
+// If your error handling code requires more context, you can attach payloads
+// to your status. See `absl::Status::SetPayload()` and
+// `absl::Status::GetPayload()` below.
+enum class StatusCode : int {
+  // StatusCode::kOk
+  //
+  // kOK (gRPC code "OK") does not indicate an error; this value is returned on
+  // success. It is typical to check for this value before proceeding on any
+  // given call across an API or RPC boundary. To check this value, use the
+  // `absl::Status::ok()` member function rather than inspecting the raw code.
+  kOk = 0,
+
+  // StatusCode::kCancelled
+  //
+  // kCancelled (gRPC code "CANCELLED") indicates the operation was cancelled,
+  // typically by the caller.
+  kCancelled = 1,
+
+  // StatusCode::kUnknown
+  //
+  // kUnknown (gRPC code "UNKNOWN") indicates an unknown error occurred. In
+  // general, more specific errors should be raised, if possible. Errors raised
+  // by APIs that do not return enough error information may be converted to
+  // this error.
+  kUnknown = 2,
+
+  // StatusCode::kInvalidArgument
+  //
+  // kInvalidArgument (gRPC code "INVALID_ARGUMENT") indicates the caller
+  // specified an invalid argument, such a malformed filename. Note that such
+  // errors should be narrowly limited to indicate to the invalid nature of the
+  // arguments themselves. Errors with validly formed arguments that may cause
+  // errors with the state of the receiving system should be denoted with
+  // `kFailedPrecondition` instead.
+  kInvalidArgument = 3,
+
+  // StatusCode::kDeadlineExceeded
+  //
+  // kDeadlineExceeded (gRPC code "DEADLINE_EXCEEDED") indicates a deadline
+  // expired before the operation could complete. For operations that may change
+  // state within a system, this error may be returned even if the operation has
+  // completed successfully. For example, a successful response from a server
+  // could have been delayed long enough for the deadline to expire.
+  kDeadlineExceeded = 4,
+
+  // StatusCode::kNotFound
+  //
+  // kNotFound (gRPC code "NOT_FOUND") indicates some requested entity (such as
+  // a file or directory) was not found.
+  //
+  // `kNotFound` is useful if a request should be denied for an entire class of
+  // users, such as during a gradual feature rollout or undocumented allow list.
+  // If, instead, a request should be denied for specific sets of users, such as
+  // through user-based access control, use `kPermissionDenied` instead.
+  kNotFound = 5,
+
+  // StatusCode::kAlreadyExists
+  //
+  // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates the entity that a
+  // caller attempted to create (such as file or directory) is already present.
+  kAlreadyExists = 6,
+
+  // StatusCode::kPermissionDenied
+  //
+  // kPermissionDenied (gRPC code "PERMISSION_DENIED") indicates that the caller
+  // does not have permission to execute the specified operation. Note that this
+  // error is different than an error due to an *un*authenticated user. This
+  // error code does not imply the request is valid or the requested entity
+  // exists or satisfies any other pre-conditions.
+  //
+  // `kPermissionDenied` must not be used for rejections caused by exhausting
+  // some resource. Instead, use `kResourceExhausted` for those errors.
+  // `kPermissionDenied` must not be used if the caller cannot be identified.
+  // Instead, use `kUnauthenticated` for those errors.
+  kPermissionDenied = 7,
+
+  // StatusCode::kResourceExhausted
+  //
+  // kResourceExhausted (gRPC code "RESOURCE_EXHAUSTED") indicates some resource
+  // has been exhausted, perhaps a per-user quota, or perhaps the entire file
+  // system is out of space.
+  kResourceExhausted = 8,
+
+  // StatusCode::kFailedPrecondition
+  //
+  // kFailedPrecondition (gRPC code "FAILED_PRECONDITION") indicates that the
+  // operation was rejected because the system is not in a state required for
+  // the operation's execution. For example, a directory to be deleted may be
+  // non-empty, an "rmdir" operation is applied to a non-directory, etc.
+  //
+  // Some guidelines that may help a service implementer in deciding between
+  // `kFailedPrecondition`, `kAborted`, and `kUnavailable`:
+  //
+  //  (a) Use `kUnavailable` if the client can retry just the failing call.
+  //  (b) Use `kAborted` if the client should retry at a higher transaction
+  //      level (such as when a client-specified test-and-set fails, indicating
+  //      the client should restart a read-modify-write sequence).
+  //  (c) Use `kFailedPrecondition` if the client should not retry until
+  //      the system state has been explicitly fixed. For example, if an "rmdir"
+  //      fails because the directory is non-empty, `kFailedPrecondition`
+  //      should be returned since the client should not retry unless
+  //      the files are deleted from the directory.
+  kFailedPrecondition = 9,
+
+  // StatusCode::kAborted
+  //
+  // kAborted (gRPC code "ABORTED") indicates the operation was aborted,
+  // typically due to a concurrency issue such as a sequencer check failure or a
+  // failed transaction.
+  //
+  // See the guidelines above for deciding between `kFailedPrecondition`,
+  // `kAborted`, and `kUnavailable`.
+  kAborted = 10,
+
+  // StatusCode::kOutOfRange
+  //
+  // kOutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was
+  // attempted past the valid range, such as seeking or reading past an
+  // end-of-file.
+  //
+  // Unlike `kInvalidArgument`, this error indicates a problem that may
+  // be fixed if the system state changes. For example, a 32-bit file
+  // system will generate `kInvalidArgument` if asked to read at an
+  // offset that is not in the range [0,2^32-1], but it will generate
+  // `kOutOfRange` if asked to read from an offset past the current
+  // file size.
+  //
+  // There is a fair bit of overlap between `kFailedPrecondition` and
+  // `kOutOfRange`.  We recommend using `kOutOfRange` (the more specific
+  // error) when it applies so that callers who are iterating through
+  // a space can easily look for an `kOutOfRange` error to detect when
+  // they are done.
+  kOutOfRange = 11,
+
+  // StatusCode::kUnimplemented
+  //
+  // kUnimplemented (gRPC code "UNIMPLEMENTED") indicates the operation is not
+  // implemented or supported in this service. In this case, the operation
+  // should not be re-attempted.
+  kUnimplemented = 12,
+
+  // StatusCode::kInternal
+  //
+  // kInternal (gRPC code "INTERNAL") indicates an internal error has occurred
+  // and some invariants expected by the underlying system have not been
+  // satisfied. This error code is reserved for serious errors.
+  kInternal = 13,
+
+  // StatusCode::kUnavailable
+  //
+  // kUnavailable (gRPC code "UNAVAILABLE") indicates the service is currently
+  // unavailable and that this is most likely a transient condition. An error
+  // such as this can be corrected by retrying with a backoff scheme. Note that
+  // it is not always safe to retry non-idempotent operations.
+  //
+  // See the guidelines above for deciding between `kFailedPrecondition`,
+  // `kAborted`, and `kUnavailable`.
+  kUnavailable = 14,
+
+  // StatusCode::kDataLoss
+  //
+  // kDataLoss (gRPC code "DATA_LOSS") indicates that unrecoverable data loss or
+  // corruption has occurred. As this error is serious, proper alerting should
+  // be attached to errors such as this.
+  kDataLoss = 15,
+
+  // StatusCode::kUnauthenticated
+  //
+  // kUnauthenticated (gRPC code "UNAUTHENTICATED") indicates that the request
+  // does not have valid authentication credentials for the operation. Correct
+  // the authentication and try again.
+  kUnauthenticated = 16,
+
+  // StatusCode::DoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_
+  //
+  // NOTE: this error code entry should not be used and you should not rely on
+  // its value, which may change.
+  //
+  // The purpose of this enumerated value is to force people who handle status
+  // codes with `switch()` statements to *not* simply enumerate all possible
+  // values, but instead provide a "default:" case. Providing such a default
+  // case ensures that code will compile when new codes are added.
+  kDoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ = 20
+};
+
+// StatusCodeToString()
+//
+// Returns the name for the status code, or "" if it is an unknown value.
+std::string StatusCodeToString(StatusCode code);
+
+// operator<<
+//
+// Streams StatusCodeToString(code) to `os`.
+std::ostream& operator<<(std::ostream& os, StatusCode code);
+
+// absl::Status
+//
+// The `absl::Status` class is generally used to gracefully handle errors
+// across API boundaries (and in particular across RPC boundaries). Some of
+// these errors may be recoverable, but others may not. Most
+// functions which can produce a recoverable error should be designed to return
+// either an `absl::Status` (or the similar `absl::StatusOr<T>`, which holds
+// either an object of type `T` or an error).
+//
+// API developers should construct their functions to return `absl::OkStatus()`
+// upon success, or an `absl::StatusCode` upon another type of error (e.g
+// an `absl::StatusCode::kInvalidArgument` error). The API provides convenience
+// functions to constuct each status code.
+//
+// Example:
+//
+// absl::Status myFunction(absl::string_view fname, ...) {
+//   ...
+//   // encounter error
+//   if (error condition) {
+//     // Construct an absl::StatusCode::kInvalidArgument error
+//     return absl::InvalidArgumentError("bad mode");
+//   }
+//   // else, return OK
+//   return absl::OkStatus();
+// }
+//
+// Users handling status error codes should prefer checking for an OK status
+// using the `ok()` member function. Handling multiple error codes may justify
+// use of switch statement, but only check for error codes you know how to
+// handle; do not try to exhaustively match against all canonical error codes.
+// Errors that cannot be handled should be logged and/or propagated for higher
+// levels to deal with. If you do use a switch statement, make sure that you
+// also provide a `default:` switch case, so that code does not break as other
+// canonical codes are added to the API.
+//
+// Example:
+//
+//   absl::Status result = DoSomething();
+//   if (!result.ok()) {
+//     LOG(ERROR) << result;
+//   }
+//
+//   // Provide a default if switching on multiple error codes
+//   switch (result.code()) {
+//     // The user hasn't authenticated. Ask them to reauth
+//     case absl::StatusCode::kUnauthenticated:
+//       DoReAuth();
+//       break;
+//     // The user does not have permission. Log an error.
+//     case absl::StatusCode::kPermissionDenied:
+//       LOG(ERROR) << result;
+//       break;
+//     // Propagate the error otherwise.
+//     default:
+//       return true;
+//   }
+//
+// An `absl::Status` can optionally include a payload with more information
+// about the error. Typically, this payload serves one of several purposes:
+//
+//   * It may provide more fine-grained semantic information about the error to
+//     facilitate actionable remedies.
+//   * It may provide human-readable contexual information that is more
+//     appropriate to display to an end user.
+//
+// Example:
+//
+//   absl::Status result = DoSomething();
+//   // Inform user to retry after 30 seconds
+//   // See more error details in googleapis/google/rpc/error_details.proto
+//   if (absl::IsResourceExhausted(result)) {
+//     google::rpc::RetryInfo info;
+//     info.retry_delay().seconds() = 30;
+//     // Payloads require a unique key (a URL to ensure no collisions with
+//     // other payloads), and an `absl::Cord` to hold the encoded data.
+//     absl::string_view url = "type.googleapis.com/google.rpc.RetryInfo";
+//     result.SetPayload(url, info.SerializeAsCord());
+//     return result;
+//   }
+//
+class ABSL_MUST_USE_RESULT Status final {
+ public:
+  // Constructors
+
+  // This default constructor creates an OK status with no message or payload.
+  // Avoid this constructor and prefer explicit construction of an OK status
+  // with `absl::OkStatus()`.
+  Status();
+
+  // Creates a status in the canonical error space with the specified
+  // `absl::StatusCode` and error message.  If `code == absl::StatusCode::kOk`,
+  // `msg` is ignored and an object identical to an OK status is constructed.
+  //
+  // The `msg` string must be in UTF-8. The implementation may complain (e.g.,
+  // by printing a warning) if it is not.
+  Status(absl::StatusCode code, absl::string_view msg);
+
+  Status(const Status&);
+  Status& operator=(const Status& x);
+
+  // Move operators
+
+  // The moved-from state is valid but unspecified.
+  Status(Status&&) noexcept;
+  Status& operator=(Status&&);
+
+  ~Status();
+
+  // Status::Update()
+  //
+  // Updates the existing status with `new_status` provided that `this->ok()`.
+  // If the existing status already contains a non-OK error, this update has no
+  // effect and preserves the current data. Note that this behavior may change
+  // in the future to augment a current non-ok status with additional
+  // information about `new_status`.
+  //
+  // `Update()` provides a convenient way of keeping track of the first error
+  // encountered.
+  //
+  // Example:
+  //   // Instead of "if (overall_status.ok()) overall_status = new_status"
+  //   overall_status.Update(new_status);
+  //
+  void Update(const Status& new_status);
+  void Update(Status&& new_status);
+
+  // Status::ok()
+  //
+  // Returns `true` if `this->ok()`. Prefer checking for an OK status using this
+  // member function.
+  ABSL_MUST_USE_RESULT bool ok() const;
+
+  // Status::code()
+  //
+  // Returns the canonical error code of type `absl::StatusCode` of this status.
+  absl::StatusCode code() const;
+
+  // Status::raw_code()
+  //
+  // Returns a raw (canonical) error code corresponding to the enum value of
+  // `google.rpc.Code` definitions within
+  // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto.
+  // These values could be out of the range of canonical `absl::StatusCode`
+  // enum values.
+  //
+  // NOTE: This function should only be called when converting to an associated
+  // wire format. Use `Status::code()` for error handling.
+  int raw_code() const;
+
+  // Status::message()
+  //
+  // Returns the error message associated with this error code, if available.
+  // Note that this message rarely describes the error code.  It is not unusual
+  // for the error message to be the empty string. As a result, prefer
+  // `Status::ToString()` for debug logging.
+  absl::string_view message() const;
+
+  friend bool operator==(const Status&, const Status&);
+  friend bool operator!=(const Status&, const Status&);
+
+  // Status::ToString()
+  //
+  // Returns a combination of the error code name, the message and any
+  // associated payload messages. This string is designed simply to be human
+  // readable and its exact format should not be load bearing. Do not depend on
+  // the exact format of the result of `ToString()` which is subject to change.
+  //
+  // The printed code name and the message are generally substrings of the
+  // result, and the payloads to be printed use the status payload printer
+  // mechanism (which is internal).
+  std::string ToString() const;
+
+  // Status::IgnoreError()
+  //
+  // Ignores any errors. This method does nothing except potentially suppress
+  // complaints from any tools that are checking that errors are not dropped on
+  // the floor.
+  void IgnoreError() const;
+
+  // swap()
+  //
+  // Swap the contents of one status with another.
+  friend void swap(Status& a, Status& b);
+
+  //----------------------------------------------------------------------------
+  // Payload Management APIs
+  //----------------------------------------------------------------------------
+
+  // A payload may be attached to a status to provide additional context to an
+  // error that may not be satisifed by an existing `absl::StatusCode`.
+  // Typically, this payload serves one of several purposes:
+  //
+  //   * It may provide more fine-grained semantic information about the error
+  //     to facilitate actionable remedies.
+  //   * It may provide human-readable contexual information that is more
+  //     appropriate to display to an end user.
+  //
+  // A payload consists of a [key,value] pair, where the key is a string
+  // referring to a unique "type URL" and the value is an object of type
+  // `absl::Cord` to hold the contextual data.
+  //
+  // The "type URL" should be unique and follow the format of a URL
+  // (https://en.wikipedia.org/wiki/URL) and, ideally, provide some
+  // documentation or schema on how to interpret its associated data. For
+  // example, the default type URL for a protobuf message type is
+  // "type.googleapis.com/packagename.messagename". Other custom wire formats
+  // should define the format of type URL in a similar practice so as to
+  // minimize the chance of conflict between type URLs.
+  // Users should ensure that the type URL can be mapped to a concrete
+  // C++ type if they want to deserialize the payload and read it effectively.
+  //
+  // To attach a payload to a status object, call `Status::SetPayload()`,
+  // passing it the type URL and an `absl::Cord` of associated data. Similarly,
+  // to extract the payload from a status, call `Status::GetPayload()`. You
+  // may attach multiple payloads (with differing type URLs) to any given
+  // status object, provided that the status is currently exhibiting an error
+  // code (i.e. is not OK).
+
+  // Status::GetPayload()
+  //
+  // Gets the payload of a status given its unique `type_url` key, if present.
+  absl::optional<absl::Cord> GetPayload(absl::string_view type_url) const;
+
+  // Status::SetPayload()
+  //
+  // Sets the payload for a non-ok status using a `type_url` key, overwriting
+  // any existing payload for that `type_url`.
+  //
+  // NOTE: This function does nothing if the Status is ok.
+  void SetPayload(absl::string_view type_url, absl::Cord payload);
+
+  // Status::ErasePayload()
+  //
+  // Erases the payload corresponding to the `type_url` key.  Returns `true` if
+  // the payload was present.
+  bool ErasePayload(absl::string_view type_url);
+
+  // Status::ForEachPayload()
+  //
+  // Iterates over the stored payloads and calls the
+  // `visitor(type_key, payload)` callable for each one.
+  //
+  // NOTE: The order of calls to `visitor()` is not specified and may change at
+  // any time.
+  //
+  // NOTE: Any mutation on the same 'absl::Status' object during visitation is
+  // forbidden and could result in undefined behavior.
+  void ForEachPayload(
+      const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
+      const;
+
+ private:
+  friend Status CancelledError();
+
+  // Creates a status in the canonical error space with the specified
+  // code, and an empty error message.
+  explicit Status(absl::StatusCode code);
+
+  static void UnrefNonInlined(uintptr_t rep);
+  static void Ref(uintptr_t rep);
+  static void Unref(uintptr_t rep);
+
+  // REQUIRES: !ok()
+  // Ensures rep_ is not shared with any other Status.
+  void PrepareToModify();
+
+  const status_internal::Payloads* GetPayloads() const;
+  status_internal::Payloads* GetPayloads();
+
+  // Takes ownership of payload.
+  static uintptr_t NewRep(absl::StatusCode code, absl::string_view msg,
+                          std::unique_ptr<status_internal::Payloads> payload);
+  static bool EqualsSlow(const absl::Status& a, const absl::Status& b);
+
+  // MSVC 14.0 limitation requires the const.
+  static constexpr const char kMovedFromString[] =
+      "Status accessed after move.";
+
+  static const std::string* EmptyString();
+  static const std::string* MovedFromString();
+
+  // Returns whether rep contains an inlined representation.
+  // See rep_ for details.
+  static bool IsInlined(uintptr_t rep);
+
+  // Indicates whether this Status was the rhs of a move operation. See rep_
+  // for details.
+  static bool IsMovedFrom(uintptr_t rep);
+  static uintptr_t MovedFromRep();
+
+  // Convert between error::Code and the inlined uintptr_t representation used
+  // by rep_. See rep_ for details.
+  static uintptr_t CodeToInlinedRep(absl::StatusCode code);
+  static absl::StatusCode InlinedRepToCode(uintptr_t rep);
+
+  // Converts between StatusRep* and the external uintptr_t representation used
+  // by rep_. See rep_ for details.
+  static uintptr_t PointerToRep(status_internal::StatusRep* r);
+  static status_internal::StatusRep* RepToPointer(uintptr_t r);
+
+  // Returns string for non-ok Status.
+  std::string ToStringSlow() const;
+
+  // Status supports two different representations.
+  //  - When the low bit is off it is an inlined representation.
+  //    It uses the canonical error space, no message or payload.
+  //    The error code is (rep_ >> 2).
+  //    The (rep_ & 2) bit is the "moved from" indicator, used in IsMovedFrom().
+  //  - When the low bit is on it is an external representation.
+  //    In this case all the data comes from a heap allocated Rep object.
+  //    (rep_ - 1) is a status_internal::StatusRep* pointer to that structure.
+  uintptr_t rep_;
+};
+
+// OkStatus()
+//
+// Returns an OK status, equivalent to a default constructed instance. Prefer
+// usage of `absl::OkStatus()` when constructing such an OK status.
+Status OkStatus();
+
+// operator<<()
+//
+// Prints a human-readable representation of `x` to `os`.
+std::ostream& operator<<(std::ostream& os, const Status& x);
+
+// IsAborted()
+// IsAlreadyExists()
+// IsCancelled()
+// IsDataLoss()
+// IsDeadlineExceeded()
+// IsFailedPrecondition()
+// IsInternal()
+// IsInvalidArgument()
+// IsNotFound()
+// IsOutOfRange()
+// IsPermissionDenied()
+// IsResourceExhausted()
+// IsUnauthenticated()
+// IsUnavailable()
+// IsUnimplemented()
+// IsUnknown()
+//
+// These convenience functions return `true` if a given status matches the
+// `absl::StatusCode` error code of its associated function.
+ABSL_MUST_USE_RESULT bool IsAborted(const Status& status);
+ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status);
+ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status);
+ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status);
+ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status);
+ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status);
+ABSL_MUST_USE_RESULT bool IsInternal(const Status& status);
+ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status);
+ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status);
+ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status);
+ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status);
+ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status);
+
+// AbortedError()
+// AlreadyExistsError()
+// CancelledError()
+// DataLossError()
+// DeadlineExceededError()
+// FailedPreconditionError()
+// InternalError()
+// InvalidArgumentError()
+// NotFoundError()
+// OutOfRangeError()
+// PermissionDeniedError()
+// ResourceExhaustedError()
+// UnauthenticatedError()
+// UnavailableError()
+// UnimplementedError()
+// UnknownError()
+//
+// These convenience functions create an `absl::Status` object with an error
+// code as indicated by the associated function name, using the error message
+// passed in `message`.
+Status AbortedError(absl::string_view message);
+Status AlreadyExistsError(absl::string_view message);
+Status CancelledError(absl::string_view message);
+Status DataLossError(absl::string_view message);
+Status DeadlineExceededError(absl::string_view message);
+Status FailedPreconditionError(absl::string_view message);
+Status InternalError(absl::string_view message);
+Status InvalidArgumentError(absl::string_view message);
+Status NotFoundError(absl::string_view message);
+Status OutOfRangeError(absl::string_view message);
+Status PermissionDeniedError(absl::string_view message);
+Status ResourceExhaustedError(absl::string_view message);
+Status UnauthenticatedError(absl::string_view message);
+Status UnavailableError(absl::string_view message);
+Status UnimplementedError(absl::string_view message);
+Status UnknownError(absl::string_view message);
+
+//------------------------------------------------------------------------------
+// Implementation details follow
+//------------------------------------------------------------------------------
+
+inline Status::Status() : rep_(CodeToInlinedRep(absl::StatusCode::kOk)) {}
+
+inline Status::Status(absl::StatusCode code) : rep_(CodeToInlinedRep(code)) {}
+
+inline Status::Status(const Status& x) : rep_(x.rep_) { Ref(rep_); }
+
+inline Status& Status::operator=(const Status& x) {
+  uintptr_t old_rep = rep_;
+  if (x.rep_ != old_rep) {
+    Ref(x.rep_);
+    rep_ = x.rep_;
+    Unref(old_rep);
+  }
+  return *this;
+}
+
+inline Status::Status(Status&& x) noexcept : rep_(x.rep_) {
+  x.rep_ = MovedFromRep();
+}
+
+inline Status& Status::operator=(Status&& x) {
+  uintptr_t old_rep = rep_;
+  if (x.rep_ != old_rep) {
+    rep_ = x.rep_;
+    x.rep_ = MovedFromRep();
+    Unref(old_rep);
+  }
+  return *this;
+}
+
+inline void Status::Update(const Status& new_status) {
+  if (ok()) {
+    *this = new_status;
+  }
+}
+
+inline void Status::Update(Status&& new_status) {
+  if (ok()) {
+    *this = std::move(new_status);
+  }
+}
+
+inline Status::~Status() { Unref(rep_); }
+
+inline bool Status::ok() const {
+  return rep_ == CodeToInlinedRep(absl::StatusCode::kOk);
+}
+
+inline absl::string_view Status::message() const {
+  return !IsInlined(rep_)
+             ? RepToPointer(rep_)->message
+             : (IsMovedFrom(rep_) ? absl::string_view(kMovedFromString)
+                                  : absl::string_view());
+}
+
+inline bool operator==(const Status& lhs, const Status& rhs) {
+  return lhs.rep_ == rhs.rep_ || Status::EqualsSlow(lhs, rhs);
+}
+
+inline bool operator!=(const Status& lhs, const Status& rhs) {
+  return !(lhs == rhs);
+}
+
+inline std::string Status::ToString() const {
+  return ok() ? "OK" : ToStringSlow();
+}
+
+inline void Status::IgnoreError() const {
+  // no-op
+}
+
+inline void swap(absl::Status& a, absl::Status& b) {
+  using std::swap;
+  swap(a.rep_, b.rep_);
+}
+
+inline const status_internal::Payloads* Status::GetPayloads() const {
+  return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get();
+}
+
+inline status_internal::Payloads* Status::GetPayloads() {
+  return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get();
+}
+
+inline bool Status::IsInlined(uintptr_t rep) { return (rep & 1) == 0; }
+
+inline bool Status::IsMovedFrom(uintptr_t rep) {
+  return IsInlined(rep) && (rep & 2) != 0;
+}
+
+inline uintptr_t Status::MovedFromRep() {
+  return CodeToInlinedRep(absl::StatusCode::kInternal) | 2;
+}
+
+inline uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) {
+  return static_cast<uintptr_t>(code) << 2;
+}
+
+inline absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) {
+  assert(IsInlined(rep));
+  return static_cast<absl::StatusCode>(rep >> 2);
+}
+
+inline status_internal::StatusRep* Status::RepToPointer(uintptr_t rep) {
+  assert(!IsInlined(rep));
+  return reinterpret_cast<status_internal::StatusRep*>(rep - 1);
+}
+
+inline uintptr_t Status::PointerToRep(status_internal::StatusRep* rep) {
+  return reinterpret_cast<uintptr_t>(rep) + 1;
+}
+
+inline void Status::Ref(uintptr_t rep) {
+  if (!IsInlined(rep)) {
+    RepToPointer(rep)->ref.fetch_add(1, std::memory_order_relaxed);
+  }
+}
+
+inline void Status::Unref(uintptr_t rep) {
+  if (!IsInlined(rep)) {
+    UnrefNonInlined(rep);
+  }
+}
+
+inline Status OkStatus() { return Status(); }
+
+// Creates a `Status` object with the `absl::StatusCode::kCancelled` error code
+// and an empty message. It is provided only for efficiency, given that
+// message-less kCancelled errors are common in the infrastructure.
+inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); }
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STATUS_STATUS_H_
diff --git a/absl/status/status_payload_printer.cc b/absl/status/status_payload_printer.cc
new file mode 100644
index 0000000..a47aea1
--- /dev/null
+++ b/absl/status/status_payload_printer.cc
@@ -0,0 +1,38 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "absl/status/status_payload_printer.h"
+
+#include <atomic>
+
+#include "absl/base/attributes.h"
+#include "absl/base/internal/atomic_hook.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace status_internal {
+
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+static absl::base_internal::AtomicHook<StatusPayloadPrinter> storage;
+
+void SetStatusPayloadPrinter(StatusPayloadPrinter printer) {
+  storage.Store(printer);
+}
+
+StatusPayloadPrinter GetStatusPayloadPrinter() {
+  return storage.Load();
+}
+
+}  // namespace status_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/status/status_payload_printer.h b/absl/status/status_payload_printer.h
new file mode 100644
index 0000000..5e0937f
--- /dev/null
+++ b/absl/status/status_payload_printer.h
@@ -0,0 +1,51 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_
+#define ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_
+
+#include <string>
+
+#include "absl/strings/cord.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace status_internal {
+
+// By default, `Status::ToString` and `operator<<(Status)` print a payload by
+// dumping the type URL and the raw bytes. To help debugging, we provide an
+// extension point, which is a global printer function that can be set by users
+// to specify how to print payloads. The function takes the type URL and the
+// payload as input, and should return a valid human-readable string on success
+// or `absl::nullopt` on failure (in which case it falls back to the default
+// approach of printing the raw bytes).
+// NOTE: This is an internal API and the design is subject to change in the
+// future in a non-backward-compatible way. Since it's only meant for debugging
+// purpose, you should not rely on it in any critical logic.
+using StatusPayloadPrinter = absl::optional<std::string> (*)(absl::string_view,
+                                                             const absl::Cord&);
+
+// Sets the global payload printer. Only one printer should be set per process.
+// If multiple printers are set, it's undefined which one will be used.
+void SetStatusPayloadPrinter(StatusPayloadPrinter);
+
+// Returns the global payload printer if previously set, otherwise `nullptr`.
+StatusPayloadPrinter GetStatusPayloadPrinter();
+
+}  // namespace status_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_
diff --git a/absl/status/status_test.cc b/absl/status/status_test.cc
new file mode 100644
index 0000000..25333fa
--- /dev/null
+++ b/absl/status/status_test.cc
@@ -0,0 +1,464 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/status/status.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/strings/str_cat.h"
+
+namespace {
+
+using ::testing::Eq;
+using ::testing::HasSubstr;
+using ::testing::Optional;
+using ::testing::UnorderedElementsAreArray;
+
+TEST(StatusCode, InsertionOperator) {
+  const absl::StatusCode code = absl::StatusCode::kUnknown;
+  std::ostringstream oss;
+  oss << code;
+  EXPECT_EQ(oss.str(), absl::StatusCodeToString(code));
+}
+
+// This structure holds the details for testing a single error code,
+// its creator, and its classifier.
+struct ErrorTest {
+  absl::StatusCode code;
+  using Creator = absl::Status (*)(absl::string_view);
+  using Classifier = bool (*)(const absl::Status&);
+  Creator creator;
+  Classifier classifier;
+};
+
+constexpr ErrorTest kErrorTests[]{
+    {absl::StatusCode::kCancelled, absl::CancelledError, absl::IsCancelled},
+    {absl::StatusCode::kUnknown, absl::UnknownError, absl::IsUnknown},
+    {absl::StatusCode::kInvalidArgument, absl::InvalidArgumentError,
+     absl::IsInvalidArgument},
+    {absl::StatusCode::kDeadlineExceeded, absl::DeadlineExceededError,
+     absl::IsDeadlineExceeded},
+    {absl::StatusCode::kNotFound, absl::NotFoundError, absl::IsNotFound},
+    {absl::StatusCode::kAlreadyExists, absl::AlreadyExistsError,
+     absl::IsAlreadyExists},
+    {absl::StatusCode::kPermissionDenied, absl::PermissionDeniedError,
+     absl::IsPermissionDenied},
+    {absl::StatusCode::kResourceExhausted, absl::ResourceExhaustedError,
+     absl::IsResourceExhausted},
+    {absl::StatusCode::kFailedPrecondition, absl::FailedPreconditionError,
+     absl::IsFailedPrecondition},
+    {absl::StatusCode::kAborted, absl::AbortedError, absl::IsAborted},
+    {absl::StatusCode::kOutOfRange, absl::OutOfRangeError, absl::IsOutOfRange},
+    {absl::StatusCode::kUnimplemented, absl::UnimplementedError,
+     absl::IsUnimplemented},
+    {absl::StatusCode::kInternal, absl::InternalError, absl::IsInternal},
+    {absl::StatusCode::kUnavailable, absl::UnavailableError,
+     absl::IsUnavailable},
+    {absl::StatusCode::kDataLoss, absl::DataLossError, absl::IsDataLoss},
+    {absl::StatusCode::kUnauthenticated, absl::UnauthenticatedError,
+     absl::IsUnauthenticated},
+};
+
+TEST(Status, CreateAndClassify) {
+  for (const auto& test : kErrorTests) {
+    SCOPED_TRACE(absl::StatusCodeToString(test.code));
+
+    // Ensure that the creator does, in fact, create status objects with the
+    // expected error code and message.
+    std::string message =
+        absl::StrCat("error code ", test.code, " test message");
+    absl::Status status = test.creator(message);
+    EXPECT_EQ(test.code, status.code());
+    EXPECT_EQ(message, status.message());
+
+    // Ensure that the classifier returns true for a status produced by the
+    // creator.
+    EXPECT_TRUE(test.classifier(status));
+
+    // Ensure that the classifier returns false for status with a different
+    // code.
+    for (const auto& other : kErrorTests) {
+      if (other.code != test.code) {
+        EXPECT_FALSE(test.classifier(absl::Status(other.code, "")))
+            << " other.code = " << other.code;
+      }
+    }
+  }
+}
+
+TEST(Status, DefaultConstructor) {
+  absl::Status status;
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(absl::StatusCode::kOk, status.code());
+  EXPECT_EQ("", status.message());
+}
+
+TEST(Status, OkStatus) {
+  absl::Status status = absl::OkStatus();
+  EXPECT_TRUE(status.ok());
+  EXPECT_EQ(absl::StatusCode::kOk, status.code());
+  EXPECT_EQ("", status.message());
+}
+
+TEST(Status, ConstructorWithCodeMessage) {
+  {
+    absl::Status status(absl::StatusCode::kCancelled, "");
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kCancelled, status.code());
+    EXPECT_EQ("", status.message());
+  }
+  {
+    absl::Status status(absl::StatusCode::kInternal, "message");
+    EXPECT_FALSE(status.ok());
+    EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+    EXPECT_EQ("message", status.message());
+  }
+}
+
+TEST(Status, ConstructOutOfRangeCode) {
+  const int kRawCode = 9999;
+  absl::Status status(static_cast<absl::StatusCode>(kRawCode), "");
+  EXPECT_EQ(absl::StatusCode::kUnknown, status.code());
+  EXPECT_EQ(kRawCode, status.raw_code());
+}
+
+constexpr char kUrl1[] = "url.payload.1";
+constexpr char kUrl2[] = "url.payload.2";
+constexpr char kUrl3[] = "url.payload.3";
+constexpr char kUrl4[] = "url.payload.xx";
+
+constexpr char kPayload1[] = "aaaaa";
+constexpr char kPayload2[] = "bbbbb";
+constexpr char kPayload3[] = "ccccc";
+
+using PayloadsVec = std::vector<std::pair<std::string, absl::Cord>>;
+
+TEST(Status, TestGetSetPayload) {
+  absl::Status ok_status = absl::OkStatus();
+  ok_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+  ok_status.SetPayload(kUrl2, absl::Cord(kPayload2));
+
+  EXPECT_FALSE(ok_status.GetPayload(kUrl1));
+  EXPECT_FALSE(ok_status.GetPayload(kUrl2));
+
+  absl::Status bad_status(absl::StatusCode::kInternal, "fail");
+  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+  bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
+
+  EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload1)));
+  EXPECT_THAT(bad_status.GetPayload(kUrl2), Optional(Eq(kPayload2)));
+
+  EXPECT_FALSE(bad_status.GetPayload(kUrl3));
+
+  bad_status.SetPayload(kUrl1, absl::Cord(kPayload3));
+  EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload3)));
+
+  // Testing dynamically generated type_url
+  bad_status.SetPayload(absl::StrCat(kUrl1, ".1"), absl::Cord(kPayload1));
+  EXPECT_THAT(bad_status.GetPayload(absl::StrCat(kUrl1, ".1")),
+              Optional(Eq(kPayload1)));
+}
+
+TEST(Status, TestErasePayload) {
+  absl::Status bad_status(absl::StatusCode::kInternal, "fail");
+  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+  bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
+  bad_status.SetPayload(kUrl3, absl::Cord(kPayload3));
+
+  EXPECT_FALSE(bad_status.ErasePayload(kUrl4));
+
+  EXPECT_TRUE(bad_status.GetPayload(kUrl2));
+  EXPECT_TRUE(bad_status.ErasePayload(kUrl2));
+  EXPECT_FALSE(bad_status.GetPayload(kUrl2));
+  EXPECT_FALSE(bad_status.ErasePayload(kUrl2));
+
+  EXPECT_TRUE(bad_status.ErasePayload(kUrl1));
+  EXPECT_TRUE(bad_status.ErasePayload(kUrl3));
+
+  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+  EXPECT_TRUE(bad_status.ErasePayload(kUrl1));
+}
+
+TEST(Status, TestComparePayloads) {
+  absl::Status bad_status1(absl::StatusCode::kInternal, "fail");
+  bad_status1.SetPayload(kUrl1, absl::Cord(kPayload1));
+  bad_status1.SetPayload(kUrl2, absl::Cord(kPayload2));
+  bad_status1.SetPayload(kUrl3, absl::Cord(kPayload3));
+
+  absl::Status bad_status2(absl::StatusCode::kInternal, "fail");
+  bad_status2.SetPayload(kUrl2, absl::Cord(kPayload2));
+  bad_status2.SetPayload(kUrl3, absl::Cord(kPayload3));
+  bad_status2.SetPayload(kUrl1, absl::Cord(kPayload1));
+
+  EXPECT_EQ(bad_status1, bad_status2);
+}
+
+TEST(Status, TestComparePayloadsAfterErase) {
+  absl::Status payload_status(absl::StatusCode::kInternal, "");
+  payload_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+  payload_status.SetPayload(kUrl2, absl::Cord(kPayload2));
+
+  absl::Status empty_status(absl::StatusCode::kInternal, "");
+
+  // Different payloads, not equal
+  EXPECT_NE(payload_status, empty_status);
+  EXPECT_TRUE(payload_status.ErasePayload(kUrl1));
+
+  // Still Different payloads, still not equal.
+  EXPECT_NE(payload_status, empty_status);
+  EXPECT_TRUE(payload_status.ErasePayload(kUrl2));
+
+  // Both empty payloads, should be equal
+  EXPECT_EQ(payload_status, empty_status);
+}
+
+PayloadsVec AllVisitedPayloads(const absl::Status& s) {
+  PayloadsVec result;
+
+  s.ForEachPayload([&](absl::string_view type_url, const absl::Cord& payload) {
+    result.push_back(std::make_pair(std::string(type_url), payload));
+  });
+
+  return result;
+}
+
+TEST(Status, TestForEachPayload) {
+  absl::Status bad_status(absl::StatusCode::kInternal, "fail");
+  bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+  bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
+  bad_status.SetPayload(kUrl3, absl::Cord(kPayload3));
+
+  int count = 0;
+
+  bad_status.ForEachPayload(
+      [&count](absl::string_view, const absl::Cord&) { ++count; });
+
+  EXPECT_EQ(count, 3);
+
+  PayloadsVec expected_payloads = {{kUrl1, absl::Cord(kPayload1)},
+                                   {kUrl2, absl::Cord(kPayload2)},
+                                   {kUrl3, absl::Cord(kPayload3)}};
+
+  // Test that we visit all the payloads in the status.
+  PayloadsVec visited_payloads = AllVisitedPayloads(bad_status);
+  EXPECT_THAT(visited_payloads, UnorderedElementsAreArray(expected_payloads));
+
+  // Test that visitation order is not consistent between run.
+  std::vector<absl::Status> scratch;
+  while (true) {
+    scratch.emplace_back(absl::StatusCode::kInternal, "fail");
+
+    scratch.back().SetPayload(kUrl1, absl::Cord(kPayload1));
+    scratch.back().SetPayload(kUrl2, absl::Cord(kPayload2));
+    scratch.back().SetPayload(kUrl3, absl::Cord(kPayload3));
+
+    if (AllVisitedPayloads(scratch.back()) != visited_payloads) {
+      break;
+    }
+  }
+}
+
+TEST(Status, ToString) {
+  absl::Status s(absl::StatusCode::kInternal, "fail");
+  EXPECT_EQ("INTERNAL: fail", s.ToString());
+  s.SetPayload("foo", absl::Cord("bar"));
+  EXPECT_EQ("INTERNAL: fail [foo='bar']", s.ToString());
+  s.SetPayload("bar", absl::Cord("\377"));
+  EXPECT_THAT(s.ToString(),
+              AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+                    HasSubstr("[bar='\\xff']")));
+}
+
+absl::Status EraseAndReturn(const absl::Status& base) {
+  absl::Status copy = base;
+  EXPECT_TRUE(copy.ErasePayload(kUrl1));
+  return copy;
+}
+
+TEST(Status, CopyOnWriteForErasePayload) {
+  {
+    absl::Status base(absl::StatusCode::kInvalidArgument, "fail");
+    base.SetPayload(kUrl1, absl::Cord(kPayload1));
+    EXPECT_TRUE(base.GetPayload(kUrl1).has_value());
+    absl::Status copy = EraseAndReturn(base);
+    EXPECT_TRUE(base.GetPayload(kUrl1).has_value());
+    EXPECT_FALSE(copy.GetPayload(kUrl1).has_value());
+  }
+  {
+    absl::Status base(absl::StatusCode::kInvalidArgument, "fail");
+    base.SetPayload(kUrl1, absl::Cord(kPayload1));
+    absl::Status copy = base;
+
+    EXPECT_TRUE(base.GetPayload(kUrl1).has_value());
+    EXPECT_TRUE(copy.GetPayload(kUrl1).has_value());
+
+    EXPECT_TRUE(base.ErasePayload(kUrl1));
+
+    EXPECT_FALSE(base.GetPayload(kUrl1).has_value());
+    EXPECT_TRUE(copy.GetPayload(kUrl1).has_value());
+  }
+}
+
+TEST(Status, CopyConstructor) {
+  {
+    absl::Status status;
+    absl::Status copy(status);
+    EXPECT_EQ(copy, status);
+  }
+  {
+    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+    absl::Status copy(status);
+    EXPECT_EQ(copy, status);
+  }
+  {
+    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+    status.SetPayload(kUrl1, absl::Cord(kPayload1));
+    absl::Status copy(status);
+    EXPECT_EQ(copy, status);
+  }
+}
+
+TEST(Status, CopyAssignment) {
+  absl::Status assignee;
+  {
+    absl::Status status;
+    assignee = status;
+    EXPECT_EQ(assignee, status);
+  }
+  {
+    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+    assignee = status;
+    EXPECT_EQ(assignee, status);
+  }
+  {
+    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+    status.SetPayload(kUrl1, absl::Cord(kPayload1));
+    assignee = status;
+    EXPECT_EQ(assignee, status);
+  }
+}
+
+TEST(Status, CopyAssignmentIsNotRef) {
+  const absl::Status status_orig(absl::StatusCode::kInvalidArgument, "message");
+  absl::Status status_copy = status_orig;
+  EXPECT_EQ(status_orig, status_copy);
+  status_copy.SetPayload(kUrl1, absl::Cord(kPayload1));
+  EXPECT_NE(status_orig, status_copy);
+}
+
+TEST(Status, MoveConstructor) {
+  {
+    absl::Status status;
+    absl::Status copy(absl::Status{});
+    EXPECT_EQ(copy, status);
+  }
+  {
+    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+    absl::Status copy(
+        absl::Status(absl::StatusCode::kInvalidArgument, "message"));
+    EXPECT_EQ(copy, status);
+  }
+  {
+    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+    status.SetPayload(kUrl1, absl::Cord(kPayload1));
+    absl::Status copy1(status);
+    absl::Status copy2(std::move(status));
+    EXPECT_EQ(copy1, copy2);
+  }
+}
+
+TEST(Status, MoveAssignment) {
+  absl::Status assignee;
+  {
+    absl::Status status;
+    assignee = absl::Status();
+    EXPECT_EQ(assignee, status);
+  }
+  {
+    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+    assignee = absl::Status(absl::StatusCode::kInvalidArgument, "message");
+    EXPECT_EQ(assignee, status);
+  }
+  {
+    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+    status.SetPayload(kUrl1, absl::Cord(kPayload1));
+    absl::Status copy(status);
+    assignee = std::move(status);
+    EXPECT_EQ(assignee, copy);
+  }
+  {
+    absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+    absl::Status copy(status);
+    status = static_cast<absl::Status&&>(status);
+    EXPECT_EQ(status, copy);
+  }
+}
+
+TEST(Status, Update) {
+  absl::Status s;
+  s.Update(absl::OkStatus());
+  EXPECT_TRUE(s.ok());
+  const absl::Status a(absl::StatusCode::kCancelled, "message");
+  s.Update(a);
+  EXPECT_EQ(s, a);
+  const absl::Status b(absl::StatusCode::kInternal, "other message");
+  s.Update(b);
+  EXPECT_EQ(s, a);
+  s.Update(absl::OkStatus());
+  EXPECT_EQ(s, a);
+  EXPECT_FALSE(s.ok());
+}
+
+TEST(Status, Equality) {
+  absl::Status ok;
+  absl::Status no_payload = absl::CancelledError("no payload");
+  absl::Status one_payload = absl::InvalidArgumentError("one payload");
+  one_payload.SetPayload(kUrl1, absl::Cord(kPayload1));
+  absl::Status two_payloads = one_payload;
+  two_payloads.SetPayload(kUrl2, absl::Cord(kPayload2));
+  const std::array<absl::Status, 4> status_arr = {ok, no_payload, one_payload,
+                                                  two_payloads};
+  for (int i = 0; i < status_arr.size(); i++) {
+    for (int j = 0; j < status_arr.size(); j++) {
+      if (i == j) {
+        EXPECT_TRUE(status_arr[i] == status_arr[j]);
+        EXPECT_FALSE(status_arr[i] != status_arr[j]);
+      } else {
+        EXPECT_TRUE(status_arr[i] != status_arr[j]);
+        EXPECT_FALSE(status_arr[i] == status_arr[j]);
+      }
+    }
+  }
+}
+
+TEST(Status, Swap) {
+  auto test_swap = [](const absl::Status& s1, const absl::Status& s2) {
+    absl::Status copy1 = s1, copy2 = s2;
+    swap(copy1, copy2);
+    EXPECT_EQ(copy1, s2);
+    EXPECT_EQ(copy2, s1);
+  };
+  const absl::Status ok;
+  const absl::Status no_payload(absl::StatusCode::kAlreadyExists, "no payload");
+  absl::Status with_payload(absl::StatusCode::kInternal, "with payload");
+  with_payload.SetPayload(kUrl1, absl::Cord(kPayload1));
+  test_swap(ok, no_payload);
+  test_swap(no_payload, ok);
+  test_swap(ok, with_payload);
+  test_swap(with_payload, ok);
+  test_swap(no_payload, with_payload);
+  test_swap(with_payload, no_payload);
+}
+
+}  // namespace
diff --git a/absl/status/statusor.cc b/absl/status/statusor.cc
new file mode 100644
index 0000000..b954b45
--- /dev/null
+++ b/absl/status/statusor.cc
@@ -0,0 +1,71 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "absl/status/statusor.h"
+
+#include <cstdlib>
+#include <utility>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/status/status.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+BadStatusOrAccess::BadStatusOrAccess(absl::Status status)
+    : status_(std::move(status)) {}
+
+BadStatusOrAccess::~BadStatusOrAccess() = default;
+const char* BadStatusOrAccess::what() const noexcept {
+  return "Bad StatusOr access";
+}
+
+const absl::Status& BadStatusOrAccess::status() const { return status_; }
+
+namespace internal_statusor {
+
+void Helper::HandleInvalidStatusCtorArg(absl::Status* status) {
+  const char* kMessage =
+      "An OK status is not a valid constructor argument to StatusOr<T>";
+#ifdef NDEBUG
+  ABSL_INTERNAL_LOG(ERROR, kMessage);
+#else
+  ABSL_INTERNAL_LOG(FATAL, kMessage);
+#endif
+  // In optimized builds, we will fall back to InternalError.
+  *status = absl::InternalError(kMessage);
+}
+
+void Helper::Crash(const absl::Status& status) {
+  ABSL_INTERNAL_LOG(
+      FATAL,
+      absl::StrCat("Attempting to fetch value instead of handling error ",
+                   status.ToString()));
+}
+
+void ThrowBadStatusOrAccess(absl::Status status) {
+#ifdef ABSL_HAVE_EXCEPTIONS
+  throw absl::BadStatusOrAccess(std::move(status));
+#else
+  ABSL_INTERNAL_LOG(
+      FATAL,
+      absl::StrCat("Attempting to fetch value instead of handling error ",
+                   status.ToString()));
+  std::abort();
+#endif
+}
+
+}  // namespace internal_statusor
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/status/statusor.h b/absl/status/statusor.h
new file mode 100644
index 0000000..469d486
--- /dev/null
+++ b/absl/status/statusor.h
@@ -0,0 +1,760 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: statusor.h
+// -----------------------------------------------------------------------------
+//
+// An `absl::StatusOr<T>` represents a union of an `absl::Status` object
+// and an object of type `T`. The `absl::StatusOr<T>` will either contain an
+// object of type `T` (indicating a successful operation), or an error (of type
+// `absl::Status`) explaining why such a value is not present.
+//
+// In general, check the success of an operation returning an
+// `absl::StatusOr<T>` like you would an `absl::Status` by using the `ok()`
+// member function.
+//
+// Example:
+//
+//   StatusOr<Foo> result = Calculation();
+//   if (result.ok()) {
+//     result->DoSomethingCool();
+//   } else {
+//     LOG(ERROR) << result.status();
+//   }
+#ifndef ABSL_STATUS_STATUSOR_H_
+#define ABSL_STATUS_STATUSOR_H_
+
+#include <exception>
+#include <initializer_list>
+#include <new>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/meta/type_traits.h"
+#include "absl/status/internal/statusor_internal.h"
+#include "absl/status/status.h"
+#include "absl/types/variant.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// BadStatusOrAccess
+//
+// This class defines the type of object to throw (if exceptions are enabled),
+// when accessing the value of an `absl::StatusOr<T>` object that does not
+// contain a value. This behavior is analogous to that of
+// `std::bad_optional_access` in the case of accessing an invalid
+// `std::optional` value.
+//
+// Example:
+//
+// try {
+//   absl::StatusOr<int> v = FetchInt();
+//   DoWork(v.value());  // Accessing value() when not "OK" may throw
+// } catch (absl::BadStatusOrAccess& ex) {
+//   LOG(ERROR) << ex.status();
+// }
+class BadStatusOrAccess : public std::exception {
+ public:
+  explicit BadStatusOrAccess(absl::Status status);
+  ~BadStatusOrAccess() override;
+
+  // BadStatusOrAccess::what()
+  //
+  // Returns the associated explanatory string of the `absl::StatusOr<T>`
+  // object's error code. This function only returns the string literal "Bad
+  // StatusOr Access" for cases when evaluating general exceptions.
+  //
+  // The pointer of this string is guaranteed to be valid until any non-const
+  // function is invoked on the exception object.
+  const char* what() const noexcept override;
+
+  // BadStatusOrAccess::status()
+  //
+  // Returns the associated `absl::Status` of the `absl::StatusOr<T>` object's
+  // error.
+  const absl::Status& status() const;
+
+ private:
+  absl::Status status_;
+};
+
+// Returned StatusOr objects may not be ignored.
+template <typename T>
+class ABSL_MUST_USE_RESULT StatusOr;
+
+// absl::StatusOr<T>
+//
+// The `absl::StatusOr<T>` class template is a union of an `absl::Status` object
+// and an object of type `T`. The `absl::StatusOr<T>` models an object that is
+// either a usable object, or an error (of type `absl::Status`) explaining why
+// such an object is not present. An `absl::StatusOr<T>` is typically the return
+// value of a function which may fail.
+//
+// An `absl::StatusOr<T>` can never hold an "OK" status (an
+// `absl::StatusCode::kOk` value); instead, the presence of an object of type
+// `T` indicates success. Instead of checking for a `kOk` value, use the
+// `absl::StatusOr<T>::ok()` member function. (It is for this reason, and code
+// readability, that using the `ok()` function is preferred for `absl::Status`
+// as well.)
+//
+// Example:
+//
+//   StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+//   if (result.ok()) {
+//     result->DoSomethingCool();
+//   } else {
+//     LOG(ERROR) << result.status();
+//   }
+//
+// Accessing the object held by an `absl::StatusOr<T>` should be performed via
+// `operator*` or `operator->`, after a call to `ok()` confirms that the
+// `absl::StatusOr<T>` holds an object of type `T`:
+//
+// Example:
+//
+//   absl::StatusOr<int> i = GetCount();
+//   if (i.ok()) {
+//     updated_total += *i
+//   }
+//
+// NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will
+// throw an exception if exceptions are enabled or terminate the process when
+// execeptions are not enabled.
+//
+// Example:
+//
+//   StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+//   const Foo& foo = result.value();    // Crash/exception if no value present
+//   foo.DoSomethingCool();
+//
+// A `absl::StatusOr<T*>` can be constructed from a null pointer like any other
+// pointer value, and the result will be that `ok()` returns `true` and
+// `value()` returns `nullptr`. Checking the value of pointer in an
+// `absl::StatusOr<T>` generally requires a bit more care, to ensure both that a
+// value is present and that value is not null:
+//
+//  StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
+//  if (!result.ok()) {
+//    LOG(ERROR) << result.status();
+//  } else if (*result == nullptr) {
+//    LOG(ERROR) << "Unexpected null pointer";
+//  } else {
+//    (*result)->DoSomethingCool();
+//  }
+//
+// Example factory implementation returning StatusOr<T>:
+//
+//  StatusOr<Foo> FooFactory::MakeFoo(int arg) {
+//    if (arg <= 0) {
+//      return absl::Status(absl::StatusCode::kInvalidArgument,
+//                          "Arg must be positive");
+//    }
+//    return Foo(arg);
+//  }
+template <typename T>
+class StatusOr : private internal_statusor::StatusOrData<T>,
+                 private internal_statusor::CopyCtorBase<T>,
+                 private internal_statusor::MoveCtorBase<T>,
+                 private internal_statusor::CopyAssignBase<T>,
+                 private internal_statusor::MoveAssignBase<T> {
+  template <typename U>
+  friend class StatusOr;
+
+  typedef internal_statusor::StatusOrData<T> Base;
+
+ public:
+  // StatusOr<T>::value_type
+  //
+  // This instance data provides a generic `value_type` member for use within
+  // generic programming. This usage is analogous to that of
+  // `optional::value_type` in the case of `std::optional`.
+  typedef T value_type;
+
+  // Constructors
+
+  // Constructs a new `absl::StatusOr` with an `absl::StatusCode::kUnknown`
+  // status. This constructor is marked 'explicit' to prevent usages in return
+  // values such as 'return {};', under the misconception that
+  // `absl::StatusOr<std::vector<int>>` will be initialized with an empty
+  // vector, instead of an `absl::StatusCode::kUnknown` error code.
+  explicit StatusOr();
+
+  // `StatusOr<T>` is copy constructible if `T` is copy constructible.
+  StatusOr(const StatusOr&) = default;
+  // `StatusOr<T>` is copy assignable if `T` is copy constructible and copy
+  // assignable.
+  StatusOr& operator=(const StatusOr&) = default;
+
+  // `StatusOr<T>` is move constructible if `T` is move constructible.
+  StatusOr(StatusOr&&) = default;
+  // `StatusOr<T>` is moveAssignable if `T` is move constructible and move
+  // assignable.
+  StatusOr& operator=(StatusOr&&) = default;
+
+  // Converting Constructors
+
+  // Constructs a new `absl::StatusOr<T>` from an `absl::StatusOr<U>`, when `T`
+  // is constructible from `U`. To avoid ambiguity, these constructors are
+  // disabled if `T` is also constructible from `StatusOr<U>.`. This constructor
+  // is explicit if and only if the corresponding construction of `T` from `U`
+  // is explicit. (This constructor inherits its explicitness from the
+  // underlying constructor.)
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>,
+              std::is_constructible<T, const U&>,
+              std::is_convertible<const U&, T>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  StatusOr(const StatusOr<U>& other)  // NOLINT
+      : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>,
+              std::is_constructible<T, const U&>,
+              absl::negation<std::is_convertible<const U&, T>>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  explicit StatusOr(const StatusOr<U>& other)
+      : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
+
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+              std::is_convertible<U&&, T>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  StatusOr(StatusOr<U>&& other)  // NOLINT
+      : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+              absl::negation<std::is_convertible<U&&, T>>,
+              absl::negation<
+                  internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+                      T, U>>>::value,
+          int> = 0>
+  explicit StatusOr(StatusOr<U>&& other)
+      : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
+
+  // Converting Assignment Operators
+
+  // Creates an `absl::StatusOr<T>` through assignment from an
+  // `absl::StatusOr<U>` when:
+  //
+  //   * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` are OK by assigning
+  //     `U` to `T` directly.
+  //   * `absl::StatusOr<T>` is OK and `absl::StatusOr<U>` contains an error
+  //      code by destroying `absl::StatusOr<T>`'s value and assigning from
+  //      `absl::StatusOr<U>'
+  //   * `absl::StatusOr<T>` contains an error code and `absl::StatusOr<U>` is
+  //      OK by directly initializing `T` from `U`.
+  //   * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` contain an error
+  //     code by assigning the `Status` in `absl::StatusOr<U>` to
+  //     `absl::StatusOr<T>`
+  //
+  // These overloads only apply if `absl::StatusOr<T>` is constructible and
+  // assignable from `absl::StatusOr<U>` and `StatusOr<T>` cannot be directly
+  // assigned from `StatusOr<U>`.
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>,
+              std::is_constructible<T, const U&>,
+              std::is_assignable<T, const U&>,
+              absl::negation<
+                  internal_statusor::
+                      IsConstructibleOrConvertibleOrAssignableFromStatusOr<
+                          T, U>>>::value,
+          int> = 0>
+  StatusOr& operator=(const StatusOr<U>& other) {
+    this->Assign(other);
+    return *this;
+  }
+  template <
+      typename U,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+              std::is_assignable<T, U&&>,
+              absl::negation<
+                  internal_statusor::
+                      IsConstructibleOrConvertibleOrAssignableFromStatusOr<
+                          T, U>>>::value,
+          int> = 0>
+  StatusOr& operator=(StatusOr<U>&& other) {
+    this->Assign(std::move(other));
+    return *this;
+  }
+
+  // Constructs a new `absl::StatusOr<T>` with a non-ok status. After calling
+  // this constructor, `this->ok()` will be `false` and calls to `value()` will
+  // crash, or produce an exception if exceptions are enabled.
+  //
+  // The constructor also takes any type `U` that is convertible to
+  // `absl::Status`. This constructor is explicit if an only if `U` is not of
+  // type `absl::Status` and the conversion from `U` to `Status` is explicit.
+  //
+  // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed.
+  // In optimized builds, passing absl::OkStatus() here will have the effect
+  // of passing absl::StatusCode::kInternal as a fallback.
+  template <
+      typename U = absl::Status,
+      absl::enable_if_t<
+          absl::conjunction<
+              std::is_convertible<U&&, absl::Status>,
+              std::is_constructible<absl::Status, U&&>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+              absl::negation<std::is_same<absl::decay_t<U>, T>>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+              absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+                  T, U&&>>>::value,
+          int> = 0>
+  StatusOr(U&& v) : Base(std::forward<U>(v)) {}
+
+  template <
+      typename U = absl::Status,
+      absl::enable_if_t<
+          absl::conjunction<
+              absl::negation<std::is_convertible<U&&, absl::Status>>,
+              std::is_constructible<absl::Status, U&&>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+              absl::negation<std::is_same<absl::decay_t<U>, T>>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+              absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+                  T, U&&>>>::value,
+          int> = 0>
+  explicit StatusOr(U&& v) : Base(std::forward<U>(v)) {}
+
+  template <
+      typename U = absl::Status,
+      absl::enable_if_t<
+          absl::conjunction<
+              std::is_convertible<U&&, absl::Status>,
+              std::is_constructible<absl::Status, U&&>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+              absl::negation<std::is_same<absl::decay_t<U>, T>>,
+              absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+              absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+                  T, U&&>>>::value,
+          int> = 0>
+  StatusOr& operator=(U&& v) {
+    this->AssignStatus(std::forward<U>(v));
+    return *this;
+  }
+
+  // Perfect-forwarding value assignment operator.
+
+  // If `*this` contains a `T` value before the call, the contained value is
+  // assigned from `std::forward<U>(v)`; Otherwise, it is directly-initialized
+  // from `std::forward<U>(v)`.
+  // This function does not participate in overload unless:
+  // 1. `std::is_constructible_v<T, U>` is true,
+  // 2. `std::is_assignable_v<T&, U>` is true.
+  // 3. `std::is_same_v<StatusOr<T>, std::remove_cvref_t<U>>` is false.
+  // 4. Assigning `U` to `T` is not ambiguous:
+  //  If `U` is `StatusOr<V>` and `T` is constructible and assignable from
+  //  both `StatusOr<V>` and `V`, the assignment is considered bug-prone and
+  //  ambiguous thus will fail to compile. For example:
+  //    StatusOr<bool> s1 = true;  // s1.ok() && *s1 == true
+  //    StatusOr<bool> s2 = false;  // s2.ok() && *s2 == false
+  //    s1 = s2;  // ambiguous, `s1 = *s2` or `s1 = bool(s2)`?
+  template <
+      typename U = T,
+      typename = typename std::enable_if<absl::conjunction<
+          std::is_constructible<T, U&&>, std::is_assignable<T&, U&&>,
+          absl::disjunction<
+              std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, T>,
+              absl::conjunction<
+                  absl::negation<std::is_convertible<U&&, absl::Status>>,
+                  absl::negation<internal_statusor::
+                                     HasConversionOperatorToStatusOr<T, U&&>>>>,
+          internal_statusor::IsForwardingAssignmentValid<T, U&&>>::value>::type>
+  StatusOr& operator=(U&& v) {
+    this->Assign(std::forward<U>(v));
+    return *this;
+  }
+
+  // Constructs the inner value `T` in-place using the provided args, using the
+  // `T(args...)` constructor.
+  template <typename... Args>
+  explicit StatusOr(absl::in_place_t, Args&&... args);
+  template <typename U, typename... Args>
+  explicit StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
+                    Args&&... args);
+
+  // Constructs the inner value `T` in-place using the provided args, using the
+  // `T(U)` (direct-initialization) constructor. This constructor is only valid
+  // if `T` can be constructed from a `U`. Can accept move or copy constructors.
+  //
+  // This constructor is explicit if `U` is not convertible to `T`. To avoid
+  // ambiguity, this constuctor is disabled if `U` is a `StatusOr<J>`, where `J`
+  // is convertible to `T`.
+  template <
+      typename U = T,
+      absl::enable_if_t<
+          absl::conjunction<
+              internal_statusor::IsDirectInitializationValid<T, U&&>,
+              std::is_constructible<T, U&&>, std::is_convertible<U&&, T>,
+              absl::disjunction<
+                  std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                               T>,
+                  absl::conjunction<
+                      absl::negation<std::is_convertible<U&&, absl::Status>>,
+                      absl::negation<
+                          internal_statusor::HasConversionOperatorToStatusOr<
+                              T, U&&>>>>>::value,
+          int> = 0>
+  StatusOr(U&& u)  // NOLINT
+      : StatusOr(absl::in_place, std::forward<U>(u)) {
+  }
+
+  template <
+      typename U = T,
+      absl::enable_if_t<
+          absl::conjunction<
+              internal_statusor::IsDirectInitializationValid<T, U&&>,
+              absl::disjunction<
+                  std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+                               T>,
+                  absl::conjunction<
+                      absl::negation<std::is_constructible<absl::Status, U&&>>,
+                      absl::negation<
+                          internal_statusor::HasConversionOperatorToStatusOr<
+                              T, U&&>>>>,
+              std::is_constructible<T, U&&>,
+              absl::negation<std::is_convertible<U&&, T>>>::value,
+          int> = 0>
+  explicit StatusOr(U&& u)  // NOLINT
+      : StatusOr(absl::in_place, std::forward<U>(u)) {
+  }
+
+  // StatusOr<T>::ok()
+  //
+  // Returns whether or not this `absl::StatusOr<T>` holds a `T` value. This
+  // member function is analagous to `absl::Status::ok()` and should be used
+  // similarly to check the status of return values.
+  //
+  // Example:
+  //
+  // StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+  // if (result.ok()) {
+  //    // Handle result
+  // else {
+  //    // Handle error
+  // }
+  ABSL_MUST_USE_RESULT bool ok() const { return this->status_.ok(); }
+
+  // StatusOr<T>::status()
+  //
+  // Returns a reference to the current `absl::Status` contained within the
+  // `absl::StatusOr<T>`. If `absl::StatusOr<T>` contains a `T`, then this
+  // function returns `absl::OkStatus()`.
+  const Status& status() const &;
+  Status status() &&;
+
+  // StatusOr<T>::value()
+  //
+  // Returns a reference to the held value if `this->ok()`. Otherwise, throws
+  // `absl::BadStatusOrAccess` if exceptions are enabled, or is guaranteed to
+  // terminate the process if exceptions are disabled.
+  //
+  // If you have already checked the status using `this->ok()`, you probably
+  // want to use `operator*()` or `operator->()` to access the value instead of
+  // `value`.
+  //
+  // Note: for value types that are cheap to copy, prefer simple code:
+  //
+  //   T value = statusor.value();
+  //
+  // Otherwise, if the value type is expensive to copy, but can be left
+  // in the StatusOr, simply assign to a reference:
+  //
+  //   T& value = statusor.value();  // or `const T&`
+  //
+  // Otherwise, if the value type supports an efficient move, it can be
+  // used as follows:
+  //
+  //   T value = std::move(statusor).value();
+  //
+  // The `std::move` on statusor instead of on the whole expression enables
+  // warnings about possible uses of the statusor object after the move.
+  const T& value() const&;
+  T& value() &;
+  const T&& value() const&&;
+  T&& value() &&;
+
+  // StatusOr<T>:: operator*()
+  //
+  // Returns a reference to the current value.
+  //
+  // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
+  //
+  // Use `this->ok()` to verify that there is a current value within the
+  // `absl::StatusOr<T>`. Alternatively, see the `value()` member function for a
+  // similar API that guarantees crashing or throwing an exception if there is
+  // no current value.
+  const T& operator*() const&;
+  T& operator*() &;
+  const T&& operator*() const&&;
+  T&& operator*() &&;
+
+  // StatusOr<T>::operator->()
+  //
+  // Returns a pointer to the current value.
+  //
+  // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
+  //
+  // Use `this->ok()` to verify that there is a current value.
+  const T* operator->() const;
+  T* operator->();
+
+  // StatusOr<T>::value_or()
+  //
+  // Returns the current value if `this->ok() == true`. Otherwise constructs a
+  // value using the provided `default_value`.
+  //
+  // Unlike `value`, this function returns by value, copying the current value
+  // if necessary. If the value type supports an efficient move, it can be used
+  // as follows:
+  //
+  //   T value = std::move(statusor).value_or(def);
+  //
+  // Unlike with `value`, calling `std::move()` on the result of `value_or` will
+  // still trigger a copy.
+  template <typename U>
+  T value_or(U&& default_value) const&;
+  template <typename U>
+  T value_or(U&& default_value) &&;
+
+  // StatusOr<T>::IgnoreError()
+  //
+  // Ignores any errors. This method does nothing except potentially suppress
+  // complaints from any tools that are checking that errors are not dropped on
+  // the floor.
+  void IgnoreError() const;
+
+  // StatusOr<T>::emplace()
+  //
+  // Reconstructs the inner value T in-place using the provided args, using the
+  // T(args...) constructor. Returns reference to the reconstructed `T`.
+  template <typename... Args>
+  T& emplace(Args&&... args) {
+    if (ok()) {
+      this->Clear();
+      this->MakeValue(std::forward<Args>(args)...);
+    } else {
+      this->MakeValue(std::forward<Args>(args)...);
+      this->status_ = absl::OkStatus();
+    }
+    return this->data_;
+  }
+
+  template <
+      typename U, typename... Args,
+      absl::enable_if_t<
+          std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
+          int> = 0>
+  T& emplace(std::initializer_list<U> ilist, Args&&... args) {
+    if (ok()) {
+      this->Clear();
+      this->MakeValue(ilist, std::forward<Args>(args)...);
+    } else {
+      this->MakeValue(ilist, std::forward<Args>(args)...);
+      this->status_ = absl::OkStatus();
+    }
+    return this->data_;
+  }
+
+ private:
+  using internal_statusor::StatusOrData<T>::Assign;
+  template <typename U>
+  void Assign(const absl::StatusOr<U>& other);
+  template <typename U>
+  void Assign(absl::StatusOr<U>&& other);
+};
+
+// operator==()
+//
+// This operator checks the equality of two `absl::StatusOr<T>` objects.
+template <typename T>
+bool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
+  if (lhs.ok() && rhs.ok()) return *lhs == *rhs;
+  return lhs.status() == rhs.status();
+}
+
+// operator!=()
+//
+// This operator checks the inequality of two `absl::StatusOr<T>` objects.
+template <typename T>
+bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
+  return !(lhs == rhs);
+}
+
+//------------------------------------------------------------------------------
+// Implementation details for StatusOr<T>
+//------------------------------------------------------------------------------
+
+// TODO(sbenza): avoid the string here completely.
+template <typename T>
+StatusOr<T>::StatusOr() : Base(Status(absl::StatusCode::kUnknown, "")) {}
+
+template <typename T>
+template <typename U>
+inline void StatusOr<T>::Assign(const StatusOr<U>& other) {
+  if (other.ok()) {
+    this->Assign(*other);
+  } else {
+    this->AssignStatus(other.status());
+  }
+}
+
+template <typename T>
+template <typename U>
+inline void StatusOr<T>::Assign(StatusOr<U>&& other) {
+  if (other.ok()) {
+    this->Assign(*std::move(other));
+  } else {
+    this->AssignStatus(std::move(other).status());
+  }
+}
+template <typename T>
+template <typename... Args>
+StatusOr<T>::StatusOr(absl::in_place_t, Args&&... args)
+    : Base(absl::in_place, std::forward<Args>(args)...) {}
+
+template <typename T>
+template <typename U, typename... Args>
+StatusOr<T>::StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
+                      Args&&... args)
+    : Base(absl::in_place, ilist, std::forward<Args>(args)...) {}
+
+template <typename T>
+const Status& StatusOr<T>::status() const & { return this->status_; }
+template <typename T>
+Status StatusOr<T>::status() && {
+  return ok() ? OkStatus() : std::move(this->status_);
+}
+
+template <typename T>
+const T& StatusOr<T>::value() const& {
+  if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
+  return this->data_;
+}
+
+template <typename T>
+T& StatusOr<T>::value() & {
+  if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
+  return this->data_;
+}
+
+template <typename T>
+const T&& StatusOr<T>::value() const&& {
+  if (!this->ok()) {
+    internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
+  }
+  return std::move(this->data_);
+}
+
+template <typename T>
+T&& StatusOr<T>::value() && {
+  if (!this->ok()) {
+    internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
+  }
+  return std::move(this->data_);
+}
+
+template <typename T>
+const T& StatusOr<T>::operator*() const& {
+  this->EnsureOk();
+  return this->data_;
+}
+
+template <typename T>
+T& StatusOr<T>::operator*() & {
+  this->EnsureOk();
+  return this->data_;
+}
+
+template <typename T>
+const T&& StatusOr<T>::operator*() const&& {
+  this->EnsureOk();
+  return std::move(this->data_);
+}
+
+template <typename T>
+T&& StatusOr<T>::operator*() && {
+  this->EnsureOk();
+  return std::move(this->data_);
+}
+
+template <typename T>
+const T* StatusOr<T>::operator->() const {
+  this->EnsureOk();
+  return &this->data_;
+}
+
+template <typename T>
+T* StatusOr<T>::operator->() {
+  this->EnsureOk();
+  return &this->data_;
+}
+
+template <typename T>
+template <typename U>
+T StatusOr<T>::value_or(U&& default_value) const& {
+  if (ok()) {
+    return this->data_;
+  }
+  return std::forward<U>(default_value);
+}
+
+template <typename T>
+template <typename U>
+T StatusOr<T>::value_or(U&& default_value) && {
+  if (ok()) {
+    return std::move(this->data_);
+  }
+  return std::forward<U>(default_value);
+}
+
+template <typename T>
+void StatusOr<T>::IgnoreError() const {
+  // no-op
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STATUS_STATUSOR_H_
diff --git a/absl/status/statusor_test.cc b/absl/status/statusor_test.cc
new file mode 100644
index 0000000..c2e8fb7
--- /dev/null
+++ b/absl/status/statusor_test.cc
@@ -0,0 +1,1811 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/status/statusor.h"
+
+#include <array>
+#include <initializer_list>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/casts.h"
+#include "absl/memory/memory.h"
+#include "absl/status/status.h"
+#include "absl/types/any.h"
+#include "absl/utility/utility.h"
+
+namespace {
+
+using ::testing::AllOf;
+using ::testing::AnyWith;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::Ne;
+using ::testing::Not;
+using ::testing::Pointee;
+using ::testing::VariantWith;
+
+#ifdef GTEST_HAS_STATUS_MATCHERS
+using ::testing::status::IsOk;
+using ::testing::status::IsOkAndHolds;
+#else  // GTEST_HAS_STATUS_MATCHERS
+inline const ::absl::Status& GetStatus(const ::absl::Status& status) {
+  return status;
+}
+
+template <typename T>
+inline const ::absl::Status& GetStatus(const ::absl::StatusOr<T>& status) {
+  return status.status();
+}
+
+// Monomorphic implementation of matcher IsOkAndHolds(m).  StatusOrType is a
+// reference to StatusOr<T>.
+template <typename StatusOrType>
+class IsOkAndHoldsMatcherImpl
+    : public ::testing::MatcherInterface<StatusOrType> {
+ public:
+  typedef
+      typename std::remove_reference<StatusOrType>::type::value_type value_type;
+
+  template <typename InnerMatcher>
+  explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher)
+      : inner_matcher_(::testing::SafeMatcherCast<const value_type&>(
+            std::forward<InnerMatcher>(inner_matcher))) {}
+
+  void DescribeTo(std::ostream* os) const override {
+    *os << "is OK and has a value that ";
+    inner_matcher_.DescribeTo(os);
+  }
+
+  void DescribeNegationTo(std::ostream* os) const override {
+    *os << "isn't OK or has a value that ";
+    inner_matcher_.DescribeNegationTo(os);
+  }
+
+  bool MatchAndExplain(
+      StatusOrType actual_value,
+      ::testing::MatchResultListener* result_listener) const override {
+    if (!actual_value.ok()) {
+      *result_listener << "which has status " << actual_value.status();
+      return false;
+    }
+
+    ::testing::StringMatchResultListener inner_listener;
+    const bool matches =
+        inner_matcher_.MatchAndExplain(*actual_value, &inner_listener);
+    const std::string inner_explanation = inner_listener.str();
+    if (!inner_explanation.empty()) {
+      *result_listener << "which contains value "
+                       << ::testing::PrintToString(*actual_value) << ", "
+                       << inner_explanation;
+    }
+    return matches;
+  }
+
+ private:
+  const ::testing::Matcher<const value_type&> inner_matcher_;
+};
+
+// Implements IsOkAndHolds(m) as a polymorphic matcher.
+template <typename InnerMatcher>
+class IsOkAndHoldsMatcher {
+ public:
+  explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher)
+      : inner_matcher_(std::move(inner_matcher)) {}
+
+  // Converts this polymorphic matcher to a monomorphic matcher of the
+  // given type.  StatusOrType can be either StatusOr<T> or a
+  // reference to StatusOr<T>.
+  template <typename StatusOrType>
+  operator ::testing::Matcher<StatusOrType>() const {  // NOLINT
+    return ::testing::Matcher<StatusOrType>(
+        new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_));
+  }
+
+ private:
+  const InnerMatcher inner_matcher_;
+};
+
+// Monomorphic implementation of matcher IsOk() for a given type T.
+// T can be Status, StatusOr<>, or a reference to either of them.
+template <typename T>
+class MonoIsOkMatcherImpl : public ::testing::MatcherInterface<T> {
+ public:
+  void DescribeTo(std::ostream* os) const override { *os << "is OK"; }
+  void DescribeNegationTo(std::ostream* os) const override {
+    *os << "is not OK";
+  }
+  bool MatchAndExplain(T actual_value,
+                       ::testing::MatchResultListener*) const override {
+    return GetStatus(actual_value).ok();
+  }
+};
+
+// Implements IsOk() as a polymorphic matcher.
+class IsOkMatcher {
+ public:
+  template <typename T>
+  operator ::testing::Matcher<T>() const {  // NOLINT
+    return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<T>());
+  }
+};
+
+// Macros for testing the results of functions that return absl::Status or
+// absl::StatusOr<T> (for any type T).
+#define EXPECT_OK(expression) EXPECT_THAT(expression, IsOk())
+
+// Returns a gMock matcher that matches a StatusOr<> whose status is
+// OK and whose value matches the inner matcher.
+template <typename InnerMatcher>
+IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type> IsOkAndHolds(
+    InnerMatcher&& inner_matcher) {
+  return IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>(
+      std::forward<InnerMatcher>(inner_matcher));
+}
+
+// Returns a gMock matcher that matches a Status or StatusOr<> which is OK.
+inline IsOkMatcher IsOk() { return IsOkMatcher(); }
+#endif  // GTEST_HAS_STATUS_MATCHERS
+
+struct CopyDetector {
+  CopyDetector() = default;
+  explicit CopyDetector(int xx) : x(xx) {}
+  CopyDetector(CopyDetector&& d) noexcept
+      : x(d.x), copied(false), moved(true) {}
+  CopyDetector(const CopyDetector& d) : x(d.x), copied(true), moved(false) {}
+  CopyDetector& operator=(const CopyDetector& c) {
+    x = c.x;
+    copied = true;
+    moved = false;
+    return *this;
+  }
+  CopyDetector& operator=(CopyDetector&& c) noexcept {
+    x = c.x;
+    copied = false;
+    moved = true;
+    return *this;
+  }
+  int x = 0;
+  bool copied = false;
+  bool moved = false;
+};
+
+testing::Matcher<const CopyDetector&> CopyDetectorHas(int a, bool b, bool c) {
+  return AllOf(Field(&CopyDetector::x, a), Field(&CopyDetector::moved, b),
+               Field(&CopyDetector::copied, c));
+}
+
+class Base1 {
+ public:
+  virtual ~Base1() {}
+  int pad;
+};
+
+class Base2 {
+ public:
+  virtual ~Base2() {}
+  int yetotherpad;
+};
+
+class Derived : public Base1, public Base2 {
+ public:
+  virtual ~Derived() {}
+  int evenmorepad;
+};
+
+class CopyNoAssign {
+ public:
+  explicit CopyNoAssign(int value) : foo(value) {}
+  CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}
+  int foo;
+
+ private:
+  const CopyNoAssign& operator=(const CopyNoAssign&);
+};
+
+absl::StatusOr<std::unique_ptr<int>> ReturnUniquePtr() {
+  // Uses implicit constructor from T&&
+  return absl::make_unique<int>(0);
+}
+
+TEST(StatusOr, ElementType) {
+  static_assert(std::is_same<absl::StatusOr<int>::value_type, int>(), "");
+  static_assert(std::is_same<absl::StatusOr<char>::value_type, char>(), "");
+}
+
+TEST(StatusOr, TestMoveOnlyInitialization) {
+  absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
+  ASSERT_TRUE(thing.ok());
+  EXPECT_EQ(0, **thing);
+  int* previous = thing->get();
+
+  thing = ReturnUniquePtr();
+  EXPECT_TRUE(thing.ok());
+  EXPECT_EQ(0, **thing);
+  EXPECT_NE(previous, thing->get());
+}
+
+TEST(StatusOr, TestMoveOnlyValueExtraction) {
+  absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
+  ASSERT_TRUE(thing.ok());
+  std::unique_ptr<int> ptr = *std::move(thing);
+  EXPECT_EQ(0, *ptr);
+
+  thing = std::move(ptr);
+  ptr = std::move(*thing);
+  EXPECT_EQ(0, *ptr);
+}
+
+TEST(StatusOr, TestMoveOnlyInitializationFromTemporaryByValueOrDie) {
+  std::unique_ptr<int> ptr(*ReturnUniquePtr());
+  EXPECT_EQ(0, *ptr);
+}
+
+TEST(StatusOr, TestValueOrDieOverloadForConstTemporary) {
+  static_assert(
+      std::is_same<const int&&,
+                   decltype(
+                       std::declval<const absl::StatusOr<int>&&>().value())>(),
+      "value() for const temporaries should return const T&&");
+}
+
+TEST(StatusOr, TestMoveOnlyConversion) {
+  absl::StatusOr<std::unique_ptr<const int>> const_thing(ReturnUniquePtr());
+  EXPECT_TRUE(const_thing.ok());
+  EXPECT_EQ(0, **const_thing);
+
+  // Test rvalue converting assignment
+  const int* const_previous = const_thing->get();
+  const_thing = ReturnUniquePtr();
+  EXPECT_TRUE(const_thing.ok());
+  EXPECT_EQ(0, **const_thing);
+  EXPECT_NE(const_previous, const_thing->get());
+}
+
+TEST(StatusOr, TestMoveOnlyVector) {
+  // Sanity check that absl::StatusOr<MoveOnly> works in vector.
+  std::vector<absl::StatusOr<std::unique_ptr<int>>> vec;
+  vec.push_back(ReturnUniquePtr());
+  vec.resize(2);
+  auto another_vec = std::move(vec);
+  EXPECT_EQ(0, **another_vec[0]);
+  EXPECT_EQ(absl::UnknownError(""), another_vec[1].status());
+}
+
+TEST(StatusOr, TestDefaultCtor) {
+  absl::StatusOr<int> thing;
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);
+}
+
+TEST(StatusOr, StatusCtorForwards) {
+  absl::Status status(absl::StatusCode::kInternal, "Some error");
+
+  EXPECT_EQ(absl::StatusOr<int>(status).status().message(), "Some error");
+  EXPECT_EQ(status.message(), "Some error");
+
+  EXPECT_EQ(absl::StatusOr<int>(std::move(status)).status().message(),
+            "Some error");
+  EXPECT_NE(status.message(), "Some error");
+}
+
+// Define `EXPECT_DEATH_OR_THROW` to test the behavior of `StatusOr::value`,
+// which either throws `BadStatusOrAccess` or `LOG(FATAL)` based on whether
+// exceptions are enabled.
+#ifdef ABSL_HAVE_EXCEPTIONS
+#define EXPECT_DEATH_OR_THROW(statement, status_)    \
+  EXPECT_THROW(                                      \
+      {                                              \
+        try {                                        \
+          statement;                                 \
+        } catch (const absl::BadStatusOrAccess& e) { \
+          EXPECT_EQ(e.status(), status_);            \
+          throw;                                     \
+        }                                            \
+      },                                             \
+      absl::BadStatusOrAccess);
+#else  // ABSL_HAVE_EXCEPTIONS
+#define EXPECT_DEATH_OR_THROW(statement, status) \
+  EXPECT_DEATH_IF_SUPPORTED(statement, status.ToString());
+#endif  // ABSL_HAVE_EXCEPTIONS
+
+TEST(StatusOrDeathTest, TestDefaultCtorValue) {
+  absl::StatusOr<int> thing;
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+  const absl::StatusOr<int> thing2;
+  EXPECT_DEATH_OR_THROW(thing2.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestValueNotOk) {
+  absl::StatusOr<int> thing(absl::CancelledError());
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+TEST(StatusOrDeathTest, TestValueNotOkConst) {
+  const absl::StatusOr<int> thing(absl::UnknownError(""));
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestPointerDefaultCtorValue) {
+  absl::StatusOr<int*> thing;
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestPointerValueNotOk) {
+  absl::StatusOr<int*> thing(absl::CancelledError());
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+TEST(StatusOrDeathTest, TestPointerValueNotOkConst) {
+  const absl::StatusOr<int*> thing(absl::CancelledError());
+  EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(StatusOrDeathTest, TestStatusCtorStatusOk) {
+  EXPECT_DEBUG_DEATH(
+      {
+        // This will DCHECK
+        absl::StatusOr<int> thing(absl::OkStatus());
+        // In optimized mode, we are actually going to get error::INTERNAL for
+        // status here, rather than crashing, so check that.
+        EXPECT_FALSE(thing.ok());
+        EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);
+      },
+      "An OK status is not a valid constructor argument");
+}
+
+TEST(StatusOrDeathTest, TestPointerStatusCtorStatusOk) {
+  EXPECT_DEBUG_DEATH(
+      {
+        absl::StatusOr<int*> thing(absl::OkStatus());
+        // In optimized mode, we are actually going to get error::INTERNAL for
+        // status here, rather than crashing, so check that.
+        EXPECT_FALSE(thing.ok());
+        EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);
+      },
+      "An OK status is not a valid constructor argument");
+}
+#endif
+
+TEST(StatusOr, ValueAccessor) {
+  const int kIntValue = 110;
+  {
+    absl::StatusOr<int> status_or(kIntValue);
+    EXPECT_EQ(kIntValue, status_or.value());
+    EXPECT_EQ(kIntValue, std::move(status_or).value());
+  }
+  {
+    absl::StatusOr<CopyDetector> status_or(kIntValue);
+    EXPECT_THAT(status_or,
+                IsOkAndHolds(CopyDetectorHas(kIntValue, false, false)));
+    CopyDetector copy_detector = status_or.value();
+    EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, false, true));
+    copy_detector = std::move(status_or).value();
+    EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, true, false));
+  }
+}
+
+TEST(StatusOr, BadValueAccess) {
+  const absl::Status kError = absl::CancelledError("message");
+  absl::StatusOr<int> status_or(kError);
+  EXPECT_DEATH_OR_THROW(status_or.value(), kError);
+}
+
+TEST(StatusOr, TestStatusCtor) {
+  absl::StatusOr<int> thing(absl::CancelledError());
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);
+}
+
+
+
+TEST(StatusOr, TestValueCtor) {
+  const int kI = 4;
+  const absl::StatusOr<int> thing(kI);
+  EXPECT_TRUE(thing.ok());
+  EXPECT_EQ(kI, *thing);
+}
+
+struct Foo {
+  const int x;
+  explicit Foo(int y) : x(y) {}
+};
+
+TEST(StatusOr, InPlaceConstruction) {
+  EXPECT_THAT(absl::StatusOr<Foo>(absl::in_place, 10),
+              IsOkAndHolds(Field(&Foo::x, 10)));
+}
+
+struct InPlaceHelper {
+  InPlaceHelper(std::initializer_list<int> xs, std::unique_ptr<int> yy)
+      : x(xs), y(std::move(yy)) {}
+  const std::vector<int> x;
+  std::unique_ptr<int> y;
+};
+
+TEST(StatusOr, InPlaceInitListConstruction) {
+  absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},
+                                          absl::make_unique<int>(13));
+  EXPECT_THAT(status_or, IsOkAndHolds(AllOf(
+                             Field(&InPlaceHelper::x, ElementsAre(10, 11, 12)),
+                             Field(&InPlaceHelper::y, Pointee(13)))));
+}
+
+TEST(StatusOr, Emplace) {
+  absl::StatusOr<Foo> status_or_foo(10);
+  status_or_foo.emplace(20);
+  EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));
+  status_or_foo = absl::InvalidArgumentError("msg");
+  EXPECT_FALSE(status_or_foo.ok());
+  EXPECT_EQ(status_or_foo.status().code(), absl::StatusCode::kInvalidArgument);
+  EXPECT_EQ(status_or_foo.status().message(), "msg");
+  status_or_foo.emplace(20);
+  EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));
+}
+
+TEST(StatusOr, EmplaceInitializerList) {
+  absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},
+                                          absl::make_unique<int>(13));
+  status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));
+  EXPECT_THAT(status_or,
+              IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),
+                                 Field(&InPlaceHelper::y, Pointee(4)))));
+  status_or = absl::InvalidArgumentError("msg");
+  EXPECT_FALSE(status_or.ok());
+  EXPECT_EQ(status_or.status().code(), absl::StatusCode::kInvalidArgument);
+  EXPECT_EQ(status_or.status().message(), "msg");
+  status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));
+  EXPECT_THAT(status_or,
+              IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),
+                                 Field(&InPlaceHelper::y, Pointee(4)))));
+}
+
+TEST(StatusOr, TestCopyCtorStatusOk) {
+  const int kI = 4;
+  const absl::StatusOr<int> original(kI);
+  const absl::StatusOr<int> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOk) {
+  absl::StatusOr<int> original(absl::CancelledError());
+  absl::StatusOr<int> copy(original);
+  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestCopyCtorNonAssignable) {
+  const int kI = 4;
+  CopyNoAssign value(kI);
+  absl::StatusOr<CopyNoAssign> original(value);
+  absl::StatusOr<CopyNoAssign> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(original->foo, copy->foo);
+}
+
+TEST(StatusOr, TestCopyCtorStatusOKConverting) {
+  const int kI = 4;
+  absl::StatusOr<int> original(kI);
+  absl::StatusOr<double> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_DOUBLE_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
+  absl::StatusOr<int> original(absl::CancelledError());
+  absl::StatusOr<double> copy(original);
+  EXPECT_EQ(copy.status(), original.status());
+}
+
+TEST(StatusOr, TestAssignmentStatusOk) {
+  // Copy assignmment
+  {
+    const auto p = std::make_shared<int>(17);
+    absl::StatusOr<std::shared_ptr<int>> source(p);
+
+    absl::StatusOr<std::shared_ptr<int>> target;
+    target = source;
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_EQ(p, *target);
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_EQ(p, *source);
+  }
+
+  // Move asssignment
+  {
+    const auto p = std::make_shared<int>(17);
+    absl::StatusOr<std::shared_ptr<int>> source(p);
+
+    absl::StatusOr<std::shared_ptr<int>> target;
+    target = std::move(source);
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_EQ(p, *target);
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_EQ(nullptr, *source);
+  }
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOk) {
+  // Copy assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<int> target;
+    target = source;
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(expected, source.status());
+  }
+
+  // Move assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<int> target;
+    target = std::move(source);
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);
+  }
+}
+
+TEST(StatusOr, TestAssignmentStatusOKConverting) {
+  // Copy assignment
+  {
+    const int kI = 4;
+    absl::StatusOr<int> source(kI);
+
+    absl::StatusOr<double> target;
+    target = source;
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_DOUBLE_EQ(kI, *target);
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_DOUBLE_EQ(kI, *source);
+  }
+
+  // Move assignment
+  {
+    const auto p = new int(17);
+    absl::StatusOr<std::unique_ptr<int>> source(absl::WrapUnique(p));
+
+    absl::StatusOr<std::shared_ptr<int>> target;
+    target = std::move(source);
+
+    ASSERT_TRUE(target.ok());
+    EXPECT_OK(target.status());
+    EXPECT_EQ(p, target->get());
+
+    ASSERT_TRUE(source.ok());
+    EXPECT_OK(source.status());
+    EXPECT_EQ(nullptr, source->get());
+  }
+}
+
+struct A {
+  int x;
+};
+
+struct ImplicitConstructibleFromA {
+  int x;
+  bool moved;
+  ImplicitConstructibleFromA(const A& a)  // NOLINT
+      : x(a.x), moved(false) {}
+  ImplicitConstructibleFromA(A&& a)  // NOLINT
+      : x(a.x), moved(true) {}
+};
+
+TEST(StatusOr, ImplicitConvertingConstructor) {
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(
+          absl::StatusOr<A>(A{11})),
+      IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 11),
+                         Field(&ImplicitConstructibleFromA::moved, true))));
+  absl::StatusOr<A> a(A{12});
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(a),
+      IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 12),
+                         Field(&ImplicitConstructibleFromA::moved, false))));
+}
+
+struct ExplicitConstructibleFromA {
+  int x;
+  bool moved;
+  explicit ExplicitConstructibleFromA(const A& a) : x(a.x), moved(false) {}
+  explicit ExplicitConstructibleFromA(A&& a) : x(a.x), moved(true) {}
+};
+
+TEST(StatusOr, ExplicitConvertingConstructor) {
+  EXPECT_FALSE(
+      (std::is_convertible<const absl::StatusOr<A>&,
+                           absl::StatusOr<ExplicitConstructibleFromA>>::value));
+  EXPECT_FALSE(
+      (std::is_convertible<absl::StatusOr<A>&&,
+                           absl::StatusOr<ExplicitConstructibleFromA>>::value));
+  EXPECT_THAT(
+      absl::StatusOr<ExplicitConstructibleFromA>(absl::StatusOr<A>(A{11})),
+      IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 11),
+                         Field(&ExplicitConstructibleFromA::moved, true))));
+  absl::StatusOr<A> a(A{12});
+  EXPECT_THAT(
+      absl::StatusOr<ExplicitConstructibleFromA>(a),
+      IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 12),
+                         Field(&ExplicitConstructibleFromA::moved, false))));
+}
+
+struct ImplicitConstructibleFromBool {
+  ImplicitConstructibleFromBool(bool y) : x(y) {}  // NOLINT
+  bool x = false;
+};
+
+struct ConvertibleToBool {
+  explicit ConvertibleToBool(bool y) : x(y) {}
+  operator bool() const { return x; }  // NOLINT
+  bool x = false;
+};
+
+TEST(StatusOr, ImplicitBooleanConstructionWithImplicitCasts) {
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromBool>>(
+          absl::StatusOr<bool>(false)),
+      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+  EXPECT_FALSE((std::is_convertible<
+                absl::StatusOr<ConvertibleToBool>,
+                absl::StatusOr<ImplicitConstructibleFromBool>>::value));
+}
+
+TEST(StatusOr, BooleanConstructionWithImplicitCasts) {
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<bool>(false)},
+      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<bool>(absl::InvalidArgumentError(""))},
+      Not(IsOk()));
+
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<ConvertibleToBool>(ConvertibleToBool{false})},
+      IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+  EXPECT_THAT(
+      absl::StatusOr<ImplicitConstructibleFromBool>{
+          absl::StatusOr<ConvertibleToBool>(absl::InvalidArgumentError(""))},
+      Not(IsOk()));
+}
+
+TEST(StatusOr, ConstImplicitCast) {
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(
+                  absl::StatusOr<const bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(
+                  absl::StatusOr<const bool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(
+                  absl::StatusOr<bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(
+                  absl::StatusOr<bool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const std::string>>(
+                  absl::StatusOr<std::string>("foo")),
+              IsOkAndHolds("foo"));
+  EXPECT_THAT(absl::implicit_cast<absl::StatusOr<std::string>>(
+                  absl::StatusOr<const std::string>("foo")),
+              IsOkAndHolds("foo"));
+  EXPECT_THAT(
+      absl::implicit_cast<absl::StatusOr<std::shared_ptr<const std::string>>>(
+          absl::StatusOr<std::shared_ptr<std::string>>(
+              std::make_shared<std::string>("foo"))),
+      IsOkAndHolds(Pointee(std::string("foo"))));
+}
+
+TEST(StatusOr, ConstExplicitConstruction) {
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(false)),
+              IsOkAndHolds(false));
+  EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(true)),
+              IsOkAndHolds(true));
+  EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(false)),
+              IsOkAndHolds(false));
+}
+
+struct ExplicitConstructibleFromInt {
+  int x;
+  explicit ExplicitConstructibleFromInt(int y) : x(y) {}
+};
+
+TEST(StatusOr, ExplicitConstruction) {
+  EXPECT_THAT(absl::StatusOr<ExplicitConstructibleFromInt>(10),
+              IsOkAndHolds(Field(&ExplicitConstructibleFromInt::x, 10)));
+}
+
+TEST(StatusOr, ImplicitConstruction) {
+  // Check implicit casting works.
+  auto status_or =
+      absl::implicit_cast<absl::StatusOr<absl::variant<int, std::string>>>(10);
+  EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));
+}
+
+TEST(StatusOr, ImplicitConstructionFromInitliazerList) {
+  // Note: dropping the explicit std::initializer_list<int> is not supported
+  // by absl::StatusOr or absl::optional.
+  auto status_or =
+      absl::implicit_cast<absl::StatusOr<std::vector<int>>>({{10, 20, 30}});
+  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, UniquePtrImplicitConstruction) {
+  auto status_or = absl::implicit_cast<absl::StatusOr<std::unique_ptr<Base1>>>(
+      absl::make_unique<Derived>());
+  EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));
+}
+
+TEST(StatusOr, NestedStatusOrCopyAndMoveConstructorTests) {
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =
+      absl::InvalidArgumentError("foo");
+  EXPECT_THAT(status_or,
+              IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::StatusOr<CopyDetector>> a = status_or;
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  absl::StatusOr<absl::StatusOr<CopyDetector>> a_err = status_error;
+  EXPECT_THAT(a_err, Not(IsOk()));
+
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;
+  absl::StatusOr<absl::StatusOr<CopyDetector>> b = cref;  // NOLINT
+  EXPECT_THAT(b, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;
+  absl::StatusOr<absl::StatusOr<CopyDetector>> b_err = cref_err;  // NOLINT
+  EXPECT_THAT(b_err, Not(IsOk()));
+
+  absl::StatusOr<absl::StatusOr<CopyDetector>> c = std::move(status_or);
+  EXPECT_THAT(c, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::StatusOr<CopyDetector>> c_err = std::move(status_error);
+  EXPECT_THAT(c_err, Not(IsOk()));
+}
+
+TEST(StatusOr, NestedStatusOrCopyAndMoveAssignment) {
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);
+  absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =
+      absl::InvalidArgumentError("foo");
+  absl::StatusOr<absl::StatusOr<CopyDetector>> a;
+  a = status_or;
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  a = status_error;
+  EXPECT_THAT(a, Not(IsOk()));
+
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;
+  a = cref;
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;
+  a = cref_err;
+  EXPECT_THAT(a, Not(IsOk()));
+  a = std::move(status_or);
+  EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+  a = std::move(status_error);
+  EXPECT_THAT(a, Not(IsOk()));
+}
+
+struct Copyable {
+  Copyable() {}
+  Copyable(const Copyable&) {}
+  Copyable& operator=(const Copyable&) { return *this; }
+};
+
+struct MoveOnly {
+  MoveOnly() {}
+  MoveOnly(MoveOnly&&) {}
+  MoveOnly& operator=(MoveOnly&&) { return *this; }
+};
+
+struct NonMovable {
+  NonMovable() {}
+  NonMovable(const NonMovable&) = delete;
+  NonMovable(NonMovable&&) = delete;
+  NonMovable& operator=(const NonMovable&) = delete;
+  NonMovable& operator=(NonMovable&&) = delete;
+};
+
+TEST(StatusOr, CopyAndMoveAbility) {
+  EXPECT_TRUE(std::is_copy_constructible<Copyable>::value);
+  EXPECT_TRUE(std::is_copy_assignable<Copyable>::value);
+  EXPECT_TRUE(std::is_move_constructible<Copyable>::value);
+  EXPECT_TRUE(std::is_move_assignable<Copyable>::value);
+  EXPECT_FALSE(std::is_copy_constructible<MoveOnly>::value);
+  EXPECT_FALSE(std::is_copy_assignable<MoveOnly>::value);
+  EXPECT_TRUE(std::is_move_constructible<MoveOnly>::value);
+  EXPECT_TRUE(std::is_move_assignable<MoveOnly>::value);
+  EXPECT_FALSE(std::is_copy_constructible<NonMovable>::value);
+  EXPECT_FALSE(std::is_copy_assignable<NonMovable>::value);
+  EXPECT_FALSE(std::is_move_constructible<NonMovable>::value);
+  EXPECT_FALSE(std::is_move_assignable<NonMovable>::value);
+}
+
+TEST(StatusOr, StatusOrAnyCopyAndMoveConstructorTests) {
+  absl::StatusOr<absl::any> status_or = CopyDetector(10);
+  absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo");
+  EXPECT_THAT(
+      status_or,
+      IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::any> a = status_or;
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  absl::StatusOr<absl::any> a_err = status_error;
+  EXPECT_THAT(a_err, Not(IsOk()));
+
+  const absl::StatusOr<absl::any>& cref = status_or;
+  // No lint for no-change copy.
+  absl::StatusOr<absl::any> b = cref;  // NOLINT
+  EXPECT_THAT(
+      b, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::any>& cref_err = status_error;
+  // No lint for no-change copy.
+  absl::StatusOr<absl::any> b_err = cref_err;  // NOLINT
+  EXPECT_THAT(b_err, Not(IsOk()));
+
+  absl::StatusOr<absl::any> c = std::move(status_or);
+  EXPECT_THAT(
+      c, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+  absl::StatusOr<absl::any> c_err = std::move(status_error);
+  EXPECT_THAT(c_err, Not(IsOk()));
+}
+
+TEST(StatusOr, StatusOrAnyCopyAndMoveAssignment) {
+  absl::StatusOr<absl::any> status_or = CopyDetector(10);
+  absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo");
+  absl::StatusOr<absl::any> a;
+  a = status_or;
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  a = status_error;
+  EXPECT_THAT(a, Not(IsOk()));
+
+  const absl::StatusOr<absl::any>& cref = status_or;
+  a = cref;
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+  const absl::StatusOr<absl::any>& cref_err = status_error;
+  a = cref_err;
+  EXPECT_THAT(a, Not(IsOk()));
+  a = std::move(status_or);
+  EXPECT_THAT(
+      a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+  a = std::move(status_error);
+  EXPECT_THAT(a, Not(IsOk()));
+}
+
+TEST(StatusOr, StatusOrCopyAndMoveTestsConstructor) {
+  absl::StatusOr<CopyDetector> status_or(10);
+  ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));
+  absl::StatusOr<CopyDetector> a(status_or);
+  EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  const absl::StatusOr<CopyDetector>& cref = status_or;
+  absl::StatusOr<CopyDetector> b(cref);  // NOLINT
+  EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  absl::StatusOr<CopyDetector> c(std::move(status_or));
+  EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));
+}
+
+TEST(StatusOr, StatusOrCopyAndMoveTestsAssignment) {
+  absl::StatusOr<CopyDetector> status_or(10);
+  ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));
+  absl::StatusOr<CopyDetector> a;
+  a = status_or;
+  EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  const absl::StatusOr<CopyDetector>& cref = status_or;
+  absl::StatusOr<CopyDetector> b;
+  b = cref;
+  EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+  absl::StatusOr<CopyDetector> c;
+  c = std::move(status_or);
+  EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));
+}
+
+TEST(StatusOr, AbslAnyAssignment) {
+  EXPECT_FALSE((std::is_assignable<absl::StatusOr<absl::any>,
+                                   absl::StatusOr<int>>::value));
+  absl::StatusOr<absl::any> status_or;
+  status_or = absl::InvalidArgumentError("foo");
+  EXPECT_THAT(status_or, Not(IsOk()));
+}
+
+TEST(StatusOr, ImplicitAssignment) {
+  absl::StatusOr<absl::variant<int, std::string>> status_or;
+  status_or = 10;
+  EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));
+}
+
+TEST(StatusOr, SelfDirectInitAssignment) {
+  absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};
+  status_or = *status_or;
+  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, ImplicitCastFromInitializerList) {
+  absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};
+  EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, UniquePtrImplicitAssignment) {
+  absl::StatusOr<std::unique_ptr<Base1>> status_or;
+  status_or = absl::make_unique<Derived>();
+  EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));
+}
+
+TEST(StatusOr, Pointer) {
+  struct A {};
+  struct B : public A {};
+  struct C : private A {};
+
+  EXPECT_TRUE((std::is_constructible<absl::StatusOr<A*>, B*>::value));
+  EXPECT_TRUE((std::is_convertible<B*, absl::StatusOr<A*>>::value));
+  EXPECT_FALSE((std::is_constructible<absl::StatusOr<A*>, C*>::value));
+  EXPECT_FALSE((std::is_convertible<C*, absl::StatusOr<A*>>::value));
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
+  // Copy assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<double> target;
+    target = source;
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(expected, source.status());
+  }
+
+  // Move assignment
+  {
+    const absl::Status expected = absl::CancelledError();
+    absl::StatusOr<int> source(expected);
+
+    absl::StatusOr<double> target;
+    target = std::move(source);
+
+    EXPECT_FALSE(target.ok());
+    EXPECT_EQ(expected, target.status());
+
+    EXPECT_FALSE(source.ok());
+    EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);
+  }
+}
+
+TEST(StatusOr, SelfAssignment) {
+  // Copy-assignment, status OK
+  {
+    // A string long enough that it's likely to defeat any inline representation
+    // optimization.
+    const std::string long_str(128, 'a');
+
+    absl::StatusOr<std::string> so = long_str;
+    so = *&so;
+
+    ASSERT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(long_str, *so);
+  }
+
+  // Copy-assignment, error status
+  {
+    absl::StatusOr<int> so = absl::NotFoundError("taco");
+    so = *&so;
+
+    EXPECT_FALSE(so.ok());
+    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+    EXPECT_EQ(so.status().message(), "taco");
+  }
+
+  // Move-assignment with copyable type, status OK
+  {
+    absl::StatusOr<int> so = 17;
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    ASSERT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(17, *so);
+  }
+
+  // Move-assignment with copyable type, error status
+  {
+    absl::StatusOr<int> so = absl::NotFoundError("taco");
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    EXPECT_FALSE(so.ok());
+    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+    EXPECT_EQ(so.status().message(), "taco");
+  }
+
+  // Move-assignment with non-copyable type, status OK
+  {
+    const auto raw = new int(17);
+    absl::StatusOr<std::unique_ptr<int>> so = absl::WrapUnique(raw);
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    ASSERT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(raw, so->get());
+  }
+
+  // Move-assignment with non-copyable type, error status
+  {
+    absl::StatusOr<std::unique_ptr<int>> so = absl::NotFoundError("taco");
+
+    // Fool the compiler, which otherwise complains.
+    auto& same = so;
+    so = std::move(same);
+
+    EXPECT_FALSE(so.ok());
+    EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+    EXPECT_EQ(so.status().message(), "taco");
+  }
+}
+
+// These types form the overload sets of the constructors and the assignment
+// operators of `MockValue`. They distinguish construction from assignment,
+// lvalue from rvalue.
+struct FromConstructibleAssignableLvalue {};
+struct FromConstructibleAssignableRvalue {};
+struct FromImplicitConstructibleOnly {};
+struct FromAssignableOnly {};
+
+// This class is for testing the forwarding value assignments of `StatusOr`.
+// `from_rvalue` indicates whether the constructor or the assignment taking
+// rvalue reference is called. `from_assignment` indicates whether any
+// assignment is called.
+struct MockValue {
+  // Constructs `MockValue` from `FromConstructibleAssignableLvalue`.
+  MockValue(const FromConstructibleAssignableLvalue&)  // NOLINT
+      : from_rvalue(false), assigned(false) {}
+  // Constructs `MockValue` from `FromConstructibleAssignableRvalue`.
+  MockValue(FromConstructibleAssignableRvalue&&)  // NOLINT
+      : from_rvalue(true), assigned(false) {}
+  // Constructs `MockValue` from `FromImplicitConstructibleOnly`.
+  // `MockValue` is not assignable from `FromImplicitConstructibleOnly`.
+  MockValue(const FromImplicitConstructibleOnly&)  // NOLINT
+      : from_rvalue(false), assigned(false) {}
+  // Assigns `FromConstructibleAssignableLvalue`.
+  MockValue& operator=(const FromConstructibleAssignableLvalue&) {
+    from_rvalue = false;
+    assigned = true;
+    return *this;
+  }
+  // Assigns `FromConstructibleAssignableRvalue` (rvalue only).
+  MockValue& operator=(FromConstructibleAssignableRvalue&&) {
+    from_rvalue = true;
+    assigned = true;
+    return *this;
+  }
+  // Assigns `FromAssignableOnly`, but not constructible from
+  // `FromAssignableOnly`.
+  MockValue& operator=(const FromAssignableOnly&) {
+    from_rvalue = false;
+    assigned = true;
+    return *this;
+  }
+  bool from_rvalue;
+  bool assigned;
+};
+
+// operator=(U&&)
+TEST(StatusOr, PerfectForwardingAssignment) {
+  // U == T
+  constexpr int kValue1 = 10, kValue2 = 20;
+  absl::StatusOr<CopyDetector> status_or;
+  CopyDetector lvalue(kValue1);
+  status_or = lvalue;
+  EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue1, false, true)));
+  status_or = CopyDetector(kValue2);
+  EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue2, true, false)));
+
+  // U != T
+  EXPECT_TRUE(
+      (std::is_assignable<absl::StatusOr<MockValue>&,
+                          const FromConstructibleAssignableLvalue&>::value));
+  EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,
+                                  FromConstructibleAssignableLvalue&&>::value));
+  EXPECT_FALSE(
+      (std::is_assignable<absl::StatusOr<MockValue>&,
+                          const FromConstructibleAssignableRvalue&>::value));
+  EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,
+                                  FromConstructibleAssignableRvalue&&>::value));
+  EXPECT_TRUE(
+      (std::is_assignable<absl::StatusOr<MockValue>&,
+                          const FromImplicitConstructibleOnly&>::value));
+  EXPECT_FALSE((std::is_assignable<absl::StatusOr<MockValue>&,
+                                   const FromAssignableOnly&>::value));
+
+  absl::StatusOr<MockValue> from_lvalue(FromConstructibleAssignableLvalue{});
+  EXPECT_FALSE(from_lvalue->from_rvalue);
+  EXPECT_FALSE(from_lvalue->assigned);
+  from_lvalue = FromConstructibleAssignableLvalue{};
+  EXPECT_FALSE(from_lvalue->from_rvalue);
+  EXPECT_TRUE(from_lvalue->assigned);
+
+  absl::StatusOr<MockValue> from_rvalue(FromConstructibleAssignableRvalue{});
+  EXPECT_TRUE(from_rvalue->from_rvalue);
+  EXPECT_FALSE(from_rvalue->assigned);
+  from_rvalue = FromConstructibleAssignableRvalue{};
+  EXPECT_TRUE(from_rvalue->from_rvalue);
+  EXPECT_TRUE(from_rvalue->assigned);
+
+  absl::StatusOr<MockValue> from_implicit_constructible(
+      FromImplicitConstructibleOnly{});
+  EXPECT_FALSE(from_implicit_constructible->from_rvalue);
+  EXPECT_FALSE(from_implicit_constructible->assigned);
+  // construct a temporary `StatusOr` object and invoke the `StatusOr` move
+  // assignment operator.
+  from_implicit_constructible = FromImplicitConstructibleOnly{};
+  EXPECT_FALSE(from_implicit_constructible->from_rvalue);
+  EXPECT_FALSE(from_implicit_constructible->assigned);
+}
+
+TEST(StatusOr, TestStatus) {
+  absl::StatusOr<int> good(4);
+  EXPECT_TRUE(good.ok());
+  absl::StatusOr<int> bad(absl::CancelledError());
+  EXPECT_FALSE(bad.ok());
+  EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, OperatorStarRefQualifiers) {
+  static_assert(
+      std::is_same<const int&,
+                   decltype(*std::declval<const absl::StatusOr<int>&>())>(),
+      "Unexpected ref-qualifiers");
+  static_assert(
+      std::is_same<int&, decltype(*std::declval<absl::StatusOr<int>&>())>(),
+      "Unexpected ref-qualifiers");
+  static_assert(
+      std::is_same<const int&&,
+                   decltype(*std::declval<const absl::StatusOr<int>&&>())>(),
+      "Unexpected ref-qualifiers");
+  static_assert(
+      std::is_same<int&&, decltype(*std::declval<absl::StatusOr<int>&&>())>(),
+      "Unexpected ref-qualifiers");
+}
+
+TEST(StatusOr, OperatorStar) {
+  const absl::StatusOr<std::string> const_lvalue("hello");
+  EXPECT_EQ("hello", *const_lvalue);
+
+  absl::StatusOr<std::string> lvalue("hello");
+  EXPECT_EQ("hello", *lvalue);
+
+  // Note: Recall that std::move() is equivalent to a static_cast to an rvalue
+  // reference type.
+  const absl::StatusOr<std::string> const_rvalue("hello");
+  EXPECT_EQ("hello", *std::move(const_rvalue));  // NOLINT
+
+  absl::StatusOr<std::string> rvalue("hello");
+  EXPECT_EQ("hello", *std::move(rvalue));
+}
+
+TEST(StatusOr, OperatorArrowQualifiers) {
+  static_assert(
+      std::is_same<
+          const int*,
+          decltype(std::declval<const absl::StatusOr<int>&>().operator->())>(),
+      "Unexpected qualifiers");
+  static_assert(
+      std::is_same<
+          int*, decltype(std::declval<absl::StatusOr<int>&>().operator->())>(),
+      "Unexpected qualifiers");
+  static_assert(
+      std::is_same<
+          const int*,
+          decltype(std::declval<const absl::StatusOr<int>&&>().operator->())>(),
+      "Unexpected qualifiers");
+  static_assert(
+      std::is_same<
+          int*, decltype(std::declval<absl::StatusOr<int>&&>().operator->())>(),
+      "Unexpected qualifiers");
+}
+
+TEST(StatusOr, OperatorArrow) {
+  const absl::StatusOr<std::string> const_lvalue("hello");
+  EXPECT_EQ(std::string("hello"), const_lvalue->c_str());
+
+  absl::StatusOr<std::string> lvalue("hello");
+  EXPECT_EQ(std::string("hello"), lvalue->c_str());
+}
+
+TEST(StatusOr, RValueStatus) {
+  absl::StatusOr<int> so(absl::NotFoundError("taco"));
+  const absl::Status s = std::move(so).status();
+
+  EXPECT_EQ(s.code(), absl::StatusCode::kNotFound);
+  EXPECT_EQ(s.message(), "taco");
+
+  // Check that !ok() still implies !status().ok(), even after moving out of the
+  // object. See the note on the rvalue ref-qualified status method.
+  EXPECT_FALSE(so.ok());  // NOLINT
+  EXPECT_FALSE(so.status().ok());
+  EXPECT_EQ(so.status().code(), absl::StatusCode::kInternal);
+  EXPECT_EQ(so.status().message(), "Status accessed after move.");
+}
+
+TEST(StatusOr, TestValue) {
+  const int kI = 4;
+  absl::StatusOr<int> thing(kI);
+  EXPECT_EQ(kI, *thing);
+}
+
+TEST(StatusOr, TestValueConst) {
+  const int kI = 4;
+  const absl::StatusOr<int> thing(kI);
+  EXPECT_EQ(kI, *thing);
+}
+
+TEST(StatusOr, TestPointerDefaultCtor) {
+  absl::StatusOr<int*> thing;
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);
+}
+
+
+
+TEST(StatusOr, TestPointerStatusCtor) {
+  absl::StatusOr<int*> thing(absl::CancelledError());
+  EXPECT_FALSE(thing.ok());
+  EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerValueCtor) {
+  const int kI = 4;
+
+  // Construction from a non-null pointer
+  {
+    absl::StatusOr<const int*> so(&kI);
+    EXPECT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(&kI, *so);
+  }
+
+  // Construction from a null pointer constant
+  {
+    absl::StatusOr<const int*> so(nullptr);
+    EXPECT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(nullptr, *so);
+  }
+
+  // Construction from a non-literal null pointer
+  {
+    const int* const p = nullptr;
+
+    absl::StatusOr<const int*> so(p);
+    EXPECT_TRUE(so.ok());
+    EXPECT_OK(so.status());
+    EXPECT_EQ(nullptr, *so);
+  }
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOk) {
+  const int kI = 0;
+  absl::StatusOr<const int*> original(&kI);
+  absl::StatusOr<const int*> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
+  absl::StatusOr<int*> original(absl::CancelledError());
+  absl::StatusOr<int*> copy(original);
+  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) {
+  Derived derived;
+  absl::StatusOr<Derived*> original(&derived);
+  absl::StatusOr<Base2*> copy(original);
+  EXPECT_OK(copy.status());
+  EXPECT_EQ(static_cast<const Base2*>(*original), *copy);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
+  absl::StatusOr<Derived*> original(absl::CancelledError());
+  absl::StatusOr<Base2*> copy(original);
+  EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOk) {
+  const int kI = 0;
+  absl::StatusOr<const int*> source(&kI);
+  absl::StatusOr<const int*> target;
+  target = source;
+  EXPECT_OK(target.status());
+  EXPECT_EQ(*source, *target);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
+  absl::StatusOr<int*> source(absl::CancelledError());
+  absl::StatusOr<int*> target;
+  target = source;
+  EXPECT_EQ(target.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOKConverting) {
+  Derived derived;
+  absl::StatusOr<Derived*> source(&derived);
+  absl::StatusOr<Base2*> target;
+  target = source;
+  EXPECT_OK(target.status());
+  EXPECT_EQ(static_cast<const Base2*>(*source), *target);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {
+  absl::StatusOr<Derived*> source(absl::CancelledError());
+  absl::StatusOr<Base2*> target;
+  target = source;
+  EXPECT_EQ(target.status(), source.status());
+}
+
+TEST(StatusOr, TestPointerStatus) {
+  const int kI = 0;
+  absl::StatusOr<const int*> good(&kI);
+  EXPECT_TRUE(good.ok());
+  absl::StatusOr<const int*> bad(absl::CancelledError());
+  EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerValue) {
+  const int kI = 0;
+  absl::StatusOr<const int*> thing(&kI);
+  EXPECT_EQ(&kI, *thing);
+}
+
+TEST(StatusOr, TestPointerValueConst) {
+  const int kI = 0;
+  const absl::StatusOr<const int*> thing(&kI);
+  EXPECT_EQ(&kI, *thing);
+}
+
+TEST(StatusOr, StatusOrVectorOfUniquePointerCanReserveAndResize) {
+  using EvilType = std::vector<std::unique_ptr<int>>;
+  static_assert(std::is_copy_constructible<EvilType>::value, "");
+  std::vector<::absl::StatusOr<EvilType>> v(5);
+  v.reserve(v.capacity() + 10);
+  v.resize(v.capacity() + 10);
+}
+
+TEST(StatusOr, ConstPayload) {
+  // A reduced version of a problematic type found in the wild. All of the
+  // operations below should compile.
+  absl::StatusOr<const int> a;
+
+  // Copy-construction
+  absl::StatusOr<const int> b(a);
+
+  // Copy-assignment
+  EXPECT_FALSE(std::is_copy_assignable<absl::StatusOr<const int>>::value);
+
+  // Move-construction
+  absl::StatusOr<const int> c(std::move(a));
+
+  // Move-assignment
+  EXPECT_FALSE(std::is_move_assignable<absl::StatusOr<const int>>::value);
+}
+
+TEST(StatusOr, MapToStatusOrUniquePtr) {
+  // A reduced version of a problematic type found in the wild. All of the
+  // operations below should compile.
+  using MapType = std::map<std::string, absl::StatusOr<std::unique_ptr<int>>>;
+
+  MapType a;
+
+  // Move-construction
+  MapType b(std::move(a));
+
+  // Move-assignment
+  a = std::move(b);
+}
+
+TEST(StatusOr, ValueOrOk) {
+  const absl::StatusOr<int> status_or = 0;
+  EXPECT_EQ(status_or.value_or(-1), 0);
+}
+
+TEST(StatusOr, ValueOrDefault) {
+  const absl::StatusOr<int> status_or = absl::CancelledError();
+  EXPECT_EQ(status_or.value_or(-1), -1);
+}
+
+TEST(StatusOr, MoveOnlyValueOrOk) {
+  EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(0))
+                  .value_or(absl::make_unique<int>(-1)),
+              Pointee(0));
+}
+
+TEST(StatusOr, MoveOnlyValueOrDefault) {
+  EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::CancelledError())
+                  .value_or(absl::make_unique<int>(-1)),
+              Pointee(-1));
+}
+
+static absl::StatusOr<int> MakeStatus() { return 100; }
+
+TEST(StatusOr, TestIgnoreError) { MakeStatus().IgnoreError(); }
+
+TEST(StatusOr, EqualityOperator) {
+  constexpr int kNumCases = 4;
+  std::array<absl::StatusOr<int>, kNumCases> group1 = {
+      absl::StatusOr<int>(1), absl::StatusOr<int>(2),
+      absl::StatusOr<int>(absl::InvalidArgumentError("msg")),
+      absl::StatusOr<int>(absl::InternalError("msg"))};
+  std::array<absl::StatusOr<int>, kNumCases> group2 = {
+      absl::StatusOr<int>(1), absl::StatusOr<int>(2),
+      absl::StatusOr<int>(absl::InvalidArgumentError("msg")),
+      absl::StatusOr<int>(absl::InternalError("msg"))};
+  for (int i = 0; i < kNumCases; ++i) {
+    for (int j = 0; j < kNumCases; ++j) {
+      if (i == j) {
+        EXPECT_TRUE(group1[i] == group2[j]);
+        EXPECT_FALSE(group1[i] != group2[j]);
+      } else {
+        EXPECT_FALSE(group1[i] == group2[j]);
+        EXPECT_TRUE(group1[i] != group2[j]);
+      }
+    }
+  }
+}
+
+struct MyType {
+  bool operator==(const MyType&) const { return true; }
+};
+
+enum class ConvTraits { kNone = 0, kImplicit = 1, kExplicit = 2 };
+
+// This class has conversion operator to `StatusOr<T>` based on value of
+// `conv_traits`.
+template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
+struct StatusOrConversionBase {};
+
+template <typename T>
+struct StatusOrConversionBase<T, ConvTraits::kImplicit> {
+  operator absl::StatusOr<T>() const& {  // NOLINT
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+  operator absl::StatusOr<T>() && {  // NOLINT
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+};
+
+template <typename T>
+struct StatusOrConversionBase<T, ConvTraits::kExplicit> {
+  explicit operator absl::StatusOr<T>() const& {
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+  explicit operator absl::StatusOr<T>() && {
+    return absl::InvalidArgumentError("conversion to absl::StatusOr");
+  }
+};
+
+// This class has conversion operator to `T` based on the value of
+// `conv_traits`.
+template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
+struct ConversionBase {};
+
+template <typename T>
+struct ConversionBase<T, ConvTraits::kImplicit> {
+  operator T() const& { return t; }         // NOLINT
+  operator T() && { return std::move(t); }  // NOLINT
+  T t;
+};
+
+template <typename T>
+struct ConversionBase<T, ConvTraits::kExplicit> {
+  explicit operator T() const& { return t; }
+  explicit operator T() && { return std::move(t); }
+  T t;
+};
+
+// This class has conversion operator to `absl::Status` based on the value of
+// `conv_traits`.
+template <ConvTraits conv_traits = ConvTraits::kNone>
+struct StatusConversionBase {};
+
+template <>
+struct StatusConversionBase<ConvTraits::kImplicit> {
+  operator absl::Status() const& {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+  operator absl::Status() && {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+};
+
+template <>
+struct StatusConversionBase<ConvTraits::kExplicit> {
+  explicit operator absl::Status() const& {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+  explicit operator absl::Status() && {  // NOLINT
+    return absl::InternalError("conversion to Status");
+  }
+};
+
+static constexpr int kConvToStatus = 1;
+static constexpr int kConvToStatusOr = 2;
+static constexpr int kConvToT = 4;
+static constexpr int kConvExplicit = 8;
+
+constexpr ConvTraits GetConvTraits(int bit, int config) {
+  return (config & bit) == 0
+             ? ConvTraits::kNone
+             : ((config & kConvExplicit) == 0 ? ConvTraits::kImplicit
+                                              : ConvTraits::kExplicit);
+}
+
+// This class conditionally has conversion operator to `absl::Status`, `T`,
+// `StatusOr<T>`, based on values of the template parameters.
+template <typename T, int config>
+struct CustomType
+    : StatusOrConversionBase<T, GetConvTraits(kConvToStatusOr, config)>,
+      ConversionBase<T, GetConvTraits(kConvToT, config)>,
+      StatusConversionBase<GetConvTraits(kConvToStatus, config)> {};
+
+struct ConvertibleToAnyStatusOr {
+  template <typename T>
+  operator absl::StatusOr<T>() const {  // NOLINT
+    return absl::InvalidArgumentError("Conversion to absl::StatusOr");
+  }
+};
+
+// Test the rank of overload resolution for `StatusOr<T>` constructor and
+// assignment, from highest to lowest:
+// 1. T/Status
+// 2. U that has conversion operator to absl::StatusOr<T>
+// 3. U that is convertible to Status
+// 4. U that is convertible to T
+TEST(StatusOr, ConstructionFromT) {
+  // Construct absl::StatusOr<T> from T when T is convertible to
+  // absl::StatusOr<T>
+  {
+    ConvertibleToAnyStatusOr v;
+    absl::StatusOr<ConvertibleToAnyStatusOr> statusor(v);
+    EXPECT_TRUE(statusor.ok());
+  }
+  {
+    ConvertibleToAnyStatusOr v;
+    absl::StatusOr<ConvertibleToAnyStatusOr> statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+  // Construct absl::StatusOr<T> from T when T is explicitly convertible to
+  // Status
+  {
+    CustomType<MyType, kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor(
+        v);
+    EXPECT_TRUE(statusor.ok());
+  }
+  {
+    CustomType<MyType, kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor =
+        v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+// Construct absl::StatusOr<T> from U when U is explicitly convertible to T
+TEST(StatusOr, ConstructionFromTypeConvertibleToT) {
+  {
+    CustomType<MyType, kConvToT | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_TRUE(statusor.ok());
+  }
+  {
+    CustomType<MyType, kConvToT> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+// Construct absl::StatusOr<T> from U when U has explicit conversion operator to
+// absl::StatusOr<T>
+TEST(StatusOr, ConstructionFromTypeWithConversionOperatorToStatusOrT) {
+  {
+    CustomType<MyType, kConvToStatusOr | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr | kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType,
+               kConvToT | kConvToStatusOr | kConvToStatus | kConvExplicit>
+        v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+}
+
+TEST(StatusOr, ConstructionFromTypeConvertibleToStatus) {
+  // Construction fails because conversion to `Status` is explicit.
+  {
+    CustomType<MyType, kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatus | kConvExplicit> v;
+    absl::StatusOr<MyType> statusor(v);
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+}
+
+TEST(StatusOr, AssignmentFromT) {
+  // Assign to absl::StatusOr<T> from T when T is convertible to
+  // absl::StatusOr<T>
+  {
+    ConvertibleToAnyStatusOr v;
+    absl::StatusOr<ConvertibleToAnyStatusOr> statusor;
+    statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+  // Assign to absl::StatusOr<T> from T when T is convertible to Status
+  {
+    CustomType<MyType, kConvToStatus> v;
+    absl::StatusOr<CustomType<MyType, kConvToStatus>> statusor;
+    statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+TEST(StatusOr, AssignmentFromTypeConvertibleToT) {
+  // Assign to absl::StatusOr<T> from U when U is convertible to T
+  {
+    CustomType<MyType, kConvToT> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_TRUE(statusor.ok());
+  }
+}
+
+TEST(StatusOr, AssignmentFromTypeWithConversionOperatortoStatusOrT) {
+  // Assign to absl::StatusOr<T> from U when U has conversion operator to
+  // absl::StatusOr<T>
+  {
+    CustomType<MyType, kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+  }
+}
+
+TEST(StatusOr, AssignmentFromTypeConvertibleToStatus) {
+  // Assign to absl::StatusOr<T> from U when U is convertible to Status
+  {
+    CustomType<MyType, kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+  {
+    CustomType<MyType, kConvToT | kConvToStatus> v;
+    absl::StatusOr<MyType> statusor;
+    statusor = v;
+    EXPECT_FALSE(statusor.ok());
+    EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+  }
+}
+
+}  // namespace
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index eae75d8..7001679 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -25,7 +25,7 @@
     features = ["parse_headers"],
 )
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "strings",
@@ -54,6 +54,7 @@
         "ascii.h",
         "charconv.h",
         "escaping.h",
+        "internal/string_constant.h",
         "match.h",
         "numbers.h",
         "str_cat.h",
@@ -68,7 +69,6 @@
     deps = [
         ":internal",
         "//absl/base",
-        "//absl/base:bits",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:endian",
@@ -76,6 +76,7 @@
         "//absl/base:throw_delegate",
         "//absl/memory",
         "//absl/meta:type_traits",
+        "//absl/numeric:bits",
         "//absl/numeric:int128",
     ],
 )
@@ -83,19 +84,23 @@
 cc_library(
     name = "internal",
     srcs = [
+        "internal/escaping.cc",
         "internal/ostringstream.cc",
         "internal/utf8.cc",
     ],
     hdrs = [
         "internal/char_map.h",
+        "internal/escaping.h",
         "internal/ostringstream.h",
         "internal/resize_uninitialized.h",
         "internal/utf8.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     deps = [
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:endian",
+        "//absl/base:raw_logging_internal",
         "//absl/meta:type_traits",
     ],
 )
@@ -122,6 +127,7 @@
     copts = ABSL_TEST_COPTS,
     visibility = ["//visibility:private"],
     deps = [
+        ":cord",
         ":strings",
         "//absl/base:core_headers",
         "//absl/container:fixed_array",
@@ -218,6 +224,19 @@
 )
 
 cc_test(
+    name = "string_constant_test",
+    size = "small",
+    srcs = ["internal/string_constant_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":strings",
+        "//absl/meta:type_traits",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
     name = "string_view_benchmark",
     srcs = ["string_view_benchmark.cc"],
     copts = ABSL_TEST_COPTS,
@@ -246,6 +265,88 @@
     ],
 )
 
+cc_library(
+    name = "cord_internal",
+    srcs = [
+        "internal/cord_internal.cc",
+    ],
+    hdrs = [
+        "internal/cord_internal.h",
+        "internal/cord_rep_flat.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    visibility = [
+        "//visibility:private",
+    ],
+    deps = [
+        ":strings",
+        "//absl/base:base_internal",
+        "//absl/base:core_headers",
+        "//absl/container:compressed_tuple",
+        "//absl/container:inlined_vector",
+        "//absl/meta:type_traits",
+    ],
+)
+
+cc_library(
+    name = "cord",
+    srcs = [
+        "cord.cc",
+    ],
+    hdrs = [
+        "cord.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        ":cord_internal",
+        ":internal",
+        ":str_format",
+        ":strings",
+        "//absl/base",
+        "//absl/base:core_headers",
+        "//absl/base:endian",
+        "//absl/base:raw_logging_internal",
+        "//absl/container:fixed_array",
+        "//absl/container:inlined_vector",
+        "//absl/functional:function_ref",
+        "//absl/meta:type_traits",
+        "//absl/types:optional",
+    ],
+)
+
+cc_library(
+    name = "cord_test_helpers",
+    testonly = 1,
+    hdrs = [
+        "cord_test_helpers.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    deps = [
+        ":cord",
+    ],
+)
+
+cc_test(
+    name = "cord_test",
+    size = "medium",
+    srcs = ["cord_test.cc"],
+    copts = ABSL_TEST_COPTS,
+    visibility = ["//visibility:private"],
+    deps = [
+        ":cord",
+        ":cord_test_helpers",
+        ":str_format",
+        ":strings",
+        "//absl/base",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/base:endian",
+        "//absl/base:raw_logging_internal",
+        "//absl/container:fixed_array",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
 cc_test(
     name = "substitute_test",
     size = "small",
@@ -293,6 +394,8 @@
         ":strings",
         "//absl/base:core_headers",
         "//absl/base:dynamic_annotations",
+        "//absl/container:flat_hash_map",
+        "//absl/container:node_hash_map",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -411,10 +514,13 @@
     copts = ABSL_TEST_COPTS,
     visibility = ["//visibility:private"],
     deps = [
+        ":internal",
         ":pow10_helper",
         ":strings",
-        "//absl/base:core_headers",
+        "//absl/base:config",
         "//absl/base:raw_logging_internal",
+        "//absl/random",
+        "//absl/random:distributions",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -428,6 +534,8 @@
     deps = [
         ":strings",
         "//absl/base:raw_logging_internal",
+        "//absl/random",
+        "//absl/random:distributions",
         "@com_github_google_benchmark//:benchmark_main",
     ],
 )
@@ -486,6 +594,7 @@
     copts = ABSL_TEST_COPTS,
     deps = [
         ":strings",
+        "//absl/base:config",
         "//absl/base:raw_logging_internal",
         "@com_google_googletest//:gtest_main",
     ],
@@ -501,6 +610,7 @@
     copts = ABSL_TEST_COPTS,
     deps = [
         ":strings",
+        "//absl/base:config",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -555,8 +665,11 @@
         ":strings",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/functional:function_ref",
         "//absl/meta:type_traits",
+        "//absl/numeric:bits",
         "//absl/numeric:int128",
+        "//absl/types:optional",
         "//absl/types:span",
     ],
 )
@@ -567,6 +680,7 @@
     copts = ABSL_TEST_COPTS,
     visibility = ["//visibility:private"],
     deps = [
+        ":cord",
         ":str_format",
         ":strings",
         "//absl/base:core_headers",
@@ -584,6 +698,7 @@
     deps = [
         ":str_format",
         ":str_format_internal",
+        ":strings",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -630,7 +745,9 @@
     visibility = ["//visibility:private"],
     deps = [
         ":str_format_internal",
-        "//absl/numeric:int128",
+        ":strings",
+        "//absl/base:raw_logging_internal",
+        "//absl/types:optional",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -641,6 +758,7 @@
     copts = ABSL_TEST_COPTS,
     visibility = ["//visibility:private"],
     deps = [
+        ":cord",
         ":str_format_internal",
         "@com_google_googletest//:gtest_main",
     ],
@@ -664,6 +782,7 @@
     srcs = ["internal/pow10_helper.cc"],
     hdrs = ["internal/pow10_helper.h"],
     visibility = ["//visibility:private"],
+    deps = ["//absl/base:config"],
 )
 
 cc_test(
diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt
index ccff444..654d0fd 100644
--- a/absl/strings/CMakeLists.txt
+++ b/absl/strings/CMakeLists.txt
@@ -21,6 +21,7 @@
     "ascii.h"
     "charconv.h"
     "escaping.h"
+    "internal/string_constant.h"
     "match.h"
     "numbers.h"
     "str_cat.h"
@@ -72,6 +73,8 @@
     strings_internal
   HDRS
     "internal/char_map.h"
+    "internal/escaping.cc"
+    "internal/escaping.h"
     "internal/ostringstream.h"
     "internal/resize_uninitialized.h"
     "internal/utf8.h"
@@ -81,8 +84,10 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
+    absl::config
     absl::core_headers
     absl::endian
+    absl::raw_logging_internal
     absl::type_traits
 )
 
@@ -156,6 +161,19 @@
 
 absl_cc_test(
   NAME
+    string_constant_test
+  SRCS
+    "internal/string_constant_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::strings
+    absl::type_traits
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
     string_view_test
   SRCS
     "string_view_test.cc"
@@ -206,6 +224,8 @@
     absl::base
     absl::core_headers
     absl::dynamic_annotations
+    absl::flat_hash_map
+    absl::node_hash_map
     gmock_main
 )
 
@@ -276,7 +296,11 @@
     absl::strings
     absl::core_headers
     absl::pow10_helper
+    absl::config
     absl::raw_logging_internal
+    absl::random_random
+    absl::random_distributions
+    absl::strings_internal
     gmock_main
 )
 
@@ -329,6 +353,7 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::strings
+    absl::config
     absl::raw_logging_internal
     gmock_main
 )
@@ -344,6 +369,7 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::strings
+    absl::config
     gmock_main
 )
 
@@ -380,6 +406,7 @@
   COPTS
     ${ABSL_DEFAULT_COPTS}
   DEPS
+    absl::bits
     absl::strings
     absl::config
     absl::core_headers
@@ -397,6 +424,7 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::str_format
+    absl::cord
     absl::strings
     absl::core_headers
     gmock_main
@@ -412,6 +440,7 @@
   DEPS
     absl::str_format
     absl::str_format_internal
+    absl::strings
     gmock_main
 )
 
@@ -460,7 +489,9 @@
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::strings
     absl::str_format_internal
+    absl::raw_logging_internal
     absl::int128
     gmock_main
 )
@@ -474,6 +505,7 @@
     ${ABSL_TEST_COPTS}
   DEPS
     absl::str_format_internal
+    absl::cord
     gmock_main
 )
 
@@ -499,6 +531,8 @@
     "internal/pow10_helper.cc"
   COPTS
     ${ABSL_TEST_COPTS}
+  DEPS
+    absl::config
   TESTONLY
 )
 
@@ -514,3 +548,64 @@
     absl::str_format
     gmock_main
 )
+
+absl_cc_library(
+  NAME
+    cord
+  HDRS
+    "cord.h"
+  SRCS
+    "cord.cc"
+    "internal/cord_internal.cc"
+    "internal/cord_internal.h"
+    "internal/cord_rep_flat.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::base
+    absl::base_internal
+    absl::compressed_tuple
+    absl::core_headers
+    absl::endian
+    absl::fixed_array
+    absl::function_ref
+    absl::inlined_vector
+    absl::optional
+    absl::raw_logging_internal
+    absl::strings
+    absl::strings_internal
+    absl::type_traits
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    cord_test_helpers
+  HDRS
+    "cord_test_helpers.h"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::cord
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
+    cord_test
+  SRCS
+    "cord_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::cord
+    absl::str_format
+    absl::strings
+    absl::base
+    absl::config
+    absl::core_headers
+    absl::endian
+    absl::raw_logging_internal
+    absl::fixed_array
+    gmock_main
+)
diff --git a/absl/strings/ascii.cc b/absl/strings/ascii.cc
index 3f7c581..93bb03e 100644
--- a/absl/strings/ascii.cc
+++ b/absl/strings/ascii.cc
@@ -15,6 +15,7 @@
 #include "absl/strings/ascii.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace ascii_internal {
 
 // # Table generated by this Python code (bit 0x02 is currently unused):
@@ -56,7 +57,7 @@
 // of these bits is tightly coupled to this implementation, the individual bits
 // are not named. Note that bitfields for all characters above ASCII 127 are
 // zero-initialized.
-const unsigned char kPropertyBits[256] = {
+ABSL_DLL const unsigned char kPropertyBits[256] = {
     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0x00
     0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
     0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,  // 0x10
@@ -78,7 +79,7 @@
 // Array of characters for the ascii_tolower() function. For values 'A'
 // through 'Z', return the lower-case character; otherwise, return the
 // identity of the passed character.
-const char kToLower[256] = {
+ABSL_DLL const char kToLower[256] = {
   '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
   '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
   '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
@@ -116,7 +117,7 @@
 // Array of characters for the ascii_toupper() function. For values 'a'
 // through 'z', return the upper-case character; otherwise, return the
 // identity of the passed character.
-const char kToUpper[256] = {
+ABSL_DLL const char kToUpper[256] = {
   '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
   '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
   '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
@@ -195,4 +196,5 @@
   str->erase(output_it - &(*str)[0]);
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/ascii.h b/absl/strings/ascii.h
index f9e4fd1..b46bc71 100644
--- a/absl/strings/ascii.h
+++ b/absl/strings/ascii.h
@@ -56,19 +56,21 @@
 #include <string>
 
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace ascii_internal {
 
 // Declaration for an array of bitfields holding character information.
-extern const unsigned char kPropertyBits[256];
+ABSL_DLL extern const unsigned char kPropertyBits[256];
 
 // Declaration for the array of characters to upper-case characters.
-extern const char kToUpper[256];
+ABSL_DLL extern const char kToUpper[256];
 
 // Declaration for the array of characters to lower-case characters.
-extern const char kToLower[256];
+ABSL_DLL extern const char kToLower[256];
 
 }  // namespace ascii_internal
 
@@ -234,6 +236,7 @@
 // Removes leading, trailing, and consecutive internal whitespace.
 void RemoveExtraAsciiWhitespace(std::string*);
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_ASCII_H_
diff --git a/absl/strings/charconv.cc b/absl/strings/charconv.cc
index bc07e7a..b8674c2 100644
--- a/absl/strings/charconv.cc
+++ b/absl/strings/charconv.cc
@@ -20,7 +20,7 @@
 #include <cstring>
 
 #include "absl/base/casts.h"
-#include "absl/base/internal/bits.h"
+#include "absl/numeric/bits.h"
 #include "absl/numeric/int128.h"
 #include "absl/strings/internal/charconv_bigint.h"
 #include "absl/strings/internal/charconv_parse.h"
@@ -57,6 +57,7 @@
 // narrower mantissas.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 template <typename FloatType>
@@ -241,11 +242,11 @@
 
 // Returns the bit width of the given uint128.  (Equivalently, returns 128
 // minus the number of leading zero bits.)
-int BitWidth(uint128 value) {
+unsigned BitWidth(uint128 value) {
   if (Uint128High64(value) == 0) {
-    return 64 - base_internal::CountLeadingZeros64(Uint128Low64(value));
+    return static_cast<unsigned>(bit_width(Uint128Low64(value)));
   }
-  return 128 - base_internal::CountLeadingZeros64(Uint128High64(value));
+  return 128 - countl_zero(Uint128High64(value));
 }
 
 // Calculates how far to the right a mantissa needs to be shifted to create a
@@ -518,7 +519,7 @@
     const strings_internal::ParsedFloat& parsed_hex) {
   uint64_t mantissa = parsed_hex.mantissa;
   int exponent = parsed_hex.exponent;
-  int mantissa_width = 64 - base_internal::CountLeadingZeros64(mantissa);
+  auto mantissa_width = static_cast<unsigned>(bit_width(mantissa));
   const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent);
   bool result_exact;
   exponent += shift;
@@ -618,10 +619,10 @@
       // Either we failed to parse a hex float after the "0x", or we read
       // "0xinf" or "0xnan" which we don't want to match.
       //
-      // However, a std::string that begins with "0x" also begins with "0", which
+      // However, a string that begins with "0x" also begins with "0", which
       // is normally a valid match for the number zero.  So we want these
       // strings to match zero unless fmt_flags is `scientific`.  (This flag
-      // means an exponent is required, which the std::string "0" does not have.)
+      // means an exponent is required, which the string "0" does not have.)
       if (fmt_flags == chars_format::scientific) {
         result.ec = std::errc::invalid_argument;
       } else {
@@ -672,7 +673,6 @@
     EncodeResult(calculated, negative, &result, &value);
     return result;
   }
-  return result;
 }
 }  // namespace
 
@@ -980,4 +980,5 @@
 };
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/charconv.h b/absl/strings/charconv.h
index 3f5891b..e04be32 100644
--- a/absl/strings/charconv.h
+++ b/absl/strings/charconv.h
@@ -17,7 +17,10 @@
 
 #include <system_error>  // NOLINT(build/c++11)
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // Workalike compatibilty version of std::chars_format from C++17.
 //
@@ -110,6 +113,7 @@
   return lhs;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_CHARCONV_H_
diff --git a/absl/strings/charconv_benchmark.cc b/absl/strings/charconv_benchmark.cc
index 644b2ab..e8c7371 100644
--- a/absl/strings/charconv_benchmark.cc
+++ b/absl/strings/charconv_benchmark.cc
@@ -132,7 +132,7 @@
 std::string MakeHardCase(int length) {
   // The number 1.1521...e-297 is exactly halfway between 12345 * 2**-1000 and
   // the next larger representable number.  The digits of this number are in
-  // the std::string below.
+  // the string below.
   const std::string digits =
       "1."
       "152113937042223790993097181572444900347587985074226836242307364987727724"
diff --git a/absl/strings/charconv_test.cc b/absl/strings/charconv_test.cc
index b58fad2..b83de5a 100644
--- a/absl/strings/charconv_test.cc
+++ b/absl/strings/charconv_test.cc
@@ -511,6 +511,13 @@
   EXPECT_EQ(f, std::numeric_limits<float>::max());
 }
 
+TEST(FromChars, RegressionTestsFromFuzzer) {
+  absl::string_view src = "0x21900000p00000000099";
+  float f;
+  auto result = absl::from_chars(src.data(), src.data() + src.size(), f);
+  EXPECT_EQ(result.ec, std::errc::result_out_of_range);
+}
+
 TEST(FromChars, ReturnValuePtr) {
   // Check that `ptr` points one past the number scanned, even if that number
   // is not representable.
@@ -646,7 +653,9 @@
                      negative_from_chars_float);
     EXPECT_TRUE(std::signbit(negative_from_chars_float));
     EXPECT_FALSE(Identical(negative_from_chars_float, from_chars_float));
-    from_chars_float = std::copysign(from_chars_float, -1.0);
+    // Use the (float, float) overload of std::copysign to prevent narrowing;
+    // see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98251.
+    from_chars_float = std::copysign(from_chars_float, -1.0f);
     EXPECT_TRUE(Identical(negative_from_chars_float, from_chars_float));
   }
 }
diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc
new file mode 100644
index 0000000..7cadf75
--- /dev/null
+++ b/absl/strings/cord.cc
@@ -0,0 +1,1825 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/cord.h"
+
+#include <algorithm>
+#include <atomic>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <iomanip>
+#include <iostream>
+#include <limits>
+#include <ostream>
+#include <sstream>
+#include <type_traits>
+#include <unordered_set>
+#include <vector>
+
+#include "absl/base/casts.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/base/port.h"
+#include "absl/container/fixed_array.h"
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/cord_rep_flat.h"
+#include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+using ::absl::cord_internal::CordRep;
+using ::absl::cord_internal::CordRepConcat;
+using ::absl::cord_internal::CordRepExternal;
+using ::absl::cord_internal::CordRepFlat;
+using ::absl::cord_internal::CordRepSubstring;
+
+using ::absl::cord_internal::kMinFlatLength;
+using ::absl::cord_internal::kMaxFlatLength;
+
+using ::absl::cord_internal::CONCAT;
+using ::absl::cord_internal::EXTERNAL;
+using ::absl::cord_internal::FLAT;
+using ::absl::cord_internal::RING;
+using ::absl::cord_internal::SUBSTRING;
+
+using ::absl::cord_internal::kInlinedVectorSize;
+using ::absl::cord_internal::kMaxBytesToCopy;
+
+constexpr uint64_t Fibonacci(unsigned char n, uint64_t a = 0, uint64_t b = 1) {
+  return n == 0 ? a : Fibonacci(n - 1, b, a + b);
+}
+
+static_assert(Fibonacci(63) == 6557470319842,
+              "Fibonacci values computed incorrectly");
+
+// Minimum length required for a given depth tree -- a tree is considered
+// balanced if
+//      length(t) >= min_length[depth(t)]
+// The root node depth is allowed to become twice as large to reduce rebalancing
+// for larger strings (see IsRootBalanced).
+static constexpr uint64_t min_length[] = {
+    Fibonacci(2),          Fibonacci(3),  Fibonacci(4),  Fibonacci(5),
+    Fibonacci(6),          Fibonacci(7),  Fibonacci(8),  Fibonacci(9),
+    Fibonacci(10),         Fibonacci(11), Fibonacci(12), Fibonacci(13),
+    Fibonacci(14),         Fibonacci(15), Fibonacci(16), Fibonacci(17),
+    Fibonacci(18),         Fibonacci(19), Fibonacci(20), Fibonacci(21),
+    Fibonacci(22),         Fibonacci(23), Fibonacci(24), Fibonacci(25),
+    Fibonacci(26),         Fibonacci(27), Fibonacci(28), Fibonacci(29),
+    Fibonacci(30),         Fibonacci(31), Fibonacci(32), Fibonacci(33),
+    Fibonacci(34),         Fibonacci(35), Fibonacci(36), Fibonacci(37),
+    Fibonacci(38),         Fibonacci(39), Fibonacci(40), Fibonacci(41),
+    Fibonacci(42),         Fibonacci(43), Fibonacci(44), Fibonacci(45),
+    Fibonacci(46),         Fibonacci(47),
+    0xffffffffffffffffull,  // Avoid overflow
+};
+
+static const int kMinLengthSize = ABSL_ARRAYSIZE(min_length);
+
+static inline bool IsRootBalanced(CordRep* node) {
+  if (node->tag != CONCAT) {
+    return true;
+  } else if (node->concat()->depth() <= 15) {
+    return true;
+  } else if (node->concat()->depth() > kMinLengthSize) {
+    return false;
+  } else {
+    // Allow depth to become twice as large as implied by fibonacci rule to
+    // reduce rebalancing for larger strings.
+    return (node->length >= min_length[node->concat()->depth() / 2]);
+  }
+}
+
+static CordRep* Rebalance(CordRep* node);
+static void DumpNode(CordRep* rep, bool include_data, std::ostream* os);
+static bool VerifyNode(CordRep* root, CordRep* start_node,
+                       bool full_validation);
+
+static inline CordRep* VerifyTree(CordRep* node) {
+  // Verification is expensive, so only do it in debug mode.
+  // Even in debug mode we normally do only light validation.
+  // If you are debugging Cord itself, you should define the
+  // macro EXTRA_CORD_VALIDATION, e.g. by adding
+  // --copt=-DEXTRA_CORD_VALIDATION to the blaze line.
+#ifdef EXTRA_CORD_VALIDATION
+  assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/true));
+#else   // EXTRA_CORD_VALIDATION
+  assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/false));
+#endif  // EXTRA_CORD_VALIDATION
+  static_cast<void>(&VerifyNode);
+
+  return node;
+}
+
+// Return the depth of a node
+static int Depth(const CordRep* rep) {
+  if (rep->tag == CONCAT) {
+    return rep->concat()->depth();
+  } else {
+    return 0;
+  }
+}
+
+static void SetConcatChildren(CordRepConcat* concat, CordRep* left,
+                              CordRep* right) {
+  concat->left = left;
+  concat->right = right;
+
+  concat->length = left->length + right->length;
+  concat->set_depth(1 + std::max(Depth(left), Depth(right)));
+}
+
+// Create a concatenation of the specified nodes.
+// Does not change the refcounts of "left" and "right".
+// The returned node has a refcount of 1.
+static CordRep* RawConcat(CordRep* left, CordRep* right) {
+  // Avoid making degenerate concat nodes (one child is empty)
+  if (left == nullptr) return right;
+  if (right == nullptr) return left;
+  if (left->length == 0) {
+    CordRep::Unref(left);
+    return right;
+  }
+  if (right->length == 0) {
+    CordRep::Unref(right);
+    return left;
+  }
+
+  CordRepConcat* rep = new CordRepConcat();
+  rep->tag = CONCAT;
+  SetConcatChildren(rep, left, right);
+
+  return rep;
+}
+
+static CordRep* Concat(CordRep* left, CordRep* right) {
+  CordRep* rep = RawConcat(left, right);
+  if (rep != nullptr && !IsRootBalanced(rep)) {
+    rep = Rebalance(rep);
+  }
+  return VerifyTree(rep);
+}
+
+// Make a balanced tree out of an array of leaf nodes.
+static CordRep* MakeBalancedTree(CordRep** reps, size_t n) {
+  // Make repeated passes over the array, merging adjacent pairs
+  // until we are left with just a single node.
+  while (n > 1) {
+    size_t dst = 0;
+    for (size_t src = 0; src < n; src += 2) {
+      if (src + 1 < n) {
+        reps[dst] = Concat(reps[src], reps[src + 1]);
+      } else {
+        reps[dst] = reps[src];
+      }
+      dst++;
+    }
+    n = dst;
+  }
+
+  return reps[0];
+}
+
+// Create a new tree out of the specified array.
+// The returned node has a refcount of 1.
+static CordRep* NewTree(const char* data,
+                        size_t length,
+                        size_t alloc_hint) {
+  if (length == 0) return nullptr;
+  absl::FixedArray<CordRep*> reps((length - 1) / kMaxFlatLength + 1);
+  size_t n = 0;
+  do {
+    const size_t len = std::min(length, kMaxFlatLength);
+    CordRep* rep = CordRepFlat::New(len + alloc_hint);
+    rep->length = len;
+    memcpy(rep->data, data, len);
+    reps[n++] = VerifyTree(rep);
+    data += len;
+    length -= len;
+  } while (length != 0);
+  return MakeBalancedTree(reps.data(), n);
+}
+
+namespace cord_internal {
+
+void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) {
+  assert(!data.empty());
+  rep->length = data.size();
+  rep->tag = EXTERNAL;
+  rep->base = data.data();
+  VerifyTree(rep);
+}
+
+}  // namespace cord_internal
+
+static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) {
+  // Never create empty substring nodes
+  if (length == 0) {
+    CordRep::Unref(child);
+    return nullptr;
+  } else {
+    CordRepSubstring* rep = new CordRepSubstring();
+    assert((offset + length) <= child->length);
+    rep->length = length;
+    rep->tag = SUBSTRING;
+    rep->start = offset;
+    rep->child = child;
+    return VerifyTree(rep);
+  }
+}
+
+// --------------------------------------------------------------------
+// Cord::InlineRep functions
+
+constexpr unsigned char Cord::InlineRep::kMaxInline;
+
+inline void Cord::InlineRep::set_data(const char* data, size_t n,
+                                      bool nullify_tail) {
+  static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15");
+
+  cord_internal::SmallMemmove(data_.as_chars, data, n, nullify_tail);
+  set_tagged_size(static_cast<char>(n));
+}
+
+inline char* Cord::InlineRep::set_data(size_t n) {
+  assert(n <= kMaxInline);
+  ResetToEmpty();
+  set_tagged_size(static_cast<char>(n));
+  return data_.as_chars;
+}
+
+inline CordRep* Cord::InlineRep::force_tree(size_t extra_hint) {
+  size_t len = tagged_size();
+  if (len > kMaxInline) {
+    return data_.as_tree.rep;
+  }
+
+  CordRep* result = CordRepFlat::New(len + extra_hint);
+  result->length = len;
+  static_assert(kMinFlatLength >= sizeof(data_.as_chars), "");
+  memcpy(result->data, data_.as_chars, sizeof(data_.as_chars));
+  set_tree(result);
+  return result;
+}
+
+inline void Cord::InlineRep::reduce_size(size_t n) {
+  size_t tag = tagged_size();
+  assert(tag <= kMaxInline);
+  assert(tag >= n);
+  tag -= n;
+  memset(data_.as_chars + tag, 0, n);
+  set_tagged_size(static_cast<char>(tag));
+}
+
+inline void Cord::InlineRep::remove_prefix(size_t n) {
+  cord_internal::SmallMemmove(data_.as_chars, data_.as_chars + n,
+                              tagged_size() - n);
+  reduce_size(n);
+}
+
+void Cord::InlineRep::AppendTree(CordRep* tree) {
+  if (tree == nullptr) return;
+  size_t len = tagged_size();
+  if (len == 0) {
+    set_tree(tree);
+  } else {
+    set_tree(Concat(force_tree(0), tree));
+  }
+}
+
+void Cord::InlineRep::PrependTree(CordRep* tree) {
+  assert(tree != nullptr);
+  size_t len = tagged_size();
+  if (len == 0) {
+    set_tree(tree);
+  } else {
+    set_tree(Concat(tree, force_tree(0)));
+  }
+}
+
+// Searches for a non-full flat node at the rightmost leaf of the tree. If a
+// suitable leaf is found, the function will update the length field for all
+// nodes to account for the size increase. The append region address will be
+// written to region and the actual size increase will be written to size.
+static inline bool PrepareAppendRegion(CordRep* root, char** region,
+                                       size_t* size, size_t max_length) {
+  // Search down the right-hand path for a non-full FLAT node.
+  CordRep* dst = root;
+  while (dst->tag == CONCAT && dst->refcount.IsOne()) {
+    dst = dst->concat()->right;
+  }
+
+  if (dst->tag < FLAT || !dst->refcount.IsOne()) {
+    *region = nullptr;
+    *size = 0;
+    return false;
+  }
+
+  const size_t in_use = dst->length;
+  const size_t capacity = dst->flat()->Capacity();
+  if (in_use == capacity) {
+    *region = nullptr;
+    *size = 0;
+    return false;
+  }
+
+  size_t size_increase = std::min(capacity - in_use, max_length);
+
+  // We need to update the length fields for all nodes, including the leaf node.
+  for (CordRep* rep = root; rep != dst; rep = rep->concat()->right) {
+    rep->length += size_increase;
+  }
+  dst->length += size_increase;
+
+  *region = dst->data + in_use;
+  *size = size_increase;
+  return true;
+}
+
+void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
+                                      size_t max_length) {
+  if (max_length == 0) {
+    *region = nullptr;
+    *size = 0;
+    return;
+  }
+
+  // Try to fit in the inline buffer if possible.
+  size_t inline_length = tagged_size();
+  if (inline_length < kMaxInline && max_length <= kMaxInline - inline_length) {
+    *region = data_.as_chars + inline_length;
+    *size = max_length;
+    set_tagged_size(static_cast<char>(inline_length + max_length));
+    return;
+  }
+
+  CordRep* root = force_tree(max_length);
+
+  if (PrepareAppendRegion(root, region, size, max_length)) {
+    return;
+  }
+
+  // Allocate new node.
+  CordRepFlat* new_node =
+      CordRepFlat::New(std::max(static_cast<size_t>(root->length), max_length));
+  new_node->length = std::min(new_node->Capacity(), max_length);
+  *region = new_node->data;
+  *size = new_node->length;
+  replace_tree(Concat(root, new_node));
+}
+
+void Cord::InlineRep::GetAppendRegion(char** region, size_t* size) {
+  const size_t max_length = std::numeric_limits<size_t>::max();
+
+  // Try to fit in the inline buffer if possible.
+  size_t inline_length = tagged_size();
+  if (inline_length < kMaxInline) {
+    *region = data_.as_chars + inline_length;
+    *size = kMaxInline - inline_length;
+    set_tagged_size(kMaxInline);
+    return;
+  }
+
+  CordRep* root = force_tree(max_length);
+
+  if (PrepareAppendRegion(root, region, size, max_length)) {
+    return;
+  }
+
+  // Allocate new node.
+  CordRepFlat* new_node = CordRepFlat::New(root->length);
+  new_node->length = new_node->Capacity();
+  *region = new_node->data;
+  *size = new_node->length;
+  replace_tree(Concat(root, new_node));
+}
+
+// If the rep is a leaf, this will increment the value at total_mem_usage and
+// will return true.
+static bool RepMemoryUsageLeaf(const CordRep* rep, size_t* total_mem_usage) {
+  if (rep->tag >= FLAT) {
+    *total_mem_usage += rep->flat()->AllocatedSize();
+    return true;
+  }
+  if (rep->tag == EXTERNAL) {
+    *total_mem_usage += sizeof(CordRepConcat) + rep->length;
+    return true;
+  }
+  return false;
+}
+
+void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
+  ClearSlow();
+
+  data_ = src.data_;
+  if (is_tree()) {
+    CordRep::Ref(tree());
+  }
+}
+
+void Cord::InlineRep::ClearSlow() {
+  if (is_tree()) {
+    CordRep::Unref(tree());
+  }
+  ResetToEmpty();
+}
+
+// --------------------------------------------------------------------
+// Constructors and destructors
+
+Cord::Cord(const Cord& src) : contents_(src.contents_) {
+  if (CordRep* tree = contents_.tree()) {
+    CordRep::Ref(tree);
+  }
+}
+
+Cord::Cord(absl::string_view src) {
+  const size_t n = src.size();
+  if (n <= InlineRep::kMaxInline) {
+    contents_.set_data(src.data(), n, false);
+  } else {
+    contents_.set_tree(NewTree(src.data(), n, 0));
+  }
+}
+
+template <typename T, Cord::EnableIfString<T>>
+Cord::Cord(T&& src) {
+  if (
+      // String is short: copy data to avoid external block overhead.
+      src.size() <= kMaxBytesToCopy ||
+      // String is wasteful: copy data to avoid pinning too much unused memory.
+      src.size() < src.capacity() / 2
+  ) {
+    if (src.size() <= InlineRep::kMaxInline) {
+      contents_.set_data(src.data(), src.size(), false);
+    } else {
+      contents_.set_tree(NewTree(src.data(), src.size(), 0));
+    }
+  } else {
+    struct StringReleaser {
+      void operator()(absl::string_view /* data */) {}
+      std::string data;
+    };
+    const absl::string_view original_data = src;
+    auto* rep = static_cast<
+        ::absl::cord_internal::CordRepExternalImpl<StringReleaser>*>(
+        absl::cord_internal::NewExternalRep(
+            original_data, StringReleaser{std::forward<T>(src)}));
+    // Moving src may have invalidated its data pointer, so adjust it.
+    rep->base = rep->template get<0>().data.data();
+    contents_.set_tree(rep);
+  }
+}
+
+template Cord::Cord(std::string&& src);
+
+// The destruction code is separate so that the compiler can determine
+// that it does not need to call the destructor on a moved-from Cord.
+void Cord::DestroyCordSlow() {
+  if (CordRep* tree = contents_.tree()) {
+    CordRep::Unref(VerifyTree(tree));
+  }
+}
+
+// --------------------------------------------------------------------
+// Mutators
+
+void Cord::Clear() {
+  if (CordRep* tree = contents_.clear()) {
+    CordRep::Unref(tree);
+  }
+}
+
+Cord& Cord::operator=(absl::string_view src) {
+
+  const char* data = src.data();
+  size_t length = src.size();
+  CordRep* tree = contents_.tree();
+  if (length <= InlineRep::kMaxInline) {
+    // Embed into this->contents_
+    contents_.set_data(data, length, true);
+    if (tree) CordRep::Unref(tree);
+    return *this;
+  }
+  if (tree != nullptr && tree->tag >= FLAT &&
+      tree->flat()->Capacity() >= length &&
+      tree->refcount.IsOne()) {
+    // Copy in place if the existing FLAT node is reusable.
+    memmove(tree->data, data, length);
+    tree->length = length;
+    VerifyTree(tree);
+    return *this;
+  }
+  contents_.set_tree(NewTree(data, length, 0));
+  if (tree) CordRep::Unref(tree);
+  return *this;
+}
+
+template <typename T, Cord::EnableIfString<T>>
+Cord& Cord::operator=(T&& src) {
+  if (src.size() <= kMaxBytesToCopy) {
+    *this = absl::string_view(src);
+  } else {
+    *this = Cord(std::forward<T>(src));
+  }
+  return *this;
+}
+
+template Cord& Cord::operator=(std::string&& src);
+
+// TODO(sanjay): Move to Cord::InlineRep section of file.  For now,
+// we keep it here to make diffs easier.
+void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
+  if (src_size == 0) return;  // memcpy(_, nullptr, 0) is undefined.
+  // Try to fit in the inline buffer if possible.
+  size_t inline_length = tagged_size();
+  if (inline_length < kMaxInline && src_size <= kMaxInline - inline_length) {
+    // Append new data to embedded array
+    set_tagged_size(static_cast<char>(inline_length + src_size));
+    memcpy(data_.as_chars + inline_length, src_data, src_size);
+    return;
+  }
+
+  CordRep* root = tree();
+
+  size_t appended = 0;
+  if (root) {
+    char* region;
+    if (PrepareAppendRegion(root, &region, &appended, src_size)) {
+      memcpy(region, src_data, appended);
+    }
+  } else {
+    // It is possible that src_data == data_, but when we transition from an
+    // InlineRep to a tree we need to assign data_ = root via set_tree. To
+    // avoid corrupting the source data before we copy it, delay calling
+    // set_tree until after we've copied data.
+    // We are going from an inline size to beyond inline size. Make the new size
+    // either double the inlined size, or the added size + 10%.
+    const size_t size1 = inline_length * 2 + src_size;
+    const size_t size2 = inline_length + src_size / 10;
+    root = CordRepFlat::New(std::max<size_t>(size1, size2));
+    appended = std::min(
+        src_size, root->flat()->Capacity() - inline_length);
+    memcpy(root->data, data_.as_chars, inline_length);
+    memcpy(root->data + inline_length, src_data, appended);
+    root->length = inline_length + appended;
+    set_tree(root);
+  }
+
+  src_data += appended;
+  src_size -= appended;
+  if (src_size == 0) {
+    return;
+  }
+
+  // Use new block(s) for any remaining bytes that were not handled above.
+  // Alloc extra memory only if the right child of the root of the new tree is
+  // going to be a FLAT node, which will permit further inplace appends.
+  size_t length = src_size;
+  if (src_size < kMaxFlatLength) {
+    // The new length is either
+    // - old size + 10%
+    // - old_size + src_size
+    // This will cause a reasonable conservative step-up in size that is still
+    // large enough to avoid excessive amounts of small fragments being added.
+    length = std::max<size_t>(root->length / 10, src_size);
+  }
+  set_tree(Concat(root, NewTree(src_data, src_size, length - src_size)));
+}
+
+inline CordRep* Cord::TakeRep() const& {
+  return CordRep::Ref(contents_.tree());
+}
+
+inline CordRep* Cord::TakeRep() && {
+  CordRep* rep = contents_.tree();
+  contents_.clear();
+  return rep;
+}
+
+template <typename C>
+inline void Cord::AppendImpl(C&& src) {
+  if (empty()) {
+    // In case of an empty destination avoid allocating a new node, do not copy
+    // data.
+    *this = std::forward<C>(src);
+    return;
+  }
+
+  // For short cords, it is faster to copy data if there is room in dst.
+  const size_t src_size = src.contents_.size();
+  if (src_size <= kMaxBytesToCopy) {
+    CordRep* src_tree = src.contents_.tree();
+    if (src_tree == nullptr) {
+      // src has embedded data.
+      contents_.AppendArray(src.contents_.data(), src_size);
+      return;
+    }
+    if (src_tree->tag >= FLAT) {
+      // src tree just has one flat node.
+      contents_.AppendArray(src_tree->data, src_size);
+      return;
+    }
+    if (&src == this) {
+      // ChunkIterator below assumes that src is not modified during traversal.
+      Append(Cord(src));
+      return;
+    }
+    // TODO(mec): Should we only do this if "dst" has space?
+    for (absl::string_view chunk : src.Chunks()) {
+      Append(chunk);
+    }
+    return;
+  }
+
+  // Guaranteed to be a tree (kMaxBytesToCopy > kInlinedSize)
+  contents_.AppendTree(std::forward<C>(src).TakeRep());
+}
+
+void Cord::Append(const Cord& src) { AppendImpl(src); }
+
+void Cord::Append(Cord&& src) { AppendImpl(std::move(src)); }
+
+template <typename T, Cord::EnableIfString<T>>
+void Cord::Append(T&& src) {
+  if (src.size() <= kMaxBytesToCopy) {
+    Append(absl::string_view(src));
+  } else {
+    Append(Cord(std::forward<T>(src)));
+  }
+}
+
+template void Cord::Append(std::string&& src);
+
+void Cord::Prepend(const Cord& src) {
+  CordRep* src_tree = src.contents_.tree();
+  if (src_tree != nullptr) {
+    CordRep::Ref(src_tree);
+    contents_.PrependTree(src_tree);
+    return;
+  }
+
+  // `src` cord is inlined.
+  absl::string_view src_contents(src.contents_.data(), src.contents_.size());
+  return Prepend(src_contents);
+}
+
+void Cord::Prepend(absl::string_view src) {
+  if (src.empty()) return;  // memcpy(_, nullptr, 0) is undefined.
+  size_t cur_size = contents_.size();
+  if (!contents_.is_tree() && cur_size + src.size() <= InlineRep::kMaxInline) {
+    // Use embedded storage.
+    char data[InlineRep::kMaxInline + 1] = {0};
+    data[InlineRep::kMaxInline] = cur_size + src.size();  // set size
+    memcpy(data, src.data(), src.size());
+    memcpy(data + src.size(), contents_.data(), cur_size);
+    memcpy(reinterpret_cast<void*>(&contents_), data,
+           InlineRep::kMaxInline + 1);
+  } else {
+    contents_.PrependTree(NewTree(src.data(), src.size(), 0));
+  }
+}
+
+template <typename T, Cord::EnableIfString<T>>
+inline void Cord::Prepend(T&& src) {
+  if (src.size() <= kMaxBytesToCopy) {
+    Prepend(absl::string_view(src));
+  } else {
+    Prepend(Cord(std::forward<T>(src)));
+  }
+}
+
+template void Cord::Prepend(std::string&& src);
+
+static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
+  if (n >= node->length) return nullptr;
+  if (n == 0) return CordRep::Ref(node);
+  absl::InlinedVector<CordRep*, kInlinedVectorSize> rhs_stack;
+
+  while (node->tag == CONCAT) {
+    assert(n <= node->length);
+    if (n < node->concat()->left->length) {
+      // Push right to stack, descend left.
+      rhs_stack.push_back(node->concat()->right);
+      node = node->concat()->left;
+    } else {
+      // Drop left, descend right.
+      n -= node->concat()->left->length;
+      node = node->concat()->right;
+    }
+  }
+  assert(n <= node->length);
+
+  if (n == 0) {
+    CordRep::Ref(node);
+  } else {
+    size_t start = n;
+    size_t len = node->length - n;
+    if (node->tag == SUBSTRING) {
+      // Consider in-place update of node, similar to in RemoveSuffixFrom().
+      start += node->substring()->start;
+      node = node->substring()->child;
+    }
+    node = NewSubstring(CordRep::Ref(node), start, len);
+  }
+  while (!rhs_stack.empty()) {
+    node = Concat(node, CordRep::Ref(rhs_stack.back()));
+    rhs_stack.pop_back();
+  }
+  return node;
+}
+
+// RemoveSuffixFrom() is very similar to RemovePrefixFrom(), with the
+// exception that removing a suffix has an optimization where a node may be
+// edited in place iff that node and all its ancestors have a refcount of 1.
+static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
+  if (n >= node->length) return nullptr;
+  if (n == 0) return CordRep::Ref(node);
+  absl::InlinedVector<CordRep*, kInlinedVectorSize> lhs_stack;
+  bool inplace_ok = node->refcount.IsOne();
+
+  while (node->tag == CONCAT) {
+    assert(n <= node->length);
+    if (n < node->concat()->right->length) {
+      // Push left to stack, descend right.
+      lhs_stack.push_back(node->concat()->left);
+      node = node->concat()->right;
+    } else {
+      // Drop right, descend left.
+      n -= node->concat()->right->length;
+      node = node->concat()->left;
+    }
+    inplace_ok = inplace_ok && node->refcount.IsOne();
+  }
+  assert(n <= node->length);
+
+  if (n == 0) {
+    CordRep::Ref(node);
+  } else if (inplace_ok && node->tag != EXTERNAL) {
+    // Consider making a new buffer if the current node capacity is much
+    // larger than the new length.
+    CordRep::Ref(node);
+    node->length -= n;
+  } else {
+    size_t start = 0;
+    size_t len = node->length - n;
+    if (node->tag == SUBSTRING) {
+      start = node->substring()->start;
+      node = node->substring()->child;
+    }
+    node = NewSubstring(CordRep::Ref(node), start, len);
+  }
+  while (!lhs_stack.empty()) {
+    node = Concat(CordRep::Ref(lhs_stack.back()), node);
+    lhs_stack.pop_back();
+  }
+  return node;
+}
+
+void Cord::RemovePrefix(size_t n) {
+  ABSL_INTERNAL_CHECK(n <= size(),
+                      absl::StrCat("Requested prefix size ", n,
+                                   " exceeds Cord's size ", size()));
+  CordRep* tree = contents_.tree();
+  if (tree == nullptr) {
+    contents_.remove_prefix(n);
+  } else {
+    CordRep* newrep = RemovePrefixFrom(tree, n);
+    CordRep::Unref(tree);
+    contents_.replace_tree(VerifyTree(newrep));
+  }
+}
+
+void Cord::RemoveSuffix(size_t n) {
+  ABSL_INTERNAL_CHECK(n <= size(),
+                      absl::StrCat("Requested suffix size ", n,
+                                   " exceeds Cord's size ", size()));
+  CordRep* tree = contents_.tree();
+  if (tree == nullptr) {
+    contents_.reduce_size(n);
+  } else {
+    CordRep* newrep = RemoveSuffixFrom(tree, n);
+    CordRep::Unref(tree);
+    contents_.replace_tree(VerifyTree(newrep));
+  }
+}
+
+// Work item for NewSubRange().
+struct SubRange {
+  SubRange(CordRep* a_node, size_t a_pos, size_t a_n)
+      : node(a_node), pos(a_pos), n(a_n) {}
+  CordRep* node;  // nullptr means concat last 2 results.
+  size_t pos;
+  size_t n;
+};
+
+static CordRep* NewSubRange(CordRep* node, size_t pos, size_t n) {
+  absl::InlinedVector<CordRep*, kInlinedVectorSize> results;
+  absl::InlinedVector<SubRange, kInlinedVectorSize> todo;
+  todo.push_back(SubRange(node, pos, n));
+  do {
+    const SubRange& sr = todo.back();
+    node = sr.node;
+    pos = sr.pos;
+    n = sr.n;
+    todo.pop_back();
+
+    if (node == nullptr) {
+      assert(results.size() >= 2);
+      CordRep* right = results.back();
+      results.pop_back();
+      CordRep* left = results.back();
+      results.pop_back();
+      results.push_back(Concat(left, right));
+    } else if (pos == 0 && n == node->length) {
+      results.push_back(CordRep::Ref(node));
+    } else if (node->tag != CONCAT) {
+      if (node->tag == SUBSTRING) {
+        pos += node->substring()->start;
+        node = node->substring()->child;
+      }
+      results.push_back(NewSubstring(CordRep::Ref(node), pos, n));
+    } else if (pos + n <= node->concat()->left->length) {
+      todo.push_back(SubRange(node->concat()->left, pos, n));
+    } else if (pos >= node->concat()->left->length) {
+      pos -= node->concat()->left->length;
+      todo.push_back(SubRange(node->concat()->right, pos, n));
+    } else {
+      size_t left_n = node->concat()->left->length - pos;
+      todo.push_back(SubRange(nullptr, 0, 0));  // Concat()
+      todo.push_back(SubRange(node->concat()->right, 0, n - left_n));
+      todo.push_back(SubRange(node->concat()->left, pos, left_n));
+    }
+  } while (!todo.empty());
+  assert(results.size() == 1);
+  return results[0];
+}
+
+Cord Cord::Subcord(size_t pos, size_t new_size) const {
+  Cord sub_cord;
+  size_t length = size();
+  if (pos > length) pos = length;
+  if (new_size > length - pos) new_size = length - pos;
+  CordRep* tree = contents_.tree();
+  if (tree == nullptr) {
+    // sub_cord is newly constructed, no need to re-zero-out the tail of
+    // contents_ memory.
+    sub_cord.contents_.set_data(contents_.data() + pos, new_size, false);
+  } else if (new_size == 0) {
+    // We want to return empty subcord, so nothing to do.
+  } else if (new_size <= InlineRep::kMaxInline) {
+    Cord::ChunkIterator it = chunk_begin();
+    it.AdvanceBytes(pos);
+    char* dest = sub_cord.contents_.data_.as_chars;
+    size_t remaining_size = new_size;
+    while (remaining_size > it->size()) {
+      cord_internal::SmallMemmove(dest, it->data(), it->size());
+      remaining_size -= it->size();
+      dest += it->size();
+      ++it;
+    }
+    cord_internal::SmallMemmove(dest, it->data(), remaining_size);
+    sub_cord.contents_.set_tagged_size(new_size);
+  } else {
+    sub_cord.contents_.set_tree(NewSubRange(tree, pos, new_size));
+  }
+  return sub_cord;
+}
+
+// --------------------------------------------------------------------
+// Balancing
+
+class CordForest {
+ public:
+  explicit CordForest(size_t length)
+      : root_length_(length), trees_(kMinLengthSize, nullptr) {}
+
+  void Build(CordRep* cord_root) {
+    std::vector<CordRep*> pending = {cord_root};
+
+    while (!pending.empty()) {
+      CordRep* node = pending.back();
+      pending.pop_back();
+      CheckNode(node);
+      if (ABSL_PREDICT_FALSE(node->tag != CONCAT)) {
+        AddNode(node);
+        continue;
+      }
+
+      CordRepConcat* concat_node = node->concat();
+      if (concat_node->depth() >= kMinLengthSize ||
+          concat_node->length < min_length[concat_node->depth()]) {
+        pending.push_back(concat_node->right);
+        pending.push_back(concat_node->left);
+
+        if (concat_node->refcount.IsOne()) {
+          concat_node->left = concat_freelist_;
+          concat_freelist_ = concat_node;
+        } else {
+          CordRep::Ref(concat_node->right);
+          CordRep::Ref(concat_node->left);
+          CordRep::Unref(concat_node);
+        }
+      } else {
+        AddNode(node);
+      }
+    }
+  }
+
+  CordRep* ConcatNodes() {
+    CordRep* sum = nullptr;
+    for (auto* node : trees_) {
+      if (node == nullptr) continue;
+
+      sum = PrependNode(node, sum);
+      root_length_ -= node->length;
+      if (root_length_ == 0) break;
+    }
+    ABSL_INTERNAL_CHECK(sum != nullptr, "Failed to locate sum node");
+    return VerifyTree(sum);
+  }
+
+ private:
+  CordRep* AppendNode(CordRep* node, CordRep* sum) {
+    return (sum == nullptr) ? node : MakeConcat(sum, node);
+  }
+
+  CordRep* PrependNode(CordRep* node, CordRep* sum) {
+    return (sum == nullptr) ? node : MakeConcat(node, sum);
+  }
+
+  void AddNode(CordRep* node) {
+    CordRep* sum = nullptr;
+
+    // Collect together everything with which we will merge with node
+    int i = 0;
+    for (; node->length > min_length[i + 1]; ++i) {
+      auto& tree_at_i = trees_[i];
+
+      if (tree_at_i == nullptr) continue;
+      sum = PrependNode(tree_at_i, sum);
+      tree_at_i = nullptr;
+    }
+
+    sum = AppendNode(node, sum);
+
+    // Insert sum into appropriate place in the forest
+    for (; sum->length >= min_length[i]; ++i) {
+      auto& tree_at_i = trees_[i];
+      if (tree_at_i == nullptr) continue;
+
+      sum = MakeConcat(tree_at_i, sum);
+      tree_at_i = nullptr;
+    }
+
+    // min_length[0] == 1, which means sum->length >= min_length[0]
+    assert(i > 0);
+    trees_[i - 1] = sum;
+  }
+
+  // Make concat node trying to resue existing CordRepConcat nodes we
+  // already collected in the concat_freelist_.
+  CordRep* MakeConcat(CordRep* left, CordRep* right) {
+    if (concat_freelist_ == nullptr) return RawConcat(left, right);
+
+    CordRepConcat* rep = concat_freelist_;
+    if (concat_freelist_->left == nullptr) {
+      concat_freelist_ = nullptr;
+    } else {
+      concat_freelist_ = concat_freelist_->left->concat();
+    }
+    SetConcatChildren(rep, left, right);
+
+    return rep;
+  }
+
+  static void CheckNode(CordRep* node) {
+    ABSL_INTERNAL_CHECK(node->length != 0u, "");
+    if (node->tag == CONCAT) {
+      ABSL_INTERNAL_CHECK(node->concat()->left != nullptr, "");
+      ABSL_INTERNAL_CHECK(node->concat()->right != nullptr, "");
+      ABSL_INTERNAL_CHECK(node->length == (node->concat()->left->length +
+                                           node->concat()->right->length),
+                          "");
+    }
+  }
+
+  size_t root_length_;
+
+  // use an inlined vector instead of a flat array to get bounds checking
+  absl::InlinedVector<CordRep*, kInlinedVectorSize> trees_;
+
+  // List of concat nodes we can re-use for Cord balancing.
+  CordRepConcat* concat_freelist_ = nullptr;
+};
+
+static CordRep* Rebalance(CordRep* node) {
+  VerifyTree(node);
+  assert(node->tag == CONCAT);
+
+  if (node->length == 0) {
+    return nullptr;
+  }
+
+  CordForest forest(node->length);
+  forest.Build(node);
+  return forest.ConcatNodes();
+}
+
+// --------------------------------------------------------------------
+// Comparators
+
+namespace {
+
+int ClampResult(int memcmp_res) {
+  return static_cast<int>(memcmp_res > 0) - static_cast<int>(memcmp_res < 0);
+}
+
+int CompareChunks(absl::string_view* lhs, absl::string_view* rhs,
+                  size_t* size_to_compare) {
+  size_t compared_size = std::min(lhs->size(), rhs->size());
+  assert(*size_to_compare >= compared_size);
+  *size_to_compare -= compared_size;
+
+  int memcmp_res = ::memcmp(lhs->data(), rhs->data(), compared_size);
+  if (memcmp_res != 0) return memcmp_res;
+
+  lhs->remove_prefix(compared_size);
+  rhs->remove_prefix(compared_size);
+
+  return 0;
+}
+
+// This overload set computes comparison results from memcmp result. This
+// interface is used inside GenericCompare below. Differet implementations
+// are specialized for int and bool. For int we clamp result to {-1, 0, 1}
+// set. For bool we just interested in "value == 0".
+template <typename ResultType>
+ResultType ComputeCompareResult(int memcmp_res) {
+  return ClampResult(memcmp_res);
+}
+template <>
+bool ComputeCompareResult<bool>(int memcmp_res) {
+  return memcmp_res == 0;
+}
+
+}  // namespace
+
+// Helper routine. Locates the first flat chunk of the Cord without
+// initializing the iterator.
+inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
+  size_t n = tagged_size();
+  if (n <= kMaxInline) {
+    return absl::string_view(data_.as_chars, n);
+  }
+
+  CordRep* node = tree();
+  if (node->tag >= FLAT) {
+    return absl::string_view(node->data, node->length);
+  }
+
+  if (node->tag == EXTERNAL) {
+    return absl::string_view(node->external()->base, node->length);
+  }
+
+  // Walk down the left branches until we hit a non-CONCAT node.
+  while (node->tag == CONCAT) {
+    node = node->concat()->left;
+  }
+
+  // Get the child node if we encounter a SUBSTRING.
+  size_t offset = 0;
+  size_t length = node->length;
+  assert(length != 0);
+
+  if (node->tag == SUBSTRING) {
+    offset = node->substring()->start;
+    node = node->substring()->child;
+  }
+
+  if (node->tag >= FLAT) {
+    return absl::string_view(node->data + offset, length);
+  }
+
+  assert((node->tag == EXTERNAL) && "Expect FLAT or EXTERNAL node here");
+
+  return absl::string_view(node->external()->base + offset, length);
+}
+
+inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size,
+                                 size_t size_to_compare) const {
+  auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) {
+    if (!chunk->empty()) return true;
+    ++*it;
+    if (it->bytes_remaining_ == 0) return false;
+    *chunk = **it;
+    return true;
+  };
+
+  Cord::ChunkIterator lhs_it = chunk_begin();
+
+  // compared_size is inside first chunk.
+  absl::string_view lhs_chunk =
+      (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view();
+  assert(compared_size <= lhs_chunk.size());
+  assert(compared_size <= rhs.size());
+  lhs_chunk.remove_prefix(compared_size);
+  rhs.remove_prefix(compared_size);
+  size_to_compare -= compared_size;  // skip already compared size.
+
+  while (advance(&lhs_it, &lhs_chunk) && !rhs.empty()) {
+    int comparison_result = CompareChunks(&lhs_chunk, &rhs, &size_to_compare);
+    if (comparison_result != 0) return comparison_result;
+    if (size_to_compare == 0) return 0;
+  }
+
+  return static_cast<int>(rhs.empty()) - static_cast<int>(lhs_chunk.empty());
+}
+
+inline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size,
+                                 size_t size_to_compare) const {
+  auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) {
+    if (!chunk->empty()) return true;
+    ++*it;
+    if (it->bytes_remaining_ == 0) return false;
+    *chunk = **it;
+    return true;
+  };
+
+  Cord::ChunkIterator lhs_it = chunk_begin();
+  Cord::ChunkIterator rhs_it = rhs.chunk_begin();
+
+  // compared_size is inside both first chunks.
+  absl::string_view lhs_chunk =
+      (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view();
+  absl::string_view rhs_chunk =
+      (rhs_it.bytes_remaining_ != 0) ? *rhs_it : absl::string_view();
+  assert(compared_size <= lhs_chunk.size());
+  assert(compared_size <= rhs_chunk.size());
+  lhs_chunk.remove_prefix(compared_size);
+  rhs_chunk.remove_prefix(compared_size);
+  size_to_compare -= compared_size;  // skip already compared size.
+
+  while (advance(&lhs_it, &lhs_chunk) && advance(&rhs_it, &rhs_chunk)) {
+    int memcmp_res = CompareChunks(&lhs_chunk, &rhs_chunk, &size_to_compare);
+    if (memcmp_res != 0) return memcmp_res;
+    if (size_to_compare == 0) return 0;
+  }
+
+  return static_cast<int>(rhs_chunk.empty()) -
+         static_cast<int>(lhs_chunk.empty());
+}
+
+inline absl::string_view Cord::GetFirstChunk(const Cord& c) {
+  return c.contents_.FindFlatStartPiece();
+}
+inline absl::string_view Cord::GetFirstChunk(absl::string_view sv) {
+  return sv;
+}
+
+// Compares up to 'size_to_compare' bytes of 'lhs' with 'rhs'. It is assumed
+// that 'size_to_compare' is greater that size of smallest of first chunks.
+template <typename ResultType, typename RHS>
+ResultType GenericCompare(const Cord& lhs, const RHS& rhs,
+                          size_t size_to_compare) {
+  absl::string_view lhs_chunk = Cord::GetFirstChunk(lhs);
+  absl::string_view rhs_chunk = Cord::GetFirstChunk(rhs);
+
+  size_t compared_size = std::min(lhs_chunk.size(), rhs_chunk.size());
+  assert(size_to_compare >= compared_size);
+  int memcmp_res = ::memcmp(lhs_chunk.data(), rhs_chunk.data(), compared_size);
+  if (compared_size == size_to_compare || memcmp_res != 0) {
+    return ComputeCompareResult<ResultType>(memcmp_res);
+  }
+
+  return ComputeCompareResult<ResultType>(
+      lhs.CompareSlowPath(rhs, compared_size, size_to_compare));
+}
+
+bool Cord::EqualsImpl(absl::string_view rhs, size_t size_to_compare) const {
+  return GenericCompare<bool>(*this, rhs, size_to_compare);
+}
+
+bool Cord::EqualsImpl(const Cord& rhs, size_t size_to_compare) const {
+  return GenericCompare<bool>(*this, rhs, size_to_compare);
+}
+
+template <typename RHS>
+inline int SharedCompareImpl(const Cord& lhs, const RHS& rhs) {
+  size_t lhs_size = lhs.size();
+  size_t rhs_size = rhs.size();
+  if (lhs_size == rhs_size) {
+    return GenericCompare<int>(lhs, rhs, lhs_size);
+  }
+  if (lhs_size < rhs_size) {
+    auto data_comp_res = GenericCompare<int>(lhs, rhs, lhs_size);
+    return data_comp_res == 0 ? -1 : data_comp_res;
+  }
+
+  auto data_comp_res = GenericCompare<int>(lhs, rhs, rhs_size);
+  return data_comp_res == 0 ? +1 : data_comp_res;
+}
+
+int Cord::Compare(absl::string_view rhs) const {
+  return SharedCompareImpl(*this, rhs);
+}
+
+int Cord::CompareImpl(const Cord& rhs) const {
+  return SharedCompareImpl(*this, rhs);
+}
+
+bool Cord::EndsWith(absl::string_view rhs) const {
+  size_t my_size = size();
+  size_t rhs_size = rhs.size();
+
+  if (my_size < rhs_size) return false;
+
+  Cord tmp(*this);
+  tmp.RemovePrefix(my_size - rhs_size);
+  return tmp.EqualsImpl(rhs, rhs_size);
+}
+
+bool Cord::EndsWith(const Cord& rhs) const {
+  size_t my_size = size();
+  size_t rhs_size = rhs.size();
+
+  if (my_size < rhs_size) return false;
+
+  Cord tmp(*this);
+  tmp.RemovePrefix(my_size - rhs_size);
+  return tmp.EqualsImpl(rhs, rhs_size);
+}
+
+// --------------------------------------------------------------------
+// Misc.
+
+Cord::operator std::string() const {
+  std::string s;
+  absl::CopyCordToString(*this, &s);
+  return s;
+}
+
+void CopyCordToString(const Cord& src, std::string* dst) {
+  if (!src.contents_.is_tree()) {
+    src.contents_.CopyTo(dst);
+  } else {
+    absl::strings_internal::STLStringResizeUninitialized(dst, src.size());
+    src.CopyToArraySlowPath(&(*dst)[0]);
+  }
+}
+
+void Cord::CopyToArraySlowPath(char* dst) const {
+  assert(contents_.is_tree());
+  absl::string_view fragment;
+  if (GetFlatAux(contents_.tree(), &fragment)) {
+    memcpy(dst, fragment.data(), fragment.size());
+    return;
+  }
+  for (absl::string_view chunk : Chunks()) {
+    memcpy(dst, chunk.data(), chunk.size());
+    dst += chunk.size();
+  }
+}
+
+Cord::ChunkIterator& Cord::ChunkIterator::AdvanceStack() {
+  auto& stack_of_right_children = stack_of_right_children_;
+  if (stack_of_right_children.empty()) {
+    assert(!current_chunk_.empty());  // Called on invalid iterator.
+    // We have reached the end of the Cord.
+    return *this;
+  }
+
+  // Process the next node on the stack.
+  CordRep* node = stack_of_right_children.back();
+  stack_of_right_children.pop_back();
+
+  // Walk down the left branches until we hit a non-CONCAT node. Save the
+  // right children to the stack for subsequent traversal.
+  while (node->tag == CONCAT) {
+    stack_of_right_children.push_back(node->concat()->right);
+    node = node->concat()->left;
+  }
+
+  // Get the child node if we encounter a SUBSTRING.
+  size_t offset = 0;
+  size_t length = node->length;
+  if (node->tag == SUBSTRING) {
+    offset = node->substring()->start;
+    node = node->substring()->child;
+  }
+
+  assert(node->tag == EXTERNAL || node->tag >= FLAT);
+  assert(length != 0);
+  const char* data =
+      node->tag == EXTERNAL ? node->external()->base : node->data;
+  current_chunk_ = absl::string_view(data + offset, length);
+  current_leaf_ = node;
+  return *this;
+}
+
+Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
+  ABSL_HARDENING_ASSERT(bytes_remaining_ >= n &&
+                        "Attempted to iterate past `end()`");
+  Cord subcord;
+
+  if (n <= InlineRep::kMaxInline) {
+    // Range to read fits in inline data. Flatten it.
+    char* data = subcord.contents_.set_data(n);
+    while (n > current_chunk_.size()) {
+      memcpy(data, current_chunk_.data(), current_chunk_.size());
+      data += current_chunk_.size();
+      n -= current_chunk_.size();
+      ++*this;
+    }
+    memcpy(data, current_chunk_.data(), n);
+    if (n < current_chunk_.size()) {
+      RemoveChunkPrefix(n);
+    } else if (n > 0) {
+      ++*this;
+    }
+    return subcord;
+  }
+  auto& stack_of_right_children = stack_of_right_children_;
+  if (n < current_chunk_.size()) {
+    // Range to read is a proper subrange of the current chunk.
+    assert(current_leaf_ != nullptr);
+    CordRep* subnode = CordRep::Ref(current_leaf_);
+    const char* data =
+        subnode->tag == EXTERNAL ? subnode->external()->base : subnode->data;
+    subnode = NewSubstring(subnode, current_chunk_.data() - data, n);
+    subcord.contents_.set_tree(VerifyTree(subnode));
+    RemoveChunkPrefix(n);
+    return subcord;
+  }
+
+  // Range to read begins with a proper subrange of the current chunk.
+  assert(!current_chunk_.empty());
+  assert(current_leaf_ != nullptr);
+  CordRep* subnode = CordRep::Ref(current_leaf_);
+  if (current_chunk_.size() < subnode->length) {
+    const char* data =
+        subnode->tag == EXTERNAL ? subnode->external()->base : subnode->data;
+    subnode = NewSubstring(subnode, current_chunk_.data() - data,
+                           current_chunk_.size());
+  }
+  n -= current_chunk_.size();
+  bytes_remaining_ -= current_chunk_.size();
+
+  // Process the next node(s) on the stack, reading whole subtrees depending on
+  // their length and how many bytes we are advancing.
+  CordRep* node = nullptr;
+  while (!stack_of_right_children.empty()) {
+    node = stack_of_right_children.back();
+    stack_of_right_children.pop_back();
+    if (node->length > n) break;
+    // TODO(qrczak): This might unnecessarily recreate existing concat nodes.
+    // Avoiding that would need pretty complicated logic (instead of
+    // current_leaf, keep current_subtree_ which points to the highest node
+    // such that the current leaf can be found on the path of left children
+    // starting from current_subtree_; delay creating subnode while node is
+    // below current_subtree_; find the proper node along the path of left
+    // children starting from current_subtree_ if this loop exits while staying
+    // below current_subtree_; etc.; alternatively, push parents instead of
+    // right children on the stack).
+    subnode = Concat(subnode, CordRep::Ref(node));
+    n -= node->length;
+    bytes_remaining_ -= node->length;
+    node = nullptr;
+  }
+
+  if (node == nullptr) {
+    // We have reached the end of the Cord.
+    assert(bytes_remaining_ == 0);
+    subcord.contents_.set_tree(VerifyTree(subnode));
+    return subcord;
+  }
+
+  // Walk down the appropriate branches until we hit a non-CONCAT node. Save the
+  // right children to the stack for subsequent traversal.
+  while (node->tag == CONCAT) {
+    if (node->concat()->left->length > n) {
+      // Push right, descend left.
+      stack_of_right_children.push_back(node->concat()->right);
+      node = node->concat()->left;
+    } else {
+      // Read left, descend right.
+      subnode = Concat(subnode, CordRep::Ref(node->concat()->left));
+      n -= node->concat()->left->length;
+      bytes_remaining_ -= node->concat()->left->length;
+      node = node->concat()->right;
+    }
+  }
+
+  // Get the child node if we encounter a SUBSTRING.
+  size_t offset = 0;
+  size_t length = node->length;
+  if (node->tag == SUBSTRING) {
+    offset = node->substring()->start;
+    node = node->substring()->child;
+  }
+
+  // Range to read ends with a proper (possibly empty) subrange of the current
+  // chunk.
+  assert(node->tag == EXTERNAL || node->tag >= FLAT);
+  assert(length > n);
+  if (n > 0) {
+    subnode = Concat(subnode, NewSubstring(CordRep::Ref(node), offset, n));
+  }
+  const char* data =
+      node->tag == EXTERNAL ? node->external()->base : node->data;
+  current_chunk_ = absl::string_view(data + offset + n, length - n);
+  current_leaf_ = node;
+  bytes_remaining_ -= n;
+  subcord.contents_.set_tree(VerifyTree(subnode));
+  return subcord;
+}
+
+void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
+  assert(bytes_remaining_ >= n && "Attempted to iterate past `end()`");
+  assert(n >= current_chunk_.size());  // This should only be called when
+                                       // iterating to a new node.
+
+  n -= current_chunk_.size();
+  bytes_remaining_ -= current_chunk_.size();
+
+  if (stack_of_right_children_.empty()) {
+    // We have reached the end of the Cord.
+    assert(bytes_remaining_ == 0);
+    return;
+  }
+
+  // Process the next node(s) on the stack, skipping whole subtrees depending on
+  // their length and how many bytes we are advancing.
+  CordRep* node = nullptr;
+  auto& stack_of_right_children = stack_of_right_children_;
+  while (!stack_of_right_children.empty()) {
+    node = stack_of_right_children.back();
+    stack_of_right_children.pop_back();
+    if (node->length > n) break;
+    n -= node->length;
+    bytes_remaining_ -= node->length;
+    node = nullptr;
+  }
+
+  if (node == nullptr) {
+    // We have reached the end of the Cord.
+    assert(bytes_remaining_ == 0);
+    return;
+  }
+
+  // Walk down the appropriate branches until we hit a non-CONCAT node. Save the
+  // right children to the stack for subsequent traversal.
+  while (node->tag == CONCAT) {
+    if (node->concat()->left->length > n) {
+      // Push right, descend left.
+      stack_of_right_children.push_back(node->concat()->right);
+      node = node->concat()->left;
+    } else {
+      // Skip left, descend right.
+      n -= node->concat()->left->length;
+      bytes_remaining_ -= node->concat()->left->length;
+      node = node->concat()->right;
+    }
+  }
+
+  // Get the child node if we encounter a SUBSTRING.
+  size_t offset = 0;
+  size_t length = node->length;
+  if (node->tag == SUBSTRING) {
+    offset = node->substring()->start;
+    node = node->substring()->child;
+  }
+
+  assert(node->tag == EXTERNAL || node->tag >= FLAT);
+  assert(length > n);
+  const char* data =
+      node->tag == EXTERNAL ? node->external()->base : node->data;
+  current_chunk_ = absl::string_view(data + offset + n, length - n);
+  current_leaf_ = node;
+  bytes_remaining_ -= n;
+}
+
+char Cord::operator[](size_t i) const {
+  ABSL_HARDENING_ASSERT(i < size());
+  size_t offset = i;
+  const CordRep* rep = contents_.tree();
+  if (rep == nullptr) {
+    return contents_.data()[i];
+  }
+  while (true) {
+    assert(rep != nullptr);
+    assert(offset < rep->length);
+    if (rep->tag >= FLAT) {
+      // Get the "i"th character directly from the flat array.
+      return rep->data[offset];
+    } else if (rep->tag == EXTERNAL) {
+      // Get the "i"th character from the external array.
+      return rep->external()->base[offset];
+    } else if (rep->tag == CONCAT) {
+      // Recursively branch to the side of the concatenation that the "i"th
+      // character is on.
+      size_t left_length = rep->concat()->left->length;
+      if (offset < left_length) {
+        rep = rep->concat()->left;
+      } else {
+        offset -= left_length;
+        rep = rep->concat()->right;
+      }
+    } else {
+      // This must be a substring a node, so bypass it to get to the child.
+      assert(rep->tag == SUBSTRING);
+      offset += rep->substring()->start;
+      rep = rep->substring()->child;
+    }
+  }
+}
+
+absl::string_view Cord::FlattenSlowPath() {
+  size_t total_size = size();
+  CordRep* new_rep;
+  char* new_buffer;
+
+  // Try to put the contents into a new flat rep. If they won't fit in the
+  // biggest possible flat node, use an external rep instead.
+  if (total_size <= kMaxFlatLength) {
+    new_rep = CordRepFlat::New(total_size);
+    new_rep->length = total_size;
+    new_buffer = new_rep->data;
+    CopyToArraySlowPath(new_buffer);
+  } else {
+    new_buffer = std::allocator<char>().allocate(total_size);
+    CopyToArraySlowPath(new_buffer);
+    new_rep = absl::cord_internal::NewExternalRep(
+        absl::string_view(new_buffer, total_size), [](absl::string_view s) {
+          std::allocator<char>().deallocate(const_cast<char*>(s.data()),
+                                            s.size());
+        });
+  }
+  if (CordRep* tree = contents_.tree()) {
+    CordRep::Unref(tree);
+  }
+  contents_.set_tree(new_rep);
+  return absl::string_view(new_buffer, total_size);
+}
+
+/* static */ bool Cord::GetFlatAux(CordRep* rep, absl::string_view* fragment) {
+  assert(rep != nullptr);
+  if (rep->tag >= FLAT) {
+    *fragment = absl::string_view(rep->data, rep->length);
+    return true;
+  } else if (rep->tag == EXTERNAL) {
+    *fragment = absl::string_view(rep->external()->base, rep->length);
+    return true;
+  } else if (rep->tag == SUBSTRING) {
+    CordRep* child = rep->substring()->child;
+    if (child->tag >= FLAT) {
+      *fragment =
+          absl::string_view(child->data + rep->substring()->start, rep->length);
+      return true;
+    } else if (child->tag == EXTERNAL) {
+      *fragment = absl::string_view(
+          child->external()->base + rep->substring()->start, rep->length);
+      return true;
+    }
+  }
+  return false;
+}
+
+/* static */ void Cord::ForEachChunkAux(
+    absl::cord_internal::CordRep* rep,
+    absl::FunctionRef<void(absl::string_view)> callback) {
+  assert(rep != nullptr);
+  int stack_pos = 0;
+  constexpr int stack_max = 128;
+  // Stack of right branches for tree traversal
+  absl::cord_internal::CordRep* stack[stack_max];
+  absl::cord_internal::CordRep* current_node = rep;
+  while (true) {
+    if (current_node->tag == CONCAT) {
+      if (stack_pos == stack_max) {
+        // There's no more room on our stack array to add another right branch,
+        // and the idea is to avoid allocations, so call this function
+        // recursively to navigate this subtree further.  (This is not something
+        // we expect to happen in practice).
+        ForEachChunkAux(current_node, callback);
+
+        // Pop the next right branch and iterate.
+        current_node = stack[--stack_pos];
+        continue;
+      } else {
+        // Save the right branch for later traversal and continue down the left
+        // branch.
+        stack[stack_pos++] = current_node->concat()->right;
+        current_node = current_node->concat()->left;
+        continue;
+      }
+    }
+    // This is a leaf node, so invoke our callback.
+    absl::string_view chunk;
+    bool success = GetFlatAux(current_node, &chunk);
+    assert(success);
+    if (success) {
+      callback(chunk);
+    }
+    if (stack_pos == 0) {
+      // end of traversal
+      return;
+    }
+    current_node = stack[--stack_pos];
+  }
+}
+
+static void DumpNode(CordRep* rep, bool include_data, std::ostream* os) {
+  const int kIndentStep = 1;
+  int indent = 0;
+  absl::InlinedVector<CordRep*, kInlinedVectorSize> stack;
+  absl::InlinedVector<int, kInlinedVectorSize> indents;
+  for (;;) {
+    *os << std::setw(3) << rep->refcount.Get();
+    *os << " " << std::setw(7) << rep->length;
+    *os << " [";
+    if (include_data) *os << static_cast<void*>(rep);
+    *os << "]";
+    *os << " " << (IsRootBalanced(rep) ? 'b' : 'u');
+    *os << " " << std::setw(indent) << "";
+    if (rep->tag == CONCAT) {
+      *os << "CONCAT depth=" << Depth(rep) << "\n";
+      indent += kIndentStep;
+      indents.push_back(indent);
+      stack.push_back(rep->concat()->right);
+      rep = rep->concat()->left;
+    } else if (rep->tag == SUBSTRING) {
+      *os << "SUBSTRING @ " << rep->substring()->start << "\n";
+      indent += kIndentStep;
+      rep = rep->substring()->child;
+    } else {  // Leaf
+      if (rep->tag == EXTERNAL) {
+        *os << "EXTERNAL [";
+        if (include_data)
+          *os << absl::CEscape(std::string(rep->external()->base, rep->length));
+        *os << "]\n";
+      } else {
+        *os << "FLAT cap=" << rep->flat()->Capacity()
+            << " [";
+        if (include_data)
+          *os << absl::CEscape(std::string(rep->data, rep->length));
+        *os << "]\n";
+      }
+      if (stack.empty()) break;
+      rep = stack.back();
+      stack.pop_back();
+      indent = indents.back();
+      indents.pop_back();
+    }
+  }
+  ABSL_INTERNAL_CHECK(indents.empty(), "");
+}
+
+static std::string ReportError(CordRep* root, CordRep* node) {
+  std::ostringstream buf;
+  buf << "Error at node " << node << " in:";
+  DumpNode(root, true, &buf);
+  return buf.str();
+}
+
+static bool VerifyNode(CordRep* root, CordRep* start_node,
+                       bool full_validation) {
+  absl::InlinedVector<CordRep*, 2> worklist;
+  worklist.push_back(start_node);
+  do {
+    CordRep* node = worklist.back();
+    worklist.pop_back();
+
+    ABSL_INTERNAL_CHECK(node != nullptr, ReportError(root, node));
+    if (node != root) {
+      ABSL_INTERNAL_CHECK(node->length != 0, ReportError(root, node));
+    }
+
+    if (node->tag == CONCAT) {
+      ABSL_INTERNAL_CHECK(node->concat()->left != nullptr,
+                          ReportError(root, node));
+      ABSL_INTERNAL_CHECK(node->concat()->right != nullptr,
+                          ReportError(root, node));
+      ABSL_INTERNAL_CHECK((node->length == node->concat()->left->length +
+                                               node->concat()->right->length),
+                          ReportError(root, node));
+      if (full_validation) {
+        worklist.push_back(node->concat()->right);
+        worklist.push_back(node->concat()->left);
+      }
+    } else if (node->tag >= FLAT) {
+      ABSL_INTERNAL_CHECK(
+          node->length <= node->flat()->Capacity(),
+          ReportError(root, node));
+    } else if (node->tag == EXTERNAL) {
+      ABSL_INTERNAL_CHECK(node->external()->base != nullptr,
+                          ReportError(root, node));
+    } else if (node->tag == SUBSTRING) {
+      ABSL_INTERNAL_CHECK(
+          node->substring()->start < node->substring()->child->length,
+          ReportError(root, node));
+      ABSL_INTERNAL_CHECK(node->substring()->start + node->length <=
+                              node->substring()->child->length,
+                          ReportError(root, node));
+    }
+  } while (!worklist.empty());
+  return true;
+}
+
+// Traverses the tree and computes the total memory allocated.
+/* static */ size_t Cord::MemoryUsageAux(const CordRep* rep) {
+  size_t total_mem_usage = 0;
+
+  // Allow a quick exit for the common case that the root is a leaf.
+  if (RepMemoryUsageLeaf(rep, &total_mem_usage)) {
+    return total_mem_usage;
+  }
+
+  // Iterate over the tree. cur_node is never a leaf node and leaf nodes will
+  // never be appended to tree_stack. This reduces overhead from manipulating
+  // tree_stack.
+  absl::InlinedVector<const CordRep*, kInlinedVectorSize> tree_stack;
+  const CordRep* cur_node = rep;
+  while (true) {
+    const CordRep* next_node = nullptr;
+
+    if (cur_node->tag == CONCAT) {
+      total_mem_usage += sizeof(CordRepConcat);
+      const CordRep* left = cur_node->concat()->left;
+      if (!RepMemoryUsageLeaf(left, &total_mem_usage)) {
+        next_node = left;
+      }
+
+      const CordRep* right = cur_node->concat()->right;
+      if (!RepMemoryUsageLeaf(right, &total_mem_usage)) {
+        if (next_node) {
+          tree_stack.push_back(next_node);
+        }
+        next_node = right;
+      }
+    } else {
+      // Since cur_node is not a leaf or a concat node it must be a substring.
+      assert(cur_node->tag == SUBSTRING);
+      total_mem_usage += sizeof(CordRepSubstring);
+      next_node = cur_node->substring()->child;
+      if (RepMemoryUsageLeaf(next_node, &total_mem_usage)) {
+        next_node = nullptr;
+      }
+    }
+
+    if (!next_node) {
+      if (tree_stack.empty()) {
+        return total_mem_usage;
+      }
+      next_node = tree_stack.back();
+      tree_stack.pop_back();
+    }
+    cur_node = next_node;
+  }
+}
+
+std::ostream& operator<<(std::ostream& out, const Cord& cord) {
+  for (absl::string_view chunk : cord.Chunks()) {
+    out.write(chunk.data(), chunk.size());
+  }
+  return out;
+}
+
+namespace strings_internal {
+size_t CordTestAccess::FlatOverhead() { return cord_internal::kFlatOverhead; }
+size_t CordTestAccess::MaxFlatLength() { return cord_internal::kMaxFlatLength; }
+size_t CordTestAccess::FlatTagToLength(uint8_t tag) {
+  return cord_internal::TagToLength(tag);
+}
+uint8_t CordTestAccess::LengthToTag(size_t s) {
+  ABSL_INTERNAL_CHECK(s <= kMaxFlatLength, absl::StrCat("Invalid length ", s));
+  return cord_internal::AllocatedSizeToTag(s + cord_internal::kFlatOverhead);
+}
+size_t CordTestAccess::SizeofCordRepConcat() { return sizeof(CordRepConcat); }
+size_t CordTestAccess::SizeofCordRepExternal() {
+  return sizeof(CordRepExternal);
+}
+size_t CordTestAccess::SizeofCordRepSubstring() {
+  return sizeof(CordRepSubstring);
+}
+}  // namespace strings_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/strings/cord.h b/absl/strings/cord.h
new file mode 100644
index 0000000..7136f03
--- /dev/null
+++ b/absl/strings/cord.h
@@ -0,0 +1,1322 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: cord.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the `absl::Cord` data structure and operations on that data
+// structure. A Cord is a string-like sequence of characters optimized for
+// specific use cases. Unlike a `std::string`, which stores an array of
+// contiguous characters, Cord data is stored in a structure consisting of
+// separate, reference-counted "chunks." (Currently, this implementation is a
+// tree structure, though that implementation may change.)
+//
+// Because a Cord consists of these chunks, data can be added to or removed from
+// a Cord during its lifetime. Chunks may also be shared between Cords. Unlike a
+// `std::string`, a Cord can therefore accomodate data that changes over its
+// lifetime, though it's not quite "mutable"; it can change only in the
+// attachment, detachment, or rearrangement of chunks of its constituent data.
+//
+// A Cord provides some benefit over `std::string` under the following (albeit
+// narrow) circumstances:
+//
+//   * Cord data is designed to grow and shrink over a Cord's lifetime. Cord
+//     provides efficient insertions and deletions at the start and end of the
+//     character sequences, avoiding copies in those cases. Static data should
+//     generally be stored as strings.
+//   * External memory consisting of string-like data can be directly added to
+//     a Cord without requiring copies or allocations.
+//   * Cord data may be shared and copied cheaply. Cord provides a copy-on-write
+//     implementation and cheap sub-Cord operations. Copying a Cord is an O(1)
+//     operation.
+//
+// As a consequence to the above, Cord data is generally large. Small data
+// should generally use strings, as construction of a Cord requires some
+// overhead. Small Cords (<= 15 bytes) are represented inline, but most small
+// Cords are expected to grow over their lifetimes.
+//
+// Note that because a Cord is made up of separate chunked data, random access
+// to character data within a Cord is slower than within a `std::string`.
+//
+// Thread Safety
+//
+// Cord has the same thread-safety properties as many other types like
+// std::string, std::vector<>, int, etc -- it is thread-compatible. In
+// particular, if threads do not call non-const methods, then it is safe to call
+// const methods without synchronization. Copying a Cord produces a new instance
+// that can be used concurrently with the original in arbitrary ways.
+
+#ifndef ABSL_STRINGS_CORD_H_
+#define ABSL_STRINGS_CORD_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <iosfwd>
+#include <iterator>
+#include <string>
+#include <type_traits>
+
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/per_thread_tls.h"
+#include "absl/base/macros.h"
+#include "absl/base/port.h"
+#include "absl/container/inlined_vector.h"
+#include "absl/functional/function_ref.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/internal/string_constant.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+class Cord;
+class CordTestPeer;
+template <typename Releaser>
+Cord MakeCordFromExternal(absl::string_view, Releaser&&);
+void CopyCordToString(const Cord& src, std::string* dst);
+
+// Cord
+//
+// A Cord is a sequence of characters, designed to be more efficient than a
+// `std::string` in certain circumstances: namely, large string data that needs
+// to change over its lifetime or shared, especially when such data is shared
+// across API boundaries.
+//
+// A Cord stores its character data in a structure that allows efficient prepend
+// and append operations. This makes a Cord useful for large string data sent
+// over in a wire format that may need to be prepended or appended at some point
+// during the data exchange (e.g. HTTP, protocol buffers). For example, a
+// Cord is useful for storing an HTTP request, and prepending an HTTP header to
+// such a request.
+//
+// Cords should not be used for storing general string data, however. They
+// require overhead to construct and are slower than strings for random access.
+//
+// The Cord API provides the following common API operations:
+//
+// * Create or assign Cords out of existing string data, memory, or other Cords
+// * Append and prepend data to an existing Cord
+// * Create new Sub-Cords from existing Cord data
+// * Swap Cord data and compare Cord equality
+// * Write out Cord data by constructing a `std::string`
+//
+// Additionally, the API provides iterator utilities to iterate through Cord
+// data via chunks or character bytes.
+//
+class Cord {
+ private:
+  template <typename T>
+  using EnableIfString =
+      absl::enable_if_t<std::is_same<T, std::string>::value, int>;
+
+ public:
+  // Cord::Cord() Constructors.
+
+  // Creates an empty Cord.
+  constexpr Cord() noexcept;
+
+  // Creates a Cord from an existing Cord. Cord is copyable and efficiently
+  // movable. The moved-from state is valid but unspecified.
+  Cord(const Cord& src);
+  Cord(Cord&& src) noexcept;
+  Cord& operator=(const Cord& x);
+  Cord& operator=(Cord&& x) noexcept;
+
+  // Creates a Cord from a `src` string. This constructor is marked explicit to
+  // prevent implicit Cord constructions from arguments convertible to an
+  // `absl::string_view`.
+  explicit Cord(absl::string_view src);
+  Cord& operator=(absl::string_view src);
+
+  // Creates a Cord from a `std::string&&` rvalue. These constructors are
+  // templated to avoid ambiguities for types that are convertible to both
+  // `absl::string_view` and `std::string`, such as `const char*`.
+  template <typename T, EnableIfString<T> = 0>
+  explicit Cord(T&& src);
+  template <typename T, EnableIfString<T> = 0>
+  Cord& operator=(T&& src);
+
+  // Cord::~Cord()
+  //
+  // Destructs the Cord.
+  ~Cord() {
+    if (contents_.is_tree()) DestroyCordSlow();
+  }
+
+  // MakeCordFromExternal()
+  //
+  // Creates a Cord that takes ownership of external string memory. The
+  // contents of `data` are not copied to the Cord; instead, the external
+  // memory is added to the Cord and reference-counted. This data may not be
+  // changed for the life of the Cord, though it may be prepended or appended
+  // to.
+  //
+  // `MakeCordFromExternal()` takes a callable "releaser" that is invoked when
+  // the reference count for `data` reaches zero. As noted above, this data must
+  // remain live until the releaser is invoked. The callable releaser also must:
+  //
+  //   * be move constructible
+  //   * support `void operator()(absl::string_view) const` or `void operator()`
+  //
+  // Example:
+  //
+  // Cord MakeCord(BlockPool* pool) {
+  //   Block* block = pool->NewBlock();
+  //   FillBlock(block);
+  //   return absl::MakeCordFromExternal(
+  //       block->ToStringView(),
+  //       [pool, block](absl::string_view v) {
+  //         pool->FreeBlock(block, v);
+  //       });
+  // }
+  //
+  // WARNING: Because a Cord can be reference-counted, it's likely a bug if your
+  // releaser doesn't do anything. For example, consider the following:
+  //
+  // void Foo(const char* buffer, int len) {
+  //   auto c = absl::MakeCordFromExternal(absl::string_view(buffer, len),
+  //                                       [](absl::string_view) {});
+  //
+  //   // BUG: If Bar() copies its cord for any reason, including keeping a
+  //   // substring of it, the lifetime of buffer might be extended beyond
+  //   // when Foo() returns.
+  //   Bar(c);
+  // }
+  template <typename Releaser>
+  friend Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser);
+
+  // Cord::Clear()
+  //
+  // Releases the Cord data. Any nodes that share data with other Cords, if
+  // applicable, will have their reference counts reduced by 1.
+  void Clear();
+
+  // Cord::Append()
+  //
+  // Appends data to the Cord, which may come from another Cord or other string
+  // data.
+  void Append(const Cord& src);
+  void Append(Cord&& src);
+  void Append(absl::string_view src);
+  template <typename T, EnableIfString<T> = 0>
+  void Append(T&& src);
+
+  // Cord::Prepend()
+  //
+  // Prepends data to the Cord, which may come from another Cord or other string
+  // data.
+  void Prepend(const Cord& src);
+  void Prepend(absl::string_view src);
+  template <typename T, EnableIfString<T> = 0>
+  void Prepend(T&& src);
+
+  // Cord::RemovePrefix()
+  //
+  // Removes the first `n` bytes of a Cord.
+  void RemovePrefix(size_t n);
+  void RemoveSuffix(size_t n);
+
+  // Cord::Subcord()
+  //
+  // Returns a new Cord representing the subrange [pos, pos + new_size) of
+  // *this. If pos >= size(), the result is empty(). If
+  // (pos + new_size) >= size(), the result is the subrange [pos, size()).
+  Cord Subcord(size_t pos, size_t new_size) const;
+
+  // Cord::swap()
+  //
+  // Swaps the contents of the Cord with `other`.
+  void swap(Cord& other) noexcept;
+
+  // swap()
+  //
+  // Swaps the contents of two Cords.
+  friend void swap(Cord& x, Cord& y) noexcept {
+    x.swap(y);
+  }
+
+  // Cord::size()
+  //
+  // Returns the size of the Cord.
+  size_t size() const;
+
+  // Cord::empty()
+  //
+  // Determines whether the given Cord is empty, returning `true` is so.
+  bool empty() const;
+
+  // Cord::EstimatedMemoryUsage()
+  //
+  // Returns the *approximate* number of bytes held in full or in part by this
+  // Cord (which may not remain the same between invocations).  Note that Cords
+  // that share memory could each be "charged" independently for the same shared
+  // memory.
+  size_t EstimatedMemoryUsage() const;
+
+  // Cord::Compare()
+  //
+  // Compares 'this' Cord with rhs. This function and its relatives treat Cords
+  // as sequences of unsigned bytes. The comparison is a straightforward
+  // lexicographic comparison. `Cord::Compare()` returns values as follows:
+  //
+  //   -1  'this' Cord is smaller
+  //    0  two Cords are equal
+  //    1  'this' Cord is larger
+  int Compare(absl::string_view rhs) const;
+  int Compare(const Cord& rhs) const;
+
+  // Cord::StartsWith()
+  //
+  // Determines whether the Cord starts with the passed string data `rhs`.
+  bool StartsWith(const Cord& rhs) const;
+  bool StartsWith(absl::string_view rhs) const;
+
+  // Cord::EndsWidth()
+  //
+  // Determines whether the Cord ends with the passed string data `rhs`.
+  bool EndsWith(absl::string_view rhs) const;
+  bool EndsWith(const Cord& rhs) const;
+
+  // Cord::operator std::string()
+  //
+  // Converts a Cord into a `std::string()`. This operator is marked explicit to
+  // prevent unintended Cord usage in functions that take a string.
+  explicit operator std::string() const;
+
+  // CopyCordToString()
+  //
+  // Copies the contents of a `src` Cord into a `*dst` string.
+  //
+  // This function optimizes the case of reusing the destination string since it
+  // can reuse previously allocated capacity. However, this function does not
+  // guarantee that pointers previously returned by `dst->data()` remain valid
+  // even if `*dst` had enough capacity to hold `src`. If `*dst` is a new
+  // object, prefer to simply use the conversion operator to `std::string`.
+  friend void CopyCordToString(const Cord& src, std::string* dst);
+
+  class CharIterator;
+
+  //----------------------------------------------------------------------------
+  // Cord::ChunkIterator
+  //----------------------------------------------------------------------------
+  //
+  // A `Cord::ChunkIterator` allows iteration over the constituent chunks of its
+  // Cord. Such iteration allows you to perform non-const operatons on the data
+  // of a Cord without modifying it.
+  //
+  // Generally, you do not instantiate a `Cord::ChunkIterator` directly;
+  // instead, you create one implicitly through use of the `Cord::Chunks()`
+  // member function.
+  //
+  // The `Cord::ChunkIterator` has the following properties:
+  //
+  //   * The iterator is invalidated after any non-const operation on the
+  //     Cord object over which it iterates.
+  //   * The `string_view` returned by dereferencing a valid, non-`end()`
+  //     iterator is guaranteed to be non-empty.
+  //   * Two `ChunkIterator` objects can be compared equal if and only if they
+  //     remain valid and iterate over the same Cord.
+  //   * The iterator in this case is a proxy iterator; the `string_view`
+  //     returned by the iterator does not live inside the Cord, and its
+  //     lifetime is limited to the lifetime of the iterator itself. To help
+  //     prevent lifetime issues, `ChunkIterator::reference` is not a true
+  //     reference type and is equivalent to `value_type`.
+  //   * The iterator keeps state that can grow for Cords that contain many
+  //     nodes and are imbalanced due to sharing. Prefer to pass this type by
+  //     const reference instead of by value.
+  class ChunkIterator {
+   public:
+    using iterator_category = std::input_iterator_tag;
+    using value_type = absl::string_view;
+    using difference_type = ptrdiff_t;
+    using pointer = const value_type*;
+    using reference = value_type;
+
+    ChunkIterator() = default;
+
+    ChunkIterator& operator++();
+    ChunkIterator operator++(int);
+    bool operator==(const ChunkIterator& other) const;
+    bool operator!=(const ChunkIterator& other) const;
+    reference operator*() const;
+    pointer operator->() const;
+
+    friend class Cord;
+    friend class CharIterator;
+
+   private:
+    // Stack of right children of concat nodes that we have to visit.
+    // Keep this at the end of the structure to avoid cache-thrashing.
+    // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for
+    // the inlined vector size (47 exists for backward compatibility).
+    using Stack = absl::InlinedVector<absl::cord_internal::CordRep*, 47>;
+
+    // Constructs a `begin()` iterator from `cord`.
+    explicit ChunkIterator(const Cord* cord);
+
+    // Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than
+    // `current_chunk_.size()`.
+    void RemoveChunkPrefix(size_t n);
+    Cord AdvanceAndReadBytes(size_t n);
+    void AdvanceBytes(size_t n);
+
+    // Stack specific operator++
+    ChunkIterator& AdvanceStack();
+
+    // Iterates `n` bytes, where `n` is expected to be greater than or equal to
+    // `current_chunk_.size()`.
+    void AdvanceBytesSlowPath(size_t n);
+
+    // A view into bytes of the current `CordRep`. It may only be a view to a
+    // suffix of bytes if this is being used by `CharIterator`.
+    absl::string_view current_chunk_;
+    // The current leaf, or `nullptr` if the iterator points to short data.
+    // If the current chunk is a substring node, current_leaf_ points to the
+    // underlying flat or external node.
+    absl::cord_internal::CordRep* current_leaf_ = nullptr;
+    // The number of bytes left in the `Cord` over which we are iterating.
+    size_t bytes_remaining_ = 0;
+    // See 'Stack' alias definition.
+    Stack stack_of_right_children_;
+  };
+
+  // Cord::ChunkIterator::chunk_begin()
+  //
+  // Returns an iterator to the first chunk of the `Cord`.
+  //
+  // Generally, prefer using `Cord::Chunks()` within a range-based for loop for
+  // iterating over the chunks of a Cord. This method may be useful for getting
+  // a `ChunkIterator` where range-based for-loops are not useful.
+  //
+  // Example:
+  //
+  //   absl::Cord::ChunkIterator FindAsChunk(const absl::Cord& c,
+  //                                         absl::string_view s) {
+  //     return std::find(c.chunk_begin(), c.chunk_end(), s);
+  //   }
+  ChunkIterator chunk_begin() const;
+
+  // Cord::ChunkItertator::chunk_end()
+  //
+  // Returns an iterator one increment past the last chunk of the `Cord`.
+  //
+  // Generally, prefer using `Cord::Chunks()` within a range-based for loop for
+  // iterating over the chunks of a Cord. This method may be useful for getting
+  // a `ChunkIterator` where range-based for-loops may not be available.
+  ChunkIterator chunk_end() const;
+
+  //----------------------------------------------------------------------------
+  // Cord::ChunkIterator::ChunkRange
+  //----------------------------------------------------------------------------
+  //
+  // `ChunkRange` is a helper class for iterating over the chunks of the `Cord`,
+  // producing an iterator which can be used within a range-based for loop.
+  // Construction of a `ChunkRange` will return an iterator pointing to the
+  // first chunk of the Cord. Generally, do not construct a `ChunkRange`
+  // directly; instead, prefer to use the `Cord::Chunks()` method.
+  //
+  // Implementation note: `ChunkRange` is simply a convenience wrapper over
+  // `Cord::chunk_begin()` and `Cord::chunk_end()`.
+  class ChunkRange {
+   public:
+    explicit ChunkRange(const Cord* cord) : cord_(cord) {}
+
+    ChunkIterator begin() const;
+    ChunkIterator end() const;
+
+   private:
+    const Cord* cord_;
+  };
+
+  // Cord::Chunks()
+  //
+  // Returns a `Cord::ChunkIterator::ChunkRange` for iterating over the chunks
+  // of a `Cord` with a range-based for-loop. For most iteration tasks on a
+  // Cord, use `Cord::Chunks()` to retrieve this iterator.
+  //
+  // Example:
+  //
+  //   void ProcessChunks(const Cord& cord) {
+  //     for (absl::string_view chunk : cord.Chunks()) { ... }
+  //   }
+  //
+  // Note that the ordinary caveats of temporary lifetime extension apply:
+  //
+  //   void Process() {
+  //     for (absl::string_view chunk : CordFactory().Chunks()) {
+  //       // The temporary Cord returned by CordFactory has been destroyed!
+  //     }
+  //   }
+  ChunkRange Chunks() const;
+
+  //----------------------------------------------------------------------------
+  // Cord::CharIterator
+  //----------------------------------------------------------------------------
+  //
+  // A `Cord::CharIterator` allows iteration over the constituent characters of
+  // a `Cord`.
+  //
+  // Generally, you do not instantiate a `Cord::CharIterator` directly; instead,
+  // you create one implicitly through use of the `Cord::Chars()` member
+  // function.
+  //
+  // A `Cord::CharIterator` has the following properties:
+  //
+  //   * The iterator is invalidated after any non-const operation on the
+  //     Cord object over which it iterates.
+  //   * Two `CharIterator` objects can be compared equal if and only if they
+  //     remain valid and iterate over the same Cord.
+  //   * The iterator keeps state that can grow for Cords that contain many
+  //     nodes and are imbalanced due to sharing. Prefer to pass this type by
+  //     const reference instead of by value.
+  //   * This type cannot act as a forward iterator because a `Cord` can reuse
+  //     sections of memory. This fact violates the requirement for forward
+  //     iterators to compare equal if dereferencing them returns the same
+  //     object.
+  class CharIterator {
+   public:
+    using iterator_category = std::input_iterator_tag;
+    using value_type = char;
+    using difference_type = ptrdiff_t;
+    using pointer = const char*;
+    using reference = const char&;
+
+    CharIterator() = default;
+
+    CharIterator& operator++();
+    CharIterator operator++(int);
+    bool operator==(const CharIterator& other) const;
+    bool operator!=(const CharIterator& other) const;
+    reference operator*() const;
+    pointer operator->() const;
+
+    friend Cord;
+
+   private:
+    explicit CharIterator(const Cord* cord) : chunk_iterator_(cord) {}
+
+    ChunkIterator chunk_iterator_;
+  };
+
+  // Cord::CharIterator::AdvanceAndRead()
+  //
+  // Advances the `Cord::CharIterator` by `n_bytes` and returns the bytes
+  // advanced as a separate `Cord`. `n_bytes` must be less than or equal to the
+  // number of bytes within the Cord; otherwise, behavior is undefined. It is
+  // valid to pass `char_end()` and `0`.
+  static Cord AdvanceAndRead(CharIterator* it, size_t n_bytes);
+
+  // Cord::CharIterator::Advance()
+  //
+  // Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than
+  // or equal to the number of bytes remaining within the Cord; otherwise,
+  // behavior is undefined. It is valid to pass `char_end()` and `0`.
+  static void Advance(CharIterator* it, size_t n_bytes);
+
+  // Cord::CharIterator::ChunkRemaining()
+  //
+  // Returns the longest contiguous view starting at the iterator's position.
+  //
+  // `it` must be dereferenceable.
+  static absl::string_view ChunkRemaining(const CharIterator& it);
+
+  // Cord::CharIterator::char_begin()
+  //
+  // Returns an iterator to the first character of the `Cord`.
+  //
+  // Generally, prefer using `Cord::Chars()` within a range-based for loop for
+  // iterating over the chunks of a Cord. This method may be useful for getting
+  // a `CharIterator` where range-based for-loops may not be available.
+  CharIterator char_begin() const;
+
+  // Cord::CharIterator::char_end()
+  //
+  // Returns an iterator to one past the last character of the `Cord`.
+  //
+  // Generally, prefer using `Cord::Chars()` within a range-based for loop for
+  // iterating over the chunks of a Cord. This method may be useful for getting
+  // a `CharIterator` where range-based for-loops are not useful.
+  CharIterator char_end() const;
+
+  // Cord::CharIterator::CharRange
+  //
+  // `CharRange` is a helper class for iterating over the characters of a
+  // producing an iterator which can be used within a range-based for loop.
+  // Construction of a `CharRange` will return an iterator pointing to the first
+  // character of the Cord. Generally, do not construct a `CharRange` directly;
+  // instead, prefer to use the `Cord::Chars()` method show below.
+  //
+  // Implementation note: `CharRange` is simply a convenience wrapper over
+  // `Cord::char_begin()` and `Cord::char_end()`.
+  class CharRange {
+   public:
+    explicit CharRange(const Cord* cord) : cord_(cord) {}
+
+    CharIterator begin() const;
+    CharIterator end() const;
+
+   private:
+    const Cord* cord_;
+  };
+
+  // Cord::CharIterator::Chars()
+  //
+  // Returns a `Cord::CharIterator` for iterating over the characters of a
+  // `Cord` with a range-based for-loop. For most character-based iteration
+  // tasks on a Cord, use `Cord::Chars()` to retrieve this iterator.
+  //
+  // Example:
+  //
+  //   void ProcessCord(const Cord& cord) {
+  //     for (char c : cord.Chars()) { ... }
+  //   }
+  //
+  // Note that the ordinary caveats of temporary lifetime extension apply:
+  //
+  //   void Process() {
+  //     for (char c : CordFactory().Chars()) {
+  //       // The temporary Cord returned by CordFactory has been destroyed!
+  //     }
+  //   }
+  CharRange Chars() const;
+
+  // Cord::operator[]
+  //
+  // Gets the "i"th character of the Cord and returns it, provided that
+  // 0 <= i < Cord.size().
+  //
+  // NOTE: This routine is reasonably efficient. It is roughly
+  // logarithmic based on the number of chunks that make up the cord. Still,
+  // if you need to iterate over the contents of a cord, you should
+  // use a CharIterator/ChunkIterator rather than call operator[] or Get()
+  // repeatedly in a loop.
+  char operator[](size_t i) const;
+
+  // Cord::TryFlat()
+  //
+  // If this cord's representation is a single flat array, returns a
+  // string_view referencing that array.  Otherwise returns nullopt.
+  absl::optional<absl::string_view> TryFlat() const;
+
+  // Cord::Flatten()
+  //
+  // Flattens the cord into a single array and returns a view of the data.
+  //
+  // If the cord was already flat, the contents are not modified.
+  absl::string_view Flatten();
+
+  // Supports absl::Cord as a sink object for absl::Format().
+  friend void AbslFormatFlush(absl::Cord* cord, absl::string_view part) {
+    cord->Append(part);
+  }
+
+  template <typename H>
+  friend H AbslHashValue(H hash_state, const absl::Cord& c) {
+    absl::optional<absl::string_view> maybe_flat = c.TryFlat();
+    if (maybe_flat.has_value()) {
+      return H::combine(std::move(hash_state), *maybe_flat);
+    }
+    return c.HashFragmented(std::move(hash_state));
+  }
+
+  // Create a Cord with the contents of StringConstant<T>::value.
+  // No allocations will be done and no data will be copied.
+  // This is an INTERNAL API and subject to change or removal. This API can only
+  // be used by spelling absl::strings_internal::MakeStringConstant, which is
+  // also an internal API.
+  template <typename T>
+  explicit constexpr Cord(strings_internal::StringConstant<T>);
+
+ private:
+  friend class CordTestPeer;
+  friend bool operator==(const Cord& lhs, const Cord& rhs);
+  friend bool operator==(const Cord& lhs, absl::string_view rhs);
+
+  // Calls the provided function once for each cord chunk, in order.  Unlike
+  // Chunks(), this API will not allocate memory.
+  void ForEachChunk(absl::FunctionRef<void(absl::string_view)>) const;
+
+  // Allocates new contiguous storage for the contents of the cord. This is
+  // called by Flatten() when the cord was not already flat.
+  absl::string_view FlattenSlowPath();
+
+  // Actual cord contents are hidden inside the following simple
+  // class so that we can isolate the bulk of cord.cc from changes
+  // to the representation.
+  //
+  // InlineRep holds either a tree pointer, or an array of kMaxInline bytes.
+  class InlineRep {
+   public:
+    static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;
+    static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), "");
+    static constexpr unsigned char kTreeFlag = cord_internal::kTreeFlag;
+    static constexpr unsigned char kProfiledFlag = cord_internal::kProfiledFlag;
+
+    constexpr InlineRep() : data_() {}
+    InlineRep(const InlineRep& src);
+    InlineRep(InlineRep&& src);
+    InlineRep& operator=(const InlineRep& src);
+    InlineRep& operator=(InlineRep&& src) noexcept;
+
+    explicit constexpr InlineRep(cord_internal::InlineData data);
+
+    void Swap(InlineRep* rhs);
+    bool empty() const;
+    size_t size() const;
+    const char* data() const;  // Returns nullptr if holding pointer
+    void set_data(const char* data, size_t n,
+                  bool nullify_tail);  // Discards pointer, if any
+    char* set_data(size_t n);  // Write data to the result
+    // Returns nullptr if holding bytes
+    absl::cord_internal::CordRep* tree() const;
+    // Discards old pointer, if any
+    void set_tree(absl::cord_internal::CordRep* rep);
+    // Replaces a tree with a new root. This is faster than set_tree, but it
+    // should only be used when it's clear that the old rep was a tree.
+    void replace_tree(absl::cord_internal::CordRep* rep);
+    // Returns non-null iff was holding a pointer
+    absl::cord_internal::CordRep* clear();
+    // Converts to pointer if necessary.
+    absl::cord_internal::CordRep* force_tree(size_t extra_hint);
+    void reduce_size(size_t n);  // REQUIRES: holding data
+    void remove_prefix(size_t n);  // REQUIRES: holding data
+    void AppendArray(const char* src_data, size_t src_size);
+    absl::string_view FindFlatStartPiece() const;
+    void AppendTree(absl::cord_internal::CordRep* tree);
+    void PrependTree(absl::cord_internal::CordRep* tree);
+    void GetAppendRegion(char** region, size_t* size, size_t max_length);
+    void GetAppendRegion(char** region, size_t* size);
+    bool IsSame(const InlineRep& other) const {
+      return memcmp(&data_, &other.data_, sizeof(data_)) == 0;
+    }
+    int BitwiseCompare(const InlineRep& other) const {
+      uint64_t x, y;
+      // Use memcpy to avoid aliasing issues.
+      memcpy(&x, &data_, sizeof(x));
+      memcpy(&y, &other.data_, sizeof(y));
+      if (x == y) {
+        memcpy(&x, reinterpret_cast<const char*>(&data_) + 8, sizeof(x));
+        memcpy(&y, reinterpret_cast<const char*>(&other.data_) + 8, sizeof(y));
+        if (x == y) return 0;
+      }
+      return absl::big_endian::FromHost64(x) < absl::big_endian::FromHost64(y)
+                 ? -1
+                 : 1;
+    }
+    void CopyTo(std::string* dst) const {
+      // memcpy is much faster when operating on a known size. On most supported
+      // platforms, the small string optimization is large enough that resizing
+      // to 15 bytes does not cause a memory allocation.
+      absl::strings_internal::STLStringResizeUninitialized(dst,
+                                                           sizeof(data_) - 1);
+      memcpy(&(*dst)[0], &data_, sizeof(data_) - 1);
+      // erase is faster than resize because the logic for memory allocation is
+      // not needed.
+      dst->erase(tagged_size());
+    }
+
+    // Copies the inline contents into `dst`. Assumes the cord is not empty.
+    void CopyToArray(char* dst) const;
+
+    bool is_tree() const { return tagged_size() > kMaxInline; }
+
+   private:
+    friend class Cord;
+
+    void AssignSlow(const InlineRep& src);
+    // Unrefs the tree, stops profiling, and zeroes the contents
+    void ClearSlow();
+
+    void ResetToEmpty() { data_ = {}; }
+
+    // This uses reinterpret_cast instead of the union to avoid accessing the
+    // inactive union element. The tagged size is not a common prefix.
+    void set_tagged_size(char new_tag) {
+      reinterpret_cast<char*>(&data_)[kMaxInline] = new_tag;
+    }
+    char tagged_size() const {
+      return reinterpret_cast<const char*>(&data_)[kMaxInline];
+    }
+
+    cord_internal::InlineData data_;
+  };
+  InlineRep contents_;
+
+  // Helper for MemoryUsage().
+  static size_t MemoryUsageAux(const absl::cord_internal::CordRep* rep);
+
+  // Helper for GetFlat() and TryFlat().
+  static bool GetFlatAux(absl::cord_internal::CordRep* rep,
+                         absl::string_view* fragment);
+
+  // Helper for ForEachChunk().
+  static void ForEachChunkAux(
+      absl::cord_internal::CordRep* rep,
+      absl::FunctionRef<void(absl::string_view)> callback);
+
+  // The destructor for non-empty Cords.
+  void DestroyCordSlow();
+
+  // Out-of-line implementation of slower parts of logic.
+  void CopyToArraySlowPath(char* dst) const;
+  int CompareSlowPath(absl::string_view rhs, size_t compared_size,
+                      size_t size_to_compare) const;
+  int CompareSlowPath(const Cord& rhs, size_t compared_size,
+                      size_t size_to_compare) const;
+  bool EqualsImpl(absl::string_view rhs, size_t size_to_compare) const;
+  bool EqualsImpl(const Cord& rhs, size_t size_to_compare) const;
+  int CompareImpl(const Cord& rhs) const;
+
+  template <typename ResultType, typename RHS>
+  friend ResultType GenericCompare(const Cord& lhs, const RHS& rhs,
+                                   size_t size_to_compare);
+  static absl::string_view GetFirstChunk(const Cord& c);
+  static absl::string_view GetFirstChunk(absl::string_view sv);
+
+  // Returns a new reference to contents_.tree(), or steals an existing
+  // reference if called on an rvalue.
+  absl::cord_internal::CordRep* TakeRep() const&;
+  absl::cord_internal::CordRep* TakeRep() &&;
+
+  // Helper for Append().
+  template <typename C>
+  void AppendImpl(C&& src);
+
+  // Helper for AbslHashValue().
+  template <typename H>
+  H HashFragmented(H hash_state) const {
+    typename H::AbslInternalPiecewiseCombiner combiner;
+    ForEachChunk([&combiner, &hash_state](absl::string_view chunk) {
+      hash_state = combiner.add_buffer(std::move(hash_state), chunk.data(),
+                                       chunk.size());
+    });
+    return H::combine(combiner.finalize(std::move(hash_state)), size());
+  }
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// allow a Cord to be logged
+extern std::ostream& operator<<(std::ostream& out, const Cord& cord);
+
+// ------------------------------------------------------------------
+// Internal details follow.  Clients should ignore.
+
+namespace cord_internal {
+
+// Fast implementation of memmove for up to 15 bytes. This implementation is
+// safe for overlapping regions. If nullify_tail is true, the destination is
+// padded with '\0' up to 16 bytes.
+inline void SmallMemmove(char* dst, const char* src, size_t n,
+                         bool nullify_tail = false) {
+  if (n >= 8) {
+    assert(n <= 16);
+    uint64_t buf1;
+    uint64_t buf2;
+    memcpy(&buf1, src, 8);
+    memcpy(&buf2, src + n - 8, 8);
+    if (nullify_tail) {
+      memset(dst + 8, 0, 8);
+    }
+    memcpy(dst, &buf1, 8);
+    memcpy(dst + n - 8, &buf2, 8);
+  } else if (n >= 4) {
+    uint32_t buf1;
+    uint32_t buf2;
+    memcpy(&buf1, src, 4);
+    memcpy(&buf2, src + n - 4, 4);
+    if (nullify_tail) {
+      memset(dst + 4, 0, 4);
+      memset(dst + 8, 0, 8);
+    }
+    memcpy(dst, &buf1, 4);
+    memcpy(dst + n - 4, &buf2, 4);
+  } else {
+    if (n != 0) {
+      dst[0] = src[0];
+      dst[n / 2] = src[n / 2];
+      dst[n - 1] = src[n - 1];
+    }
+    if (nullify_tail) {
+      memset(dst + 8, 0, 8);
+      memset(dst + n, 0, 8);
+    }
+  }
+}
+
+// Does non-template-specific `CordRepExternal` initialization.
+// Expects `data` to be non-empty.
+void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep);
+
+// Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer
+// to it, or `nullptr` if `data` was empty.
+template <typename Releaser>
+// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
+CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) {
+  using ReleaserType = absl::decay_t<Releaser>;
+  if (data.empty()) {
+    // Never create empty external nodes.
+    InvokeReleaser(Rank0{}, ReleaserType(std::forward<Releaser>(releaser)),
+                   data);
+    return nullptr;
+  }
+
+  CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(
+      std::forward<Releaser>(releaser), 0);
+  InitializeCordRepExternal(data, rep);
+  return rep;
+}
+
+// Overload for function reference types that dispatches using a function
+// pointer because there are no `alignof()` or `sizeof()` a function reference.
+// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
+inline CordRep* NewExternalRep(absl::string_view data,
+                               void (&releaser)(absl::string_view)) {
+  return NewExternalRep(data, &releaser);
+}
+
+}  // namespace cord_internal
+
+template <typename Releaser>
+Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {
+  Cord cord;
+  cord.contents_.set_tree(::absl::cord_internal::NewExternalRep(
+      data, std::forward<Releaser>(releaser)));
+  return cord;
+}
+
+constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data)
+    : data_(data) {}
+
+inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src) {
+  data_ = src.data_;
+}
+
+inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) {
+  data_ = src.data_;
+  src.ResetToEmpty();
+}
+
+inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
+  if (this == &src) {
+    return *this;
+  }
+  if (!is_tree() && !src.is_tree()) {
+    data_ = src.data_;
+    return *this;
+  }
+  AssignSlow(src);
+  return *this;
+}
+
+inline Cord::InlineRep& Cord::InlineRep::operator=(
+    Cord::InlineRep&& src) noexcept {
+  if (is_tree()) {
+    ClearSlow();
+  }
+  data_ = src.data_;
+  src.ResetToEmpty();
+  return *this;
+}
+
+inline void Cord::InlineRep::Swap(Cord::InlineRep* rhs) {
+  if (rhs == this) {
+    return;
+  }
+
+  std::swap(data_, rhs->data_);
+}
+
+inline const char* Cord::InlineRep::data() const {
+  return is_tree() ? nullptr : data_.as_chars;
+}
+
+inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const {
+  if (is_tree()) {
+    return data_.as_tree.rep;
+  } else {
+    return nullptr;
+  }
+}
+
+inline bool Cord::InlineRep::empty() const { return tagged_size() == 0; }
+
+inline size_t Cord::InlineRep::size() const {
+  const char tag = tagged_size();
+  if (tag <= kMaxInline) return tag;
+  return static_cast<size_t>(tree()->length);
+}
+
+inline void Cord::InlineRep::set_tree(absl::cord_internal::CordRep* rep) {
+  if (rep == nullptr) {
+    ResetToEmpty();
+  } else {
+    bool was_tree = is_tree();
+    data_.as_tree = {rep, {}, tagged_size()};
+    if (!was_tree) {
+      // If we were not a tree already, set the tag.
+      // Otherwise, leave it alone because it might have the profile bit on.
+      set_tagged_size(kTreeFlag);
+    }
+  }
+}
+
+inline void Cord::InlineRep::replace_tree(absl::cord_internal::CordRep* rep) {
+  ABSL_ASSERT(is_tree());
+  if (ABSL_PREDICT_FALSE(rep == nullptr)) {
+    set_tree(rep);
+    return;
+  }
+  data_.as_tree = {rep, {}, tagged_size()};
+}
+
+inline absl::cord_internal::CordRep* Cord::InlineRep::clear() {
+  absl::cord_internal::CordRep* result = tree();
+  ResetToEmpty();
+  return result;
+}
+
+inline void Cord::InlineRep::CopyToArray(char* dst) const {
+  assert(!is_tree());
+  size_t n = tagged_size();
+  assert(n != 0);
+  cord_internal::SmallMemmove(dst, data_.as_chars, n);
+}
+
+constexpr inline Cord::Cord() noexcept {}
+
+template <typename T>
+constexpr Cord::Cord(strings_internal::StringConstant<T>)
+    : contents_(strings_internal::StringConstant<T>::value.size() <=
+                        cord_internal::kMaxInline
+                    ? cord_internal::InlineData(
+                          strings_internal::StringConstant<T>::value)
+                    : cord_internal::InlineData(cord_internal::AsTree{
+                          &cord_internal::ConstInitExternalStorage<
+                              strings_internal::StringConstant<T>>::value,
+                          {},
+                          cord_internal::kTreeFlag})) {}
+
+inline Cord& Cord::operator=(const Cord& x) {
+  contents_ = x.contents_;
+  return *this;
+}
+
+inline Cord::Cord(Cord&& src) noexcept : contents_(std::move(src.contents_)) {}
+
+inline void Cord::swap(Cord& other) noexcept {
+  contents_.Swap(&other.contents_);
+}
+
+inline Cord& Cord::operator=(Cord&& x) noexcept {
+  contents_ = std::move(x.contents_);
+  return *this;
+}
+
+extern template Cord::Cord(std::string&& src);
+extern template Cord& Cord::operator=(std::string&& src);
+
+inline size_t Cord::size() const {
+  // Length is 1st field in str.rep_
+  return contents_.size();
+}
+
+inline bool Cord::empty() const { return contents_.empty(); }
+
+inline size_t Cord::EstimatedMemoryUsage() const {
+  size_t result = sizeof(Cord);
+  if (const absl::cord_internal::CordRep* rep = contents_.tree()) {
+    result += MemoryUsageAux(rep);
+  }
+  return result;
+}
+
+inline absl::optional<absl::string_view> Cord::TryFlat() const {
+  absl::cord_internal::CordRep* rep = contents_.tree();
+  if (rep == nullptr) {
+    return absl::string_view(contents_.data(), contents_.size());
+  }
+  absl::string_view fragment;
+  if (GetFlatAux(rep, &fragment)) {
+    return fragment;
+  }
+  return absl::nullopt;
+}
+
+inline absl::string_view Cord::Flatten() {
+  absl::cord_internal::CordRep* rep = contents_.tree();
+  if (rep == nullptr) {
+    return absl::string_view(contents_.data(), contents_.size());
+  } else {
+    absl::string_view already_flat_contents;
+    if (GetFlatAux(rep, &already_flat_contents)) {
+      return already_flat_contents;
+    }
+  }
+  return FlattenSlowPath();
+}
+
+inline void Cord::Append(absl::string_view src) {
+  contents_.AppendArray(src.data(), src.size());
+}
+
+extern template void Cord::Append(std::string&& src);
+extern template void Cord::Prepend(std::string&& src);
+
+inline int Cord::Compare(const Cord& rhs) const {
+  if (!contents_.is_tree() && !rhs.contents_.is_tree()) {
+    return contents_.BitwiseCompare(rhs.contents_);
+  }
+
+  return CompareImpl(rhs);
+}
+
+// Does 'this' cord start/end with rhs
+inline bool Cord::StartsWith(const Cord& rhs) const {
+  if (contents_.IsSame(rhs.contents_)) return true;
+  size_t rhs_size = rhs.size();
+  if (size() < rhs_size) return false;
+  return EqualsImpl(rhs, rhs_size);
+}
+
+inline bool Cord::StartsWith(absl::string_view rhs) const {
+  size_t rhs_size = rhs.size();
+  if (size() < rhs_size) return false;
+  return EqualsImpl(rhs, rhs_size);
+}
+
+inline Cord::ChunkIterator::ChunkIterator(const Cord* cord)
+    : bytes_remaining_(cord->size()) {
+  if (cord->empty()) return;
+  if (cord->contents_.is_tree()) {
+    stack_of_right_children_.push_back(cord->contents_.tree());
+    operator++();
+  } else {
+    current_chunk_ = absl::string_view(cord->contents_.data(), cord->size());
+  }
+}
+
+inline Cord::ChunkIterator& Cord::ChunkIterator::operator++() {
+  ABSL_HARDENING_ASSERT(bytes_remaining_ > 0 &&
+                        "Attempted to iterate past `end()`");
+  assert(bytes_remaining_ >= current_chunk_.size());
+  bytes_remaining_ -= current_chunk_.size();
+  if (bytes_remaining_ > 0) {
+    return AdvanceStack();
+  } else {
+    current_chunk_ = {};
+  }
+  return *this;
+}
+
+inline Cord::ChunkIterator Cord::ChunkIterator::operator++(int) {
+  ChunkIterator tmp(*this);
+  operator++();
+  return tmp;
+}
+
+inline bool Cord::ChunkIterator::operator==(const ChunkIterator& other) const {
+  return bytes_remaining_ == other.bytes_remaining_;
+}
+
+inline bool Cord::ChunkIterator::operator!=(const ChunkIterator& other) const {
+  return !(*this == other);
+}
+
+inline Cord::ChunkIterator::reference Cord::ChunkIterator::operator*() const {
+  ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
+  return current_chunk_;
+}
+
+inline Cord::ChunkIterator::pointer Cord::ChunkIterator::operator->() const {
+  ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
+  return &current_chunk_;
+}
+
+inline void Cord::ChunkIterator::RemoveChunkPrefix(size_t n) {
+  assert(n < current_chunk_.size());
+  current_chunk_.remove_prefix(n);
+  bytes_remaining_ -= n;
+}
+
+inline void Cord::ChunkIterator::AdvanceBytes(size_t n) {
+  if (ABSL_PREDICT_TRUE(n < current_chunk_.size())) {
+    RemoveChunkPrefix(n);
+  } else if (n != 0) {
+    AdvanceBytesSlowPath(n);
+  }
+}
+
+inline Cord::ChunkIterator Cord::chunk_begin() const {
+  return ChunkIterator(this);
+}
+
+inline Cord::ChunkIterator Cord::chunk_end() const { return ChunkIterator(); }
+
+inline Cord::ChunkIterator Cord::ChunkRange::begin() const {
+  return cord_->chunk_begin();
+}
+
+inline Cord::ChunkIterator Cord::ChunkRange::end() const {
+  return cord_->chunk_end();
+}
+
+inline Cord::ChunkRange Cord::Chunks() const { return ChunkRange(this); }
+
+inline Cord::CharIterator& Cord::CharIterator::operator++() {
+  if (ABSL_PREDICT_TRUE(chunk_iterator_->size() > 1)) {
+    chunk_iterator_.RemoveChunkPrefix(1);
+  } else {
+    ++chunk_iterator_;
+  }
+  return *this;
+}
+
+inline Cord::CharIterator Cord::CharIterator::operator++(int) {
+  CharIterator tmp(*this);
+  operator++();
+  return tmp;
+}
+
+inline bool Cord::CharIterator::operator==(const CharIterator& other) const {
+  return chunk_iterator_ == other.chunk_iterator_;
+}
+
+inline bool Cord::CharIterator::operator!=(const CharIterator& other) const {
+  return !(*this == other);
+}
+
+inline Cord::CharIterator::reference Cord::CharIterator::operator*() const {
+  return *chunk_iterator_->data();
+}
+
+inline Cord::CharIterator::pointer Cord::CharIterator::operator->() const {
+  return chunk_iterator_->data();
+}
+
+inline Cord Cord::AdvanceAndRead(CharIterator* it, size_t n_bytes) {
+  assert(it != nullptr);
+  return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes);
+}
+
+inline void Cord::Advance(CharIterator* it, size_t n_bytes) {
+  assert(it != nullptr);
+  it->chunk_iterator_.AdvanceBytes(n_bytes);
+}
+
+inline absl::string_view Cord::ChunkRemaining(const CharIterator& it) {
+  return *it.chunk_iterator_;
+}
+
+inline Cord::CharIterator Cord::char_begin() const {
+  return CharIterator(this);
+}
+
+inline Cord::CharIterator Cord::char_end() const { return CharIterator(); }
+
+inline Cord::CharIterator Cord::CharRange::begin() const {
+  return cord_->char_begin();
+}
+
+inline Cord::CharIterator Cord::CharRange::end() const {
+  return cord_->char_end();
+}
+
+inline Cord::CharRange Cord::Chars() const { return CharRange(this); }
+
+inline void Cord::ForEachChunk(
+    absl::FunctionRef<void(absl::string_view)> callback) const {
+  absl::cord_internal::CordRep* rep = contents_.tree();
+  if (rep == nullptr) {
+    callback(absl::string_view(contents_.data(), contents_.size()));
+  } else {
+    return ForEachChunkAux(rep, callback);
+  }
+}
+
+// Nonmember Cord-to-Cord relational operarators.
+inline bool operator==(const Cord& lhs, const Cord& rhs) {
+  if (lhs.contents_.IsSame(rhs.contents_)) return true;
+  size_t rhs_size = rhs.size();
+  if (lhs.size() != rhs_size) return false;
+  return lhs.EqualsImpl(rhs, rhs_size);
+}
+
+inline bool operator!=(const Cord& x, const Cord& y) { return !(x == y); }
+inline bool operator<(const Cord& x, const Cord& y) {
+  return x.Compare(y) < 0;
+}
+inline bool operator>(const Cord& x, const Cord& y) {
+  return x.Compare(y) > 0;
+}
+inline bool operator<=(const Cord& x, const Cord& y) {
+  return x.Compare(y) <= 0;
+}
+inline bool operator>=(const Cord& x, const Cord& y) {
+  return x.Compare(y) >= 0;
+}
+
+// Nonmember Cord-to-absl::string_view relational operators.
+//
+// Due to implicit conversions, these also enable comparisons of Cord with
+// with std::string, ::string, and const char*.
+inline bool operator==(const Cord& lhs, absl::string_view rhs) {
+  size_t lhs_size = lhs.size();
+  size_t rhs_size = rhs.size();
+  if (lhs_size != rhs_size) return false;
+  return lhs.EqualsImpl(rhs, rhs_size);
+}
+
+inline bool operator==(absl::string_view x, const Cord& y) { return y == x; }
+inline bool operator!=(const Cord& x, absl::string_view y) { return !(x == y); }
+inline bool operator!=(absl::string_view x, const Cord& y) { return !(x == y); }
+inline bool operator<(const Cord& x, absl::string_view y) {
+  return x.Compare(y) < 0;
+}
+inline bool operator<(absl::string_view x, const Cord& y) {
+  return y.Compare(x) > 0;
+}
+inline bool operator>(const Cord& x, absl::string_view y) { return y < x; }
+inline bool operator>(absl::string_view x, const Cord& y) { return y < x; }
+inline bool operator<=(const Cord& x, absl::string_view y) { return !(y < x); }
+inline bool operator<=(absl::string_view x, const Cord& y) { return !(y < x); }
+inline bool operator>=(const Cord& x, absl::string_view y) { return !(x < y); }
+inline bool operator>=(absl::string_view x, const Cord& y) { return !(x < y); }
+
+// Some internals exposed to test code.
+namespace strings_internal {
+class CordTestAccess {
+ public:
+  static size_t FlatOverhead();
+  static size_t MaxFlatLength();
+  static size_t SizeofCordRepConcat();
+  static size_t SizeofCordRepExternal();
+  static size_t SizeofCordRepSubstring();
+  static size_t FlatTagToLength(uint8_t tag);
+  static uint8_t LengthToTag(size_t s);
+};
+}  // namespace strings_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_CORD_H_
diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc
new file mode 100644
index 0000000..7942bfc
--- /dev/null
+++ b/absl/strings/cord_test.cc
@@ -0,0 +1,1711 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/cord.h"
+
+#include <algorithm>
+#include <climits>
+#include <cstdio>
+#include <iterator>
+#include <map>
+#include <numeric>
+#include <random>
+#include <sstream>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/casts.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/container/fixed_array.h"
+#include "absl/strings/cord_test_helpers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+
+typedef std::mt19937_64 RandomEngine;
+
+static std::string RandomLowercaseString(RandomEngine* rng);
+static std::string RandomLowercaseString(RandomEngine* rng, size_t length);
+
+static int GetUniformRandomUpTo(RandomEngine* rng, int upper_bound) {
+  if (upper_bound > 0) {
+    std::uniform_int_distribution<int> uniform(0, upper_bound - 1);
+    return uniform(*rng);
+  } else {
+    return 0;
+  }
+}
+
+static size_t GetUniformRandomUpTo(RandomEngine* rng, size_t upper_bound) {
+  if (upper_bound > 0) {
+    std::uniform_int_distribution<size_t> uniform(0, upper_bound - 1);
+    return uniform(*rng);
+  } else {
+    return 0;
+  }
+}
+
+static int32_t GenerateSkewedRandom(RandomEngine* rng, int max_log) {
+  const uint32_t base = (*rng)() % (max_log + 1);
+  const uint32_t mask = ((base < 32) ? (1u << base) : 0u) - 1u;
+  return (*rng)() & mask;
+}
+
+static std::string RandomLowercaseString(RandomEngine* rng) {
+  int length;
+  std::bernoulli_distribution one_in_1k(0.001);
+  std::bernoulli_distribution one_in_10k(0.0001);
+  // With low probability, make a large fragment
+  if (one_in_10k(*rng)) {
+    length = GetUniformRandomUpTo(rng, 1048576);
+  } else if (one_in_1k(*rng)) {
+    length = GetUniformRandomUpTo(rng, 10000);
+  } else {
+    length = GenerateSkewedRandom(rng, 10);
+  }
+  return RandomLowercaseString(rng, length);
+}
+
+static std::string RandomLowercaseString(RandomEngine* rng, size_t length) {
+  std::string result(length, '\0');
+  std::uniform_int_distribution<int> chars('a', 'z');
+  std::generate(result.begin(), result.end(),
+                [&]() { return static_cast<char>(chars(*rng)); });
+  return result;
+}
+
+static void DoNothing(absl::string_view /* data */, void* /* arg */) {}
+
+static void DeleteExternalString(absl::string_view data, void* arg) {
+  std::string* s = reinterpret_cast<std::string*>(arg);
+  EXPECT_EQ(data, *s);
+  delete s;
+}
+
+// Add "s" to *dst via `MakeCordFromExternal`
+static void AddExternalMemory(absl::string_view s, absl::Cord* dst) {
+  std::string* str = new std::string(s.data(), s.size());
+  dst->Append(absl::MakeCordFromExternal(*str, [str](absl::string_view data) {
+    DeleteExternalString(data, str);
+  }));
+}
+
+static void DumpGrowth() {
+  absl::Cord str;
+  for (int i = 0; i < 1000; i++) {
+    char c = 'a' + i % 26;
+    str.Append(absl::string_view(&c, 1));
+  }
+}
+
+// Make a Cord with some number of fragments.  Return the size (in bytes)
+// of the smallest fragment.
+static size_t AppendWithFragments(const std::string& s, RandomEngine* rng,
+                                  absl::Cord* cord) {
+  size_t j = 0;
+  const size_t max_size = s.size() / 5;  // Make approx. 10 fragments
+  size_t min_size = max_size;            // size of smallest fragment
+  while (j < s.size()) {
+    size_t N = 1 + GetUniformRandomUpTo(rng, max_size);
+    if (N > (s.size() - j)) {
+      N = s.size() - j;
+    }
+    if (N < min_size) {
+      min_size = N;
+    }
+
+    std::bernoulli_distribution coin_flip(0.5);
+    if (coin_flip(*rng)) {
+      // Grow by adding an external-memory.
+      AddExternalMemory(absl::string_view(s.data() + j, N), cord);
+    } else {
+      cord->Append(absl::string_view(s.data() + j, N));
+    }
+    j += N;
+  }
+  return min_size;
+}
+
+// Add an external memory that contains the specified std::string to cord
+static void AddNewStringBlock(const std::string& str, absl::Cord* dst) {
+  char* data = new char[str.size()];
+  memcpy(data, str.data(), str.size());
+  dst->Append(absl::MakeCordFromExternal(
+      absl::string_view(data, str.size()),
+      [](absl::string_view s) { delete[] s.data(); }));
+}
+
+// Make a Cord out of many different types of nodes.
+static absl::Cord MakeComposite() {
+  absl::Cord cord;
+  cord.Append("the");
+  AddExternalMemory(" quick brown", &cord);
+  AddExternalMemory(" fox jumped", &cord);
+
+  absl::Cord full(" over");
+  AddExternalMemory(" the lazy", &full);
+  AddNewStringBlock(" dog slept the whole day away", &full);
+  absl::Cord substring = full.Subcord(0, 18);
+
+  // Make substring long enough to defeat the copying fast path in Append.
+  substring.Append(std::string(1000, '.'));
+  cord.Append(substring);
+  cord = cord.Subcord(0, cord.size() - 998);  // Remove most of extra junk
+
+  return cord;
+}
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+class CordTestPeer {
+ public:
+  static void ForEachChunk(
+      const Cord& c, absl::FunctionRef<void(absl::string_view)> callback) {
+    c.ForEachChunk(callback);
+  }
+
+  static bool IsTree(const Cord& c) { return c.contents_.is_tree(); }
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+TEST(Cord, AllFlatSizes) {
+  using absl::strings_internal::CordTestAccess;
+
+  for (size_t s = 0; s < CordTestAccess::MaxFlatLength(); s++) {
+    // Make a string of length s.
+    std::string src;
+    while (src.size() < s) {
+      src.push_back('a' + (src.size() % 26));
+    }
+
+    absl::Cord dst(src);
+    EXPECT_EQ(std::string(dst), src) << s;
+  }
+}
+
+// We create a Cord at least 128GB in size using the fact that Cords can
+// internally reference-count; thus the Cord is enormous without actually
+// consuming very much memory.
+TEST(GigabyteCord, FromExternal) {
+  const size_t one_gig = 1024U * 1024U * 1024U;
+  size_t max_size = 2 * one_gig;
+  if (sizeof(max_size) > 4) max_size = 128 * one_gig;
+
+  size_t length = 128 * 1024;
+  char* data = new char[length];
+  absl::Cord from = absl::MakeCordFromExternal(
+      absl::string_view(data, length),
+      [](absl::string_view sv) { delete[] sv.data(); });
+
+  // This loop may seem odd due to its combination of exponential doubling of
+  // size and incremental size increases.  We do it incrementally to be sure the
+  // Cord will need rebalancing and will exercise code that, in the past, has
+  // caused crashes in production.  We grow exponentially so that the code will
+  // execute in a reasonable amount of time.
+  absl::Cord c;
+  ABSL_RAW_LOG(INFO, "Made a Cord with %zu bytes!", c.size());
+  c.Append(from);
+  while (c.size() < max_size) {
+    c.Append(c);
+    c.Append(from);
+    c.Append(from);
+    c.Append(from);
+    c.Append(from);
+  }
+
+  for (int i = 0; i < 1024; ++i) {
+    c.Append(from);
+  }
+  ABSL_RAW_LOG(INFO, "Made a Cord with %zu bytes!", c.size());
+  // Note: on a 32-bit build, this comes out to   2,818,048,000 bytes.
+  // Note: on a 64-bit build, this comes out to 171,932,385,280 bytes.
+}
+
+static absl::Cord MakeExternalCord(int size) {
+  char* buffer = new char[size];
+  memset(buffer, 'x', size);
+  absl::Cord cord;
+  cord.Append(absl::MakeCordFromExternal(
+      absl::string_view(buffer, size),
+      [](absl::string_view s) { delete[] s.data(); }));
+  return cord;
+}
+
+// Extern to fool clang that this is not constant. Needed to suppress
+// a warning of unsafe code we want to test.
+extern bool my_unique_true_boolean;
+bool my_unique_true_boolean = true;
+
+TEST(Cord, Assignment) {
+  absl::Cord x(absl::string_view("hi there"));
+  absl::Cord y(x);
+  ASSERT_EQ(std::string(x), "hi there");
+  ASSERT_EQ(std::string(y), "hi there");
+  ASSERT_TRUE(x == y);
+  ASSERT_TRUE(x <= y);
+  ASSERT_TRUE(y <= x);
+
+  x = absl::string_view("foo");
+  ASSERT_EQ(std::string(x), "foo");
+  ASSERT_EQ(std::string(y), "hi there");
+  ASSERT_TRUE(x < y);
+  ASSERT_TRUE(y > x);
+  ASSERT_TRUE(x != y);
+  ASSERT_TRUE(x <= y);
+  ASSERT_TRUE(y >= x);
+
+  x = "foo";
+  ASSERT_EQ(x, "foo");
+
+  // Test that going from inline rep to tree we don't leak memory.
+  std::vector<std::pair<absl::string_view, absl::string_view>>
+      test_string_pairs = {{"hi there", "foo"},
+                           {"loooooong coooooord", "short cord"},
+                           {"short cord", "loooooong coooooord"},
+                           {"loooooong coooooord1", "loooooong coooooord2"}};
+  for (std::pair<absl::string_view, absl::string_view> test_strings :
+       test_string_pairs) {
+    absl::Cord tmp(test_strings.first);
+    absl::Cord z(std::move(tmp));
+    ASSERT_EQ(std::string(z), test_strings.first);
+    tmp = test_strings.second;
+    z = std::move(tmp);
+    ASSERT_EQ(std::string(z), test_strings.second);
+  }
+  {
+    // Test that self-move assignment doesn't crash/leak.
+    // Do not write such code!
+    absl::Cord my_small_cord("foo");
+    absl::Cord my_big_cord("loooooong coooooord");
+    // Bypass clang's warning on self move-assignment.
+    absl::Cord* my_small_alias =
+        my_unique_true_boolean ? &my_small_cord : &my_big_cord;
+    absl::Cord* my_big_alias =
+        !my_unique_true_boolean ? &my_small_cord : &my_big_cord;
+
+    *my_small_alias = std::move(my_small_cord);
+    *my_big_alias = std::move(my_big_cord);
+    // my_small_cord and my_big_cord are in an unspecified but valid
+    // state, and will be correctly destroyed here.
+  }
+}
+
+TEST(Cord, StartsEndsWith) {
+  absl::Cord x(absl::string_view("abcde"));
+  absl::Cord empty("");
+
+  ASSERT_TRUE(x.StartsWith(absl::Cord("abcde")));
+  ASSERT_TRUE(x.StartsWith(absl::Cord("abc")));
+  ASSERT_TRUE(x.StartsWith(absl::Cord("")));
+  ASSERT_TRUE(empty.StartsWith(absl::Cord("")));
+  ASSERT_TRUE(x.EndsWith(absl::Cord("abcde")));
+  ASSERT_TRUE(x.EndsWith(absl::Cord("cde")));
+  ASSERT_TRUE(x.EndsWith(absl::Cord("")));
+  ASSERT_TRUE(empty.EndsWith(absl::Cord("")));
+
+  ASSERT_TRUE(!x.StartsWith(absl::Cord("xyz")));
+  ASSERT_TRUE(!empty.StartsWith(absl::Cord("xyz")));
+  ASSERT_TRUE(!x.EndsWith(absl::Cord("xyz")));
+  ASSERT_TRUE(!empty.EndsWith(absl::Cord("xyz")));
+
+  ASSERT_TRUE(x.StartsWith("abcde"));
+  ASSERT_TRUE(x.StartsWith("abc"));
+  ASSERT_TRUE(x.StartsWith(""));
+  ASSERT_TRUE(empty.StartsWith(""));
+  ASSERT_TRUE(x.EndsWith("abcde"));
+  ASSERT_TRUE(x.EndsWith("cde"));
+  ASSERT_TRUE(x.EndsWith(""));
+  ASSERT_TRUE(empty.EndsWith(""));
+
+  ASSERT_TRUE(!x.StartsWith("xyz"));
+  ASSERT_TRUE(!empty.StartsWith("xyz"));
+  ASSERT_TRUE(!x.EndsWith("xyz"));
+  ASSERT_TRUE(!empty.EndsWith("xyz"));
+}
+
+TEST(Cord, Subcord) {
+  RandomEngine rng(testing::GTEST_FLAG(random_seed));
+  const std::string s = RandomLowercaseString(&rng, 1024);
+
+  absl::Cord a;
+  AppendWithFragments(s, &rng, &a);
+  ASSERT_EQ(s.size(), a.size());
+
+  // Check subcords of a, from a variety of interesting points.
+  std::set<size_t> positions;
+  for (int i = 0; i <= 32; ++i) {
+    positions.insert(i);
+    positions.insert(i * 32 - 1);
+    positions.insert(i * 32);
+    positions.insert(i * 32 + 1);
+    positions.insert(a.size() - i);
+  }
+  positions.insert(237);
+  positions.insert(732);
+  for (size_t pos : positions) {
+    if (pos > a.size()) continue;
+    for (size_t end_pos : positions) {
+      if (end_pos < pos || end_pos > a.size()) continue;
+      absl::Cord sa = a.Subcord(pos, end_pos - pos);
+      EXPECT_EQ(absl::string_view(s).substr(pos, end_pos - pos),
+                std::string(sa))
+          << a;
+    }
+  }
+
+  // Do the same thing for an inline cord.
+  const std::string sh = "short";
+  absl::Cord c(sh);
+  for (size_t pos = 0; pos <= sh.size(); ++pos) {
+    for (size_t n = 0; n <= sh.size() - pos; ++n) {
+      absl::Cord sc = c.Subcord(pos, n);
+      EXPECT_EQ(sh.substr(pos, n), std::string(sc)) << c;
+    }
+  }
+
+  // Check subcords of subcords.
+  absl::Cord sa = a.Subcord(0, a.size());
+  std::string ss = s.substr(0, s.size());
+  while (sa.size() > 1) {
+    sa = sa.Subcord(1, sa.size() - 2);
+    ss = ss.substr(1, ss.size() - 2);
+    EXPECT_EQ(ss, std::string(sa)) << a;
+    if (HasFailure()) break;  // halt cascade
+  }
+
+  // It is OK to ask for too much.
+  sa = a.Subcord(0, a.size() + 1);
+  EXPECT_EQ(s, std::string(sa));
+
+  // It is OK to ask for something beyond the end.
+  sa = a.Subcord(a.size() + 1, 0);
+  EXPECT_TRUE(sa.empty());
+  sa = a.Subcord(a.size() + 1, 1);
+  EXPECT_TRUE(sa.empty());
+}
+
+TEST(Cord, Swap) {
+  absl::string_view a("Dexter");
+  absl::string_view b("Mandark");
+  absl::Cord x(a);
+  absl::Cord y(b);
+  swap(x, y);
+  ASSERT_EQ(x, absl::Cord(b));
+  ASSERT_EQ(y, absl::Cord(a));
+  x.swap(y);
+  ASSERT_EQ(x, absl::Cord(a));
+  ASSERT_EQ(y, absl::Cord(b));
+}
+
+static void VerifyCopyToString(const absl::Cord& cord) {
+  std::string initially_empty;
+  absl::CopyCordToString(cord, &initially_empty);
+  EXPECT_EQ(initially_empty, cord);
+
+  constexpr size_t kInitialLength = 1024;
+  std::string has_initial_contents(kInitialLength, 'x');
+  const char* address_before_copy = has_initial_contents.data();
+  absl::CopyCordToString(cord, &has_initial_contents);
+  EXPECT_EQ(has_initial_contents, cord);
+
+  if (cord.size() <= kInitialLength) {
+    EXPECT_EQ(has_initial_contents.data(), address_before_copy)
+        << "CopyCordToString allocated new string storage; "
+           "has_initial_contents = \""
+        << has_initial_contents << "\"";
+  }
+}
+
+TEST(Cord, CopyToString) {
+  VerifyCopyToString(absl::Cord());
+  VerifyCopyToString(absl::Cord("small cord"));
+  VerifyCopyToString(
+      absl::MakeFragmentedCord({"fragmented ", "cord ", "to ", "test ",
+                                "copying ", "to ", "a ", "string."}));
+}
+
+TEST(TryFlat, Empty) {
+  absl::Cord c;
+  EXPECT_EQ(c.TryFlat(), "");
+}
+
+TEST(TryFlat, Flat) {
+  absl::Cord c("hello");
+  EXPECT_EQ(c.TryFlat(), "hello");
+}
+
+TEST(TryFlat, SubstrInlined) {
+  absl::Cord c("hello");
+  c.RemovePrefix(1);
+  EXPECT_EQ(c.TryFlat(), "ello");
+}
+
+TEST(TryFlat, SubstrFlat) {
+  absl::Cord c("longer than 15 bytes");
+  c.RemovePrefix(1);
+  EXPECT_EQ(c.TryFlat(), "onger than 15 bytes");
+}
+
+TEST(TryFlat, Concat) {
+  absl::Cord c = absl::MakeFragmentedCord({"hel", "lo"});
+  EXPECT_EQ(c.TryFlat(), absl::nullopt);
+}
+
+TEST(TryFlat, External) {
+  absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
+  EXPECT_EQ(c.TryFlat(), "hell");
+}
+
+TEST(TryFlat, SubstrExternal) {
+  absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
+  c.RemovePrefix(1);
+  EXPECT_EQ(c.TryFlat(), "ell");
+}
+
+TEST(TryFlat, SubstrConcat) {
+  absl::Cord c = absl::MakeFragmentedCord({"hello", " world"});
+  c.RemovePrefix(1);
+  EXPECT_EQ(c.TryFlat(), absl::nullopt);
+}
+
+static bool IsFlat(const absl::Cord& c) {
+  return c.chunk_begin() == c.chunk_end() || ++c.chunk_begin() == c.chunk_end();
+}
+
+static void VerifyFlatten(absl::Cord c) {
+  std::string old_contents(c);
+  absl::string_view old_flat;
+  bool already_flat_and_non_empty = IsFlat(c) && !c.empty();
+  if (already_flat_and_non_empty) {
+    old_flat = *c.chunk_begin();
+  }
+  absl::string_view new_flat = c.Flatten();
+
+  // Verify that the contents of the flattened Cord are correct.
+  EXPECT_EQ(new_flat, old_contents);
+  EXPECT_EQ(std::string(c), old_contents);
+
+  // If the Cord contained data and was already flat, verify that the data
+  // wasn't copied.
+  if (already_flat_and_non_empty) {
+    EXPECT_EQ(old_flat.data(), new_flat.data())
+        << "Allocated new memory even though the Cord was already flat.";
+  }
+
+  // Verify that the flattened Cord is in fact flat.
+  EXPECT_TRUE(IsFlat(c));
+}
+
+TEST(Cord, Flatten) {
+  VerifyFlatten(absl::Cord());
+  VerifyFlatten(absl::Cord("small cord"));
+  VerifyFlatten(absl::Cord("larger than small buffer optimization"));
+  VerifyFlatten(absl::MakeFragmentedCord({"small ", "fragmented ", "cord"}));
+
+  // Test with a cord that is longer than the largest flat buffer
+  RandomEngine rng(testing::GTEST_FLAG(random_seed));
+  VerifyFlatten(absl::Cord(RandomLowercaseString(&rng, 8192)));
+}
+
+// Test data
+namespace {
+class TestData {
+ private:
+  std::vector<std::string> data_;
+
+  // Return a std::string of the specified length.
+  static std::string MakeString(int length) {
+    std::string result;
+    char buf[30];
+    snprintf(buf, sizeof(buf), "(%d)", length);
+    while (result.size() < length) {
+      result += buf;
+    }
+    result.resize(length);
+    return result;
+  }
+
+ public:
+  TestData() {
+    // short strings increasing in length by one
+    for (int i = 0; i < 30; i++) {
+      data_.push_back(MakeString(i));
+    }
+
+    // strings around half kMaxFlatLength
+    static const int kMaxFlatLength = 4096 - 9;
+    static const int kHalf = kMaxFlatLength / 2;
+
+    for (int i = -10; i <= +10; i++) {
+      data_.push_back(MakeString(kHalf + i));
+    }
+
+    for (int i = -10; i <= +10; i++) {
+      data_.push_back(MakeString(kMaxFlatLength + i));
+    }
+  }
+
+  size_t size() const { return data_.size(); }
+  const std::string& data(size_t i) const { return data_[i]; }
+};
+}  // namespace
+
+TEST(Cord, MultipleLengths) {
+  TestData d;
+  for (size_t i = 0; i < d.size(); i++) {
+    std::string a = d.data(i);
+
+    {  // Construct from Cord
+      absl::Cord tmp(a);
+      absl::Cord x(tmp);
+      EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
+    }
+
+    {  // Construct from absl::string_view
+      absl::Cord x(a);
+      EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
+    }
+
+    {  // Append cord to self
+      absl::Cord self(a);
+      self.Append(self);
+      EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
+    }
+
+    {  // Prepend cord to self
+      absl::Cord self(a);
+      self.Prepend(self);
+      EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
+    }
+
+    // Try to append/prepend others
+    for (size_t j = 0; j < d.size(); j++) {
+      std::string b = d.data(j);
+
+      {  // CopyFrom Cord
+        absl::Cord x(a);
+        absl::Cord y(b);
+        x = y;
+        EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
+      }
+
+      {  // CopyFrom absl::string_view
+        absl::Cord x(a);
+        x = b;
+        EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
+      }
+
+      {  // Cord::Append(Cord)
+        absl::Cord x(a);
+        absl::Cord y(b);
+        x.Append(y);
+        EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
+      }
+
+      {  // Cord::Append(absl::string_view)
+        absl::Cord x(a);
+        x.Append(b);
+        EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
+      }
+
+      {  // Cord::Prepend(Cord)
+        absl::Cord x(a);
+        absl::Cord y(b);
+        x.Prepend(y);
+        EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
+      }
+
+      {  // Cord::Prepend(absl::string_view)
+        absl::Cord x(a);
+        x.Prepend(b);
+        EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
+      }
+    }
+  }
+}
+
+namespace {
+
+TEST(Cord, RemoveSuffixWithExternalOrSubstring) {
+  absl::Cord cord = absl::MakeCordFromExternal(
+      "foo bar baz", [](absl::string_view s) { DoNothing(s, nullptr); });
+
+  EXPECT_EQ("foo bar baz", std::string(cord));
+
+  // This RemoveSuffix() will wrap the EXTERNAL node in a SUBSTRING node.
+  cord.RemoveSuffix(4);
+  EXPECT_EQ("foo bar", std::string(cord));
+
+  // This RemoveSuffix() will adjust the SUBSTRING node in-place.
+  cord.RemoveSuffix(4);
+  EXPECT_EQ("foo", std::string(cord));
+}
+
+TEST(Cord, RemoveSuffixMakesZeroLengthNode) {
+  absl::Cord c;
+  c.Append(absl::Cord(std::string(100, 'x')));
+  absl::Cord other_ref = c;  // Prevent inplace appends
+  c.Append(absl::Cord(std::string(200, 'y')));
+  c.RemoveSuffix(200);
+  EXPECT_EQ(std::string(100, 'x'), std::string(c));
+}
+
+}  // namespace
+
+// CordSpliceTest contributed by hendrie.
+namespace {
+
+// Create a cord with an external memory block filled with 'z'
+absl::Cord CordWithZedBlock(size_t size) {
+  char* data = new char[size];
+  if (size > 0) {
+    memset(data, 'z', size);
+  }
+  absl::Cord cord = absl::MakeCordFromExternal(
+      absl::string_view(data, size),
+      [](absl::string_view s) { delete[] s.data(); });
+  return cord;
+}
+
+// Establish that ZedBlock does what we think it does.
+TEST(CordSpliceTest, ZedBlock) {
+  absl::Cord blob = CordWithZedBlock(10);
+  EXPECT_EQ(10, blob.size());
+  std::string s;
+  absl::CopyCordToString(blob, &s);
+  EXPECT_EQ("zzzzzzzzzz", s);
+}
+
+TEST(CordSpliceTest, ZedBlock0) {
+  absl::Cord blob = CordWithZedBlock(0);
+  EXPECT_EQ(0, blob.size());
+  std::string s;
+  absl::CopyCordToString(blob, &s);
+  EXPECT_EQ("", s);
+}
+
+TEST(CordSpliceTest, ZedBlockSuffix1) {
+  absl::Cord blob = CordWithZedBlock(10);
+  EXPECT_EQ(10, blob.size());
+  absl::Cord suffix(blob);
+  suffix.RemovePrefix(9);
+  EXPECT_EQ(1, suffix.size());
+  std::string s;
+  absl::CopyCordToString(suffix, &s);
+  EXPECT_EQ("z", s);
+}
+
+// Remove all of a prefix block
+TEST(CordSpliceTest, ZedBlockSuffix0) {
+  absl::Cord blob = CordWithZedBlock(10);
+  EXPECT_EQ(10, blob.size());
+  absl::Cord suffix(blob);
+  suffix.RemovePrefix(10);
+  EXPECT_EQ(0, suffix.size());
+  std::string s;
+  absl::CopyCordToString(suffix, &s);
+  EXPECT_EQ("", s);
+}
+
+absl::Cord BigCord(size_t len, char v) {
+  std::string s(len, v);
+  return absl::Cord(s);
+}
+
+// Splice block into cord.
+absl::Cord SpliceCord(const absl::Cord& blob, int64_t offset,
+                      const absl::Cord& block) {
+  ABSL_RAW_CHECK(offset >= 0, "");
+  ABSL_RAW_CHECK(offset + block.size() <= blob.size(), "");
+  absl::Cord result(blob);
+  result.RemoveSuffix(blob.size() - offset);
+  result.Append(block);
+  absl::Cord suffix(blob);
+  suffix.RemovePrefix(offset + block.size());
+  result.Append(suffix);
+  ABSL_RAW_CHECK(blob.size() == result.size(), "");
+  return result;
+}
+
+// Taking an empty suffix of a block breaks appending.
+TEST(CordSpliceTest, RemoveEntireBlock1) {
+  absl::Cord zero = CordWithZedBlock(10);
+  absl::Cord suffix(zero);
+  suffix.RemovePrefix(10);
+  absl::Cord result;
+  result.Append(suffix);
+}
+
+TEST(CordSpliceTest, RemoveEntireBlock2) {
+  absl::Cord zero = CordWithZedBlock(10);
+  absl::Cord prefix(zero);
+  prefix.RemoveSuffix(10);
+  absl::Cord suffix(zero);
+  suffix.RemovePrefix(10);
+  absl::Cord result(prefix);
+  result.Append(suffix);
+}
+
+TEST(CordSpliceTest, RemoveEntireBlock3) {
+  absl::Cord blob = CordWithZedBlock(10);
+  absl::Cord block = BigCord(10, 'b');
+  blob = SpliceCord(blob, 0, block);
+}
+
+struct CordCompareTestCase {
+  template <typename LHS, typename RHS>
+  CordCompareTestCase(const LHS& lhs, const RHS& rhs)
+      : lhs_cord(lhs), rhs_cord(rhs) {}
+
+  absl::Cord lhs_cord;
+  absl::Cord rhs_cord;
+};
+
+const auto sign = [](int x) { return x == 0 ? 0 : (x > 0 ? 1 : -1); };
+
+void VerifyComparison(const CordCompareTestCase& test_case) {
+  std::string lhs_string(test_case.lhs_cord);
+  std::string rhs_string(test_case.rhs_cord);
+  int expected = sign(lhs_string.compare(rhs_string));
+  EXPECT_EQ(expected, test_case.lhs_cord.Compare(test_case.rhs_cord))
+      << "LHS=" << lhs_string << "; RHS=" << rhs_string;
+  EXPECT_EQ(expected, test_case.lhs_cord.Compare(rhs_string))
+      << "LHS=" << lhs_string << "; RHS=" << rhs_string;
+  EXPECT_EQ(-expected, test_case.rhs_cord.Compare(test_case.lhs_cord))
+      << "LHS=" << rhs_string << "; RHS=" << lhs_string;
+  EXPECT_EQ(-expected, test_case.rhs_cord.Compare(lhs_string))
+      << "LHS=" << rhs_string << "; RHS=" << lhs_string;
+}
+
+TEST(Cord, Compare) {
+  absl::Cord subcord("aaaaaBBBBBcccccDDDDD");
+  subcord = subcord.Subcord(3, 10);
+
+  absl::Cord tmp("aaaaaaaaaaaaaaaa");
+  tmp.Append("BBBBBBBBBBBBBBBB");
+  absl::Cord concat = absl::Cord("cccccccccccccccc");
+  concat.Append("DDDDDDDDDDDDDDDD");
+  concat.Prepend(tmp);
+
+  absl::Cord concat2("aaaaaaaaaaaaa");
+  concat2.Append("aaaBBBBBBBBBBBBBBBBccccc");
+  concat2.Append("cccccccccccDDDDDDDDDDDDDD");
+  concat2.Append("DD");
+
+  std::vector<CordCompareTestCase> test_cases = {{
+      // Inline cords
+      {"abcdef", "abcdef"},
+      {"abcdef", "abcdee"},
+      {"abcdef", "abcdeg"},
+      {"bbcdef", "abcdef"},
+      {"bbcdef", "abcdeg"},
+      {"abcdefa", "abcdef"},
+      {"abcdef", "abcdefa"},
+
+      // Small flat cords
+      {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDD"},
+      {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBxccccDDDDD"},
+      {"aaaaaBBBBBcxcccDDDDD", "aaaaaBBBBBcccccDDDDD"},
+      {"aaaaaBBBBBxccccDDDDD", "aaaaaBBBBBcccccDDDDX"},
+      {"aaaaaBBBBBcccccDDDDDa", "aaaaaBBBBBcccccDDDDD"},
+      {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDDa"},
+
+      // Subcords
+      {subcord, subcord},
+      {subcord, "aaBBBBBccc"},
+      {subcord, "aaBBBBBccd"},
+      {subcord, "aaBBBBBccb"},
+      {subcord, "aaBBBBBxcb"},
+      {subcord, "aaBBBBBccca"},
+      {subcord, "aaBBBBBcc"},
+
+      // Concats
+      {concat, concat},
+      {concat,
+       "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDD"},
+      {concat,
+       "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBcccccccccccccccxDDDDDDDDDDDDDDDD"},
+      {concat,
+       "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBacccccccccccccccDDDDDDDDDDDDDDDD"},
+      {concat,
+       "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDD"},
+      {concat,
+       "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDDe"},
+
+      {concat, concat2},
+  }};
+
+  for (const auto& tc : test_cases) {
+    VerifyComparison(tc);
+  }
+}
+
+TEST(Cord, CompareAfterAssign) {
+  absl::Cord a("aaaaaa1111111");
+  absl::Cord b("aaaaaa2222222");
+  a = "cccccc";
+  b = "cccccc";
+  EXPECT_EQ(a, b);
+  EXPECT_FALSE(a < b);
+
+  a = "aaaa";
+  b = "bbbbb";
+  a = "";
+  b = "";
+  EXPECT_EQ(a, b);
+  EXPECT_FALSE(a < b);
+}
+
+// Test CompareTo() and ComparePrefix() against string and substring
+// comparison methods from basic_string.
+static void TestCompare(const absl::Cord& c, const absl::Cord& d,
+                        RandomEngine* rng) {
+  typedef std::basic_string<uint8_t> ustring;
+  ustring cs(reinterpret_cast<const uint8_t*>(std::string(c).data()), c.size());
+  ustring ds(reinterpret_cast<const uint8_t*>(std::string(d).data()), d.size());
+  // ustring comparison is ideal because we expect Cord comparisons to be
+  // based on unsigned byte comparisons regardless of whether char is signed.
+  int expected = sign(cs.compare(ds));
+  EXPECT_EQ(expected, sign(c.Compare(d))) << c << ", " << d;
+}
+
+TEST(Compare, ComparisonIsUnsigned) {
+  RandomEngine rng(testing::GTEST_FLAG(random_seed));
+  std::uniform_int_distribution<uint32_t> uniform_uint8(0, 255);
+  char x = static_cast<char>(uniform_uint8(rng));
+  TestCompare(
+      absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x)),
+      absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x ^ 0x80)), &rng);
+}
+
+TEST(Compare, RandomComparisons) {
+  const int kIters = 5000;
+  RandomEngine rng(testing::GTEST_FLAG(random_seed));
+
+  int n = GetUniformRandomUpTo(&rng, 5000);
+  absl::Cord a[] = {MakeExternalCord(n),
+                    absl::Cord("ant"),
+                    absl::Cord("elephant"),
+                    absl::Cord("giraffe"),
+                    absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100),
+                                           GetUniformRandomUpTo(&rng, 100))),
+                    absl::Cord(""),
+                    absl::Cord("x"),
+                    absl::Cord("A"),
+                    absl::Cord("B"),
+                    absl::Cord("C")};
+  for (int i = 0; i < kIters; i++) {
+    absl::Cord c, d;
+    for (int j = 0; j < (i % 7) + 1; j++) {
+      c.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);
+      d.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);
+    }
+    std::bernoulli_distribution coin_flip(0.5);
+    TestCompare(coin_flip(rng) ? c : absl::Cord(std::string(c)),
+                coin_flip(rng) ? d : absl::Cord(std::string(d)), &rng);
+  }
+}
+
+template <typename T1, typename T2>
+void CompareOperators() {
+  const T1 a("a");
+  const T2 b("b");
+
+  EXPECT_TRUE(a == a);
+  // For pointer type (i.e. `const char*`), operator== compares the address
+  // instead of the string, so `a == const char*("a")` isn't necessarily true.
+  EXPECT_TRUE(std::is_pointer<T1>::value || a == T1("a"));
+  EXPECT_TRUE(std::is_pointer<T2>::value || a == T2("a"));
+  EXPECT_FALSE(a == b);
+
+  EXPECT_TRUE(a != b);
+  EXPECT_FALSE(a != a);
+
+  EXPECT_TRUE(a < b);
+  EXPECT_FALSE(b < a);
+
+  EXPECT_TRUE(b > a);
+  EXPECT_FALSE(a > b);
+
+  EXPECT_TRUE(a >= a);
+  EXPECT_TRUE(b >= a);
+  EXPECT_FALSE(a >= b);
+
+  EXPECT_TRUE(a <= a);
+  EXPECT_TRUE(a <= b);
+  EXPECT_FALSE(b <= a);
+}
+
+TEST(ComparisonOperators, Cord_Cord) {
+  CompareOperators<absl::Cord, absl::Cord>();
+}
+
+TEST(ComparisonOperators, Cord_StringPiece) {
+  CompareOperators<absl::Cord, absl::string_view>();
+}
+
+TEST(ComparisonOperators, StringPiece_Cord) {
+  CompareOperators<absl::string_view, absl::Cord>();
+}
+
+TEST(ComparisonOperators, Cord_string) {
+  CompareOperators<absl::Cord, std::string>();
+}
+
+TEST(ComparisonOperators, string_Cord) {
+  CompareOperators<std::string, absl::Cord>();
+}
+
+TEST(ComparisonOperators, stdstring_Cord) {
+  CompareOperators<std::string, absl::Cord>();
+}
+
+TEST(ComparisonOperators, Cord_stdstring) {
+  CompareOperators<absl::Cord, std::string>();
+}
+
+TEST(ComparisonOperators, charstar_Cord) {
+  CompareOperators<const char*, absl::Cord>();
+}
+
+TEST(ComparisonOperators, Cord_charstar) {
+  CompareOperators<absl::Cord, const char*>();
+}
+
+TEST(ConstructFromExternal, ReleaserInvoked) {
+  // Empty external memory means the releaser should be called immediately.
+  {
+    bool invoked = false;
+    auto releaser = [&invoked](absl::string_view) { invoked = true; };
+    {
+      auto c = absl::MakeCordFromExternal("", releaser);
+      EXPECT_TRUE(invoked);
+    }
+  }
+
+  // If the size of the data is small enough, a future constructor
+  // implementation may copy the bytes and immediately invoke the releaser
+  // instead of creating an external node. We make a large dummy std::string to
+  // make this test independent of such an optimization.
+  std::string large_dummy(2048, 'c');
+  {
+    bool invoked = false;
+    auto releaser = [&invoked](absl::string_view) { invoked = true; };
+    {
+      auto c = absl::MakeCordFromExternal(large_dummy, releaser);
+      EXPECT_FALSE(invoked);
+    }
+    EXPECT_TRUE(invoked);
+  }
+
+  {
+    bool invoked = false;
+    auto releaser = [&invoked](absl::string_view) { invoked = true; };
+    {
+      absl::Cord copy;
+      {
+        auto c = absl::MakeCordFromExternal(large_dummy, releaser);
+        copy = c;
+        EXPECT_FALSE(invoked);
+      }
+      EXPECT_FALSE(invoked);
+    }
+    EXPECT_TRUE(invoked);
+  }
+}
+
+TEST(ConstructFromExternal, CompareContents) {
+  RandomEngine rng(testing::GTEST_FLAG(random_seed));
+
+  for (int length = 1; length <= 2048; length *= 2) {
+    std::string data = RandomLowercaseString(&rng, length);
+    auto* external = new std::string(data);
+    auto cord =
+        absl::MakeCordFromExternal(*external, [external](absl::string_view sv) {
+          EXPECT_EQ(external->data(), sv.data());
+          EXPECT_EQ(external->size(), sv.size());
+          delete external;
+        });
+    EXPECT_EQ(data, cord);
+  }
+}
+
+TEST(ConstructFromExternal, LargeReleaser) {
+  RandomEngine rng(testing::GTEST_FLAG(random_seed));
+  constexpr size_t kLength = 256;
+  std::string data = RandomLowercaseString(&rng, kLength);
+  std::array<char, kLength> data_array;
+  for (size_t i = 0; i < kLength; ++i) data_array[i] = data[i];
+  bool invoked = false;
+  auto releaser = [data_array, &invoked](absl::string_view data) {
+    EXPECT_EQ(data, absl::string_view(data_array.data(), data_array.size()));
+    invoked = true;
+  };
+  (void)absl::MakeCordFromExternal(data, releaser);
+  EXPECT_TRUE(invoked);
+}
+
+TEST(ConstructFromExternal, FunctionPointerReleaser) {
+  static absl::string_view data("hello world");
+  static bool invoked;
+  auto* releaser =
+      static_cast<void (*)(absl::string_view)>([](absl::string_view sv) {
+        EXPECT_EQ(data, sv);
+        invoked = true;
+      });
+  invoked = false;
+  (void)absl::MakeCordFromExternal(data, releaser);
+  EXPECT_TRUE(invoked);
+
+  invoked = false;
+  (void)absl::MakeCordFromExternal(data, *releaser);
+  EXPECT_TRUE(invoked);
+}
+
+TEST(ConstructFromExternal, MoveOnlyReleaser) {
+  struct Releaser {
+    explicit Releaser(bool* invoked) : invoked(invoked) {}
+    Releaser(Releaser&& other) noexcept : invoked(other.invoked) {}
+    void operator()(absl::string_view) const { *invoked = true; }
+
+    bool* invoked;
+  };
+
+  bool invoked = false;
+  (void)absl::MakeCordFromExternal("dummy", Releaser(&invoked));
+  EXPECT_TRUE(invoked);
+}
+
+TEST(ConstructFromExternal, NoArgLambda) {
+  bool invoked = false;
+  (void)absl::MakeCordFromExternal("dummy", [&invoked]() { invoked = true; });
+  EXPECT_TRUE(invoked);
+}
+
+TEST(ConstructFromExternal, StringViewArgLambda) {
+  bool invoked = false;
+  (void)absl::MakeCordFromExternal(
+      "dummy", [&invoked](absl::string_view) { invoked = true; });
+  EXPECT_TRUE(invoked);
+}
+
+TEST(ConstructFromExternal, NonTrivialReleaserDestructor) {
+  struct Releaser {
+    explicit Releaser(bool* destroyed) : destroyed(destroyed) {}
+    ~Releaser() { *destroyed = true; }
+    void operator()(absl::string_view) const {}
+
+    bool* destroyed;
+  };
+
+  bool destroyed = false;
+  Releaser releaser(&destroyed);
+  (void)absl::MakeCordFromExternal("dummy", releaser);
+  EXPECT_TRUE(destroyed);
+}
+
+TEST(ConstructFromExternal, ReferenceQualifierOverloads) {
+  struct Releaser {
+    void operator()(absl::string_view) & { *lvalue_invoked = true; }
+    void operator()(absl::string_view) && { *rvalue_invoked = true; }
+
+    bool* lvalue_invoked;
+    bool* rvalue_invoked;
+  };
+
+  bool lvalue_invoked = false;
+  bool rvalue_invoked = false;
+  Releaser releaser = {&lvalue_invoked, &rvalue_invoked};
+  (void)absl::MakeCordFromExternal("", releaser);
+  EXPECT_FALSE(lvalue_invoked);
+  EXPECT_TRUE(rvalue_invoked);
+  rvalue_invoked = false;
+
+  (void)absl::MakeCordFromExternal("dummy", releaser);
+  EXPECT_FALSE(lvalue_invoked);
+  EXPECT_TRUE(rvalue_invoked);
+  rvalue_invoked = false;
+
+  // NOLINTNEXTLINE: suppress clang-tidy std::move on trivially copyable type.
+  (void)absl::MakeCordFromExternal("dummy", std::move(releaser));
+  EXPECT_FALSE(lvalue_invoked);
+  EXPECT_TRUE(rvalue_invoked);
+}
+
+TEST(ExternalMemory, BasicUsage) {
+  static const char* strings[] = {"", "hello", "there"};
+  for (const char* str : strings) {
+    absl::Cord dst("(prefix)");
+    AddExternalMemory(str, &dst);
+    dst.Append("(suffix)");
+    EXPECT_EQ((std::string("(prefix)") + str + std::string("(suffix)")),
+              std::string(dst));
+  }
+}
+
+TEST(ExternalMemory, RemovePrefixSuffix) {
+  // Exhaustively try all sub-strings.
+  absl::Cord cord = MakeComposite();
+  std::string s = std::string(cord);
+  for (int offset = 0; offset <= s.size(); offset++) {
+    for (int length = 0; length <= s.size() - offset; length++) {
+      absl::Cord result(cord);
+      result.RemovePrefix(offset);
+      result.RemoveSuffix(result.size() - length);
+      EXPECT_EQ(s.substr(offset, length), std::string(result))
+          << offset << " " << length;
+    }
+  }
+}
+
+TEST(ExternalMemory, Get) {
+  absl::Cord cord("hello");
+  AddExternalMemory(" world!", &cord);
+  AddExternalMemory(" how are ", &cord);
+  cord.Append(" you?");
+  std::string s = std::string(cord);
+  for (int i = 0; i < s.size(); i++) {
+    EXPECT_EQ(s[i], cord[i]);
+  }
+}
+
+// CordMemoryUsage tests verify the correctness of the EstimatedMemoryUsage()
+// These tests take into account that the reported memory usage is approximate
+// and non-deterministic. For all tests, We verify that the reported memory
+// usage is larger than `size()`, and less than `size() * 1.5` as a cord should
+// never reserve more 'extra' capacity than half of its size as it grows.
+// Additionally we have some whiteboxed expectations based on our knowledge of
+// the layout and size of empty and inlined cords, and flat nodes.
+
+TEST(CordMemoryUsage, Empty) {
+  EXPECT_EQ(sizeof(absl::Cord), absl::Cord().EstimatedMemoryUsage());
+}
+
+TEST(CordMemoryUsage, Embedded) {
+  absl::Cord a("hello");
+  EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord));
+}
+
+TEST(CordMemoryUsage, EmbeddedAppend) {
+  absl::Cord a("a");
+  absl::Cord b("bcd");
+  EXPECT_EQ(b.EstimatedMemoryUsage(), sizeof(absl::Cord));
+  a.Append(b);
+  EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord));
+}
+
+TEST(CordMemoryUsage, ExternalMemory) {
+  static const int kLength = 1000;
+  absl::Cord cord;
+  AddExternalMemory(std::string(kLength, 'x'), &cord);
+  EXPECT_GT(cord.EstimatedMemoryUsage(), kLength);
+  EXPECT_LE(cord.EstimatedMemoryUsage(), kLength * 1.5);
+}
+
+TEST(CordMemoryUsage, Flat) {
+  static const int kLength = 125;
+  absl::Cord a(std::string(kLength, 'a'));
+  EXPECT_GT(a.EstimatedMemoryUsage(), kLength);
+  EXPECT_LE(a.EstimatedMemoryUsage(), kLength * 1.5);
+}
+
+TEST(CordMemoryUsage, AppendFlat) {
+  using absl::strings_internal::CordTestAccess;
+  absl::Cord a(std::string(CordTestAccess::MaxFlatLength(), 'a'));
+  size_t length = a.EstimatedMemoryUsage();
+  a.Append(std::string(CordTestAccess::MaxFlatLength(), 'b'));
+  size_t delta = a.EstimatedMemoryUsage() - length;
+  EXPECT_GT(delta, CordTestAccess::MaxFlatLength());
+  EXPECT_LE(delta, CordTestAccess::MaxFlatLength() * 1.5);
+}
+
+// Regtest for a change that had to be rolled back because it expanded out
+// of the InlineRep too soon, which was observable through MemoryUsage().
+TEST(CordMemoryUsage, InlineRep) {
+  constexpr size_t kMaxInline = 15;  // Cord::InlineRep::N
+  const std::string small_string(kMaxInline, 'x');
+  absl::Cord c1(small_string);
+
+  absl::Cord c2;
+  c2.Append(small_string);
+  EXPECT_EQ(c1, c2);
+  EXPECT_EQ(c1.EstimatedMemoryUsage(), c2.EstimatedMemoryUsage());
+}
+
+}  // namespace
+
+// Regtest for 7510292 (fix a bug introduced by 7465150)
+TEST(Cord, Concat_Append) {
+  // Create a rep of type CONCAT
+  absl::Cord s1("foobarbarbarbarbar");
+  s1.Append("abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg");
+  size_t size = s1.size();
+
+  // Create a copy of s1 and append to it.
+  absl::Cord s2 = s1;
+  s2.Append("x");
+
+  // 7465150 modifies s1 when it shouldn't.
+  EXPECT_EQ(s1.size(), size);
+  EXPECT_EQ(s2.size(), size + 1);
+}
+
+TEST(MakeFragmentedCord, MakeFragmentedCordFromInitializerList) {
+  absl::Cord fragmented =
+      absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"});
+
+  EXPECT_EQ("A fragmented Cord", fragmented);
+
+  auto chunk_it = fragmented.chunk_begin();
+
+  ASSERT_TRUE(chunk_it != fragmented.chunk_end());
+  EXPECT_EQ("A ", *chunk_it);
+
+  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
+  EXPECT_EQ("fragmented ", *chunk_it);
+
+  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
+  EXPECT_EQ("Cord", *chunk_it);
+
+  ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
+}
+
+TEST(MakeFragmentedCord, MakeFragmentedCordFromVector) {
+  std::vector<absl::string_view> chunks = {"A ", "fragmented ", "Cord"};
+  absl::Cord fragmented = absl::MakeFragmentedCord(chunks);
+
+  EXPECT_EQ("A fragmented Cord", fragmented);
+
+  auto chunk_it = fragmented.chunk_begin();
+
+  ASSERT_TRUE(chunk_it != fragmented.chunk_end());
+  EXPECT_EQ("A ", *chunk_it);
+
+  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
+  EXPECT_EQ("fragmented ", *chunk_it);
+
+  ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
+  EXPECT_EQ("Cord", *chunk_it);
+
+  ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
+}
+
+TEST(CordChunkIterator, Traits) {
+  static_assert(std::is_copy_constructible<absl::Cord::ChunkIterator>::value,
+                "");
+  static_assert(std::is_copy_assignable<absl::Cord::ChunkIterator>::value, "");
+
+  // Move semantics to satisfy swappable via std::swap
+  static_assert(std::is_move_constructible<absl::Cord::ChunkIterator>::value,
+                "");
+  static_assert(std::is_move_assignable<absl::Cord::ChunkIterator>::value, "");
+
+  static_assert(
+      std::is_same<
+          std::iterator_traits<absl::Cord::ChunkIterator>::iterator_category,
+          std::input_iterator_tag>::value,
+      "");
+  static_assert(
+      std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::value_type,
+                   absl::string_view>::value,
+      "");
+  static_assert(
+      std::is_same<
+          std::iterator_traits<absl::Cord::ChunkIterator>::difference_type,
+          ptrdiff_t>::value,
+      "");
+  static_assert(
+      std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::pointer,
+                   const absl::string_view*>::value,
+      "");
+  static_assert(
+      std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::reference,
+                   absl::string_view>::value,
+      "");
+}
+
+static void VerifyChunkIterator(const absl::Cord& cord,
+                                size_t expected_chunks) {
+  EXPECT_EQ(cord.chunk_begin() == cord.chunk_end(), cord.empty()) << cord;
+  EXPECT_EQ(cord.chunk_begin() != cord.chunk_end(), !cord.empty());
+
+  absl::Cord::ChunkRange range = cord.Chunks();
+  EXPECT_EQ(range.begin() == range.end(), cord.empty());
+  EXPECT_EQ(range.begin() != range.end(), !cord.empty());
+
+  std::string content(cord);
+  size_t pos = 0;
+  auto pre_iter = cord.chunk_begin(), post_iter = cord.chunk_begin();
+  size_t n_chunks = 0;
+  while (pre_iter != cord.chunk_end() && post_iter != cord.chunk_end()) {
+    EXPECT_FALSE(pre_iter == cord.chunk_end());   // NOLINT: explicitly test ==
+    EXPECT_FALSE(post_iter == cord.chunk_end());  // NOLINT
+
+    EXPECT_EQ(pre_iter, post_iter);
+    EXPECT_EQ(*pre_iter, *post_iter);
+
+    EXPECT_EQ(pre_iter->data(), (*pre_iter).data());
+    EXPECT_EQ(pre_iter->size(), (*pre_iter).size());
+
+    absl::string_view chunk = *pre_iter;
+    EXPECT_FALSE(chunk.empty());
+    EXPECT_LE(pos + chunk.size(), content.size());
+    EXPECT_EQ(absl::string_view(content.c_str() + pos, chunk.size()), chunk);
+
+    int n_equal_iterators = 0;
+    for (absl::Cord::ChunkIterator it = range.begin(); it != range.end();
+         ++it) {
+      n_equal_iterators += static_cast<int>(it == pre_iter);
+    }
+    EXPECT_EQ(n_equal_iterators, 1);
+
+    ++pre_iter;
+    EXPECT_EQ(*post_iter++, chunk);
+
+    pos += chunk.size();
+    ++n_chunks;
+  }
+  EXPECT_EQ(expected_chunks, n_chunks);
+  EXPECT_EQ(pos, content.size());
+  EXPECT_TRUE(pre_iter == cord.chunk_end());   // NOLINT: explicitly test ==
+  EXPECT_TRUE(post_iter == cord.chunk_end());  // NOLINT
+}
+
+TEST(CordChunkIterator, Operations) {
+  absl::Cord empty_cord;
+  VerifyChunkIterator(empty_cord, 0);
+
+  absl::Cord small_buffer_cord("small cord");
+  VerifyChunkIterator(small_buffer_cord, 1);
+
+  absl::Cord flat_node_cord("larger than small buffer optimization");
+  VerifyChunkIterator(flat_node_cord, 1);
+
+  VerifyChunkIterator(
+      absl::MakeFragmentedCord({"a ", "small ", "fragmented ", "cord ", "for ",
+                                "testing ", "chunk ", "iterations."}),
+      8);
+
+  absl::Cord reused_nodes_cord(std::string(40, 'c'));
+  reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'b')));
+  reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'a')));
+  size_t expected_chunks = 3;
+  for (int i = 0; i < 8; ++i) {
+    reused_nodes_cord.Prepend(reused_nodes_cord);
+    expected_chunks *= 2;
+    VerifyChunkIterator(reused_nodes_cord, expected_chunks);
+  }
+
+  RandomEngine rng(testing::GTEST_FLAG(random_seed));
+  absl::Cord flat_cord(RandomLowercaseString(&rng, 256));
+  absl::Cord subcords;
+  for (int i = 0; i < 128; ++i) subcords.Prepend(flat_cord.Subcord(i, 128));
+  VerifyChunkIterator(subcords, 128);
+}
+
+TEST(CordCharIterator, Traits) {
+  static_assert(std::is_copy_constructible<absl::Cord::CharIterator>::value,
+                "");
+  static_assert(std::is_copy_assignable<absl::Cord::CharIterator>::value, "");
+
+  // Move semantics to satisfy swappable via std::swap
+  static_assert(std::is_move_constructible<absl::Cord::CharIterator>::value,
+                "");
+  static_assert(std::is_move_assignable<absl::Cord::CharIterator>::value, "");
+
+  static_assert(
+      std::is_same<
+          std::iterator_traits<absl::Cord::CharIterator>::iterator_category,
+          std::input_iterator_tag>::value,
+      "");
+  static_assert(
+      std::is_same<std::iterator_traits<absl::Cord::CharIterator>::value_type,
+                   char>::value,
+      "");
+  static_assert(
+      std::is_same<
+          std::iterator_traits<absl::Cord::CharIterator>::difference_type,
+          ptrdiff_t>::value,
+      "");
+  static_assert(
+      std::is_same<std::iterator_traits<absl::Cord::CharIterator>::pointer,
+                   const char*>::value,
+      "");
+  static_assert(
+      std::is_same<std::iterator_traits<absl::Cord::CharIterator>::reference,
+                   const char&>::value,
+      "");
+}
+
+static void VerifyCharIterator(const absl::Cord& cord) {
+  EXPECT_EQ(cord.char_begin() == cord.char_end(), cord.empty());
+  EXPECT_EQ(cord.char_begin() != cord.char_end(), !cord.empty());
+
+  absl::Cord::CharRange range = cord.Chars();
+  EXPECT_EQ(range.begin() == range.end(), cord.empty());
+  EXPECT_EQ(range.begin() != range.end(), !cord.empty());
+
+  size_t i = 0;
+  absl::Cord::CharIterator pre_iter = cord.char_begin();
+  absl::Cord::CharIterator post_iter = cord.char_begin();
+  std::string content(cord);
+  while (pre_iter != cord.char_end() && post_iter != cord.char_end()) {
+    EXPECT_FALSE(pre_iter == cord.char_end());   // NOLINT: explicitly test ==
+    EXPECT_FALSE(post_iter == cord.char_end());  // NOLINT
+
+    EXPECT_LT(i, cord.size());
+    EXPECT_EQ(content[i], *pre_iter);
+
+    EXPECT_EQ(pre_iter, post_iter);
+    EXPECT_EQ(*pre_iter, *post_iter);
+    EXPECT_EQ(&*pre_iter, &*post_iter);
+
+    EXPECT_EQ(&*pre_iter, pre_iter.operator->());
+
+    const char* character_address = &*pre_iter;
+    absl::Cord::CharIterator copy = pre_iter;
+    ++copy;
+    EXPECT_EQ(character_address, &*pre_iter);
+
+    int n_equal_iterators = 0;
+    for (absl::Cord::CharIterator it = range.begin(); it != range.end(); ++it) {
+      n_equal_iterators += static_cast<int>(it == pre_iter);
+    }
+    EXPECT_EQ(n_equal_iterators, 1);
+
+    absl::Cord::CharIterator advance_iter = range.begin();
+    absl::Cord::Advance(&advance_iter, i);
+    EXPECT_EQ(pre_iter, advance_iter);
+
+    advance_iter = range.begin();
+    EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, i), cord.Subcord(0, i));
+    EXPECT_EQ(pre_iter, advance_iter);
+
+    advance_iter = pre_iter;
+    absl::Cord::Advance(&advance_iter, cord.size() - i);
+    EXPECT_EQ(range.end(), advance_iter);
+
+    advance_iter = pre_iter;
+    EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, cord.size() - i),
+              cord.Subcord(i, cord.size() - i));
+    EXPECT_EQ(range.end(), advance_iter);
+
+    ++i;
+    ++pre_iter;
+    post_iter++;
+  }
+  EXPECT_EQ(i, cord.size());
+  EXPECT_TRUE(pre_iter == cord.char_end());   // NOLINT: explicitly test ==
+  EXPECT_TRUE(post_iter == cord.char_end());  // NOLINT
+
+  absl::Cord::CharIterator zero_advanced_end = cord.char_end();
+  absl::Cord::Advance(&zero_advanced_end, 0);
+  EXPECT_EQ(zero_advanced_end, cord.char_end());
+
+  absl::Cord::CharIterator it = cord.char_begin();
+  for (absl::string_view chunk : cord.Chunks()) {
+    while (!chunk.empty()) {
+      EXPECT_EQ(absl::Cord::ChunkRemaining(it), chunk);
+      chunk.remove_prefix(1);
+      ++it;
+    }
+  }
+}
+
+TEST(CordCharIterator, Operations) {
+  absl::Cord empty_cord;
+  VerifyCharIterator(empty_cord);
+
+  absl::Cord small_buffer_cord("small cord");
+  VerifyCharIterator(small_buffer_cord);
+
+  absl::Cord flat_node_cord("larger than small buffer optimization");
+  VerifyCharIterator(flat_node_cord);
+
+  VerifyCharIterator(
+      absl::MakeFragmentedCord({"a ", "small ", "fragmented ", "cord ", "for ",
+                                "testing ", "character ", "iteration."}));
+
+  absl::Cord reused_nodes_cord("ghi");
+  reused_nodes_cord.Prepend(absl::Cord("def"));
+  reused_nodes_cord.Prepend(absl::Cord("abc"));
+  for (int i = 0; i < 4; ++i) {
+    reused_nodes_cord.Prepend(reused_nodes_cord);
+    VerifyCharIterator(reused_nodes_cord);
+  }
+
+  RandomEngine rng(testing::GTEST_FLAG(random_seed));
+  absl::Cord flat_cord(RandomLowercaseString(&rng, 256));
+  absl::Cord subcords;
+  for (int i = 0; i < 4; ++i) subcords.Prepend(flat_cord.Subcord(16 * i, 128));
+  VerifyCharIterator(subcords);
+}
+
+TEST(Cord, StreamingOutput) {
+  absl::Cord c =
+      absl::MakeFragmentedCord({"A ", "small ", "fragmented ", "Cord", "."});
+  std::stringstream output;
+  output << c;
+  EXPECT_EQ("A small fragmented Cord.", output.str());
+}
+
+TEST(Cord, ForEachChunk) {
+  for (int num_elements : {1, 10, 200}) {
+    SCOPED_TRACE(num_elements);
+    std::vector<std::string> cord_chunks;
+    for (int i = 0; i < num_elements; ++i) {
+      cord_chunks.push_back(absl::StrCat("[", i, "]"));
+    }
+    absl::Cord c = absl::MakeFragmentedCord(cord_chunks);
+
+    std::vector<std::string> iterated_chunks;
+    absl::CordTestPeer::ForEachChunk(c,
+                                     [&iterated_chunks](absl::string_view sv) {
+                                       iterated_chunks.emplace_back(sv);
+                                     });
+    EXPECT_EQ(iterated_chunks, cord_chunks);
+  }
+}
+
+TEST(Cord, SmallBufferAssignFromOwnData) {
+  constexpr size_t kMaxInline = 15;
+  std::string contents = "small buff cord";
+  EXPECT_EQ(contents.size(), kMaxInline);
+  for (size_t pos = 0; pos < contents.size(); ++pos) {
+    for (size_t count = contents.size() - pos; count > 0; --count) {
+      absl::Cord c(contents);
+      absl::string_view flat = c.Flatten();
+      c = flat.substr(pos, count);
+      EXPECT_EQ(c, contents.substr(pos, count))
+          << "pos = " << pos << "; count = " << count;
+    }
+  }
+}
+
+TEST(Cord, Format) {
+  absl::Cord c;
+  absl::Format(&c, "There were %04d little %s.", 3, "pigs");
+  EXPECT_EQ(c, "There were 0003 little pigs.");
+  absl::Format(&c, "And %-3llx bad wolf!", 1);
+  EXPECT_EQ(c, "There were 0003 little pigs.And 1   bad wolf!");
+}
+
+TEST(CordDeathTest, Hardening) {
+  absl::Cord cord("hello");
+  // These statement should abort the program in all builds modes.
+  EXPECT_DEATH_IF_SUPPORTED(cord.RemovePrefix(6), "");
+  EXPECT_DEATH_IF_SUPPORTED(cord.RemoveSuffix(6), "");
+
+  bool test_hardening = false;
+  ABSL_HARDENING_ASSERT([&]() {
+    // This only runs when ABSL_HARDENING_ASSERT is active.
+    test_hardening = true;
+    return true;
+  }());
+  if (!test_hardening) return;
+
+  EXPECT_DEATH_IF_SUPPORTED(cord[5], "");
+  EXPECT_DEATH_IF_SUPPORTED(*cord.chunk_end(), "");
+  EXPECT_DEATH_IF_SUPPORTED(static_cast<void>(cord.chunk_end()->empty()), "");
+  EXPECT_DEATH_IF_SUPPORTED(++cord.chunk_end(), "");
+}
+
+class AfterExitCordTester {
+ public:
+  bool Set(absl::Cord* cord, absl::string_view expected) {
+    cord_ = cord;
+    expected_ = expected;
+    return true;
+  }
+
+  ~AfterExitCordTester() {
+    EXPECT_EQ(*cord_, expected_);
+  }
+ private:
+  absl::Cord* cord_;
+  absl::string_view expected_;
+};
+
+template <typename Str>
+void TestConstinitConstructor(Str) {
+  const auto expected = Str::value;
+  // Defined before `cord` to be destroyed after it.
+  static AfterExitCordTester exit_tester;  // NOLINT
+  ABSL_CONST_INIT static absl::Cord cord(Str{});  // NOLINT
+  static bool init_exit_tester = exit_tester.Set(&cord, expected);
+  (void)init_exit_tester;
+
+  EXPECT_EQ(cord, expected);
+  // Copy the object and test the copy, and the original.
+  {
+    absl::Cord copy = cord;
+    EXPECT_EQ(copy, expected);
+  }
+  // The original still works
+  EXPECT_EQ(cord, expected);
+
+  // Try making adding more structure to the tree.
+  {
+    absl::Cord copy = cord;
+    std::string expected_copy(expected);
+    for (int i = 0; i < 10; ++i) {
+      copy.Append(cord);
+      absl::StrAppend(&expected_copy, expected);
+      EXPECT_EQ(copy, expected_copy);
+    }
+  }
+
+  // Make sure we are using the right branch during constant evaluation.
+  EXPECT_EQ(absl::CordTestPeer::IsTree(cord), cord.size() >= 16);
+
+  for (int i = 0; i < 10; ++i) {
+    // Make a few more Cords from the same global rep.
+    // This tests what happens when the refcount for it gets below 1.
+    EXPECT_EQ(expected, absl::Cord(Str{}));
+  }
+}
+
+constexpr int SimpleStrlen(const char* p) {
+  return *p ? 1 + SimpleStrlen(p + 1) : 0;
+}
+
+struct ShortView {
+  constexpr absl::string_view operator()() const {
+    return absl::string_view("SSO string", SimpleStrlen("SSO string"));
+  }
+};
+
+struct LongView {
+  constexpr absl::string_view operator()() const {
+    return absl::string_view("String that does not fit SSO.",
+                             SimpleStrlen("String that does not fit SSO."));
+  }
+};
+
+
+TEST(Cord, ConstinitConstructor) {
+  TestConstinitConstructor(
+      absl::strings_internal::MakeStringConstant(ShortView{}));
+  TestConstinitConstructor(
+      absl::strings_internal::MakeStringConstant(LongView{}));
+}
diff --git a/absl/strings/cord_test_helpers.h b/absl/strings/cord_test_helpers.h
new file mode 100644
index 0000000..f1036e3
--- /dev/null
+++ b/absl/strings/cord_test_helpers.h
@@ -0,0 +1,60 @@
+//
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef ABSL_STRINGS_CORD_TEST_HELPERS_H_
+#define ABSL_STRINGS_CORD_TEST_HELPERS_H_
+
+#include "absl/strings/cord.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// Creates a multi-segment Cord from an iterable container of strings.  The
+// resulting Cord is guaranteed to have one segment for every string in the
+// container.  This allows code to be unit tested with multi-segment Cord
+// inputs.
+//
+// Example:
+//
+//   absl::Cord c = absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"});
+//   EXPECT_FALSE(c.GetFlat(&unused));
+//
+// The mechanism by which this Cord is created is an implementation detail.  Any
+// implementation that produces a multi-segment Cord may produce a flat Cord in
+// the future as new optimizations are added to the Cord class.
+// MakeFragmentedCord will, however, always be updated to return a multi-segment
+// Cord.
+template <typename Container>
+Cord MakeFragmentedCord(const Container& c) {
+  Cord result;
+  for (const auto& s : c) {
+    auto* external = new std::string(s);
+    Cord tmp = absl::MakeCordFromExternal(
+        *external, [external](absl::string_view) { delete external; });
+    tmp.Prepend(result);
+    result = tmp;
+  }
+  return result;
+}
+
+inline Cord MakeFragmentedCord(std::initializer_list<absl::string_view> list) {
+  return MakeFragmentedCord<std::initializer_list<absl::string_view>>(list);
+}
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_CORD_TEST_HELPERS_H_
diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc
index 0d336e3..18b20b8 100644
--- a/absl/strings/escaping.cc
+++ b/absl/strings/escaping.cc
@@ -26,6 +26,7 @@
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/unaligned_access.h"
 #include "absl/strings/internal/char_map.h"
+#include "absl/strings/internal/escaping.h"
 #include "absl/strings/internal/resize_uninitialized.h"
 #include "absl/strings/internal/utf8.h"
 #include "absl/strings/str_cat.h"
@@ -33,29 +34,9 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
-// Digit conversion.
-constexpr char kHexChar[] = "0123456789abcdef";
-
-constexpr char kHexTable[513] =
-    "000102030405060708090a0b0c0d0e0f"
-    "101112131415161718191a1b1c1d1e1f"
-    "202122232425262728292a2b2c2d2e2f"
-    "303132333435363738393a3b3c3d3e3f"
-    "404142434445464748494a4b4c4d4e4f"
-    "505152535455565758595a5b5c5d5e5f"
-    "606162636465666768696a6b6c6d6e6f"
-    "707172737475767778797a7b7c7d7e7f"
-    "808182838485868788898a8b8c8d8e8f"
-    "909192939495969798999a9b9c9d9e9f"
-    "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
-    "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
-    "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
-    "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
-    "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
-    "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
-
 // These are used for the leave_nulls_escaped argument to CUnescapeInternal().
 constexpr bool kUnescapeNulls = false;
 
@@ -156,7 +137,7 @@
             // Copy the escape sequence for the null character
             const ptrdiff_t octal_size = p + 1 - octal_start;
             *d++ = '\\';
-            memcpy(d, octal_start, octal_size);
+            memmove(d, octal_start, octal_size);
             d += octal_size;
             break;
           }
@@ -189,7 +170,7 @@
             // Copy the escape sequence for the null character
             const ptrdiff_t hex_size = p + 1 - hex_start;
             *d++ = '\\';
-            memcpy(d, hex_start, hex_size);
+            memmove(d, hex_start, hex_size);
             d += hex_size;
             break;
           }
@@ -222,7 +203,7 @@
           if ((rune == 0) && leave_nulls_escaped) {
             // Copy the escape sequence for the null character
             *d++ = '\\';
-            memcpy(d, hex_start, 5);  // u0000
+            memmove(d, hex_start, 5);  // u0000
             d += 5;
             break;
           }
@@ -270,7 +251,7 @@
           if ((rune == 0) && leave_nulls_escaped) {
             // Copy the escape sequence for the null character
             *d++ = '\\';
-            memcpy(d, hex_start, 9);  // U00000000
+            memmove(d, hex_start, 9);  // U00000000
             d += 9;
             break;
           }
@@ -348,14 +329,14 @@
              (last_hex_escape && absl::ascii_isxdigit(c)))) {
           if (use_hex) {
             dest.append("\\" "x");
-            dest.push_back(kHexChar[c / 16]);
-            dest.push_back(kHexChar[c % 16]);
+            dest.push_back(numbers_internal::kHexChar[c / 16]);
+            dest.push_back(numbers_internal::kHexChar[c % 16]);
             is_hex_escape = true;
           } else {
             dest.append("\\");
-            dest.push_back(kHexChar[c / 64]);
-            dest.push_back(kHexChar[(c % 64) / 8]);
-            dest.push_back(kHexChar[c % 8]);
+            dest.push_back(numbers_internal::kHexChar[c / 64]);
+            dest.push_back(numbers_internal::kHexChar[(c % 64) / 8]);
+            dest.push_back(numbers_internal::kHexChar[c % 8]);
           }
         } else {
           dest.push_back(c);
@@ -469,7 +450,7 @@
 
   // The GET_INPUT macro gets the next input character, skipping
   // over any whitespace, and stopping when we reach the end of the
-  // std::string or when we read any non-data character.  The arguments are
+  // string or when we read any non-data character.  The arguments are
   // an arbitrary identifier (used as a label for goto) and the number
   // of data bytes that must remain in the input to avoid aborting the
   // loop.
@@ -492,18 +473,18 @@
   if (dest) {
     // This loop consumes 4 input bytes and produces 3 output bytes
     // per iteration.  We can't know at the start that there is enough
-    // data left in the std::string for a full iteration, so the loop may
+    // data left in the string for a full iteration, so the loop may
     // break out in the middle; if so 'state' will be set to the
     // number of input bytes read.
 
     while (szsrc >= 4) {
       // We'll start by optimistically assuming that the next four
-      // bytes of the std::string (src[0..3]) are four good data bytes
+      // bytes of the string (src[0..3]) are four good data bytes
       // (that is, no nulls, whitespace, padding chars, or illegal
       // chars).  We need to test src[0..2] for nulls individually
       // before constructing temp to preserve the property that we
-      // never read past a null in the std::string (no matter how long
-      // szsrc claims the std::string is).
+      // never read past a null in the string (no matter how long
+      // szsrc claims the string is).
 
       if (!src[0] || !src[1] || !src[2] ||
           ((temp = ((unsigned(unbase64[src[0]]) << 18) |
@@ -528,7 +509,7 @@
         temp = (temp << 6) | decode;
       } else {
         // We really did have four good data bytes, so advance four
-        // characters in the std::string.
+        // characters in the string.
 
         szsrc -= 4;
         src += 4;
@@ -663,7 +644,7 @@
                    state);
   }
 
-  // The remainder of the std::string should be all whitespace, mixed with
+  // The remainder of the string should be all whitespace, mixed with
   // exactly 0 equals signs, or exactly 'expected_equals' equals
   // signs.  (Always accepting 0 equals signs is an Abseil extension
   // not covered in the RFC, as is accepting dot as the pad character.)
@@ -784,180 +765,13 @@
 };
 /* clang-format on */
 
-size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) {
-  // Base64 encodes three bytes of input at a time. If the input is not
-  // divisible by three, we pad as appropriate.
-  //
-  // (from https://tools.ietf.org/html/rfc3548)
-  // Special processing is performed if fewer than 24 bits are available
-  // at the end of the data being encoded.  A full encoding quantum is
-  // always completed at the end of a quantity.  When fewer than 24 input
-  // bits are available in an input group, zero bits are added (on the
-  // right) to form an integral number of 6-bit groups.  Padding at the
-  // end of the data is performed using the '=' character.  Since all base
-  // 64 input is an integral number of octets, only the following cases
-  // can arise:
-
-  // Base64 encodes each three bytes of input into four bytes of output.
-  size_t len = (input_len / 3) * 4;
-
-  if (input_len % 3 == 0) {
-    // (from https://tools.ietf.org/html/rfc3548)
-    // (1) the final quantum of encoding input is an integral multiple of 24
-    // bits; here, the final unit of encoded output will be an integral
-    // multiple of 4 characters with no "=" padding,
-  } else if (input_len % 3 == 1) {
-    // (from https://tools.ietf.org/html/rfc3548)
-    // (2) the final quantum of encoding input is exactly 8 bits; here, the
-    // final unit of encoded output will be two characters followed by two
-    // "=" padding characters, or
-    len += 2;
-    if (do_padding) {
-      len += 2;
-    }
-  } else {  // (input_len % 3 == 2)
-    // (from https://tools.ietf.org/html/rfc3548)
-    // (3) the final quantum of encoding input is exactly 16 bits; here, the
-    // final unit of encoded output will be three characters followed by one
-    // "=" padding character.
-    len += 3;
-    if (do_padding) {
-      len += 1;
-    }
-  }
-
-  assert(len >= input_len);  // make sure we didn't overflow
-  return len;
-}
-
-size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
-                            size_t szdest, const char* base64,
-                            bool do_padding) {
-  static const char kPad64 = '=';
-
-  if (szsrc * 4 > szdest * 3) return 0;
-
-  char* cur_dest = dest;
-  const unsigned char* cur_src = src;
-
-  char* const limit_dest = dest + szdest;
-  const unsigned char* const limit_src = src + szsrc;
-
-  // Three bytes of data encodes to four characters of cyphertext.
-  // So we can pump through three-byte chunks atomically.
-  if (szsrc >= 3) {  // "limit_src - 3" is UB if szsrc < 3.
-    while (cur_src < limit_src - 3) {  // While we have >= 32 bits.
-      uint32_t in = absl::big_endian::Load32(cur_src) >> 8;
-
-      cur_dest[0] = base64[in >> 18];
-      in &= 0x3FFFF;
-      cur_dest[1] = base64[in >> 12];
-      in &= 0xFFF;
-      cur_dest[2] = base64[in >> 6];
-      in &= 0x3F;
-      cur_dest[3] = base64[in];
-
-      cur_dest += 4;
-      cur_src += 3;
-    }
-  }
-  // To save time, we didn't update szdest or szsrc in the loop.  So do it now.
-  szdest = limit_dest - cur_dest;
-  szsrc = limit_src - cur_src;
-
-  /* now deal with the tail (<=3 bytes) */
-  switch (szsrc) {
-    case 0:
-      // Nothing left; nothing more to do.
-      break;
-    case 1: {
-      // One byte left: this encodes to two characters, and (optionally)
-      // two pad characters to round out the four-character cypherblock.
-      if (szdest < 2) return 0;
-      uint32_t in = cur_src[0];
-      cur_dest[0] = base64[in >> 2];
-      in &= 0x3;
-      cur_dest[1] = base64[in << 4];
-      cur_dest += 2;
-      szdest -= 2;
-      if (do_padding) {
-        if (szdest < 2) return 0;
-        cur_dest[0] = kPad64;
-        cur_dest[1] = kPad64;
-        cur_dest += 2;
-        szdest -= 2;
-      }
-      break;
-    }
-    case 2: {
-      // Two bytes left: this encodes to three characters, and (optionally)
-      // one pad character to round out the four-character cypherblock.
-      if (szdest < 3) return 0;
-      uint32_t in = absl::big_endian::Load16(cur_src);
-      cur_dest[0] = base64[in >> 10];
-      in &= 0x3FF;
-      cur_dest[1] = base64[in >> 4];
-      in &= 0x00F;
-      cur_dest[2] = base64[in << 2];
-      cur_dest += 3;
-      szdest -= 3;
-      if (do_padding) {
-        if (szdest < 1) return 0;
-        cur_dest[0] = kPad64;
-        cur_dest += 1;
-        szdest -= 1;
-      }
-      break;
-    }
-    case 3: {
-      // Three bytes left: same as in the big loop above.  We can't do this in
-      // the loop because the loop above always reads 4 bytes, and the fourth
-      // byte is past the end of the input.
-      if (szdest < 4) return 0;
-      uint32_t in = (cur_src[0] << 16) + absl::big_endian::Load16(cur_src + 1);
-      cur_dest[0] = base64[in >> 18];
-      in &= 0x3FFFF;
-      cur_dest[1] = base64[in >> 12];
-      in &= 0xFFF;
-      cur_dest[2] = base64[in >> 6];
-      in &= 0x3F;
-      cur_dest[3] = base64[in];
-      cur_dest += 4;
-      szdest -= 4;
-      break;
-    }
-    default:
-      // Should not be reached: blocks of 4 bytes are handled
-      // in the while loop before this switch statement.
-      ABSL_RAW_LOG(FATAL, "Logic problem? szsrc = %zu", szsrc);
-      break;
-  }
-  return (cur_dest - dest);
-}
-
-constexpr char kBase64Chars[] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
 constexpr char kWebSafeBase64Chars[] =
     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
 
 template <typename String>
-void Base64EscapeInternal(const unsigned char* src, size_t szsrc, String* dest,
-                          bool do_padding, const char* base64_chars) {
-  const size_t calc_escaped_size =
-      CalculateBase64EscapedLenInternal(szsrc, do_padding);
-  strings_internal::STLStringResizeUninitialized(dest, calc_escaped_size);
-
-  const size_t escaped_len = Base64EscapeInternal(
-      src, szsrc, &(*dest)[0], dest->size(), base64_chars, do_padding);
-  assert(calc_escaped_size == escaped_len);
-  dest->erase(escaped_len);
-}
-
-template <typename String>
 bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
                             const signed char* unbase64) {
-  // Determine the size of the output std::string.  Base64 encodes every 3 bytes into
+  // Determine the size of the output string.  Base64 encodes every 3 bytes into
   // 4 characters.  any leftover chars are added directly for good measure.
   // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548
   const size_t dest_len = 3 * (slen / 4) + (slen % 4);
@@ -965,7 +779,7 @@
   strings_internal::STLStringResizeUninitialized(dest, dest_len);
 
   // We are getting the destination buffer by getting the beginning of the
-  // std::string and converting it into a char *.
+  // string and converting it into a char *.
   size_t len;
   const bool ok =
       Base64UnescapeInternal(src, slen, &(*dest)[0], dest_len, unbase64, &len);
@@ -982,7 +796,7 @@
 }
 
 /* clang-format off */
-constexpr char kHexValue[256] = {
+constexpr char kHexValueLenient[256] = {
     0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -998,8 +812,9 @@
     0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 };
+
 /* clang-format on */
 
 // This is a templated function so that T can be either a char*
@@ -1008,8 +823,8 @@
 template <typename T>
 void HexStringToBytesInternal(const char* from, T to, ptrdiff_t num) {
   for (int i = 0; i < num; i++) {
-    to[i] = (kHexValue[from[i * 2] & 0xFF] << 4) +
-            (kHexValue[from[i * 2 + 1] & 0xFF]);
+    to[i] = (kHexValueLenient[from[i * 2] & 0xFF] << 4) +
+            (kHexValueLenient[from[i * 2 + 1] & 0xFF]);
   }
 }
 
@@ -1019,7 +834,7 @@
 void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) {
   auto dest_ptr = &dest[0];
   for (auto src_ptr = src; src_ptr != (src + num); ++src_ptr, dest_ptr += 2) {
-    const char* hex_p = &kHexTable[*src_ptr * 2];
+    const char* hex_p = &numbers_internal::kHexTable[*src_ptr * 2];
     std::copy(hex_p, hex_p + 2, dest_ptr);
   }
 }
@@ -1087,26 +902,30 @@
 }
 
 void Base64Escape(absl::string_view src, std::string* dest) {
-  Base64EscapeInternal(reinterpret_cast<const unsigned char*>(src.data()),
-                       src.size(), dest, true, kBase64Chars);
+  strings_internal::Base64EscapeInternal(
+      reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
+      true, strings_internal::kBase64Chars);
 }
 
 void WebSafeBase64Escape(absl::string_view src, std::string* dest) {
-  Base64EscapeInternal(reinterpret_cast<const unsigned char*>(src.data()),
-                       src.size(), dest, false, kWebSafeBase64Chars);
+  strings_internal::Base64EscapeInternal(
+      reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
+      false, kWebSafeBase64Chars);
 }
 
 std::string Base64Escape(absl::string_view src) {
   std::string dest;
-  Base64EscapeInternal(reinterpret_cast<const unsigned char*>(src.data()),
-                       src.size(), &dest, true, kBase64Chars);
+  strings_internal::Base64EscapeInternal(
+      reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
+      true, strings_internal::kBase64Chars);
   return dest;
 }
 
 std::string WebSafeBase64Escape(absl::string_view src) {
   std::string dest;
-  Base64EscapeInternal(reinterpret_cast<const unsigned char*>(src.data()),
-                       src.size(), &dest, false, kWebSafeBase64Chars);
+  strings_internal::Base64EscapeInternal(
+      reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
+      false, kWebSafeBase64Chars);
   return dest;
 }
 
@@ -1126,4 +945,5 @@
   return result;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/escaping.h b/absl/strings/escaping.h
index 198b934..f5ca26c 100644
--- a/absl/strings/escaping.h
+++ b/absl/strings/escaping.h
@@ -33,6 +33,7 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // CUnescape()
 //
@@ -157,6 +158,7 @@
 // `2*from.size()`.
 std::string BytesToHexString(absl::string_view from);
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_ESCAPING_H_
diff --git a/absl/strings/escaping_test.cc b/absl/strings/escaping_test.cc
index 1967975..45671a0 100644
--- a/absl/strings/escaping_test.cc
+++ b/absl/strings/escaping_test.cc
@@ -300,7 +300,7 @@
   absl::string_view plaintext;
   absl::string_view cyphertext;
 } const base64_tests[] = {
-    // Empty std::string.
+    // Empty string.
     {{"", 0}, {"", 0}},
     {{nullptr, 0},
      {"", 0}},  // if length is zero, plaintext ptr must be ignored!
@@ -586,7 +586,7 @@
     EXPECT_EQ(encoded, websafe);
     EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), websafe);
 
-    // Let's try the std::string version of the decoder
+    // Let's try the string version of the decoder
     decoded = "this junk should be ignored";
     EXPECT_TRUE(absl::WebSafeBase64Unescape(websafe, &decoded));
     EXPECT_EQ(decoded, tc.plaintext);
@@ -625,7 +625,7 @@
   std::string escaped;
   absl::Base64Escape(huge, &escaped);
 
-  // Generates the std::string that should match a base64 encoded "xxx..." std::string.
+  // Generates the string that should match a base64 encoded "xxx..." string.
   // "xxx" in base64 is "eHh4".
   std::string expected_encoding;
   expected_encoding.reserve(kSize / 3 * 4);
diff --git a/absl/strings/internal/char_map.h b/absl/strings/internal/char_map.h
index b9108b8..61484de 100644
--- a/absl/strings/internal/char_map.h
+++ b/absl/strings/internal/char_map.h
@@ -28,6 +28,7 @@
 #include "absl/base/port.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 class Charmap {
@@ -71,7 +72,7 @@
                    CharMaskForWord(x, 2), CharMaskForWord(x, 3));
   }
 
-  // Containing all the chars in the C-std::string 's'.
+  // Containing all the chars in the C-string 's'.
   // Note that this is expensively recursive because of the C++11 constexpr
   // formulation. Use only in constexpr initializers.
   static constexpr Charmap FromString(const char* s) {
@@ -149,6 +150,7 @@
 constexpr Charmap PunctCharmap() { return GraphCharmap() & ~AlnumCharmap(); }
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
diff --git a/absl/strings/internal/charconv_bigint.cc b/absl/strings/internal/charconv_bigint.cc
index 95d471d..ebf8c07 100644
--- a/absl/strings/internal/charconv_bigint.cc
+++ b/absl/strings/internal/charconv_bigint.cc
@@ -19,6 +19,7 @@
 #include <string>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 namespace {
@@ -157,12 +158,12 @@
 int LargePowerOfFiveSize(int i) { return 2 * i; }
 }  // namespace
 
-const uint32_t kFiveToNth[14] = {
+ABSL_DLL const uint32_t kFiveToNth[14] = {
     1,     5,      25,      125,     625,      3125,      15625,
     78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125,
 };
 
-const uint32_t kTenToNth[10] = {
+ABSL_DLL const uint32_t kTenToNth[10] = {
     1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
 };
 
@@ -207,7 +208,7 @@
     ++dropped_digits;
   }
   if (begin < end && *std::prev(end) == '.') {
-    // If the std::string ends in '.', either before or after dropping zeroes, then
+    // If the string ends in '.', either before or after dropping zeroes, then
     // drop the decimal point and look for more digits to drop.
     dropped_digits = 0;
     --end;
@@ -354,4 +355,5 @@
 template class BigUnsigned<84>;
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/charconv_bigint.h b/absl/strings/internal/charconv_bigint.h
index 7da9a7e..8f70297 100644
--- a/absl/strings/internal/charconv_bigint.h
+++ b/absl/strings/internal/charconv_bigint.h
@@ -20,11 +20,13 @@
 #include <iostream>
 #include <string>
 
+#include "absl/base/config.h"
 #include "absl/strings/ascii.h"
 #include "absl/strings/internal/charconv_parse.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 // The largest power that 5 that can be raised to, and still fit in a uint32_t.
@@ -32,8 +34,9 @@
 // The largest power that 10 that can be raised to, and still fit in a uint32_t.
 constexpr int kMaxSmallPowerOfTen = 9;
 
-extern const uint32_t kFiveToNth[kMaxSmallPowerOfFive + 1];
-extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
+ABSL_DLL extern const uint32_t
+    kFiveToNth[kMaxSmallPowerOfFive + 1];
+ABSL_DLL extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
 
 // Large, fixed-width unsigned integer.
 //
@@ -63,7 +66,7 @@
                static_cast<uint32_t>(v >> 32)} {}
 
   // Constructs a BigUnsigned from the given string_view containing a decimal
-  // value.  If the input std::string is not a decimal integer, constructs a 0
+  // value.  If the input string is not a decimal integer, constructs a 0
   // instead.
   explicit BigUnsigned(absl::string_view sv) : size_(0), words_{} {
     // Check for valid input, returning a 0 otherwise.  This is reasonable
@@ -207,7 +210,7 @@
     return words_[index];
   }
 
-  // Returns this integer as a decimal std::string.  This is not used in the decimal-
+  // Returns this integer as a decimal string.  This is not used in the decimal-
   // to-binary conversion; it is intended to aid in testing.
   std::string ToString() const;
 
@@ -414,6 +417,7 @@
 extern template class BigUnsigned<84>;
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
diff --git a/absl/strings/internal/charconv_bigint_test.cc b/absl/strings/internal/charconv_bigint_test.cc
index 745714a..a8b9945 100644
--- a/absl/strings/internal/charconv_bigint_test.cc
+++ b/absl/strings/internal/charconv_bigint_test.cc
@@ -19,6 +19,7 @@
 #include "gtest/gtest.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 TEST(BigUnsigned, ShiftLeft) {
@@ -68,6 +69,61 @@
     // And we should have fully rotated all bits off by now:
     EXPECT_EQ(a, BigUnsigned<84>(0u));
   }
+  {
+    // Bit shifting large and small numbers by large and small offsets.
+    // Intended to exercise bounds-checking corner on ShiftLeft() (directly
+    // and under asan).
+
+    // 2**(32*84)-1
+    const BigUnsigned<84> all_bits_one(
+        "1474444211396924248063325089479706787923460402125687709454567433186613"
+        "6228083464060749874845919674257665016359189106695900028098437021384227"
+        "3285029708032466536084583113729486015826557532750465299832071590813090"
+        "2011853039837649252477307070509704043541368002938784757296893793903797"
+        "8180292336310543540677175225040919704702800559606097685920595947397024"
+        "8303316808753252115729411497720357971050627997031988036134171378490368"
+        "6008000778741115399296162550786288457245180872759047016734959330367829"
+        "5235612397427686310674725251378116268607113017720538636924549612987647"
+        "5767411074510311386444547332882472126067840027882117834454260409440463"
+        "9345147252664893456053258463203120637089916304618696601333953616715125"
+        "2115882482473279040772264257431663818610405673876655957323083702713344"
+        "4201105427930770976052393421467136557055");
+    const BigUnsigned<84> zero(0u);
+    const BigUnsigned<84> one(1u);
+    // in bounds shifts
+    for (int i = 1; i < 84*32; ++i) {
+      // shifting all_bits_one to the left should result in a smaller number,
+      // since the high bits rotate off and the low bits are replaced with
+      // zeroes.
+      BigUnsigned<84> big_shifted = all_bits_one;
+      big_shifted.ShiftLeft(i);
+      EXPECT_GT(all_bits_one, big_shifted);
+      // Shifting 1 to the left should instead result in a larger number.
+      BigUnsigned<84> small_shifted = one;
+      small_shifted.ShiftLeft(i);
+      EXPECT_LT(one, small_shifted);
+    }
+    // Shifting by zero or a negative number has no effect
+    for (int no_op_shift : {0, -1, -84 * 32, std::numeric_limits<int>::min()}) {
+      BigUnsigned<84> big_shifted = all_bits_one;
+      big_shifted.ShiftLeft(no_op_shift);
+      EXPECT_EQ(all_bits_one, big_shifted);
+      BigUnsigned<84> small_shifted = one;
+      big_shifted.ShiftLeft(no_op_shift);
+      EXPECT_EQ(one, small_shifted);
+    }
+    // Shifting by an amount greater than the number of bits should result in
+    // zero.
+    for (int out_of_bounds_shift :
+         {84 * 32, 84 * 32 + 1, std::numeric_limits<int>::max()}) {
+      BigUnsigned<84> big_shifted = all_bits_one;
+      big_shifted.ShiftLeft(out_of_bounds_shift);
+      EXPECT_EQ(zero, big_shifted);
+      BigUnsigned<84> small_shifted = one;
+      small_shifted.ShiftLeft(out_of_bounds_shift);
+      EXPECT_EQ(zero, small_shifted);
+    }
+  }
 }
 
 TEST(BigUnsigned, MultiplyByUint32) {
@@ -200,4 +256,5 @@
 
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/charconv_parse.cc b/absl/strings/internal/charconv_parse.cc
index f3c7232..8b11868 100644
--- a/absl/strings/internal/charconv_parse.cc
+++ b/absl/strings/internal/charconv_parse.cc
@@ -22,6 +22,7 @@
 #include "absl/strings/internal/memutil.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 // ParseFloat<10> will read the first 19 significant digits of the mantissa.
@@ -245,14 +246,20 @@
 // ConsumeDigits does not protect against overflow on *out; max_digits must
 // be chosen with respect to type T to avoid the possibility of overflow.
 template <int base, typename T>
-std::size_t ConsumeDigits(const char* begin, const char* end, int max_digits,
-                          T* out, bool* dropped_nonzero_digit) {
+int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,
+                  bool* dropped_nonzero_digit) {
   if (base == 10) {
     assert(max_digits <= std::numeric_limits<T>::digits10);
   } else if (base == 16) {
     assert(max_digits * 4 <= std::numeric_limits<T>::digits);
   }
   const char* const original_begin = begin;
+
+  // Skip leading zeros, but only if *out is zero.
+  // They don't cause an overflow so we don't have to count them for
+  // `max_digits`.
+  while (!*out && end != begin && *begin == '0') ++begin;
+
   T accumulator = *out;
   const char* significant_digits_end =
       (end - begin > max_digits) ? begin + max_digits : end;
@@ -275,7 +282,7 @@
     *dropped_nonzero_digit = true;
   }
   *out = accumulator;
-  return begin - original_begin;
+  return static_cast<int>(begin - original_begin);
 }
 
 // Returns true if `v` is one of the chars allowed inside parentheses following
@@ -295,7 +302,7 @@
   switch (*begin) {
     case 'i':
     case 'I': {
-      // An infinity std::string consists of the characters "inf" or "infinity",
+      // An infinity string consists of the characters "inf" or "infinity",
       // case insensitive.
       if (strings_internal::memcasecmp(begin + 1, "nf", 2) != 0) {
         return false;
@@ -319,7 +326,7 @@
       }
       out->type = strings_internal::FloatType::kNan;
       out->end = begin + 3;
-      // NaN is allowed to be followed by a parenthesized std::string, consisting of
+      // NaN is allowed to be followed by a parenthesized string, consisting of
       // only the characters [a-zA-Z0-9_].  Match that if it's present.
       begin += 3;
       if (begin < end && *begin == '(') {
@@ -365,7 +372,7 @@
 
   int exponent_adjustment = 0;
   bool mantissa_is_inexact = false;
-  std::size_t pre_decimal_digits = ConsumeDigits<base>(
+  int pre_decimal_digits = ConsumeDigits<base>(
       begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
   begin += pre_decimal_digits;
   int digits_left;
@@ -391,14 +398,14 @@
       while (begin < end && *begin == '0') {
         ++begin;
       }
-      std::size_t zeros_skipped = begin - begin_zeros;
+      int zeros_skipped = static_cast<int>(begin - begin_zeros);
       if (zeros_skipped >= DigitLimit<base>()) {
         // refuse to parse pathological inputs
         return result;
       }
       exponent_adjustment -= static_cast<int>(zeros_skipped);
     }
-    std::size_t post_decimal_digits = ConsumeDigits<base>(
+    int post_decimal_digits = ConsumeDigits<base>(
         begin, end, digits_left, &mantissa, &mantissa_is_inexact);
     begin += post_decimal_digits;
 
@@ -493,4 +500,5 @@
                                     chars_format format_flags);
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/charconv_parse.h b/absl/strings/internal/charconv_parse.h
index 44d06b2..505998b 100644
--- a/absl/strings/internal/charconv_parse.h
+++ b/absl/strings/internal/charconv_parse.h
@@ -17,9 +17,11 @@
 
 #include <cstdint>
 
+#include "absl/base/config.h"
 #include "absl/strings/charconv.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 // Enum indicating whether a parsed float is a number or special value.
@@ -92,5 +94,6 @@
                                            absl::chars_format format_flags);
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 #endif  // ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_
diff --git a/absl/strings/internal/charconv_parse_test.cc b/absl/strings/internal/charconv_parse_test.cc
index 9511c98..bc2d111 100644
--- a/absl/strings/internal/charconv_parse_test.cc
+++ b/absl/strings/internal/charconv_parse_test.cc
@@ -63,7 +63,7 @@
   }
   const std::string::size_type expected_characters_matched = s.find('$');
   ABSL_RAW_CHECK(expected_characters_matched != std::string::npos,
-                 "Input std::string must contain $");
+                 "Input string must contain $");
   s.replace(expected_characters_matched, 1, "");
 
   ParsedFloat parsed =
diff --git a/absl/strings/internal/cord_internal.cc b/absl/strings/internal/cord_internal.cc
new file mode 100644
index 0000000..59f2e4d
--- /dev/null
+++ b/absl/strings/internal/cord_internal.cc
@@ -0,0 +1,79 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "absl/strings/internal/cord_internal.h"
+
+#include <atomic>
+#include <cassert>
+#include <memory>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/internal/cord_rep_flat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+ABSL_CONST_INIT std::atomic<bool> cord_ring_buffer_enabled(
+    kCordEnableRingBufferDefault);
+ABSL_CONST_INIT std::atomic<bool> shallow_subcords_enabled(
+    kCordShallowSubcordsDefault);
+
+void CordRep::Destroy(CordRep* rep) {
+  assert(rep != nullptr);
+
+  absl::InlinedVector<CordRep*, Constants::kInlinedVectorSize> pending;
+  while (true) {
+    assert(!rep->refcount.IsImmortal());
+    if (rep->tag == CONCAT) {
+      CordRepConcat* rep_concat = rep->concat();
+      CordRep* right = rep_concat->right;
+      if (!right->refcount.Decrement()) {
+        pending.push_back(right);
+      }
+      CordRep* left = rep_concat->left;
+      delete rep_concat;
+      rep = nullptr;
+      if (!left->refcount.Decrement()) {
+        rep = left;
+        continue;
+      }
+    } else if (rep->tag == EXTERNAL) {
+      CordRepExternal::Delete(rep);
+      rep = nullptr;
+    } else if (rep->tag == SUBSTRING) {
+      CordRepSubstring* rep_substring = rep->substring();
+      CordRep* child = rep_substring->child;
+      delete rep_substring;
+      rep = nullptr;
+      if (!child->refcount.Decrement()) {
+        rep = child;
+        continue;
+      }
+    } else {
+      CordRepFlat::Delete(rep);
+      rep = nullptr;
+    }
+
+    if (!pending.empty()) {
+      rep = pending.back();
+      pending.pop_back();
+    } else {
+      break;
+    }
+  }
+}
+
+}  // namespace cord_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h
new file mode 100644
index 0000000..57e7046
--- /dev/null
+++ b/absl/strings/internal/cord_internal.h
@@ -0,0 +1,408 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
+#define ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
+
+#include <atomic>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
+#include "absl/base/internal/invoke.h"
+#include "absl/base/optimization.h"
+#include "absl/container/internal/compressed_tuple.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+// Default feature enable states for cord ring buffers
+enum CordFeatureDefaults {
+  kCordEnableRingBufferDefault = false,
+  kCordShallowSubcordsDefault = false
+};
+
+extern std::atomic<bool> cord_ring_buffer_enabled;
+extern std::atomic<bool> shallow_subcords_enabled;
+
+inline void enable_cord_ring_buffer(bool enable) {
+  cord_ring_buffer_enabled.store(enable, std::memory_order_relaxed);
+}
+
+inline void enable_shallow_subcords(bool enable) {
+  shallow_subcords_enabled.store(enable, std::memory_order_relaxed);
+}
+
+enum Constants {
+  // The inlined size to use with absl::InlinedVector.
+  //
+  // Note: The InlinedVectors in this file (and in cord.h) do not need to use
+  // the same value for their inlined size. The fact that they do is historical.
+  // It may be desirable for each to use a different inlined size optimized for
+  // that InlinedVector's usage.
+  //
+  // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for
+  // the inlined vector size (47 exists for backward compatibility).
+  kInlinedVectorSize = 47,
+
+  // Prefer copying blocks of at most this size, otherwise reference count.
+  kMaxBytesToCopy = 511
+};
+
+// Wraps std::atomic for reference counting.
+class Refcount {
+ public:
+  constexpr Refcount() : count_{kRefIncrement} {}
+  struct Immortal {};
+  explicit constexpr Refcount(Immortal) : count_(kImmortalTag) {}
+
+  // Increments the reference count. Imposes no memory ordering.
+  inline void Increment() {
+    count_.fetch_add(kRefIncrement, std::memory_order_relaxed);
+  }
+
+  // Asserts that the current refcount is greater than 0. If the refcount is
+  // greater than 1, decrements the reference count.
+  //
+  // Returns false if there are no references outstanding; true otherwise.
+  // Inserts barriers to ensure that state written before this method returns
+  // false will be visible to a thread that just observed this method returning
+  // false.
+  inline bool Decrement() {
+    int32_t refcount = count_.load(std::memory_order_acquire);
+    assert(refcount > 0 || refcount & kImmortalTag);
+    return refcount != kRefIncrement &&
+           count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) !=
+               kRefIncrement;
+  }
+
+  // Same as Decrement but expect that refcount is greater than 1.
+  inline bool DecrementExpectHighRefcount() {
+    int32_t refcount =
+        count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel);
+    assert(refcount > 0 || refcount & kImmortalTag);
+    return refcount != kRefIncrement;
+  }
+
+  // Returns the current reference count using acquire semantics.
+  inline int32_t Get() const {
+    return count_.load(std::memory_order_acquire) >> kImmortalShift;
+  }
+
+  // Returns whether the atomic integer is 1.
+  // If the reference count is used in the conventional way, a
+  // reference count of 1 implies that the current thread owns the
+  // reference and no other thread shares it.
+  // This call performs the test for a reference count of one, and
+  // performs the memory barrier needed for the owning thread
+  // to act on the object, knowing that it has exclusive access to the
+  // object.
+  inline bool IsOne() {
+    return count_.load(std::memory_order_acquire) == kRefIncrement;
+  }
+
+  bool IsImmortal() const {
+    return (count_.load(std::memory_order_relaxed) & kImmortalTag) != 0;
+  }
+
+ private:
+  // We reserve the bottom bit to tag a reference count as immortal.
+  // By making it `1` we ensure that we never reach `0` when adding/subtracting
+  // `2`, thus it never looks as if it should be destroyed.
+  // These are used for the StringConstant constructor where we do not increase
+  // the refcount at construction time (due to constinit requirements) but we
+  // will still decrease it at destruction time to avoid branching on Unref.
+  enum {
+    kImmortalShift = 1,
+    kRefIncrement = 1 << kImmortalShift,
+    kImmortalTag = kRefIncrement - 1
+  };
+
+  std::atomic<int32_t> count_;
+};
+
+// The overhead of a vtable is too much for Cord, so we roll our own subclasses
+// using only a single byte to differentiate classes from each other - the "tag"
+// byte.  Define the subclasses first so we can provide downcasting helper
+// functions in the base class.
+
+struct CordRepConcat;
+struct CordRepExternal;
+struct CordRepFlat;
+struct CordRepSubstring;
+
+// Various representations that we allow
+enum CordRepKind {
+  CONCAT        = 0,
+  EXTERNAL      = 1,
+  SUBSTRING     = 2,
+  RING          = 3,
+
+  // We have different tags for different sized flat arrays,
+  // starting with FLAT, and limited to MAX_FLAT_TAG. The 224 value is based on
+  // the current 'size to tag' encoding of 8 / 32 bytes. If a new tag is needed
+  // in the future, then 'FLAT' and 'MAX_FLAT_TAG' should be adjusted as well
+  // as the Tag <---> Size logic so that FLAT stil represents the minimum flat
+  // allocation size. (32 bytes as of now).
+  FLAT = 4,
+  MAX_FLAT_TAG = 224,
+};
+
+struct CordRep {
+  CordRep() = default;
+  constexpr CordRep(Refcount::Immortal immortal, size_t l)
+      : length(l), refcount(immortal), tag(EXTERNAL), data{} {}
+
+  // The following three fields have to be less than 32 bytes since
+  // that is the smallest supported flat node size.
+  size_t length;
+  Refcount refcount;
+  // If tag < FLAT, it represents CordRepKind and indicates the type of node.
+  // Otherwise, the node type is CordRepFlat and the tag is the encoded size.
+  uint8_t tag;
+  char data[1];  // Starting point for flat array: MUST BE LAST FIELD of CordRep
+
+  inline CordRepConcat* concat();
+  inline const CordRepConcat* concat() const;
+  inline CordRepSubstring* substring();
+  inline const CordRepSubstring* substring() const;
+  inline CordRepExternal* external();
+  inline const CordRepExternal* external() const;
+  inline CordRepFlat* flat();
+  inline const CordRepFlat* flat() const;
+
+  // --------------------------------------------------------------------
+  // Memory management
+
+  // This internal routine is called from the cold path of Unref below. Keeping
+  // it in a separate routine allows good inlining of Unref into many profitable
+  // call sites. However, the call to this function can be highly disruptive to
+  // the register pressure in those callers. To minimize the cost to callers, we
+  // use a special LLVM calling convention that preserves most registers. This
+  // allows the call to this routine in cold paths to not disrupt the caller's
+  // register pressure. This calling convention is not available on all
+  // platforms; we intentionally allow LLVM to ignore the attribute rather than
+  // attempting to hardcode the list of supported platforms.
+#if defined(__clang__) && !defined(__i386__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wattributes"
+  __attribute__((preserve_most))
+#pragma clang diagnostic pop
+#endif
+  static void Destroy(CordRep* rep);
+
+  // Increments the reference count of `rep`.
+  // Requires `rep` to be a non-null pointer value.
+  static inline CordRep* Ref(CordRep* rep);
+
+  // Decrements the reference count of `rep`. Destroys rep if count reaches
+  // zero. Requires `rep` to be a non-null pointer value.
+  static inline void Unref(CordRep* rep);
+};
+
+struct CordRepConcat : public CordRep {
+  CordRep* left;
+  CordRep* right;
+
+  uint8_t depth() const { return static_cast<uint8_t>(data[0]); }
+  void set_depth(uint8_t depth) { data[0] = static_cast<char>(depth); }
+};
+
+struct CordRepSubstring : public CordRep {
+  size_t start;  // Starting offset of substring in child
+  CordRep* child;
+};
+
+// Type for function pointer that will invoke the releaser function and also
+// delete the `CordRepExternalImpl` corresponding to the passed in
+// `CordRepExternal`.
+using ExternalReleaserInvoker = void (*)(CordRepExternal*);
+
+// External CordReps are allocated together with a type erased releaser. The
+// releaser is stored in the memory directly following the CordRepExternal.
+struct CordRepExternal : public CordRep {
+  CordRepExternal() = default;
+  explicit constexpr CordRepExternal(absl::string_view str)
+      : CordRep(Refcount::Immortal{}, str.size()),
+        base(str.data()),
+        releaser_invoker(nullptr) {}
+
+  const char* base;
+  // Pointer to function that knows how to call and destroy the releaser.
+  ExternalReleaserInvoker releaser_invoker;
+
+  // Deletes (releases) the external rep.
+  // Requires rep != nullptr and rep->tag == EXTERNAL
+  static void Delete(CordRep* rep);
+};
+
+struct Rank1 {};
+struct Rank0 : Rank1 {};
+
+template <typename Releaser, typename = ::absl::base_internal::invoke_result_t<
+                                 Releaser, absl::string_view>>
+void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view data) {
+  ::absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
+}
+
+template <typename Releaser,
+          typename = ::absl::base_internal::invoke_result_t<Releaser>>
+void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view) {
+  ::absl::base_internal::invoke(std::forward<Releaser>(releaser));
+}
+
+// We use CompressedTuple so that we can benefit from EBCO.
+template <typename Releaser>
+struct CordRepExternalImpl
+    : public CordRepExternal,
+      public ::absl::container_internal::CompressedTuple<Releaser> {
+  // The extra int arg is so that we can avoid interfering with copy/move
+  // constructors while still benefitting from perfect forwarding.
+  template <typename T>
+  CordRepExternalImpl(T&& releaser, int)
+      : CordRepExternalImpl::CompressedTuple(std::forward<T>(releaser)) {
+    this->releaser_invoker = &Release;
+  }
+
+  ~CordRepExternalImpl() {
+    InvokeReleaser(Rank0{}, std::move(this->template get<0>()),
+                   absl::string_view(base, length));
+  }
+
+  static void Release(CordRepExternal* rep) {
+    delete static_cast<CordRepExternalImpl*>(rep);
+  }
+};
+
+inline void CordRepExternal::Delete(CordRep* rep) {
+  assert(rep != nullptr && rep->tag == EXTERNAL);
+  auto* rep_external = static_cast<CordRepExternal*>(rep);
+  assert(rep_external->releaser_invoker != nullptr);
+  rep_external->releaser_invoker(rep_external);
+}
+
+template <typename Str>
+struct ConstInitExternalStorage {
+  ABSL_CONST_INIT static CordRepExternal value;
+};
+
+template <typename Str>
+CordRepExternal ConstInitExternalStorage<Str>::value(Str::value);
+
+enum {
+  kMaxInline = 15,
+  // Tag byte & kMaxInline means we are storing a pointer.
+  kTreeFlag = 1 << 4,
+  // Tag byte & kProfiledFlag means we are profiling the Cord.
+  kProfiledFlag = 1 << 5
+};
+
+// If the data has length <= kMaxInline, we store it in `as_chars`, and
+// store the size in `tagged_size`.
+// Else we store it in a tree and store a pointer to that tree in
+// `as_tree.rep` and store a tag in `tagged_size`.
+struct AsTree {
+  absl::cord_internal::CordRep* rep;
+  char padding[kMaxInline + 1 - sizeof(absl::cord_internal::CordRep*) - 1];
+  char tagged_size;
+};
+
+constexpr char GetOrNull(absl::string_view data, size_t pos) {
+  return pos < data.size() ? data[pos] : '\0';
+}
+
+union InlineData {
+  constexpr InlineData() : as_chars{} {}
+  explicit constexpr InlineData(AsTree tree) : as_tree(tree) {}
+  explicit constexpr InlineData(absl::string_view chars)
+      : as_chars{GetOrNull(chars, 0),  GetOrNull(chars, 1),
+                 GetOrNull(chars, 2),  GetOrNull(chars, 3),
+                 GetOrNull(chars, 4),  GetOrNull(chars, 5),
+                 GetOrNull(chars, 6),  GetOrNull(chars, 7),
+                 GetOrNull(chars, 8),  GetOrNull(chars, 9),
+                 GetOrNull(chars, 10), GetOrNull(chars, 11),
+                 GetOrNull(chars, 12), GetOrNull(chars, 13),
+                 GetOrNull(chars, 14), static_cast<char>(chars.size())} {}
+
+  AsTree as_tree;
+  char as_chars[kMaxInline + 1];
+};
+static_assert(sizeof(InlineData) == kMaxInline + 1, "");
+static_assert(sizeof(AsTree) == sizeof(InlineData), "");
+static_assert(offsetof(AsTree, tagged_size) == kMaxInline, "");
+
+inline CordRepConcat* CordRep::concat() {
+  assert(tag == CONCAT);
+  return static_cast<CordRepConcat*>(this);
+}
+
+inline const CordRepConcat* CordRep::concat() const {
+  assert(tag == CONCAT);
+  return static_cast<const CordRepConcat*>(this);
+}
+
+inline CordRepSubstring* CordRep::substring() {
+  assert(tag == SUBSTRING);
+  return static_cast<CordRepSubstring*>(this);
+}
+
+inline const CordRepSubstring* CordRep::substring() const {
+  assert(tag == SUBSTRING);
+  return static_cast<const CordRepSubstring*>(this);
+}
+
+inline CordRepExternal* CordRep::external() {
+  assert(tag == EXTERNAL);
+  return static_cast<CordRepExternal*>(this);
+}
+
+inline const CordRepExternal* CordRep::external() const {
+  assert(tag == EXTERNAL);
+  return static_cast<const CordRepExternal*>(this);
+}
+
+inline CordRepFlat* CordRep::flat() {
+  assert(tag >= FLAT && tag <= MAX_FLAT_TAG);
+  return reinterpret_cast<CordRepFlat*>(this);
+}
+
+inline const CordRepFlat* CordRep::flat() const {
+  assert(tag >= FLAT && tag <= MAX_FLAT_TAG);
+  return reinterpret_cast<const CordRepFlat*>(this);
+}
+
+inline CordRep* CordRep::Ref(CordRep* rep) {
+  assert(rep != nullptr);
+  rep->refcount.Increment();
+  return rep;
+}
+
+inline void CordRep::Unref(CordRep* rep) {
+  assert(rep != nullptr);
+  // Expect refcount to be 0. Avoiding the cost of an atomic decrement should
+  // typically outweigh the cost of an extra branch checking for ref == 1.
+  if (ABSL_PREDICT_FALSE(!rep->refcount.DecrementExpectHighRefcount())) {
+    Destroy(rep);
+  }
+}
+
+}  // namespace cord_internal
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+#endif  // ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
diff --git a/absl/strings/internal/cord_rep_flat.h b/absl/strings/internal/cord_rep_flat.h
new file mode 100644
index 0000000..80391a5
--- /dev/null
+++ b/absl/strings/internal/cord_rep_flat.h
@@ -0,0 +1,129 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
+#define ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+
+#include "absl/strings/internal/cord_internal.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+// Note: all constants below are never ODR used and internal to cord, we define
+// these as static constexpr to avoid 'in struct' definition and usage clutter.
+
+// Largest and smallest flat node lengths we are willing to allocate
+// Flat allocation size is stored in tag, which currently can encode sizes up
+// to 4K, encoded as multiple of either 8 or 32 bytes.
+// If we allow for larger sizes, we need to change this to 8/64, 16/128, etc.
+// kMinFlatSize is bounded by tag needing to be at least FLAT * 8 bytes, and
+// ideally a 'nice' size aligning with allocation and cacheline sizes like 32.
+// kMaxFlatSize is bounded by the size resulting in a computed tag no greater
+// than MAX_FLAT_TAG. MAX_FLAT_TAG provides for additional 'high' tag values.
+static constexpr size_t kFlatOverhead = offsetof(CordRep, data);
+static constexpr size_t kMinFlatSize = 32;
+static constexpr size_t kMaxFlatSize = 4096;
+static constexpr size_t kMaxFlatLength = kMaxFlatSize - kFlatOverhead;
+static constexpr size_t kMinFlatLength = kMinFlatSize - kFlatOverhead;
+
+constexpr size_t AllocatedSizeToTagUnchecked(size_t size) {
+  return (size <= 1024) ? size / 8 : 128 + size / 32 - 1024 / 32;
+}
+
+static_assert(kMinFlatSize / 8 >= FLAT, "");
+static_assert(AllocatedSizeToTagUnchecked(kMaxFlatSize) <= MAX_FLAT_TAG, "");
+
+// Helper functions for rounded div, and rounding to exact sizes.
+constexpr size_t DivUp(size_t n, size_t m) { return (n + m - 1) / m; }
+constexpr size_t RoundUp(size_t n, size_t m) { return DivUp(n, m) * m; }
+
+// Returns the size to the nearest equal or larger value that can be
+// expressed exactly as a tag value.
+inline size_t RoundUpForTag(size_t size) {
+  return RoundUp(size, (size <= 1024) ? 8 : 32);
+}
+
+// Converts the allocated size to a tag, rounding down if the size
+// does not exactly match a 'tag expressible' size value. The result is
+// undefined if the size exceeds the maximum size that can be encoded in
+// a tag, i.e., if size is larger than TagToAllocatedSize(<max tag>).
+inline uint8_t AllocatedSizeToTag(size_t size) {
+  const size_t tag = AllocatedSizeToTagUnchecked(size);
+  assert(tag <= MAX_FLAT_TAG);
+  return tag;
+}
+
+// Converts the provided tag to the corresponding allocated size
+constexpr size_t TagToAllocatedSize(uint8_t tag) {
+  return (tag <= 128) ? (tag * 8) : (1024 + (tag - 128) * 32);
+}
+
+// Converts the provided tag to the corresponding available data length
+constexpr size_t TagToLength(uint8_t tag) {
+  return TagToAllocatedSize(tag) - kFlatOverhead;
+}
+
+// Enforce that kMaxFlatSize maps to a well-known exact tag value.
+static_assert(TagToAllocatedSize(224) == kMaxFlatSize, "Bad tag logic");
+
+struct CordRepFlat : public CordRep {
+  // Creates a new flat node.
+  static CordRepFlat* New(size_t len) {
+    if (len <= kMinFlatLength) {
+      len = kMinFlatLength;
+    } else if (len > kMaxFlatLength) {
+      len = kMaxFlatLength;
+    }
+
+    // Round size up so it matches a size we can exactly express in a tag.
+    const size_t size = RoundUpForTag(len + kFlatOverhead);
+    void* const raw_rep = ::operator new(size);
+    CordRepFlat* rep = new (raw_rep) CordRepFlat();
+    rep->tag = AllocatedSizeToTag(size);
+    return rep;
+  }
+
+  // Deletes a CordRepFlat instance created previously through a call to New().
+  // Flat CordReps are allocated and constructed with raw ::operator new and
+  // placement new, and must be destructed and deallocated accordingly.
+  static void Delete(CordRep*rep) {
+    assert(rep->tag >= FLAT);
+#if defined(__cpp_sized_deallocation)
+    size_t size = TagToAllocatedSize(rep->tag);
+    rep->~CordRep();
+    ::operator delete(rep, size);
+#else
+    rep->~CordRep();
+    ::operator delete(rep);
+#endif
+  }
+
+  // Returns the maximum capacity (payload size) of this instance.
+  size_t Capacity() const { return TagToLength(tag); }
+
+  // Returns the allocated size (payload + overhead) of this instance.
+  size_t AllocatedSize() const { return TagToAllocatedSize(tag); }
+};
+
+}  // namespace cord_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
diff --git a/absl/strings/internal/escaping.cc b/absl/strings/internal/escaping.cc
new file mode 100644
index 0000000..c527128
--- /dev/null
+++ b/absl/strings/internal/escaping.cc
@@ -0,0 +1,180 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/internal/escaping.h"
+
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/raw_logging.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+const char kBase64Chars[] =
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) {
+  // Base64 encodes three bytes of input at a time. If the input is not
+  // divisible by three, we pad as appropriate.
+  //
+  // (from https://tools.ietf.org/html/rfc3548)
+  // Special processing is performed if fewer than 24 bits are available
+  // at the end of the data being encoded.  A full encoding quantum is
+  // always completed at the end of a quantity.  When fewer than 24 input
+  // bits are available in an input group, zero bits are added (on the
+  // right) to form an integral number of 6-bit groups.  Padding at the
+  // end of the data is performed using the '=' character.  Since all base
+  // 64 input is an integral number of octets, only the following cases
+  // can arise:
+
+  // Base64 encodes each three bytes of input into four bytes of output.
+  size_t len = (input_len / 3) * 4;
+
+  if (input_len % 3 == 0) {
+    // (from https://tools.ietf.org/html/rfc3548)
+    // (1) the final quantum of encoding input is an integral multiple of 24
+    // bits; here, the final unit of encoded output will be an integral
+    // multiple of 4 characters with no "=" padding,
+  } else if (input_len % 3 == 1) {
+    // (from https://tools.ietf.org/html/rfc3548)
+    // (2) the final quantum of encoding input is exactly 8 bits; here, the
+    // final unit of encoded output will be two characters followed by two
+    // "=" padding characters, or
+    len += 2;
+    if (do_padding) {
+      len += 2;
+    }
+  } else {  // (input_len % 3 == 2)
+    // (from https://tools.ietf.org/html/rfc3548)
+    // (3) the final quantum of encoding input is exactly 16 bits; here, the
+    // final unit of encoded output will be three characters followed by one
+    // "=" padding character.
+    len += 3;
+    if (do_padding) {
+      len += 1;
+    }
+  }
+
+  assert(len >= input_len);  // make sure we didn't overflow
+  return len;
+}
+
+size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
+                            size_t szdest, const char* base64,
+                            bool do_padding) {
+  static const char kPad64 = '=';
+
+  if (szsrc * 4 > szdest * 3) return 0;
+
+  char* cur_dest = dest;
+  const unsigned char* cur_src = src;
+
+  char* const limit_dest = dest + szdest;
+  const unsigned char* const limit_src = src + szsrc;
+
+  // Three bytes of data encodes to four characters of cyphertext.
+  // So we can pump through three-byte chunks atomically.
+  if (szsrc >= 3) {                    // "limit_src - 3" is UB if szsrc < 3.
+    while (cur_src < limit_src - 3) {  // While we have >= 32 bits.
+      uint32_t in = absl::big_endian::Load32(cur_src) >> 8;
+
+      cur_dest[0] = base64[in >> 18];
+      in &= 0x3FFFF;
+      cur_dest[1] = base64[in >> 12];
+      in &= 0xFFF;
+      cur_dest[2] = base64[in >> 6];
+      in &= 0x3F;
+      cur_dest[3] = base64[in];
+
+      cur_dest += 4;
+      cur_src += 3;
+    }
+  }
+  // To save time, we didn't update szdest or szsrc in the loop.  So do it now.
+  szdest = limit_dest - cur_dest;
+  szsrc = limit_src - cur_src;
+
+  /* now deal with the tail (<=3 bytes) */
+  switch (szsrc) {
+    case 0:
+      // Nothing left; nothing more to do.
+      break;
+    case 1: {
+      // One byte left: this encodes to two characters, and (optionally)
+      // two pad characters to round out the four-character cypherblock.
+      if (szdest < 2) return 0;
+      uint32_t in = cur_src[0];
+      cur_dest[0] = base64[in >> 2];
+      in &= 0x3;
+      cur_dest[1] = base64[in << 4];
+      cur_dest += 2;
+      szdest -= 2;
+      if (do_padding) {
+        if (szdest < 2) return 0;
+        cur_dest[0] = kPad64;
+        cur_dest[1] = kPad64;
+        cur_dest += 2;
+        szdest -= 2;
+      }
+      break;
+    }
+    case 2: {
+      // Two bytes left: this encodes to three characters, and (optionally)
+      // one pad character to round out the four-character cypherblock.
+      if (szdest < 3) return 0;
+      uint32_t in = absl::big_endian::Load16(cur_src);
+      cur_dest[0] = base64[in >> 10];
+      in &= 0x3FF;
+      cur_dest[1] = base64[in >> 4];
+      in &= 0x00F;
+      cur_dest[2] = base64[in << 2];
+      cur_dest += 3;
+      szdest -= 3;
+      if (do_padding) {
+        if (szdest < 1) return 0;
+        cur_dest[0] = kPad64;
+        cur_dest += 1;
+        szdest -= 1;
+      }
+      break;
+    }
+    case 3: {
+      // Three bytes left: same as in the big loop above.  We can't do this in
+      // the loop because the loop above always reads 4 bytes, and the fourth
+      // byte is past the end of the input.
+      if (szdest < 4) return 0;
+      uint32_t in = (cur_src[0] << 16) + absl::big_endian::Load16(cur_src + 1);
+      cur_dest[0] = base64[in >> 18];
+      in &= 0x3FFFF;
+      cur_dest[1] = base64[in >> 12];
+      in &= 0xFFF;
+      cur_dest[2] = base64[in >> 6];
+      in &= 0x3F;
+      cur_dest[3] = base64[in];
+      cur_dest += 4;
+      szdest -= 4;
+      break;
+    }
+    default:
+      // Should not be reached: blocks of 4 bytes are handled
+      // in the while loop before this switch statement.
+      ABSL_RAW_LOG(FATAL, "Logic problem? szsrc = %zu", szsrc);
+      break;
+  }
+  return (cur_dest - dest);
+}
+
+}  // namespace strings_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/absl/strings/internal/escaping.h b/absl/strings/internal/escaping.h
new file mode 100644
index 0000000..6a9ce60
--- /dev/null
+++ b/absl/strings/internal/escaping.h
@@ -0,0 +1,58 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_H_
+#define ABSL_STRINGS_INTERNAL_ESCAPING_H_
+
+#include <cassert>
+
+#include "absl/strings/internal/resize_uninitialized.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+ABSL_CONST_INIT extern const char kBase64Chars[];
+
+// Calculates how long a string will be when it is base64 encoded given its
+// length and whether or not the result should be padded.
+size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding);
+
+// Base64-encodes `src` using the alphabet provided in `base64` and writes the
+// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars
+// until its length is a multiple of 3. Returns the length of `dest`.
+size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
+                            size_t szdest, const char* base64, bool do_padding);
+
+// Base64-encodes `src` using the alphabet provided in `base64` and writes the
+// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars
+// until its length is a multiple of 3.
+template <typename String>
+void Base64EscapeInternal(const unsigned char* src, size_t szsrc, String* dest,
+                          bool do_padding, const char* base64_chars) {
+  const size_t calc_escaped_size =
+      CalculateBase64EscapedLenInternal(szsrc, do_padding);
+  STLStringResizeUninitialized(dest, calc_escaped_size);
+
+  const size_t escaped_len = Base64EscapeInternal(
+      src, szsrc, &(*dest)[0], dest->size(), base64_chars, do_padding);
+  assert(calc_escaped_size == escaped_len);
+  dest->erase(escaped_len);
+}
+
+}  // namespace strings_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_INTERNAL_ESCAPING_H_
diff --git a/absl/strings/internal/escaping_test_common.h b/absl/strings/internal/escaping_test_common.h
index bd80303..7b18017 100644
--- a/absl/strings/internal/escaping_test_common.h
+++ b/absl/strings/internal/escaping_test_common.h
@@ -22,6 +22,7 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 struct base64_testcase {
@@ -126,6 +127,7 @@
 }
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
diff --git a/absl/strings/internal/memutil.cc b/absl/strings/internal/memutil.cc
index 77aa63c..2519c68 100644
--- a/absl/strings/internal/memutil.cc
+++ b/absl/strings/internal/memutil.cc
@@ -17,6 +17,7 @@
 #include <cstdlib>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 int memcasecmp(const char* s1, const char* s2, size_t len) {
@@ -107,4 +108,5 @@
 }
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/memutil.h b/absl/strings/internal/memutil.h
index 7c071a8..9ad0535 100644
--- a/absl/strings/internal/memutil.h
+++ b/absl/strings/internal/memutil.h
@@ -69,6 +69,7 @@
 #include "absl/strings/ascii.h"  // for absl::ascii_tolower
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 inline char* memcat(char* dest, size_t destlen, const char* src,
@@ -141,6 +142,7 @@
                      size_t neelen);
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_MEMUTIL_H_
diff --git a/absl/strings/internal/numbers_test_common.h b/absl/strings/internal/numbers_test_common.h
index 2824720..eaa88a8 100644
--- a/absl/strings/internal/numbers_test_common.h
+++ b/absl/strings/internal/numbers_test_common.h
@@ -23,7 +23,10 @@
 #include <limits>
 #include <string>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 template <typename IntType>
@@ -42,8 +45,9 @@
   while (value != 0) {
     const IntType next_value = value / base;
     // Can't use std::abs here because of problems when IntType is unsigned.
-    int remainder = value > next_value * base ? value - next_value * base
-                                              : next_value * base - value;
+    int remainder =
+        static_cast<int>(value > next_value * base ? value - next_value * base
+                                                   : next_value * base - value);
     char c = remainder < 10 ? '0' + remainder : 'A' + remainder - 10;
     destination->insert(0, 1, c);
     value = next_value;
@@ -166,7 +170,7 @@
 
       {"0x1234", true, 16, 0x1234},
 
-      // Base-10 std::string version.
+      // Base-10 string version.
       {"1234", true, 0, 1234},
       {nullptr, false, 0, 0},
   }};
@@ -174,6 +178,7 @@
 }
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
diff --git a/absl/strings/internal/ostringstream.cc b/absl/strings/internal/ostringstream.cc
index d0f0f84..05324c7 100644
--- a/absl/strings/internal/ostringstream.cc
+++ b/absl/strings/internal/ostringstream.cc
@@ -15,6 +15,7 @@
 #include "absl/strings/internal/ostringstream.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 OStringStream::Buf::int_type OStringStream::overflow(int c) {
@@ -31,4 +32,5 @@
 }
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/ostringstream.h b/absl/strings/internal/ostringstream.h
index 2079201..d25d604 100644
--- a/absl/strings/internal/ostringstream.h
+++ b/absl/strings/internal/ostringstream.h
@@ -23,6 +23,7 @@
 #include "absl/base/port.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 // The same as std::ostringstream but appends to a user-specified std::string,
@@ -82,6 +83,7 @@
 };
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_
diff --git a/absl/strings/internal/pow10_helper.cc b/absl/strings/internal/pow10_helper.cc
index 03ed8d0..42e96c3 100644
--- a/absl/strings/internal/pow10_helper.cc
+++ b/absl/strings/internal/pow10_helper.cc
@@ -17,6 +17,7 @@
 #include <cmath>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 namespace {
@@ -117,4 +118,5 @@
 }
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/pow10_helper.h b/absl/strings/internal/pow10_helper.h
index 9d1aa71..c37c2c3 100644
--- a/absl/strings/internal/pow10_helper.h
+++ b/absl/strings/internal/pow10_helper.h
@@ -22,7 +22,10 @@
 
 #include <vector>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 // Computes the precise value of 10^exp. (I.e. the nearest representable
@@ -31,6 +34,7 @@
 double Pow10(int exp);
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
diff --git a/absl/strings/internal/pow10_helper_test.cc b/absl/strings/internal/pow10_helper_test.cc
index a4a68b5..a4ff76d 100644
--- a/absl/strings/internal/pow10_helper_test.cc
+++ b/absl/strings/internal/pow10_helper_test.cc
@@ -20,6 +20,7 @@
 #include "absl/strings/str_format.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 namespace {
@@ -117,4 +118,5 @@
 
 }  // namespace
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/resize_uninitialized.h b/absl/strings/internal/resize_uninitialized.h
index 469962b..e42628e 100644
--- a/absl/strings/internal/resize_uninitialized.h
+++ b/absl/strings/internal/resize_uninitialized.h
@@ -25,6 +25,7 @@
 #include "absl/meta/type_traits.h"  //  for void_t
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 // Is a subclass of true_type or false_type, depending on whether or not
@@ -35,8 +36,7 @@
   static void Resize(string_type* s, size_t new_size) { s->resize(new_size); }
 };
 
-// __resize_default_init is provided by libc++ >= 8.0 and by Google's internal
-// ::string implementation.
+// __resize_default_init is provided by libc++ >= 8.0
 template <typename string_type>
 struct ResizeUninitializedTraits<
     string_type, absl::void_t<decltype(std::declval<string_type&>()
@@ -67,6 +67,7 @@
 }
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
diff --git a/absl/strings/internal/resize_uninitialized_test.cc b/absl/strings/internal/resize_uninitialized_test.cc
index c5be0b1..0f8b3c2 100644
--- a/absl/strings/internal/resize_uninitialized_test.cc
+++ b/absl/strings/internal/resize_uninitialized_test.cc
@@ -20,13 +20,27 @@
 
 int resize_call_count = 0;
 
+// A mock string class whose only purpose is to track how many times its
+// resize() method has been called.
 struct resizable_string {
+  size_t size() const { return 0; }
+  char& operator[](size_t) {
+    static char c = '\0';
+    return c;
+  }
   void resize(size_t) { resize_call_count += 1; }
 };
 
 int resize_default_init_call_count = 0;
 
+// A mock string class whose only purpose is to track how many times its
+// resize() and __resize_default_init() methods have been called.
 struct resize_default_init_string {
+  size_t size() const { return 0; }
+  char& operator[](size_t) {
+    static char c = '\0';
+    return c;
+  }
   void resize(size_t) { resize_call_count += 1; }
   void __resize_default_init(size_t) { resize_default_init_call_count += 1; }
 };
diff --git a/absl/strings/internal/stl_type_traits.h b/absl/strings/internal/stl_type_traits.h
index 202ab37..6035ca4 100644
--- a/absl/strings/internal/stl_type_traits.h
+++ b/absl/strings/internal/stl_type_traits.h
@@ -40,6 +40,7 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 template <typename C, template <typename...> class T>
@@ -242,5 +243,6 @@
                         IsConvertibleToSTLContainer<C>> {};
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 #endif  // ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_
diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc
index b40be8f..e28a29b 100644
--- a/absl/strings/internal/str_format/arg.cc
+++ b/absl/strings/internal/str_format/arg.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 //
 // POSIX spec:
 //   http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
@@ -12,13 +26,13 @@
 
 #include "absl/base/port.h"
 #include "absl/strings/internal/str_format/float_conversion.h"
+#include "absl/strings/numbers.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 namespace {
 
-const char kDigit[2][32] = { "0123456789abcdef", "0123456789ABCDEF" };
-
 // Reduce *capacity by s.size(), clipped to a 0 minimum.
 void ReducePadding(string_view s, size_t *capacity) {
   *capacity = Excess(s.size(), *capacity);
@@ -32,6 +46,10 @@
 template <typename T>
 struct MakeUnsigned : std::make_unsigned<T> {};
 template <>
+struct MakeUnsigned<absl::int128> {
+  using type = absl::uint128;
+};
+template <>
 struct MakeUnsigned<absl::uint128> {
   using type = absl::uint128;
 };
@@ -39,128 +57,183 @@
 template <typename T>
 struct IsSigned : std::is_signed<T> {};
 template <>
+struct IsSigned<absl::int128> : std::true_type {};
+template <>
 struct IsSigned<absl::uint128> : std::false_type {};
 
-class ConvertedIntInfo {
+// Integral digit printer.
+// Call one of the PrintAs* routines after construction once.
+// Use with_neg_and_zero/without_neg_or_zero/is_negative to access the results.
+class IntDigits {
  public:
+  // Print the unsigned integer as octal.
+  // Supports unsigned integral types and uint128.
   template <typename T>
-  ConvertedIntInfo(T v, ConversionChar conv) {
-    using Unsigned = typename MakeUnsigned<T>::type;
-    auto u = static_cast<Unsigned>(v);
-    if (IsNeg(v)) {
-      is_neg_ = true;
-      u = Unsigned{} - u;
-    } else {
-      is_neg_ = false;
-    }
-    UnsignedToStringRight(u, conv);
+  void PrintAsOct(T v) {
+    static_assert(!IsSigned<T>::value, "");
+    char *p = storage_ + sizeof(storage_);
+    do {
+      *--p = static_cast<char>('0' + (static_cast<size_t>(v) & 7));
+      v >>= 3;
+    } while (v);
+    start_ = p;
+    size_ = storage_ + sizeof(storage_) - p;
   }
 
-  string_view digits() const {
-    return {end() - size_, static_cast<size_t>(size_)};
+  // Print the signed or unsigned integer as decimal.
+  // Supports all integral types.
+  template <typename T>
+  void PrintAsDec(T v) {
+    static_assert(std::is_integral<T>::value, "");
+    start_ = storage_;
+    size_ = numbers_internal::FastIntToBuffer(v, storage_) - storage_;
   }
-  bool is_neg() const { return is_neg_; }
+
+  void PrintAsDec(int128 v) {
+    auto u = static_cast<uint128>(v);
+    bool add_neg = false;
+    if (v < 0) {
+      add_neg = true;
+      u = uint128{} - u;
+    }
+    PrintAsDec(u, add_neg);
+  }
+
+  void PrintAsDec(uint128 v, bool add_neg = false) {
+    // This function can be sped up if needed. We can call FastIntToBuffer
+    // twice, or fix FastIntToBuffer to support uint128.
+    char *p = storage_ + sizeof(storage_);
+    do {
+      p -= 2;
+      numbers_internal::PutTwoDigits(static_cast<size_t>(v % 100), p);
+      v /= 100;
+    } while (v);
+    if (p[0] == '0') {
+      // We printed one too many hexits.
+      ++p;
+    }
+    if (add_neg) {
+      *--p = '-';
+    }
+    size_ = storage_ + sizeof(storage_) - p;
+    start_ = p;
+  }
+
+  // Print the unsigned integer as hex using lowercase.
+  // Supports unsigned integral types and uint128.
+  template <typename T>
+  void PrintAsHexLower(T v) {
+    static_assert(!IsSigned<T>::value, "");
+    char *p = storage_ + sizeof(storage_);
+
+    do {
+      p -= 2;
+      constexpr const char* table = numbers_internal::kHexTable;
+      std::memcpy(p, table + 2 * (static_cast<size_t>(v) & 0xFF), 2);
+      if (sizeof(T) == 1) break;
+      v >>= 8;
+    } while (v);
+    if (p[0] == '0') {
+      // We printed one too many digits.
+      ++p;
+    }
+    start_ = p;
+    size_ = storage_ + sizeof(storage_) - p;
+  }
+
+  // Print the unsigned integer as hex using uppercase.
+  // Supports unsigned integral types and uint128.
+  template <typename T>
+  void PrintAsHexUpper(T v) {
+    static_assert(!IsSigned<T>::value, "");
+    char *p = storage_ + sizeof(storage_);
+
+    // kHexTable is only lowercase, so do it manually for uppercase.
+    do {
+      *--p = "0123456789ABCDEF"[static_cast<size_t>(v) & 15];
+      v >>= 4;
+    } while (v);
+    start_ = p;
+    size_ = storage_ + sizeof(storage_) - p;
+  }
+
+  // The printed value including the '-' sign if available.
+  // For inputs of value `0`, this will return "0"
+  string_view with_neg_and_zero() const { return {start_, size_}; }
+
+  // The printed value not including the '-' sign.
+  // For inputs of value `0`, this will return "".
+  string_view without_neg_or_zero() const {
+    static_assert('-' < '0', "The check below verifies both.");
+    size_t advance = start_[0] <= '0' ? 1 : 0;
+    return {start_ + advance, size_ - advance};
+  }
+
+  bool is_negative() const { return start_[0] == '-'; }
 
  private:
-  template <typename T, bool IsSigned>
-  struct IsNegImpl {
-    static bool Eval(T v) { return v < 0; }
-  };
-  template <typename T>
-  struct IsNegImpl<T, false> {
-    static bool Eval(T) {
-      return false;
-    }
-  };
-
-  template <typename T>
-  bool IsNeg(T v) {
-    return IsNegImpl<T, IsSigned<T>::value>::Eval(v);
-  }
-
-  template <typename T>
-  void UnsignedToStringRight(T u, ConversionChar conv) {
-    char *p = end();
-    switch (conv.radix()) {
-      default:
-      case 10:
-        for (; u; u /= 10)
-          *--p = static_cast<char>('0' + static_cast<size_t>(u % 10));
-        break;
-      case 8:
-        for (; u; u /= 8)
-          *--p = static_cast<char>('0' + static_cast<size_t>(u % 8));
-        break;
-      case 16: {
-        const char *digits = kDigit[conv.upper() ? 1 : 0];
-        for (; u; u /= 16) *--p = digits[static_cast<size_t>(u % 16)];
-        break;
-      }
-    }
-    size_ = static_cast<int>(end() - p);
-  }
-
-  const char *end() const { return storage_ + sizeof(storage_); }
-  char *end() { return storage_ + sizeof(storage_); }
-
-  bool is_neg_;
-  int size_;
-  // Max size: 128 bit value as octal -> 43 digits
-  char storage_[128 / 3 + 1];
+  const char *start_;
+  size_t size_;
+  // Max size: 128 bit value as octal -> 43 digits, plus sign char
+  char storage_[128 / 3 + 1 + 1];
 };
 
 // Note: 'o' conversions do not have a base indicator, it's just that
 // the '#' flag is specified to modify the precision for 'o' conversions.
-string_view BaseIndicator(const ConvertedIntInfo &info,
-                          const ConversionSpec conv) {
-  bool alt = conv.flags().alt;
-  int radix = conv.conv().radix();
-  if (conv.conv().id() == ConversionChar::p)
-    alt = true;  // always show 0x for %p.
+string_view BaseIndicator(const IntDigits &as_digits,
+                          const FormatConversionSpecImpl conv) {
+  // always show 0x for %p.
+  bool alt = conv.has_alt_flag() ||
+             conv.conversion_char() == FormatConversionCharInternal::p;
+  bool hex = (conv.conversion_char() == FormatConversionCharInternal::x ||
+              conv.conversion_char() == FormatConversionCharInternal::X ||
+              conv.conversion_char() == FormatConversionCharInternal::p);
   // From the POSIX description of '#' flag:
   //   "For x or X conversion specifiers, a non-zero result shall have
   //   0x (or 0X) prefixed to it."
-  if (alt && radix == 16 && !info.digits().empty()) {
-    if (conv.conv().upper()) return "0X";
-    return "0x";
+  if (alt && hex && !as_digits.without_neg_or_zero().empty()) {
+    return conv.conversion_char() == FormatConversionCharInternal::X ? "0X"
+                                                                     : "0x";
   }
   return {};
 }
 
-string_view SignColumn(bool neg, const ConversionSpec conv) {
-  if (conv.conv().is_signed()) {
+string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) {
+  if (conv.conversion_char() == FormatConversionCharInternal::d ||
+      conv.conversion_char() == FormatConversionCharInternal::i) {
     if (neg) return "-";
-    if (conv.flags().show_pos) return "+";
-    if (conv.flags().sign_col) return " ";
+    if (conv.has_show_pos_flag()) return "+";
+    if (conv.has_sign_col_flag()) return " ";
   }
   return {};
 }
 
-bool ConvertCharImpl(unsigned char v, const ConversionSpec conv,
+bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv,
                      FormatSinkImpl *sink) {
   size_t fill = 0;
   if (conv.width() >= 0) fill = conv.width();
   ReducePadding(1, &fill);
-  if (!conv.flags().left) sink->Append(fill, ' ');
+  if (!conv.has_left_flag()) sink->Append(fill, ' ');
   sink->Append(1, v);
-  if (conv.flags().left) sink->Append(fill, ' ');
+  if (conv.has_left_flag()) sink->Append(fill, ' ');
   return true;
 }
 
-bool ConvertIntImplInner(const ConvertedIntInfo &info,
-                         const ConversionSpec conv, FormatSinkImpl *sink) {
+bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
+                             const FormatConversionSpecImpl conv,
+                             FormatSinkImpl *sink) {
   // Print as a sequence of Substrings:
   //   [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]
   size_t fill = 0;
   if (conv.width() >= 0) fill = conv.width();
 
-  string_view formatted = info.digits();
+  string_view formatted = as_digits.without_neg_or_zero();
   ReducePadding(formatted, &fill);
 
-  string_view sign = SignColumn(info.is_neg(), conv);
+  string_view sign = SignColumn(as_digits.is_negative(), conv);
   ReducePadding(sign, &fill);
 
-  string_view base_indicator = BaseIndicator(info, conv);
+  string_view base_indicator = BaseIndicator(as_digits, conv);
   ReducePadding(base_indicator, &fill);
 
   int precision = conv.precision();
@@ -168,7 +241,8 @@
   if (!precision_specified)
     precision = 1;
 
-  if (conv.flags().alt && conv.conv().id() == ConversionChar::o) {
+  if (conv.has_alt_flag() &&
+      conv.conversion_char() == FormatConversionCharInternal::o) {
     // From POSIX description of the '#' (alt) flag:
     //   "For o conversion, it increases the precision (if necessary) to
     //   force the first digit of the result to be zero."
@@ -181,13 +255,13 @@
   size_t num_zeroes = Excess(formatted.size(), precision);
   ReducePadding(num_zeroes, &fill);
 
-  size_t num_left_spaces = !conv.flags().left ? fill : 0;
-  size_t num_right_spaces = conv.flags().left ? fill : 0;
+  size_t num_left_spaces = !conv.has_left_flag() ? fill : 0;
+  size_t num_right_spaces = conv.has_left_flag() ? fill : 0;
 
   // From POSIX description of the '0' (zero) flag:
   //   "For d, i, o, u, x, and X conversion specifiers, if a precision
   //   is specified, the '0' flag is ignored."
-  if (!precision_specified && conv.flags().zero) {
+  if (!precision_specified && conv.has_zero_flag()) {
     num_zeroes += num_left_spaces;
     num_left_spaces = 0;
   }
@@ -202,72 +276,97 @@
 }
 
 template <typename T>
-bool ConvertIntImplInner(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
-  ConvertedIntInfo info(v, conv.conv());
-  if (conv.flags().basic && conv.conv().id() != ConversionChar::p) {
-    if (info.is_neg()) sink->Append(1, '-');
-    if (info.digits().empty()) {
-      sink->Append(1, '0');
-    } else {
-      sink->Append(info.digits());
-    }
+bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
+                   FormatSinkImpl *sink) {
+  using U = typename MakeUnsigned<T>::type;
+  IntDigits as_digits;
+
+  // This odd casting is due to a bug in -Wswitch behavior in gcc49 which causes
+  // it to complain about a switch/case type mismatch, even though both are
+  // FormatConverionChar.  Likely this is because at this point
+  // FormatConversionChar is declared, but not defined.
+  switch (static_cast<uint8_t>(conv.conversion_char())) {
+    case static_cast<uint8_t>(FormatConversionCharInternal::c):
+      return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
+
+    case static_cast<uint8_t>(FormatConversionCharInternal::o):
+      as_digits.PrintAsOct(static_cast<U>(v));
+      break;
+
+    case static_cast<uint8_t>(FormatConversionCharInternal::x):
+      as_digits.PrintAsHexLower(static_cast<U>(v));
+      break;
+    case static_cast<uint8_t>(FormatConversionCharInternal::X):
+      as_digits.PrintAsHexUpper(static_cast<U>(v));
+      break;
+
+    case static_cast<uint8_t>(FormatConversionCharInternal::u):
+      as_digits.PrintAsDec(static_cast<U>(v));
+      break;
+
+    case static_cast<uint8_t>(FormatConversionCharInternal::d):
+    case static_cast<uint8_t>(FormatConversionCharInternal::i):
+      as_digits.PrintAsDec(v);
+      break;
+
+    case static_cast<uint8_t>(FormatConversionCharInternal::a):
+    case static_cast<uint8_t>(FormatConversionCharInternal::e):
+    case static_cast<uint8_t>(FormatConversionCharInternal::f):
+    case static_cast<uint8_t>(FormatConversionCharInternal::g):
+    case static_cast<uint8_t>(FormatConversionCharInternal::A):
+    case static_cast<uint8_t>(FormatConversionCharInternal::E):
+    case static_cast<uint8_t>(FormatConversionCharInternal::F):
+    case static_cast<uint8_t>(FormatConversionCharInternal::G):
+      return ConvertFloatImpl(static_cast<double>(v), conv, sink);
+
+    default:
+       ABSL_INTERNAL_ASSUME(false);
+  }
+
+  if (conv.is_basic()) {
+    sink->Append(as_digits.with_neg_and_zero());
     return true;
   }
-  return ConvertIntImplInner(info, conv, sink);
+  return ConvertIntImplInnerSlow(as_digits, conv, sink);
 }
 
 template <typename T>
-bool ConvertIntArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
-  if (conv.conv().is_float()) {
-    return FormatConvertImpl(static_cast<double>(v), conv, sink).value;
-  }
-  if (conv.conv().id() == ConversionChar::c)
-    return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
-  if (!conv.conv().is_integral())
-    return false;
-  if (!conv.conv().is_signed() && IsSigned<T>::value) {
-    using U = typename MakeUnsigned<T>::type;
-    return FormatConvertImpl(static_cast<U>(v), conv, sink).value;
-  }
-  return ConvertIntImplInner(v, conv, sink);
+bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv,
+                     FormatSinkImpl *sink) {
+  return FormatConversionCharIsFloat(conv.conversion_char()) &&
+         ConvertFloatImpl(v, conv, sink);
 }
 
-template <typename T>
-bool ConvertFloatArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
-  return conv.conv().is_float() && ConvertFloatImpl(v, conv, sink);
-}
-
-inline bool ConvertStringArg(string_view v, const ConversionSpec conv,
+inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv,
                              FormatSinkImpl *sink) {
-  if (conv.conv().id() != ConversionChar::s)
-    return false;
-  if (conv.flags().basic) {
+  if (conv.is_basic()) {
     sink->Append(v);
     return true;
   }
   return sink->PutPaddedString(v, conv.width(), conv.precision(),
-                               conv.flags().left);
+                               conv.has_left_flag());
 }
 
 }  // namespace
 
 // ==================== Strings ====================
-ConvertResult<Conv::s> FormatConvertImpl(const std::string &v,
-                                         const ConversionSpec conv,
-                                         FormatSinkImpl *sink) {
+StringConvertResult FormatConvertImpl(const std::string &v,
+                                      const FormatConversionSpecImpl conv,
+                                      FormatSinkImpl *sink) {
   return {ConvertStringArg(v, conv, sink)};
 }
 
-ConvertResult<Conv::s> FormatConvertImpl(string_view v,
-                                         const ConversionSpec conv,
-                                         FormatSinkImpl *sink) {
+StringConvertResult FormatConvertImpl(string_view v,
+                                      const FormatConversionSpecImpl conv,
+                                      FormatSinkImpl *sink) {
   return {ConvertStringArg(v, conv, sink)};
 }
 
-ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char *v,
-                                                   const ConversionSpec conv,
-                                                   FormatSinkImpl *sink) {
-  if (conv.conv().id() == ConversionChar::p)
+ArgConvertResult<FormatConversionCharSetUnion(
+    FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
+FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,
+                  FormatSinkImpl *sink) {
+  if (conv.conversion_char() == FormatConversionCharInternal::p)
     return {FormatConvertImpl(VoidPtr(v), conv, sink).value};
   size_t len;
   if (v == nullptr) {
@@ -275,96 +374,106 @@
   } else if (conv.precision() < 0) {
     len = std::strlen(v);
   } else {
-    // If precision is set, we look for the null terminator on the valid range.
+    // If precision is set, we look for the NUL-terminator on the valid range.
     len = std::find(v, v + conv.precision(), '\0') - v;
   }
   return {ConvertStringArg(string_view(v, len), conv, sink)};
 }
 
 // ==================== Raw pointers ====================
-ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, const ConversionSpec conv,
-                                         FormatSinkImpl *sink) {
-  if (conv.conv().id() != ConversionChar::p)
-    return {false};
+ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
+    VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) {
   if (!v.value) {
     sink->Append("(nil)");
     return {true};
   }
-  return {ConvertIntImplInner(v.value, conv, sink)};
+  IntDigits as_digits;
+  as_digits.PrintAsHexLower(v.value);
+  return {ConvertIntImplInnerSlow(as_digits, conv, sink)};
 }
 
 // ==================== Floats ====================
-FloatingConvertResult FormatConvertImpl(float v, const ConversionSpec conv,
+FloatingConvertResult FormatConvertImpl(float v,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertFloatArg(v, conv, sink)};
 }
-FloatingConvertResult FormatConvertImpl(double v, const ConversionSpec conv,
+FloatingConvertResult FormatConvertImpl(double v,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertFloatArg(v, conv, sink)};
 }
 FloatingConvertResult FormatConvertImpl(long double v,
-                                        const ConversionSpec conv,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertFloatArg(v, conv, sink)};
 }
 
 // ==================== Chars ====================
-IntegralConvertResult FormatConvertImpl(char v, const ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(char v,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
 IntegralConvertResult FormatConvertImpl(signed char v,
-                                        const ConversionSpec conv,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
 IntegralConvertResult FormatConvertImpl(unsigned char v,
-                                        const ConversionSpec conv,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
 
 // ==================== Ints ====================
 IntegralConvertResult FormatConvertImpl(short v,  // NOLINT
-                                        const ConversionSpec conv,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
 IntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT
-                                        const ConversionSpec conv,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
-IntegralConvertResult FormatConvertImpl(int v, const ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(int v,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
-IntegralConvertResult FormatConvertImpl(unsigned v, const ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(unsigned v,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
 IntegralConvertResult FormatConvertImpl(long v,  // NOLINT
-                                        const ConversionSpec conv,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
 IntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT
-                                        const ConversionSpec conv,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
 IntegralConvertResult FormatConvertImpl(long long v,  // NOLINT
-                                        const ConversionSpec conv,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
 IntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT
-                                        const ConversionSpec conv,
+                                        const FormatConversionSpecImpl conv,
+                                        FormatSinkImpl *sink) {
+  return {ConvertIntArg(v, conv, sink)};
+}
+IntegralConvertResult FormatConvertImpl(absl::int128 v,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
 IntegralConvertResult FormatConvertImpl(absl::uint128 v,
-                                        const ConversionSpec conv,
+                                        const FormatConversionSpecImpl conv,
                                         FormatSinkImpl *sink) {
   return {ConvertIntArg(v, conv, sink)};
 }
@@ -372,6 +481,8 @@
 ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_();
 
 
+
 }  // namespace str_format_internal
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h
index 5cb3a14..7040c86 100644
--- a/absl/strings/internal/str_format/arg.h
+++ b/absl/strings/internal/str_format/arg.h
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
 
@@ -18,24 +32,44 @@
 #include "absl/strings/internal/str_format/extension.h"
 #include "absl/strings/string_view.h"
 
-class Cord;
-class CordReader;
-
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
+class Cord;
 class FormatCountCapture;
 class FormatSink;
 
+template <absl::FormatConversionCharSet C>
+struct FormatConvertResult;
+class FormatConversionSpec;
+
 namespace str_format_internal {
 
 template <typename T, typename = void>
 struct HasUserDefinedConvert : std::false_type {};
 
 template <typename T>
-struct HasUserDefinedConvert<
-    T, void_t<decltype(AbslFormatConvert(
-           std::declval<const T&>(), std::declval<ConversionSpec>(),
-           std::declval<FormatSink*>()))>> : std::true_type {};
+struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
+                                    std::declval<const T&>(),
+                                    std::declval<const FormatConversionSpec&>(),
+                                    std::declval<FormatSink*>()))>>
+    : std::true_type {};
+
+void AbslFormatConvert();  // Stops the lexical name lookup
+template <typename T>
+auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
+                       FormatSinkImpl* sink)
+    -> decltype(AbslFormatConvert(v,
+                                  std::declval<const FormatConversionSpec&>(),
+                                  std::declval<FormatSink*>())) {
+  using FormatConversionSpecT =
+      absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
+  using FormatSinkT =
+      absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
+  auto fcs = conv.Wrap<FormatConversionSpecT>();
+  auto fs = sink->Wrap<FormatSinkT>();
+  return AbslFormatConvert(v, fcs, &fs);
+}
 
 template <typename T>
 class StreamedWrapper;
@@ -44,6 +78,13 @@
 // then convert it, appending to `sink` and return `true`.
 // Otherwise fail and return `false`.
 
+// AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v'
+// as an extension mechanism. These FormatConvertImpl functions are the default
+// implementations.
+// The ADL search is augmented via the 'Sink*' parameter, which also
+// serves as a disambiguator to reject possible unintended 'AbslFormatConvert'
+// functions in the namespaces associated with 'v'.
+
 // Raw pointers.
 struct VoidPtr {
   VoidPtr() = default;
@@ -53,28 +94,45 @@
       : value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
   uintptr_t value;
 };
-ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, ConversionSpec conv,
-                                         FormatSinkImpl* sink);
+
+template <FormatConversionCharSet C>
+struct ArgConvertResult {
+  bool value;
+};
+
+template <FormatConversionCharSet C>
+constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
+  return C;
+}
+
+template <FormatConversionCharSet C>
+constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {
+  return C;
+}
+
+using StringConvertResult =
+    ArgConvertResult<FormatConversionCharSetInternal::s>;
+ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
+    VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
 
 // Strings.
-ConvertResult<Conv::s> FormatConvertImpl(const std::string& v,
-                                         ConversionSpec conv,
-                                         FormatSinkImpl* sink);
-ConvertResult<Conv::s> FormatConvertImpl(string_view v, ConversionSpec conv,
-                                         FormatSinkImpl* sink);
-ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char* v,
-                                                   ConversionSpec conv,
-                                                   FormatSinkImpl* sink);
-template <class AbslCord,
-          typename std::enable_if<
-              std::is_same<AbslCord, ::Cord>::value>::type* = nullptr,
-          class AbslCordReader = ::CordReader>
-ConvertResult<Conv::s> FormatConvertImpl(const AbslCord& value,
-                                         ConversionSpec conv,
-                                         FormatSinkImpl* sink) {
-  if (conv.conv().id() != ConversionChar::s) return {false};
+StringConvertResult FormatConvertImpl(const std::string& v,
+                                      FormatConversionSpecImpl conv,
+                                      FormatSinkImpl* sink);
+StringConvertResult FormatConvertImpl(string_view v,
+                                      FormatConversionSpecImpl conv,
+                                      FormatSinkImpl* sink);
+ArgConvertResult<FormatConversionCharSetUnion(
+    FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
+FormatConvertImpl(const char* v, const FormatConversionSpecImpl conv,
+                  FormatSinkImpl* sink);
 
-  bool is_left = conv.flags().left;
+template <class AbslCord, typename std::enable_if<std::is_same<
+                              AbslCord, absl::Cord>::value>::type* = nullptr>
+StringConvertResult FormatConvertImpl(const AbslCord& value,
+                                      FormatConversionSpecImpl conv,
+                                      FormatSinkImpl* sink) {
+  bool is_left = conv.has_left_flag();
   size_t space_remaining = 0;
 
   int width = conv.width();
@@ -90,64 +148,80 @@
 
   if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
 
-  string_view piece;
-  for (AbslCordReader reader(value);
-       to_write > 0 && reader.ReadFragment(&piece); to_write -= piece.size()) {
-    if (piece.size() > to_write) piece.remove_suffix(piece.size() - to_write);
+  for (string_view piece : value.Chunks()) {
+    if (piece.size() > to_write) {
+      piece.remove_suffix(piece.size() - to_write);
+      to_write = 0;
+    } else {
+      to_write -= piece.size();
+    }
     sink->Append(piece);
+    if (to_write == 0) {
+      break;
+    }
   }
 
   if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
   return {true};
 }
 
-using IntegralConvertResult =
-    ConvertResult<Conv::c | Conv::numeric | Conv::star>;
-using FloatingConvertResult = ConvertResult<Conv::floating>;
+using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
+    FormatConversionCharSetInternal::c,
+    FormatConversionCharSetInternal::kNumeric,
+    FormatConversionCharSetInternal::kStar)>;
+using FloatingConvertResult =
+    ArgConvertResult<FormatConversionCharSetInternal::kFloating>;
 
 // Floats.
-FloatingConvertResult FormatConvertImpl(float v, ConversionSpec conv,
+FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
-FloatingConvertResult FormatConvertImpl(double v, ConversionSpec conv,
+FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
-FloatingConvertResult FormatConvertImpl(long double v, ConversionSpec conv,
+FloatingConvertResult FormatConvertImpl(long double v,
+                                        FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
 
 // Chars.
-IntegralConvertResult FormatConvertImpl(char v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(signed char v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(signed char v,
+                                        FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned char v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(unsigned char v,
+                                        FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
 
 // Ints.
 IntegralConvertResult FormatConvertImpl(short v,  // NOLINT
-                                        ConversionSpec conv,
+                                        FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
 IntegralConvertResult FormatConvertImpl(unsigned short v,  // NOLINT
-                                        ConversionSpec conv,
+                                        FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(int v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(unsigned v,
+                                        FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
 IntegralConvertResult FormatConvertImpl(long v,  // NOLINT
-                                        ConversionSpec conv,
+                                        FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
 IntegralConvertResult FormatConvertImpl(unsigned long v,  // NOLINT
-                                        ConversionSpec conv,
+                                        FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
 IntegralConvertResult FormatConvertImpl(long long v,  // NOLINT
-                                        ConversionSpec conv,
+                                        FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
 IntegralConvertResult FormatConvertImpl(unsigned long long v,  // NOLINT
-                                        ConversionSpec conv,
+                                        FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(uint128 v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,
+                                        FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(uint128 v,
+                                        FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink);
 template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
-IntegralConvertResult FormatConvertImpl(T v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
                                         FormatSinkImpl* sink) {
   return FormatConvertImpl(static_cast<int>(v), conv, sink);
 }
@@ -158,12 +232,12 @@
 typename std::enable_if<std::is_enum<T>::value &&
                             !HasUserDefinedConvert<T>::value,
                         IntegralConvertResult>::type
-FormatConvertImpl(T v, ConversionSpec conv, FormatSinkImpl* sink);
+FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
 
 template <typename T>
-ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<T>& v,
-                                         ConversionSpec conv,
-                                         FormatSinkImpl* out) {
+StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
+                                      FormatConversionSpecImpl conv,
+                                      FormatSinkImpl* out) {
   std::ostringstream oss;
   oss << v.v_;
   if (!oss) return {false};
@@ -174,22 +248,24 @@
 // until after FormatCountCapture is fully defined.
 struct FormatCountCaptureHelper {
   template <class T = int>
-  static ConvertResult<Conv::n> ConvertHelper(const FormatCountCapture& v,
-                                              ConversionSpec conv,
-                                              FormatSinkImpl* sink) {
+  static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(
+      const FormatCountCapture& v, FormatConversionSpecImpl conv,
+      FormatSinkImpl* sink) {
     const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
 
-    if (conv.conv().id() != str_format_internal::ConversionChar::n)
+    if (conv.conversion_char() !=
+        str_format_internal::FormatConversionCharInternal::n) {
       return {false};
+    }
     *v2.p_ = static_cast<int>(sink->size());
     return {true};
   }
 };
 
 template <class T = int>
-ConvertResult<Conv::n> FormatConvertImpl(const FormatCountCapture& v,
-                                         ConversionSpec conv,
-                                         FormatSinkImpl* sink) {
+ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
+    const FormatCountCapture& v, FormatConversionSpecImpl conv,
+    FormatSinkImpl* sink) {
   return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
 }
 
@@ -198,13 +274,13 @@
 struct FormatArgImplFriend {
   template <typename Arg>
   static bool ToInt(Arg arg, int* out) {
-    // A value initialized ConversionSpec has a `none` conv, which tells the
-    // dispatcher to run the `int` conversion.
+    // A value initialized FormatConversionSpecImpl has a `none` conv, which
+    // tells the dispatcher to run the `int` conversion.
     return arg.dispatcher_(arg.data_, {}, out);
   }
 
   template <typename Arg>
-  static bool Convert(Arg arg, str_format_internal::ConversionSpec conv,
+  static bool Convert(Arg arg, FormatConversionSpecImpl conv,
                       FormatSinkImpl* out) {
     return arg.dispatcher_(arg.data_, conv, out);
   }
@@ -215,6 +291,15 @@
   }
 };
 
+template <typename Arg>
+constexpr FormatConversionCharSet ArgumentToConv() {
+  return absl::str_format_internal::ExtractCharSet(
+      decltype(str_format_internal::FormatConvertImpl(
+          std::declval<const Arg&>(),
+          std::declval<const FormatConversionSpecImpl&>(),
+          std::declval<FormatSinkImpl*>())){});
+}
+
 // A type-erased handle to a format argument.
 class FormatArgImpl {
  private:
@@ -228,7 +313,7 @@
     char buf[kInlinedSpace];
   };
 
-  using Dispatcher = bool (*)(Data, ConversionSpec, void* out);
+  using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out);
 
   template <typename T>
   struct store_by_value
@@ -370,15 +455,20 @@
   }
 
   template <typename T>
-  static bool Dispatch(Data arg, ConversionSpec spec, void* out) {
+  static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) {
     // A `none` conv indicates that we want the `int` conversion.
-    if (ABSL_PREDICT_FALSE(spec.conv().id() == ConversionChar::none)) {
+    if (ABSL_PREDICT_FALSE(spec.conversion_char() ==
+                           FormatConversionCharInternal::kNone)) {
       return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
                       std::is_enum<T>());
     }
-
+    if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv<T>(),
+                                     spec.conversion_char()))) {
+      return false;
+    }
     return str_format_internal::FormatConvertImpl(
-               Manager<T>::Value(arg), spec, static_cast<FormatSinkImpl*>(out))
+               Manager<T>::Value(arg), spec,
+               static_cast<FormatSinkImpl*>(out))
         .value;
   }
 
@@ -386,8 +476,9 @@
   Dispatcher dispatcher_;
 };
 
-#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
-  E template bool FormatArgImpl::Dispatch<T>(Data, ConversionSpec, void*)
+#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E)                     \
+  E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \
+                                             void*)
 
 #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...)                   \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr,     \
@@ -408,6 +499,7 @@
                                              __VA_ARGS__);                     \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */  \
                                              __VA_ARGS__);                     \
+  ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __VA_ARGS__);             \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__);            \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__);              \
   ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__);             \
@@ -418,7 +510,9 @@
 
 ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
 
+
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
diff --git a/absl/strings/internal/str_format/arg_test.cc b/absl/strings/internal/str_format/arg_test.cc
index 3421fac..1261937 100644
--- a/absl/strings/internal/str_format/arg_test.cc
+++ b/absl/strings/internal/str_format/arg_test.cc
@@ -6,6 +6,12 @@
 //
 //      https://www.apache.org/licenses/LICENSE-2.0
 //
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #include "absl/strings/internal/str_format/arg.h"
 
 #include <ostream>
@@ -14,6 +20,7 @@
 #include "absl/strings/str_format.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 namespace {
 
@@ -22,8 +29,17 @@
   enum Color { kRed, kGreen, kBlue };
 
   static const char *hi() { return "hi"; }
+
+  struct X {};
+
+  X x_;
 };
 
+inline FormatConvertResult<FormatConversionCharSet{}> AbslFormatConvert(
+    const FormatArgImplTest::X &, const FormatConversionSpec &, FormatSink *) {
+  return {false};
+}
+
 TEST_F(FormatArgImplTest, ToInt) {
   int out = 0;
   EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(1), &out));
@@ -58,6 +74,7 @@
       FormatArgImpl(static_cast<int *>(nullptr)), &out));
   EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(hi()), &out));
   EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl("hi"), &out));
+  EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(x_), &out));
   EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(kBlue), &out));
   EXPECT_EQ(2, out);
 }
@@ -94,11 +111,12 @@
 TEST_F(FormatArgImplTest, WorksWithCharArraysOfUnknownSize) {
   std::string s;
   FormatSinkImpl sink(&s);
-  ConversionSpec conv;
-  conv.set_conv(ConversionChar::FromChar('s'));
-  conv.set_flags(Flags());
-  conv.set_width(-1);
-  conv.set_precision(-1);
+  FormatConversionSpecImpl conv;
+  FormatConversionSpecImplFriend::SetConversionChar(
+      FormatConversionCharInternal::s, &conv);
+  FormatConversionSpecImplFriend::SetFlags(Flags(), &conv);
+  FormatConversionSpecImplFriend::SetWidth(-1, &conv);
+  FormatConversionSpecImplFriend::SetPrecision(-1, &conv);
   EXPECT_TRUE(
       FormatArgImplFriend::Convert(FormatArgImpl(kMyArray), conv, &sink));
   sink.Flush();
@@ -108,4 +126,5 @@
 
 }  // namespace
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/bind.cc b/absl/strings/internal/str_format/bind.cc
index a31859e..4e68b90 100644
--- a/absl/strings/internal/str_format/bind.cc
+++ b/absl/strings/internal/str_format/bind.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #include "absl/strings/internal/str_format/bind.h"
 
 #include <cerrno>
@@ -6,6 +20,7 @@
 #include <string>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 
 namespace {
@@ -65,19 +80,22 @@
         return false;
     }
 
-    bound->set_width(width);
-    bound->set_precision(precision);
-    bound->set_flags(unbound->flags);
-    if (force_left)
-      bound->set_left(true);
-  } else {
-    bound->set_flags(unbound->flags);
-    bound->set_width(-1);
-    bound->set_precision(-1);
-  }
+    FormatConversionSpecImplFriend::SetWidth(width, bound);
+    FormatConversionSpecImplFriend::SetPrecision(precision, bound);
 
-  bound->set_length_mod(unbound->length_mod);
-  bound->set_conv(unbound->conv);
+    if (force_left) {
+      Flags flags = unbound->flags;
+      flags.left = true;
+      FormatConversionSpecImplFriend::SetFlags(flags, bound);
+    } else {
+      FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
+    }
+  } else {
+    FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
+    FormatConversionSpecImplFriend::SetWidth(-1, bound);
+    FormatConversionSpecImplFriend::SetPrecision(-1, bound);
+  }
+  FormatConversionSpecImplFriend::SetConversionChar(unbound->conv, bound);
   bound->set_arg(arg);
   return true;
 }
@@ -139,10 +157,11 @@
     UntypedFormatSpecImpl spec("%d");
 
     std::ostringstream ss;
-    ss << "{" << Streamable(spec, {*bound.arg()}) << ":" << bound.flags();
+    ss << "{" << Streamable(spec, {*bound.arg()}) << ":"
+       << FormatConversionSpecImplFriend::FlagsToString(bound);
     if (bound.width() >= 0) ss << bound.width();
     if (bound.precision() >= 0) ss << "." << bound.precision();
-    ss << bound.length_mod() << bound.conv() << "}";
+    ss << bound.conversion_char() << "}";
     Append(ss.str());
     return true;
   }
@@ -196,6 +215,15 @@
   return *out;
 }
 
+std::string FormatPack(const UntypedFormatSpecImpl format,
+                       absl::Span<const FormatArgImpl> args) {
+  std::string out;
+  if (ABSL_PREDICT_FALSE(!FormatUntyped(&out, format, args))) {
+    out.clear();
+  }
+  return out;
+}
+
 int FprintF(std::FILE* output, const UntypedFormatSpecImpl format,
             absl::Span<const FormatArgImpl> args) {
   FILERawSink sink(output);
@@ -207,7 +235,7 @@
     errno = sink.error();
     return -1;
   }
-  if (sink.count() > std::numeric_limits<int>::max()) {
+  if (sink.count() > static_cast<size_t>(std::numeric_limits<int>::max())) {
     errno = EFBIG;
     return -1;
   }
@@ -227,4 +255,5 @@
 }
 
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h
index 7df140a..267cc0e 100644
--- a/absl/strings/internal/str_format/bind.h
+++ b/absl/strings/internal/str_format/bind.h
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
 
@@ -13,12 +27,13 @@
 #include "absl/types/span.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 class UntypedFormatSpec;
 
 namespace str_format_internal {
 
-class BoundConversion : public ConversionSpec {
+class BoundConversion : public FormatConversionSpecImpl {
  public:
   const FormatArgImpl* arg() const { return arg_; }
   void set_arg(const FormatArgImpl* a) { arg_ = a; }
@@ -59,7 +74,7 @@
   size_t size_;
 };
 
-template <typename T, typename...>
+template <typename T, FormatConversionCharSet...>
 struct MakeDependent {
   using type = T;
 };
@@ -67,19 +82,19 @@
 // Implicitly convertible from `const char*`, `string_view`, and the
 // `ExtendedParsedFormat` type. This abstraction allows all format functions to
 // operate on any without providing too many overloads.
-template <typename... Args>
+template <FormatConversionCharSet... Args>
 class FormatSpecTemplate
     : public MakeDependent<UntypedFormatSpec, Args...>::type {
   using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
 
  public:
-#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 
-  // Honeypot overload for when the std::string is not constexpr.
+  // Honeypot overload for when the string is not constexpr.
   // We use the 'unavailable' attribute to give a better compiler error than
   // just 'method is deleted'.
   FormatSpecTemplate(...)  // NOLINT
-      __attribute__((unavailable("Format std::string is not constexpr.")));
+      __attribute__((unavailable("Format string is not constexpr.")));
 
   // Honeypot overload for when the format is constexpr and invalid.
   // We use the 'unavailable' attribute to give a better compiler error than
@@ -104,13 +119,11 @@
 
   // Good format overload.
   FormatSpecTemplate(const char* s)  // NOLINT
-      __attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
-                               "bad format trap")))
+      __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
       : Base(s) {}
 
   FormatSpecTemplate(string_view s)  // NOLINT
-      __attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
-                               "bad format trap")))
+      __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
       : Base(s) {}
 
 #else  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
@@ -120,19 +133,15 @@
 
 #endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 
-  template <Conv... C, typename = typename std::enable_if<
-                           sizeof...(C) == sizeof...(Args) &&
-                           AllOf(Contains(ArgumentToConv<Args>(),
-                                          C)...)>::type>
+  template <
+      FormatConversionCharSet... C,
+      typename = typename std::enable_if<sizeof...(C) == sizeof...(Args)>::type,
+      typename = typename std::enable_if<AllOf(Contains(Args,
+                                                        C)...)>::type>
   FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc)  // NOLINT
       : Base(&pc) {}
 };
 
-template <typename... Args>
-struct FormatSpecDeductionBarrier {
-  using type = FormatSpecTemplate<Args...>;
-};
-
 class Streamable {
  public:
   Streamable(const UntypedFormatSpecImpl& format,
@@ -178,12 +187,8 @@
 std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,
                         absl::Span<const FormatArgImpl> args);
 
-inline std::string FormatPack(const UntypedFormatSpecImpl format,
-                              absl::Span<const FormatArgImpl> args) {
-  std::string out;
-  AppendPack(&out, format, args);
-  return out;
-}
+std::string FormatPack(const UntypedFormatSpecImpl format,
+                       absl::Span<const FormatArgImpl> args);
 
 int FprintF(std::FILE* output, UntypedFormatSpecImpl format,
             absl::Span<const FormatArgImpl> args);
@@ -199,13 +204,14 @@
 
  private:
   template <typename S>
-  friend ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<S>& v,
-                                                  ConversionSpec conv,
-                                                  FormatSinkImpl* out);
+  friend ArgConvertResult<FormatConversionCharSetInternal::s> FormatConvertImpl(
+      const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
+      FormatSinkImpl* out);
   const T& v_;
 };
 
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
diff --git a/absl/strings/internal/str_format/bind_test.cc b/absl/strings/internal/str_format/bind_test.cc
index 2574801..1eef9c4 100644
--- a/absl/strings/internal/str_format/bind_test.cc
+++ b/absl/strings/internal/str_format/bind_test.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #include "absl/strings/internal/str_format/bind.h"
 
 #include <string.h>
@@ -6,6 +20,7 @@
 #include "gtest/gtest.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 namespace {
 
@@ -112,18 +127,18 @@
                                 FormatArgImpl(ia[2]), FormatArgImpl(ia[3]),
                                 FormatArgImpl(ia[4])};
   const Expectation kExpect[] = {
-    {__LINE__, "a%4db%dc", "a{10:4d}b{20:d}c"},
-    {__LINE__, "a%.4db%dc", "a{10:.4d}b{20:d}c"},
-    {__LINE__, "a%4.5db%dc", "a{10:4.5d}b{20:d}c"},
-    {__LINE__, "a%db%4.5dc", "a{10:d}b{20:4.5d}c"},
-    {__LINE__, "a%db%*.*dc", "a{10:d}b{40:20.30d}c"},
-    {__LINE__, "a%.*fb", "a{20:.10f}b"},
-    {__LINE__, "a%1$db%2$*3$.*4$dc", "a{10:d}b{20:30.40d}c"},
-    {__LINE__, "a%4$db%3$*2$.*1$dc", "a{40:d}b{30:20.10d}c"},
-    {__LINE__, "a%04ldb", "a{10:04ld}b"},
-    {__LINE__, "a%-#04lldb", "a{10:-#04lld}b"},
-    {__LINE__, "a%1$*5$db", "a{10:-10d}b"},
-    {__LINE__, "a%1$.*5$db", "a{10:d}b"},
+      {__LINE__, "a%4db%dc", "a{10:4d}b{20:d}c"},
+      {__LINE__, "a%.4db%dc", "a{10:.4d}b{20:d}c"},
+      {__LINE__, "a%4.5db%dc", "a{10:4.5d}b{20:d}c"},
+      {__LINE__, "a%db%4.5dc", "a{10:d}b{20:4.5d}c"},
+      {__LINE__, "a%db%*.*dc", "a{10:d}b{40:20.30d}c"},
+      {__LINE__, "a%.*fb", "a{20:.10f}b"},
+      {__LINE__, "a%1$db%2$*3$.*4$dc", "a{10:d}b{20:30.40d}c"},
+      {__LINE__, "a%4$db%3$*2$.*1$dc", "a{40:d}b{30:20.10d}c"},
+      {__LINE__, "a%04ldb", "a{10:04d}b"},
+      {__LINE__, "a%-#04lldb", "a{10:-#04d}b"},
+      {__LINE__, "a%1$*5$db", "a{10:-10d}b"},
+      {__LINE__, "a%1$.*5$db", "a{10:d}b"},
   };
   for (const Expectation &e : kExpect) {
     absl::string_view fmt = e.fmt;
@@ -138,4 +153,5 @@
 
 }  // namespace
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/checker.h b/absl/strings/internal/str_format/checker.h
index 8b594f2..2a2601e 100644
--- a/absl/strings/internal/str_format/checker.h
+++ b/absl/strings/internal/str_format/checker.h
@@ -1,20 +1,34 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
 
+#include "absl/base/attributes.h"
 #include "absl/strings/internal/str_format/arg.h"
 #include "absl/strings/internal/str_format/extension.h"
 
 // Compile time check support for entry points.
 
 #ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
-#if defined(__clang__) && !defined(__native_client__)
-#if __has_attribute(enable_if)
+#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
 #define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1
-#endif  // __has_attribute(enable_if)
-#endif  // defined(__clang__) && !defined(__native_client__)
+#endif  // ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
 #endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 
 constexpr bool AllOf() { return true; }
@@ -24,14 +38,7 @@
   return b && AllOf(t...);
 }
 
-template <typename Arg>
-constexpr Conv ArgumentToConv() {
-  return decltype(str_format_internal::FormatConvertImpl(
-      std::declval<const Arg&>(), std::declval<const ConversionSpec&>(),
-      std::declval<FormatSinkImpl*>()))::kConv;
-}
-
-#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 
 constexpr bool ContainsChar(const char* chars, char c) {
   return *chars == c || (*chars && ContainsChar(chars + 1, c));
@@ -39,14 +46,14 @@
 
 // A constexpr compatible list of Convs.
 struct ConvList {
-  const Conv* array;
+  const FormatConversionCharSet* array;
   int count;
 
   // We do the bound check here to avoid having to do it on the callers.
-  // Returning an empty Conv has the same effect as short circuiting because it
-  // will never match any conversion.
-  constexpr Conv operator[](int i) const {
-    return i < count ? array[i] : Conv{};
+  // Returning an empty FormatConversionCharSet has the same effect as
+  // short circuiting because it will never match any conversion.
+  constexpr FormatConversionCharSet operator[](int i) const {
+    return i < count ? array[i] : FormatConversionCharSet{};
   }
 
   constexpr ConvList without_front() const {
@@ -57,7 +64,7 @@
 template <size_t count>
 struct ConvListT {
   // Make sure the array has size > 0.
-  Conv list[count ? count : 1];
+  FormatConversionCharSet list[count ? count : 1];
 };
 
 constexpr char GetChar(string_view str, size_t index) {
@@ -310,7 +317,7 @@
   ConvList args_;
 };
 
-template <Conv... C>
+template <FormatConversionCharSet... C>
 constexpr bool ValidFormatImpl(string_view format) {
   return FormatParser(format,
                       {ConvListT<sizeof...(C)>{{C...}}.list, sizeof...(C)})
@@ -320,6 +327,7 @@
 #endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
diff --git a/absl/strings/internal/str_format/checker_test.cc b/absl/strings/internal/str_format/checker_test.cc
index c1d8c76..7c70f47 100644
--- a/absl/strings/internal/str_format/checker_test.cc
+++ b/absl/strings/internal/str_format/checker_test.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #include <string>
 
 #include "gmock/gmock.h"
@@ -5,21 +19,26 @@
 #include "absl/strings/str_format.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 namespace {
 
-std::string ConvToString(Conv conv) {
+std::string ConvToString(FormatConversionCharSet conv) {
   std::string out;
-#define CONV_SET_CASE(c) \
-  if (Contains(conv, Conv::c)) out += #c;
-  ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
+#define CONV_SET_CASE(c)                                    \
+  if (Contains(conv, FormatConversionCharSetInternal::c)) { \
+    out += #c;                                              \
+  }
+  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
 #undef CONV_SET_CASE
-  if (Contains(conv, Conv::star)) out += "*";
+  if (Contains(conv, FormatConversionCharSetInternal::kStar)) {
+    out += "*";
+  }
   return out;
 }
 
 TEST(StrFormatChecker, ArgumentToConv) {
-  Conv conv = ArgumentToConv<std::string>();
+  FormatConversionCharSet conv = ArgumentToConv<std::string>();
   EXPECT_EQ(ConvToString(conv), "s");
 
   conv = ArgumentToConv<const char*>();
@@ -35,7 +54,7 @@
   EXPECT_EQ(ConvToString(conv), "p");
 }
 
-#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 
 struct Case {
   bool result;
@@ -147,4 +166,5 @@
 
 }  // namespace
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc
index 814ccf4..375db0a 100644
--- a/absl/strings/internal/str_format/convert_test.cc
+++ b/absl/strings/internal/str_format/convert_test.cc
@@ -1,17 +1,46 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #include <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
+
 #include <cctype>
 #include <cmath>
+#include <limits>
 #include <string>
+#include <thread>  // NOLINT
 
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
 #include "absl/strings/internal/str_format/bind.h"
+#include "absl/strings/match.h"
+#include "absl/types/optional.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 namespace {
 
+struct NativePrintfTraits {
+  bool hex_float_has_glibc_rounding;
+  bool hex_float_prefers_denormal_repr;
+  bool hex_float_uses_minimal_precision_when_not_specified;
+  bool hex_float_optimizes_leading_digit_bit_count;
+};
+
 template <typename T, size_t N>
 size_t ArraySize(T (&)[N]) {
   return N;
@@ -54,7 +83,7 @@
   return oss.str();
 }
 
-void StrAppend(std::string *dst, const char *format, va_list ap) {
+void StrAppendV(std::string *dst, const char *format, va_list ap) {
   // First try with a small fixed size buffer
   static const int kSpaceLength = 1024;
   char space[kSpaceLength];
@@ -95,15 +124,79 @@
   delete[] buf;
 }
 
+void StrAppend(std::string *out, const char *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  StrAppendV(out, format, ap);
+  va_end(ap);
+}
+
 std::string StrPrint(const char *format, ...) {
   va_list ap;
   va_start(ap, format);
   std::string result;
-  StrAppend(&result, format, ap);
+  StrAppendV(&result, format, ap);
   va_end(ap);
   return result;
 }
 
+NativePrintfTraits VerifyNativeImplementationImpl() {
+  NativePrintfTraits result;
+
+  // >>> hex_float_has_glibc_rounding. To have glibc's rounding behavior we need
+  // to meet three requirements:
+  //
+  //   - The threshold for rounding up is 8 (for e.g. MSVC uses 9).
+  //   - If the digits lower than than the 8 are non-zero then we round up.
+  //   - If the digits lower than the 8 are all zero then we round toward even.
+  //
+  // The numbers below represent all the cases covering {below,at,above} the
+  // threshold (8) with both {zero,non-zero} lower bits and both {even,odd}
+  // preceding digits.
+  const double d0079 = 65657.0;  // 0x1.0079p+16
+  const double d0179 = 65913.0;  // 0x1.0179p+16
+  const double d0080 = 65664.0;  // 0x1.0080p+16
+  const double d0180 = 65920.0;  // 0x1.0180p+16
+  const double d0081 = 65665.0;  // 0x1.0081p+16
+  const double d0181 = 65921.0;  // 0x1.0181p+16
+  result.hex_float_has_glibc_rounding =
+      StartsWith(StrPrint("%.2a", d0079), "0x1.00") &&
+      StartsWith(StrPrint("%.2a", d0179), "0x1.01") &&
+      StartsWith(StrPrint("%.2a", d0080), "0x1.00") &&
+      StartsWith(StrPrint("%.2a", d0180), "0x1.02") &&
+      StartsWith(StrPrint("%.2a", d0081), "0x1.01") &&
+      StartsWith(StrPrint("%.2a", d0181), "0x1.02");
+
+  // >>> hex_float_prefers_denormal_repr. Formatting `denormal` on glibc yields
+  // "0x0.0000000000001p-1022", whereas on std libs that don't use denormal
+  // representation it would either be 0x1p-1074 or 0x1.0000000000000-1074.
+  const double denormal = std::numeric_limits<double>::denorm_min();
+  result.hex_float_prefers_denormal_repr =
+      StartsWith(StrPrint("%a", denormal), "0x0.0000000000001");
+
+  // >>> hex_float_uses_minimal_precision_when_not_specified. Some (non-glibc)
+  // libs will format the following as "0x1.0079000000000p+16".
+  result.hex_float_uses_minimal_precision_when_not_specified =
+      (StrPrint("%a", d0079) == "0x1.0079p+16");
+
+  // >>> hex_float_optimizes_leading_digit_bit_count. The number 1.5, when
+  // formatted by glibc should yield "0x1.8p+0" for `double` and "0xcp-3" for
+  // `long double`, i.e., number of bits in the leading digit is adapted to the
+  // number of bits in the mantissa.
+  const double d_15 = 1.5;
+  const long double ld_15 = 1.5;
+  result.hex_float_optimizes_leading_digit_bit_count =
+      StartsWith(StrPrint("%a", d_15), "0x1.8") &&
+      StartsWith(StrPrint("%La", ld_15), "0xc");
+
+  return result;
+}
+
+const NativePrintfTraits &VerifyNativeImplementation() {
+  static NativePrintfTraits native_traits = VerifyNativeImplementationImpl();
+  return native_traits;
+}
+
 class FormatConvertTest : public ::testing::Test { };
 
 template <typename T>
@@ -151,18 +244,26 @@
   UntypedFormatSpecImpl format("%.1s");
   EXPECT_EQ("a", FormatPack(format, {FormatArgImpl(p)}));
 
-  // We cap at the nul terminator.
+  // We cap at the NUL-terminator.
   p = "ABC";
   UntypedFormatSpecImpl format2("%.10s");
   EXPECT_EQ("ABC", FormatPack(format2, {FormatArgImpl(p)}));
 }
 
+// Pointer formatting is implementation defined. This checks that the argument
+// can be matched to `ptr`.
+MATCHER_P(MatchesPointerString, ptr, "") {
+  if (ptr == nullptr && arg == "(nil)") {
+    return true;
+  }
+  void* parsed = nullptr;
+  if (sscanf(arg.c_str(), "%p", &parsed) != 1) {
+    ABSL_RAW_LOG(FATAL, "Could not parse %s", arg.c_str());
+  }
+  return ptr == parsed;
+}
+
 TEST_F(FormatConvertTest, Pointer) {
-#ifdef _MSC_VER
-  // MSVC's printf implementation prints pointers differently. We can't easily
-  // compare our implementation to theirs.
-  return;
-#endif
   static int x = 0;
   const int *xp = &x;
   char c = 'h';
@@ -173,48 +274,62 @@
   using VoidF = void (*)();
   VoidF fp = [] {}, fnil = nullptr;
   volatile char vc;
-  volatile char* vcp = &vc;
-  volatile char* vcnil = nullptr;
-  const FormatArgImpl args[] = {
+  volatile char *vcp = &vc;
+  volatile char *vcnil = nullptr;
+  const FormatArgImpl args_array[] = {
       FormatArgImpl(xp),   FormatArgImpl(cp),  FormatArgImpl(inil),
       FormatArgImpl(cnil), FormatArgImpl(mcp), FormatArgImpl(fp),
       FormatArgImpl(fnil), FormatArgImpl(vcp), FormatArgImpl(vcnil),
   };
-  struct Expectation {
-    std::string out;
-    const char *fmt;
-  };
-  const Expectation kExpect[] = {
-      {StrPrint("%p", &x), "%p"},
-      {StrPrint("%20p", &x), "%20p"},
-      {StrPrint("%.1p", &x), "%.1p"},
-      {StrPrint("%.20p", &x), "%.20p"},
-      {StrPrint("%30.20p", &x), "%30.20p"},
+  auto args = absl::MakeConstSpan(args_array);
 
-      {StrPrint("%-p", &x), "%-p"},
-      {StrPrint("%-20p", &x), "%-20p"},
-      {StrPrint("%-.1p", &x), "%-.1p"},
-      {StrPrint("%.20p", &x), "%.20p"},
-      {StrPrint("%-30.20p", &x), "%-30.20p"},
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%p"), args),
+              MatchesPointerString(&x));
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%20p"), args),
+              MatchesPointerString(&x));
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.1p"), args),
+              MatchesPointerString(&x));
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args),
+              MatchesPointerString(&x));
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%30.20p"), args),
+              MatchesPointerString(&x));
 
-      {StrPrint("%p", cp), "%2$p"},   // const char*
-      {"(nil)", "%3$p"},              // null const char *
-      {"(nil)", "%4$p"},              // null const int *
-      {StrPrint("%p", mcp), "%5$p"},  // nonconst char*
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-p"), args),
+              MatchesPointerString(&x));
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-20p"), args),
+              MatchesPointerString(&x));
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-.1p"), args),
+              MatchesPointerString(&x));
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args),
+              MatchesPointerString(&x));
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-30.20p"), args),
+              MatchesPointerString(&x));
 
-      {StrPrint("%p", fp), "%6$p"},   // function pointer
-      {StrPrint("%p", vcp), "%8$p"},  // function pointer
+  // const char*
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%2$p"), args),
+              MatchesPointerString(cp));
+  // null const int*
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%3$p"), args),
+              MatchesPointerString(nullptr));
+  // null const char*
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%4$p"), args),
+              MatchesPointerString(nullptr));
+  // nonconst char*
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%5$p"), args),
+              MatchesPointerString(mcp));
 
-#ifndef __APPLE__
-      // Apple's printf differs here (0x0 vs. nil)
-      {StrPrint("%p", fnil), "%7$p"},   // null function pointer
-      {StrPrint("%p", vcnil), "%9$p"},  // null function pointer
-#endif
-  };
-  for (const Expectation &e : kExpect) {
-    UntypedFormatSpecImpl format(e.fmt);
-    EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))) << e.fmt;
-  }
+  // function pointers
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%6$p"), args),
+              MatchesPointerString(reinterpret_cast<const void*>(fp)));
+  EXPECT_THAT(
+      FormatPack(UntypedFormatSpecImpl("%8$p"), args),
+      MatchesPointerString(reinterpret_cast<volatile const void *>(vcp)));
+
+  // null function pointers
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%7$p"), args),
+              MatchesPointerString(nullptr));
+  EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%9$p"), args),
+              MatchesPointerString(nullptr));
 }
 
 struct Cardinal {
@@ -366,7 +481,6 @@
     AllIntTypes;
 INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes,
                               TypedFormatConvertTest, AllIntTypes);
-
 TEST_F(FormatConvertTest, VectorBool) {
   // Make sure vector<bool>'s values behave as bools.
   std::vector<bool> v = {true, false};
@@ -378,6 +492,42 @@
                             FormatArgImpl(cv[0]), FormatArgImpl(cv[1])})));
 }
 
+
+TEST_F(FormatConvertTest, Int128) {
+  absl::int128 positive = static_cast<absl::int128>(0x1234567890abcdef) * 1979;
+  absl::int128 negative = -positive;
+  absl::int128 max = absl::Int128Max(), min = absl::Int128Min();
+  const FormatArgImpl args[] = {FormatArgImpl(positive),
+                                FormatArgImpl(negative), FormatArgImpl(max),
+                                FormatArgImpl(min)};
+
+  struct Case {
+    const char* format;
+    const char* expected;
+  } cases[] = {
+      {"%1$d", "2595989796776606496405"},
+      {"%1$30d", "        2595989796776606496405"},
+      {"%1$-30d", "2595989796776606496405        "},
+      {"%1$u", "2595989796776606496405"},
+      {"%1$x", "8cba9876066020f695"},
+      {"%2$d", "-2595989796776606496405"},
+      {"%2$30d", "       -2595989796776606496405"},
+      {"%2$-30d", "-2595989796776606496405       "},
+      {"%2$u", "340282366920938460867384810655161715051"},
+      {"%2$x", "ffffffffffffff73456789f99fdf096b"},
+      {"%3$d", "170141183460469231731687303715884105727"},
+      {"%3$u", "170141183460469231731687303715884105727"},
+      {"%3$x", "7fffffffffffffffffffffffffffffff"},
+      {"%4$d", "-170141183460469231731687303715884105728"},
+      {"%4$x", "80000000000000000000000000000000"},
+  };
+
+  for (auto c : cases) {
+    UntypedFormatSpecImpl format(c.format);
+    EXPECT_EQ(c.expected, FormatPack(format, absl::MakeSpan(args)));
+  }
+}
+
 TEST_F(FormatConvertTest, Uint128) {
   absl::uint128 v = static_cast<absl::uint128>(0x1234567890abcdef) * 1979;
   absl::uint128 max = absl::Uint128Max();
@@ -403,6 +553,68 @@
   }
 }
 
+template <typename Floating>
+void TestWithMultipleFormatsHelper(const std::vector<Floating> &floats) {
+  const NativePrintfTraits &native_traits = VerifyNativeImplementation();
+  // Reserve the space to ensure we don't allocate memory in the output itself.
+  std::string str_format_result;
+  str_format_result.reserve(1 << 20);
+  std::string string_printf_result;
+  string_printf_result.reserve(1 << 20);
+
+  const char *const kFormats[] = {
+      "%",  "%.3", "%8.5", "%500",   "%.5000", "%.60", "%.30",   "%03",
+      "%+", "% ",  "%-10", "%#15.3", "%#.0",   "%.0",  "%1$*2$", "%1$.*2$"};
+
+  for (const char *fmt : kFormats) {
+    for (char f : {'f', 'F',  //
+                   'g', 'G',  //
+                   'a', 'A',  //
+                   'e', 'E'}) {
+      std::string fmt_str = std::string(fmt) + f;
+
+      if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F' &&
+          f != 'a' && f != 'A') {
+        // This particular test takes way too long with snprintf.
+        // Disable for the case we are not implementing natively.
+        continue;
+      }
+
+      if ((f == 'a' || f == 'A') &&
+          !native_traits.hex_float_has_glibc_rounding) {
+        continue;
+      }
+
+      for (Floating d : floats) {
+        if (!native_traits.hex_float_prefers_denormal_repr &&
+            (f == 'a' || f == 'A') && std::fpclassify(d) == FP_SUBNORMAL) {
+          continue;
+        }
+        int i = -10;
+        FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)};
+        UntypedFormatSpecImpl format(fmt_str);
+
+        string_printf_result.clear();
+        StrAppend(&string_printf_result, fmt_str.c_str(), d, i);
+        str_format_result.clear();
+
+        {
+          AppendPack(&str_format_result, format, absl::MakeSpan(args));
+        }
+
+        if (string_printf_result != str_format_result) {
+          // We use ASSERT_EQ here because failures are usually correlated and a
+          // bug would print way too many failed expectations causing the test
+          // to time out.
+          ASSERT_EQ(string_printf_result, str_format_result)
+              << fmt_str << " " << StrPrint("%.18g", d) << " "
+              << StrPrint("%a", d) << " " << StrPrint("%.50f", d);
+        }
+      }
+    }
+  }
+}
+
 TEST_F(FormatConvertTest, Float) {
 #ifdef _MSC_VER
   // MSVC has a different rounding policy than us so we can't test our
@@ -410,9 +622,62 @@
   return;
 #endif  // _MSC_VER
 
-  const char *const kFormats[] = {
-      "%",  "%.3",  "%8.5",   "%9",   "%.60", "%.30",   "%03",    "%+",
-      "% ", "%-10", "%#15.3", "%#.0", "%.0",  "%1$*2$", "%1$.*2$"};
+  std::vector<float> floats = {0.0f,
+                               -0.0f,
+                               .9999999f,
+                               9999999.f,
+                               std::numeric_limits<float>::max(),
+                               -std::numeric_limits<float>::max(),
+                               std::numeric_limits<float>::min(),
+                               -std::numeric_limits<float>::min(),
+                               std::numeric_limits<float>::lowest(),
+                               -std::numeric_limits<float>::lowest(),
+                               std::numeric_limits<float>::epsilon(),
+                               std::numeric_limits<float>::epsilon() + 1.0f,
+                               std::numeric_limits<float>::infinity(),
+                               -std::numeric_limits<float>::infinity()};
+
+  // Some regression tests.
+  floats.push_back(0.999999989f);
+
+  if (std::numeric_limits<float>::has_denorm != std::denorm_absent) {
+    floats.push_back(std::numeric_limits<float>::denorm_min());
+    floats.push_back(-std::numeric_limits<float>::denorm_min());
+  }
+
+  for (float base :
+       {1.f, 12.f, 123.f, 1234.f, 12345.f, 123456.f, 1234567.f, 12345678.f,
+        123456789.f, 1234567890.f, 12345678901.f, 12345678.f, 12345678.f}) {
+    for (int exp = -123; exp <= 123; ++exp) {
+      for (int sign : {1, -1}) {
+        floats.push_back(sign * std::ldexp(base, exp));
+      }
+    }
+  }
+
+  for (int exp = -300; exp <= 300; ++exp) {
+    const float all_ones_mantissa = 0xffffff;
+    floats.push_back(std::ldexp(all_ones_mantissa, exp));
+  }
+
+  // Remove duplicates to speed up the logic below.
+  std::sort(floats.begin(), floats.end());
+  floats.erase(std::unique(floats.begin(), floats.end()), floats.end());
+
+#ifndef __APPLE__
+  // Apple formats NaN differently (+nan) vs. (nan)
+  floats.push_back(std::nan(""));
+#endif
+
+  TestWithMultipleFormatsHelper(floats);
+}
+
+TEST_F(FormatConvertTest, Double) {
+#ifdef _MSC_VER
+  // MSVC has a different rounding policy than us so we can't test our
+  // implementation against the native one there.
+  return;
+#endif  // _MSC_VER
 
   std::vector<double> doubles = {0.0,
                                  -0.0,
@@ -429,11 +694,6 @@
                                  std::numeric_limits<double>::infinity(),
                                  -std::numeric_limits<double>::infinity()};
 
-#ifndef __APPLE__
-  // Apple formats NaN differently (+nan) vs. (nan)
-  doubles.push_back(std::nan(""));
-#endif
-
   // Some regression tests.
   doubles.push_back(0.99999999999999989);
 
@@ -452,43 +712,375 @@
     }
   }
 
-  for (const char *fmt : kFormats) {
-    for (char f : {'f', 'F',  //
-                   'g', 'G',  //
-                   'a', 'A',  //
-                   'e', 'E'}) {
-      std::string fmt_str = std::string(fmt) + f;
-      for (double d : doubles) {
-        int i = -10;
-        FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)};
-        UntypedFormatSpecImpl format(fmt_str);
-        // We use ASSERT_EQ here because failures are usually correlated and a
-        // bug would print way too many failed expectations causing the test to
-        // time out.
-        ASSERT_EQ(StrPrint(fmt_str.c_str(), d, i),
-                  FormatPack(format, absl::MakeSpan(args)))
-            << fmt_str << " " << StrPrint("%.18g", d) << " "
-            << StrPrint("%.999f", d);
+  // Workaround libc bug.
+  // https://sourceware.org/bugzilla/show_bug.cgi?id=22142
+  const bool gcc_bug_22142 =
+      StrPrint("%f", std::numeric_limits<double>::max()) !=
+      "1797693134862315708145274237317043567980705675258449965989174768031"
+      "5726078002853876058955863276687817154045895351438246423432132688946"
+      "4182768467546703537516986049910576551282076245490090389328944075868"
+      "5084551339423045832369032229481658085593321233482747978262041447231"
+      "68738177180919299881250404026184124858368.000000";
+
+  if (!gcc_bug_22142) {
+    for (int exp = -300; exp <= 300; ++exp) {
+      const double all_ones_mantissa = 0x1fffffffffffff;
+      doubles.push_back(std::ldexp(all_ones_mantissa, exp));
+    }
+  }
+
+  if (gcc_bug_22142) {
+    for (auto &d : doubles) {
+      using L = std::numeric_limits<double>;
+      double d2 = std::abs(d);
+      if (d2 == L::max() || d2 == L::min() || d2 == L::denorm_min()) {
+        d = 0;
       }
     }
   }
+
+  // Remove duplicates to speed up the logic below.
+  std::sort(doubles.begin(), doubles.end());
+  doubles.erase(std::unique(doubles.begin(), doubles.end()), doubles.end());
+
+#ifndef __APPLE__
+  // Apple formats NaN differently (+nan) vs. (nan)
+  doubles.push_back(std::nan(""));
+#endif
+
+  TestWithMultipleFormatsHelper(doubles);
+}
+
+TEST_F(FormatConvertTest, DoubleRound) {
+  std::string s;
+  const auto format = [&](const char *fmt, double d) -> std::string & {
+    s.clear();
+    FormatArgImpl args[1] = {FormatArgImpl(d)};
+    AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));
+#if !defined(_MSC_VER)
+    // MSVC has a different rounding policy than us so we can't test our
+    // implementation against the native one there.
+    EXPECT_EQ(StrPrint(fmt, d), s);
+#endif  // _MSC_VER
+
+    return s;
+  };
+  // All of these values have to be exactly represented.
+  // Otherwise we might not be testing what we think we are testing.
+
+  // These values can fit in a 64bit "fast" representation.
+  const double exact_value = 0.00000000000005684341886080801486968994140625;
+  assert(exact_value == std::pow(2, -44));
+  // Round up at a 5xx.
+  EXPECT_EQ(format("%.13f", exact_value), "0.0000000000001");
+  // Round up at a >5
+  EXPECT_EQ(format("%.14f", exact_value), "0.00000000000006");
+  // Round down at a <5
+  EXPECT_EQ(format("%.16f", exact_value), "0.0000000000000568");
+  // Nine handling
+  EXPECT_EQ(format("%.35f", exact_value),
+            "0.00000000000005684341886080801486969");
+  EXPECT_EQ(format("%.36f", exact_value),
+            "0.000000000000056843418860808014869690");
+  // Round down the last nine.
+  EXPECT_EQ(format("%.37f", exact_value),
+            "0.0000000000000568434188608080148696899");
+  EXPECT_EQ(format("%.10f", 0.000003814697265625), "0.0000038147");
+  // Round up the last nine
+  EXPECT_EQ(format("%.11f", 0.000003814697265625), "0.00000381470");
+  EXPECT_EQ(format("%.12f", 0.000003814697265625), "0.000003814697");
+
+  // Round to even (down)
+  EXPECT_EQ(format("%.43f", exact_value),
+            "0.0000000000000568434188608080148696899414062");
+  // Exact
+  EXPECT_EQ(format("%.44f", exact_value),
+            "0.00000000000005684341886080801486968994140625");
+  // Round to even (up), let make the last digits 75 instead of 25
+  EXPECT_EQ(format("%.43f", exact_value + std::pow(2, -43)),
+            "0.0000000000001705302565824240446090698242188");
+  // Exact, just to check.
+  EXPECT_EQ(format("%.44f", exact_value + std::pow(2, -43)),
+            "0.00000000000017053025658242404460906982421875");
+
+  // This value has to be small enough that it won't fit in the uint128
+  // representation for printing.
+  const double small_exact_value =
+      0.000000000000000000000000000000000000752316384526264005099991383822237233803945956334136013765601092018187046051025390625;  // NOLINT
+  assert(small_exact_value == std::pow(2, -120));
+  // Round up at a 5xx.
+  EXPECT_EQ(format("%.37f", small_exact_value),
+            "0.0000000000000000000000000000000000008");
+  // Round down at a <5
+  EXPECT_EQ(format("%.38f", small_exact_value),
+            "0.00000000000000000000000000000000000075");
+  // Round up at a >5
+  EXPECT_EQ(format("%.41f", small_exact_value),
+            "0.00000000000000000000000000000000000075232");
+  // Nine handling
+  EXPECT_EQ(format("%.55f", small_exact_value),
+            "0.0000000000000000000000000000000000007523163845262640051");
+  EXPECT_EQ(format("%.56f", small_exact_value),
+            "0.00000000000000000000000000000000000075231638452626400510");
+  EXPECT_EQ(format("%.57f", small_exact_value),
+            "0.000000000000000000000000000000000000752316384526264005100");
+  EXPECT_EQ(format("%.58f", small_exact_value),
+            "0.0000000000000000000000000000000000007523163845262640051000");
+  // Round down the last nine
+  EXPECT_EQ(format("%.59f", small_exact_value),
+            "0.00000000000000000000000000000000000075231638452626400509999");
+  // Round up the last nine
+  EXPECT_EQ(format("%.79f", small_exact_value),
+            "0.000000000000000000000000000000000000"
+            "7523163845262640050999913838222372338039460");
+
+  // Round to even (down)
+  EXPECT_EQ(format("%.119f", small_exact_value),
+            "0.000000000000000000000000000000000000"
+            "75231638452626400509999138382223723380"
+            "394595633413601376560109201818704605102539062");
+  // Exact
+  EXPECT_EQ(format("%.120f", small_exact_value),
+            "0.000000000000000000000000000000000000"
+            "75231638452626400509999138382223723380"
+            "3945956334136013765601092018187046051025390625");
+  // Round to even (up), let make the last digits 75 instead of 25
+  EXPECT_EQ(format("%.119f", small_exact_value + std::pow(2, -119)),
+            "0.000000000000000000000000000000000002"
+            "25694915357879201529997415146671170141"
+            "183786900240804129680327605456113815307617188");
+  // Exact, just to check.
+  EXPECT_EQ(format("%.120f", small_exact_value + std::pow(2, -119)),
+            "0.000000000000000000000000000000000002"
+            "25694915357879201529997415146671170141"
+            "1837869002408041296803276054561138153076171875");
+}
+
+TEST_F(FormatConvertTest, DoubleRoundA) {
+  const NativePrintfTraits &native_traits = VerifyNativeImplementation();
+  std::string s;
+  const auto format = [&](const char *fmt, double d) -> std::string & {
+    s.clear();
+    FormatArgImpl args[1] = {FormatArgImpl(d)};
+    AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));
+    if (native_traits.hex_float_has_glibc_rounding) {
+      EXPECT_EQ(StrPrint(fmt, d), s);
+    }
+    return s;
+  };
+
+  // 0x1.00018000p+100
+  const double on_boundary_odd = 1267679614447900152596896153600.0;
+  EXPECT_EQ(format("%.0a", on_boundary_odd), "0x1p+100");
+  EXPECT_EQ(format("%.1a", on_boundary_odd), "0x1.0p+100");
+  EXPECT_EQ(format("%.2a", on_boundary_odd), "0x1.00p+100");
+  EXPECT_EQ(format("%.3a", on_boundary_odd), "0x1.000p+100");
+  EXPECT_EQ(format("%.4a", on_boundary_odd), "0x1.0002p+100");  // round
+  EXPECT_EQ(format("%.5a", on_boundary_odd), "0x1.00018p+100");
+  EXPECT_EQ(format("%.6a", on_boundary_odd), "0x1.000180p+100");
+
+  // 0x1.00028000p-2
+  const double on_boundary_even = 0.250009536743164062500;
+  EXPECT_EQ(format("%.0a", on_boundary_even), "0x1p-2");
+  EXPECT_EQ(format("%.1a", on_boundary_even), "0x1.0p-2");
+  EXPECT_EQ(format("%.2a", on_boundary_even), "0x1.00p-2");
+  EXPECT_EQ(format("%.3a", on_boundary_even), "0x1.000p-2");
+  EXPECT_EQ(format("%.4a", on_boundary_even), "0x1.0002p-2");  // no round
+  EXPECT_EQ(format("%.5a", on_boundary_even), "0x1.00028p-2");
+  EXPECT_EQ(format("%.6a", on_boundary_even), "0x1.000280p-2");
+
+  // 0x1.00018001p+1
+  const double slightly_over = 2.00004577683284878730773925781250;
+  EXPECT_EQ(format("%.0a", slightly_over), "0x1p+1");
+  EXPECT_EQ(format("%.1a", slightly_over), "0x1.0p+1");
+  EXPECT_EQ(format("%.2a", slightly_over), "0x1.00p+1");
+  EXPECT_EQ(format("%.3a", slightly_over), "0x1.000p+1");
+  EXPECT_EQ(format("%.4a", slightly_over), "0x1.0002p+1");
+  EXPECT_EQ(format("%.5a", slightly_over), "0x1.00018p+1");
+  EXPECT_EQ(format("%.6a", slightly_over), "0x1.000180p+1");
+
+  // 0x1.00017fffp+0
+  const double slightly_under = 1.000022887950763106346130371093750;
+  EXPECT_EQ(format("%.0a", slightly_under), "0x1p+0");
+  EXPECT_EQ(format("%.1a", slightly_under), "0x1.0p+0");
+  EXPECT_EQ(format("%.2a", slightly_under), "0x1.00p+0");
+  EXPECT_EQ(format("%.3a", slightly_under), "0x1.000p+0");
+  EXPECT_EQ(format("%.4a", slightly_under), "0x1.0001p+0");
+  EXPECT_EQ(format("%.5a", slightly_under), "0x1.00018p+0");
+  EXPECT_EQ(format("%.6a", slightly_under), "0x1.000180p+0");
+  EXPECT_EQ(format("%.7a", slightly_under), "0x1.0001800p+0");
+
+  // 0x1.1b3829ac28058p+3
+  const double hex_value = 8.85060580848964661981881363317370414733886718750;
+  EXPECT_EQ(format("%.0a", hex_value), "0x1p+3");
+  EXPECT_EQ(format("%.1a", hex_value), "0x1.2p+3");
+  EXPECT_EQ(format("%.2a", hex_value), "0x1.1bp+3");
+  EXPECT_EQ(format("%.3a", hex_value), "0x1.1b4p+3");
+  EXPECT_EQ(format("%.4a", hex_value), "0x1.1b38p+3");
+  EXPECT_EQ(format("%.5a", hex_value), "0x1.1b383p+3");
+  EXPECT_EQ(format("%.6a", hex_value), "0x1.1b382ap+3");
+  EXPECT_EQ(format("%.7a", hex_value), "0x1.1b3829bp+3");
+  EXPECT_EQ(format("%.8a", hex_value), "0x1.1b3829acp+3");
+  EXPECT_EQ(format("%.9a", hex_value), "0x1.1b3829ac3p+3");
+  EXPECT_EQ(format("%.10a", hex_value), "0x1.1b3829ac28p+3");
+  EXPECT_EQ(format("%.11a", hex_value), "0x1.1b3829ac280p+3");
+  EXPECT_EQ(format("%.12a", hex_value), "0x1.1b3829ac2806p+3");
+  EXPECT_EQ(format("%.13a", hex_value), "0x1.1b3829ac28058p+3");
+  EXPECT_EQ(format("%.14a", hex_value), "0x1.1b3829ac280580p+3");
+  EXPECT_EQ(format("%.15a", hex_value), "0x1.1b3829ac2805800p+3");
+  EXPECT_EQ(format("%.16a", hex_value), "0x1.1b3829ac28058000p+3");
+  EXPECT_EQ(format("%.17a", hex_value), "0x1.1b3829ac280580000p+3");
+  EXPECT_EQ(format("%.18a", hex_value), "0x1.1b3829ac2805800000p+3");
+  EXPECT_EQ(format("%.19a", hex_value), "0x1.1b3829ac28058000000p+3");
+  EXPECT_EQ(format("%.20a", hex_value), "0x1.1b3829ac280580000000p+3");
+  EXPECT_EQ(format("%.21a", hex_value), "0x1.1b3829ac2805800000000p+3");
+
+  // 0x1.0818283848586p+3
+  const double hex_value2 = 8.2529488658208371987257123691961169242858886718750;
+  EXPECT_EQ(format("%.0a", hex_value2), "0x1p+3");
+  EXPECT_EQ(format("%.1a", hex_value2), "0x1.1p+3");
+  EXPECT_EQ(format("%.2a", hex_value2), "0x1.08p+3");
+  EXPECT_EQ(format("%.3a", hex_value2), "0x1.082p+3");
+  EXPECT_EQ(format("%.4a", hex_value2), "0x1.0818p+3");
+  EXPECT_EQ(format("%.5a", hex_value2), "0x1.08183p+3");
+  EXPECT_EQ(format("%.6a", hex_value2), "0x1.081828p+3");
+  EXPECT_EQ(format("%.7a", hex_value2), "0x1.0818284p+3");
+  EXPECT_EQ(format("%.8a", hex_value2), "0x1.08182838p+3");
+  EXPECT_EQ(format("%.9a", hex_value2), "0x1.081828385p+3");
+  EXPECT_EQ(format("%.10a", hex_value2), "0x1.0818283848p+3");
+  EXPECT_EQ(format("%.11a", hex_value2), "0x1.08182838486p+3");
+  EXPECT_EQ(format("%.12a", hex_value2), "0x1.081828384858p+3");
+  EXPECT_EQ(format("%.13a", hex_value2), "0x1.0818283848586p+3");
+  EXPECT_EQ(format("%.14a", hex_value2), "0x1.08182838485860p+3");
+  EXPECT_EQ(format("%.15a", hex_value2), "0x1.081828384858600p+3");
+  EXPECT_EQ(format("%.16a", hex_value2), "0x1.0818283848586000p+3");
+  EXPECT_EQ(format("%.17a", hex_value2), "0x1.08182838485860000p+3");
+  EXPECT_EQ(format("%.18a", hex_value2), "0x1.081828384858600000p+3");
+  EXPECT_EQ(format("%.19a", hex_value2), "0x1.0818283848586000000p+3");
+  EXPECT_EQ(format("%.20a", hex_value2), "0x1.08182838485860000000p+3");
+  EXPECT_EQ(format("%.21a", hex_value2), "0x1.081828384858600000000p+3");
+}
+
+TEST_F(FormatConvertTest, LongDoubleRoundA) {
+  if (std::numeric_limits<long double>::digits % 4 != 0) {
+    // This test doesn't really make sense to run on platforms where a long
+    // double has a different mantissa size (mod 4) than Prod, since then the
+    // leading digit will be formatted differently.
+    return;
+  }
+  const NativePrintfTraits &native_traits = VerifyNativeImplementation();
+  std::string s;
+  const auto format = [&](const char *fmt, long double d) -> std::string & {
+    s.clear();
+    FormatArgImpl args[1] = {FormatArgImpl(d)};
+    AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));
+    if (native_traits.hex_float_has_glibc_rounding &&
+        native_traits.hex_float_optimizes_leading_digit_bit_count) {
+      EXPECT_EQ(StrPrint(fmt, d), s);
+    }
+    return s;
+  };
+
+  // 0x8.8p+4
+  const long double on_boundary_even = 136.0;
+  EXPECT_EQ(format("%.0La", on_boundary_even), "0x8p+4");
+  EXPECT_EQ(format("%.1La", on_boundary_even), "0x8.8p+4");
+  EXPECT_EQ(format("%.2La", on_boundary_even), "0x8.80p+4");
+  EXPECT_EQ(format("%.3La", on_boundary_even), "0x8.800p+4");
+  EXPECT_EQ(format("%.4La", on_boundary_even), "0x8.8000p+4");
+  EXPECT_EQ(format("%.5La", on_boundary_even), "0x8.80000p+4");
+  EXPECT_EQ(format("%.6La", on_boundary_even), "0x8.800000p+4");
+
+  // 0x9.8p+4
+  const long double on_boundary_odd = 152.0;
+  EXPECT_EQ(format("%.0La", on_boundary_odd), "0xap+4");
+  EXPECT_EQ(format("%.1La", on_boundary_odd), "0x9.8p+4");
+  EXPECT_EQ(format("%.2La", on_boundary_odd), "0x9.80p+4");
+  EXPECT_EQ(format("%.3La", on_boundary_odd), "0x9.800p+4");
+  EXPECT_EQ(format("%.4La", on_boundary_odd), "0x9.8000p+4");
+  EXPECT_EQ(format("%.5La", on_boundary_odd), "0x9.80000p+4");
+  EXPECT_EQ(format("%.6La", on_boundary_odd), "0x9.800000p+4");
+
+  // 0x8.80001p+24
+  const long double slightly_over = 142606352.0;
+  EXPECT_EQ(format("%.0La", slightly_over), "0x9p+24");
+  EXPECT_EQ(format("%.1La", slightly_over), "0x8.8p+24");
+  EXPECT_EQ(format("%.2La", slightly_over), "0x8.80p+24");
+  EXPECT_EQ(format("%.3La", slightly_over), "0x8.800p+24");
+  EXPECT_EQ(format("%.4La", slightly_over), "0x8.8000p+24");
+  EXPECT_EQ(format("%.5La", slightly_over), "0x8.80001p+24");
+  EXPECT_EQ(format("%.6La", slightly_over), "0x8.800010p+24");
+
+  // 0x8.7ffffp+24
+  const long double slightly_under = 142606320.0;
+  EXPECT_EQ(format("%.0La", slightly_under), "0x8p+24");
+  EXPECT_EQ(format("%.1La", slightly_under), "0x8.8p+24");
+  EXPECT_EQ(format("%.2La", slightly_under), "0x8.80p+24");
+  EXPECT_EQ(format("%.3La", slightly_under), "0x8.800p+24");
+  EXPECT_EQ(format("%.4La", slightly_under), "0x8.8000p+24");
+  EXPECT_EQ(format("%.5La", slightly_under), "0x8.7ffffp+24");
+  EXPECT_EQ(format("%.6La", slightly_under), "0x8.7ffff0p+24");
+  EXPECT_EQ(format("%.7La", slightly_under), "0x8.7ffff00p+24");
+
+  // 0xc.0828384858688000p+128
+  const long double eights = 4094231060438608800781871108094404067328.0;
+  EXPECT_EQ(format("%.0La", eights), "0xcp+128");
+  EXPECT_EQ(format("%.1La", eights), "0xc.1p+128");
+  EXPECT_EQ(format("%.2La", eights), "0xc.08p+128");
+  EXPECT_EQ(format("%.3La", eights), "0xc.083p+128");
+  EXPECT_EQ(format("%.4La", eights), "0xc.0828p+128");
+  EXPECT_EQ(format("%.5La", eights), "0xc.08284p+128");
+  EXPECT_EQ(format("%.6La", eights), "0xc.082838p+128");
+  EXPECT_EQ(format("%.7La", eights), "0xc.0828385p+128");
+  EXPECT_EQ(format("%.8La", eights), "0xc.08283848p+128");
+  EXPECT_EQ(format("%.9La", eights), "0xc.082838486p+128");
+  EXPECT_EQ(format("%.10La", eights), "0xc.0828384858p+128");
+  EXPECT_EQ(format("%.11La", eights), "0xc.08283848587p+128");
+  EXPECT_EQ(format("%.12La", eights), "0xc.082838485868p+128");
+  EXPECT_EQ(format("%.13La", eights), "0xc.0828384858688p+128");
+  EXPECT_EQ(format("%.14La", eights), "0xc.08283848586880p+128");
+  EXPECT_EQ(format("%.15La", eights), "0xc.082838485868800p+128");
+  EXPECT_EQ(format("%.16La", eights), "0xc.0828384858688000p+128");
+}
+
+// We don't actually store the results. This is just to exercise the rest of the
+// machinery.
+struct NullSink {
+  friend void AbslFormatFlush(NullSink *sink, string_view str) {}
+};
+
+template <typename... T>
+bool FormatWithNullSink(absl::string_view fmt, const T &... a) {
+  NullSink sink;
+  FormatArgImpl args[] = {FormatArgImpl(a)...};
+  return FormatUntyped(&sink, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));
+}
+
+TEST_F(FormatConvertTest, ExtremeWidthPrecision) {
+  for (const char *fmt : {"f"}) {
+    for (double d : {1e-100, 1.0, 1e100}) {
+      constexpr int max = std::numeric_limits<int>::max();
+      EXPECT_TRUE(FormatWithNullSink(std::string("%.*") + fmt, max, d));
+      EXPECT_TRUE(FormatWithNullSink(std::string("%1.*") + fmt, max, d));
+      EXPECT_TRUE(FormatWithNullSink(std::string("%*") + fmt, max, d));
+      EXPECT_TRUE(FormatWithNullSink(std::string("%*.*") + fmt, max, max, d));
+    }
+  }
 }
 
 TEST_F(FormatConvertTest, LongDouble) {
-  const char *const kFormats[] = {"%",    "%.3", "%8.5", "%9",
+#ifdef _MSC_VER
+  // MSVC has a different rounding policy than us so we can't test our
+  // implementation against the native one there.
+  return;
+#endif  // _MSC_VER
+  const NativePrintfTraits &native_traits = VerifyNativeImplementation();
+  const char *const kFormats[] = {"%",    "%.3", "%8.5", "%9",  "%.5000",
                                   "%.60", "%+",  "% ",   "%-10"};
 
-  // This value is not representable in double, but it is in long double that
-  // uses the extended format.
-  // This is to verify that we are not truncating the value mistakenly through a
-  // double.
-  long double very_precise = 10000000000000000.25L;
-
   std::vector<long double> doubles = {
       0.0,
       -0.0,
-      very_precise,
-      1 / very_precise,
       std::numeric_limits<long double>::max(),
       -std::numeric_limits<long double>::max(),
       std::numeric_limits<long double>::min(),
@@ -496,28 +1088,65 @@
       std::numeric_limits<long double>::infinity(),
       -std::numeric_limits<long double>::infinity()};
 
+  for (long double base : {1.L, 12.L, 123.L, 1234.L, 12345.L, 123456.L,
+                           1234567.L, 12345678.L, 123456789.L, 1234567890.L,
+                           12345678901.L, 123456789012.L, 1234567890123.L,
+                           // This value is not representable in double, but it
+                           // is in long double that uses the extended format.
+                           // This is to verify that we are not truncating the
+                           // value mistakenly through a double.
+                           10000000000000000.25L}) {
+    for (int exp : {-1000, -500, 0, 500, 1000}) {
+      for (int sign : {1, -1}) {
+        doubles.push_back(sign * std::ldexp(base, exp));
+        doubles.push_back(sign / std::ldexp(base, exp));
+      }
+    }
+  }
+
+  // Regression tests
+  //
+  // Using a string literal because not all platforms support hex literals or it
+  // might be out of range.
+  doubles.push_back(std::strtold("-0xf.ffffffb5feafffbp-16324L", nullptr));
+
   for (const char *fmt : kFormats) {
     for (char f : {'f', 'F',  //
                    'g', 'G',  //
                    'a', 'A',  //
                    'e', 'E'}) {
       std::string fmt_str = std::string(fmt) + 'L' + f;
+
+      if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F' &&
+          f != 'a' && f != 'A') {
+        // This particular test takes way too long with snprintf.
+        // Disable for the case we are not implementing natively.
+        continue;
+      }
+
+      if (f == 'a' || f == 'A') {
+        if (!native_traits.hex_float_has_glibc_rounding ||
+            !native_traits.hex_float_optimizes_leading_digit_bit_count) {
+          continue;
+        }
+      }
+
       for (auto d : doubles) {
         FormatArgImpl arg(d);
         UntypedFormatSpecImpl format(fmt_str);
         // We use ASSERT_EQ here because failures are usually correlated and a
         // bug would print way too many failed expectations causing the test to
         // time out.
-        ASSERT_EQ(StrPrint(fmt_str.c_str(), d),
-                  FormatPack(format, {&arg, 1}))
+        ASSERT_EQ(StrPrint(fmt_str.c_str(), d), FormatPack(format, {&arg, 1}))
             << fmt_str << " " << StrPrint("%.18Lg", d) << " "
-            << StrPrint("%.999Lf", d);
+            << StrPrint("%La", d) << " " << StrPrint("%.1080Lf", d);
       }
     }
   }
 }
 
-TEST_F(FormatConvertTest, IntAsFloat) {
+TEST_F(FormatConvertTest, IntAsDouble) {
+  const NativePrintfTraits &native_traits = VerifyNativeImplementation();
   const int kMin = std::numeric_limits<int>::min();
   const int kMax = std::numeric_limits<int>::max();
   const int ia[] = {
@@ -533,14 +1162,17 @@
       const char *fmt;
     };
     const double dx = static_cast<double>(fx);
-    const Expectation kExpect[] = {
-      { __LINE__, StrPrint("%f", dx), "%f" },
-      { __LINE__, StrPrint("%12f", dx), "%12f" },
-      { __LINE__, StrPrint("%.12f", dx), "%.12f" },
-      { __LINE__, StrPrint("%12a", dx), "%12a" },
-      { __LINE__, StrPrint("%.12a", dx), "%.12a" },
+    std::vector<Expectation> expect = {
+        {__LINE__, StrPrint("%f", dx), "%f"},
+        {__LINE__, StrPrint("%12f", dx), "%12f"},
+        {__LINE__, StrPrint("%.12f", dx), "%.12f"},
+        {__LINE__, StrPrint("%.12a", dx), "%.12a"},
     };
-    for (const Expectation &e : kExpect) {
+    if (native_traits.hex_float_uses_minimal_precision_when_not_specified) {
+      Expectation ex = {__LINE__, StrPrint("%12a", dx), "%12a"};
+      expect.push_back(ex);
+    }
+    for (const Expectation &e : expect) {
       SCOPED_TRACE(e.line);
       SCOPED_TRACE(e.fmt);
       UntypedFormatSpecImpl format(e.fmt);
@@ -585,6 +1217,26 @@
   EXPECT_TRUE(FormatFails("%*d", ""));
 }
 
+// Sanity check to make sure that we are testing what we think we're testing on
+// e.g. the x86_64+glibc platform.
+TEST_F(FormatConvertTest, GlibcHasCorrectTraits) {
+#if !defined(__GLIBC__) || !defined(__x86_64__)
+  return;
+#endif
+  const NativePrintfTraits &native_traits = VerifyNativeImplementation();
+  // If one of the following tests break then it is either because the above PP
+  // macro guards failed to exclude a new platform (likely) or because something
+  // has changed in the implemention of glibc sprintf float formatting behavior.
+  // If the latter, then the code that computes these flags needs to be
+  // revisited and/or possibly the StrFormat implementation.
+  EXPECT_TRUE(native_traits.hex_float_has_glibc_rounding);
+  EXPECT_TRUE(native_traits.hex_float_prefers_denormal_repr);
+  EXPECT_TRUE(
+      native_traits.hex_float_uses_minimal_precision_when_not_specified);
+  EXPECT_TRUE(native_traits.hex_float_optimizes_leading_digit_bit_count);
+}
+
 }  // namespace
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/extension.cc b/absl/strings/internal/str_format/extension.cc
index d7f5815..bb0d96c 100644
--- a/absl/strings/internal/str_format/extension.cc
+++ b/absl/strings/internal/str_format/extension.cc
@@ -20,38 +20,8 @@
 #include <string>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
-namespace {
-// clang-format off
-#define ABSL_LENGTH_MODS_EXPAND_ \
-  X_VAL(h) X_SEP \
-  X_VAL(hh) X_SEP \
-  X_VAL(l) X_SEP \
-  X_VAL(ll) X_SEP \
-  X_VAL(L) X_SEP \
-  X_VAL(j) X_SEP \
-  X_VAL(z) X_SEP \
-  X_VAL(t) X_SEP \
-  X_VAL(q)
-// clang-format on
-}  // namespace
-
-const LengthMod::Spec LengthMod::kSpecs[] = {
-#define X_VAL(id) { LengthMod::id, #id, strlen(#id) }
-#define X_SEP ,
-    ABSL_LENGTH_MODS_EXPAND_, {LengthMod::none, "", 0}
-#undef X_VAL
-#undef X_SEP
-};
-
-const ConversionChar::Spec ConversionChar::kSpecs[] = {
-#define X_VAL(id) { ConversionChar::id, #id[0] }
-#define X_SEP ,
-    ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP),
-    {ConversionChar::none, '\0'},
-#undef X_VAL
-#undef X_SEP
-};
 
 std::string Flags::ToString() const {
   std::string s;
@@ -63,22 +33,43 @@
   return s;
 }
 
-const size_t LengthMod::kNumValues;
+#define ABSL_INTERNAL_X_VAL(id) \
+  constexpr absl::FormatConversionChar FormatConversionCharInternal::id;
+ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
+#undef ABSL_INTERNAL_X_VAL
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr absl::FormatConversionChar FormatConversionCharInternal::kNone;
 
-const size_t ConversionChar::kNumValues;
+#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
+  constexpr FormatConversionCharSet FormatConversionCharSetInternal::c;
+ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
+#undef ABSL_INTERNAL_CHAR_SET_CASE
 
-bool FormatSinkImpl::PutPaddedString(string_view v, int w, int p, bool l) {
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kStar;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kIntegral;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kFloating;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kNumeric;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kPointer;
+
+bool FormatSinkImpl::PutPaddedString(string_view value, int width,
+                                     int precision, bool left) {
   size_t space_remaining = 0;
-  if (w >= 0) space_remaining = w;
-  size_t n = v.size();
-  if (p >= 0) n = std::min(n, static_cast<size_t>(p));
-  string_view shown(v.data(), n);
+  if (width >= 0) space_remaining = width;
+  size_t n = value.size();
+  if (precision >= 0) n = std::min(n, static_cast<size_t>(precision));
+  string_view shown(value.data(), n);
   space_remaining = Excess(shown.size(), space_remaining);
-  if (!l) Append(space_remaining, ' ');
+  if (!left) Append(space_remaining, ' ');
   Append(shown);
-  if (l) Append(space_remaining, ' ');
+  if (left) Append(space_remaining, ' ');
   return true;
 }
 
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h
index eb81f8a..a9b9e13 100644
--- a/absl/strings/internal/str_format/extension.h
+++ b/absl/strings/internal/str_format/extension.h
@@ -17,17 +17,22 @@
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
 
 #include <limits.h>
+
 #include <cstddef>
 #include <cstring>
 #include <ostream>
 
+#include "absl/base/config.h"
 #include "absl/base/port.h"
+#include "absl/meta/type_traits.h"
 #include "absl/strings/internal/str_format/output.h"
 #include "absl/strings/string_view.h"
 
-class Cord;
-
 namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+enum class FormatConversionChar : uint8_t;
+enum class FormatConversionCharSet : uint64_t;
 
 namespace str_format_internal {
 
@@ -102,7 +107,7 @@
   size_t size() const { return size_; }
 
   // Put 'v' to 'sink' with specified width, precision, and left flag.
-  bool PutPaddedString(string_view v, int w, int p, bool l);
+  bool PutPaddedString(string_view v, int width, int precision, bool left);
 
   template <typename T>
   T Wrap() {
@@ -136,58 +141,10 @@
   }
 };
 
-struct LengthMod {
- public:
-  enum Id : uint8_t {
-    h, hh, l, ll, L, j, z, t, q, none
-  };
-  static const size_t kNumValues = none + 1;
-
-  LengthMod() : id_(none) {}
-
-  // Index into the opaque array of LengthMod enums.
-  // Requires: i < kNumValues
-  static LengthMod FromIndex(size_t i) {
-    return LengthMod(kSpecs[i].value);
-  }
-
-  static LengthMod FromId(Id id) { return LengthMod(id); }
-
-  // The length modifier std::string associated with a specified LengthMod.
-  string_view name() const {
-    const Spec& spec = kSpecs[id_];
-    return {spec.name, spec.name_length};
-  }
-
-  Id id() const { return id_; }
-
-  friend bool operator==(const LengthMod& a, const LengthMod& b) {
-    return a.id() == b.id();
-  }
-  friend bool operator!=(const LengthMod& a, const LengthMod& b) {
-    return !(a == b);
-  }
-  friend std::ostream& operator<<(std::ostream& os, const LengthMod& v) {
-    return os << v.name();
-  }
-
- private:
-  struct Spec {
-    Id value;
-    const char *name;
-    size_t name_length;
-  };
-  static const Spec kSpecs[];
-
-  explicit LengthMod(Id id) : id_(id) {}
-
-  Id id_;
-};
-
 // clang-format off
-#define ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
+#define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
   /* text */ \
-  X_VAL(c) X_SEP X_VAL(C) X_SEP X_VAL(s) X_SEP X_VAL(S) X_SEP \
+  X_VAL(c) X_SEP X_VAL(s) X_SEP \
   /* ints */ \
   X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \
   X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \
@@ -198,119 +155,119 @@
   X_VAL(n) X_SEP X_VAL(p)
 // clang-format on
 
-struct ConversionChar {
- public:
-  enum Id : uint8_t {
-    c, C, s, S,              // text
+// This type should not be referenced, it exists only to provide labels
+// internally that match the values declared in FormatConversionChar in
+// str_format.h. This is meant to allow internal libraries to use the same
+// declared interface type as the public interface
+// (absl::StrFormatConversionChar) while keeping the definition in a public
+// header.
+// Internal libraries should use the form
+// `FormatConversionCharInternal::c`, `FormatConversionCharInternal::kNone` for
+// comparisons.  Use in switch statements is not recommended due to a bug in how
+// gcc 4.9 -Wswitch handles declared but undefined enums.
+struct FormatConversionCharInternal {
+  FormatConversionCharInternal() = delete;
+
+ private:
+  // clang-format off
+  enum class Enum : uint8_t {
+    c, s,                    // text
     d, i, o, u, x, X,        // int
     f, F, e, E, g, G, a, A,  // float
     n, p,                    // misc
-    none
+    kNone
   };
-  static const size_t kNumValues = none + 1;
-
-  ConversionChar() : id_(none) {}
-
+  // clang-format on
  public:
-  // Index into the opaque array of ConversionChar enums.
-  // Requires: i < kNumValues
-  static ConversionChar FromIndex(size_t i) {
-    return ConversionChar(kSpecs[i].value);
-  }
-
-  static ConversionChar FromChar(char c) {
-    ConversionChar::Id out_id = ConversionChar::none;
-    switch (c) {
-#define X_VAL(id)                \
-  case #id[0]:                   \
-    out_id = ConversionChar::id; \
-    break;
-      ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, )
-#undef X_VAL
-      default:
-        break;
-    }
-    return ConversionChar(out_id);
-  }
-
-  static ConversionChar FromId(Id id) { return ConversionChar(id); }
-  Id id() const { return id_; }
-
-  int radix() const {
-    switch (id()) {
-      case x: case X: case a: case A: case p: return 16;
-      case o: return 8;
-      default: return 10;
-    }
-  }
-
-  bool upper() const {
-    switch (id()) {
-      case X: case F: case E: case G: case A: return true;
-      default: return false;
-    }
-  }
-
-  bool is_signed() const {
-    switch (id()) {
-      case d: case i: return true;
-      default: return false;
-    }
-  }
-
-  bool is_integral() const {
-    switch (id()) {
-      case d: case i: case u: case o: case x: case X:
-        return true;
-      default: return false;
-    }
-  }
-
-  bool is_float() const {
-    switch (id()) {
-      case a: case e: case f: case g: case A: case E: case F: case G:
-        return true;
-      default: return false;
-    }
-  }
-
-  bool IsValid() const { return id() != none; }
-
-  // The associated char.
-  char Char() const { return kSpecs[id_].name; }
-
-  friend bool operator==(const ConversionChar& a, const ConversionChar& b) {
-    return a.id() == b.id();
-  }
-  friend bool operator!=(const ConversionChar& a, const ConversionChar& b) {
-    return !(a == b);
-  }
-  friend std::ostream& operator<<(std::ostream& os, const ConversionChar& v) {
-    char c = v.Char();
-    if (!c) c = '?';
-    return os << c;
-  }
-
- private:
-  struct Spec {
-    Id value;
-    char name;
-  };
-  static const Spec kSpecs[];
-
-  explicit ConversionChar(Id id) : id_(id) {}
-
-  Id id_;
+#define ABSL_INTERNAL_X_VAL(id)              \
+  static constexpr FormatConversionChar id = \
+      static_cast<FormatConversionChar>(Enum::id);
+  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
+#undef ABSL_INTERNAL_X_VAL
+  static constexpr FormatConversionChar kNone =
+      static_cast<FormatConversionChar>(Enum::kNone);
 };
+// clang-format on
 
-class ConversionSpec {
+inline FormatConversionChar FormatConversionCharFromChar(char c) {
+  switch (c) {
+#define ABSL_INTERNAL_X_VAL(id) \
+  case #id[0]:                  \
+    return FormatConversionCharInternal::id;
+    ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
+#undef ABSL_INTERNAL_X_VAL
+  }
+  return FormatConversionCharInternal::kNone;
+}
+
+inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
+  if (c == FormatConversionCharInternal::X ||
+      c == FormatConversionCharInternal::F ||
+      c == FormatConversionCharInternal::E ||
+      c == FormatConversionCharInternal::G ||
+      c == FormatConversionCharInternal::A) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
+  if (c == FormatConversionCharInternal::a ||
+      c == FormatConversionCharInternal::e ||
+      c == FormatConversionCharInternal::f ||
+      c == FormatConversionCharInternal::g ||
+      c == FormatConversionCharInternal::A ||
+      c == FormatConversionCharInternal::E ||
+      c == FormatConversionCharInternal::F ||
+      c == FormatConversionCharInternal::G) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+inline char FormatConversionCharToChar(FormatConversionChar c) {
+  if (c == FormatConversionCharInternal::kNone) {
+    return '\0';
+
+#define ABSL_INTERNAL_X_VAL(e)                       \
+  } else if (c == FormatConversionCharInternal::e) { \
+    return #e[0];
+#define ABSL_INTERNAL_X_SEP
+  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL,
+                                         ABSL_INTERNAL_X_SEP)
+  } else {
+    return '\0';
+  }
+
+#undef ABSL_INTERNAL_X_VAL
+#undef ABSL_INTERNAL_X_SEP
+}
+
+// The associated char.
+inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
+  char c = FormatConversionCharToChar(v);
+  if (!c) c = '?';
+  return os << c;
+}
+
+struct FormatConversionSpecImplFriend;
+
+class FormatConversionSpecImpl {
  public:
-  Flags flags() const { return flags_; }
-  LengthMod length_mod() const { return length_mod_; }
-  ConversionChar conv() const {
+  // Width and precison are not specified, no flags are set.
+  bool is_basic() const { return flags_.basic; }
+  bool has_left_flag() const { return flags_.left; }
+  bool has_show_pos_flag() const { return flags_.show_pos; }
+  bool has_sign_col_flag() const { return flags_.sign_col; }
+  bool has_alt_flag() const { return flags_.alt; }
+  bool has_zero_flag() const { return flags_.zero; }
+
+  FormatConversionChar conversion_char() const {
     // Keep this field first in the struct . It generates better code when
     // accessing it when ConversionSpec is passed by value in registers.
-    static_assert(offsetof(ConversionSpec, conv_) == 0, "");
+    static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, "");
     return conv_;
   }
 
@@ -321,46 +278,36 @@
   // negative value.
   int precision() const { return precision_; }
 
-  void set_flags(Flags f) { flags_ = f; }
-  void set_length_mod(LengthMod lm) { length_mod_ = lm; }
-  void set_conv(ConversionChar c) { conv_ = c; }
-  void set_width(int w) { width_ = w; }
-  void set_precision(int p) { precision_ = p; }
-  void set_left(bool b) { flags_.left = b; }
+  template <typename T>
+  T Wrap() {
+    return T(*this);
+  }
 
  private:
-  ConversionChar conv_;
+  friend struct str_format_internal::FormatConversionSpecImplFriend;
+  FormatConversionChar conv_ = FormatConversionCharInternal::kNone;
   Flags flags_;
-  LengthMod length_mod_;
   int width_;
   int precision_;
 };
 
-constexpr uint64_t ConversionCharToConvValue(char conv) {
-  return
-#define CONV_SET_CASE(c) \
-  conv == #c[0] ? (uint64_t{1} << (1 + ConversionChar::Id::c)):
-      ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
-#undef CONV_SET_CASE
-                  conv == '*'
-          ? 1
-          : 0;
-}
-
-enum class Conv : uint64_t {
-#define CONV_SET_CASE(c) c = ConversionCharToConvValue(#c[0]),
-  ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
-#undef CONV_SET_CASE
-
-  // Used for width/precision '*' specification.
-  star = ConversionCharToConvValue('*'),
-
-  // Some predefined values:
-  integral = d | i | u | o | x | X,
-  floating = a | e | f | g | A | E | F | G,
-  numeric = integral | floating,
-  string = s,
-  pointer = p
+struct FormatConversionSpecImplFriend final {
+  static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
+    conv->flags_ = f;
+  }
+  static void SetConversionChar(FormatConversionChar c,
+                                FormatConversionSpecImpl* conv) {
+    conv->conv_ = c;
+  }
+  static void SetWidth(int w, FormatConversionSpecImpl* conv) {
+    conv->width_ = w;
+  }
+  static void SetPrecision(int p, FormatConversionSpecImpl* conv) {
+    conv->precision_ = p;
+  }
+  static std::string FlagsToString(const FormatConversionSpecImpl& spec) {
+    return spec.flags_.ToString();
+  }
 };
 
 // Type safe OR operator.
@@ -368,36 +315,104 @@
 //  1. operator| on enums makes them decay to integers and the result is an
 //     integer. We need the result to stay as an enum.
 //  2. We use "enum class" which would not work even if we accepted the decay.
-constexpr Conv operator|(Conv a, Conv b) {
-  return Conv(static_cast<uint64_t>(a) | static_cast<uint64_t>(b));
+constexpr FormatConversionCharSet FormatConversionCharSetUnion(
+    FormatConversionCharSet a) {
+  return a;
+}
+
+template <typename... CharSet>
+constexpr FormatConversionCharSet FormatConversionCharSetUnion(
+    FormatConversionCharSet a, CharSet... rest) {
+  return static_cast<FormatConversionCharSet>(
+      static_cast<uint64_t>(a) |
+      static_cast<uint64_t>(FormatConversionCharSetUnion(rest...)));
+}
+
+constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) {
+  return uint64_t{1} << (1 + static_cast<uint8_t>(c));
+}
+
+constexpr uint64_t FormatConversionCharToConvInt(char conv) {
+  return
+#define ABSL_INTERNAL_CHAR_SET_CASE(c)                                 \
+  conv == #c[0]                                                        \
+      ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \
+      :
+      ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
+#undef ABSL_INTERNAL_CHAR_SET_CASE
+                  conv == '*'
+          ? 1
+          : 0;
+}
+
+constexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) {
+  return static_cast<FormatConversionCharSet>(
+      FormatConversionCharToConvInt(conv));
+}
+
+struct FormatConversionCharSetInternal {
+#define ABSL_INTERNAL_CHAR_SET_CASE(c)         \
+  static constexpr FormatConversionCharSet c = \
+      FormatConversionCharToConvValue(#c[0]);
+  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
+#undef ABSL_INTERNAL_CHAR_SET_CASE
+
+  // Used for width/precision '*' specification.
+  static constexpr FormatConversionCharSet kStar =
+      FormatConversionCharToConvValue('*');
+
+  static constexpr FormatConversionCharSet kIntegral =
+      FormatConversionCharSetUnion(d, i, u, o, x, X);
+  static constexpr FormatConversionCharSet kFloating =
+      FormatConversionCharSetUnion(a, e, f, g, A, E, F, G);
+  static constexpr FormatConversionCharSet kNumeric =
+      FormatConversionCharSetUnion(kIntegral, kFloating);
+  static constexpr FormatConversionCharSet kPointer = p;
+};
+
+// Type safe OR operator.
+// We need this for two reasons:
+//  1. operator| on enums makes them decay to integers and the result is an
+//     integer. We need the result to stay as an enum.
+//  2. We use "enum class" which would not work even if we accepted the decay.
+constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
+                                            FormatConversionCharSet b) {
+  return FormatConversionCharSetUnion(a, b);
+}
+
+// Overloaded conversion functions to support absl::ParsedFormat.
+// Get a conversion with a single character in it.
+constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
+  return static_cast<FormatConversionCharSet>(
+      FormatConversionCharToConvValue(c));
 }
 
 // Get a conversion with a single character in it.
-constexpr Conv ConversionCharToConv(char c) {
-  return Conv(ConversionCharToConvValue(c));
+constexpr FormatConversionCharSet ToFormatConversionCharSet(
+    FormatConversionCharSet c) {
+  return c;
 }
 
+template <typename T>
+void ToFormatConversionCharSet(T) = delete;
+
 // Checks whether `c` exists in `set`.
-constexpr bool Contains(Conv set, char c) {
-  return (static_cast<uint64_t>(set) & ConversionCharToConvValue(c)) != 0;
+constexpr bool Contains(FormatConversionCharSet set, char c) {
+  return (static_cast<uint64_t>(set) &
+          static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;
 }
 
 // Checks whether all the characters in `c` are contained in `set`
-constexpr bool Contains(Conv set, Conv c) {
+constexpr bool Contains(FormatConversionCharSet set,
+                        FormatConversionCharSet c) {
   return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==
          static_cast<uint64_t>(c);
 }
 
-// Return type of the AbslFormatConvert() functions.
-// The Conv template parameter is used to inform the framework of what
-// conversion characters are supported by that AbslFormatConvert routine.
-template <Conv C>
-struct ConvertResult {
-  static constexpr Conv kConv = C;
-  bool value;
-};
-template <Conv C>
-constexpr Conv ConvertResult<C>::kConv;
+// Checks whether all the characters in `c` are contained in `set`
+constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) {
+  return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0;
+}
 
 // Return capacity - used, clipped to a minimum of 0.
 inline size_t Excess(size_t used, size_t capacity) {
@@ -406,6 +421,7 @@
 
 }  // namespace str_format_internal
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
diff --git a/absl/strings/internal/str_format/extension_test.cc b/absl/strings/internal/str_format/extension_test.cc
index 4e23fef..1c93fdb 100644
--- a/absl/strings/internal/str_format/extension_test.cc
+++ b/absl/strings/internal/str_format/extension_test.cc
@@ -19,9 +19,26 @@
 #include <random>
 #include <string>
 
-#include "absl/strings/str_format.h"
-
 #include "gtest/gtest.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+
+namespace my_namespace {
+class UserDefinedType {
+ public:
+  UserDefinedType() = default;
+
+  void Append(absl::string_view str) { value_.append(str.data(), str.size()); }
+  const std::string& Value() const { return value_; }
+
+  friend void AbslFormatFlush(UserDefinedType* x, absl::string_view str) {
+    x->Append(str);
+  }
+
+ private:
+  std::string value_;
+};
+}  // namespace my_namespace
 
 namespace {
 
@@ -63,4 +80,19 @@
     EXPECT_EQ(actual, expected);
   }
 }
+
+TEST(FormatExtensionTest, VerifyEnumEquality) {
+#define X_VAL(id)                           \
+  EXPECT_EQ(absl::FormatConversionChar::id, \
+            absl::str_format_internal::FormatConversionCharInternal::id);
+  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, );
+#undef X_VAL
+
+#define X_VAL(id)                              \
+  EXPECT_EQ(absl::FormatConversionCharSet::id, \
+            absl::str_format_internal::FormatConversionCharSetInternal::id);
+  ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, );
+#undef X_VAL
+}
+
 }  // namespace
diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc
index 9236acd..2aa41aa 100644
--- a/absl/strings/internal/str_format/float_conversion.cc
+++ b/absl/strings/internal/str_format/float_conversion.cc
@@ -1,25 +1,938 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #include "absl/strings/internal/str_format/float_conversion.h"
 
 #include <string.h>
+
 #include <algorithm>
 #include <cassert>
 #include <cmath>
+#include <limits>
 #include <string>
 
+#include "absl/base/attributes.h"
 #include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/functional/function_ref.h"
+#include "absl/meta/type_traits.h"
+#include "absl/numeric/bits.h"
+#include "absl/numeric/int128.h"
+#include "absl/strings/numbers.h"
+#include "absl/types/optional.h"
+#include "absl/types/span.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 
 namespace {
 
-char *CopyStringTo(string_view v, char *out) {
+// The code below wants to avoid heap allocations.
+// To do so it needs to allocate memory on the stack.
+// `StackArray` will allocate memory on the stack in the form of a uint32_t
+// array and call the provided callback with said memory.
+// It will allocate memory in increments of 512 bytes. We could allocate the
+// largest needed unconditionally, but that is more than we need in most of
+// cases. This way we use less stack in the common cases.
+class StackArray {
+  using Func = absl::FunctionRef<void(absl::Span<uint32_t>)>;
+  static constexpr size_t kStep = 512 / sizeof(uint32_t);
+  // 5 steps is 2560 bytes, which is enough to hold a long double with the
+  // largest/smallest exponents.
+  // The operations below will static_assert their particular maximum.
+  static constexpr size_t kNumSteps = 5;
+
+  // We do not want this function to be inlined.
+  // Otherwise the caller will allocate the stack space unnecessarily for all
+  // the variants even though it only calls one.
+  template <size_t steps>
+  ABSL_ATTRIBUTE_NOINLINE static void RunWithCapacityImpl(Func f) {
+    uint32_t values[steps * kStep]{};
+    f(absl::MakeSpan(values));
+  }
+
+ public:
+  static constexpr size_t kMaxCapacity = kStep * kNumSteps;
+
+  static void RunWithCapacity(size_t capacity, Func f) {
+    assert(capacity <= kMaxCapacity);
+    const size_t step = (capacity + kStep - 1) / kStep;
+    assert(step <= kNumSteps);
+    switch (step) {
+      case 1:
+        return RunWithCapacityImpl<1>(f);
+      case 2:
+        return RunWithCapacityImpl<2>(f);
+      case 3:
+        return RunWithCapacityImpl<3>(f);
+      case 4:
+        return RunWithCapacityImpl<4>(f);
+      case 5:
+        return RunWithCapacityImpl<5>(f);
+    }
+
+    assert(false && "Invalid capacity");
+  }
+};
+
+// Calculates `10 * (*v) + carry` and stores the result in `*v` and returns
+// the carry.
+template <typename Int>
+inline Int MultiplyBy10WithCarry(Int *v, Int carry) {
+  using BiggerInt = absl::conditional_t<sizeof(Int) == 4, uint64_t, uint128>;
+  BiggerInt tmp = 10 * static_cast<BiggerInt>(*v) + carry;
+  *v = static_cast<Int>(tmp);
+  return static_cast<Int>(tmp >> (sizeof(Int) * 8));
+}
+
+// Calculates `(2^64 * carry + *v) / 10`.
+// Stores the quotient in `*v` and returns the remainder.
+// Requires: `0 <= carry <= 9`
+inline uint64_t DivideBy10WithCarry(uint64_t *v, uint64_t carry) {
+  constexpr uint64_t divisor = 10;
+  // 2^64 / divisor = chunk_quotient + chunk_remainder / divisor
+  constexpr uint64_t chunk_quotient = (uint64_t{1} << 63) / (divisor / 2);
+  constexpr uint64_t chunk_remainder = uint64_t{} - chunk_quotient * divisor;
+
+  const uint64_t mod = *v % divisor;
+  const uint64_t next_carry = chunk_remainder * carry + mod;
+  *v = *v / divisor + carry * chunk_quotient + next_carry / divisor;
+  return next_carry % divisor;
+}
+
+// Generates the decimal representation for an integer of the form `v * 2^exp`,
+// where `v` and `exp` are both positive integers.
+// It generates the digits from the left (ie the most significant digit first)
+// to allow for direct printing into the sink.
+//
+// Requires `0 <= exp` and `exp <= numeric_limits<long double>::max_exponent`.
+class BinaryToDecimal {
+  static constexpr int ChunksNeeded(int exp) {
+    // We will left shift a uint128 by `exp` bits, so we need `128+exp` total
+    // bits. Round up to 32.
+    // See constructor for details about adding `10%` to the value.
+    return (128 + exp + 31) / 32 * 11 / 10;
+  }
+
+ public:
+  // Run the conversion for `v * 2^exp` and call `f(binary_to_decimal)`.
+  // This function will allocate enough stack space to perform the conversion.
+  static void RunConversion(uint128 v, int exp,
+                            absl::FunctionRef<void(BinaryToDecimal)> f) {
+    assert(exp > 0);
+    assert(exp <= std::numeric_limits<long double>::max_exponent);
+    static_assert(
+        static_cast<int>(StackArray::kMaxCapacity) >=
+            ChunksNeeded(std::numeric_limits<long double>::max_exponent),
+        "");
+
+    StackArray::RunWithCapacity(
+        ChunksNeeded(exp),
+        [=](absl::Span<uint32_t> input) { f(BinaryToDecimal(input, v, exp)); });
+  }
+
+  int TotalDigits() const {
+    return static_cast<int>((decimal_end_ - decimal_start_) * kDigitsPerChunk +
+                            CurrentDigits().size());
+  }
+
+  // See the current block of digits.
+  absl::string_view CurrentDigits() const {
+    return absl::string_view(digits_ + kDigitsPerChunk - size_, size_);
+  }
+
+  // Advance the current view of digits.
+  // Returns `false` when no more digits are available.
+  bool AdvanceDigits() {
+    if (decimal_start_ >= decimal_end_) return false;
+
+    uint32_t w = data_[decimal_start_++];
+    for (size_ = 0; size_ < kDigitsPerChunk; w /= 10) {
+      digits_[kDigitsPerChunk - ++size_] = w % 10 + '0';
+    }
+    return true;
+  }
+
+ private:
+  BinaryToDecimal(absl::Span<uint32_t> data, uint128 v, int exp) : data_(data) {
+    // We need to print the digits directly into the sink object without
+    // buffering them all first. To do this we need two things:
+    // - to know the total number of digits to do padding when necessary
+    // - to generate the decimal digits from the left.
+    //
+    // In order to do this, we do a two pass conversion.
+    // On the first pass we convert the binary representation of the value into
+    // a decimal representation in which each uint32_t chunk holds up to 9
+    // decimal digits.  In the second pass we take each decimal-holding-uint32_t
+    // value and generate the ascii decimal digits into `digits_`.
+    //
+    // The binary and decimal representations actually share the same memory
+    // region. As we go converting the chunks from binary to decimal we free
+    // them up and reuse them for the decimal representation. One caveat is that
+    // the decimal representation is around 7% less efficient in space than the
+    // binary one. We allocate an extra 10% memory to account for this. See
+    // ChunksNeeded for this calculation.
+    int chunk_index = exp / 32;
+    decimal_start_ = decimal_end_ = ChunksNeeded(exp);
+    const int offset = exp % 32;
+    // Left shift v by exp bits.
+    data_[chunk_index] = static_cast<uint32_t>(v << offset);
+    for (v >>= (32 - offset); v; v >>= 32)
+      data_[++chunk_index] = static_cast<uint32_t>(v);
+
+    while (chunk_index >= 0) {
+      // While we have more than one chunk available, go in steps of 1e9.
+      // `data_[chunk_index]` holds the highest non-zero binary chunk, so keep
+      // the variable updated.
+      uint32_t carry = 0;
+      for (int i = chunk_index; i >= 0; --i) {
+        uint64_t tmp = uint64_t{data_[i]} + (uint64_t{carry} << 32);
+        data_[i] = static_cast<uint32_t>(tmp / uint64_t{1000000000});
+        carry = static_cast<uint32_t>(tmp % uint64_t{1000000000});
+      }
+
+      // If the highest chunk is now empty, remove it from view.
+      if (data_[chunk_index] == 0) --chunk_index;
+
+      --decimal_start_;
+      assert(decimal_start_ != chunk_index);
+      data_[decimal_start_] = carry;
+    }
+
+    // Fill the first set of digits. The first chunk might not be complete, so
+    // handle differently.
+    for (uint32_t first = data_[decimal_start_++]; first != 0; first /= 10) {
+      digits_[kDigitsPerChunk - ++size_] = first % 10 + '0';
+    }
+  }
+
+ private:
+  static constexpr int kDigitsPerChunk = 9;
+
+  int decimal_start_;
+  int decimal_end_;
+
+  char digits_[kDigitsPerChunk];
+  int size_ = 0;
+
+  absl::Span<uint32_t> data_;
+};
+
+// Converts a value of the form `x * 2^-exp` into a sequence of decimal digits.
+// Requires `-exp < 0` and
+// `-exp >= limits<long double>::min_exponent - limits<long double>::digits`.
+class FractionalDigitGenerator {
+ public:
+  // Run the conversion for `v * 2^exp` and call `f(generator)`.
+  // This function will allocate enough stack space to perform the conversion.
+  static void RunConversion(
+      uint128 v, int exp, absl::FunctionRef<void(FractionalDigitGenerator)> f) {
+    using Limits = std::numeric_limits<long double>;
+    assert(-exp < 0);
+    assert(-exp >= Limits::min_exponent - 128);
+    static_assert(StackArray::kMaxCapacity >=
+                      (Limits::digits + 128 - Limits::min_exponent + 31) / 32,
+                  "");
+    StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32,
+                                [=](absl::Span<uint32_t> input) {
+                                  f(FractionalDigitGenerator(input, v, exp));
+                                });
+  }
+
+  // Returns true if there are any more non-zero digits left.
+  bool HasMoreDigits() const { return next_digit_ != 0 || chunk_index_ >= 0; }
+
+  // Returns true if the remainder digits are greater than 5000...
+  bool IsGreaterThanHalf() const {
+    return next_digit_ > 5 || (next_digit_ == 5 && chunk_index_ >= 0);
+  }
+  // Returns true if the remainder digits are exactly 5000...
+  bool IsExactlyHalf() const { return next_digit_ == 5 && chunk_index_ < 0; }
+
+  struct Digits {
+    int digit_before_nine;
+    int num_nines;
+  };
+
+  // Get the next set of digits.
+  // They are composed by a non-9 digit followed by a runs of zero or more 9s.
+  Digits GetDigits() {
+    Digits digits{next_digit_, 0};
+
+    next_digit_ = GetOneDigit();
+    while (next_digit_ == 9) {
+      ++digits.num_nines;
+      next_digit_ = GetOneDigit();
+    }
+
+    return digits;
+  }
+
+ private:
+  // Return the next digit.
+  int GetOneDigit() {
+    if (chunk_index_ < 0) return 0;
+
+    uint32_t carry = 0;
+    for (int i = chunk_index_; i >= 0; --i) {
+      carry = MultiplyBy10WithCarry(&data_[i], carry);
+    }
+    // If the lowest chunk is now empty, remove it from view.
+    if (data_[chunk_index_] == 0) --chunk_index_;
+    return carry;
+  }
+
+  FractionalDigitGenerator(absl::Span<uint32_t> data, uint128 v, int exp)
+      : chunk_index_(exp / 32), data_(data) {
+    const int offset = exp % 32;
+    // Right shift `v` by `exp` bits.
+    data_[chunk_index_] = static_cast<uint32_t>(v << (32 - offset));
+    v >>= offset;
+    // Make sure we don't overflow the data. We already calculated that
+    // non-zero bits fit, so we might not have space for leading zero bits.
+    for (int pos = chunk_index_; v; v >>= 32)
+      data_[--pos] = static_cast<uint32_t>(v);
+
+    // Fill next_digit_, as GetDigits expects it to be populated always.
+    next_digit_ = GetOneDigit();
+  }
+
+  int next_digit_;
+  int chunk_index_;
+  absl::Span<uint32_t> data_;
+};
+
+// Count the number of leading zero bits.
+int LeadingZeros(uint64_t v) { return countl_zero(v); }
+int LeadingZeros(uint128 v) {
+  auto high = static_cast<uint64_t>(v >> 64);
+  auto low = static_cast<uint64_t>(v);
+  return high != 0 ? countl_zero(high) : 64 + countl_zero(low);
+}
+
+// Round up the text digits starting at `p`.
+// The buffer must have an extra digit that is known to not need rounding.
+// This is done below by having an extra '0' digit on the left.
+void RoundUp(char *p) {
+  while (*p == '9' || *p == '.') {
+    if (*p == '9') *p = '0';
+    --p;
+  }
+  ++*p;
+}
+
+// Check the previous digit and round up or down to follow the round-to-even
+// policy.
+void RoundToEven(char *p) {
+  if (*p == '.') --p;
+  if (*p % 2 == 1) RoundUp(p);
+}
+
+// Simple integral decimal digit printing for values that fit in 64-bits.
+// Returns the pointer to the last written digit.
+char *PrintIntegralDigitsFromRightFast(uint64_t v, char *p) {
+  do {
+    *--p = DivideBy10WithCarry(&v, 0) + '0';
+  } while (v != 0);
+  return p;
+}
+
+// Simple integral decimal digit printing for values that fit in 128-bits.
+// Returns the pointer to the last written digit.
+char *PrintIntegralDigitsFromRightFast(uint128 v, char *p) {
+  auto high = static_cast<uint64_t>(v >> 64);
+  auto low = static_cast<uint64_t>(v);
+
+  while (high != 0) {
+    uint64_t carry = DivideBy10WithCarry(&high, 0);
+    carry = DivideBy10WithCarry(&low, carry);
+    *--p = carry + '0';
+  }
+  return PrintIntegralDigitsFromRightFast(low, p);
+}
+
+// Simple fractional decimal digit printing for values that fir in 64-bits after
+// shifting.
+// Performs rounding if necessary to fit within `precision`.
+// Returns the pointer to one after the last character written.
+char *PrintFractionalDigitsFast(uint64_t v, char *start, int exp,
+                                int precision) {
+  char *p = start;
+  v <<= (64 - exp);
+  while (precision > 0) {
+    if (!v) return p;
+    *p++ = MultiplyBy10WithCarry(&v, uint64_t{0}) + '0';
+    --precision;
+  }
+
+  // We need to round.
+  if (v < 0x8000000000000000) {
+    // We round down, so nothing to do.
+  } else if (v > 0x8000000000000000) {
+    // We round up.
+    RoundUp(p - 1);
+  } else {
+    RoundToEven(p - 1);
+  }
+
+  assert(precision == 0);
+  // Precision can only be zero here.
+  return p;
+}
+
+// Simple fractional decimal digit printing for values that fir in 128-bits
+// after shifting.
+// Performs rounding if necessary to fit within `precision`.
+// Returns the pointer to one after the last character written.
+char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
+                                int precision) {
+  char *p = start;
+  v <<= (128 - exp);
+  auto high = static_cast<uint64_t>(v >> 64);
+  auto low = static_cast<uint64_t>(v);
+
+  // While we have digits to print and `low` is not empty, do the long
+  // multiplication.
+  while (precision > 0 && low != 0) {
+    uint64_t carry = MultiplyBy10WithCarry(&low, uint64_t{0});
+    carry = MultiplyBy10WithCarry(&high, carry);
+
+    *p++ = carry + '0';
+    --precision;
+  }
+
+  // Now `low` is empty, so use a faster approach for the rest of the digits.
+  // This block is pretty much the same as the main loop for the 64-bit case
+  // above.
+  while (precision > 0) {
+    if (!high) return p;
+    *p++ = MultiplyBy10WithCarry(&high, uint64_t{0}) + '0';
+    --precision;
+  }
+
+  // We need to round.
+  if (high < 0x8000000000000000) {
+    // We round down, so nothing to do.
+  } else if (high > 0x8000000000000000 || low != 0) {
+    // We round up.
+    RoundUp(p - 1);
+  } else {
+    RoundToEven(p - 1);
+  }
+
+  assert(precision == 0);
+  // Precision can only be zero here.
+  return p;
+}
+
+struct FormatState {
+  char sign_char;
+  int precision;
+  const FormatConversionSpecImpl &conv;
+  FormatSinkImpl *sink;
+
+  // In `alt` mode (flag #) we keep the `.` even if there are no fractional
+  // digits. In non-alt mode, we strip it.
+  bool ShouldPrintDot() const { return precision != 0 || conv.has_alt_flag(); }
+};
+
+struct Padding {
+  int left_spaces;
+  int zeros;
+  int right_spaces;
+};
+
+Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
+  if (state.conv.width() < 0 ||
+      static_cast<size_t>(state.conv.width()) <= total_size) {
+    return {0, 0, 0};
+  }
+  int missing_chars = state.conv.width() - total_size;
+  if (state.conv.has_left_flag()) {
+    return {0, 0, missing_chars};
+  } else if (state.conv.has_zero_flag()) {
+    return {0, missing_chars, 0};
+  } else {
+    return {missing_chars, 0, 0};
+  }
+}
+
+void FinalPrint(const FormatState &state, absl::string_view data,
+                int padding_offset, int trailing_zeros,
+                absl::string_view data_postfix) {
+  if (state.conv.width() < 0) {
+    // No width specified. Fast-path.
+    if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+    state.sink->Append(data);
+    state.sink->Append(trailing_zeros, '0');
+    state.sink->Append(data_postfix);
+    return;
+  }
+
+  auto padding = ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) +
+                                         data.size() + data_postfix.size() +
+                                         static_cast<size_t>(trailing_zeros),
+                                     state);
+
+  state.sink->Append(padding.left_spaces, ' ');
+  if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+  // Padding in general needs to be inserted somewhere in the middle of `data`.
+  state.sink->Append(data.substr(0, padding_offset));
+  state.sink->Append(padding.zeros, '0');
+  state.sink->Append(data.substr(padding_offset));
+  state.sink->Append(trailing_zeros, '0');
+  state.sink->Append(data_postfix);
+  state.sink->Append(padding.right_spaces, ' ');
+}
+
+// Fastpath %f formatter for when the shifted value fits in a simple integral
+// type.
+// Prints `v*2^exp` with the options from `state`.
+template <typename Int>
+void FormatFFast(Int v, int exp, const FormatState &state) {
+  constexpr int input_bits = sizeof(Int) * 8;
+
+  static constexpr size_t integral_size =
+      /* in case we need to round up an extra digit */ 1 +
+      /* decimal digits for uint128 */ 40 + 1;
+  char buffer[integral_size + /* . */ 1 + /* max digits uint128 */ 128];
+  buffer[integral_size] = '.';
+  char *const integral_digits_end = buffer + integral_size;
+  char *integral_digits_start;
+  char *const fractional_digits_start = buffer + integral_size + 1;
+  char *fractional_digits_end = fractional_digits_start;
+
+  if (exp >= 0) {
+    const int total_bits = input_bits - LeadingZeros(v) + exp;
+    integral_digits_start =
+        total_bits <= 64
+            ? PrintIntegralDigitsFromRightFast(static_cast<uint64_t>(v) << exp,
+                                               integral_digits_end)
+            : PrintIntegralDigitsFromRightFast(static_cast<uint128>(v) << exp,
+                                               integral_digits_end);
+  } else {
+    exp = -exp;
+
+    integral_digits_start = PrintIntegralDigitsFromRightFast(
+        exp < input_bits ? v >> exp : 0, integral_digits_end);
+    // PrintFractionalDigits may pull a carried 1 all the way up through the
+    // integral portion.
+    integral_digits_start[-1] = '0';
+
+    fractional_digits_end =
+        exp <= 64 ? PrintFractionalDigitsFast(v, fractional_digits_start, exp,
+                                              state.precision)
+                  : PrintFractionalDigitsFast(static_cast<uint128>(v),
+                                              fractional_digits_start, exp,
+                                              state.precision);
+    // There was a carry, so include the first digit too.
+    if (integral_digits_start[-1] != '0') --integral_digits_start;
+  }
+
+  size_t size = fractional_digits_end - integral_digits_start;
+
+  // In `alt` mode (flag #) we keep the `.` even if there are no fractional
+  // digits. In non-alt mode, we strip it.
+  if (!state.ShouldPrintDot()) --size;
+  FinalPrint(state, absl::string_view(integral_digits_start, size),
+             /*padding_offset=*/0,
+             static_cast<int>(state.precision - (fractional_digits_end -
+                                                 fractional_digits_start)),
+             /*data_postfix=*/"");
+}
+
+// Slow %f formatter for when the shifted value does not fit in a uint128, and
+// `exp > 0`.
+// Prints `v*2^exp` with the options from `state`.
+// This one is guaranteed to not have fractional digits, so we don't have to
+// worry about anything after the `.`.
+void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) {
+  BinaryToDecimal::RunConversion(v, exp, [&](BinaryToDecimal btd) {
+    const size_t total_digits =
+        btd.TotalDigits() +
+        (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
+
+    const auto padding = ExtraWidthToPadding(
+        total_digits + (state.sign_char != '\0' ? 1 : 0), state);
+
+    state.sink->Append(padding.left_spaces, ' ');
+    if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+    state.sink->Append(padding.zeros, '0');
+
+    do {
+      state.sink->Append(btd.CurrentDigits());
+    } while (btd.AdvanceDigits());
+
+    if (state.ShouldPrintDot()) state.sink->Append(1, '.');
+    state.sink->Append(state.precision, '0');
+    state.sink->Append(padding.right_spaces, ' ');
+  });
+}
+
+// Slow %f formatter for when the shifted value does not fit in a uint128, and
+// `exp < 0`.
+// Prints `v*2^exp` with the options from `state`.
+// This one is guaranteed to be < 1.0, so we don't have to worry about integral
+// digits.
+void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) {
+  const size_t total_digits =
+      /* 0 */ 1 +
+      (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
+  auto padding =
+      ExtraWidthToPadding(total_digits + (state.sign_char ? 1 : 0), state);
+  padding.zeros += 1;
+  state.sink->Append(padding.left_spaces, ' ');
+  if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+  state.sink->Append(padding.zeros, '0');
+
+  if (state.ShouldPrintDot()) state.sink->Append(1, '.');
+
+  // Print digits
+  int digits_to_go = state.precision;
+
+  FractionalDigitGenerator::RunConversion(
+      v, exp, [&](FractionalDigitGenerator digit_gen) {
+        // There are no digits to print here.
+        if (state.precision == 0) return;
+
+        // We go one digit at a time, while keeping track of runs of nines.
+        // The runs of nines are used to perform rounding when necessary.
+
+        while (digits_to_go > 0 && digit_gen.HasMoreDigits()) {
+          auto digits = digit_gen.GetDigits();
+
+          // Now we have a digit and a run of nines.
+          // See if we can print them all.
+          if (digits.num_nines + 1 < digits_to_go) {
+            // We don't have to round yet, so print them.
+            state.sink->Append(1, digits.digit_before_nine + '0');
+            state.sink->Append(digits.num_nines, '9');
+            digits_to_go -= digits.num_nines + 1;
+
+          } else {
+            // We can't print all the nines, see where we have to truncate.
+
+            bool round_up = false;
+            if (digits.num_nines + 1 > digits_to_go) {
+              // We round up at a nine. No need to print them.
+              round_up = true;
+            } else {
+              // We can fit all the nines, but truncate just after it.
+              if (digit_gen.IsGreaterThanHalf()) {
+                round_up = true;
+              } else if (digit_gen.IsExactlyHalf()) {
+                // Round to even
+                round_up =
+                    digits.num_nines != 0 || digits.digit_before_nine % 2 == 1;
+              }
+            }
+
+            if (round_up) {
+              state.sink->Append(1, digits.digit_before_nine + '1');
+              --digits_to_go;
+              // The rest will be zeros.
+            } else {
+              state.sink->Append(1, digits.digit_before_nine + '0');
+              state.sink->Append(digits_to_go - 1, '9');
+              digits_to_go = 0;
+            }
+            return;
+          }
+        }
+      });
+
+  state.sink->Append(digits_to_go, '0');
+  state.sink->Append(padding.right_spaces, ' ');
+}
+
+template <typename Int>
+void FormatF(Int mantissa, int exp, const FormatState &state) {
+  if (exp >= 0) {
+    const int total_bits = sizeof(Int) * 8 - LeadingZeros(mantissa) + exp;
+
+    // Fallback to the slow stack-based approach if we can't do it in a 64 or
+    // 128 bit state.
+    if (ABSL_PREDICT_FALSE(total_bits > 128)) {
+      return FormatFPositiveExpSlow(mantissa, exp, state);
+    }
+  } else {
+    // Fallback to the slow stack-based approach if we can't do it in a 64 or
+    // 128 bit state.
+    if (ABSL_PREDICT_FALSE(exp < -128)) {
+      return FormatFNegativeExpSlow(mantissa, -exp, state);
+    }
+  }
+  return FormatFFast(mantissa, exp, state);
+}
+
+// Grab the group of four bits (nibble) from `n`. E.g., nibble 1 corresponds to
+// bits 4-7.
+template <typename Int>
+uint8_t GetNibble(Int n, int nibble_index) {
+  constexpr Int mask_low_nibble = Int{0xf};
+  int shift = nibble_index * 4;
+  n &= mask_low_nibble << shift;
+  return static_cast<uint8_t>((n >> shift) & 0xf);
+}
+
+// Add one to the given nibble, applying carry to higher nibbles. Returns true
+// if overflow, false otherwise.
+template <typename Int>
+bool IncrementNibble(int nibble_index, Int *n) {
+  constexpr int kShift = sizeof(Int) * 8 - 1;
+  constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
+  Int before = *n >> kShift;
+  // Here we essentially want to take the number 1 and move it into the requsted
+  // nibble, then add it to *n to effectively increment the nibble. However,
+  // ASan will complain if we try to shift the 1 beyond the limits of the Int,
+  // i.e., if the nibble_index is out of range. So therefore we check for this
+  // and if we are out of range we just add 0 which leaves *n unchanged, which
+  // seems like the reasonable thing to do in that case.
+  *n += ((nibble_index >= kNumNibbles) ? 0 : (Int{1} << (nibble_index * 4)));
+  Int after = *n >> kShift;
+  return (before && !after) || (nibble_index >= kNumNibbles);
+}
+
+// Return a mask with 1's in the given nibble and all lower nibbles.
+template <typename Int>
+Int MaskUpToNibbleInclusive(int nibble_index) {
+  constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
+  static const Int ones = ~Int{0};
+  return ones >> std::max(0, 4 * (kNumNibbles - nibble_index - 1));
+}
+
+// Return a mask with 1's below the given nibble.
+template <typename Int>
+Int MaskUpToNibbleExclusive(int nibble_index) {
+  return nibble_index <= 0 ? 0 : MaskUpToNibbleInclusive<Int>(nibble_index - 1);
+}
+
+template <typename Int>
+Int MoveToNibble(uint8_t nibble, int nibble_index) {
+  return Int{nibble} << (4 * nibble_index);
+}
+
+// Given mantissa size, find optimal # of mantissa bits to put in initial digit.
+//
+// In the hex representation we keep a single hex digit to the left of the dot.
+// However, the question as to how many bits of the mantissa should be put into
+// that hex digit in theory is arbitrary, but in practice it is optimal to
+// choose based on the size of the mantissa. E.g., for a `double`, there are 53
+// mantissa bits, so that means that we should put 1 bit to the left of the dot,
+// thereby leaving 52 bits to the right, which is evenly divisible by four and
+// thus all fractional digits represent actual precision. For a `long double`,
+// on the other hand, there are 64 bits of mantissa, thus we can use all four
+// bits for the initial hex digit and still have a number left over (60) that is
+// a multiple of four. Once again, the goal is to have all fractional digits
+// represent real precision.
+template <typename Float>
+constexpr int HexFloatLeadingDigitSizeInBits() {
+  return std::numeric_limits<Float>::digits % 4 > 0
+             ? std::numeric_limits<Float>::digits % 4
+             : 4;
+}
+
+// This function captures the rounding behavior of glibc for hex float
+// representations. E.g. when rounding 0x1.ab800000 to a precision of .2
+// ("%.2a") glibc will round up because it rounds toward the even number (since
+// 0xb is an odd number, it will round up to 0xc). However, when rounding at a
+// point that is not followed by 800000..., it disregards the parity and rounds
+// up if > 8 and rounds down if < 8.
+template <typename Int>
+bool HexFloatNeedsRoundUp(Int mantissa, int final_nibble_displayed,
+                          uint8_t leading) {
+  // If the last nibble (hex digit) to be displayed is the lowest on in the
+  // mantissa then that means that we don't have any further nibbles to inform
+  // rounding, so don't round.
+  if (final_nibble_displayed <= 0) {
+    return false;
+  }
+  int rounding_nibble_idx = final_nibble_displayed - 1;
+  constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+  assert(final_nibble_displayed <= kTotalNibbles);
+  Int mantissa_up_to_rounding_nibble_inclusive =
+      mantissa & MaskUpToNibbleInclusive<Int>(rounding_nibble_idx);
+  Int eight = MoveToNibble<Int>(8, rounding_nibble_idx);
+  if (mantissa_up_to_rounding_nibble_inclusive != eight) {
+    return mantissa_up_to_rounding_nibble_inclusive > eight;
+  }
+  // Nibble in question == 8.
+  uint8_t round_if_odd = (final_nibble_displayed == kTotalNibbles)
+                             ? leading
+                             : GetNibble(mantissa, final_nibble_displayed);
+  return round_if_odd % 2 == 1;
+}
+
+// Stores values associated with a Float type needed by the FormatA
+// implementation in order to avoid templatizing that function by the Float
+// type.
+struct HexFloatTypeParams {
+  template <typename Float>
+  explicit HexFloatTypeParams(Float)
+      : min_exponent(std::numeric_limits<Float>::min_exponent - 1),
+        leading_digit_size_bits(HexFloatLeadingDigitSizeInBits<Float>()) {
+    assert(leading_digit_size_bits >= 1 && leading_digit_size_bits <= 4);
+  }
+
+  int min_exponent;
+  int leading_digit_size_bits;
+};
+
+// Hex Float Rounding. First check if we need to round; if so, then we do that
+// by manipulating (incrementing) the mantissa, that way we can later print the
+// mantissa digits by iterating through them in the same way regardless of
+// whether a rounding happened.
+template <typename Int>
+void FormatARound(bool precision_specified, const FormatState &state,
+                  uint8_t *leading, Int *mantissa, int *exp) {
+  constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+  // Index of the last nibble that we could display given precision.
+  int final_nibble_displayed =
+      precision_specified ? std::max(0, (kTotalNibbles - state.precision)) : 0;
+  if (HexFloatNeedsRoundUp(*mantissa, final_nibble_displayed, *leading)) {
+    // Need to round up.
+    bool overflow = IncrementNibble(final_nibble_displayed, mantissa);
+    *leading += (overflow ? 1 : 0);
+    if (ABSL_PREDICT_FALSE(*leading > 15)) {
+      // We have overflowed the leading digit. This would mean that we would
+      // need two hex digits to the left of the dot, which is not allowed. So
+      // adjust the mantissa and exponent so that the result is always 1.0eXXX.
+      *leading = 1;
+      *mantissa = 0;
+      *exp += 4;
+    }
+  }
+  // Now that we have handled a possible round-up we can go ahead and zero out
+  // all the nibbles of the mantissa that we won't need.
+  if (precision_specified) {
+    *mantissa &= ~MaskUpToNibbleExclusive<Int>(final_nibble_displayed);
+  }
+}
+
+template <typename Int>
+void FormatANormalize(const HexFloatTypeParams float_traits, uint8_t *leading,
+                      Int *mantissa, int *exp) {
+  constexpr int kIntBits = sizeof(Int) * 8;
+  static const Int kHighIntBit = Int{1} << (kIntBits - 1);
+  const int kLeadDigitBitsCount = float_traits.leading_digit_size_bits;
+  // Normalize mantissa so that highest bit set is in MSB position, unless we
+  // get interrupted by the exponent threshold.
+  while (*mantissa && !(*mantissa & kHighIntBit)) {
+    if (ABSL_PREDICT_FALSE(*exp - 1 < float_traits.min_exponent)) {
+      *mantissa >>= (float_traits.min_exponent - *exp);
+      *exp = float_traits.min_exponent;
+      return;
+    }
+    *mantissa <<= 1;
+    --*exp;
+  }
+  // Extract bits for leading digit then shift them away leaving the
+  // fractional part.
+  *leading =
+      static_cast<uint8_t>(*mantissa >> (kIntBits - kLeadDigitBitsCount));
+  *exp -= (*mantissa != 0) ? kLeadDigitBitsCount : *exp;
+  *mantissa <<= kLeadDigitBitsCount;
+}
+
+template <typename Int>
+void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,
+             bool uppercase, const FormatState &state) {
+  // Int properties.
+  constexpr int kIntBits = sizeof(Int) * 8;
+  constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+  // Did the user specify a precision explicitly?
+  const bool precision_specified = state.conv.precision() >= 0;
+
+  // ========== Normalize/Denormalize ==========
+  exp += kIntBits;  // make all digits fractional digits.
+  // This holds the (up to four) bits of leading digit, i.e., the '1' in the
+  // number 0x1.e6fp+2. It's always > 0 unless number is zero or denormal.
+  uint8_t leading = 0;
+  FormatANormalize(float_traits, &leading, &mantissa, &exp);
+
+  // =============== Rounding ==================
+  // Check if we need to round; if so, then we do that by manipulating
+  // (incrementing) the mantissa before beginning to print characters.
+  FormatARound(precision_specified, state, &leading, &mantissa, &exp);
+
+  // ============= Format Result ===============
+  // This buffer holds the "0x1.ab1de3" portion of "0x1.ab1de3pe+2". Compute the
+  // size with long double which is the largest of the floats.
+  constexpr size_t kBufSizeForHexFloatRepr =
+      2                                               // 0x
+      + std::numeric_limits<long double>::digits / 4  // number of hex digits
+      + 1                                             // round up
+      + 1;                                            // "." (dot)
+  char digits_buffer[kBufSizeForHexFloatRepr];
+  char *digits_iter = digits_buffer;
+  const char *const digits =
+      static_cast<const char *>("0123456789ABCDEF0123456789abcdef") +
+      (uppercase ? 0 : 16);
+
+  // =============== Hex Prefix ================
+  *digits_iter++ = '0';
+  *digits_iter++ = uppercase ? 'X' : 'x';
+
+  // ========== Non-Fractional Digit ===========
+  *digits_iter++ = digits[leading];
+
+  // ================== Dot ====================
+  // There are three reasons we might need a dot. Keep in mind that, at this
+  // point, the mantissa holds only the fractional part.
+  if ((precision_specified && state.precision > 0) ||
+      (!precision_specified && mantissa > 0) || state.conv.has_alt_flag()) {
+    *digits_iter++ = '.';
+  }
+
+  // ============ Fractional Digits ============
+  int digits_emitted = 0;
+  while (mantissa > 0) {
+    *digits_iter++ = digits[GetNibble(mantissa, kTotalNibbles - 1)];
+    mantissa <<= 4;
+    ++digits_emitted;
+  }
+  int trailing_zeros =
+      precision_specified ? state.precision - digits_emitted : 0;
+  assert(trailing_zeros >= 0);
+  auto digits_result = string_view(digits_buffer, digits_iter - digits_buffer);
+
+  // =============== Exponent ==================
+  constexpr size_t kBufSizeForExpDecRepr =
+      numbers_internal::kFastToBufferSize  // requred for FastIntToBuffer
+      + 1                                  // 'p' or 'P'
+      + 1;                                 // '+' or '-'
+  char exp_buffer[kBufSizeForExpDecRepr];
+  exp_buffer[0] = uppercase ? 'P' : 'p';
+  exp_buffer[1] = exp >= 0 ? '+' : '-';
+  numbers_internal::FastIntToBuffer(exp < 0 ? -exp : exp, exp_buffer + 2);
+
+  // ============ Assemble Result ==============
+  FinalPrint(state,           //
+             digits_result,   // 0xN.NNN...
+             2,               // offset in `data` to start padding if needed.
+             trailing_zeros,  // num remaining mantissa padding zeros
+             exp_buffer);     // exponent
+}
+
+char *CopyStringTo(absl::string_view v, char *out) {
   std::memcpy(out, v.data(), v.size());
   return out + v.size();
 }
 
 template <typename Float>
-bool FallbackToSnprintf(const Float v, const ConversionSpec &conv,
+bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
                         FormatSinkImpl *sink) {
   int w = conv.width() >= 0 ? conv.width() : 0;
   int p = conv.precision() >= 0 ? conv.precision() : -1;
@@ -27,22 +940,22 @@
   {
     char *fp = fmt;
     *fp++ = '%';
-    fp = CopyStringTo(conv.flags().ToString(), fp);
+    fp = CopyStringTo(FormatConversionSpecImplFriend::FlagsToString(conv), fp);
     fp = CopyStringTo("*.*", fp);
     if (std::is_same<long double, Float>()) {
       *fp++ = 'L';
     }
-    *fp++ = conv.conv().Char();
+    *fp++ = FormatConversionCharToChar(conv.conversion_char());
     *fp = 0;
     assert(fp < fmt + sizeof(fmt));
   }
   std::string space(512, '\0');
-  string_view result;
+  absl::string_view result;
   while (true) {
     int n = snprintf(&space[0], space.size(), fmt, w, p, v);
     if (n < 0) return false;
     if (static_cast<size_t>(n) < space.size()) {
-      result = string_view(space.data(), n);
+      result = absl::string_view(space.data(), n);
       break;
     }
     space.resize(n + 1);
@@ -95,19 +1008,24 @@
 // Otherwise, return false.
 template <typename Float>
 bool ConvertNonNumericFloats(char sign_char, Float v,
-                             const ConversionSpec &conv, FormatSinkImpl *sink) {
+                             const FormatConversionSpecImpl &conv,
+                             FormatSinkImpl *sink) {
   char text[4], *ptr = text;
-  if (sign_char) *ptr++ = sign_char;
+  if (sign_char != '\0') *ptr++ = sign_char;
   if (std::isnan(v)) {
-    ptr = std::copy_n(conv.conv().upper() ? "NAN" : "nan", 3, ptr);
+    ptr = std::copy_n(
+        FormatConversionCharIsUpper(conv.conversion_char()) ? "NAN" : "nan", 3,
+        ptr);
   } else if (std::isinf(v)) {
-    ptr = std::copy_n(conv.conv().upper() ? "INF" : "inf", 3, ptr);
+    ptr = std::copy_n(
+        FormatConversionCharIsUpper(conv.conversion_char()) ? "INF" : "inf", 3,
+        ptr);
   } else {
     return false;
   }
 
   return sink->PutPaddedString(string_view(text, ptr - text), conv.width(), -1,
-                               conv.flags().left);
+                               conv.has_left_flag());
 }
 
 // Round up the last digit of the value.
@@ -167,7 +1085,12 @@
 
 template <typename Float>
 struct Decomposed {
-  Float mantissa;
+  using MantissaType =
+      absl::conditional_t<std::is_same<long double, Float>::value, uint128,
+                          uint64_t>;
+  static_assert(std::numeric_limits<Float>::digits <= sizeof(MantissaType) * 8,
+                "");
+  MantissaType mantissa;
   int exponent;
 };
 
@@ -178,7 +1101,8 @@
   Float m = std::frexp(v, &exp);
   m = std::ldexp(m, std::numeric_limits<Float>::digits);
   exp -= std::numeric_limits<Float>::digits;
-  return {m, exp};
+
+  return {static_cast<typename Decomposed<Float>::MantissaType>(m), exp};
 }
 
 // Print 'digits' as decimal.
@@ -347,31 +1271,32 @@
   return false;
 }
 
-void WriteBufferToSink(char sign_char, string_view str,
-                       const ConversionSpec &conv, FormatSinkImpl *sink) {
+void WriteBufferToSink(char sign_char, absl::string_view str,
+                       const FormatConversionSpecImpl &conv,
+                       FormatSinkImpl *sink) {
   int left_spaces = 0, zeros = 0, right_spaces = 0;
   int missing_chars =
       conv.width() >= 0 ? std::max(conv.width() - static_cast<int>(str.size()) -
                                        static_cast<int>(sign_char != 0),
                                    0)
                         : 0;
-  if (conv.flags().left) {
+  if (conv.has_left_flag()) {
     right_spaces = missing_chars;
-  } else if (conv.flags().zero) {
+  } else if (conv.has_zero_flag()) {
     zeros = missing_chars;
   } else {
     left_spaces = missing_chars;
   }
 
   sink->Append(left_spaces, ' ');
-  if (sign_char) sink->Append(1, sign_char);
+  if (sign_char != '\0') sink->Append(1, sign_char);
   sink->Append(zeros, '0');
   sink->Append(str);
   sink->Append(right_spaces, ' ');
 }
 
 template <typename Float>
-bool FloatToSink(const Float v, const ConversionSpec &conv,
+bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
                  FormatSinkImpl *sink) {
   // Print the sign or the sign column.
   Float abs_v = v;
@@ -379,9 +1304,9 @@
   if (std::signbit(abs_v)) {
     sign_char = '-';
     abs_v = -abs_v;
-  } else if (conv.flags().show_pos) {
+  } else if (conv.has_show_pos_flag()) {
     sign_char = '+';
-  } else if (conv.flags().sign_col) {
+  } else if (conv.has_sign_col_flag()) {
     sign_char = ' ';
   }
 
@@ -398,88 +1323,96 @@
 
   Buffer buffer;
 
-  switch (conv.conv().id()) {
-    case ConversionChar::f:
-    case ConversionChar::F:
-      if (!FloatToBuffer<FormatStyle::Fixed>(decomposed, precision, &buffer,
-                                             nullptr)) {
-        return FallbackToSnprintf(v, conv, sink);
-      }
-      if (!conv.flags().alt && buffer.back() == '.') buffer.pop_back();
-      break;
+  FormatConversionChar c = conv.conversion_char();
 
-    case ConversionChar::e:
-    case ConversionChar::E:
-      if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
-                                                 &exp)) {
-        return FallbackToSnprintf(v, conv, sink);
-      }
-      if (!conv.flags().alt && buffer.back() == '.') buffer.pop_back();
-      PrintExponent(exp, conv.conv().upper() ? 'E' : 'e', &buffer);
-      break;
-
-    case ConversionChar::g:
-    case ConversionChar::G:
-      precision = std::max(0, precision - 1);
-      if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
-                                                 &exp)) {
-        return FallbackToSnprintf(v, conv, sink);
-      }
-      if (precision + 1 > exp && exp >= -4) {
-        if (exp < 0) {
-          // Have 1.23456, needs 0.00123456
-          // Move the first digit
-          buffer.begin[1] = *buffer.begin;
-          // Add some zeros
-          for (; exp < -1; ++exp) *buffer.begin-- = '0';
-          *buffer.begin-- = '.';
-          *buffer.begin = '0';
-        } else if (exp > 0) {
-          // Have 1.23456, needs 1234.56
-          // Move the '.' exp positions to the right.
-          std::rotate(buffer.begin + 1, buffer.begin + 2,
-                      buffer.begin + exp + 2);
-        }
-        exp = 0;
-      }
-      if (!conv.flags().alt) {
-        while (buffer.back() == '0') buffer.pop_back();
-        if (buffer.back() == '.') buffer.pop_back();
-      }
-      if (exp) PrintExponent(exp, conv.conv().upper() ? 'E' : 'e', &buffer);
-      break;
-
-    case ConversionChar::a:
-    case ConversionChar::A:
+  if (c == FormatConversionCharInternal::f ||
+      c == FormatConversionCharInternal::F) {
+    FormatF(decomposed.mantissa, decomposed.exponent,
+            {sign_char, precision, conv, sink});
+    return true;
+  } else if (c == FormatConversionCharInternal::e ||
+             c == FormatConversionCharInternal::E) {
+    if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
+                                               &exp)) {
       return FallbackToSnprintf(v, conv, sink);
-
-    default:
-      return false;
+    }
+    if (!conv.has_alt_flag() && buffer.back() == '.') buffer.pop_back();
+    PrintExponent(
+        exp, FormatConversionCharIsUpper(conv.conversion_char()) ? 'E' : 'e',
+        &buffer);
+  } else if (c == FormatConversionCharInternal::g ||
+             c == FormatConversionCharInternal::G) {
+    precision = std::max(0, precision - 1);
+    if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
+                                               &exp)) {
+      return FallbackToSnprintf(v, conv, sink);
+    }
+    if (precision + 1 > exp && exp >= -4) {
+      if (exp < 0) {
+        // Have 1.23456, needs 0.00123456
+        // Move the first digit
+        buffer.begin[1] = *buffer.begin;
+        // Add some zeros
+        for (; exp < -1; ++exp) *buffer.begin-- = '0';
+        *buffer.begin-- = '.';
+        *buffer.begin = '0';
+      } else if (exp > 0) {
+        // Have 1.23456, needs 1234.56
+        // Move the '.' exp positions to the right.
+        std::rotate(buffer.begin + 1, buffer.begin + 2, buffer.begin + exp + 2);
+      }
+      exp = 0;
+    }
+    if (!conv.has_alt_flag()) {
+      while (buffer.back() == '0') buffer.pop_back();
+      if (buffer.back() == '.') buffer.pop_back();
+    }
+    if (exp) {
+      PrintExponent(
+          exp, FormatConversionCharIsUpper(conv.conversion_char()) ? 'E' : 'e',
+          &buffer);
+    }
+  } else if (c == FormatConversionCharInternal::a ||
+             c == FormatConversionCharInternal::A) {
+    bool uppercase = (c == FormatConversionCharInternal::A);
+    FormatA(HexFloatTypeParams(Float{}), decomposed.mantissa,
+            decomposed.exponent, uppercase, {sign_char, precision, conv, sink});
+    return true;
+  } else {
+    return false;
   }
 
   WriteBufferToSink(sign_char,
-                    string_view(buffer.begin, buffer.end - buffer.begin), conv,
-                    sink);
+                    absl::string_view(buffer.begin, buffer.end - buffer.begin),
+                    conv, sink);
 
   return true;
 }
 
 }  // namespace
 
-bool ConvertFloatImpl(long double v, const ConversionSpec &conv,
+bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
                       FormatSinkImpl *sink) {
+  if (std::numeric_limits<long double>::digits ==
+      2 * std::numeric_limits<double>::digits) {
+    // This is the `double-double` representation of `long double`.
+    // We do not handle it natively. Fallback to snprintf.
+    return FallbackToSnprintf(v, conv, sink);
+  }
+
   return FloatToSink(v, conv, sink);
 }
 
-bool ConvertFloatImpl(float v, const ConversionSpec &conv,
+bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,
                       FormatSinkImpl *sink) {
-  return FloatToSink(v, conv, sink);
+  return FloatToSink(static_cast<double>(v), conv, sink);
 }
 
-bool ConvertFloatImpl(double v, const ConversionSpec &conv,
+bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
                       FormatSinkImpl *sink) {
   return FloatToSink(v, conv, sink);
 }
 
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/float_conversion.h b/absl/strings/internal/str_format/float_conversion.h
index 8ba5566..71100e7 100644
--- a/absl/strings/internal/str_format/float_conversion.h
+++ b/absl/strings/internal/str_format/float_conversion.h
@@ -1,21 +1,37 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
 
 #include "absl/strings/internal/str_format/extension.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 
-bool ConvertFloatImpl(float v, const ConversionSpec &conv,
+bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,
                       FormatSinkImpl *sink);
 
-bool ConvertFloatImpl(double v, const ConversionSpec &conv,
+bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
                       FormatSinkImpl *sink);
 
-bool ConvertFloatImpl(long double v, const ConversionSpec &conv,
+bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
                       FormatSinkImpl *sink);
 
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
diff --git a/absl/strings/internal/str_format/output.cc b/absl/strings/internal/str_format/output.cc
index 38987b6..c4b2470 100644
--- a/absl/strings/internal/str_format/output.cc
+++ b/absl/strings/internal/str_format/output.cc
@@ -18,6 +18,7 @@
 #include <cstring>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 
 namespace {
@@ -67,4 +68,5 @@
 }
 
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/output.h b/absl/strings/internal/str_format/output.h
index 42da641..8030dae 100644
--- a/absl/strings/internal/str_format/output.h
+++ b/absl/strings/internal/str_format/output.h
@@ -28,9 +28,8 @@
 #include "absl/base/port.h"
 #include "absl/strings/string_view.h"
 
-class Cord;
-
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 
 // RawSink implementation that writes into a char* buffer.
@@ -75,12 +74,6 @@
   out->write(s.data(), s.size());
 }
 
-template <class AbslCord, typename = typename std::enable_if<
-                              std::is_same<AbslCord, ::Cord>::value>::type>
-inline void AbslFormatFlush(AbslCord* out, string_view s) {
-  out->Append(s);
-}
-
 inline void AbslFormatFlush(FILERawSink* sink, string_view v) {
   sink->Write(v);
 }
@@ -89,13 +82,15 @@
   sink->Write(v);
 }
 
+// This is a SFINAE to get a better compiler error message when the type
+// is not supported.
 template <typename T>
-auto InvokeFlush(T* out, string_view s)
-    -> decltype(str_format_internal::AbslFormatFlush(out, s)) {
-  str_format_internal::AbslFormatFlush(out, s);
+auto InvokeFlush(T* out, string_view s) -> decltype(AbslFormatFlush(out, s)) {
+  AbslFormatFlush(out, s);
 }
 
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
diff --git a/absl/strings/internal/str_format/output_test.cc b/absl/strings/internal/str_format/output_test.cc
index 6e04abe..ce2e91a 100644
--- a/absl/strings/internal/str_format/output_test.cc
+++ b/absl/strings/internal/str_format/output_test.cc
@@ -19,8 +19,10 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/strings/cord.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 TEST(InvokeFlush, String) {
@@ -36,6 +38,12 @@
   EXPECT_EQ(str.str(), "ABCDEF");
 }
 
+TEST(InvokeFlush, Cord) {
+  absl::Cord str("ABC");
+  str_format_internal::InvokeFlush(&str, "DEF");
+  EXPECT_EQ(str, "ABCDEF");
+}
+
 TEST(BufferRawSink, Limits) {
   char buf[16];
   {
@@ -67,5 +75,5 @@
 }
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
-
diff --git a/absl/strings/internal/str_format/parser.cc b/absl/strings/internal/str_format/parser.cc
index 9ef5615..f308d02 100644
--- a/absl/strings/internal/str_format/parser.cc
+++ b/absl/strings/internal/str_format/parser.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #include "absl/strings/internal/str_format/parser.h"
 
 #include <assert.h>
@@ -14,10 +28,12 @@
 #include <unordered_set>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 
-using CC = ConversionChar::Id;
-using LM = LengthMod::Id;
+using CC = FormatConversionCharInternal;
+using LM = LengthMod;
+
 ABSL_CONST_INIT const ConvTag kTags[256] = {
     {},    {},    {},    {},    {},    {},    {},    {},     // 00-07
     {},    {},    {},    {},    {},    {},    {},    {},     // 08-0f
@@ -27,9 +43,9 @@
     {},    {},    {},    {},    {},    {},    {},    {},     // 28-2f
     {},    {},    {},    {},    {},    {},    {},    {},     // 30-37
     {},    {},    {},    {},    {},    {},    {},    {},     // 38-3f
-    {},    CC::A, {},    CC::C, {},    CC::E, CC::F, CC::G,  // @ABCDEFG
+    {},    CC::A, {},    {},    {},    CC::E, CC::F, CC::G,  // @ABCDEFG
     {},    {},    {},    {},    LM::L, {},    {},    {},     // HIJKLMNO
-    {},    {},    {},    CC::S, {},    {},    {},    {},     // PQRSTUVW
+    {},    {},    {},    {},    {},    {},    {},    {},     // PQRSTUVW
     CC::X, {},    {},    {},    {},    {},    {},    {},     // XYZ[\]^_
     {},    CC::a, {},    CC::c, CC::d, CC::e, CC::f, CC::g,  // `abcdefg
     LM::h, CC::i, LM::j, {},    LM::l, {},    CC::n, CC::o,  // hijklmno
@@ -204,11 +220,11 @@
     using str_format_internal::LengthMod;
     LengthMod length_mod = tag.as_length();
     ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
-    if (c == 'h' && length_mod.id() == LengthMod::h) {
-      conv->length_mod = LengthMod::FromId(LengthMod::hh);
+    if (c == 'h' && length_mod == LengthMod::h) {
+      conv->length_mod = LengthMod::hh;
       ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
-    } else if (c == 'l' && length_mod.id() == LengthMod::l) {
-      conv->length_mod = LengthMod::FromId(LengthMod::ll);
+    } else if (c == 'l' && length_mod == LengthMod::l) {
+      conv->length_mod = LengthMod::ll;
       ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
     } else {
       conv->length_mod = length_mod;
@@ -227,6 +243,32 @@
 
 }  // namespace
 
+std::string LengthModToString(LengthMod v) {
+  switch (v) {
+    case LengthMod::h:
+      return "h";
+    case LengthMod::hh:
+      return "hh";
+    case LengthMod::l:
+      return "l";
+    case LengthMod::ll:
+      return "ll";
+    case LengthMod::L:
+      return "L";
+    case LengthMod::j:
+      return "j";
+    case LengthMod::z:
+      return "z";
+    case LengthMod::t:
+      return "t";
+    case LengthMod::q:
+      return "q";
+    case LengthMod::none:
+      return "";
+  }
+  return "";
+}
+
 const char *ConsumeUnboundConversion(const char *p, const char *end,
                                      UnboundConversion *conv, int *next_arg) {
   if (*next_arg < 0) return ConsumeConversion<true>(p, end, conv, next_arg);
@@ -268,15 +310,17 @@
   char* data_pos;
 };
 
-ParsedFormatBase::ParsedFormatBase(string_view format, bool allow_ignored,
-                                   std::initializer_list<Conv> convs)
+ParsedFormatBase::ParsedFormatBase(
+    string_view format, bool allow_ignored,
+    std::initializer_list<FormatConversionCharSet> convs)
     : data_(format.empty() ? nullptr : new char[format.size()]) {
   has_error_ = !ParseFormatString(format, ParsedFormatConsumer(this)) ||
                !MatchesConversions(allow_ignored, convs);
 }
 
 bool ParsedFormatBase::MatchesConversions(
-    bool allow_ignored, std::initializer_list<Conv> convs) const {
+    bool allow_ignored,
+    std::initializer_list<FormatConversionCharSet> convs) const {
   std::unordered_set<int> used;
   auto add_if_valid_conv = [&](int pos, char c) {
       if (static_cast<size_t>(pos) > convs.size() ||
@@ -294,10 +338,13 @@
     if (conv.width.is_from_arg() &&
         !add_if_valid_conv(conv.width.get_from_arg(), '*'))
       return false;
-    if (!add_if_valid_conv(conv.arg_position, conv.conv.Char())) return false;
+    if (!add_if_valid_conv(conv.arg_position,
+                           FormatConversionCharToChar(conv.conv)))
+      return false;
   }
   return used.size() == convs.size() || allow_ignored;
 }
 
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_format/parser.h b/absl/strings/internal/str_format/parser.h
index b7614a0..6504dd3 100644
--- a/absl/strings/internal/str_format/parser.h
+++ b/absl/strings/internal/str_format/parser.h
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
 
@@ -6,18 +20,25 @@
 #include <stdlib.h>
 
 #include <cassert>
+#include <cstdint>
 #include <initializer_list>
 #include <iosfwd>
 #include <iterator>
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "absl/strings/internal/str_format/checker.h"
 #include "absl/strings/internal/str_format/extension.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 
+enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };
+
+std::string LengthModToString(LengthMod v);
+
 // The analyzed properties of a single specified conversion.
 struct UnboundConversion {
   UnboundConversion()
@@ -59,8 +80,8 @@
   InputValue precision;
 
   Flags flags;
-  LengthMod length_mod;
-  ConversionChar conv;
+  LengthMod length_mod = LengthMod::none;
+  FormatConversionChar conv = FormatConversionCharInternal::kNone;
 };
 
 // Consume conversion spec prefix (not including '%') of [p, end) if valid.
@@ -72,25 +93,28 @@
                                      UnboundConversion* conv, int* next_arg);
 
 // Helper tag class for the table below.
-// It allows fast `char -> ConversionChar/LengthMod` checking and conversions.
+// It allows fast `char -> ConversionChar/LengthMod` checking and
+// conversions.
 class ConvTag {
  public:
-  constexpr ConvTag(ConversionChar::Id id) : tag_(id) {}  // NOLINT
+  constexpr ConvTag(FormatConversionChar conversion_char)  // NOLINT
+      : tag_(static_cast<int8_t>(conversion_char)) {}
   // We invert the length modifiers to make them negative so that we can easily
   // test for them.
-  constexpr ConvTag(LengthMod::Id id) : tag_(~id) {}  // NOLINT
+  constexpr ConvTag(LengthMod length_mod)  // NOLINT
+      : tag_(~static_cast<std::int8_t>(length_mod)) {}
   // Everything else is -128, which is negative to make is_conv() simpler.
   constexpr ConvTag() : tag_(-128) {}
 
   bool is_conv() const { return tag_ >= 0; }
   bool is_length() const { return tag_ < 0 && tag_ != -128; }
-  ConversionChar as_conv() const {
+  FormatConversionChar as_conv() const {
     assert(is_conv());
-    return ConversionChar::FromId(static_cast<ConversionChar::Id>(tag_));
+    return static_cast<FormatConversionChar>(tag_);
   }
   LengthMod as_length() const {
     assert(is_length());
-    return LengthMod::FromId(static_cast<LengthMod::Id>(~tag_));
+    return static_cast<LengthMod>(~tag_);
   }
 
  private:
@@ -133,7 +157,7 @@
     auto tag = GetTagForChar(percent[1]);
     if (tag.is_conv()) {
       if (ABSL_PREDICT_FALSE(next_arg < 0)) {
-        // This indicates an error in the format std::string.
+        // This indicates an error in the format string.
         // The only way to get `next_arg < 0` here is to have a positional
         // argument first which sets next_arg to -1 and then a non-positional
         // argument.
@@ -176,8 +200,9 @@
 
 class ParsedFormatBase {
  public:
-  explicit ParsedFormatBase(string_view format, bool allow_ignored,
-                            std::initializer_list<Conv> convs);
+  explicit ParsedFormatBase(
+      string_view format, bool allow_ignored,
+      std::initializer_list<FormatConversionCharSet> convs);
 
   ParsedFormatBase(const ParsedFormatBase& other) { *this = other; }
 
@@ -224,8 +249,9 @@
  private:
   // Returns whether the conversions match and if !allow_ignored it verifies
   // that all conversions are used by the format.
-  bool MatchesConversions(bool allow_ignored,
-                          std::initializer_list<Conv> convs) const;
+  bool MatchesConversions(
+      bool allow_ignored,
+      std::initializer_list<FormatConversionCharSet> convs) const;
 
   struct ParsedFormatConsumer;
 
@@ -270,14 +296,14 @@
 // This is the only API that allows the user to pass a runtime specified format
 // string. These factory functions will return NULL if the format does not match
 // the conversions requested by the user.
-template <str_format_internal::Conv... C>
+template <FormatConversionCharSet... C>
 class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {
  public:
   explicit ExtendedParsedFormat(string_view format)
-#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
       __attribute__((
           enable_if(str_format_internal::EnsureConstexpr(format),
-                    "Format std::string is not constexpr."),
+                    "Format string is not constexpr."),
           enable_if(str_format_internal::ValidFormatImpl<C...>(format),
                     "Format specified does not match the template arguments.")))
 #endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
@@ -317,6 +343,7 @@
       : ParsedFormatBase(s, allow_ignored, {C...}) {}
 };
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
diff --git a/absl/strings/internal/str_format/parser_test.cc b/absl/strings/internal/str_format/parser_test.cc
index 6d356093..a5fa1c7 100644
--- a/absl/strings/internal/str_format/parser_test.cc
+++ b/absl/strings/internal/str_format/parser_test.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 #include "absl/strings/internal/str_format/parser.h"
 
 #include <string.h>
@@ -7,6 +21,7 @@
 #include "absl/base/macros.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace str_format_internal {
 
 namespace {
@@ -16,7 +31,7 @@
 TEST(LengthModTest, Names) {
   struct Expectation {
     int line;
-    LengthMod::Id id;
+    LengthMod mod;
     const char *name;
   };
   const Expectation kExpect[] = {
@@ -31,37 +46,33 @@
     {__LINE__, LengthMod::t,    "t" },
     {__LINE__, LengthMod::q,    "q" },
   };
-  EXPECT_EQ(ABSL_ARRAYSIZE(kExpect), LengthMod::kNumValues);
+  EXPECT_EQ(ABSL_ARRAYSIZE(kExpect), 10);
   for (auto e : kExpect) {
     SCOPED_TRACE(e.line);
-    LengthMod mod = LengthMod::FromId(e.id);
-    EXPECT_EQ(e.id, mod.id());
-    EXPECT_EQ(e.name, mod.name());
+    EXPECT_EQ(e.name, LengthModToString(e.mod));
   }
 }
 
 TEST(ConversionCharTest, Names) {
   struct Expectation {
-    ConversionChar::Id id;
+    FormatConversionChar id;
     char name;
   };
   // clang-format off
   const Expectation kExpect[] = {
-#define X(c) {ConversionChar::c, #c[0]}
-    X(c), X(C), X(s), X(S),                          // text
+#define X(c) {FormatConversionCharInternal::c, #c[0]}
+    X(c), X(s),                                      // text
     X(d), X(i), X(o), X(u), X(x), X(X),              // int
     X(f), X(F), X(e), X(E), X(g), X(G), X(a), X(A),  // float
     X(n), X(p),                                      // misc
 #undef X
-    {ConversionChar::none, '\0'},
+    {FormatConversionCharInternal::kNone, '\0'},
   };
   // clang-format on
-  EXPECT_EQ(ABSL_ARRAYSIZE(kExpect), ConversionChar::kNumValues);
   for (auto e : kExpect) {
     SCOPED_TRACE(e.name);
-    ConversionChar v = ConversionChar::FromId(e.id);
-    EXPECT_EQ(e.id, v.id());
-    EXPECT_EQ(e.name, v.Char());
+    FormatConversionChar v = e.id;
+    EXPECT_EQ(e.name, FormatConversionCharToChar(v));
   }
 }
 
@@ -120,13 +131,12 @@
   EXPECT_FALSE(Run("dd"));  // no excess allowed
 
   EXPECT_TRUE(Run("d"));
-  EXPECT_EQ('d', o.conv.Char());
+  EXPECT_EQ('d', FormatConversionCharToChar(o.conv));
   EXPECT_FALSE(o.width.is_from_arg());
   EXPECT_LT(o.width.value(), 0);
   EXPECT_FALSE(o.precision.is_from_arg());
   EXPECT_LT(o.precision.value(), 0);
   EXPECT_EQ(1, o.arg_position);
-  EXPECT_EQ(LengthMod::none, o.length_mod.id());
 }
 
 TEST_F(ConsumeUnboundConversionTest, ArgPosition) {
@@ -162,7 +172,7 @@
 
 TEST_F(ConsumeUnboundConversionTest, WidthAndPrecision) {
   EXPECT_TRUE(Run("14d"));
-  EXPECT_EQ('d', o.conv.Char());
+  EXPECT_EQ('d', FormatConversionCharToChar(o.conv));
   EXPECT_FALSE(o.width.is_from_arg());
   EXPECT_EQ(14, o.width.value());
   EXPECT_FALSE(o.precision.is_from_arg());
@@ -289,6 +299,29 @@
   }
 }
 
+TEST_F(ConsumeUnboundConversionTest, LengthMod) {
+  EXPECT_TRUE(Run("d"));
+  EXPECT_EQ(LengthMod::none, o.length_mod);
+  EXPECT_TRUE(Run("hd"));
+  EXPECT_EQ(LengthMod::h, o.length_mod);
+  EXPECT_TRUE(Run("hhd"));
+  EXPECT_EQ(LengthMod::hh, o.length_mod);
+  EXPECT_TRUE(Run("ld"));
+  EXPECT_EQ(LengthMod::l, o.length_mod);
+  EXPECT_TRUE(Run("lld"));
+  EXPECT_EQ(LengthMod::ll, o.length_mod);
+  EXPECT_TRUE(Run("Lf"));
+  EXPECT_EQ(LengthMod::L, o.length_mod);
+  EXPECT_TRUE(Run("qf"));
+  EXPECT_EQ(LengthMod::q, o.length_mod);
+  EXPECT_TRUE(Run("jd"));
+  EXPECT_EQ(LengthMod::j, o.length_mod);
+  EXPECT_TRUE(Run("zd"));
+  EXPECT_EQ(LengthMod::z, o.length_mod);
+  EXPECT_TRUE(Run("td"));
+  EXPECT_EQ(LengthMod::t, o.length_mod);
+}
+
 struct SummarizeConsumer {
   std::string* out;
   explicit SummarizeConsumer(std::string* out) : out(out) {}
@@ -309,7 +342,7 @@
     if (conv.precision.is_from_arg()) {
       *out += "." + std::to_string(conv.precision.get_from_arg()) + "$*";
     }
-    *out += conv.conv.Char();
+    *out += FormatConversionCharToChar(conv.conv);
     *out += "}";
     return true;
   }
@@ -330,7 +363,8 @@
   ParsedFormatBase p2 = p1;  // copy construct (empty)
   EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p2));
 
-  p1 = ParsedFormatBase("hello%s", true, {Conv::s});  // move assign
+  p1 = ParsedFormatBase("hello%s", true,
+                        {FormatConversionCharSetInternal::s});  // move assign
   EXPECT_EQ("[hello]{s:1$s}", SummarizeParsedFormat(p1));
 
   ParsedFormatBase p3 = p1;  // copy construct (nonempty)
@@ -348,7 +382,7 @@
 
 struct ExpectParse {
   const char* in;
-  std::initializer_list<Conv> conv_set;
+  std::initializer_list<FormatConversionCharSet> conv_set;
   const char* out;
 };
 
@@ -358,9 +392,9 @@
   const ExpectParse kExpect[] = {
       {"", {}, ""},
       {"ab", {}, "[ab]"},
-      {"a%d", {Conv::d}, "[a]{d:1$d}"},
-      {"a%+d", {Conv::d}, "[a]{+d:1$d}"},
-      {"a% d", {Conv::d}, "[a]{ d:1$d}"},
+      {"a%d", {FormatConversionCharSetInternal::d}, "[a]{d:1$d}"},
+      {"a%+d", {FormatConversionCharSetInternal::d}, "[a]{+d:1$d}"},
+      {"a% d", {FormatConversionCharSetInternal::d}, "[a]{ d:1$d}"},
       {"a%b %d", {}, "[a]!"},  // stop after error
   };
   for (const auto& e : kExpect) {
@@ -372,13 +406,13 @@
 
 TEST_F(ParsedFormatTest, ParsingFlagOrder) {
   const ExpectParse kExpect[] = {
-      {"a%+ 0d", {Conv::d}, "[a]{+ 0d:1$d}"},
-      {"a%+0 d", {Conv::d}, "[a]{+0 d:1$d}"},
-      {"a%0+ d", {Conv::d}, "[a]{0+ d:1$d}"},
-      {"a% +0d", {Conv::d}, "[a]{ +0d:1$d}"},
-      {"a%0 +d", {Conv::d}, "[a]{0 +d:1$d}"},
-      {"a% 0+d", {Conv::d}, "[a]{ 0+d:1$d}"},
-      {"a%+   0+d", {Conv::d}, "[a]{+   0+d:1$d}"},
+      {"a%+ 0d", {FormatConversionCharSetInternal::d}, "[a]{+ 0d:1$d}"},
+      {"a%+0 d", {FormatConversionCharSetInternal::d}, "[a]{+0 d:1$d}"},
+      {"a%0+ d", {FormatConversionCharSetInternal::d}, "[a]{0+ d:1$d}"},
+      {"a% +0d", {FormatConversionCharSetInternal::d}, "[a]{ +0d:1$d}"},
+      {"a%0 +d", {FormatConversionCharSetInternal::d}, "[a]{0 +d:1$d}"},
+      {"a% 0+d", {FormatConversionCharSetInternal::d}, "[a]{ 0+d:1$d}"},
+      {"a%+   0+d", {FormatConversionCharSetInternal::d}, "[a]{+   0+d:1$d}"},
   };
   for (const auto& e : kExpect) {
     SCOPED_TRACE(e.in);
@@ -389,4 +423,5 @@
 
 }  // namespace
 }  // namespace str_format_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/str_join_internal.h b/absl/strings/internal/str_join_internal.h
index 7c35f4d..31dbf67 100644
--- a/absl/strings/internal/str_join_internal.h
+++ b/absl/strings/internal/str_join_internal.h
@@ -43,6 +43,7 @@
 #include "absl/strings/str_cat.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 //
@@ -307,6 +308,7 @@
 }
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_
diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h
index 52f6222..a2f41c1 100644
--- a/absl/strings/internal/str_split_internal.h
+++ b/absl/strings/internal/str_split_internal.h
@@ -47,12 +47,13 @@
 #endif  // _GLIBCXX_DEBUG
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 // This class is implicitly constructible from everything that absl::string_view
-// is implicitly constructible from. If it's constructed from a temporary
-// string, the data is moved into a data member so its lifetime matches that of
-// the ConvertibleToStringView instance.
+// is implicitly constructible from, except for rvalue strings.  This means it
+// can be used as a function parameter in places where passing a temporary
+// string might cause memory lifetime issues.
 class ConvertibleToStringView {
  public:
   ConvertibleToStringView(const char* s)  // NOLINT(runtime/explicit)
@@ -64,41 +65,12 @@
       : value_(s) {}
 
   // Matches rvalue strings and moves their data to a member.
-ConvertibleToStringView(std::string&& s)  // NOLINT(runtime/explicit)
-    : copy_(std::move(s)), value_(copy_) {}
-
-  ConvertibleToStringView(const ConvertibleToStringView& other)
-      : copy_(other.copy_),
-        value_(other.IsSelfReferential() ? copy_ : other.value_) {}
-
-  ConvertibleToStringView(ConvertibleToStringView&& other) {
-    StealMembers(std::move(other));
-  }
-
-  ConvertibleToStringView& operator=(ConvertibleToStringView other) {
-    StealMembers(std::move(other));
-    return *this;
-  }
+  ConvertibleToStringView(std::string&& s) = delete;
+  ConvertibleToStringView(const std::string&& s) = delete;
 
   absl::string_view value() const { return value_; }
 
  private:
-  // Returns true if ctsp's value refers to its internal copy_ member.
-  bool IsSelfReferential() const { return value_.data() == copy_.data(); }
-
-  void StealMembers(ConvertibleToStringView&& other) {
-    if (other.IsSelfReferential()) {
-      copy_ = std::move(other.copy_);
-      value_ = copy_;
-      other.value_ = other.copy_;
-    } else {
-      value_ = other.value_;
-    }
-  }
-
-  // Holds the data moved from temporary std::string arguments. Declared first
-  // so that 'value' can refer to 'copy_'.
-  std::string copy_;
   absl::string_view value_;
 };
 
@@ -272,7 +244,11 @@
 // the split strings: only strings for which the predicate returns true will be
 // kept. A Predicate object is any unary functor that takes an absl::string_view
 // and returns bool.
-template <typename Delimiter, typename Predicate>
+//
+// The StringType parameter can be either string_view or string, depending on
+// whether the Splitter refers to a string stored elsewhere, or if the string
+// resides inside the Splitter itself.
+template <typename Delimiter, typename Predicate, typename StringType>
 class Splitter {
  public:
   using DelimiterType = Delimiter;
@@ -280,12 +256,12 @@
   using const_iterator = strings_internal::SplitIterator<Splitter>;
   using value_type = typename std::iterator_traits<const_iterator>::value_type;
 
-  Splitter(ConvertibleToStringView input_text, Delimiter d, Predicate p)
+  Splitter(StringType input_text, Delimiter d, Predicate p)
       : text_(std::move(input_text)),
         delimiter_(std::move(d)),
         predicate_(std::move(p)) {}
 
-  absl::string_view text() const { return text_.value(); }
+  absl::string_view text() const { return text_; }
   const Delimiter& delimiter() const { return delimiter_; }
   const Predicate& predicate() const { return predicate_; }
 
@@ -335,7 +311,7 @@
     Container operator()(const Splitter& splitter) const {
       Container c;
       auto it = std::inserter(c, c.end());
-      for (const auto sp : splitter) {
+      for (const auto& sp : splitter) {
         *it++ = ValueType(sp);
       }
       return c;
@@ -400,7 +376,7 @@
       Container m;
       typename Container::iterator it;
       bool insert = true;
-      for (const auto sp : splitter) {
+      for (const auto& sp : splitter) {
         if (insert) {
           it = Inserter<Container>::Insert(&m, First(sp), Second());
         } else {
@@ -442,12 +418,13 @@
     };
   };
 
-  ConvertibleToStringView text_;
+  StringType text_;
   Delimiter delimiter_;
   Predicate predicate_;
 };
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_
diff --git a/absl/strings/internal/string_constant.h b/absl/strings/internal/string_constant.h
new file mode 100644
index 0000000..a11336b
--- /dev/null
+++ b/absl/strings/internal/string_constant.h
@@ -0,0 +1,64 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
+#define ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
+
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+// StringConstant<T> represents a compile time string constant.
+// It can be accessed via its `absl::string_view value` static member.
+// It is guaranteed that the `string_view` returned has constant `.data()`,
+// constant `.size()` and constant `value[i]` for all `0 <= i < .size()`
+//
+// The `T` is an opaque type. It is guaranteed that different string constants
+// will have different values of `T`. This allows users to associate the string
+// constant with other static state at compile time.
+//
+// Instances should be made using the `MakeStringConstant()` factory function
+// below.
+template <typename T>
+struct StringConstant {
+  static constexpr absl::string_view value = T{}();
+  constexpr absl::string_view operator()() const { return value; }
+
+  // Check to be sure `view` points to constant data.
+  // Otherwise, it can't be constant evaluated.
+  static_assert(value.empty() || 2 * value[0] != 1,
+                "The input string_view must point to constant data.");
+};
+
+template <typename T>
+constexpr absl::string_view StringConstant<T>::value;  // NOLINT
+
+// Factory function for `StringConstant` instances.
+// It supports callables that have a constexpr default constructor and a
+// constexpr operator().
+// It must return an `absl::string_view` or `const char*` pointing to constant
+// data. This is validated at compile time.
+template <typename T>
+constexpr StringConstant<T> MakeStringConstant(T) {
+  return {};
+}
+
+}  // namespace strings_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
diff --git a/absl/strings/internal/string_constant_test.cc b/absl/strings/internal/string_constant_test.cc
new file mode 100644
index 0000000..392833c
--- /dev/null
+++ b/absl/strings/internal/string_constant_test.cc
@@ -0,0 +1,60 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/internal/string_constant.h"
+
+#include "absl/meta/type_traits.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+using absl::strings_internal::MakeStringConstant;
+
+struct Callable {
+  constexpr absl::string_view operator()() const {
+    return absl::string_view("Callable", 8);
+  }
+};
+
+TEST(StringConstant, Traits) {
+  constexpr auto str = MakeStringConstant(Callable{});
+  using T = decltype(str);
+
+  EXPECT_TRUE(std::is_empty<T>::value);
+  EXPECT_TRUE(std::is_trivial<T>::value);
+  EXPECT_TRUE(absl::is_trivially_default_constructible<T>::value);
+  EXPECT_TRUE(absl::is_trivially_copy_constructible<T>::value);
+  EXPECT_TRUE(absl::is_trivially_move_constructible<T>::value);
+  EXPECT_TRUE(absl::is_trivially_destructible<T>::value);
+}
+
+TEST(StringConstant, MakeFromCallable) {
+  constexpr auto str = MakeStringConstant(Callable{});
+  using T = decltype(str);
+  EXPECT_EQ(Callable{}(), T::value);
+  EXPECT_EQ(Callable{}(), str());
+}
+
+TEST(StringConstant, MakeFromStringConstant) {
+  // We want to make sure the StringConstant itself is a valid input to the
+  // factory function.
+  constexpr auto str = MakeStringConstant(Callable{});
+  constexpr auto str2 = MakeStringConstant(str);
+  using T = decltype(str2);
+  EXPECT_EQ(Callable{}(), T::value);
+  EXPECT_EQ(Callable{}(), str2());
+}
+
+}  // namespace
diff --git a/absl/strings/internal/utf8.cc b/absl/strings/internal/utf8.cc
index 82d36c2..8fd8edc 100644
--- a/absl/strings/internal/utf8.cc
+++ b/absl/strings/internal/utf8.cc
@@ -17,6 +17,7 @@
 #include "absl/strings/internal/utf8.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 size_t EncodeUTF8Char(char *buffer, char32_t utf8_char) {
@@ -48,4 +49,5 @@
 }
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/internal/utf8.h b/absl/strings/internal/utf8.h
index 0423630..32fb109 100644
--- a/absl/strings/internal/utf8.h
+++ b/absl/strings/internal/utf8.h
@@ -20,7 +20,10 @@
 #include <cstddef>
 #include <cstdint>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 // For Unicode code points 0 through 0x10FFFF, EncodeUTF8Char writes
@@ -41,6 +44,7 @@
 size_t EncodeUTF8Char(char *buffer, char32_t utf8_char);
 
 }  // namespace strings_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_INTERNAL_UTF8_H_
diff --git a/absl/strings/match.cc b/absl/strings/match.cc
index 7b24241..2d67250 100644
--- a/absl/strings/match.cc
+++ b/absl/strings/match.cc
@@ -17,22 +17,27 @@
 #include "absl/strings/internal/memutil.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
-bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2) {
+bool EqualsIgnoreCase(absl::string_view piece1,
+                      absl::string_view piece2) noexcept {
   return (piece1.size() == piece2.size() &&
           0 == absl::strings_internal::memcasecmp(piece1.data(), piece2.data(),
                                                   piece1.size()));
   // memcasecmp uses absl::ascii_tolower().
 }
 
-bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) {
+bool StartsWithIgnoreCase(absl::string_view text,
+                          absl::string_view prefix) noexcept {
   return (text.size() >= prefix.size()) &&
          EqualsIgnoreCase(text.substr(0, prefix.size()), prefix);
 }
 
-bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) {
+bool EndsWithIgnoreCase(absl::string_view text,
+                        absl::string_view suffix) noexcept {
   return (text.size() >= suffix.size()) &&
          EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix);
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/match.h b/absl/strings/match.h
index 762f359..038cbb3 100644
--- a/absl/strings/match.h
+++ b/absl/strings/match.h
@@ -20,7 +20,7 @@
 // This file contains simple utilities for performing string matching checks.
 // All of these function parameters are specified as `absl::string_view`,
 // meaning that these functions can accept `std::string`, `absl::string_view` or
-// nul-terminated C-style strings.
+// NUL-terminated C-style strings.
 //
 // Examples:
 //   std::string s = "foo";
@@ -38,18 +38,25 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // StrContains()
 //
 // Returns whether a given string `haystack` contains the substring `needle`.
-inline bool StrContains(absl::string_view haystack, absl::string_view needle) {
+inline bool StrContains(absl::string_view haystack,
+                        absl::string_view needle) noexcept {
   return haystack.find(needle, 0) != haystack.npos;
 }
 
+inline bool StrContains(absl::string_view haystack, char needle) noexcept {
+  return haystack.find(needle) != haystack.npos;
+}
+
 // StartsWith()
 //
 // Returns whether a given string `text` begins with `prefix`.
-inline bool StartsWith(absl::string_view text, absl::string_view prefix) {
+inline bool StartsWith(absl::string_view text,
+                       absl::string_view prefix) noexcept {
   return prefix.empty() ||
          (text.size() >= prefix.size() &&
           memcmp(text.data(), prefix.data(), prefix.size()) == 0);
@@ -58,7 +65,8 @@
 // EndsWith()
 //
 // Returns whether a given string `text` ends with `suffix`.
-inline bool EndsWith(absl::string_view text, absl::string_view suffix) {
+inline bool EndsWith(absl::string_view text,
+                     absl::string_view suffix) noexcept {
   return suffix.empty() ||
          (text.size() >= suffix.size() &&
           memcmp(text.data() + (text.size() - suffix.size()), suffix.data(),
@@ -69,20 +77,24 @@
 //
 // Returns whether given ASCII strings `piece1` and `piece2` are equal, ignoring
 // case in the comparison.
-bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2);
+bool EqualsIgnoreCase(absl::string_view piece1,
+                      absl::string_view piece2) noexcept;
 
 // StartsWithIgnoreCase()
 //
 // Returns whether a given ASCII string `text` starts with `prefix`,
 // ignoring case in the comparison.
-bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix);
+bool StartsWithIgnoreCase(absl::string_view text,
+                          absl::string_view prefix) noexcept;
 
 // EndsWithIgnoreCase()
 //
 // Returns whether a given ASCII string `text` ends with `suffix`, ignoring
 // case in the comparison.
-bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix);
+bool EndsWithIgnoreCase(absl::string_view text,
+                        absl::string_view suffix) noexcept;
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_MATCH_H_
diff --git a/absl/strings/match_test.cc b/absl/strings/match_test.cc
index 4c313dd..5841bc1 100644
--- a/absl/strings/match_test.cc
+++ b/absl/strings/match_test.cc
@@ -66,6 +66,23 @@
   EXPECT_FALSE(absl::StrContains("", "a"));
 }
 
+TEST(MatchTest, ContainsChar) {
+  absl::string_view a("abcdefg");
+  absl::string_view b("abcd");
+  EXPECT_TRUE(absl::StrContains(a, 'a'));
+  EXPECT_TRUE(absl::StrContains(a, 'b'));
+  EXPECT_TRUE(absl::StrContains(a, 'e'));
+  EXPECT_FALSE(absl::StrContains(a, 'h'));
+
+  EXPECT_TRUE(absl::StrContains(b, 'a'));
+  EXPECT_TRUE(absl::StrContains(b, 'b'));
+  EXPECT_FALSE(absl::StrContains(b, 'e'));
+  EXPECT_FALSE(absl::StrContains(b, 'h'));
+
+  EXPECT_FALSE(absl::StrContains("", 'a'));
+  EXPECT_FALSE(absl::StrContains("", 'a'));
+}
+
 TEST(MatchTest, ContainsNull) {
   const std::string s = "foo";
   const char* cs = "foo";
diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc
index 38d1486..e6bf44c 100644
--- a/absl/strings/numbers.cc
+++ b/absl/strings/numbers.cc
@@ -19,8 +19,8 @@
 
 #include <algorithm>
 #include <cassert>
-#include <cfloat>          // for DBL_DIG and FLT_DIG
-#include <cmath>           // for HUGE_VAL
+#include <cfloat>  // for DBL_DIG and FLT_DIG
+#include <cmath>   // for HUGE_VAL
 #include <cstdint>
 #include <cstdio>
 #include <cstdlib>
@@ -30,15 +30,18 @@
 #include <memory>
 #include <utility>
 
-#include "absl/base/internal/bits.h"
+#include "absl/base/attributes.h"
 #include "absl/base/internal/raw_logging.h"
+#include "absl/numeric/bits.h"
 #include "absl/strings/ascii.h"
 #include "absl/strings/charconv.h"
+#include "absl/strings/escaping.h"
 #include "absl/strings/internal/memutil.h"
 #include "absl/strings/match.h"
 #include "absl/strings/str_cat.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 bool SimpleAtof(absl::string_view str, float* out) {
   *out = 0.0;
@@ -92,43 +95,6 @@
   return true;
 }
 
-namespace {
-
-// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
-// range 0 <= i < 100, and buf must have space for two characters. Example:
-//   char buf[2];
-//   PutTwoDigits(42, buf);
-//   // buf[0] == '4'
-//   // buf[1] == '2'
-inline void PutTwoDigits(size_t i, char* buf) {
-  static const char two_ASCII_digits[100][2] = {
-    {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'},
-    {'0', '5'}, {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'},
-    {'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'},
-    {'1', '5'}, {'1', '6'}, {'1', '7'}, {'1', '8'}, {'1', '9'},
-    {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'},
-    {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
-    {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'},
-    {'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'},
-    {'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'},
-    {'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'},
-    {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'},
-    {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
-    {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'},
-    {'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'},
-    {'7', '0'}, {'7', '1'}, {'7', '2'}, {'7', '3'}, {'7', '4'},
-    {'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'},
-    {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, {'8', '4'},
-    {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
-    {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'},
-    {'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}
-  };
-  assert(i < 100);
-  memcpy(buf, two_ASCII_digits[i], 2);
-}
-
-}  // namespace
-
 bool SimpleAtob(absl::string_view str, bool* out) {
   ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr.");
   if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") ||
@@ -337,7 +303,7 @@
   uint64_t bits128_up = (bits96_127 >> 32) + (bits64_127 < bits64_95);
   if (bits128_up == 0) return {bits64_127, bits0_63};
 
-  int shift = 64 - base_internal::CountLeadingZeros64(bits128_up);
+  auto shift = static_cast<unsigned>(bit_width(bits128_up));
   uint64_t lo = (bits0_63 >> shift) + (bits64_127 << (64 - shift));
   uint64_t hi = (bits64_127 >> shift) + (bits128_up << (64 - shift));
   return {hi, lo};
@@ -368,7 +334,7 @@
       5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
       5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5};
   result = Mul32(result, powers_of_five[expfive & 15]);
-  int shift = base_internal::CountLeadingZeros64(result.first);
+  int shift = countl_zero(result.first);
   if (shift != 0) {
     result.first = (result.first << shift) + (result.second >> (64 - shift));
     result.second = (result.second << shift);
@@ -495,13 +461,13 @@
 
   int two_digits = dddddd / 10000;
   dddddd -= two_digits * 10000;
-  PutTwoDigits(two_digits, &exp_dig.digits[0]);
+  numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[0]);
 
   two_digits = dddddd / 100;
   dddddd -= two_digits * 100;
-  PutTwoDigits(two_digits, &exp_dig.digits[2]);
+  numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[2]);
 
-  PutTwoDigits(dddddd, &exp_dig.digits[4]);
+  numbers_internal::PutTwoDigits(dddddd, &exp_dig.digits[4]);
   return exp_dig;
 }
 
@@ -754,8 +720,8 @@
 // commonly used bases.
 template <typename IntType>
 struct LookupTables {
-  static const IntType kVmaxOverBase[];
-  static const IntType kVminOverBase[];
+  ABSL_CONST_INIT static const IntType kVmaxOverBase[];
+  ABSL_CONST_INIT static const IntType kVminOverBase[];
 };
 
 // An array initializer macro for X/base where base in [0, 36].
@@ -770,6 +736,163 @@
         X / 35, X / 36,                                                   \
   }
 
+// This kVmaxOverBase is generated with
+//  for (int base = 2; base < 37; ++base) {
+//    absl::uint128 max = std::numeric_limits<absl::uint128>::max();
+//    auto result = max / base;
+//    std::cout << "    MakeUint128(" << absl::Uint128High64(result) << "u, "
+//              << absl::Uint128Low64(result) << "u),\n";
+//  }
+// See https://godbolt.org/z/aneYsb
+//
+// uint128& operator/=(uint128) is not constexpr, so hardcode the resulting
+// array to avoid a static initializer.
+template<>
+const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
+    0,
+    0,
+    MakeUint128(9223372036854775807u, 18446744073709551615u),
+    MakeUint128(6148914691236517205u, 6148914691236517205u),
+    MakeUint128(4611686018427387903u, 18446744073709551615u),
+    MakeUint128(3689348814741910323u, 3689348814741910323u),
+    MakeUint128(3074457345618258602u, 12297829382473034410u),
+    MakeUint128(2635249153387078802u, 5270498306774157604u),
+    MakeUint128(2305843009213693951u, 18446744073709551615u),
+    MakeUint128(2049638230412172401u, 14347467612885206812u),
+    MakeUint128(1844674407370955161u, 11068046444225730969u),
+    MakeUint128(1676976733973595601u, 8384883669867978007u),
+    MakeUint128(1537228672809129301u, 6148914691236517205u),
+    MakeUint128(1418980313362273201u, 4256940940086819603u),
+    MakeUint128(1317624576693539401u, 2635249153387078802u),
+    MakeUint128(1229782938247303441u, 1229782938247303441u),
+    MakeUint128(1152921504606846975u, 18446744073709551615u),
+    MakeUint128(1085102592571150095u, 1085102592571150095u),
+    MakeUint128(1024819115206086200u, 16397105843297379214u),
+    MakeUint128(970881267037344821u, 16504981539634861972u),
+    MakeUint128(922337203685477580u, 14757395258967641292u),
+    MakeUint128(878416384462359600u, 14054662151397753612u),
+    MakeUint128(838488366986797800u, 13415813871788764811u),
+    MakeUint128(802032351030850070u, 4812194106185100421u),
+    MakeUint128(768614336404564650u, 12297829382473034410u),
+    MakeUint128(737869762948382064u, 11805916207174113034u),
+    MakeUint128(709490156681136600u, 11351842506898185609u),
+    MakeUint128(683212743470724133u, 17080318586768103348u),
+    MakeUint128(658812288346769700u, 10540996613548315209u),
+    MakeUint128(636094623231363848u, 15266270957552732371u),
+    MakeUint128(614891469123651720u, 9838263505978427528u),
+    MakeUint128(595056260442243600u, 9520900167075897608u),
+    MakeUint128(576460752303423487u, 18446744073709551615u),
+    MakeUint128(558992244657865200u, 8943875914525843207u),
+    MakeUint128(542551296285575047u, 9765923333140350855u),
+    MakeUint128(527049830677415760u, 8432797290838652167u),
+    MakeUint128(512409557603043100u, 8198552921648689607u),
+};
+
+// This kVmaxOverBase generated with
+//   for (int base = 2; base < 37; ++base) {
+//    absl::int128 max = std::numeric_limits<absl::int128>::max();
+//    auto result = max / base;
+//    std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", "
+//              << absl::Int128Low64(result) << "u),\n";
+//  }
+// See https://godbolt.org/z/7djYWz
+//
+// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
+// to avoid a static initializer.
+template<>
+const int128 LookupTables<int128>::kVmaxOverBase[] = {
+    0,
+    0,
+    MakeInt128(4611686018427387903, 18446744073709551615u),
+    MakeInt128(3074457345618258602, 12297829382473034410u),
+    MakeInt128(2305843009213693951, 18446744073709551615u),
+    MakeInt128(1844674407370955161, 11068046444225730969u),
+    MakeInt128(1537228672809129301, 6148914691236517205u),
+    MakeInt128(1317624576693539401, 2635249153387078802u),
+    MakeInt128(1152921504606846975, 18446744073709551615u),
+    MakeInt128(1024819115206086200, 16397105843297379214u),
+    MakeInt128(922337203685477580, 14757395258967641292u),
+    MakeInt128(838488366986797800, 13415813871788764811u),
+    MakeInt128(768614336404564650, 12297829382473034410u),
+    MakeInt128(709490156681136600, 11351842506898185609u),
+    MakeInt128(658812288346769700, 10540996613548315209u),
+    MakeInt128(614891469123651720, 9838263505978427528u),
+    MakeInt128(576460752303423487, 18446744073709551615u),
+    MakeInt128(542551296285575047, 9765923333140350855u),
+    MakeInt128(512409557603043100, 8198552921648689607u),
+    MakeInt128(485440633518672410, 17475862806672206794u),
+    MakeInt128(461168601842738790, 7378697629483820646u),
+    MakeInt128(439208192231179800, 7027331075698876806u),
+    MakeInt128(419244183493398900, 6707906935894382405u),
+    MakeInt128(401016175515425035, 2406097053092550210u),
+    MakeInt128(384307168202282325, 6148914691236517205u),
+    MakeInt128(368934881474191032, 5902958103587056517u),
+    MakeInt128(354745078340568300, 5675921253449092804u),
+    MakeInt128(341606371735362066, 17763531330238827482u),
+    MakeInt128(329406144173384850, 5270498306774157604u),
+    MakeInt128(318047311615681924, 7633135478776366185u),
+    MakeInt128(307445734561825860, 4919131752989213764u),
+    MakeInt128(297528130221121800, 4760450083537948804u),
+    MakeInt128(288230376151711743, 18446744073709551615u),
+    MakeInt128(279496122328932600, 4471937957262921603u),
+    MakeInt128(271275648142787523, 14106333703424951235u),
+    MakeInt128(263524915338707880, 4216398645419326083u),
+    MakeInt128(256204778801521550, 4099276460824344803u),
+};
+
+// This kVminOverBase generated with
+//  for (int base = 2; base < 37; ++base) {
+//    absl::int128 min = std::numeric_limits<absl::int128>::min();
+//    auto result = min / base;
+//    std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", "
+//              << absl::Int128Low64(result) << "u),\n";
+//  }
+//
+// See https://godbolt.org/z/7djYWz
+//
+// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
+// to avoid a static initializer.
+template<>
+const int128 LookupTables<int128>::kVminOverBase[] = {
+    0,
+    0,
+    MakeInt128(-4611686018427387904, 0u),
+    MakeInt128(-3074457345618258603, 6148914691236517206u),
+    MakeInt128(-2305843009213693952, 0u),
+    MakeInt128(-1844674407370955162, 7378697629483820647u),
+    MakeInt128(-1537228672809129302, 12297829382473034411u),
+    MakeInt128(-1317624576693539402, 15811494920322472814u),
+    MakeInt128(-1152921504606846976, 0u),
+    MakeInt128(-1024819115206086201, 2049638230412172402u),
+    MakeInt128(-922337203685477581, 3689348814741910324u),
+    MakeInt128(-838488366986797801, 5030930201920786805u),
+    MakeInt128(-768614336404564651, 6148914691236517206u),
+    MakeInt128(-709490156681136601, 7094901566811366007u),
+    MakeInt128(-658812288346769701, 7905747460161236407u),
+    MakeInt128(-614891469123651721, 8608480567731124088u),
+    MakeInt128(-576460752303423488, 0u),
+    MakeInt128(-542551296285575048, 8680820740569200761u),
+    MakeInt128(-512409557603043101, 10248191152060862009u),
+    MakeInt128(-485440633518672411, 970881267037344822u),
+    MakeInt128(-461168601842738791, 11068046444225730970u),
+    MakeInt128(-439208192231179801, 11419412998010674810u),
+    MakeInt128(-419244183493398901, 11738837137815169211u),
+    MakeInt128(-401016175515425036, 16040647020617001406u),
+    MakeInt128(-384307168202282326, 12297829382473034411u),
+    MakeInt128(-368934881474191033, 12543785970122495099u),
+    MakeInt128(-354745078340568301, 12770822820260458812u),
+    MakeInt128(-341606371735362067, 683212743470724134u),
+    MakeInt128(-329406144173384851, 13176245766935394012u),
+    MakeInt128(-318047311615681925, 10813608594933185431u),
+    MakeInt128(-307445734561825861, 13527612320720337852u),
+    MakeInt128(-297528130221121801, 13686293990171602812u),
+    MakeInt128(-288230376151711744, 0u),
+    MakeInt128(-279496122328932601, 13974806116446630013u),
+    MakeInt128(-271275648142787524, 4340410370284600381u),
+    MakeInt128(-263524915338707881, 14230345428290225533u),
+    MakeInt128(-256204778801521551, 14347467612885206813u),
+};
+
 template <typename IntType>
 const IntType LookupTables<IntType>::kVmaxOverBase[] =
     X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());
@@ -789,6 +912,8 @@
   assert(base >= 0);
   assert(vmax >= static_cast<IntType>(base));
   const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base];
+  assert(base < 2 ||
+         std::numeric_limits<IntType>::max() / base == vmax_over_base);
   const char* start = text.data();
   const char* end = start + text.size();
   // loop over digits
@@ -822,6 +947,8 @@
   assert(vmin < 0);
   assert(vmin <= 0 - base);
   IntType vmin_over_base = LookupTables<IntType>::kVminOverBase[base];
+  assert(base < 2 ||
+         std::numeric_limits<IntType>::min() / base == vmin_over_base);
   // 2003 c++ standard [expr.mul]
   // "... the sign of the remainder is implementation-defined."
   // Although (vmin/base)*base + vmin%base is always vmin.
@@ -885,6 +1012,48 @@
 }  // anonymous namespace
 
 namespace numbers_internal {
+
+// Digit conversion.
+ABSL_CONST_INIT ABSL_DLL const char kHexChar[] =
+    "0123456789abcdef";
+
+ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] =
+    "000102030405060708090a0b0c0d0e0f"
+    "101112131415161718191a1b1c1d1e1f"
+    "202122232425262728292a2b2c2d2e2f"
+    "303132333435363738393a3b3c3d3e3f"
+    "404142434445464748494a4b4c4d4e4f"
+    "505152535455565758595a5b5c5d5e5f"
+    "606162636465666768696a6b6c6d6e6f"
+    "707172737475767778797a7b7c7d7e7f"
+    "808182838485868788898a8b8c8d8e8f"
+    "909192939495969798999a9b9c9d9e9f"
+    "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+    "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+    "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+    "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+    "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+    "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
+
+ABSL_CONST_INIT ABSL_DLL const char two_ASCII_digits[100][2] = {
+    {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
+    {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
+    {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
+    {'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'},
+    {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
+    {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'},
+    {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'},
+    {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'},
+    {'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'},
+    {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
+    {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'},
+    {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'},
+    {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'},
+    {'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'},
+    {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
+    {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'},
+    {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
+
 bool safe_strto32_base(absl::string_view text, int32_t* value, int base) {
   return safe_int_internal<int32_t>(text, value, base);
 }
@@ -893,6 +1062,10 @@
   return safe_int_internal<int64_t>(text, value, base);
 }
 
+bool safe_strto128_base(absl::string_view text, int128* value, int base) {
+  return safe_int_internal<absl::int128>(text, value, base);
+}
+
 bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base) {
   return safe_uint_internal<uint32_t>(text, value, base);
 }
@@ -900,6 +1073,11 @@
 bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base) {
   return safe_uint_internal<uint64_t>(text, value, base);
 }
-}  // namespace numbers_internal
 
+bool safe_strtou128_base(absl::string_view text, uint128* value, int base) {
+  return safe_uint_internal<absl::uint128>(text, value, base);
+}
+
+}  // namespace numbers_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h
index 100839b..ffc738f 100644
--- a/absl/strings/numbers.h
+++ b/absl/strings/numbers.h
@@ -1,4 +1,3 @@
-//
 // Copyright 2017 The Abseil Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
@@ -24,6 +23,10 @@
 #ifndef ABSL_STRINGS_NUMBERS_H_
 #define ABSL_STRINGS_NUMBERS_H_
 
+#ifdef __SSE4_2__
+#include <x86intrin.h>
+#endif
+
 #include <cstddef>
 #include <cstdlib>
 #include <cstring>
@@ -32,38 +35,54 @@
 #include <string>
 #include <type_traits>
 
+#include "absl/base/config.h"
+#ifdef __SSE4_2__
+// TODO(jorg): Remove this when we figure out the right way
+// to swap bytes on SSE 4.2 that works with the compilers
+// we claim to support.  Also, add tests for the compiler
+// that doesn't support the Intel _bswap64 intrinsic but
+// does support all the SSE 4.2 intrinsics
+#include "absl/base/internal/endian.h"
+#endif
 #include "absl/base/macros.h"
 #include "absl/base/port.h"
+#include "absl/numeric/bits.h"
 #include "absl/numeric/int128.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // SimpleAtoi()
 //
-// Converts the given string into an integer value, returning `true` if
-// successful. The string must reflect a base-10 integer (optionally followed or
-// preceded by ASCII whitespace) whose value falls within the range of the
-// integer type. If any errors are encountered, this function returns `false`,
-// leaving `out` in an unspecified state.
+// Converts the given string (optionally followed or preceded by ASCII
+// whitespace) into an integer value, returning `true` if successful. The string
+// must reflect a base-10 integer whose value falls within the range of the
+// integer type (optionally preceded by a `+` or `-`). If any errors are
+// encountered, this function returns `false`, leaving `out` in an unspecified
+// state.
 template <typename int_type>
 ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out);
 
 // SimpleAtof()
 //
 // Converts the given string (optionally followed or preceded by ASCII
-// whitespace) into a float, which may be rounded on overflow or underflow.
+// whitespace) into a float, which may be rounded on overflow or underflow,
+// returning `true` if successful.
 // See https://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`. If any errors are encountered, this function
+// allowed formats for `str`, except SimpleAtof() is locale-independent and will
+// always use the "C" locale. If any errors are encountered, this function
 // returns `false`, leaving `out` in an unspecified state.
 ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out);
 
 // SimpleAtod()
 //
 // Converts the given string (optionally followed or preceded by ASCII
-// whitespace) into a double, which may be rounded on overflow or underflow.
+// whitespace) into a double, which may be rounded on overflow or underflow,
+// returning `true` if successful.
 // See https://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`. If any errors are encountered, this function
+// allowed formats for `str`, except SimpleAtod is locale-independent and will
+// always use the "C" locale. If any errors are encountered, this function
 // returns `false`, leaving `out` in an unspecified state.
 ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out);
 
@@ -77,18 +96,42 @@
 // unspecified state.
 ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out);
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 // End of public API.  Implementation details follow.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace numbers_internal {
 
+// Digit conversion.
+ABSL_DLL extern const char kHexChar[17];  // 0123456789abcdef
+ABSL_DLL extern const char
+    kHexTable[513];  // 000102030405060708090a0b0c0d0e0f1011...
+ABSL_DLL extern const char
+    two_ASCII_digits[100][2];  // 00, 01, 02, 03...
+
+// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
+// range 0 <= i < 100, and buf must have space for two characters. Example:
+//   char buf[2];
+//   PutTwoDigits(42, buf);
+//   // buf[0] == '4'
+//   // buf[1] == '2'
+inline void PutTwoDigits(size_t i, char* buf) {
+  assert(i < 100);
+  memcpy(buf, two_ASCII_digits[i], 2);
+}
+
 // safe_strto?() functions for implementing SimpleAtoi()
 bool safe_strto32_base(absl::string_view text, int32_t* value, int base);
 bool safe_strto64_base(absl::string_view text, int64_t* value, int base);
+bool safe_strto128_base(absl::string_view text, absl::int128* value,
+                         int base);
 bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base);
 bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base);
+bool safe_strtou128_base(absl::string_view text, absl::uint128* value,
+                         int base);
 
 static const int kFastToBufferSize = 32;
 static const int kSixDigitsToBufferSize = 16;
@@ -170,20 +213,53 @@
   return parsed;
 }
 
+// FastHexToBufferZeroPad16()
+//
+// Outputs `val` into `out` as if by `snprintf(out, 17, "%016x", val)` but
+// without the terminating null character. Thus `out` must be of length >= 16.
+// Returns the number of non-pad digits of the output (it can never be zero
+// since 0 has one digit).
+inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) {
+#ifdef __SSE4_2__
+  uint64_t be = absl::big_endian::FromHost64(val);
+  const auto kNibbleMask = _mm_set1_epi8(0xf);
+  const auto kHexDigits = _mm_setr_epi8('0', '1', '2', '3', '4', '5', '6', '7',
+                                        '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
+  auto v = _mm_loadl_epi64(reinterpret_cast<__m128i*>(&be));  // load lo dword
+  auto v4 = _mm_srli_epi64(v, 4);                            // shift 4 right
+  auto il = _mm_unpacklo_epi8(v4, v);                        // interleave bytes
+  auto m = _mm_and_si128(il, kNibbleMask);                   // mask out nibbles
+  auto hexchars = _mm_shuffle_epi8(kHexDigits, m);           // hex chars
+  _mm_storeu_si128(reinterpret_cast<__m128i*>(out), hexchars);
+#else
+  for (int i = 0; i < 8; ++i) {
+    auto byte = (val >> (56 - 8 * i)) & 0xFF;
+    auto* hex = &absl::numbers_internal::kHexTable[byte * 2];
+    std::memcpy(out + 2 * i, hex, 2);
+  }
+#endif
+  // | 0x1 so that even 0 has 1 digit.
+  return 16 - countl_zero(val | 0x1) / 4;
+}
+
 }  // namespace numbers_internal
 
-// SimpleAtoi()
-//
-// Converts a string to an integer, using `safe_strto?()` functions for actual
-// parsing, returning `true` if successful. The `safe_strto?()` functions apply
-// strict checking; the string must be a base-10 integer, optionally followed or
-// preceded by ASCII whitespace, with a value in the range of the corresponding
-// integer type.
 template <typename int_type>
 ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out) {
   return numbers_internal::safe_strtoi_base(str, out, 10);
 }
 
+ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
+                                            absl::int128* out) {
+  return numbers_internal::safe_strto128_base(str, out, 10);
+}
+
+ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
+                                            absl::uint128* out) {
+  return numbers_internal::safe_strtou128_base(str, out, 10);
+}
+
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_NUMBERS_H_
diff --git a/absl/strings/numbers_benchmark.cc b/absl/strings/numbers_benchmark.cc
index 54dbedd..6e79b3e 100644
--- a/absl/strings/numbers_benchmark.cc
+++ b/absl/strings/numbers_benchmark.cc
@@ -20,6 +20,8 @@
 
 #include "benchmark/benchmark.h"
 #include "absl/base/internal/raw_logging.h"
+#include "absl/random/distributions.h"
+#include "absl/random/random.h"
 #include "absl/strings/numbers.h"
 
 namespace {
@@ -260,4 +262,25 @@
     ->ArgPair(10, 4)
     ->ArgPair(10, 8);
 
+void BM_FastHexToBufferZeroPad16(benchmark::State& state) {
+  absl::BitGen rng;
+  std::vector<uint64_t> nums;
+  nums.resize(1000);
+  auto min = std::numeric_limits<uint64_t>::min();
+  auto max = std::numeric_limits<uint64_t>::max();
+  for (auto& num : nums) {
+    num = absl::LogUniform(rng, min, max);
+  }
+
+  char buf[16];
+  while (state.KeepRunningBatch(nums.size())) {
+    for (auto num : nums) {
+      auto digits = absl::numbers_internal::FastHexToBufferZeroPad16(num, buf);
+      benchmark::DoNotOptimize(digits);
+      benchmark::DoNotOptimize(buf);
+    }
+  }
+}
+BENCHMARK(BM_FastHexToBufferZeroPad16);
+
 }  // namespace
diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc
index 77d7e78..27616bf 100644
--- a/absl/strings/numbers_test.cc
+++ b/absl/strings/numbers_test.cc
@@ -17,6 +17,7 @@
 #include "absl/strings/numbers.h"
 
 #include <sys/types.h>
+
 #include <cfenv>  // NOLINT(build/c++11)
 #include <cinttypes>
 #include <climits>
@@ -36,13 +37,16 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/base/internal/raw_logging.h"
-#include "absl/strings/str_cat.h"
-
+#include "absl/random/distributions.h"
+#include "absl/random/random.h"
 #include "absl/strings/internal/numbers_test_common.h"
+#include "absl/strings/internal/ostringstream.h"
 #include "absl/strings/internal/pow10_helper.h"
+#include "absl/strings/str_cat.h"
 
 namespace {
 
+using absl::SimpleAtoi;
 using absl::numbers_internal::kSixDigitsToBufferSize;
 using absl::numbers_internal::safe_strto32_base;
 using absl::numbers_internal::safe_strto64_base;
@@ -52,7 +56,6 @@
 using absl::strings_internal::Itoa;
 using absl::strings_internal::strtouint32_test_cases;
 using absl::strings_internal::strtouint64_test_cases;
-using absl::SimpleAtoi;
 using testing::Eq;
 using testing::MatchesRegex;
 
@@ -204,6 +207,9 @@
   std::string actual = absl::StrCat(absl::Hex(v, absl::kZeroPad16));
   snprintf(expected, sizeof(expected), "%016" PRIx64, static_cast<uint64_t>(v));
   EXPECT_EQ(expected, actual) << " Input " << v;
+  actual = absl::StrCat(absl::Hex(v, absl::kSpacePad16));
+  snprintf(expected, sizeof(expected), "%16" PRIx64, static_cast<uint64_t>(v));
+  EXPECT_EQ(expected, actual) << " Input " << v;
 }
 
 TEST(Numbers, TestFastPrints) {
@@ -244,7 +250,9 @@
 
 template <typename int_type, typename in_val_type>
 void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {
-  std::string s = absl::StrCat(in_value);
+  std::string s;
+  // (u)int128 can be streamed but not StrCat'd.
+  absl::strings_internal::OStringStream(&s) << in_value;
   int_type x = static_cast<int_type>(~exp_value);
   EXPECT_TRUE(SimpleAtoi(s, &x))
       << "in_value=" << in_value << " s=" << s << " x=" << x;
@@ -256,7 +264,9 @@
 
 template <typename int_type, typename in_val_type>
 void VerifySimpleAtoiBad(in_val_type in_value) {
-  std::string s = absl::StrCat(in_value);
+  std::string s;
+  // (u)int128 can be streamed but not StrCat'd.
+  absl::strings_internal::OStringStream(&s) << in_value;
   int_type x;
   EXPECT_FALSE(SimpleAtoi(s, &x));
   EXPECT_FALSE(SimpleAtoi(s.c_str(), &x));
@@ -320,18 +330,68 @@
   VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<uint64_t>::max(),
                                  std::numeric_limits<uint64_t>::max());
 
+  // SimpleAtoi(absl::string_view, absl::uint128)
+  VerifySimpleAtoiGood<absl::uint128>(0, 0);
+  VerifySimpleAtoiGood<absl::uint128>(42, 42);
+  VerifySimpleAtoiBad<absl::uint128>(-42);
+
+  VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int32_t>::min());
+  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int32_t>::max(),
+                                      std::numeric_limits<int32_t>::max());
+  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint32_t>::max(),
+                                      std::numeric_limits<uint32_t>::max());
+  VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int64_t>::min());
+  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int64_t>::max(),
+                                      std::numeric_limits<int64_t>::max());
+  VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint64_t>::max(),
+                                      std::numeric_limits<uint64_t>::max());
+  VerifySimpleAtoiGood<absl::uint128>(
+      std::numeric_limits<absl::uint128>::max(),
+      std::numeric_limits<absl::uint128>::max());
+
+  // SimpleAtoi(absl::string_view, absl::int128)
+  VerifySimpleAtoiGood<absl::int128>(0, 0);
+  VerifySimpleAtoiGood<absl::int128>(42, 42);
+  VerifySimpleAtoiGood<absl::int128>(-42, -42);
+
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::min(),
+                                      std::numeric_limits<int32_t>::min());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::max(),
+                                      std::numeric_limits<int32_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint32_t>::max(),
+                                      std::numeric_limits<uint32_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::min(),
+                                      std::numeric_limits<int64_t>::min());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::max(),
+                                      std::numeric_limits<int64_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint64_t>::max(),
+                                      std::numeric_limits<uint64_t>::max());
+  VerifySimpleAtoiGood<absl::int128>(
+      std::numeric_limits<absl::int128>::min(),
+      std::numeric_limits<absl::int128>::min());
+  VerifySimpleAtoiGood<absl::int128>(
+      std::numeric_limits<absl::int128>::max(),
+      std::numeric_limits<absl::int128>::max());
+  VerifySimpleAtoiBad<absl::int128>(std::numeric_limits<absl::uint128>::max());
+
   // Some other types
   VerifySimpleAtoiGood<int>(-42, -42);
   VerifySimpleAtoiGood<int32_t>(-42, -42);
   VerifySimpleAtoiGood<uint32_t>(42, 42);
   VerifySimpleAtoiGood<unsigned int>(42, 42);
   VerifySimpleAtoiGood<int64_t>(-42, -42);
-  VerifySimpleAtoiGood<long>(-42, -42);  // NOLINT(runtime/int)
+  VerifySimpleAtoiGood<long>(-42, -42);  // NOLINT: runtime-int
   VerifySimpleAtoiGood<uint64_t>(42, 42);
   VerifySimpleAtoiGood<size_t>(42, 42);
   VerifySimpleAtoiGood<std::string::size_type>(42, 42);
 }
 
+TEST(NumbersTest, Atod) {
+  double d;
+  EXPECT_TRUE(absl::SimpleAtod("nan", &d));
+  EXPECT_TRUE(std::isnan(d));
+}
+
 TEST(NumbersTest, Atoenum) {
   enum E01 {
     E01_zero = 0,
@@ -455,7 +515,7 @@
   EXPECT_TRUE(safe_strto32_base(std::string("0x1234"), &value, 16));
   EXPECT_EQ(0x1234, value);
 
-  // Base-10 std::string version.
+  // Base-10 string version.
   EXPECT_TRUE(safe_strto32_base("1234", &value, 10));
   EXPECT_EQ(1234, value);
 }
@@ -596,7 +656,7 @@
   EXPECT_TRUE(safe_strto64_base(std::string("0x1234"), &value, 16));
   EXPECT_EQ(0x1234, value);
 
-  // Base-10 std::string version.
+  // Base-10 string version.
   EXPECT_TRUE(safe_strto64_base("1234", &value, 10));
   EXPECT_EQ(1234, value);
 }
@@ -652,6 +712,91 @@
 TEST(stringtest, safe_strtou64_random) {
   test_random_integer_parse_base<uint64_t>(&safe_strtou64_base);
 }
+TEST(stringtest, safe_strtou128_random) {
+  // random number generators don't work for uint128, and
+  // uint128 can be streamed but not StrCat'd, so this code must be custom
+  // implemented for uint128, but is generally the same as what's above.
+  // test_random_integer_parse_base<absl::uint128>(
+  //     &absl::numbers_internal::safe_strtou128_base);
+  using RandomEngine = std::minstd_rand0;
+  using IntType = absl::uint128;
+  constexpr auto parse_func = &absl::numbers_internal::safe_strtou128_base;
+
+  std::random_device rd;
+  RandomEngine rng(rd());
+  std::uniform_int_distribution<uint64_t> random_uint64(
+      std::numeric_limits<uint64_t>::min());
+  std::uniform_int_distribution<int> random_base(2, 35);
+
+  for (size_t i = 0; i < kNumRandomTests; i++) {
+    IntType value = random_uint64(rng);
+    value = (value << 64) + random_uint64(rng);
+    int base = random_base(rng);
+    std::string str_value;
+    EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
+    IntType parsed_value;
+
+    // Test successful parse
+    EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
+    EXPECT_EQ(parsed_value, value);
+
+    // Test overflow
+    std::string s;
+    absl::strings_internal::OStringStream(&s)
+        << std::numeric_limits<IntType>::max() << value;
+    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+
+    // Test underflow
+    s.clear();
+    absl::strings_internal::OStringStream(&s) << "-" << value;
+    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+  }
+}
+TEST(stringtest, safe_strto128_random) {
+  // random number generators don't work for int128, and
+  // int128 can be streamed but not StrCat'd, so this code must be custom
+  // implemented for int128, but is generally the same as what's above.
+  // test_random_integer_parse_base<absl::int128>(
+  //     &absl::numbers_internal::safe_strto128_base);
+  using RandomEngine = std::minstd_rand0;
+  using IntType = absl::int128;
+  constexpr auto parse_func = &absl::numbers_internal::safe_strto128_base;
+
+  std::random_device rd;
+  RandomEngine rng(rd());
+  std::uniform_int_distribution<int64_t> random_int64(
+      std::numeric_limits<int64_t>::min());
+  std::uniform_int_distribution<uint64_t> random_uint64(
+      std::numeric_limits<uint64_t>::min());
+  std::uniform_int_distribution<int> random_base(2, 35);
+
+  for (size_t i = 0; i < kNumRandomTests; ++i) {
+    int64_t high = random_int64(rng);
+    uint64_t low = random_uint64(rng);
+    IntType value = absl::MakeInt128(high, low);
+
+    int base = random_base(rng);
+    std::string str_value;
+    EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
+    IntType parsed_value;
+
+    // Test successful parse
+    EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
+    EXPECT_EQ(parsed_value, value);
+
+    // Test overflow
+    std::string s;
+    absl::strings_internal::OStringStream(&s)
+        << std::numeric_limits<IntType>::max() << value;
+    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+
+    // Test underflow
+    s.clear();
+    absl::strings_internal::OStringStream(&s)
+        << std::numeric_limits<IntType>::min() << value;
+    EXPECT_FALSE(parse_func(s, &parsed_value, base));
+  }
+}
 
 TEST(stringtest, safe_strtou32_base) {
   for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
@@ -713,11 +858,11 @@
   }
 }
 
-// feenableexcept() and fedisableexcept() are missing on macOS, MSVC,
-// and WebAssembly.
-#if defined(_MSC_VER) || defined(__APPLE__) || defined(__EMSCRIPTEN__)
-#define ABSL_MISSING_FEENABLEEXCEPT 1
-#define ABSL_MISSING_FEDISABLEEXCEPT 1
+// feenableexcept() and fedisableexcept() are extensions supported by some libc
+// implementations.
+#if defined(__GLIBC__) || defined(__BIONIC__)
+#define ABSL_HAVE_FEENABLEEXCEPT 1
+#define ABSL_HAVE_FEDISABLEEXCEPT 1
 #endif
 
 class SimpleDtoaTest : public testing::Test {
@@ -725,7 +870,7 @@
   void SetUp() override {
     // Store the current floating point env & clear away any pending exceptions.
     feholdexcept(&fp_env_);
-#ifndef ABSL_MISSING_FEENABLEEXCEPT
+#ifdef ABSL_HAVE_FEENABLEEXCEPT
     // Turn on floating point exceptions.
     feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
 #endif
@@ -735,7 +880,7 @@
     // Restore the floating point environment to the original state.
     // In theory fedisableexcept is unnecessary; fesetenv will also do it.
     // In practice, our toolchains have subtle bugs.
-#ifndef ABSL_MISSING_FEDISABLEEXCEPT
+#ifdef ABSL_HAVE_FEDISABLEEXCEPT
     fedisableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
 #endif
     fesetenv(&fp_env_);
@@ -1184,4 +1329,28 @@
   }
 }
 
+void TestFastHexToBufferZeroPad16(uint64_t v) {
+  char buf[16];
+  auto digits = absl::numbers_internal::FastHexToBufferZeroPad16(v, buf);
+  absl::string_view res(buf, 16);
+  char buf2[17];
+  snprintf(buf2, sizeof(buf2), "%016" PRIx64, v);
+  EXPECT_EQ(res, buf2) << v;
+  size_t expected_digits = snprintf(buf2, sizeof(buf2), "%" PRIx64, v);
+  EXPECT_EQ(digits, expected_digits) << v;
+}
+
+TEST(FastHexToBufferZeroPad16, Smoke) {
+  TestFastHexToBufferZeroPad16(std::numeric_limits<uint64_t>::min());
+  TestFastHexToBufferZeroPad16(std::numeric_limits<uint64_t>::max());
+  TestFastHexToBufferZeroPad16(std::numeric_limits<int64_t>::min());
+  TestFastHexToBufferZeroPad16(std::numeric_limits<int64_t>::max());
+  absl::BitGen rng;
+  for (int i = 0; i < 100000; ++i) {
+    TestFastHexToBufferZeroPad16(
+        absl::LogUniform(rng, std::numeric_limits<uint64_t>::min(),
+                         std::numeric_limits<uint64_t>::max()));
+  }
+}
+
 }  // namespace
diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc
index 9961944..dd5d25b 100644
--- a/absl/strings/str_cat.cc
+++ b/absl/strings/str_cat.cc
@@ -15,34 +15,34 @@
 #include "absl/strings/str_cat.h"
 
 #include <assert.h>
+
 #include <algorithm>
 #include <cstdint>
 #include <cstring>
 
 #include "absl/strings/ascii.h"
 #include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/numbers.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 AlphaNum::AlphaNum(Hex hex) {
+  static_assert(numbers_internal::kFastToBufferSize >= 32,
+                "This function only works when output buffer >= 32 bytes long");
   char* const end = &digits_[numbers_internal::kFastToBufferSize];
-  char* writer = end;
-  uint64_t value = hex.value;
-  static const char hexdigits[] = "0123456789abcdef";
-  do {
-    *--writer = hexdigits[value & 0xF];
-    value >>= 4;
-  } while (value != 0);
-
-  char* beg;
-  if (end - writer < hex.width) {
-    beg = end - hex.width;
-    std::fill_n(beg, writer - beg, hex.fill);
+  auto real_width =
+      absl::numbers_internal::FastHexToBufferZeroPad16(hex.value, end - 16);
+  if (real_width >= hex.width) {
+    piece_ = absl::string_view(end - real_width, real_width);
   } else {
-    beg = writer;
+    // Pad first 16 chars because FastHexToBufferZeroPad16 pads only to 16 and
+    // max pad width can be up to 20.
+    std::memset(end - 32, hex.fill, 16);
+    // Patch up everything else up to the real_width.
+    std::memset(end - real_width - 16, hex.fill, 16);
+    piece_ = absl::string_view(end - hex.width, hex.width);
   }
-
-  piece_ = absl::string_view(beg, end - beg);
 }
 
 AlphaNum::AlphaNum(Dec dec) {
@@ -141,12 +141,12 @@
 std::string CatPieces(std::initializer_list<absl::string_view> pieces) {
   std::string result;
   size_t total_size = 0;
-  for (const absl::string_view piece : pieces) total_size += piece.size();
+  for (const absl::string_view& piece : pieces) total_size += piece.size();
   strings_internal::STLStringResizeUninitialized(&result, total_size);
 
   char* const begin = &result[0];
   char* out = begin;
-  for (const absl::string_view piece : pieces) {
+  for (const absl::string_view& piece : pieces) {
     const size_t this_size = piece.size();
     if (this_size != 0) {
       memcpy(out, piece.data(), this_size);
@@ -170,7 +170,7 @@
                   std::initializer_list<absl::string_view> pieces) {
   size_t old_size = dest->size();
   size_t total_size = old_size;
-  for (const absl::string_view piece : pieces) {
+  for (const absl::string_view& piece : pieces) {
     ASSERT_NO_OVERLAP(*dest, piece);
     total_size += piece.size();
   }
@@ -178,7 +178,7 @@
 
   char* const begin = &(*dest)[0];
   char* out = begin + old_size;
-  for (const absl::string_view piece : pieces) {
+  for (const absl::string_view& piece : pieces) {
     const size_t this_size = piece.size();
     if (this_size != 0) {
       memcpy(out, piece.data(), this_size);
@@ -242,4 +242,5 @@
   assert(out == begin + dest->size());
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h
index a99aac0..a8a85c7 100644
--- a/absl/strings/str_cat.h
+++ b/absl/strings/str_cat.h
@@ -64,6 +64,7 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace strings_internal {
 // AlphaNumBuffer allows a way to pass a string to StrCat without having to do
@@ -252,7 +253,7 @@
       const std::basic_string<char, std::char_traits<char>, Allocator>& str)
       : piece_(str) {}
 
-  // Use std::string literals ":" instead of character literals ':'.
+  // Use string literals ":" instead of character literals ':'.
   AlphaNum(char c) = delete;  // NOLINT(runtime/explicit)
 
   AlphaNum(const AlphaNum&) = delete;
@@ -290,7 +291,8 @@
 // StrCat()
 // -----------------------------------------------------------------------------
 //
-// Merges given strings or numbers, using no delimiter(s).
+// Merges given strings or numbers, using no delimiter(s), returning the merged
+// result as a string.
 //
 // `StrCat()` is designed to be the fastest possible way to construct a string
 // out of a mix of raw C strings, string_views, strings, bool values,
@@ -400,6 +402,7 @@
   return result;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_STR_CAT_H_
diff --git a/absl/strings/str_cat_benchmark.cc b/absl/strings/str_cat_benchmark.cc
index 14c63b3..02c4dbe 100644
--- a/absl/strings/str_cat_benchmark.cc
+++ b/absl/strings/str_cat_benchmark.cc
@@ -23,7 +23,7 @@
 namespace {
 
 const char kStringOne[] = "Once Upon A Time, ";
-const char kStringTwo[] = "There was a std::string benchmark";
+const char kStringTwo[] = "There was a string benchmark";
 
 // We want to include negative numbers in the benchmark, so this function
 // is used to count 0, 1, -1, 2, -2, 3, -3, ...
@@ -137,4 +137,51 @@
 }
 BENCHMARK(BM_DoubleToString_By_SixDigits);
 
+template <typename... Chunks>
+void BM_StrAppendImpl(benchmark::State& state, size_t total_bytes,
+                      Chunks... chunks) {
+  for (auto s : state) {
+    std::string result;
+    while (result.size() < total_bytes) {
+      absl::StrAppend(&result, chunks...);
+      benchmark::DoNotOptimize(result);
+    }
+  }
+}
+
+void BM_StrAppend(benchmark::State& state) {
+  const int total_bytes = state.range(0);
+  const int chunks_at_a_time = state.range(1);
+  const absl::string_view kChunk = "0123456789";
+
+  switch (chunks_at_a_time) {
+    case 1:
+      return BM_StrAppendImpl(state, total_bytes, kChunk);
+    case 2:
+      return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk);
+    case 4:
+      return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk,
+                              kChunk);
+    case 8:
+      return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk,
+                              kChunk, kChunk, kChunk, kChunk, kChunk);
+    default:
+      std::abort();
+  }
+}
+
+template <typename B>
+void StrAppendConfig(B* benchmark) {
+  for (int bytes : {10, 100, 1000, 10000}) {
+    for (int chunks : {1, 2, 4, 8}) {
+      // Only add the ones that divide properly. Otherwise we are over counting.
+      if (bytes % (10 * chunks) == 0) {
+        benchmark->Args({bytes, chunks});
+      }
+    }
+  }
+}
+
+BENCHMARK(BM_StrAppend)->Apply(StrAppendConfig);
+
 }  // namespace
diff --git a/absl/strings/str_cat_test.cc b/absl/strings/str_cat_test.cc
index be39880..f3770dc 100644
--- a/absl/strings/str_cat_test.cc
+++ b/absl/strings/str_cat_test.cc
@@ -162,7 +162,7 @@
   EXPECT_EQ(result, "12345678910, 10987654321!");
 
   std::string one =
-      "1";  // Actually, it's the size of this std::string that we want; a
+      "1";  // Actually, it's the size of this string that we want; a
             // 64-bit build distinguishes between size_t and uint64_t,
             // even though they're both unsigned 64-bit values.
   result = absl::StrCat("And a ", one.size(), " and a ",
@@ -375,7 +375,7 @@
   EXPECT_EQ(result.substr(old_size), "12345678910, 10987654321!");
 
   std::string one =
-      "1";  // Actually, it's the size of this std::string that we want; a
+      "1";  // Actually, it's the size of this string that we want; a
             // 64-bit build distinguishes between size_t and uint64_t,
             // even though they're both unsigned 64-bit values.
   old_size = result.size();
@@ -463,7 +463,7 @@
 }
 
 TEST(StrAppend, CornerCasesNonEmptyAppend) {
-  for (std::string result : {"hello", "a std::string too long to fit in the SSO"}) {
+  for (std::string result : {"hello", "a string too long to fit in the SSO"}) {
     const std::string expected = result;
     absl::StrAppend(&result, "");
     EXPECT_EQ(result, expected);
diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h
index 607e2bc..0146510 100644
--- a/absl/strings/str_format.h
+++ b/absl/strings/str_format.h
@@ -19,7 +19,7 @@
 //
 // 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
+// header. Like the `printf` family, `str_format` uses a "format string" to
 // perform argument substitutions based on types. See the `FormatSpec` section
 // below for format string documentation.
 //
@@ -57,8 +57,7 @@
 // arbitrary sink types:
 //
 //   * A generic `Format()` function to write outputs to arbitrary sink types,
-//     which must implement a `RawSinkFormat` interface. (See
-//     `str_format_sink.h` for more information.)
+//     which must implement a `FormatRawSink` interface.
 //
 //   * A `FormatUntyped()` function that is similar to `Format()` except it is
 //     loosely typed. `FormatUntyped()` is not a template and does not perform
@@ -66,8 +65,7 @@
 //     boolean from a runtime check.
 //
 // 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.
+// augmenting formatting to new types.  See "StrFormat Extensions" below.
 
 #ifndef ABSL_STRINGS_STR_FORMAT_H_
 #define ABSL_STRINGS_STR_FORMAT_H_
@@ -82,6 +80,7 @@
 #include "absl/strings/internal/str_format/parser.h"  // IWYU pragma: export
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // UntypedFormatSpec
 //
@@ -254,8 +253,8 @@
 // argument, etc.
 
 template <typename... Args>
-using FormatSpec =
-    typename str_format_internal::FormatSpecDeductionBarrier<Args...>::type;
+using FormatSpec = str_format_internal::FormatSpecTemplate<
+    str_format_internal::ArgumentToConv<Args>()...>;
 
 // ParsedFormat
 //
@@ -282,9 +281,36 @@
 //   } else {
 //     ... error case ...
 //   }
+
+#if defined(__cpp_nontype_template_parameter_auto)
+// If C++17 is available, an 'extended' format is also allowed that can specify
+// multiple conversion characters per format argument, using a combination of
+// `absl::FormatConversionCharSet` enum values (logically a set union)
+//  via the `|` operator. (Single character-based arguments are still accepted,
+// but cannot be combined). Some common conversions also have predefined enum
+// values, such as `absl::FormatConversionCharSet::kIntegral`.
+//
+// Example:
+//   // Extended format supports multiple conversion characters per argument,
+//   // specified via a combination of `FormatConversionCharSet` enums.
+//   using MyFormat = absl::ParsedFormat<absl::FormatConversionCharSet::d |
+//                                       absl::FormatConversionCharSet::x>;
+//   MyFormat GetFormat(bool use_hex) {
+//     if (use_hex) return MyFormat("foo %x bar");
+//     return MyFormat("foo %d bar");
+//   }
+//   // `format` can be used with any value that supports 'd' and 'x',
+//   // like `int`.
+//   auto format = GetFormat(use_hex);
+//   value = StringF(format, i);
+template <auto... Conv>
+using ParsedFormat = absl::str_format_internal::ExtendedParsedFormat<
+    absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
+#else
 template <char... Conv>
 using ParsedFormat = str_format_internal::ExtendedParsedFormat<
-    str_format_internal::ConversionCharToConv(Conv)...>;
+    absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
+#endif  // defined(__cpp_nontype_template_parameter_auto)
 
 // StrFormat()
 //
@@ -400,6 +426,12 @@
 // This function is functionally equivalent to `std::snprintf()` (and
 // type-safe); prefer `absl::SNPrintF()` over `std::snprintf()`.
 //
+// In particular, a successful call to `absl::SNPrintF()` writes at most `size`
+// bytes of the formatted output to `output`, including a NUL-terminator, and
+// returns the number of bytes that would have been written if truncation did
+// not occur. In the event of an error, a negative value is returned and `errno`
+// is set.
+//
 // Example:
 //
 //   std::string_view s = "Ulaanbaatar";
@@ -425,6 +457,16 @@
 //
 // FormatRawSink is a type erased wrapper around arbitrary sink objects
 // specifically used as an argument to `Format()`.
+//
+// All the object has to do define an overload of `AbslFormatFlush()` for the
+// sink, usually by adding a ADL-based free function in the same namespace as
+// the sink:
+//
+//   void AbslFormatFlush(MySink* dest, absl::string_view part);
+//
+// where `dest` is the pointer passed to `absl::Format()`. The function should
+// append `part` to `dest`.
+//
 // FormatRawSink does not own the passed sink object. The passed object must
 // outlive the FormatRawSink.
 class FormatRawSink {
@@ -448,12 +490,13 @@
 // `absl::FormatRawSink` interface), using a format string and zero or more
 // additional arguments.
 //
-// By default, `std::string` and `std::ostream` are supported as destination
-// objects. If a `std::string` is used the formatted string is appended to it.
+// By default, `std::string`, `std::ostream`, and `absl::Cord` are supported as
+// destination objects. If a `std::string` is used the formatted string is
+// appended to it.
 //
-// `absl::Format()` is a generic version of `absl::StrFormat(), for custom
-// sinks. The format string, like format strings for `StrFormat()`, is checked
-// at compile-time.
+// `absl::Format()` is a generic version of `absl::StrAppendFormat()`, for
+// custom sinks. The format string, like format strings for `StrFormat()`, is
+// checked at compile-time.
 //
 // On failure, this function returns `false` and the state of the sink is
 // unspecified.
@@ -524,6 +567,247 @@
       str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
 }
 
+//------------------------------------------------------------------------------
+// StrFormat Extensions
+//------------------------------------------------------------------------------
+//
+// AbslFormatConvert()
+//
+// The StrFormat library provides a customization API for formatting
+// user-defined types using absl::StrFormat(). The API relies on detecting an
+// overload in the user-defined type's namespace of a free (non-member)
+// `AbslFormatConvert()` function, usually as a friend definition with the
+// following signature:
+//
+// absl::FormatConvertResult<...> AbslFormatConvert(
+//     const X& value,
+//     const absl::FormatConversionSpec& spec,
+//     absl::FormatSink *sink);
+//
+// An `AbslFormatConvert()` overload for a type should only be declared in the
+// same file and namespace as said type.
+//
+// The abstractions within this definition include:
+//
+// * An `absl::FormatConversionSpec` to specify the fields to pull from a
+//   user-defined type's format string
+// * An `absl::FormatSink` to hold the converted string data during the
+//   conversion process.
+// * An `absl::FormatConvertResult` to hold the status of the returned
+//   formatting operation
+//
+// The return type encodes all the conversion characters that your
+// AbslFormatConvert() routine accepts.  The return value should be {true}.
+// A return value of {false} will result in `StrFormat()` returning
+// an empty string.  This result will be propagated to the result of
+// `FormatUntyped`.
+//
+// Example:
+//
+// struct Point {
+//   // To add formatting support to `Point`, we simply need to add a free
+//   // (non-member) function `AbslFormatConvert()`.  This method interprets
+//   // `spec` to print in the request format. The allowed conversion characters
+//   // can be restricted via the type of the result, in this example
+//   // string and integral formatting are allowed (but not, for instance
+//   // floating point characters like "%f").  You can add such a free function
+//   // using a friend declaration within the body of the class:
+//   friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
+//                                    absl::FormatConversionCharSet::kIntegral>
+//   AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
+//                     absl::FormatSink* s) {
+//     if (spec.conversion_char() == absl::FormatConversionChar::s) {
+//       s->Append(absl::StrCat("x=", p.x, " y=", p.y));
+//     } else {
+//       s->Append(absl::StrCat(p.x, ",", p.y));
+//     }
+//     return {true};
+//   }
+//
+//   int x;
+//   int y;
+// };
+
+// clang-format off
+
+// FormatConversionChar
+//
+// Specifies the formatting character provided in the format string
+// passed to `StrFormat()`.
+enum class FormatConversionChar : uint8_t {
+  c, s,                    // text
+  d, i, o, u, x, X,        // int
+  f, F, e, E, g, G, a, A,  // float
+  n, p                     // misc
+};
+// clang-format on
+
+// FormatConversionSpec
+//
+// Specifies modifications to the conversion of the format string, through use
+// of one or more format flags in the source format string.
+class FormatConversionSpec {
+ public:
+  // FormatConversionSpec::is_basic()
+  //
+  // Indicates that width and precision are not specified, and no additional
+  // flags are set for this conversion character in the format string.
+  bool is_basic() const { return impl_.is_basic(); }
+
+  // FormatConversionSpec::has_left_flag()
+  //
+  // Indicates whether the result should be left justified for this conversion
+  // character in the format string. This flag is set through use of a '-'
+  // character in the format string. E.g. "%-s"
+  bool has_left_flag() const { return impl_.has_left_flag(); }
+
+  // FormatConversionSpec::has_show_pos_flag()
+  //
+  // Indicates whether a sign column is prepended to the result for this
+  // conversion character in the format string, even if the result is positive.
+  // This flag is set through use of a '+' character in the format string.
+  // E.g. "%+d"
+  bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }
+
+  // FormatConversionSpec::has_sign_col_flag()
+  //
+  // Indicates whether a mandatory sign column is added to the result for this
+  // conversion character. This flag is set through use of a space character
+  // (' ') in the format string. E.g. "% i"
+  bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }
+
+  // FormatConversionSpec::has_alt_flag()
+  //
+  // Indicates whether an "alternate" format is applied to the result for this
+  // conversion character. Alternative forms depend on the type of conversion
+  // character, and unallowed alternatives are undefined. This flag is set
+  // through use of a '#' character in the format string. E.g. "%#h"
+  bool has_alt_flag() const { return impl_.has_alt_flag(); }
+
+  // FormatConversionSpec::has_zero_flag()
+  //
+  // Indicates whether zeroes should be prepended to the result for this
+  // conversion character instead of spaces. This flag is set through use of the
+  // '0' character in the format string. E.g. "%0f"
+  bool has_zero_flag() const { return impl_.has_zero_flag(); }
+
+  // FormatConversionSpec::conversion_char()
+  //
+  // Returns the underlying conversion character.
+  FormatConversionChar conversion_char() const {
+    return impl_.conversion_char();
+  }
+
+  // FormatConversionSpec::width()
+  //
+  // Returns the specified width (indicated through use of a non-zero integer
+  // value or '*' character) of the conversion character. If width is
+  // unspecified, it returns a negative value.
+  int width() const { return impl_.width(); }
+
+  // FormatConversionSpec::precision()
+  //
+  // Returns the specified precision (through use of the '.' character followed
+  // by a non-zero integer value or '*' character) of the conversion character.
+  // If precision is unspecified, it returns a negative value.
+  int precision() const { return impl_.precision(); }
+
+ private:
+  explicit FormatConversionSpec(
+      str_format_internal::FormatConversionSpecImpl impl)
+      : impl_(impl) {}
+
+  friend str_format_internal::FormatConversionSpecImpl;
+
+  absl::str_format_internal::FormatConversionSpecImpl impl_;
+};
+
+// Type safe OR operator for FormatConversionCharSet to allow accepting multiple
+// conversion chars in custom format converters.
+constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
+                                            FormatConversionCharSet b) {
+  return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |
+                                              static_cast<uint64_t>(b));
+}
+
+// FormatConversionCharSet
+//
+// Specifies the _accepted_ conversion types as a template parameter to
+// FormatConvertResult for custom implementations of `AbslFormatConvert`.
+// Note the helper predefined alias definitions (kIntegral, etc.) below.
+enum class FormatConversionCharSet : uint64_t {
+  // text
+  c = str_format_internal::FormatConversionCharToConvInt('c'),
+  s = str_format_internal::FormatConversionCharToConvInt('s'),
+  // integer
+  d = str_format_internal::FormatConversionCharToConvInt('d'),
+  i = str_format_internal::FormatConversionCharToConvInt('i'),
+  o = str_format_internal::FormatConversionCharToConvInt('o'),
+  u = str_format_internal::FormatConversionCharToConvInt('u'),
+  x = str_format_internal::FormatConversionCharToConvInt('x'),
+  X = str_format_internal::FormatConversionCharToConvInt('X'),
+  // Float
+  f = str_format_internal::FormatConversionCharToConvInt('f'),
+  F = str_format_internal::FormatConversionCharToConvInt('F'),
+  e = str_format_internal::FormatConversionCharToConvInt('e'),
+  E = str_format_internal::FormatConversionCharToConvInt('E'),
+  g = str_format_internal::FormatConversionCharToConvInt('g'),
+  G = str_format_internal::FormatConversionCharToConvInt('G'),
+  a = str_format_internal::FormatConversionCharToConvInt('a'),
+  A = str_format_internal::FormatConversionCharToConvInt('A'),
+  // misc
+  n = str_format_internal::FormatConversionCharToConvInt('n'),
+  p = str_format_internal::FormatConversionCharToConvInt('p'),
+
+  // Used for width/precision '*' specification.
+  kStar = static_cast<uint64_t>(
+      absl::str_format_internal::FormatConversionCharSetInternal::kStar),
+  // Some predefined values:
+  kIntegral = d | i | u | o | x | X,
+  kFloating = a | e | f | g | A | E | F | G,
+  kNumeric = kIntegral | kFloating,
+  kString = s,
+  kPointer = p,
+};
+
+// FormatSink
+//
+// An abstraction to which conversions write their string data.
+//
+class FormatSink {
+ public:
+  // Appends `count` copies of `ch`.
+  void Append(size_t count, char ch) { sink_->Append(count, ch); }
+
+  void Append(string_view v) { sink_->Append(v); }
+
+  // Appends the first `precision` bytes of `v`. If this is less than
+  // `width`, spaces will be appended first (if `left` is false), or
+  // after (if `left` is true) to ensure the total amount appended is
+  // at least `width`.
+  bool PutPaddedString(string_view v, int width, int precision, bool left) {
+    return sink_->PutPaddedString(v, width, precision, left);
+  }
+
+ private:
+  friend str_format_internal::FormatSinkImpl;
+  explicit FormatSink(str_format_internal::FormatSinkImpl* s) : sink_(s) {}
+  str_format_internal::FormatSinkImpl* sink_;
+};
+
+// FormatConvertResult
+//
+// Indicates whether a call to AbslFormatConvert() was successful.
+// This return type informs the StrFormat extension framework (through
+// ADL but using the return type) of what conversion characters are supported.
+// It is strongly discouraged to return {false}, as this will result in an
+// empty string in StrFormat.
+template <FormatConversionCharSet C>
+struct FormatConvertResult {
+  bool value;
+};
+
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_STR_FORMAT_H_
diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc
index cfd81bb..c60027a 100644
--- a/absl/strings/str_format_test.cc
+++ b/absl/strings/str_format_test.cc
@@ -1,3 +1,18 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/str_format.h"
 
 #include <cstdarg>
 #include <cstdint>
@@ -6,10 +21,12 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
-#include "absl/strings/str_format.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 using str_format_internal::FormatArgImpl;
 
@@ -241,7 +258,7 @@
 
   std::FILE* file() const { return file_; }
 
-  // Read the file into a std::string.
+  // Read the file into a string.
   std::string ReadFile() {
     std::fseek(file_, 0, SEEK_END);
     int size = std::ftell(file_);
@@ -344,11 +361,12 @@
   EXPECT_EQ(StrFormat("%c", int{'a'}), "a");
   EXPECT_EQ(StrFormat("%c", long{'a'}), "a");  // NOLINT
   EXPECT_EQ(StrFormat("%c", uint64_t{'a'}), "a");
-  //     "s" - std::string       Eg: "C" -> "C", std::string("C++") -> "C++"
+  //     "s" - string       Eg: "C" -> "C", std::string("C++") -> "C++"
   //           Formats std::string, char*, string_view, and Cord.
   EXPECT_EQ(StrFormat("%s", "C"), "C");
   EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
   EXPECT_EQ(StrFormat("%s", string_view("view")), "view");
+  EXPECT_EQ(StrFormat("%s", absl::Cord("cord")), "cord");
   // Integral Conversion
   //     These format integral types: char, int, long, uint64_t, etc.
   EXPECT_EQ(StrFormat("%d", char{10}), "10");
@@ -449,7 +467,7 @@
     if (conv.precision.is_from_arg()) {
       *out += "." + std::to_string(conv.precision.get_from_arg()) + "$*";
     }
-    *out += conv.conv.Char();
+    *out += str_format_internal::FormatConversionCharToChar(conv.conv);
     *out += "}";
     return true;
   }
@@ -531,76 +549,152 @@
   EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format)));
 }
 
-using str_format_internal::Conv;
+#if defined(__cpp_nontype_template_parameter_auto)
+
+template <auto T>
+std::true_type IsValidParsedFormatArgTest(ParsedFormat<T>*);
+
+template <auto T>
+std::false_type IsValidParsedFormatArgTest(...);
+
+template <auto T>
+using IsValidParsedFormatArg = decltype(IsValidParsedFormatArgTest<T>(nullptr));
+
+TEST_F(ParsedFormatTest, OnlyValidTypesAllowed) {
+  ASSERT_TRUE(IsValidParsedFormatArg<'c'>::value);
+
+  ASSERT_TRUE(IsValidParsedFormatArg<FormatConversionCharSet::d>::value);
+
+  ASSERT_TRUE(IsValidParsedFormatArg<absl::FormatConversionCharSet::d |
+                                     absl::FormatConversionCharSet::x>::value);
+  ASSERT_TRUE(
+      IsValidParsedFormatArg<absl::FormatConversionCharSet::kIntegral>::value);
+
+  // This is an easy mistake to make, however, this will reduce to an integer
+  // which has no meaning, so we need to ensure it doesn't compile.
+  ASSERT_FALSE(IsValidParsedFormatArg<'x' | 'd'>::value);
+
+  // For now, we disallow construction based on ConversionChar (rather than
+  // CharSet)
+  ASSERT_FALSE(IsValidParsedFormatArg<absl::FormatConversionChar::d>::value);
+}
+
+TEST_F(ParsedFormatTest, ExtendedTyping) {
+  EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::d>::New(""));
+  ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::d>::New("%d"));
+  auto v1 = ParsedFormat<'d', absl::FormatConversionCharSet::s>::New("%d%s");
+  ASSERT_TRUE(v1);
+  auto v2 = ParsedFormat<absl::FormatConversionCharSet::d, 's'>::New("%d%s");
+  ASSERT_TRUE(v2);
+  auto v3 = ParsedFormat<absl::FormatConversionCharSet::d |
+                             absl::FormatConversionCharSet::s,
+                         's'>::New("%d%s");
+  ASSERT_TRUE(v3);
+  auto v4 = ParsedFormat<absl::FormatConversionCharSet::d |
+                             absl::FormatConversionCharSet::s,
+                         's'>::New("%s%s");
+  ASSERT_TRUE(v4);
+}
+#endif
 
 TEST_F(ParsedFormatTest, UncheckedCorrect) {
-  auto f = ExtendedParsedFormat<Conv::d>::New("ABC%dDEF");
+  auto f =
+      ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("ABC%dDEF");
   ASSERT_TRUE(f);
   EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
 
   std::string format = "%sFFF%dZZZ%f";
-  auto f2 =
-      ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(format);
+  auto f2 = ExtendedParsedFormat<
+      absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
+      absl::FormatConversionCharSet::kFloating>::New(format);
 
   ASSERT_TRUE(f2);
   EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
 
-  f2 = ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(
-      "%s %d %f");
+  f2 = ExtendedParsedFormat<
+      absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
+      absl::FormatConversionCharSet::kFloating>::New("%s %d %f");
 
   ASSERT_TRUE(f2);
   EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
 
-  auto star = ExtendedParsedFormat<Conv::star, Conv::d>::New("%*d");
+  auto star =
+      ExtendedParsedFormat<absl::FormatConversionCharSet::kStar,
+                           absl::FormatConversionCharSet::d>::New("%*d");
   ASSERT_TRUE(star);
   EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
 
-  auto dollar = ExtendedParsedFormat<Conv::d, Conv::s>::New("%2$s %1$d");
+  auto dollar =
+      ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+                           absl::FormatConversionCharSet::s>::New("%2$s %1$d");
   ASSERT_TRUE(dollar);
   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
   // with reuse
-  dollar = ExtendedParsedFormat<Conv::d, Conv::s>::New("%2$s %1$d %1$d");
+  dollar = ExtendedParsedFormat<
+      absl::FormatConversionCharSet::d,
+      absl::FormatConversionCharSet::s>::New("%2$s %1$d %1$d");
   ASSERT_TRUE(dollar);
   EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
             SummarizeParsedFormat(*dollar));
 }
 
 TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
-  EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("ABC")));
-  EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("%dABC")));
-  EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("ABC%2$s")));
-  auto f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("ABC");
+  EXPECT_FALSE(
+      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+                            absl::FormatConversionCharSet::s>::New("ABC")));
+  EXPECT_FALSE(
+      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+                            absl::FormatConversionCharSet::s>::New("%dABC")));
+  EXPECT_FALSE(
+      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+                            absl::FormatConversionCharSet::s>::New("ABC%2$s")));
+  auto f = ExtendedParsedFormat<
+      absl::FormatConversionCharSet::d,
+      absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC");
   ASSERT_TRUE(f);
   EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
-  f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("%dABC");
+  f = ExtendedParsedFormat<
+      absl::FormatConversionCharSet::d,
+      absl::FormatConversionCharSet::s>::NewAllowIgnored("%dABC");
   ASSERT_TRUE(f);
   EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
-  f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("ABC%2$s");
+  f = ExtendedParsedFormat<
+      absl::FormatConversionCharSet::d,
+      absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s");
   ASSERT_TRUE(f);
   EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
 }
 
 TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
-  auto dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d %1$x");
+  auto dx =
+      ExtendedParsedFormat<absl::FormatConversionCharSet::d |
+                           absl::FormatConversionCharSet::x>::New("%1$d %1$x");
   EXPECT_TRUE(dx);
   EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx));
 
-  dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d");
+  dx = ExtendedParsedFormat<absl::FormatConversionCharSet::d |
+                            absl::FormatConversionCharSet::x>::New("%1$d");
   EXPECT_TRUE(dx);
   EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx));
 }
 
 TEST_F(ParsedFormatTest, UncheckedIncorrect) {
-  EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New(""));
+  EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(""));
 
-  EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New("ABC%dDEF%d"));
+  EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(
+      "ABC%dDEF%d"));
 
   std::string format = "%sFFF%dZZZ%f";
-  EXPECT_FALSE((ExtendedParsedFormat<Conv::s, Conv::d, Conv::g>::New(format)));
+  EXPECT_FALSE(
+      (ExtendedParsedFormat<absl::FormatConversionCharSet::s,
+                            absl::FormatConversionCharSet::d,
+                            absl::FormatConversionCharSet::g>::New(format)));
 }
 
 TEST_F(ParsedFormatTest, RegressionMixPositional) {
-  EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::o>::New("%1$d %o")));
+  EXPECT_FALSE(
+      (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+                            absl::FormatConversionCharSet::o>::New("%1$d %o")));
 }
 
 using FormatWrapperTest = ::testing::Test;
@@ -622,8 +716,41 @@
 }
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
 
+using FormatExtensionTest = ::testing::Test;
+
+struct Point {
+  friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
+                                   absl::FormatConversionCharSet::kIntegral>
+  AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
+                    absl::FormatSink* s) {
+    if (spec.conversion_char() == absl::FormatConversionChar::s) {
+      s->Append(absl::StrCat("x=", p.x, " y=", p.y));
+    } else {
+      s->Append(absl::StrCat(p.x, ",", p.y));
+    }
+    return {true};
+  }
+
+  int x = 10;
+  int y = 20;
+};
+
+TEST_F(FormatExtensionTest, AbslFormatConvertExample) {
+  Point p;
+  EXPECT_EQ(absl::StrFormat("a %s z", p), "a x=10 y=20 z");
+  EXPECT_EQ(absl::StrFormat("a %d z", p), "a 10,20 z");
+
+  // Typed formatting will fail to compile an invalid format.
+  // StrFormat("%f", p);  // Does not compile.
+  std::string actual;
+  absl::UntypedFormatSpec f1("%f");
+  // FormatUntyped will return false for bad character.
+  EXPECT_FALSE(absl::FormatUntyped(&actual, f1, {absl::FormatArg(p)}));
+}
+
 // Some codegen thunks that we can use to easily dump the generated assembly for
 // different StrFormat calls.
 
diff --git a/absl/strings/str_join.h b/absl/strings/str_join.h
index 4772f5d..ae5731a 100644
--- a/absl/strings/str_join.h
+++ b/absl/strings/str_join.h
@@ -60,6 +60,7 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // -----------------------------------------------------------------------------
 // Concept: Formatter
@@ -286,6 +287,7 @@
   return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter());
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_STR_JOIN_H_
diff --git a/absl/strings/str_join_test.cc b/absl/strings/str_join_test.cc
index 921d9c2..2be6256 100644
--- a/absl/strings/str_join_test.cc
+++ b/absl/strings/str_join_test.cc
@@ -134,26 +134,26 @@
   //
 
   {
-    // Empty range yields an empty std::string.
+    // Empty range yields an empty string.
     std::vector<std::string> v;
     EXPECT_EQ("", absl::StrJoin(v, "-"));
   }
 
   {
-    // A range of 1 element gives a std::string with that element but no
+    // A range of 1 element gives a string with that element but no
     // separator.
     std::vector<std::string> v = {"foo"};
     EXPECT_EQ("foo", absl::StrJoin(v, "-"));
   }
 
   {
-    // A range with a single empty std::string element
+    // A range with a single empty string element
     std::vector<std::string> v = {""};
     EXPECT_EQ("", absl::StrJoin(v, "-"));
   }
 
   {
-    // A range with 2 elements, one of which is an empty std::string
+    // A range with 2 elements, one of which is an empty string
     std::vector<std::string> v = {"a", ""};
     EXPECT_EQ("a-", absl::StrJoin(v, "-"));
   }
diff --git a/absl/strings/str_replace.cc b/absl/strings/str_replace.cc
index 280f63d..2bd5fa9 100644
--- a/absl/strings/str_replace.cc
+++ b/absl/strings/str_replace.cc
@@ -17,6 +17,7 @@
 #include "absl/strings/str_cat.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace strings_internal {
 
 using FixedMapping =
@@ -77,4 +78,5 @@
   return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/str_replace.h b/absl/strings/str_replace.h
index 30540d0..273c707 100644
--- a/absl/strings/str_replace.h
+++ b/absl/strings/str_replace.h
@@ -46,6 +46,7 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // StrReplaceAll()
 //
@@ -212,6 +213,7 @@
   return substitutions;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_STR_REPLACE_H_
diff --git a/absl/strings/str_replace_benchmark.cc b/absl/strings/str_replace_benchmark.cc
index 95b2dc1..01331da 100644
--- a/absl/strings/str_replace_benchmark.cc
+++ b/absl/strings/str_replace_benchmark.cc
@@ -62,7 +62,7 @@
       }
     }
     // big_string->resize(50);
-    // OK, we've set up the std::string, now let's set up expectations - first by
+    // OK, we've set up the string, now let's set up expectations - first by
     // just replacing "the" with "box"
     after_replacing_the = new std::string(*big_string);
     for (size_t pos = 0;
diff --git a/absl/strings/str_replace_test.cc b/absl/strings/str_replace_test.cc
index 1ca23af..9d8c7f7 100644
--- a/absl/strings/str_replace_test.cc
+++ b/absl/strings/str_replace_test.cc
@@ -25,7 +25,7 @@
 TEST(StrReplaceAll, OneReplacement) {
   std::string s;
 
-  // Empty std::string.
+  // Empty string.
   s = absl::StrReplaceAll(s, {{"", ""}});
   EXPECT_EQ(s, "");
   s = absl::StrReplaceAll(s, {{"x", ""}});
@@ -47,7 +47,7 @@
   s = absl::StrReplaceAll("abc", {{"xyz", "123"}});
   EXPECT_EQ(s, "abc");
 
-  // Replace entire std::string.
+  // Replace entire string.
   s = absl::StrReplaceAll("abc", {{"abc", "xyz"}});
   EXPECT_EQ(s, "xyz");
 
@@ -88,7 +88,7 @@
 TEST(StrReplaceAll, ManyReplacements) {
   std::string s;
 
-  // Empty std::string.
+  // Empty string.
   s = absl::StrReplaceAll("", {{"", ""}, {"x", ""}, {"", "y"}, {"x", "y"}});
   EXPECT_EQ(s, "");
 
@@ -96,7 +96,7 @@
   s = absl::StrReplaceAll("abc", {{"", ""}, {"", "y"}, {"x", ""}});
   EXPECT_EQ(s, "abc");
 
-  // Replace entire std::string, one char at a time
+  // Replace entire string, one char at a time
   s = absl::StrReplaceAll("abc", {{"a", "x"}, {"b", "y"}, {"c", "z"}});
   EXPECT_EQ(s, "xyz");
   s = absl::StrReplaceAll("zxy", {{"z", "x"}, {"x", "y"}, {"y", "z"}});
@@ -264,7 +264,7 @@
   std::string s;
   int reps;
 
-  // Empty std::string.
+  // Empty string.
   s = "";
   reps = absl::StrReplaceAll({{"", ""}, {"x", ""}, {"", "y"}, {"x", "y"}}, &s);
   EXPECT_EQ(reps, 0);
@@ -276,7 +276,7 @@
   EXPECT_EQ(reps, 0);
   EXPECT_EQ(s, "abc");
 
-  // Replace entire std::string, one char at a time
+  // Replace entire string, one char at a time
   s = "abc";
   reps = absl::StrReplaceAll({{"a", "x"}, {"b", "y"}, {"c", "z"}}, &s);
   EXPECT_EQ(reps, 3);
diff --git a/absl/strings/str_split.cc b/absl/strings/str_split.cc
index 2593130..e08c26b 100644
--- a/absl/strings/str_split.cc
+++ b/absl/strings/str_split.cc
@@ -27,6 +27,7 @@
 #include "absl/strings/ascii.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace {
 
@@ -41,7 +42,7 @@
                               absl::string_view delimiter, size_t pos,
                               FindPolicy find_policy) {
   if (delimiter.empty() && text.length() > 0) {
-    // Special case for empty std::string delimiters: always return a zero-length
+    // Special case for empty string delimiters: always return a zero-length
     // absl::string_view referring to the item at position 1 past pos.
     return absl::string_view(text.data() + pos + 1, 0);
   }
@@ -126,7 +127,7 @@
                                       size_t pos) const {
   pos = std::min(pos, text.size());  // truncate `pos`
   absl::string_view substr = text.substr(pos);
-  // If the std::string is shorter than the chunk size we say we
+  // If the string is shorter than the chunk size we say we
   // "can't find the delimiter" so this will be the last chunk.
   if (substr.length() <= static_cast<size_t>(length_))
     return absl::string_view(text.data() + text.size(), 0);
@@ -134,4 +135,5 @@
   return absl::string_view(substr.data() + length_, 0);
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/str_split.h b/absl/strings/str_split.h
index 7333078..bfbca42 100644
--- a/absl/strings/str_split.h
+++ b/absl/strings/str_split.h
@@ -44,11 +44,13 @@
 #include <vector>
 
 #include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
 #include "absl/strings/internal/str_split_internal.h"
 #include "absl/strings/string_view.h"
 #include "absl/strings/strip.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 //------------------------------------------------------------------------------
 // Delimiters
@@ -367,6 +369,12 @@
   }
 };
 
+template <typename T>
+using EnableSplitIfString =
+    typename std::enable_if<std::is_same<T, std::string>::value ||
+                            std::is_same<T, const std::string>::value,
+                            int>::type;
+
 //------------------------------------------------------------------------------
 //                                  StrSplit()
 //------------------------------------------------------------------------------
@@ -487,25 +495,54 @@
 // Try not to depend on this distinction because the bug may one day be fixed.
 template <typename Delimiter>
 strings_internal::Splitter<
-    typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty>
+    typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty,
+    absl::string_view>
 StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d) {
   using DelimiterType =
       typename strings_internal::SelectDelimiter<Delimiter>::type;
-  return strings_internal::Splitter<DelimiterType, AllowEmpty>(
+  return strings_internal::Splitter<DelimiterType, AllowEmpty,
+                                    absl::string_view>(
+      text.value(), DelimiterType(d), AllowEmpty());
+}
+
+template <typename Delimiter, typename StringType,
+          EnableSplitIfString<StringType> = 0>
+strings_internal::Splitter<
+    typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty,
+    std::string>
+StrSplit(StringType&& text, Delimiter d) {
+  using DelimiterType =
+      typename strings_internal::SelectDelimiter<Delimiter>::type;
+  return strings_internal::Splitter<DelimiterType, AllowEmpty, std::string>(
       std::move(text), DelimiterType(d), AllowEmpty());
 }
 
 template <typename Delimiter, typename Predicate>
 strings_internal::Splitter<
-    typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate>
+    typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,
+    absl::string_view>
 StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d,
          Predicate p) {
   using DelimiterType =
       typename strings_internal::SelectDelimiter<Delimiter>::type;
-  return strings_internal::Splitter<DelimiterType, Predicate>(
+  return strings_internal::Splitter<DelimiterType, Predicate,
+                                    absl::string_view>(
+      text.value(), DelimiterType(d), std::move(p));
+}
+
+template <typename Delimiter, typename Predicate, typename StringType,
+          EnableSplitIfString<StringType> = 0>
+strings_internal::Splitter<
+    typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,
+    std::string>
+StrSplit(StringType&& text, Delimiter d, Predicate p) {
+  using DelimiterType =
+      typename strings_internal::SelectDelimiter<Delimiter>::type;
+  return strings_internal::Splitter<DelimiterType, Predicate, std::string>(
       std::move(text), DelimiterType(d), std::move(p));
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_STR_SPLIT_H_
diff --git a/absl/strings/str_split_test.cc b/absl/strings/str_split_test.cc
index 02f27bc..7f7c097 100644
--- a/absl/strings/str_split_test.cc
+++ b/absl/strings/str_split_test.cc
@@ -27,8 +27,10 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
-#include "absl/base/dynamic_annotations.h"  // for RunningOnValgrind
+#include "absl/base/dynamic_annotations.h"
 #include "absl/base/macros.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/node_hash_map.h"
 #include "absl/strings/numbers.h"
 
 namespace {
@@ -71,7 +73,7 @@
 // namespaces just like callers will need to use.
 TEST(Split, APIExamples) {
   {
-    // Passes std::string delimiter. Assumes the default of ByString.
+    // Passes string delimiter. Assumes the default of ByString.
     std::vector<std::string> v = absl::StrSplit("a,b,c", ",");  // NOLINT
     EXPECT_THAT(v, ElementsAre("a", "b", "c"));
 
@@ -97,7 +99,7 @@
   }
 
   {
-    // Uses the Literal std::string "=>" as the delimiter.
+    // Uses the Literal string "=>" as the delimiter.
     const std::vector<std::string> v = absl::StrSplit("a=>b=>c", "=>");
     EXPECT_THAT(v, ElementsAre("a", "b", "c"));
   }
@@ -121,17 +123,17 @@
   }
 
   {
-    // Splits the input std::string into individual characters by using an empty
-    // std::string as the delimiter.
+    // Splits the input string into individual characters by using an empty
+    // string as the delimiter.
     std::vector<std::string> v = absl::StrSplit("abc", "");
     EXPECT_THAT(v, ElementsAre("a", "b", "c"));
   }
 
   {
-    // Splits std::string data with embedded NUL characters, using NUL as the
+    // Splits string data with embedded NUL characters, using NUL as the
     // delimiter. A simple delimiter of "\0" doesn't work because strlen() will
-    // say that's the empty std::string when constructing the absl::string_view
-    // delimiter. Instead, a non-empty std::string containing NUL can be used as the
+    // say that's the empty string when constructing the absl::string_view
+    // delimiter. Instead, a non-empty string containing NUL can be used as the
     // delimiter.
     std::string embedded_nulls("a\0b\0c", 5);
     std::string null_delim("\0", 1);
@@ -365,7 +367,7 @@
 TEST(Splitter, RangeIterators) {
   auto splitter = absl::StrSplit("a,b,c", ',');
   std::vector<absl::string_view> output;
-  for (const absl::string_view p : splitter) {
+  for (const absl::string_view& p : splitter) {
     output.push_back(p);
   }
   EXPECT_THAT(output, ElementsAre("a", "b", "c"));
@@ -421,6 +423,18 @@
   TestMapConversionOperator<std::multimap<std::string, std::string>>(splitter);
   TestMapConversionOperator<std::unordered_map<std::string, std::string>>(
       splitter);
+  TestMapConversionOperator<
+      absl::node_hash_map<absl::string_view, absl::string_view>>(splitter);
+  TestMapConversionOperator<
+      absl::node_hash_map<absl::string_view, std::string>>(splitter);
+  TestMapConversionOperator<
+      absl::node_hash_map<std::string, absl::string_view>>(splitter);
+  TestMapConversionOperator<
+      absl::flat_hash_map<absl::string_view, absl::string_view>>(splitter);
+  TestMapConversionOperator<
+      absl::flat_hash_map<absl::string_view, std::string>>(splitter);
+  TestMapConversionOperator<
+      absl::flat_hash_map<std::string, absl::string_view>>(splitter);
 
   // Tests conversion to std::pair
 
@@ -436,7 +450,7 @@
 // less-than, equal-to, and more-than 2 strings.
 TEST(Splitter, ToPair) {
   {
-    // Empty std::string
+    // Empty string
     std::pair<std::string, std::string> p = absl::StrSplit("", ',');
     EXPECT_EQ("", p.first);
     EXPECT_EQ("", p.second);
@@ -565,7 +579,7 @@
 
 TEST(Split, Temporary) {
   // Use a std::string longer than the SSO length, so that when the temporary is
-  // destroyed, if the splitter keeps a reference to the std::string's contents,
+  // destroyed, if the splitter keeps a reference to the string's contents,
   // it'll reference freed memory instead of just dead on-stack memory.
   const char input[] = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u";
   EXPECT_LT(sizeof(std::string), ABSL_ARRAYSIZE(input))
@@ -651,14 +665,14 @@
   // Tests splitting utf8 strings and utf8 delimiters.
   std::string utf8_string = u8"\u03BA\u1F79\u03C3\u03BC\u03B5";
   {
-    // A utf8 input std::string with an ascii delimiter.
+    // A utf8 input string with an ascii delimiter.
     std::string to_split = "a," + utf8_string;
     std::vector<absl::string_view> v = absl::StrSplit(to_split, ',');
     EXPECT_THAT(v, ElementsAre("a", utf8_string));
   }
 
   {
-    // A utf8 input std::string and a utf8 delimiter.
+    // A utf8 input string and a utf8 delimiter.
     std::string to_split = "a," + utf8_string + ",b";
     std::string unicode_delimiter = "," + utf8_string + ",";
     std::vector<absl::string_view> v =
@@ -667,7 +681,7 @@
   }
 
   {
-    // A utf8 input std::string and ByAnyChar with ascii chars.
+    // A utf8 input string and ByAnyChar with ascii chars.
     std::vector<absl::string_view> v =
         absl::StrSplit(u8"Foo h\u00E4llo th\u4E1Ere", absl::ByAnyChar(" \t"));
     EXPECT_THAT(v, ElementsAre("Foo", u8"h\u00E4llo", u8"th\u4E1Ere"));
@@ -814,10 +828,10 @@
   ByString comma_string(",");
   TestComma(comma_string);
 
-  // The first occurrence of empty std::string ("") in a std::string is at position 0.
+  // The first occurrence of empty string ("") in a string is at position 0.
   // There is a test below that demonstrates this for absl::string_view::find().
   // If the ByString delimiter returned position 0 for this, there would
-  // be an infinite loop in the SplitIterator code. To avoid this, empty std::string
+  // be an infinite loop in the SplitIterator code. To avoid this, empty string
   // is a special case in that it always returns the item at position 1.
   absl::string_view abc("abc");
   EXPECT_EQ(0, abc.find(""));  // "" is found at position 0
@@ -876,7 +890,7 @@
   EXPECT_FALSE(IsFoundAt("=", two_delims, -1));
 
   // ByAnyChar behaves just like ByString when given a delimiter of empty
-  // std::string. That is, it always returns a zero-length absl::string_view
+  // string. That is, it always returns a zero-length absl::string_view
   // referring to the item at position 1, not position 0.
   ByAnyChar empty("");
   EXPECT_FALSE(IsFoundAt("", empty, 0));
@@ -913,7 +927,7 @@
     std::vector<absl::string_view> v = absl::StrSplit(s, '-');
     EXPECT_EQ(2, v.size());
     // The first element will contain 2G of 'x's.
-    // testing::StartsWith is too slow with a 2G std::string.
+    // testing::StartsWith is too slow with a 2G string.
     EXPECT_EQ('x', v[0][0]);
     EXPECT_EQ('x', v[0][1]);
     EXPECT_EQ('x', v[0][3]);
diff --git a/absl/strings/string_view.cc b/absl/strings/string_view.cc
index dc034a8..c5f5de9 100644
--- a/absl/strings/string_view.cc
+++ b/absl/strings/string_view.cc
@@ -14,7 +14,7 @@
 
 #include "absl/strings/string_view.h"
 
-#ifndef ABSL_HAVE_STD_STRING_VIEW
+#ifndef ABSL_USES_STD_STRING_VIEW
 
 #include <algorithm>
 #include <climits>
@@ -24,6 +24,7 @@
 #include "absl/strings/internal/memutil.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace {
 void WritePadding(std::ostream& o, size_t pad) {
@@ -228,6 +229,7 @@
 ABSL_STRING_VIEW_SELECTANY
 constexpr string_view::size_type string_view::kMaxSize;
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_HAVE_STD_STRING_VIEW
+#endif  // ABSL_USES_STD_STRING_VIEW
diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h
index 68b90aa..5260b5b 100644
--- a/absl/strings/string_view.h
+++ b/absl/strings/string_view.h
@@ -28,18 +28,6 @@
 #define ABSL_STRINGS_STRING_VIEW_H_
 
 #include <algorithm>
-#include "absl/base/config.h"
-
-#ifdef ABSL_HAVE_STD_STRING_VIEW
-
-#include <string_view>  // IWYU pragma: export
-
-namespace absl {
-using std::string_view;
-}  // namespace absl
-
-#else  // ABSL_HAVE_STD_STRING_VIEW
-
 #include <cassert>
 #include <cstddef>
 #include <cstring>
@@ -48,12 +36,33 @@
 #include <limits>
 #include <string>
 
+#include "absl/base/config.h"
 #include "absl/base/internal/throw_delegate.h"
 #include "absl/base/macros.h"
 #include "absl/base/optimization.h"
 #include "absl/base/port.h"
 
+#ifdef ABSL_USES_STD_STRING_VIEW
+
+#include <string_view>  // IWYU pragma: export
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
+using string_view = std::string_view;
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#else  // ABSL_USES_STD_STRING_VIEW
+
+#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \
+    (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_INTERNAL_STRING_VIEW_MEMCMP __builtin_memcmp
+#else  // ABSL_HAVE_BUILTIN(__builtin_memcmp)
+#define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp
+#endif  // ABSL_HAVE_BUILTIN(__builtin_memcmp)
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // absl::string_view
 //
@@ -102,17 +111,22 @@
 // example, when splitting a string, `std::vector<absl::string_view>` is a
 // natural data type for the output.
 //
-// When constructed from a source which is nul-terminated, the `string_view`
-// itself will not include the nul-terminator unless a specific size (including
-// the nul) is passed to the constructor. As a result, common idioms that work
-// on nul-terminated strings do not work on `string_view` objects. If you write
+// For another example, a Cord is a non-contiguous, potentially very
+// long string-like object.  The Cord class has an interface that iteratively
+// provides string_view objects that point to the successive pieces of a Cord
+// object.
+//
+// When constructed from a source which is NUL-terminated, the `string_view`
+// itself will not include the NUL-terminator unless a specific size (including
+// the NUL) is passed to the constructor. As a result, common idioms that work
+// on NUL-terminated strings do not work on `string_view` objects. If you write
 // code that scans a `string_view`, you must check its length rather than test
 // for nul, for example. Note, however, that nuls may still be embedded within
 // a `string_view` explicitly.
 //
 // You may create a null `string_view` in two ways:
 //
-//   absl::string_view sv();
+//   absl::string_view sv;
 //   absl::string_view sv(nullptr, 0);
 //
 // For the above, `sv.data() == nullptr`, `sv.length() == 0`, and
@@ -168,9 +182,11 @@
   string_view(  // NOLINT(runtime/explicit)
       const std::basic_string<char, std::char_traits<char>, Allocator>&
           str) noexcept
-      : ptr_(str.data()), length_(CheckLengthInternal(str.size())) {}
+      // This is implemented in terms of `string_view(p, n)` so `str.size()`
+      // doesn't need to be reevaluated after `ptr_` is set.
+      : string_view(str.data(), str.size()) {}
 
-  // Implicit constructor of a `string_view` from nul-terminated `str`. When
+  // Implicit constructor of a `string_view` from NUL-terminated `str`. When
   // accepting possibly null strings, use `absl::NullSafeStringView(str)`
   // instead (see below).
   constexpr string_view(const char* str)  // NOLINT(runtime/explicit)
@@ -271,7 +287,9 @@
   //
   // Returns the ith element of the `string_view` using the array operator.
   // Note that this operator does not perform any bounds checking.
-  constexpr const_reference operator[](size_type i) const { return ptr_[i]; }
+  constexpr const_reference operator[](size_type i) const {
+    return ABSL_HARDENING_ASSERT(i < size()), ptr_[i];
+  }
 
   // string_view::at()
   //
@@ -281,27 +299,32 @@
   constexpr const_reference at(size_type i) const {
     return ABSL_PREDICT_TRUE(i < size())
                ? ptr_[i]
-               : (base_internal::ThrowStdOutOfRange("absl::string_view::at"),
+               : ((void)base_internal::ThrowStdOutOfRange(
+                      "absl::string_view::at"),
                   ptr_[i]);
   }
 
   // string_view::front()
   //
   // Returns the first element of a `string_view`.
-  constexpr const_reference front() const { return ptr_[0]; }
+  constexpr const_reference front() const {
+    return ABSL_HARDENING_ASSERT(!empty()), ptr_[0];
+  }
 
   // string_view::back()
   //
   // Returns the last element of a `string_view`.
-  constexpr const_reference back() const { return ptr_[size() - 1]; }
+  constexpr const_reference back() const {
+    return ABSL_HARDENING_ASSERT(!empty()), ptr_[size() - 1];
+  }
 
   // string_view::data()
   //
   // Returns a pointer to the underlying character array (which is of course
   // stored elsewhere). Note that `string_view::data()` may contain embedded nul
-  // characters, but the returned buffer may or may not be nul-terminated;
-  // therefore, do not pass `data()` to a routine that expects a nul-terminated
-  // std::string.
+  // characters, but the returned buffer may or may not be NUL-terminated;
+  // therefore, do not pass `data()` to a routine that expects a NUL-terminated
+  // string.
   constexpr const_pointer data() const noexcept { return ptr_; }
 
   // Modifiers
@@ -309,9 +332,9 @@
   // string_view::remove_prefix()
   //
   // Removes the first `n` characters from the `string_view`. Note that the
-  // underlying std::string is not changed, only the view.
+  // underlying string is not changed, only the view.
   void remove_prefix(size_type n) {
-    assert(n <= length_);
+    ABSL_HARDENING_ASSERT(n <= length_);
     ptr_ += n;
     length_ -= n;
   }
@@ -319,9 +342,9 @@
   // string_view::remove_suffix()
   //
   // Removes the last `n` characters from the `string_view`. Note that the
-  // underlying std::string is not changed, only the view.
+  // underlying string is not changed, only the view.
   void remove_suffix(size_type n) {
-    assert(n <= length_);
+    ABSL_HARDENING_ASSERT(n <= length_);
     length_ -= n;
   }
 
@@ -364,31 +387,29 @@
   // Returns a "substring" of the `string_view` (at offset `pos` and length
   // `n`) as another string_view. This function throws `std::out_of_bounds` if
   // `pos > size`.
-  string_view substr(size_type pos, size_type n = npos) const {
-    if (ABSL_PREDICT_FALSE(pos > length_))
-      base_internal::ThrowStdOutOfRange("absl::string_view::substr");
-    n = (std::min)(n, length_ - pos);
-    return string_view(ptr_ + pos, n);
+  // Use absl::ClippedSubstr if you need a truncating substr operation.
+  constexpr string_view substr(size_type pos, size_type n = npos) const {
+    return ABSL_PREDICT_FALSE(pos > length_)
+               ? (base_internal::ThrowStdOutOfRange(
+                      "absl::string_view::substr"),
+                  string_view())
+               : string_view(ptr_ + pos, Min(n, length_ - pos));
   }
 
   // string_view::compare()
   //
   // Performs a lexicographical comparison between the `string_view` and
   // another `absl::string_view`, returning -1 if `this` is less than, 0 if
-  // `this` is equal to, and 1 if `this` is greater than the passed std::string
+  // `this` is equal to, and 1 if `this` is greater than the passed string
   // view. Note that in the case of data equality, a further comparison is made
   // on the respective sizes of the two `string_view`s to determine which is
   // smaller, equal, or greater.
-  int compare(string_view x) const noexcept {
-    auto min_length = (std::min)(length_, x.length_);
-    if (min_length > 0) {
-      int r = memcmp(ptr_, x.ptr_, min_length);
-      if (r < 0) return -1;
-      if (r > 0) return 1;
-    }
-    if (length_ < x.length_) return -1;
-    if (length_ > x.length_) return 1;
-    return 0;
+  constexpr int compare(string_view x) const noexcept {
+    return CompareImpl(length_, x.length_,
+                       Min(length_, x.length_) == 0
+                           ? 0
+                           : ABSL_INTERNAL_STRING_VIEW_MEMCMP(
+                                 ptr_, x.ptr_, Min(length_, x.length_)));
   }
 
   // Overload of `string_view::compare()` for comparing a substring of the
@@ -405,17 +426,17 @@
   }
 
   // Overload of `string_view::compare()` for comparing a `string_view` and a
-  // a different  C-style std::string `s`.
+  // a different  C-style string `s`.
   int compare(const char* s) const { return compare(string_view(s)); }
 
   // Overload of `string_view::compare()` for comparing a substring of the
-  // `string_view` and a different std::string C-style std::string `s`.
+  // `string_view` and a different string C-style string `s`.
   int compare(size_type pos1, size_type count1, const char* s) const {
     return substr(pos1, count1).compare(string_view(s));
   }
 
   // Overload of `string_view::compare()` for comparing a substring of the
-  // `string_view` and a substring of a different C-style std::string `s`.
+  // `string_view` and a substring of a different C-style string `s`.
   int compare(size_type pos1, size_type count1, const char* s,
               size_type count2) const {
     return substr(pos1, count1).compare(string_view(s, count2));
@@ -505,7 +526,7 @@
       (std::numeric_limits<difference_type>::max)();
 
   static constexpr size_type CheckLengthInternal(size_type len) {
-    return ABSL_ASSERT(len <= kMaxSize), len;
+    return ABSL_HARDENING_ASSERT(len <= kMaxSize), len;
   }
 
   static constexpr size_type StrlenInternal(const char* str) {
@@ -526,6 +547,17 @@
 #endif
   }
 
+  static constexpr size_t Min(size_type length_a, size_type length_b) {
+    return length_a < length_b ? length_a : length_b;
+  }
+
+  static constexpr int CompareImpl(size_type length_a, size_type length_b,
+                                   int compare_result) {
+    return compare_result == 0 ? static_cast<int>(length_a > length_b) -
+                                     static_cast<int>(length_a < length_b)
+                               : (compare_result < 0 ? -1 : 1);
+  }
+
   const char* ptr_;
   size_type length_;
 };
@@ -533,44 +565,44 @@
 // This large function is defined inline so that in a fairly common case where
 // one of the arguments is a literal, the compiler can elide a lot of the
 // following comparisons.
-inline bool operator==(string_view x, string_view y) noexcept {
-  auto len = x.size();
-  if (len != y.size()) {
-    return false;
-  }
-
-  return x.data() == y.data() || len <= 0 ||
-         memcmp(x.data(), y.data(), len) == 0;
+constexpr bool operator==(string_view x, string_view y) noexcept {
+  return x.size() == y.size() &&
+         (x.empty() ||
+          ABSL_INTERNAL_STRING_VIEW_MEMCMP(x.data(), y.data(), x.size()) == 0);
 }
 
-inline bool operator!=(string_view x, string_view y) noexcept {
+constexpr bool operator!=(string_view x, string_view y) noexcept {
   return !(x == y);
 }
 
-inline bool operator<(string_view x, string_view y) noexcept {
-  auto min_size = (std::min)(x.size(), y.size());
-  const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
-  return (r < 0) || (r == 0 && x.size() < y.size());
+constexpr bool operator<(string_view x, string_view y) noexcept {
+  return x.compare(y) < 0;
 }
 
-inline bool operator>(string_view x, string_view y) noexcept { return y < x; }
+constexpr bool operator>(string_view x, string_view y) noexcept {
+  return y < x;
+}
 
-inline bool operator<=(string_view x, string_view y) noexcept {
+constexpr bool operator<=(string_view x, string_view y) noexcept {
   return !(y < x);
 }
 
-inline bool operator>=(string_view x, string_view y) noexcept {
+constexpr bool operator>=(string_view x, string_view y) noexcept {
   return !(x < y);
 }
 
 // IO Insertion Operator
 std::ostream& operator<<(std::ostream& o, string_view piece);
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_HAVE_STD_STRING_VIEW
+#undef ABSL_INTERNAL_STRING_VIEW_MEMCMP
+
+#endif  // ABSL_USES_STD_STRING_VIEW
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // ClippedSubstr()
 //
@@ -587,10 +619,11 @@
 // Creates an `absl::string_view` from a pointer `p` even if it's null-valued.
 // This function should be used where an `absl::string_view` can be created from
 // a possibly-null pointer.
-inline string_view NullSafeStringView(const char* p) {
+constexpr string_view NullSafeStringView(const char* p) {
   return p ? string_view(p) : string_view();
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_STRING_VIEW_H_
diff --git a/absl/strings/string_view_benchmark.cc b/absl/strings/string_view_benchmark.cc
index 46909cb..0d74e23 100644
--- a/absl/strings/string_view_benchmark.cc
+++ b/absl/strings/string_view_benchmark.cc
@@ -30,6 +30,24 @@
 
 namespace {
 
+void BM_StringViewFromString(benchmark::State& state) {
+  std::string s(state.range(0), 'x');
+  std::string* ps = &s;
+  struct SV {
+    SV() = default;
+    explicit SV(const std::string& s) : sv(s) {}
+    absl::string_view sv;
+  } sv;
+  SV* psv = &sv;
+  benchmark::DoNotOptimize(ps);
+  benchmark::DoNotOptimize(psv);
+  for (auto _ : state) {
+    new (psv) SV(*ps);
+    benchmark::DoNotOptimize(sv);
+  }
+}
+BENCHMARK(BM_StringViewFromString)->Arg(12)->Arg(128);
+
 // Provide a forcibly out-of-line wrapper for operator== that can be used in
 // benchmarks to measure the impact of inlining.
 ABSL_ATTRIBUTE_NOINLINE
@@ -142,11 +160,45 @@
   absl::string_view b = y;
 
   for (auto _ : state) {
+    benchmark::DoNotOptimize(a);
+    benchmark::DoNotOptimize(b);
     benchmark::DoNotOptimize(a.compare(b));
   }
 }
 BENCHMARK(BM_CompareSame)->DenseRange(0, 3)->Range(4, 1 << 10);
 
+void BM_CompareFirstOneLess(benchmark::State& state) {
+  const int len = state.range(0);
+  std::string x(len, 'a');
+  std::string y = x;
+  y.back() = 'b';
+  absl::string_view a = x;
+  absl::string_view b = y;
+
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(a);
+    benchmark::DoNotOptimize(b);
+    benchmark::DoNotOptimize(a.compare(b));
+  }
+}
+BENCHMARK(BM_CompareFirstOneLess)->DenseRange(1, 3)->Range(4, 1 << 10);
+
+void BM_CompareSecondOneLess(benchmark::State& state) {
+  const int len = state.range(0);
+  std::string x(len, 'a');
+  std::string y = x;
+  x.back() = 'b';
+  absl::string_view a = x;
+  absl::string_view b = y;
+
+  for (auto _ : state) {
+    benchmark::DoNotOptimize(a);
+    benchmark::DoNotOptimize(b);
+    benchmark::DoNotOptimize(a.compare(b));
+  }
+}
+BENCHMARK(BM_CompareSecondOneLess)->DenseRange(1, 3)->Range(4, 1 << 10);
+
 void BM_find_string_view_len_one(benchmark::State& state) {
   std::string haystack(state.range(0), '0');
   absl::string_view s(haystack);
diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc
index eb8b170..643af8f 100644
--- a/absl/strings/string_view_test.cc
+++ b/absl/strings/string_view_test.cc
@@ -28,6 +28,7 @@
 #include "gtest/gtest.h"
 #include "absl/base/config.h"
 #include "absl/base/dynamic_annotations.h"
+#include "absl/base/options.h"
 
 #if defined(ABSL_HAVE_STD_STRING_VIEW) || defined(__ANDROID__)
 // We don't control the death messaging when using std::string_view.
@@ -410,7 +411,7 @@
   EXPECT_EQ(a.find(e, 17), 17);
   absl::string_view g("xx not found bb");
   EXPECT_EQ(a.find(g), absl::string_view::npos);
-  // empty std::string nonsense
+  // empty string nonsense
   EXPECT_EQ(d.find(b), absl::string_view::npos);
   EXPECT_EQ(e.find(b), absl::string_view::npos);
   EXPECT_EQ(d.find(b, 4), absl::string_view::npos);
@@ -438,7 +439,7 @@
   EXPECT_EQ(g.find('o', 4), 4);
   EXPECT_EQ(g.find('o', 5), 8);
   EXPECT_EQ(a.find('b', 5), absl::string_view::npos);
-  // empty std::string nonsense
+  // empty string nonsense
   EXPECT_EQ(d.find('\0'), absl::string_view::npos);
   EXPECT_EQ(e.find('\0'), absl::string_view::npos);
   EXPECT_EQ(d.find('\0', 4), absl::string_view::npos);
@@ -465,7 +466,7 @@
   EXPECT_EQ(e.rfind(b), absl::string_view::npos);
   EXPECT_EQ(d.rfind(b, 4), absl::string_view::npos);
   EXPECT_EQ(e.rfind(b, 7), absl::string_view::npos);
-  // empty std::string nonsense
+  // empty string nonsense
   EXPECT_EQ(d.rfind(d, 4), std::string().rfind(std::string()));
   EXPECT_EQ(e.rfind(d, 7), std::string().rfind(std::string()));
   EXPECT_EQ(d.rfind(e, 4), std::string().rfind(std::string()));
@@ -484,7 +485,7 @@
   EXPECT_EQ(f.rfind('\0', 12), 3);
   EXPECT_EQ(f.rfind('3'), 2);
   EXPECT_EQ(f.rfind('5'), 5);
-  // empty std::string nonsense
+  // empty string nonsense
   EXPECT_EQ(d.rfind('o'), absl::string_view::npos);
   EXPECT_EQ(e.rfind('o'), absl::string_view::npos);
   EXPECT_EQ(d.rfind('o', 4), absl::string_view::npos);
@@ -520,7 +521,7 @@
   EXPECT_EQ(g.find_first_of(c), 0);
   EXPECT_EQ(a.find_first_of(f), absl::string_view::npos);
   EXPECT_EQ(f.find_first_of(a), absl::string_view::npos);
-  // empty std::string nonsense
+  // empty string nonsense
   EXPECT_EQ(a.find_first_of(d), absl::string_view::npos);
   EXPECT_EQ(a.find_first_of(e), absl::string_view::npos);
   EXPECT_EQ(d.find_first_of(b), absl::string_view::npos);
@@ -538,7 +539,7 @@
   EXPECT_EQ(a.find_first_not_of(f), 0);
   EXPECT_EQ(a.find_first_not_of(d), 0);
   EXPECT_EQ(a.find_first_not_of(e), 0);
-  // empty std::string nonsense
+  // empty string nonsense
   EXPECT_EQ(a.find_first_not_of(d), 0);
   EXPECT_EQ(a.find_first_not_of(e), 0);
   EXPECT_EQ(a.find_first_not_of(d, 1), 1);
@@ -566,7 +567,7 @@
   EXPECT_EQ(f.find_first_not_of('\0'), 0);
   EXPECT_EQ(f.find_first_not_of('\0', 3), 4);
   EXPECT_EQ(f.find_first_not_of('\0', 2), 2);
-  // empty std::string nonsense
+  // empty string nonsense
   EXPECT_EQ(d.find_first_not_of('x'), absl::string_view::npos);
   EXPECT_EQ(e.find_first_not_of('x'), absl::string_view::npos);
   EXPECT_EQ(d.find_first_not_of('\0'), absl::string_view::npos);
@@ -606,7 +607,7 @@
   EXPECT_EQ(f.find_last_of(i, 5), 5);
   EXPECT_EQ(f.find_last_of(i, 6), 6);
   EXPECT_EQ(f.find_last_of(a, 4), absl::string_view::npos);
-  // empty std::string nonsense
+  // empty string nonsense
   EXPECT_EQ(f.find_last_of(d), absl::string_view::npos);
   EXPECT_EQ(f.find_last_of(e), absl::string_view::npos);
   EXPECT_EQ(f.find_last_of(d, 4), absl::string_view::npos);
@@ -632,7 +633,7 @@
   EXPECT_EQ(a.find_last_not_of(c, 24), 22);
   EXPECT_EQ(a.find_last_not_of(b, 3), 3);
   EXPECT_EQ(a.find_last_not_of(b, 2), absl::string_view::npos);
-  // empty std::string nonsense
+  // empty string nonsense
   EXPECT_EQ(f.find_last_not_of(d), f.size()-1);
   EXPECT_EQ(f.find_last_not_of(e), f.size()-1);
   EXPECT_EQ(f.find_last_not_of(d, 4), 4);
@@ -656,7 +657,7 @@
   EXPECT_EQ(h.find_last_not_of('x', 2), 2);
   EXPECT_EQ(h.find_last_not_of('=', 2), absl::string_view::npos);
   EXPECT_EQ(b.find_last_not_of('b', 1), 0);
-  // empty std::string nonsense
+  // empty string nonsense
   EXPECT_EQ(d.find_last_not_of('x'), absl::string_view::npos);
   EXPECT_EQ(e.find_last_not_of('x'), absl::string_view::npos);
   EXPECT_EQ(d.find_last_not_of('\0'), absl::string_view::npos);
@@ -678,7 +679,7 @@
   EXPECT_EQ(a.substr(23, 99), c);
   EXPECT_EQ(a.substr(0), a);
   EXPECT_EQ(a.substr(3, 2), "de");
-  // empty std::string nonsense
+  // empty string nonsense
   EXPECT_EQ(d.substr(0, 99), e);
   // use of npos
   EXPECT_EQ(a.substr(0, absl::string_view::npos), a);
@@ -818,6 +819,18 @@
   EXPECT_EQ(&c, &csp.back());
 }
 
+TEST(StringViewTest, FrontBackEmpty) {
+#ifndef ABSL_USES_STD_STRING_VIEW
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+  // Abseil's string_view implementation has debug assertions that check that
+  // front() and back() are not called on an empty string_view.
+  absl::string_view sv;
+  ABSL_EXPECT_DEATH_IF_SUPPORTED(sv.front(), "");
+  ABSL_EXPECT_DEATH_IF_SUPPORTED(sv.back(), "");
+#endif
+#endif
+}
+
 // `std::string_view::string_view(const char*)` calls
 // `std::char_traits<char>::length(const char*)` to get the string length. In
 // libc++, it doesn't allow `nullptr` in the constexpr context, with the error
@@ -830,7 +843,7 @@
 // to the standard, but `absl::string_view` implements a different
 // behavior for historical reasons. We work around tests that construct
 // `string_view` from `nullptr` when using libc++.
-#if !defined(ABSL_HAVE_STD_STRING_VIEW) ||                    \
+#if !defined(ABSL_USES_STD_STRING_VIEW) ||                    \
     (!(defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 9) && \
      !defined(_LIBCPP_VERSION) && !defined(_MSC_VER))
 #define ABSL_HAVE_STRING_VIEW_FROM_NULLPTR 1
@@ -847,7 +860,7 @@
   EXPECT_EQ(s.size(), 0);
 
   // .ToString() on a absl::string_view with nullptr should produce the empty
-  // std::string.
+  // string.
   EXPECT_EQ("", std::string(s));
 #endif  // ABSL_HAVE_STRING_VIEW_FROM_NULLPTR
 }
@@ -902,9 +915,9 @@
   EXPECT_EQ(abc.at(1), 'b');
   EXPECT_EQ(abc.at(2), 'c');
 #ifdef ABSL_HAVE_EXCEPTIONS
-  EXPECT_THROW(abc.at(3), std::out_of_range);
+  EXPECT_THROW((void)abc.at(3), std::out_of_range);
 #else
-  ABSL_EXPECT_DEATH_IF_SUPPORTED(abc.at(3), "absl::string_view::at");
+  ABSL_EXPECT_DEATH_IF_SUPPORTED((void)abc.at(3), "absl::string_view::at");
 #endif
 }
 
@@ -931,6 +944,31 @@
   }
 }
 
+TEST(StringViewTest, ConstexprNullSafeStringView) {
+  {
+    constexpr absl::string_view s = absl::NullSafeStringView(nullptr);
+    EXPECT_EQ(nullptr, s.data());
+    EXPECT_EQ(0, s.size());
+    EXPECT_EQ(absl::string_view(), s);
+  }
+#if !defined(_MSC_VER) || _MSC_VER >= 1910
+  // MSVC 2017+ is required for good constexpr string_view support.
+  // See the implementation of `absl::string_view::StrlenInternal()`.
+  {
+    static constexpr char kHi[] = "hi";
+    absl::string_view s = absl::NullSafeStringView(kHi);
+    EXPECT_EQ(kHi, s.data());
+    EXPECT_EQ(strlen(kHi), s.size());
+    EXPECT_EQ(absl::string_view("hi"), s);
+  }
+  {
+    constexpr absl::string_view s = absl::NullSafeStringView("hello");
+    EXPECT_EQ(s.size(), 5);
+    EXPECT_EQ("hello", s);
+  }
+#endif
+}
+
 TEST(StringViewTest, ConstexprCompiles) {
   constexpr absl::string_view sp;
 #ifdef ABSL_HAVE_STRING_VIEW_FROM_NULLPTR
@@ -938,9 +976,9 @@
 #endif
   constexpr absl::string_view cstr_len("cstr", 4);
 
-#if defined(ABSL_HAVE_STD_STRING_VIEW)
+#if defined(ABSL_USES_STD_STRING_VIEW)
   // In libstdc++ (as of 7.2), `std::string_view::string_view(const char*)`
-  // calls `std::char_traits<char>::length(const char*)` to get the std::string
+  // calls `std::char_traits<char>::length(const char*)` to get the string
   // length, but it is not marked constexpr yet. See GCC bug:
   // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78156
   // Also, there is a LWG issue that adds constexpr to length() which was just
@@ -952,7 +990,7 @@
 #define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1
 #endif  // !__GLIBCXX__
 
-#else  // ABSL_HAVE_STD_STRING_VIEW
+#else  // ABSL_USES_STD_STRING_VIEW
 
 // This duplicates the check for __builtin_strlen in the header.
 #if ABSL_HAVE_BUILTIN(__builtin_strlen) || \
@@ -967,13 +1005,36 @@
 #define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1
 #endif
 
-#endif  // ABSL_HAVE_STD_STRING_VIEW
+#endif  // ABSL_USES_STD_STRING_VIEW
 
 #ifdef ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR
   constexpr absl::string_view cstr_strlen("foo");
   EXPECT_EQ(cstr_strlen.length(), 3);
   constexpr absl::string_view cstr_strlen2 = "bar";
   EXPECT_EQ(cstr_strlen2, "bar");
+
+#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \
+    (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_COMPARISON 1
+#endif
+#ifdef ABSL_HAVE_CONSTEXPR_STRING_VIEW_COMPARISON
+  constexpr absl::string_view foo = "foo";
+  constexpr absl::string_view bar = "bar";
+  constexpr bool foo_eq_bar = foo == bar;
+  constexpr bool foo_ne_bar = foo != bar;
+  constexpr bool foo_lt_bar = foo < bar;
+  constexpr bool foo_le_bar = foo <= bar;
+  constexpr bool foo_gt_bar = foo > bar;
+  constexpr bool foo_ge_bar = foo >= bar;
+  constexpr int foo_compare_bar = foo.compare(bar);
+  EXPECT_FALSE(foo_eq_bar);
+  EXPECT_TRUE(foo_ne_bar);
+  EXPECT_FALSE(foo_lt_bar);
+  EXPECT_FALSE(foo_le_bar);
+  EXPECT_TRUE(foo_gt_bar);
+  EXPECT_TRUE(foo_ge_bar);
+  EXPECT_GT(foo_compare_bar, 0);
+#endif
 #endif
 
 #if !defined(__clang__) || 3 < __clang_major__ || \
@@ -1026,6 +1087,14 @@
   EXPECT_EQ(sp_npos, -1);
 }
 
+TEST(StringViewTest, ConstexprSubstr) {
+  constexpr absl::string_view foobar("foobar", 6);
+  constexpr absl::string_view foo = foobar.substr(0, 3);
+  constexpr absl::string_view bar = foobar.substr(3);
+  EXPECT_EQ(foo, "foo");
+  EXPECT_EQ(bar, "bar");
+}
+
 TEST(StringViewTest, Noexcept) {
   EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view,
                                              const std::string&>::value));
@@ -1060,6 +1129,17 @@
   EXPECT_TRUE(noexcept(sp.find_last_not_of('f')));
 }
 
+TEST(StringViewTest, BoundsCheck) {
+#ifndef ABSL_USES_STD_STRING_VIEW
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+  // Abseil's string_view implementation has bounds-checking in debug mode.
+  absl::string_view h = "hello";
+  ABSL_EXPECT_DEATH_IF_SUPPORTED(h[5], "");
+  ABSL_EXPECT_DEATH_IF_SUPPORTED(h[-1], "");
+#endif
+#endif
+}
+
 TEST(ComparisonOpsTest, StringCompareNotAmbiguous) {
   EXPECT_EQ("hello", std::string("hello"));
   EXPECT_LT("hello", std::string("world"));
@@ -1097,11 +1177,11 @@
   EXPECT_EQ(absl::string_view::npos, a.rfind('x'));
 }
 
-#ifndef THREAD_SANITIZER  // Allocates too much memory for tsan.
+#ifndef ABSL_HAVE_THREAD_SANITIZER  // Allocates too much memory for tsan.
 TEST(HugeStringView, TwoPointTwoGB) {
-  if (sizeof(size_t) <= 4 || RunningOnValgrind())
+  if (sizeof(size_t) <= 4)
     return;
-  // Try a huge std::string piece.
+  // Try a huge string piece.
   const size_t size = size_t{2200} * 1000 * 1000;
   std::string s(size, 'a');
   absl::string_view sp(s);
@@ -1111,9 +1191,9 @@
   sp.remove_suffix(2);
   EXPECT_EQ(size - 1 - 2, sp.length());
 }
-#endif  // THREAD_SANITIZER
+#endif  // ABSL_HAVE_THREAD_SANITIZER
 
-#if !defined(NDEBUG) && !defined(ABSL_HAVE_STD_STRING_VIEW)
+#if !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW)
 TEST(NonNegativeLenTest, NonNegativeLen) {
   ABSL_EXPECT_DEATH_IF_SUPPORTED(absl::string_view("xyz", -1),
                                  "len <= kMaxSize");
@@ -1129,7 +1209,7 @@
   ABSL_EXPECT_DEATH_IF_SUPPORTED(absl::string_view("", max_size + 1),
                                  "len <= kMaxSize");
 }
-#endif  // !defined(NDEBUG) && !defined(ABSL_HAVE_STD_STRING_VIEW)
+#endif  // !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW)
 
 class StringViewStreamTest : public ::testing::Test {
  public:
diff --git a/absl/strings/strip.h b/absl/strings/strip.h
index e1341e0..111872c 100644
--- a/absl/strings/strip.h
+++ b/absl/strings/strip.h
@@ -30,6 +30,7 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // ConsumePrefix()
 //
@@ -84,6 +85,7 @@
   return str;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_STRIP_H_
diff --git a/absl/strings/substitute.cc b/absl/strings/substitute.cc
index bc17695..1f3c740 100644
--- a/absl/strings/substitute.cc
+++ b/absl/strings/substitute.cc
@@ -23,6 +23,7 @@
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace substitute_internal {
 
 void SubstituteAndAppendArray(std::string* output, absl::string_view format,
@@ -35,7 +36,7 @@
       if (i + 1 >= format.size()) {
 #ifndef NDEBUG
         ABSL_RAW_LOG(FATAL,
-                     "Invalid strings::Substitute() format std::string: \"%s\".",
+                     "Invalid absl::Substitute() format string: \"%s\".",
                      absl::CEscape(format).c_str());
 #endif
         return;
@@ -45,8 +46,8 @@
 #ifndef NDEBUG
           ABSL_RAW_LOG(
               FATAL,
-              "Invalid strings::Substitute() format std::string: asked for \"$"
-              "%d\", but only %d args were given.  Full format std::string was: "
+              "Invalid absl::Substitute() format string: asked for \"$"
+              "%d\", but only %d args were given.  Full format string was: "
               "\"%s\".",
               index, static_cast<int>(num_args), absl::CEscape(format).c_str());
 #endif
@@ -60,7 +61,7 @@
       } else {
 #ifndef NDEBUG
         ABSL_RAW_LOG(FATAL,
-                     "Invalid strings::Substitute() format std::string: \"%s\".",
+                     "Invalid absl::Substitute() format string: \"%s\".",
                      absl::CEscape(format).c_str());
 #endif
         return;
@@ -72,7 +73,7 @@
 
   if (size == 0) return;
 
-  // Build the std::string.
+  // Build the string.
   size_t original_size = output->size();
   strings_internal::STLStringResizeUninitialized(output, original_size + size);
   char* target = &(*output)[original_size];
@@ -94,7 +95,6 @@
   assert(target == output->data() + output->size());
 }
 
-static const char kHexDigits[] = "0123456789abcdef";
 Arg::Arg(const void* value) {
   static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2,
                 "fix sizeof(scratch_)");
@@ -104,7 +104,7 @@
     char* ptr = scratch_ + sizeof(scratch_);
     uintptr_t num = reinterpret_cast<uintptr_t>(value);
     do {
-      *--ptr = kHexDigits[num & 0xf];
+      *--ptr = absl::numbers_internal::kHexChar[num & 0xf];
       num >>= 4;
     } while (num != 0);
     *--ptr = 'x';
@@ -119,7 +119,7 @@
   char* writer = end;
   uint64_t value = hex.value;
   do {
-    *--writer = kHexDigits[value & 0xF];
+    *--writer = absl::numbers_internal::kHexChar[value & 0xF];
     value >>= 4;
   } while (value != 0);
 
@@ -167,4 +167,5 @@
 }
 
 }  // namespace substitute_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h
index 233e9dc..c6da4dc 100644
--- a/absl/strings/substitute.h
+++ b/absl/strings/substitute.h
@@ -50,7 +50,7 @@
 //
 // Supported types:
 //   * absl::string_view, std::string, const char* (null is equivalent to "")
-//   * int32_t, int64_t, uint32_t, uint64
+//   * int32_t, int64_t, uint32_t, uint64_t
 //   * float, double
 //   * bool (Printed as "true" or "false")
 //   * pointer types other than char* (Printed as "0x<lower case hex string>",
@@ -86,6 +86,7 @@
 #include "absl/strings/strip.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace substitute_internal {
 
 // Arg
@@ -98,7 +99,7 @@
 // This class has implicit constructors.
 class Arg {
  public:
-  // Overloads for std::string-y things
+  // Overloads for string-y things
   //
   // Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
   Arg(const char* value)  // NOLINT(runtime/explicit)
@@ -119,7 +120,9 @@
   // representation. However, we can't really know, so we make the caller decide
   // what to do.
   Arg(char value)  // NOLINT(runtime/explicit)
-      : piece_(scratch_, 1) { scratch_[0] = value; }
+      : piece_(scratch_, 1) {
+    scratch_[0] = value;
+  }
   Arg(short value)  // NOLINT(*)
       : piece_(scratch_,
                numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
@@ -189,7 +192,12 @@
 
 #if defined(ABSL_BAD_CALL_IF)
 constexpr int CalculateOneBit(const char* format) {
-  return (*format < '0' || *format > '9') ? 0 : (1 << (*format - '0'));
+  // Returns:
+  // * 2^N for '$N' when N is in [0-9]
+  // * 0 for correct '$' escaping: '$$'.
+  // * -1 otherwise.
+  return (*format < '0' || *format > '9') ? (*format == '$' ? 0 : -1)
+                                          : (1 << (*format - '0'));
 }
 
 constexpr const char* SkipNumber(const char* format) {
@@ -197,10 +205,11 @@
 }
 
 constexpr int PlaceholderBitmask(const char* format) {
-  return !*format ? 0 : *format != '$'
-                             ? PlaceholderBitmask(format + 1)
-                             : (CalculateOneBit(format + 1) |
-                                   PlaceholderBitmask(SkipNumber(format + 1)));
+  return !*format
+             ? 0
+             : *format != '$' ? PlaceholderBitmask(format + 1)
+                              : (CalculateOneBit(format + 1) |
+                                 PlaceholderBitmask(SkipNumber(format + 1)));
 }
 #endif  // ABSL_BAD_CALL_IF
 
@@ -354,13 +363,13 @@
 void SubstituteAndAppend(std::string* output, const char* format)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0,
                      "There were no substitution arguments "
-                     "but this format std::string has a $[0-9] in it");
+                     "but this format string has a $[0-9] in it");
 
 void SubstituteAndAppend(std::string* output, const char* format,
                          const substitute_internal::Arg& a0)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1,
                      "There was 1 substitution argument given, but "
-                     "this format std::string is either missing its $0, or "
+                     "this format string is either missing its $0, or "
                      "contains one of $1-$9");
 
 void SubstituteAndAppend(std::string* output, const char* format,
@@ -368,7 +377,7 @@
                          const substitute_internal::Arg& a1)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 3,
                      "There were 2 substitution arguments given, but "
-                     "this format std::string is either missing its $0/$1, or "
+                     "this format string is either missing its $0/$1, or "
                      "contains one of $2-$9");
 
 void SubstituteAndAppend(std::string* output, const char* format,
@@ -377,7 +386,7 @@
                          const substitute_internal::Arg& a2)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 7,
                      "There were 3 substitution arguments given, but "
-                     "this format std::string is either missing its $0/$1/$2, or "
+                     "this format string is either missing its $0/$1/$2, or "
                      "contains one of $3-$9");
 
 void SubstituteAndAppend(std::string* output, const char* format,
@@ -387,7 +396,7 @@
                          const substitute_internal::Arg& a3)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 15,
                      "There were 4 substitution arguments given, but "
-                     "this format std::string is either missing its $0-$3, or "
+                     "this format string is either missing its $0-$3, or "
                      "contains one of $4-$9");
 
 void SubstituteAndAppend(std::string* output, const char* format,
@@ -398,7 +407,7 @@
                          const substitute_internal::Arg& a4)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 31,
                      "There were 5 substitution arguments given, but "
-                     "this format std::string is either missing its $0-$4, or "
+                     "this format string is either missing its $0-$4, or "
                      "contains one of $5-$9");
 
 void SubstituteAndAppend(std::string* output, const char* format,
@@ -410,7 +419,7 @@
                          const substitute_internal::Arg& a5)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 63,
                      "There were 6 substitution arguments given, but "
-                     "this format std::string is either missing its $0-$5, or "
+                     "this format string is either missing its $0-$5, or "
                      "contains one of $6-$9");
 
 void SubstituteAndAppend(
@@ -420,7 +429,7 @@
     const substitute_internal::Arg& a5, const substitute_internal::Arg& a6)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 127,
                      "There were 7 substitution arguments given, but "
-                     "this format std::string is either missing its $0-$6, or "
+                     "this format string is either missing its $0-$6, or "
                      "contains one of $7-$9");
 
 void SubstituteAndAppend(
@@ -431,7 +440,7 @@
     const substitute_internal::Arg& a7)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 255,
                      "There were 8 substitution arguments given, but "
-                     "this format std::string is either missing its $0-$7, or "
+                     "this format string is either missing its $0-$7, or "
                      "contains one of $8-$9");
 
 void SubstituteAndAppend(
@@ -443,7 +452,7 @@
     ABSL_BAD_CALL_IF(
         substitute_internal::PlaceholderBitmask(format) != 511,
         "There were 9 substitution arguments given, but "
-        "this format std::string is either missing its $0-$8, or contains a $9");
+        "this format string is either missing its $0-$8, or contains a $9");
 
 void SubstituteAndAppend(
     std::string* output, const char* format, const substitute_internal::Arg& a0,
@@ -454,7 +463,7 @@
     const substitute_internal::Arg& a9)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1023,
                      "There were 10 substitution arguments given, but this "
-                     "format std::string doesn't contain all of $0 through $9");
+                     "format string doesn't contain all of $0 through $9");
 #endif  // ABSL_BAD_CALL_IF
 
 // Substitute()
@@ -580,19 +589,19 @@
 std::string Substitute(const char* format)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0,
                      "There were no substitution arguments "
-                     "but this format std::string has a $[0-9] in it");
+                     "but this format string has a $[0-9] in it");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1,
                      "There was 1 substitution argument given, but "
-                     "this format std::string is either missing its $0, or "
+                     "this format string is either missing its $0, or "
                      "contains one of $1-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
                        const substitute_internal::Arg& a1)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 3,
                      "There were 2 substitution arguments given, but "
-                     "this format std::string is either missing its $0/$1, or "
+                     "this format string is either missing its $0/$1, or "
                      "contains one of $2-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
@@ -600,7 +609,7 @@
                        const substitute_internal::Arg& a2)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 7,
                      "There were 3 substitution arguments given, but "
-                     "this format std::string is either missing its $0/$1/$2, or "
+                     "this format string is either missing its $0/$1/$2, or "
                      "contains one of $3-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
@@ -609,7 +618,7 @@
                        const substitute_internal::Arg& a3)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 15,
                      "There were 4 substitution arguments given, but "
-                     "this format std::string is either missing its $0-$3, or "
+                     "this format string is either missing its $0-$3, or "
                      "contains one of $4-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
@@ -619,7 +628,7 @@
                        const substitute_internal::Arg& a4)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 31,
                      "There were 5 substitution arguments given, but "
-                     "this format std::string is either missing its $0-$4, or "
+                     "this format string is either missing its $0-$4, or "
                      "contains one of $5-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
@@ -630,7 +639,7 @@
                        const substitute_internal::Arg& a5)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 63,
                      "There were 6 substitution arguments given, but "
-                     "this format std::string is either missing its $0-$5, or "
+                     "this format string is either missing its $0-$5, or "
                      "contains one of $6-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
@@ -642,7 +651,7 @@
                        const substitute_internal::Arg& a6)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 127,
                      "There were 7 substitution arguments given, but "
-                     "this format std::string is either missing its $0-$6, or "
+                     "this format string is either missing its $0-$6, or "
                      "contains one of $7-$9");
 
 std::string Substitute(const char* format, const substitute_internal::Arg& a0,
@@ -655,7 +664,7 @@
                        const substitute_internal::Arg& a7)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 255,
                      "There were 8 substitution arguments given, but "
-                     "this format std::string is either missing its $0-$7, or "
+                     "this format string is either missing its $0-$7, or "
                      "contains one of $8-$9");
 
 std::string Substitute(
@@ -667,7 +676,7 @@
     ABSL_BAD_CALL_IF(
         substitute_internal::PlaceholderBitmask(format) != 511,
         "There were 9 substitution arguments given, but "
-        "this format std::string is either missing its $0-$8, or contains a $9");
+        "this format string is either missing its $0-$8, or contains a $9");
 
 std::string Substitute(
     const char* format, const substitute_internal::Arg& a0,
@@ -678,9 +687,10 @@
     const substitute_internal::Arg& a9)
     ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1023,
                      "There were 10 substitution arguments given, but this "
-                     "format std::string doesn't contain all of $0 through $9");
+                     "format string doesn't contain all of $0 through $9");
 #endif  // ABSL_BAD_CALL_IF
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_STRINGS_SUBSTITUTE_H_
diff --git a/absl/strings/substitute_test.cc b/absl/strings/substitute_test.cc
index e27abb1..442c921 100644
--- a/absl/strings/substitute_test.cc
+++ b/absl/strings/substitute_test.cc
@@ -89,7 +89,7 @@
   str = absl::Substitute("$0", char_buf);
   EXPECT_EQ("print me too", str);
 
-  // null char* is "doubly" special. Represented as the empty std::string.
+  // null char* is "doubly" special. Represented as the empty string.
   char_p = nullptr;
   str = absl::Substitute("$0", char_p);
   EXPECT_EQ("", str);
@@ -189,14 +189,14 @@
 TEST(SubstituteDeathTest, SubstituteDeath) {
   EXPECT_DEBUG_DEATH(
       static_cast<void>(absl::Substitute(absl::string_view("-$2"), "a", "b")),
-      "Invalid strings::Substitute\\(\\) format std::string: asked for \"\\$2\", "
+      "Invalid absl::Substitute\\(\\) format string: asked for \"\\$2\", "
       "but only 2 args were given.");
   EXPECT_DEBUG_DEATH(
-      static_cast<void>(absl::Substitute("-$z-")),
-      "Invalid strings::Substitute\\(\\) format std::string: \"-\\$z-\"");
+      static_cast<void>(absl::Substitute(absl::string_view("-$z-"))),
+      "Invalid absl::Substitute\\(\\) format string: \"-\\$z-\"");
   EXPECT_DEBUG_DEATH(
-      static_cast<void>(absl::Substitute("-$")),
-      "Invalid strings::Substitute\\(\\) format std::string: \"-\\$\"");
+      static_cast<void>(absl::Substitute(absl::string_view("-$"))),
+      "Invalid absl::Substitute\\(\\) format string: \"-\\$\"");
 }
 
 #endif  // GTEST_HAS_DEATH_TEST
diff --git a/absl/strings/testdata/getline-1.txt b/absl/strings/testdata/getline-1.txt
deleted file mode 100644
index 19b9097..0000000
--- a/absl/strings/testdata/getline-1.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-alpha
-
-beta gamma
diff --git a/absl/strings/testdata/getline-2.txt b/absl/strings/testdata/getline-2.txt
deleted file mode 100644
index d6842d8..0000000
--- a/absl/strings/testdata/getline-2.txt
+++ /dev/null
@@ -1 +0,0 @@
-one.two.three
diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel
index 36dc98f..cd4009a 100644
--- a/absl/synchronization/BUILD.bazel
+++ b/absl/synchronization/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 # Internal data structure for efficiently detecting mutex dependency cycles
 cc_library(
@@ -43,6 +43,7 @@
     deps = [
         "//absl/base",
         "//absl/base:base_internal",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:malloc_internal",
         "//absl/base:raw_logging_internal",
@@ -72,15 +73,14 @@
         "internal/create_thread_identity.cc",
         "internal/per_thread_sem.cc",
         "internal/waiter.cc",
+        "mutex.cc",
         "notification.cc",
-    ] + select({
-        "//conditions:default": ["mutex.cc"],
-    }),
+    ],
     hdrs = [
         "barrier.h",
         "blocking_counter.h",
         "internal/create_thread_identity.h",
-        "internal/mutex_nonprod.inc",
+        "internal/futex.h",
         "internal/per_thread_sem.h",
         "internal/waiter.h",
         "mutex.h",
@@ -89,6 +89,7 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = select({
         "//absl:windows": [],
+        "//absl:wasm": [],
         "//conditions:default": ["-pthread"],
     }) + ABSL_DEFAULT_LINKOPTS,
     deps = [
@@ -188,6 +189,7 @@
         ":synchronization",
         ":thread_pool",
         "//absl/base",
+        "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
         "//absl/memory",
@@ -209,6 +211,7 @@
         ":synchronization",
         ":thread_pool",
         "//absl/base",
+        "//absl/base:config",
         "@com_github_google_benchmark//:benchmark_main",
     ],
     alwayslink = 1,
@@ -247,6 +250,7 @@
     deps = [
         ":synchronization",
         "//absl/base",
+        "//absl/base:config",
         "//absl/strings",
         "//absl/time",
         "@com_google_googletest//:gtest",
diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt
index 3c47a1b..e633d0b 100644
--- a/absl/synchronization/CMakeLists.txt
+++ b/absl/synchronization/CMakeLists.txt
@@ -26,6 +26,7 @@
   DEPS
     absl::base
     absl::base_internal
+    absl::config
     absl::core_headers
     absl::malloc_internal
     absl::raw_logging_internal
@@ -51,7 +52,7 @@
     "barrier.h"
     "blocking_counter.h"
     "internal/create_thread_identity.h"
-    "internal/mutex_nonprod.inc"
+    "internal/futex.h"
     "internal/per_thread_sem.h"
     "internal/waiter.h"
     "mutex.h"
@@ -148,6 +149,7 @@
     absl::synchronization
     absl::thread_pool
     absl::base
+    absl::config
     absl::core_headers
     absl::memory
     absl::raw_logging_internal
@@ -178,6 +180,7 @@
   DEPS
     absl::synchronization
     absl::base
+    absl::config
     absl::strings
     absl::time
     gmock
diff --git a/absl/synchronization/barrier.cc b/absl/synchronization/barrier.cc
index c2c539a..0dfd795 100644
--- a/absl/synchronization/barrier.cc
+++ b/absl/synchronization/barrier.cc
@@ -18,6 +18,7 @@
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // Return whether int *arg is zero.
 static bool IsZero(void *arg) {
@@ -47,4 +48,5 @@
   return this->num_to_exit_ == 0;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/synchronization/barrier.h b/absl/synchronization/barrier.h
index cb5d821..d8e7544 100644
--- a/absl/synchronization/barrier.h
+++ b/absl/synchronization/barrier.h
@@ -23,6 +23,7 @@
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // Barrier
 //
@@ -73,5 +74,6 @@
   int num_to_exit_ ABSL_GUARDED_BY(lock_);
 };
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 #endif  // ABSL_SYNCHRONIZATION_BARRIER_H_
diff --git a/absl/synchronization/blocking_counter.cc b/absl/synchronization/blocking_counter.cc
index 481a06b..3cea7ae 100644
--- a/absl/synchronization/blocking_counter.cc
+++ b/absl/synchronization/blocking_counter.cc
@@ -17,6 +17,7 @@
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // Return whether int *arg is zero.
 static bool IsZero(void *arg) {
@@ -52,4 +53,5 @@
   // after we return from this method.
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/synchronization/blocking_counter.h b/absl/synchronization/blocking_counter.h
index 77560fc..1f53f9f 100644
--- a/absl/synchronization/blocking_counter.h
+++ b/absl/synchronization/blocking_counter.h
@@ -24,6 +24,7 @@
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // BlockingCounter
 //
@@ -92,6 +93,7 @@
   int num_waiting_ ABSL_GUARDED_BY(lock_);
 };
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_
diff --git a/absl/synchronization/blocking_counter_test.cc b/absl/synchronization/blocking_counter_test.cc
index c63e339..2926224 100644
--- a/absl/synchronization/blocking_counter_test.cc
+++ b/absl/synchronization/blocking_counter_test.cc
@@ -22,6 +22,7 @@
 #include "absl/time/time.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 void PauseAndDecreaseCounter(BlockingCounter* counter, int* done) {
@@ -63,4 +64,5 @@
 }
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/synchronization/internal/create_thread_identity.cc b/absl/synchronization/internal/create_thread_identity.cc
index ce3676a..53a71b3 100644
--- a/absl/synchronization/internal/create_thread_identity.cc
+++ b/absl/synchronization/internal/create_thread_identity.cc
@@ -27,17 +27,18 @@
 #include "absl/synchronization/internal/per_thread_sem.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
 // ThreadIdentity storage is persistent, we maintain a free-list of previously
 // released ThreadIdentity objects.
-static base_internal::SpinLock freelist_lock(
-    base_internal::kLinkerInitialized);
-static base_internal::ThreadIdentity* thread_identity_freelist;
+ABSL_CONST_INIT static base_internal::SpinLock freelist_lock(
+    absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
+ABSL_CONST_INIT static base_internal::ThreadIdentity* thread_identity_freelist;
 
 // A per-thread destructor for reclaiming associated ThreadIdentity objects.
 // Since we must preserve their storage we cache them for re-use.
-static void ReclaimThreadIdentity(void* v) {
+void ReclaimThreadIdentity(void* v) {
   base_internal::ThreadIdentity* identity =
       static_cast<base_internal::ThreadIdentity*>(v);
 
@@ -47,6 +48,8 @@
     base_internal::LowLevelAlloc::Free(identity->per_thread_synch.all_locks);
   }
 
+  PerThreadSem::Destroy(identity);
+
   // We must explicitly clear the current thread's identity:
   // (a) Subsequent (unrelated) per-thread destructors may require an identity.
   //     We must guarantee a new identity is used in this case (this instructor
@@ -84,7 +87,6 @@
   pts->wake = false;
   pts->cond_waiter = false;
   pts->all_locks = nullptr;
-  identity->waiter_state = {};
   identity->blocked_count_ptr = nullptr;
   identity->ticker.store(0, std::memory_order_relaxed);
   identity->wait_start.store(0, std::memory_order_relaxed);
@@ -132,6 +134,7 @@
 }
 
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_LOW_LEVEL_ALLOC_MISSING
diff --git a/absl/synchronization/internal/create_thread_identity.h b/absl/synchronization/internal/create_thread_identity.h
index ebb16c5..e121f68 100644
--- a/absl/synchronization/internal/create_thread_identity.h
+++ b/absl/synchronization/internal/create_thread_identity.h
@@ -29,12 +29,17 @@
 #include "absl/base/port.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
 // Allocates and attaches a ThreadIdentity object for the calling thread.
 // For private use only.
 base_internal::ThreadIdentity* CreateThreadIdentity();
 
+// A per-thread destructor for reclaiming associated ThreadIdentity objects.
+// For private use only.
+void ReclaimThreadIdentity(void* v);
+
 // Returns the ThreadIdentity object representing the calling thread; guaranteed
 // to be unique for its lifetime.  The returned object will remain valid for the
 // program's lifetime; although it may be re-assigned to a subsequent thread.
@@ -49,6 +54,7 @@
 }
 
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_
diff --git a/absl/synchronization/internal/futex.h b/absl/synchronization/internal/futex.h
new file mode 100644
index 0000000..06fbd6d
--- /dev/null
+++ b/absl/synchronization/internal/futex.h
@@ -0,0 +1,154 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
+#define ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
+
+#include "absl/base/config.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#ifdef __linux__
+#include <linux/futex.h>
+#include <sys/syscall.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <atomic>
+#include <cstdint>
+
+#include "absl/base/optimization.h"
+#include "absl/synchronization/internal/kernel_timeout.h"
+
+#ifdef ABSL_INTERNAL_HAVE_FUTEX
+#error ABSL_INTERNAL_HAVE_FUTEX may not be set on the command line
+#elif defined(__BIONIC__)
+// Bionic supports all the futex operations we need even when some of the futex
+// definitions are missing.
+#define ABSL_INTERNAL_HAVE_FUTEX
+#elif defined(__linux__) && defined(FUTEX_CLOCK_REALTIME)
+// FUTEX_CLOCK_REALTIME requires Linux >= 2.6.28.
+#define ABSL_INTERNAL_HAVE_FUTEX
+#endif
+
+#ifdef ABSL_INTERNAL_HAVE_FUTEX
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace synchronization_internal {
+
+// Some Android headers are missing these definitions even though they
+// support these futex operations.
+#ifdef __BIONIC__
+#ifndef SYS_futex
+#define SYS_futex __NR_futex
+#endif
+#ifndef FUTEX_WAIT_BITSET
+#define FUTEX_WAIT_BITSET 9
+#endif
+#ifndef FUTEX_PRIVATE_FLAG
+#define FUTEX_PRIVATE_FLAG 128
+#endif
+#ifndef FUTEX_CLOCK_REALTIME
+#define FUTEX_CLOCK_REALTIME 256
+#endif
+#ifndef FUTEX_BITSET_MATCH_ANY
+#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
+#endif
+#endif
+
+#if defined(__NR_futex_time64) && !defined(SYS_futex_time64)
+#define SYS_futex_time64 __NR_futex_time64
+#endif
+
+#if defined(SYS_futex_time64) && !defined(SYS_futex)
+#define SYS_futex SYS_futex_time64
+#endif
+
+class FutexImpl {
+ public:
+  static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
+                       KernelTimeout t) {
+    int err = 0;
+    if (t.has_timeout()) {
+      // https://locklessinc.com/articles/futex_cheat_sheet/
+      // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time.
+      struct timespec abs_timeout = t.MakeAbsTimespec();
+      // Atomically check that the futex value is still 0, and if it
+      // is, sleep until abs_timeout or until woken by FUTEX_WAKE.
+      err = syscall(
+          SYS_futex, reinterpret_cast<int32_t *>(v),
+          FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val,
+          &abs_timeout, nullptr, FUTEX_BITSET_MATCH_ANY);
+    } else {
+      // Atomically check that the futex value is still 0, and if it
+      // is, sleep until woken by FUTEX_WAKE.
+      err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                    FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, nullptr);
+    }
+    if (ABSL_PREDICT_FALSE(err != 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+
+  static int WaitBitsetAbsoluteTimeout(std::atomic<int32_t> *v, int32_t val,
+                                       int32_t bits,
+                                       const struct timespec *abstime) {
+    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                      FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG, val, abstime,
+                      nullptr, bits);
+    if (ABSL_PREDICT_FALSE(err != 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+
+  static int Wake(std::atomic<int32_t> *v, int32_t count) {
+    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                      FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);
+    if (ABSL_PREDICT_FALSE(err < 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+
+  // FUTEX_WAKE_BITSET
+  static int WakeBitset(std::atomic<int32_t> *v, int32_t count, int32_t bits) {
+    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+                      FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG, count, nullptr,
+                      nullptr, bits);
+    if (ABSL_PREDICT_FALSE(err < 0)) {
+      err = -errno;
+    }
+    return err;
+  }
+};
+
+class Futex : public FutexImpl {};
+
+}  // namespace synchronization_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_INTERNAL_HAVE_FUTEX
+
+#endif  // ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
diff --git a/absl/synchronization/internal/graphcycles.cc b/absl/synchronization/internal/graphcycles.cc
index 0c8c756..27fec21 100644
--- a/absl/synchronization/internal/graphcycles.cc
+++ b/absl/synchronization/internal/graphcycles.cc
@@ -37,6 +37,7 @@
 
 #include <algorithm>
 #include <array>
+#include <limits>
 #include "absl/base/internal/hide_ptr.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/spinlock.h"
@@ -44,15 +45,16 @@
 // Do not use STL.   This module does not use standard memory allocation.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
 namespace {
 
 // Avoid LowLevelAlloc's default arena since it calls malloc hooks in
 // which people are doing things like acquiring Mutexes.
-static absl::base_internal::SpinLock arena_mu(
-    absl::base_internal::kLinkerInitialized);
-static base_internal::LowLevelAlloc::Arena* arena;
+ABSL_CONST_INIT static absl::base_internal::SpinLock arena_mu(
+    absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
+ABSL_CONST_INIT static base_internal::LowLevelAlloc::Arena* arena;
 
 static void InitArenaIfNecessary() {
   arena_mu.Lock();
@@ -690,6 +692,7 @@
 }
 
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_LOW_LEVEL_ALLOC_MISSING
diff --git a/absl/synchronization/internal/graphcycles.h b/absl/synchronization/internal/graphcycles.h
index e5bde00..ceba33e 100644
--- a/absl/synchronization/internal/graphcycles.h
+++ b/absl/synchronization/internal/graphcycles.h
@@ -36,11 +36,14 @@
 //   InsertEdge() is very fast when the edge already exists, and reasonably fast
 //   otherwise.
 //   FindPath() is linear in the size of the graph.
-// The current implemenation uses O(|V|+|E|) space.
+// The current implementation uses O(|V|+|E|) space.
 
 #include <cstdint>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
 // Opaque identifier for a graph node.
@@ -132,6 +135,7 @@
 };
 
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif
diff --git a/absl/synchronization/internal/graphcycles_test.cc b/absl/synchronization/internal/graphcycles_test.cc
index 58e8477..74eaffe 100644
--- a/absl/synchronization/internal/graphcycles_test.cc
+++ b/absl/synchronization/internal/graphcycles_test.cc
@@ -25,6 +25,7 @@
 #include "absl/base/macros.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
 // We emulate a GraphCycles object with a node vector and an edge vector.
@@ -459,4 +460,5 @@
 }
 
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h
index 61c72e7..bbd4d2d 100644
--- a/absl/synchronization/internal/kernel_timeout.h
+++ b/absl/synchronization/internal/kernel_timeout.h
@@ -26,6 +26,7 @@
 #define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
 
 #include <time.h>
+
 #include <algorithm>
 #include <limits>
 
@@ -34,6 +35,7 @@
 #include "absl/time/time.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
 class Futex;
@@ -56,6 +58,10 @@
 
   bool has_timeout() const { return ns_ != 0; }
 
+  // Convert to parameter for sem_timedwait/futex/similar.  Only for approved
+  // users.  Do not call if !has_timeout.
+  struct timespec MakeAbsTimespec();
+
  private:
   // internal rep, not user visible: ns after unix epoch.
   // zero = no timeout.
@@ -81,34 +87,6 @@
     return x;
   }
 
-  // Convert to parameter for sem_timedwait/futex/similar.  Only for approved
-  // users.  Do not call if !has_timeout.
-  struct timespec MakeAbsTimespec() {
-    int64_t n = ns_;
-    static const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
-    if (n == 0) {
-      ABSL_RAW_LOG(
-          ERROR,
-          "Tried to create a timespec from a non-timeout; never do this.");
-      // But we'll try to continue sanely.  no-timeout ~= saturated timeout.
-      n = (std::numeric_limits<int64_t>::max)();
-    }
-
-    // Kernel APIs validate timespecs as being at or after the epoch,
-    // despite the kernel time type being signed.  However, no one can
-    // tell the difference between a timeout at or before the epoch (since
-    // all such timeouts have expired!)
-    if (n < 0) n = 0;
-
-    struct timespec abstime;
-    int64_t seconds = (std::min)(n / kNanosPerSecond,
-                               int64_t{(std::numeric_limits<time_t>::max)()});
-    abstime.tv_sec = static_cast<time_t>(seconds);
-    abstime.tv_nsec =
-        static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond);
-    return abstime;
-  }
-
 #ifdef _WIN32
   // Converts to milliseconds from now, or INFINITE when
   // !has_timeout(). For use by SleepConditionVariableSRW on
@@ -147,7 +125,32 @@
   friend class Waiter;
 };
 
+inline struct timespec KernelTimeout::MakeAbsTimespec() {
+  int64_t n = ns_;
+  static const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
+  if (n == 0) {
+    ABSL_RAW_LOG(
+        ERROR, "Tried to create a timespec from a non-timeout; never do this.");
+    // But we'll try to continue sanely.  no-timeout ~= saturated timeout.
+    n = (std::numeric_limits<int64_t>::max)();
+  }
+
+  // Kernel APIs validate timespecs as being at or after the epoch,
+  // despite the kernel time type being signed.  However, no one can
+  // tell the difference between a timeout at or before the epoch (since
+  // all such timeouts have expired!)
+  if (n < 0) n = 0;
+
+  struct timespec abstime;
+  int64_t seconds = (std::min)(n / kNanosPerSecond,
+                               int64_t{(std::numeric_limits<time_t>::max)()});
+  abstime.tv_sec = static_cast<time_t>(seconds);
+  abstime.tv_nsec = static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond);
+  return abstime;
+}
+
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
diff --git a/absl/synchronization/internal/mutex_nonprod.cc b/absl/synchronization/internal/mutex_nonprod.cc
deleted file mode 100644
index 267deaf..0000000
--- a/absl/synchronization/internal/mutex_nonprod.cc
+++ /dev/null
@@ -1,318 +0,0 @@
-// Copyright 2017 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Implementation of a small subset of Mutex and CondVar functionality
-// for platforms where the production implementation hasn't been fully
-// ported yet.
-
-#include "absl/synchronization/mutex.h"
-
-#if defined(_WIN32)
-#include <chrono>  // NOLINT(build/c++11)
-#else
-#include <sys/time.h>
-#include <time.h>
-#endif
-
-#include <algorithm>
-
-#include "absl/base/internal/raw_logging.h"
-#include "absl/time/time.h"
-
-namespace absl {
-namespace synchronization_internal {
-
-namespace {
-
-// Return the current time plus the timeout.
-absl::Time DeadlineFromTimeout(absl::Duration timeout) {
-  return absl::Now() + timeout;
-}
-
-// Limit the deadline to a positive, 32-bit time_t value to accommodate
-// implementation restrictions.  This also deals with InfinitePast and
-// InfiniteFuture.
-absl::Time LimitedDeadline(absl::Time deadline) {
-  deadline = std::max(absl::FromTimeT(0), deadline);
-  deadline = std::min(deadline, absl::FromTimeT(0x7fffffff));
-  return deadline;
-}
-
-}  // namespace
-
-#if defined(_WIN32)
-
-MutexImpl::MutexImpl() {}
-
-MutexImpl::~MutexImpl() {
-  if (locked_) {
-    std_mutex_.unlock();
-  }
-}
-
-void MutexImpl::Lock() {
-  std_mutex_.lock();
-  locked_ = true;
-}
-
-bool MutexImpl::TryLock() {
-  bool locked = std_mutex_.try_lock();
-  if (locked) locked_ = true;
-  return locked;
-}
-
-void MutexImpl::Unlock() {
-  locked_ = false;
-  released_.SignalAll();
-  std_mutex_.unlock();
-}
-
-CondVarImpl::CondVarImpl() {}
-
-CondVarImpl::~CondVarImpl() {}
-
-void CondVarImpl::Signal() { std_cv_.notify_one(); }
-
-void CondVarImpl::SignalAll() { std_cv_.notify_all(); }
-
-void CondVarImpl::Wait(MutexImpl* mu) {
-  mu->released_.SignalAll();
-  std_cv_.wait(mu->std_mutex_);
-}
-
-bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
-  mu->released_.SignalAll();
-  time_t when = ToTimeT(deadline);
-  int64_t nanos = ToInt64Nanoseconds(deadline - absl::FromTimeT(when));
-  std::chrono::system_clock::time_point deadline_tp =
-      std::chrono::system_clock::from_time_t(when) +
-      std::chrono::duration_cast<std::chrono::system_clock::duration>(
-          std::chrono::nanoseconds(nanos));
-  auto deadline_since_epoch =
-      std::chrono::duration_cast<std::chrono::duration<double>>(
-          deadline_tp - std::chrono::system_clock::from_time_t(0));
-  return std_cv_.wait_until(mu->std_mutex_, deadline_tp) ==
-         std::cv_status::timeout;
-}
-
-#else  // ! _WIN32
-
-MutexImpl::MutexImpl() {
-  ABSL_RAW_CHECK(pthread_mutex_init(&pthread_mutex_, nullptr) == 0,
-                 "pthread error");
-}
-
-MutexImpl::~MutexImpl() {
-  if (locked_) {
-    ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
-  }
-  ABSL_RAW_CHECK(pthread_mutex_destroy(&pthread_mutex_) == 0, "pthread error");
-}
-
-void MutexImpl::Lock() {
-  ABSL_RAW_CHECK(pthread_mutex_lock(&pthread_mutex_) == 0, "pthread error");
-  locked_ = true;
-}
-
-bool MutexImpl::TryLock() {
-  bool locked = (0 == pthread_mutex_trylock(&pthread_mutex_));
-  if (locked) locked_ = true;
-  return locked;
-}
-
-void MutexImpl::Unlock() {
-  locked_ = false;
-  released_.SignalAll();
-  ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
-}
-
-CondVarImpl::CondVarImpl() {
-  ABSL_RAW_CHECK(pthread_cond_init(&pthread_cv_, nullptr) == 0,
-                 "pthread error");
-}
-
-CondVarImpl::~CondVarImpl() {
-  ABSL_RAW_CHECK(pthread_cond_destroy(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::Signal() {
-  ABSL_RAW_CHECK(pthread_cond_signal(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::SignalAll() {
-  ABSL_RAW_CHECK(pthread_cond_broadcast(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::Wait(MutexImpl* mu) {
-  mu->released_.SignalAll();
-  ABSL_RAW_CHECK(pthread_cond_wait(&pthread_cv_, &mu->pthread_mutex_) == 0,
-                 "pthread error");
-}
-
-bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
-  mu->released_.SignalAll();
-  struct timespec ts = ToTimespec(deadline);
-  int rc = pthread_cond_timedwait(&pthread_cv_, &mu->pthread_mutex_, &ts);
-  if (rc == ETIMEDOUT) return true;
-  ABSL_RAW_CHECK(rc == 0, "pthread error");
-  return false;
-}
-
-#endif  // ! _WIN32
-
-void MutexImpl::Await(const Condition& cond) {
-  if (cond.Eval()) return;
-  released_.SignalAll();
-  do {
-    released_.Wait(this);
-  } while (!cond.Eval());
-}
-
-bool MutexImpl::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
-  if (cond.Eval()) return true;
-  released_.SignalAll();
-  while (true) {
-    if (released_.WaitWithDeadline(this, deadline)) return false;
-    if (cond.Eval()) return true;
-  }
-}
-
-}  // namespace synchronization_internal
-
-Mutex::Mutex() {}
-
-Mutex::~Mutex() {}
-
-void Mutex::Lock() { impl()->Lock(); }
-
-void Mutex::Unlock() { impl()->Unlock(); }
-
-bool Mutex::TryLock() { return impl()->TryLock(); }
-
-void Mutex::ReaderLock() { Lock(); }
-
-void Mutex::ReaderUnlock() { Unlock(); }
-
-void Mutex::Await(const Condition& cond) { impl()->Await(cond); }
-
-void Mutex::LockWhen(const Condition& cond) {
-  Lock();
-  Await(cond);
-}
-
-bool Mutex::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
-  return impl()->AwaitWithDeadline(
-      cond, synchronization_internal::LimitedDeadline(deadline));
-}
-
-bool Mutex::AwaitWithTimeout(const Condition& cond, absl::Duration timeout) {
-  return AwaitWithDeadline(
-      cond, synchronization_internal::DeadlineFromTimeout(timeout));
-}
-
-bool Mutex::LockWhenWithDeadline(const Condition& cond, absl::Time deadline) {
-  Lock();
-  return AwaitWithDeadline(cond, deadline);
-}
-
-bool Mutex::LockWhenWithTimeout(const Condition& cond, absl::Duration timeout) {
-  return LockWhenWithDeadline(
-      cond, synchronization_internal::DeadlineFromTimeout(timeout));
-}
-
-void Mutex::ReaderLockWhen(const Condition& cond) {
-  ReaderLock();
-  Await(cond);
-}
-
-bool Mutex::ReaderLockWhenWithTimeout(const Condition& cond,
-                                      absl::Duration timeout) {
-  return LockWhenWithTimeout(cond, timeout);
-}
-bool Mutex::ReaderLockWhenWithDeadline(const Condition& cond,
-                                       absl::Time deadline) {
-  return LockWhenWithDeadline(cond, deadline);
-}
-
-void Mutex::EnableDebugLog(const char*) {}
-void Mutex::EnableInvariantDebugging(void (*)(void*), void*) {}
-void Mutex::ForgetDeadlockInfo() {}
-void Mutex::AssertHeld() const {}
-void Mutex::AssertReaderHeld() const {}
-void Mutex::AssertNotHeld() const {}
-
-CondVar::CondVar() {}
-
-CondVar::~CondVar() {}
-
-void CondVar::Signal() { impl()->Signal(); }
-
-void CondVar::SignalAll() { impl()->SignalAll(); }
-
-void CondVar::Wait(Mutex* mu) { return impl()->Wait(mu->impl()); }
-
-bool CondVar::WaitWithDeadline(Mutex* mu, absl::Time deadline) {
-  return impl()->WaitWithDeadline(
-      mu->impl(), synchronization_internal::LimitedDeadline(deadline));
-}
-
-bool CondVar::WaitWithTimeout(Mutex* mu, absl::Duration timeout) {
-  return WaitWithDeadline(mu, absl::Now() + timeout);
-}
-
-void CondVar::EnableDebugLog(const char*) {}
-
-#ifdef THREAD_SANITIZER
-extern "C" void __tsan_read1(void *addr);
-#else
-#define __tsan_read1(addr)  // do nothing if TSan not enabled
-#endif
-
-// A function that just returns its argument, dereferenced
-static bool Dereference(void *arg) {
-  // ThreadSanitizer does not instrument this file for memory accesses.
-  // This function dereferences a user variable that can participate
-  // in a data race, so we need to manually tell TSan about this memory access.
-  __tsan_read1(arg);
-  return *(static_cast<bool *>(arg));
-}
-
-Condition::Condition() {}   // null constructor, used for kTrue only
-const Condition Condition::kTrue;
-
-Condition::Condition(bool (*func)(void *), void *arg)
-    : eval_(&CallVoidPtrFunction),
-      function_(func),
-      method_(nullptr),
-      arg_(arg) {}
-
-bool Condition::CallVoidPtrFunction(const Condition *c) {
-  return (*c->function_)(c->arg_);
-}
-
-Condition::Condition(const bool *cond)
-    : eval_(CallVoidPtrFunction),
-      function_(Dereference),
-      method_(nullptr),
-      // const_cast is safe since Dereference does not modify arg
-      arg_(const_cast<bool *>(cond)) {}
-
-bool Condition::Eval() const {
-  // eval_ == null for kTrue
-  return (this->eval_ == nullptr) || (*this->eval_)(this);
-}
-
-void RegisterSymbolizer(bool (*)(const void*, char*, int)) {}
-
-}  // namespace absl
diff --git a/absl/synchronization/internal/mutex_nonprod.inc b/absl/synchronization/internal/mutex_nonprod.inc
deleted file mode 100644
index b8d5af7..0000000
--- a/absl/synchronization/internal/mutex_nonprod.inc
+++ /dev/null
@@ -1,259 +0,0 @@
-// Do not include.  This is an implementation detail of base/mutex.h.
-//
-// Declares three classes:
-//
-// base::internal::MutexImpl - implementation helper for Mutex
-// base::internal::CondVarImpl - implementation helper for CondVar
-// base::internal::SynchronizationStorage<T> - implementation helper for
-//                                             Mutex, CondVar
-
-#include <type_traits>
-
-#if defined(_WIN32)
-#include <condition_variable>
-#include <mutex>
-#else
-#include <pthread.h>
-#endif
-
-#include "absl/base/call_once.h"
-#include "absl/time/time.h"
-
-// Declare that Mutex::ReaderLock is actually Lock().  Intended primarily
-// for tests, and even then as a last resort.
-#ifdef ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE
-#error ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE cannot be directly set
-#else
-#define ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE 1
-#endif
-
-// Declare that Mutex::EnableInvariantDebugging is not implemented.
-// Intended primarily for tests, and even then as a last resort.
-#ifdef ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED
-#error ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED cannot be directly set
-#else
-#define ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED 1
-#endif
-
-namespace absl {
-class Condition;
-
-namespace synchronization_internal {
-
-class MutexImpl;
-
-// Do not use this implementation detail of CondVar. Provides most of the
-// implementation, but should not be placed directly in static storage
-// because it will not linker initialize properly. See
-// SynchronizationStorage<T> below for what we mean by linker
-// initialization.
-class CondVarImpl {
- public:
-  CondVarImpl();
-  CondVarImpl(const CondVarImpl&) = delete;
-  CondVarImpl& operator=(const CondVarImpl&) = delete;
-  ~CondVarImpl();
-
-  void Signal();
-  void SignalAll();
-  void Wait(MutexImpl* mutex);
-  bool WaitWithDeadline(MutexImpl* mutex, absl::Time deadline);
-
- private:
-#if defined(_WIN32)
-  std::condition_variable_any std_cv_;
-#else
-  pthread_cond_t pthread_cv_;
-#endif
-};
-
-// Do not use this implementation detail of Mutex. Provides most of the
-// implementation, but should not be placed directly in static storage
-// because it will not linker initialize properly. See
-// SynchronizationStorage<T> below for what we mean by linker
-// initialization.
-class MutexImpl {
- public:
-  MutexImpl();
-  MutexImpl(const MutexImpl&) = delete;
-  MutexImpl& operator=(const MutexImpl&) = delete;
-  ~MutexImpl();
-
-  void Lock();
-  bool TryLock();
-  void Unlock();
-  void Await(const Condition& cond);
-  bool AwaitWithDeadline(const Condition& cond, absl::Time deadline);
-
- private:
-  friend class CondVarImpl;
-
-#if defined(_WIN32)
-  std::mutex std_mutex_;
-#else
-  pthread_mutex_t pthread_mutex_;
-#endif
-
-  // True if the underlying mutex is locked.  If the destructor is entered
-  // while locked_, the underlying mutex is unlocked.  Mutex supports
-  // destruction while locked, but the same is undefined behavior for both
-  // pthread_mutex_t and std::mutex.
-  bool locked_ = false;
-
-  // Signaled before releasing the lock, in support of Await.
-  CondVarImpl released_;
-};
-
-// Do not use this implementation detail of CondVar and Mutex.  A storage
-// space for T that supports a LinkerInitialized constructor. T must
-// have a default constructor, which is called by the first call to
-// get(). T's destructor is never called if the LinkerInitialized
-// constructor is called.
-//
-// Objects constructed with the default constructor are constructed and
-// destructed like any other object, and should never be allocated in
-// static storage.
-//
-// Objects constructed with the LinkerInitialized constructor should
-// always be in static storage. For such objects, calls to get() are always
-// valid, except from signal handlers.
-//
-// Note that this implementation relies on undefined language behavior that
-// are known to hold for the set of supported compilers. An analysis
-// follows.
-//
-// From the C++11 standard:
-//
-// [basic.life] says an object has non-trivial initialization if it is of
-// class type and it is initialized by a constructor other than a trivial
-// default constructor.  (the LinkerInitialized constructor is
-// non-trivial)
-//
-// [basic.life] says the lifetime of an object with a non-trivial
-// constructor begins when the call to the constructor is complete.
-//
-// [basic.life] says the lifetime of an object with non-trivial destructor
-// ends when the call to the destructor begins.
-//
-// [basic.life] p5 specifies undefined behavior when accessing non-static
-// members of an instance outside its
-// lifetime. (SynchronizationStorage::get() access non-static members)
-//
-// So, LinkerInitialized object of SynchronizationStorage uses a
-// non-trivial constructor, which is called at some point during dynamic
-// initialization, and is therefore subject to order of dynamic
-// initialization bugs, where get() is called before the object's
-// constructor is, resulting in undefined behavior.
-//
-// Similarly, a LinkerInitialized SynchronizationStorage object has a
-// non-trivial destructor, and so its lifetime ends at some point during
-// destruction of objects with static storage duration [basic.start.term]
-// p4. There is a window where other exit code could call get() after this
-// occurs, resulting in undefined behavior.
-//
-// Combined, these statements imply that LinkerInitialized instances
-// of SynchronizationStorage<T> rely on undefined behavior.
-//
-// However, in practice, the implementation works on all supported
-// compilers. Specifically, we rely on:
-//
-// a) zero-initialization being sufficient to initialize
-// LinkerInitialized instances for the purposes of calling
-// get(), regardless of when the constructor is called. This is
-// because the is_dynamic_ boolean is correctly zero-initialized to
-// false.
-//
-// b) the LinkerInitialized constructor is a NOP, and immaterial to
-// even to concurrent calls to get().
-//
-// c) the destructor being a NOP for LinkerInitialized objects
-// (guaranteed by a check for !is_dynamic_), and so any concurrent and
-// subsequent calls to get() functioning as if the destructor were not
-// called, by virtue of the instances' storage remaining valid after the
-// destructor runs.
-//
-// d) That a-c apply transitively when SynchronizationStorage<T> is the
-// only member of a class allocated in static storage.
-//
-// Nothing in the language standard guarantees that a-d hold.  In practice,
-// these hold in all supported compilers.
-//
-// Future direction:
-//
-// Ideally, we would simply use std::mutex or a similar class, which when
-// allocated statically would support use immediately after static
-// initialization up until static storage is reclaimed (i.e. the properties
-// we require of all "linker initialized" instances).
-//
-// Regarding construction in static storage, std::mutex is required to
-// provide a constexpr default constructor [thread.mutex.class], which
-// ensures the instance's lifetime begins with static initialization
-// [basic.start.init], and so is immune to any problems caused by the order
-// of dynamic initialization. However, as of this writing Microsoft's
-// Visual Studio does not provide a constexpr constructor for std::mutex.
-// See
-// https://blogs.msdn.microsoft.com/vcblog/2015/06/02/constexpr-complete-for-vs-2015-rtm-c11-compiler-c17-stl/
-//
-// Regarding destruction of instances in static storage, [basic.life] does
-// say an object ends when storage in which the occupies is released, in
-// the case of non-trivial destructor. However, std::mutex is not specified
-// to have a trivial destructor.
-//
-// So, we would need a class with a constexpr default constructor and a
-// trivial destructor. Today, we can achieve neither desired property using
-// std::mutex directly.
-template <typename T>
-class SynchronizationStorage {
- public:
-  // Instances allocated on the heap or on the stack should use the default
-  // constructor.
-  SynchronizationStorage()
-      : is_dynamic_(true), once_() {}
-
-  // Instances allocated in static storage (not on the heap, not on the
-  // stack) should use this constructor.
-  explicit SynchronizationStorage(base_internal::LinkerInitialized) {}
-
-  constexpr explicit SynchronizationStorage(absl::ConstInitType)
-      : is_dynamic_(false), once_(), space_{{0}} {}
-
-  SynchronizationStorage(SynchronizationStorage&) = delete;
-  SynchronizationStorage& operator=(SynchronizationStorage&) = delete;
-
-  ~SynchronizationStorage() {
-    if (is_dynamic_) {
-      get()->~T();
-    }
-  }
-
-  // Retrieve the object in storage. This is fast and thread safe, but does
-  // incur the cost of absl::call_once().
-  //
-  // For instances in static storage constructed with the
-  // LinkerInitialized constructor, may be called at any time without
-  // regard for order of dynamic initialization or destruction of objects
-  // in static storage. See the class comment for caveats.
-  T* get() {
-    absl::call_once(once_, SynchronizationStorage::Construct, this);
-    return reinterpret_cast<T*>(&space_);
-  }
-
- private:
-  static void Construct(SynchronizationStorage<T>* self) {
-    new (&self->space_) T();
-  }
-
-  // When true, T's destructor is run when this is destructed.
-  //
-  // The LinkerInitialized constructor assumes this value will be set
-  // false by static initialization.
-  bool is_dynamic_;
-
-  absl::once_flag once_;
-
-  // An aligned space for T.
-  typename std::aligned_storage<sizeof(T), alignof(T)>::type space_;
-};
-
-}  // namespace synchronization_internal
-}  // namespace absl
diff --git a/absl/synchronization/internal/per_thread_sem.cc b/absl/synchronization/internal/per_thread_sem.cc
index b7014fb..821ca9b 100644
--- a/absl/synchronization/internal/per_thread_sem.cc
+++ b/absl/synchronization/internal/per_thread_sem.cc
@@ -25,6 +25,7 @@
 #include "absl/synchronization/internal/waiter.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
 void PerThreadSem::SetThreadBlockedCounter(std::atomic<int> *counter) {
@@ -40,12 +41,16 @@
 }
 
 void PerThreadSem::Init(base_internal::ThreadIdentity *identity) {
-  Waiter::GetWaiter(identity)->Init();
+  new (Waiter::GetWaiter(identity)) Waiter();
   identity->ticker.store(0, std::memory_order_relaxed);
   identity->wait_start.store(0, std::memory_order_relaxed);
   identity->is_idle.store(false, std::memory_order_relaxed);
 }
 
+void PerThreadSem::Destroy(base_internal::ThreadIdentity *identity) {
+  Waiter::GetWaiter(identity)->~Waiter();
+}
+
 void PerThreadSem::Tick(base_internal::ThreadIdentity *identity) {
   const int ticker =
       identity->ticker.fetch_add(1, std::memory_order_relaxed) + 1;
@@ -58,6 +63,7 @@
 }
 
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 extern "C" {
diff --git a/absl/synchronization/internal/per_thread_sem.h b/absl/synchronization/internal/per_thread_sem.h
index e7da070..2228b6e 100644
--- a/absl/synchronization/internal/per_thread_sem.h
+++ b/absl/synchronization/internal/per_thread_sem.h
@@ -32,6 +32,7 @@
 #include "absl/synchronization/internal/kernel_timeout.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 class Mutex;
 
@@ -65,6 +66,10 @@
   // REQUIRES: May only be called by ThreadIdentity.
   static void Init(base_internal::ThreadIdentity* identity);
 
+  // Destroy the PerThreadSem associated with "identity".
+  // REQUIRES: May only be called by ThreadIdentity.
+  static void Destroy(base_internal::ThreadIdentity* identity);
+
   // Increments "identity"'s count.
   static inline void Post(base_internal::ThreadIdentity* identity);
 
@@ -73,13 +78,15 @@
   // !t.has_timeout() => Wait(t) will return true.
   static inline bool Wait(KernelTimeout t);
 
-  // White-listed callers.
+  // Permitted callers.
   friend class PerThreadSemTest;
   friend class absl::Mutex;
   friend absl::base_internal::ThreadIdentity* CreateThreadIdentity();
+  friend void ReclaimThreadIdentity(void* v);
 };
 
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 // In some build configurations we pass --detect-odr-violations to the
diff --git a/absl/synchronization/internal/per_thread_sem_test.cc b/absl/synchronization/internal/per_thread_sem_test.cc
index dba7239..8cf59e6 100644
--- a/absl/synchronization/internal/per_thread_sem_test.cc
+++ b/absl/synchronization/internal/per_thread_sem_test.cc
@@ -23,6 +23,7 @@
 #include <thread>              // NOLINT(build/c++11)
 
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/cycleclock.h"
 #include "absl/base/internal/thread_identity.h"
 #include "absl/strings/str_cat.h"
@@ -33,6 +34,7 @@
 // primitives which might use PerThreadSem, most notably absl::Mutex.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
 class SimpleSemaphore {
@@ -175,4 +177,5 @@
 }  // namespace
 
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/synchronization/internal/thread_pool.h b/absl/synchronization/internal/thread_pool.h
index a00f2be..0cb96da 100644
--- a/absl/synchronization/internal/thread_pool.h
+++ b/absl/synchronization/internal/thread_pool.h
@@ -26,6 +26,7 @@
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
 // A simple ThreadPool implementation for tests.
@@ -86,6 +87,7 @@
 };
 
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_
diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc
index f17ea56..2123be6 100644
--- a/absl/synchronization/internal/waiter.cc
+++ b/absl/synchronization/internal/waiter.cc
@@ -48,7 +48,9 @@
 #include "absl/base/optimization.h"
 #include "absl/synchronization/internal/kernel_timeout.h"
 
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
 static void MaybeBecomeIdle() {
@@ -65,73 +67,21 @@
 
 #if ABSL_WAITER_MODE == ABSL_WAITER_MODE_FUTEX
 
-// Some Android headers are missing these definitions even though they
-// support these futex operations.
-#ifdef __BIONIC__
-#ifndef SYS_futex
-#define SYS_futex __NR_futex
-#endif
-#ifndef FUTEX_WAIT_BITSET
-#define FUTEX_WAIT_BITSET 9
-#endif
-#ifndef FUTEX_PRIVATE_FLAG
-#define FUTEX_PRIVATE_FLAG 128
-#endif
-#ifndef FUTEX_CLOCK_REALTIME
-#define FUTEX_CLOCK_REALTIME 256
-#endif
-#ifndef FUTEX_BITSET_MATCH_ANY
-#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
-#endif
-#endif
-
-class Futex {
- public:
-  static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
-                       KernelTimeout t) {
-    int err = 0;
-    if (t.has_timeout()) {
-      // https://locklessinc.com/articles/futex_cheat_sheet/
-      // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time.
-      struct timespec abs_timeout = t.MakeAbsTimespec();
-      // Atomically check that the futex value is still 0, and if it
-      // is, sleep until abs_timeout or until woken by FUTEX_WAKE.
-      err = syscall(
-          SYS_futex, reinterpret_cast<int32_t *>(v),
-          FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val,
-          &abs_timeout, nullptr, FUTEX_BITSET_MATCH_ANY);
-    } else {
-      // Atomically check that the futex value is still 0, and if it
-      // is, sleep until woken by FUTEX_WAKE.
-      err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
-                    FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, nullptr);
-    }
-    if (err != 0) {
-      err = -errno;
-    }
-    return err;
-  }
-
-  static int Wake(std::atomic<int32_t> *v, int32_t count) {
-    int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
-                      FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);
-    if (ABSL_PREDICT_FALSE(err < 0)) {
-      err = -errno;
-    }
-    return err;
-  }
-};
-
-void Waiter::Init() {
+Waiter::Waiter() {
   futex_.store(0, std::memory_order_relaxed);
 }
 
+Waiter::~Waiter() = default;
+
 bool Waiter::Wait(KernelTimeout t) {
   // Loop until we can atomically decrement futex from a positive
   // value, waiting on a futex while we believe it is zero.
+  // Note that, since the thread ticker is just reset, we don't need to check
+  // whether the thread is idle on the very first pass of the loop.
+  bool first_pass = true;
   while (true) {
     int32_t x = futex_.load(std::memory_order_relaxed);
-    if (x != 0) {
+    while (x != 0) {
       if (!futex_.compare_exchange_weak(x, x - 1,
                                         std::memory_order_acquire,
                                         std::memory_order_relaxed)) {
@@ -140,6 +90,8 @@
       return true;  // Consumed a wakeup, we are done.
     }
 
+
+    if (!first_pass) MaybeBecomeIdle();
     const int err = Futex::WaitUntil(&futex_, 0, t);
     if (err != 0) {
       if (err == -EINTR || err == -EWOULDBLOCK) {
@@ -150,14 +102,13 @@
         ABSL_RAW_LOG(FATAL, "Futex operation failed with error %d\n", err);
       }
     }
-
-    MaybeBecomeIdle();
+    first_pass = false;
   }
 }
 
 void Waiter::Post() {
   if (futex_.fetch_add(1, std::memory_order_release) == 0) {
-    // We incremented from 0, need to wake a potential waker.
+    // We incremented from 0, need to wake a potential waiter.
     Poke();
   }
 }
@@ -195,7 +146,7 @@
   pthread_mutex_t *mu_;
 };
 
-void Waiter::Init() {
+Waiter::Waiter() {
   const int err = pthread_mutex_init(&mu_, 0);
   if (err != 0) {
     ABSL_RAW_LOG(FATAL, "pthread_mutex_init failed: %d", err);
@@ -206,8 +157,20 @@
     ABSL_RAW_LOG(FATAL, "pthread_cond_init failed: %d", err2);
   }
 
-  waiter_count_.store(0, std::memory_order_relaxed);
-  wakeup_count_.store(0, std::memory_order_relaxed);
+  waiter_count_ = 0;
+  wakeup_count_ = 0;
+}
+
+Waiter::~Waiter() {
+  const int err = pthread_mutex_destroy(&mu_);
+  if (err != 0) {
+    ABSL_RAW_LOG(FATAL, "pthread_mutex_destroy failed: %d", err);
+  }
+
+  const int err2 = pthread_cond_destroy(&cv_);
+  if (err2 != 0) {
+    ABSL_RAW_LOG(FATAL, "pthread_cond_destroy failed: %d", err2);
+  }
 }
 
 bool Waiter::Wait(KernelTimeout t) {
@@ -217,21 +180,13 @@
   }
 
   PthreadMutexHolder h(&mu_);
-  waiter_count_.fetch_add(1, std::memory_order_relaxed);
+  ++waiter_count_;
   // Loop until we find a wakeup to consume or timeout.
-  while (true) {
-    int x = wakeup_count_.load(std::memory_order_relaxed);
-    if (x != 0) {
-      if (!wakeup_count_.compare_exchange_weak(x, x - 1,
-                                               std::memory_order_acquire,
-                                               std::memory_order_relaxed)) {
-        continue;  // Raced with someone, retry.
-      }
-      // Successfully consumed a wakeup, we're done.
-      waiter_count_.fetch_sub(1, std::memory_order_relaxed);
-      return true;
-    }
-
+  // Note that, since the thread ticker is just reset, we don't need to check
+  // whether the thread is idle on the very first pass of the loop.
+  bool first_pass = true;
+  while (wakeup_count_ == 0) {
+    if (!first_pass) MaybeBecomeIdle();
     // No wakeups available, time to wait.
     if (!t.has_timeout()) {
       const int err = pthread_cond_wait(&cv_, &mu_);
@@ -241,46 +196,56 @@
     } else {
       const int err = pthread_cond_timedwait(&cv_, &mu_, &abs_timeout);
       if (err == ETIMEDOUT) {
-        waiter_count_.fetch_sub(1, std::memory_order_relaxed);
+        --waiter_count_;
         return false;
       }
       if (err != 0) {
-        ABSL_RAW_LOG(FATAL, "pthread_cond_wait failed: %d", err);
+        ABSL_RAW_LOG(FATAL, "pthread_cond_timedwait failed: %d", err);
       }
     }
-    MaybeBecomeIdle();
+    first_pass = false;
   }
+  // Consume a wakeup and we're done.
+  --wakeup_count_;
+  --waiter_count_;
+  return true;
 }
 
 void Waiter::Post() {
-  wakeup_count_.fetch_add(1, std::memory_order_release);
-  Poke();
+  PthreadMutexHolder h(&mu_);
+  ++wakeup_count_;
+  InternalCondVarPoke();
 }
 
 void Waiter::Poke() {
-  if (waiter_count_.load(std::memory_order_relaxed) == 0) {
-    return;
-  }
-  // Potentially a waker. Take the lock and check again.
   PthreadMutexHolder h(&mu_);
-  if (waiter_count_.load(std::memory_order_relaxed) == 0) {
-    return;
-  }
-  const int err = pthread_cond_signal(&cv_);
-  if (err != 0) {
-    ABSL_RAW_LOG(FATAL, "pthread_cond_signal failed: %d", err);
+  InternalCondVarPoke();
+}
+
+void Waiter::InternalCondVarPoke() {
+  if (waiter_count_ != 0) {
+    const int err = pthread_cond_signal(&cv_);
+    if (ABSL_PREDICT_FALSE(err != 0)) {
+      ABSL_RAW_LOG(FATAL, "pthread_cond_signal failed: %d", err);
+    }
   }
 }
 
 #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_SEM
 
-void Waiter::Init() {
+Waiter::Waiter() {
   if (sem_init(&sem_, 0, 0) != 0) {
     ABSL_RAW_LOG(FATAL, "sem_init failed with errno %d\n", errno);
   }
   wakeups_.store(0, std::memory_order_relaxed);
 }
 
+Waiter::~Waiter() {
+  if (sem_destroy(&sem_) != 0) {
+    ABSL_RAW_LOG(FATAL, "sem_destroy failed with errno %d\n", errno);
+  }
+}
+
 bool Waiter::Wait(KernelTimeout t) {
   struct timespec abs_timeout;
   if (t.has_timeout()) {
@@ -288,9 +253,12 @@
   }
 
   // Loop until we timeout or consume a wakeup.
+  // Note that, since the thread ticker is just reset, we don't need to check
+  // whether the thread is idle on the very first pass of the loop.
+  bool first_pass = true;
   while (true) {
     int x = wakeups_.load(std::memory_order_relaxed);
-    if (x != 0) {
+    while (x != 0) {
       if (!wakeups_.compare_exchange_weak(x, x - 1,
                                           std::memory_order_acquire,
                                           std::memory_order_relaxed)) {
@@ -300,6 +268,7 @@
       return true;
     }
 
+    if (!first_pass) MaybeBecomeIdle();
     // Nothing to consume, wait (looping on EINTR).
     while (true) {
       if (!t.has_timeout()) {
@@ -313,13 +282,16 @@
         ABSL_RAW_LOG(FATAL, "sem_timedwait failed: %d", errno);
       }
     }
-    MaybeBecomeIdle();
+    first_pass = false;
   }
 }
 
 void Waiter::Post() {
-  wakeups_.fetch_add(1, std::memory_order_release);  // Post a wakeup.
-  Poke();
+  // Post a wakeup.
+  if (wakeups_.fetch_add(1, std::memory_order_release) == 0) {
+    // We incremented from 0, need to wake a potential waiter.
+    Poke();
+  }
 }
 
 void Waiter::Poke() {
@@ -340,31 +312,29 @@
     return reinterpret_cast<CONDITION_VARIABLE *>(&w->cv_storage_);
   }
 
-  static_assert(sizeof(SRWLOCK) == sizeof(Waiter::SRWLockStorage),
-                "SRWLockStorage does not have the same size as SRWLOCK");
+  static_assert(sizeof(SRWLOCK) == sizeof(void *),
+                "`mu_storage_` does not have the same size as SRWLOCK");
+  static_assert(alignof(SRWLOCK) == alignof(void *),
+                "`mu_storage_` does not have the same alignment as SRWLOCK");
+
+  static_assert(sizeof(CONDITION_VARIABLE) == sizeof(void *),
+                "`ABSL_CONDITION_VARIABLE_STORAGE` does not have the same size "
+                "as `CONDITION_VARIABLE`");
   static_assert(
-      alignof(SRWLOCK) == alignof(Waiter::SRWLockStorage),
-      "SRWLockStorage does not have the same alignment as SRWLOCK");
+      alignof(CONDITION_VARIABLE) == alignof(void *),
+      "`cv_storage_` does not have the same alignment as `CONDITION_VARIABLE`");
 
-  static_assert(sizeof(CONDITION_VARIABLE) ==
-                    sizeof(Waiter::ConditionVariableStorage),
-                "ABSL_CONDITION_VARIABLE_STORAGE does not have the same size "
-                "as CONDITION_VARIABLE");
-  static_assert(alignof(CONDITION_VARIABLE) ==
-                    alignof(Waiter::ConditionVariableStorage),
-                "ConditionVariableStorage does not have the same "
-                "alignment as CONDITION_VARIABLE");
-
-  // The SRWLOCK and CONDITION_VARIABLE types must be trivially constuctible
+  // The SRWLOCK and CONDITION_VARIABLE types must be trivially constructible
   // and destructible because we never call their constructors or destructors.
   static_assert(std::is_trivially_constructible<SRWLOCK>::value,
-                "The SRWLOCK type must be trivially constructible");
-  static_assert(std::is_trivially_constructible<CONDITION_VARIABLE>::value,
-                "The CONDITION_VARIABLE type must be trivially constructible");
+                "The `SRWLOCK` type must be trivially constructible");
+  static_assert(
+      std::is_trivially_constructible<CONDITION_VARIABLE>::value,
+      "The `CONDITION_VARIABLE` type must be trivially constructible");
   static_assert(std::is_trivially_destructible<SRWLOCK>::value,
-                "The SRWLOCK type must be trivially destructible");
+                "The `SRWLOCK` type must be trivially destructible");
   static_assert(std::is_trivially_destructible<CONDITION_VARIABLE>::value,
-                "The CONDITION_VARIABLE type must be trivially destructible");
+                "The `CONDITION_VARIABLE` type must be trivially destructible");
 };
 
 class LockHolder {
@@ -384,36 +354,33 @@
   SRWLOCK* mu_;
 };
 
-void Waiter::Init() {
+Waiter::Waiter() {
   auto *mu = ::new (static_cast<void *>(&mu_storage_)) SRWLOCK;
   auto *cv = ::new (static_cast<void *>(&cv_storage_)) CONDITION_VARIABLE;
   InitializeSRWLock(mu);
   InitializeConditionVariable(cv);
-  waiter_count_.store(0, std::memory_order_relaxed);
-  wakeup_count_.store(0, std::memory_order_relaxed);
+  waiter_count_ = 0;
+  wakeup_count_ = 0;
 }
 
+// SRW locks and condition variables do not need to be explicitly destroyed.
+// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-initializesrwlock
+// https://stackoverflow.com/questions/28975958/why-does-windows-have-no-deleteconditionvariable-function-to-go-together-with
+Waiter::~Waiter() = default;
+
 bool Waiter::Wait(KernelTimeout t) {
   SRWLOCK *mu = WinHelper::GetLock(this);
   CONDITION_VARIABLE *cv = WinHelper::GetCond(this);
 
   LockHolder h(mu);
-  waiter_count_.fetch_add(1, std::memory_order_relaxed);
+  ++waiter_count_;
 
   // Loop until we find a wakeup to consume or timeout.
-  while (true) {
-    int x = wakeup_count_.load(std::memory_order_relaxed);
-    if (x != 0) {
-      if (!wakeup_count_.compare_exchange_weak(x, x - 1,
-                                               std::memory_order_acquire,
-                                               std::memory_order_relaxed)) {
-        continue;  // Raced with someone, retry.
-      }
-      // Successfully consumed a wakeup, we're done.
-      waiter_count_.fetch_sub(1, std::memory_order_relaxed);
-      return true;
-    }
-
+  // Note that, since the thread ticker is just reset, we don't need to check
+  // whether the thread is idle on the very first pass of the loop.
+  bool first_pass = true;
+  while (wakeup_count_ == 0) {
+    if (!first_pass) MaybeBecomeIdle();
     // No wakeups available, time to wait.
     if (!SleepConditionVariableSRW(cv, mu, t.InMillisecondsFromNow(), 0)) {
       // GetLastError() returns a Win32 DWORD, but we assign to
@@ -421,32 +388,35 @@
       // initialization guarantees this is not a narrowing conversion.
       const unsigned long err{GetLastError()};  // NOLINT(runtime/int)
       if (err == ERROR_TIMEOUT) {
-        waiter_count_.fetch_sub(1, std::memory_order_relaxed);
+        --waiter_count_;
         return false;
       } else {
         ABSL_RAW_LOG(FATAL, "SleepConditionVariableSRW failed: %lu", err);
       }
     }
-
-    MaybeBecomeIdle();
+    first_pass = false;
   }
+  // Consume a wakeup and we're done.
+  --wakeup_count_;
+  --waiter_count_;
+  return true;
 }
 
 void Waiter::Post() {
-  wakeup_count_.fetch_add(1, std::memory_order_release);
-  Poke();
+  LockHolder h(WinHelper::GetLock(this));
+  ++wakeup_count_;
+  InternalCondVarPoke();
 }
 
 void Waiter::Poke() {
-  if (waiter_count_.load(std::memory_order_relaxed) == 0) {
-    return;
-  }
-  // Potentially a waker. Take the lock and check again.
   LockHolder h(WinHelper::GetLock(this));
-  if (waiter_count_.load(std::memory_order_relaxed) == 0) {
-    return;
+  InternalCondVarPoke();
+}
+
+void Waiter::InternalCondVarPoke() {
+  if (waiter_count_ != 0) {
+    WakeConditionVariable(WinHelper::GetCond(this));
   }
-  WakeConditionVariable(WinHelper::GetCond(this));
 }
 
 #else
@@ -454,4 +424,5 @@
 #endif
 
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/synchronization/internal/waiter.h b/absl/synchronization/internal/waiter.h
index a3e3124..be3df18 100644
--- a/absl/synchronization/internal/waiter.h
+++ b/absl/synchronization/internal/waiter.h
@@ -18,10 +18,16 @@
 
 #include "absl/base/config.h"
 
-#ifndef _WIN32
+#ifdef _WIN32
+#include <sdkddkver.h>
+#else
 #include <pthread.h>
 #endif
 
+#ifdef __linux__
+#include <linux/futex.h>
+#endif
+
 #ifdef ABSL_HAVE_SEMAPHORE_H
 #include <semaphore.h>
 #endif
@@ -30,6 +36,7 @@
 #include <cstdint>
 
 #include "absl/base/internal/thread_identity.h"
+#include "absl/synchronization/internal/futex.h"
 #include "absl/synchronization/internal/kernel_timeout.h"
 
 // May be chosen at compile time via -DABSL_FORCE_WAITER_MODE=<index>
@@ -40,9 +47,9 @@
 
 #if defined(ABSL_FORCE_WAITER_MODE)
 #define ABSL_WAITER_MODE ABSL_FORCE_WAITER_MODE
-#elif defined(_WIN32)
+#elif defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_WIN32
-#elif defined(__linux__)
+#elif defined(ABSL_INTERNAL_HAVE_FUTEX)
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
 #elif defined(ABSL_HAVE_SEMAPHORE_H)
 #define ABSL_WAITER_MODE ABSL_WAITER_MODE_SEM
@@ -51,19 +58,21 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace synchronization_internal {
 
 // Waiter is an OS-specific semaphore.
 class Waiter {
  public:
-  // No constructor, instances use the reserved space in ThreadIdentity.
-  // All initialization logic belongs in `Init()`.
-  Waiter() = delete;
+  // Prepare any data to track waits.
+  Waiter();
+
+  // Not copyable or movable
   Waiter(const Waiter&) = delete;
   Waiter& operator=(const Waiter&) = delete;
 
-  // Prepare any data to track waits.
-  void Init();
+  // Destroy any data to track waits.
+  ~Waiter();
 
   // Blocks the calling thread until a matching call to `Post()` or
   // `t` has passed. Returns `true` if woken (`Post()` called),
@@ -87,8 +96,8 @@
   }
 
   // How many periods to remain idle before releasing resources
-#ifndef THREAD_SANITIZER
-  static const int kIdlePeriods = 60;
+#ifndef ABSL_HAVE_THREAD_SANITIZER
+  static constexpr int kIdlePeriods = 60;
 #else
   // Memory consumption under ThreadSanitizer is a serious concern,
   // so we release resources sooner. The value of 1 leads to 1 to 2 second
@@ -104,10 +113,13 @@
   static_assert(sizeof(int32_t) == sizeof(futex_), "Wrong size for futex");
 
 #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_CONDVAR
+  // REQUIRES: mu_ must be held.
+  void InternalCondVarPoke();
+
   pthread_mutex_t mu_;
   pthread_cond_t cv_;
-  std::atomic<int> waiter_count_;
-  std::atomic<int> wakeup_count_;  // Unclaimed wakeups, written under lock.
+  int waiter_count_;
+  int wakeup_count_;  // Unclaimed wakeups.
 
 #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_SEM
   sem_t sem_;
@@ -117,26 +129,19 @@
   std::atomic<int> wakeups_;
 
 #elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32
-  // The Windows API has lots of choices for synchronization
-  // primivitives.  We are using SRWLOCK and CONDITION_VARIABLE
-  // because they don't require a destructor to release system
-  // resources.
-  //
-  // However, we can't include Windows.h in our headers, so we use aligned
-  // storage buffers to define the storage.
-  using SRWLockStorage =
-      typename std::aligned_storage<sizeof(void*), alignof(void*)>::type;
-  using ConditionVariableStorage =
-      typename std::aligned_storage<sizeof(void*), alignof(void*)>::type;
-
   // WinHelper - Used to define utilities for accessing the lock and
   // condition variable storage once the types are complete.
   class WinHelper;
 
-  SRWLockStorage mu_storage_;
-  ConditionVariableStorage cv_storage_;
-  std::atomic<int> waiter_count_;
-  std::atomic<int> wakeup_count_;
+  // REQUIRES: WinHelper::GetLock(this) must be held.
+  void InternalCondVarPoke();
+
+  // We can't include Windows.h in our headers, so we use aligned charachter
+  // buffers to define the storage of SRWLOCK and CONDITION_VARIABLE.
+  alignas(void*) unsigned char mu_storage_[sizeof(void*)];
+  alignas(void*) unsigned char cv_storage_[sizeof(void*)];
+  int waiter_count_;
+  int wakeup_count_;
 
 #else
   #error Unknown ABSL_WAITER_MODE
@@ -144,6 +149,7 @@
 };
 
 }  // namespace synchronization_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_
diff --git a/absl/synchronization/lifetime_test.cc b/absl/synchronization/lifetime_test.cc
index 34b8875..cc973a3 100644
--- a/absl/synchronization/lifetime_test.cc
+++ b/absl/synchronization/lifetime_test.cc
@@ -122,6 +122,11 @@
   Function fn_;
 };
 
+// These tests require that the compiler correctly supports C++11 constant
+// initialization... but MSVC has a known regression since v19.10:
+// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html
+// TODO(epastor): Limit the affected range once MSVC fixes this bug.
+#if defined(__clang__) || !(defined(_MSC_VER) && _MSC_VER > 1900)
 // kConstInit
 // Test early usage.  (Declaration comes first; definitions must appear after
 // the test runner.)
@@ -151,6 +156,7 @@
   const_init_sanity_mutex.AssertHeld();
   const_init_sanity_mutex.Unlock();
 });
+#endif  // defined(__clang__) || !(defined(_MSC_VER) && _MSC_VER > 1900)
 
 // Test shutdown usage.  (Declarations come first; definitions must appear after
 // the test runner.)
diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc
index 100def2..9e01393 100644
--- a/absl/synchronization/mutex.cc
+++ b/absl/synchronization/mutex.cc
@@ -39,6 +39,7 @@
 #include <thread>  // NOLINT(build/c++11)
 
 #include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
 #include "absl/base/config.h"
 #include "absl/base/dynamic_annotations.h"
 #include "absl/base/internal/atomic_hook.h"
@@ -49,6 +50,7 @@
 #include "absl/base/internal/spinlock.h"
 #include "absl/base/internal/sysinfo.h"
 #include "absl/base/internal/thread_identity.h"
+#include "absl/base/internal/tsan_mutex_interface.h"
 #include "absl/base/port.h"
 #include "absl/debugging/stacktrace.h"
 #include "absl/debugging/symbolize.h"
@@ -58,6 +60,7 @@
 
 using absl::base_internal::CurrentThreadIdentityIfPresent;
 using absl::base_internal::PerThreadSynch;
+using absl::base_internal::SchedulingGuard;
 using absl::base_internal::ThreadIdentity;
 using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity;
 using absl::synchronization_internal::GraphCycles;
@@ -71,10 +74,11 @@
 }  // extern "C"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace {
 
-#if defined(THREAD_SANITIZER)
+#if defined(ABSL_HAVE_THREAD_SANITIZER)
 constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kIgnore;
 #else
 constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kAbort;
@@ -84,35 +88,16 @@
     kDeadlockDetectionDefault);
 ABSL_CONST_INIT std::atomic<bool> synch_check_invariants(false);
 
-// ------------------------------------------ spinlock support
-
-// Make sure read-only globals used in the Mutex code are contained on the
-// same cacheline and cacheline aligned to eliminate any false sharing with
-// other globals from this and other modules.
-static struct MutexGlobals {
-  MutexGlobals() {
-    // Find machine-specific data needed for Delay() and
-    // TryAcquireWithSpinning(). This runs in the global constructor
-    // sequence, and before that zeros are safe values.
-    num_cpus = absl::base_internal::NumCPUs();
-    spinloop_iterations = num_cpus > 1 ? 1500 : 0;
-  }
-  int num_cpus;
-  int spinloop_iterations;
-  // Pad this struct to a full cacheline to prevent false sharing.
-  char padding[ABSL_CACHELINE_SIZE - 2 * sizeof(int)];
-} ABSL_CACHELINE_ALIGNED mutex_globals;
-static_assert(
-    sizeof(MutexGlobals) == ABSL_CACHELINE_SIZE,
-    "MutexGlobals must occupy an entire cacheline to prevent false sharing");
-
-ABSL_CONST_INIT absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
     submit_profile_data;
-ABSL_CONST_INIT absl::base_internal::AtomicHook<
-    void (*)(const char *msg, const void *obj, int64_t wait_cycles)> mutex_tracer;
-ABSL_CONST_INIT absl::base_internal::AtomicHook<
-    void (*)(const char *msg, const void *cv)> cond_var_tracer;
-ABSL_CONST_INIT absl::base_internal::AtomicHook<
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<void (*)(
+    const char *msg, const void *obj, int64_t wait_cycles)>
+    mutex_tracer;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+    absl::base_internal::AtomicHook<void (*)(const char *msg, const void *cv)>
+        cond_var_tracer;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<
     bool (*)(const void *pc, char *out, int out_size)>
     symbolizer(absl::Symbolize);
 
@@ -139,33 +124,55 @@
   symbolizer.Store(fn);
 }
 
-// spinlock delay on iteration c.  Returns new c.
+struct ABSL_CACHELINE_ALIGNED MutexGlobals {
+  absl::once_flag once;
+  int num_cpus = 0;
+  int spinloop_iterations = 0;
+};
+
+static const MutexGlobals& GetMutexGlobals() {
+  ABSL_CONST_INIT static MutexGlobals data;
+  absl::base_internal::LowLevelCallOnce(&data.once, [&]() {
+    data.num_cpus = absl::base_internal::NumCPUs();
+    data.spinloop_iterations = data.num_cpus > 1 ? 1500 : 0;
+  });
+  return data;
+}
+
+// Spinlock delay on iteration c.  Returns new c.
 namespace {
   enum DelayMode { AGGRESSIVE, GENTLE };
 };
-static int Delay(int32_t c, DelayMode mode) {
+
+namespace synchronization_internal {
+int MutexDelay(int32_t c, int mode) {
   // If this a uniprocessor, only yield/sleep.  Otherwise, if the mode is
   // aggressive then spin many times before yielding.  If the mode is
   // gentle then spin only a few times before yielding.  Aggressive spinning is
   // used to ensure that an Unlock() call, which  must get the spin lock for
   // any thread to make progress gets it without undue delay.
-  int32_t limit = (mutex_globals.num_cpus > 1) ?
-      ((mode == AGGRESSIVE) ? 5000 : 250) : 0;
+  const int32_t limit =
+      GetMutexGlobals().num_cpus > 1 ? (mode == AGGRESSIVE ? 5000 : 250) : 0;
   if (c < limit) {
-    c++;               // spin
+    // Spin.
+    c++;
   } else {
+    SchedulingGuard::ScopedEnable enable_rescheduling;
     ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0);
-    if (c == limit) {  // yield once
+    if (c == limit) {
+      // Yield once.
       AbslInternalMutexYield();
       c++;
-    } else {           // then wait
+    } else {
+      // Then wait.
       absl::SleepFor(absl::Microseconds(10));
       c = 0;
     }
     ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0);
   }
-  return (c);
+  return c;
 }
+}  // namespace synchronization_internal
 
 // --------------------------Generic atomic ops
 // Ensure that "(*pv & bits) == bits" by doing an atomic update of "*pv" to
@@ -203,12 +210,12 @@
 //------------------------------------------------------------------
 
 // Data for doing deadlock detection.
-static absl::base_internal::SpinLock deadlock_graph_mu(
-    absl::base_internal::kLinkerInitialized);
+ABSL_CONST_INIT static absl::base_internal::SpinLock deadlock_graph_mu(
+    absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
 
-// graph used to detect deadlocks.
-static GraphCycles *deadlock_graph ABSL_GUARDED_BY(deadlock_graph_mu)
-    ABSL_PT_GUARDED_BY(deadlock_graph_mu);
+// Graph used to detect deadlocks.
+ABSL_CONST_INIT static GraphCycles *deadlock_graph
+    ABSL_GUARDED_BY(deadlock_graph_mu) ABSL_PT_GUARDED_BY(deadlock_graph_mu);
 
 //------------------------------------------------------------------
 // An event mechanism for debugging mutex use.
@@ -269,13 +276,12 @@
     {0, "SignalAll on "},
 };
 
-static absl::base_internal::SpinLock synch_event_mu(
-    absl::base_internal::kLinkerInitialized);
-// protects synch_event
+ABSL_CONST_INIT static absl::base_internal::SpinLock synch_event_mu(
+    absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
 
 // Hash table size; should be prime > 2.
 // Can't be too small, as it's used for deadlock detection information.
-static const uint32_t kNSynchEvent = 1031;
+static constexpr uint32_t kNSynchEvent = 1031;
 
 static struct SynchEvent {     // this is a trivial hash table for the events
   // struct is freed when refcount reaches 0
@@ -295,7 +301,7 @@
   bool log;             // logging turned on
 
   // Constant after initialization
-  char name[1];         // actually longer---null-terminated std::string
+  char name[1];         // actually longer---NUL-terminated string
 } * synch_event[kNSynchEvent] ABSL_GUARDED_BY(synch_event_mu);
 
 // Ensure that the object at "addr" has a SynchEvent struct associated with it,
@@ -486,7 +492,7 @@
   std::atomic<intptr_t> *cv_word;
 
   int64_t contention_start_cycles;  // Time (in cycles) when this thread started
-                                  // to contend for the mutex.
+                                    // to contend for the mutex.
 };
 
 struct SynchLocksHeld {
@@ -700,7 +706,7 @@
 static constexpr bool kDebugMode = true;
 #endif
 
-#ifdef THREAD_SANITIZER
+#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
 static unsigned TsanFlags(Mutex::MuHow how) {
   return how == kShared ? __tsan_mutex_read_lock : 0;
 }
@@ -1051,6 +1057,7 @@
 // Try to remove thread s from the list of waiters on this mutex.
 // Does nothing if s is not on the waiter list.
 void Mutex::TryRemove(PerThreadSynch *s) {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   intptr_t v = mu_.load(std::memory_order_relaxed);
   // acquire spinlock & lock
   if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait &&
@@ -1115,7 +1122,7 @@
       this->TryRemove(s);
       int c = 0;
       while (s->next != nullptr) {
-        c = Delay(c, GENTLE);
+        c = synchronization_internal::MutexDelay(c, GENTLE);
         this->TryRemove(s);
       }
       if (kDebugMode) {
@@ -1434,21 +1441,19 @@
 // Attempt to acquire *mu, and return whether successful.  The implementation
 // may spin for a short while if the lock cannot be acquired immediately.
 static bool TryAcquireWithSpinning(std::atomic<intptr_t>* mu) {
-  int c = mutex_globals.spinloop_iterations;
-  int result = -1;  // result of operation:  0=false, 1=true, -1=unknown
-
+  int c = GetMutexGlobals().spinloop_iterations;
   do {  // do/while somewhat faster on AMD
     intptr_t v = mu->load(std::memory_order_relaxed);
-    if ((v & (kMuReader|kMuEvent)) != 0) {  // a reader or tracing -> give up
-      result = 0;
+    if ((v & (kMuReader|kMuEvent)) != 0) {
+      return false;  // a reader or tracing -> give up
     } else if (((v & kMuWriter) == 0) &&  // no holder -> try to acquire
                mu->compare_exchange_strong(v, kMuWriter | v,
                                            std::memory_order_acquire,
                                            std::memory_order_relaxed)) {
-      result = 1;
+      return true;
     }
-  } while (result == -1 && --c > 0);
-  return result == 1;
+  } while (--c > 0);
+  return false;
 }
 
 ABSL_XRAY_LOG_ARGS(1) void Mutex::Lock() {
@@ -1747,7 +1752,8 @@
 };
 
 // Internal version of LockWhen().  See LockSlowWithDeadline()
-void Mutex::LockSlow(MuHow how, const Condition *cond, int flags) {
+ABSL_ATTRIBUTE_NOINLINE void Mutex::LockSlow(MuHow how, const Condition *cond,
+                                             int flags) {
   ABSL_RAW_CHECK(
       this->LockSlowWithDeadline(how, cond, KernelTimeout::Never(), flags),
       "condition untrue on return from LockSlow");
@@ -1762,7 +1768,7 @@
   // All memory accesses are ignored inside of mutex operations + for unlock
   // operation tsan considers that we've already released the mutex.
   bool res = false;
-#ifdef THREAD_SANITIZER
+#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
   const int flags = read_lock ? __tsan_mutex_read_lock : 0;
   const int tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);
 #endif
@@ -1812,9 +1818,9 @@
   // So we "divert" (which un-ignores both memory accesses and synchronization)
   // and then separately turn on ignores of memory accesses.
   ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
-  ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
+  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
   bool res = cond->Eval();
-  ANNOTATE_IGNORE_READS_AND_WRITES_END();
+  ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
   ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
   static_cast<void>(mu);  // Prevent unused param warning in non-TSAN builds.
   return res;
@@ -1895,6 +1901,7 @@
 }
 
 void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   int c = 0;
   intptr_t v = mu_.load(std::memory_order_relaxed);
   if ((v & kMuEvent) != 0) {
@@ -1996,7 +2003,8 @@
     ABSL_RAW_CHECK(
         waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
         "detected illegal recursion into Mutex code");
-    c = Delay(c, GENTLE);          // delay, then try again
+    // delay, then try again
+    c = synchronization_internal::MutexDelay(c, GENTLE);
   }
   ABSL_RAW_CHECK(
       waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
@@ -2013,7 +2021,8 @@
 // which holds the lock but is not runnable because its condition is false
 // or it is in the process of blocking on a condition variable; it must requeue
 // itself on the mutex/condvar to wait for its condition to become true.
-void Mutex::UnlockSlow(SynchWaitParams *waitp) {
+ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   intptr_t v = mu_.load(std::memory_order_relaxed);
   this->AssertReaderHeld();
   CheckForMutexCorruption(v, "Unlock");
@@ -2290,7 +2299,8 @@
       mu_.store(nv, std::memory_order_release);
       break;  // out of for(;;)-loop
     }
-    c = Delay(c, AGGRESSIVE);  // aggressive here; no one can proceed till we do
+    // aggressive here; no one can proceed till we do
+    c = synchronization_internal::MutexDelay(c, AGGRESSIVE);
   }                            // end of for(;;)-loop
 
   if (wake_list != kPerThreadSynchNull) {
@@ -2302,7 +2312,8 @@
     if (!cond_waiter) {
       // Sample lock contention events only if the (first) waiter was trying to
       // acquire the lock, not waiting on a condition variable or Condition.
-      int64_t wait_cycles = base_internal::CycleClock::Now() - enqueue_timestamp;
+      int64_t wait_cycles =
+          base_internal::CycleClock::Now() - enqueue_timestamp;
       mutex_tracer("slow release", this, wait_cycles);
       ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
       submit_profile_data(enqueue_timestamp);
@@ -2329,6 +2340,7 @@
 // It will later acquire the mutex with high probability.  Otherwise, we
 // enqueue thread w on this mutex.
 void Mutex::Fer(PerThreadSynch *w) {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   int c = 0;
   ABSL_RAW_CHECK(w->waitp->cond == nullptr,
                  "Mutex::Fer while waiting on Condition");
@@ -2378,7 +2390,7 @@
         return;
       }
     }
-    c = Delay(c, GENTLE);
+    c = synchronization_internal::MutexDelay(c, GENTLE);
   }
 }
 
@@ -2427,6 +2439,7 @@
 
 // Remove thread s from the list of waiters on this condition variable.
 void CondVar::Remove(PerThreadSynch *s) {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   intptr_t v;
   int c = 0;
   for (v = cv_.load(std::memory_order_relaxed);;
@@ -2455,7 +2468,8 @@
                 std::memory_order_release);
       return;
     } else {
-      c = Delay(c, GENTLE);            // try again after a delay
+      // try again after a delay
+      c = synchronization_internal::MutexDelay(c, GENTLE);
     }
   }
 }
@@ -2488,7 +2502,7 @@
          !cv_word->compare_exchange_weak(v, v | kCvSpin,
                                          std::memory_order_acquire,
                                          std::memory_order_relaxed)) {
-    c = Delay(c, GENTLE);
+    c = synchronization_internal::MutexDelay(c, GENTLE);
     v = cv_word->load(std::memory_order_relaxed);
   }
   ABSL_RAW_CHECK(waitp->thread->waitp == nullptr, "waiting when shouldn't be");
@@ -2587,6 +2601,7 @@
 }
 
 void CondVar::Signal() {
+  SchedulingGuard::ScopedDisable disable_rescheduling;
   ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);
   intptr_t v;
   int c = 0;
@@ -2619,7 +2634,7 @@
       ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
       return;
     } else {
-      c = Delay(c, GENTLE);
+      c = synchronization_internal::MutexDelay(c, GENTLE);
     }
   }
   ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
@@ -2656,7 +2671,8 @@
       ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
       return;
     } else {
-      c = Delay(c, GENTLE);           // try again after a delay
+      // try again after a delay
+      c = synchronization_internal::MutexDelay(c, GENTLE);
     }
   }
   ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
@@ -2669,7 +2685,7 @@
   this->mu_ = nullptr;
 }
 
-#ifdef THREAD_SANITIZER
+#ifdef ABSL_HAVE_THREAD_SANITIZER
 extern "C" void __tsan_read1(void *addr);
 #else
 #define __tsan_read1(addr)  // do nothing if TSan not enabled
@@ -2720,4 +2736,5 @@
          a->arg_ == b->arg_ && a->method_ == b->method_;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h
index d33318d..598d1e0 100644
--- a/absl/synchronization/mutex.h
+++ b/absl/synchronization/mutex.h
@@ -31,22 +31,23 @@
 //
 //  MutexLock - An RAII wrapper to acquire and release a `Mutex` for exclusive/
 //              write access within the current scope.
+//
 //  ReaderMutexLock
 //            - An RAII wrapper to acquire and release a `Mutex` for shared/read
 //              access within the current scope.
 //
 //  WriterMutexLock
-//            - Alias for `MutexLock` above, designed for use in distinguishing
-//              reader and writer locks within code.
+//            - Effectively an alias for `MutexLock` above, designed for use in
+//              distinguishing reader and writer locks within code.
 //
 // In addition to simple mutex locks, this file also defines ways to perform
 // locking under certain conditions.
 //
-//  Condition   - (Preferred) Used to wait for a particular predicate that
-//                depends on state protected by the `Mutex` to become true.
-//  CondVar     - A lower-level variant of `Condition` that relies on
-//                application code to explicitly signal the `CondVar` when
-//                a condition has been met.
+//  Condition - (Preferred) Used to wait for a particular predicate that
+//              depends on state protected by the `Mutex` to become true.
+//  CondVar   - A lower-level variant of `Condition` that relies on
+//              application code to explicitly signal the `CondVar` when
+//              a condition has been met.
 //
 // See below for more information on using `Condition` or `CondVar`.
 //
@@ -72,16 +73,8 @@
 #include "absl/synchronization/internal/per_thread_sem.h"
 #include "absl/time/time.h"
 
-// Decide if we should use the non-production implementation because
-// the production implementation hasn't been fully ported yet.
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-#error ABSL_INTERNAL_USE_NONPROD_MUTEX cannot be directly set
-#elif defined(ABSL_LOW_LEVEL_ALLOC_MISSING)
-#define ABSL_INTERNAL_USE_NONPROD_MUTEX 1
-#include "absl/synchronization/internal/mutex_nonprod.inc"
-#endif
-
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 class Condition;
 struct SynchWaitParams;
@@ -330,17 +323,16 @@
   // Mutex::AwaitWithTimeout()
   // Mutex::AwaitWithDeadline()
   //
-  // If `cond` is initially true, do nothing, or act as though `cond` is
-  // initially false.
-  //
-  // If `cond` is initially false, unlock this `Mutex` and block until
-  // simultaneously:
+  // Unlocks this `Mutex` and blocks until simultaneously:
   //   - either `cond` is true or the {timeout has expired, deadline has passed}
   //     and
   //   - this `Mutex` can be reacquired,
   // then reacquire this `Mutex` in the same mode in which it was previously
   // held, returning `true` iff `cond` is `true` on return.
   //
+  // If the condition is initially `true`, the implementation *may* skip the
+  // release/re-acquire step and return immediately.
+  //
   // Deadlines in the past are equivalent to an immediate deadline.
   // Negative timeouts are equivalent to a zero timeout.
   //
@@ -461,15 +453,6 @@
   static void InternalAttemptToUseMutexInFatalSignalHandler();
 
  private:
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-  friend class CondVar;
-
-  synchronization_internal::MutexImpl *impl() { return impl_.get(); }
-
-  synchronization_internal::SynchronizationStorage<
-      synchronization_internal::MutexImpl>
-      impl_;
-#else
   std::atomic<intptr_t> mu_;  // The Mutex state.
 
   // Post()/Wait() versus associated PerThreadSem; in class for required
@@ -504,7 +487,6 @@
   void Trans(MuHow how);  // used for CondVar->Mutex transfer
   void Fer(
       base_internal::PerThreadSynch *w);  // used for CondVar->Mutex transfer
-#endif
 
   // Catch the error of writing Mutex when intending MutexLock.
   Mutex(const volatile Mutex * /*ignored*/) {}  // NOLINT(runtime/explicit)
@@ -525,22 +507,36 @@
 // Example:
 //
 // Class Foo {
-//
+//  public:
 //   Foo::Bar* Baz() {
-//     MutexLock l(&lock_);
+//     MutexLock lock(&mu_);
 //     ...
 //     return bar;
 //   }
 //
 // private:
-//   Mutex lock_;
+//   Mutex mu_;
 // };
 class ABSL_SCOPED_LOCKABLE MutexLock {
  public:
+  // Constructors
+
+  // Calls `mu->Lock()` and returns when that call returns. That is, `*mu` is
+  // guaranteed to be locked when this object is constructed. Requires that
+  // `mu` be dereferenceable.
   explicit MutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
     this->mu_->Lock();
   }
 
+  // Like above, but calls `mu->LockWhen(cond)` instead. That is, in addition to
+  // the above, the condition given by `cond` is also guaranteed to hold when
+  // this object is constructed.
+  explicit MutexLock(Mutex *mu, const Condition &cond)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    this->mu_->LockWhen(cond);
+  }
+
   MutexLock(const MutexLock &) = delete;  // NOLINT(runtime/mutex)
   MutexLock(MutexLock&&) = delete;  // NOLINT(runtime/mutex)
   MutexLock& operator=(const MutexLock&) = delete;
@@ -562,6 +558,12 @@
     mu->ReaderLock();
   }
 
+  explicit ReaderMutexLock(Mutex *mu, const Condition &cond)
+      ABSL_SHARED_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    mu->ReaderLockWhen(cond);
+  }
+
   ReaderMutexLock(const ReaderMutexLock&) = delete;
   ReaderMutexLock(ReaderMutexLock&&) = delete;
   ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;
@@ -584,6 +586,12 @@
     mu->WriterLock();
   }
 
+  explicit WriterMutexLock(Mutex *mu, const Condition &cond)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    mu->WriterLockWhen(cond);
+  }
+
   WriterMutexLock(const WriterMutexLock&) = delete;
   WriterMutexLock(WriterMutexLock&&) = delete;
   WriterMutexLock& operator=(const WriterMutexLock&) = delete;
@@ -622,16 +630,26 @@
 // `noexcept`; until then this requirement cannot be enforced in the
 // type system.)
 //
-// Note: to use a `Condition`, you need only construct it and pass it within the
-// appropriate `Mutex' member function, such as `Mutex::Await()`.
+// Note: to use a `Condition`, you need only construct it and pass it to a
+// suitable `Mutex' member function, such as `Mutex::Await()`, or to the
+// constructor of one of the scope guard classes.
 //
-// Example:
+// Example using LockWhen/Unlock:
 //
 //   // assume count_ is not internal reference count
-//   int count_ GUARDED_BY(mu_);
+//   int count_ ABSL_GUARDED_BY(mu_);
+//   Condition count_is_zero(+[](int *count) { return *count == 0; }, &count_);
 //
-//   mu_.LockWhen(Condition(+[](int* count) { return *count == 0; },
-//         &count_));
+//   mu_.LockWhen(count_is_zero);
+//   // ...
+//   mu_.Unlock();
+//
+// Example using a scope guard:
+//
+//   {
+//     MutexLock lock(&mu_, count_is_zero);
+//     // ...
+//   }
 //
 // When multiple threads are waiting on exactly the same condition, make sure
 // that they are constructed with the same parameters (same pointer to function
@@ -685,6 +703,11 @@
   //     return processed_ >= current;
   //   };
   //   mu_.Await(Condition(&reached));
+  //
+  // NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReaderHeld()" in
+  // the lambda as it may be called when the mutex is being unlocked from a
+  // scope holding only a reader lock, which will make the assertion not
+  // fulfilled and crash the binary.
 
   // See class comment for performance advice. In particular, if there
   // might be more than one waiter for the same condition, make sure
@@ -769,6 +792,8 @@
 //
 class CondVar {
  public:
+  // A `CondVar` allocated on the heap or on the stack can use the this
+  // constructor.
   CondVar();
   ~CondVar();
 
@@ -831,17 +856,10 @@
   void EnableDebugLog(const char *name);
 
  private:
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-  synchronization_internal::CondVarImpl *impl() { return impl_.get(); }
-  synchronization_internal::SynchronizationStorage<
-      synchronization_internal::CondVarImpl>
-      impl_;
-#else
   bool WaitCommon(Mutex *mutex, synchronization_internal::KernelTimeout t);
   void Remove(base_internal::PerThreadSynch *s);
   void Wakeup(base_internal::PerThreadSynch *w);
   std::atomic<intptr_t> cv_;  // Condition variable state.
-#endif
   CondVar(const CondVar&) = delete;
   CondVar& operator=(const CondVar&) = delete;
 };
@@ -863,6 +881,15 @@
       this->mu_->Lock();
     }
   }
+
+  explicit MutexLockMaybe(Mutex *mu, const Condition &cond)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    if (this->mu_ != nullptr) {
+      this->mu_->LockWhen(cond);
+    }
+  }
+
   ~MutexLockMaybe() ABSL_UNLOCK_FUNCTION() {
     if (this->mu_ != nullptr) { this->mu_->Unlock(); }
   }
@@ -885,6 +912,13 @@
       : mu_(mu) {
     this->mu_->Lock();
   }
+
+  explicit ReleasableMutexLock(Mutex *mu, const Condition &cond)
+      ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+      : mu_(mu) {
+    this->mu_->LockWhen(cond);
+  }
+
   ~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {
     if (this->mu_ != nullptr) { this->mu_->Unlock(); }
   }
@@ -899,10 +933,6 @@
   ReleasableMutexLock& operator=(ReleasableMutexLock&&) = delete;
 };
 
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-inline constexpr Mutex::Mutex(absl::ConstInitType) : impl_(absl::kConstInit) {}
-
-#else
 inline Mutex::Mutex() : mu_(0) {
   ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
 }
@@ -910,7 +940,6 @@
 inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {}
 
 inline CondVar::CondVar() : cv_(0) {}
-#endif
 
 // static
 template <typename T>
@@ -978,7 +1007,7 @@
 //
 // This has the same memory ordering concerns as RegisterMutexProfiler() above.
 void RegisterMutexTracer(void (*fn)(const char *msg, const void *obj,
-                              int64_t wait_cycles));
+                                    int64_t wait_cycles));
 
 // TODO(gfalcon): Combine RegisterMutexProfiler() and RegisterMutexTracer()
 // into a single interface, since they are only ever called in pairs.
@@ -1000,7 +1029,7 @@
 //
 // 'pc' is the program counter being symbolized, 'out' is the buffer to write
 // into, and 'out_size' is the size of the buffer.  This function can return
-// false if symbolizing failed, or true if a null-terminated symbol was written
+// false if symbolizing failed, or true if a NUL-terminated symbol was written
 // to 'out.'
 //
 // This has the same memory ordering concerns as RegisterMutexProfiler() above.
@@ -1039,6 +1068,7 @@
 // the manner chosen here.
 void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode);
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 // In some build configurations we pass --detect-odr-violations to the
diff --git a/absl/synchronization/mutex_benchmark.cc b/absl/synchronization/mutex_benchmark.cc
index ab18800..933ea14 100644
--- a/absl/synchronization/mutex_benchmark.cc
+++ b/absl/synchronization/mutex_benchmark.cc
@@ -16,6 +16,7 @@
 #include <mutex>  // NOLINT(build/c++11)
 #include <vector>
 
+#include "absl/base/config.h"
 #include "absl/base/internal/cycleclock.h"
 #include "absl/base/internal/spinlock.h"
 #include "absl/synchronization/blocking_counter.h"
@@ -213,7 +214,7 @@
 }
 
 // Some configurations have higher thread limits than others.
-#if defined(__linux__) && !defined(THREAD_SANITIZER)
+#if defined(__linux__) && !defined(ABSL_HAVE_THREAD_SANITIZER)
 constexpr int kMaxConditionWaiters = 8192;
 #else
 constexpr int kMaxConditionWaiters = 1024;
diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc
index afb363a..058f757 100644
--- a/absl/synchronization/mutex_test.cc
+++ b/absl/synchronization/mutex_test.cc
@@ -30,6 +30,7 @@
 
 #include "gtest/gtest.h"
 #include "absl/base/attributes.h"
+#include "absl/base/config.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/internal/sysinfo.h"
 #include "absl/memory/memory.h"
@@ -706,6 +707,40 @@
   t.join();
 }
 
+TEST(Mutex, LockWhenGuard) {
+  absl::Mutex mu;
+  int n = 30;
+  bool done = false;
+
+  // We don't inline the lambda because the conversion is ambiguous in MSVC.
+  bool (*cond_eq_10)(int *) = [](int *p) { return *p == 10; };
+  bool (*cond_lt_10)(int *) = [](int *p) { return *p < 10; };
+
+  std::thread t1([&mu, &n, &done, cond_eq_10]() {
+    absl::ReaderMutexLock lock(&mu, absl::Condition(cond_eq_10, &n));
+    done = true;
+  });
+
+  std::thread t2[10];
+  for (std::thread &t : t2) {
+    t = std::thread([&mu, &n, cond_lt_10]() {
+      absl::WriterMutexLock lock(&mu, absl::Condition(cond_lt_10, &n));
+      ++n;
+    });
+  }
+
+  {
+    absl::MutexLock lock(&mu);
+    n = 0;
+  }
+
+  for (std::thread &t : t2) t.join();
+  t1.join();
+
+  EXPECT_TRUE(done);
+  EXPECT_EQ(n, 10);
+}
+
 // --------------------------------------------------------
 // The following test requires Mutex::ReaderLock to be a real shared
 // lock, which is not the case in all builds.
@@ -815,7 +850,7 @@
 
 // Test that we correctly handle the situation when a lock is
 // held and then destroyed (w/o unlocking).
-#ifdef THREAD_SANITIZER
+#ifdef ABSL_HAVE_THREAD_SANITIZER
 // TSAN reports errors when locked Mutexes are destroyed.
 TEST(Mutex, DISABLED_LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
 #else
@@ -1001,9 +1036,6 @@
   x.mu0.Unlock();
 }
 
-// The deadlock detector is not part of non-prod builds, so do not test it.
-#if !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
-
 TEST(Mutex, DeadlockDetector) {
   absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
 
@@ -1067,7 +1099,7 @@
 const char ScopedDisableBazelTestWarnings::kVarName[] =
     "TEST_WARNINGS_OUTPUT_FILE";
 
-#ifdef THREAD_SANITIZER
+#ifdef ABSL_HAVE_THREAD_SANITIZER
 // This test intentionally creates deadlocks to test the deadlock detector.
 TEST(Mutex, DISABLED_DeadlockDetectorBazelWarning) {
 #else
@@ -1101,7 +1133,7 @@
 // annotation-based static thread-safety analysis is not currently
 // predicate-aware and cannot tell if the two for-loops that acquire and
 // release the locks have the same predicates.
-TEST(Mutex, DeadlockDetectorStessTest) ABSL_NO_THREAD_SAFETY_ANALYSIS {
+TEST(Mutex, DeadlockDetectorStressTest) ABSL_NO_THREAD_SAFETY_ANALYSIS {
   // Stress test: Here we create a large number of locks and use all of them.
   // If a deadlock detector keeps a full graph of lock acquisition order,
   // it will likely be too slow for this test to pass.
@@ -1119,7 +1151,7 @@
   }
 }
 
-#ifdef THREAD_SANITIZER
+#ifdef ABSL_HAVE_THREAD_SANITIZER
 // TSAN reports errors when locked Mutexes are destroyed.
 TEST(Mutex, DISABLED_DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
 #else
@@ -1157,7 +1189,6 @@
   c.Lock();
   c.Unlock();
 }
-#endif  // !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
 
 // --------------------------------------------------------
 // Test for timeouts/deadlines on condition waits that are specified using
diff --git a/absl/synchronization/notification.cc b/absl/synchronization/notification.cc
index 53ace00..e91b903 100644
--- a/absl/synchronization/notification.cc
+++ b/absl/synchronization/notification.cc
@@ -22,6 +22,7 @@
 #include "absl/time/time.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 void Notification::Notify() {
   MutexLock l(&this->mutex_);
@@ -44,15 +45,6 @@
   MutexLock l(&this->mutex_);
 }
 
-static inline bool HasBeenNotifiedInternal(
-    const std::atomic<bool> *notified_yet) {
-  return notified_yet->load(std::memory_order_acquire);
-}
-
-bool Notification::HasBeenNotified() const {
-  return HasBeenNotifiedInternal(&this->notified_yet_);
-}
-
 void Notification::WaitForNotification() const {
   if (!HasBeenNotifiedInternal(&this->notified_yet_)) {
     this->mutex_.LockWhen(Condition(&HasBeenNotifiedInternal,
@@ -82,4 +74,5 @@
   return notified;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/synchronization/notification.h b/absl/synchronization/notification.h
index 82d111a..9a354ca 100644
--- a/absl/synchronization/notification.h
+++ b/absl/synchronization/notification.h
@@ -57,6 +57,7 @@
 #include "absl/time/time.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // -----------------------------------------------------------------------------
 // Notification
@@ -73,7 +74,9 @@
   // Notification::HasBeenNotified()
   //
   // Returns the value of the notification's internal "notified" state.
-  bool HasBeenNotified() const;
+  bool HasBeenNotified() const {
+    return HasBeenNotifiedInternal(&this->notified_yet_);
+  }
 
   // Notification::WaitForNotification()
   //
@@ -105,10 +108,16 @@
   void Notify();
 
  private:
+  static inline bool HasBeenNotifiedInternal(
+      const std::atomic<bool>* notified_yet) {
+    return notified_yet->load(std::memory_order_acquire);
+  }
+
   mutable Mutex mutex_;
   std::atomic<bool> notified_yet_;  // written under mutex_
 };
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_SYNCHRONIZATION_NOTIFICATION_H_
diff --git a/absl/synchronization/notification_test.cc b/absl/synchronization/notification_test.cc
index 059d4cd..100ea76 100644
--- a/absl/synchronization/notification_test.cc
+++ b/absl/synchronization/notification_test.cc
@@ -21,6 +21,7 @@
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // A thread-safe class that holds a counter.
 class ThreadSafeCounter {
@@ -128,4 +129,5 @@
   BasicTests(true, &local_notification2);
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/BUILD.bazel b/absl/time/BUILD.bazel
index a615152..3e25ca2 100644
--- a/absl/time/BUILD.bazel
+++ b/absl/time/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "time",
@@ -70,6 +70,7 @@
     ],
     deps = [
         ":time",
+        "//absl/base:config",
         "//absl/base:raw_logging_internal",
         "//absl/time/internal/cctz:time_zone",
         "@com_google_googletest//:gtest",
@@ -93,6 +94,7 @@
         ":time",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/numeric:int128",
         "//absl/time/internal/cctz:time_zone",
         "@com_google_googletest//:gtest_main",
     ],
@@ -117,6 +119,7 @@
         ":time",
         "//absl/base",
         "//absl/base:core_headers",
+        "//absl/flags:flag",
         "//absl/hash",
         "@com_github_google_benchmark//:benchmark_main",
     ],
diff --git a/absl/time/CMakeLists.txt b/absl/time/CMakeLists.txt
index 853563e..00bdd49 100644
--- a/absl/time/CMakeLists.txt
+++ b/absl/time/CMakeLists.txt
@@ -99,6 +99,7 @@
     ${ABSL_DEFAULT_COPTS}
   DEPS
     absl::time
+    absl::config
     absl::raw_logging_internal
     absl::time_zone
     gmock
diff --git a/absl/time/civil_time.cc b/absl/time/civil_time.cc
index 7527fc1..bdfe9ce 100644
--- a/absl/time/civil_time.cc
+++ b/absl/time/civil_time.cc
@@ -21,6 +21,7 @@
 #include "absl/time/time.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace {
 
@@ -37,26 +38,116 @@
   const CivilSecond ncs(NormalizeYear(cs.year()), cs.month(), cs.day(),
                         cs.hour(), cs.minute(), cs.second());
   const TimeZone utc = UTCTimeZone();
-  // TODO(absl-team): Avoid conversion of fmt std::string.
+  // TODO(absl-team): Avoid conversion of fmt string.
   return StrCat(cs.year(),
                 FormatTime(std::string(fmt), FromCivil(ncs, utc), utc));
 }
 
+template <typename CivilT>
+bool ParseYearAnd(string_view fmt, string_view s, CivilT* c) {
+  // Civil times support a larger year range than absl::Time, so we need to
+  // parse the year separately, normalize it, then use absl::ParseTime on the
+  // normalized string.
+  const std::string ss = std::string(s);  // TODO(absl-team): Avoid conversion.
+  const char* const np = ss.c_str();
+  char* endp;
+  errno = 0;
+  const civil_year_t y =
+      std::strtoll(np, &endp, 10);  // NOLINT(runtime/deprecated_fn)
+  if (endp == np || errno == ERANGE) return false;
+  const std::string norm = StrCat(NormalizeYear(y), endp);
+
+  const TimeZone utc = UTCTimeZone();
+  Time t;
+  if (ParseTime(StrCat("%Y", fmt), norm, utc, &t, nullptr)) {
+    const auto cs = ToCivilSecond(t, utc);
+    *c = CivilT(y, cs.month(), cs.day(), cs.hour(), cs.minute(), cs.second());
+    return true;
+  }
+
+  return false;
+}
+
+// Tries to parse the type as a CivilT1, but then assigns the result to the
+// argument of type CivilT2.
+template <typename CivilT1, typename CivilT2>
+bool ParseAs(string_view s, CivilT2* c) {
+  CivilT1 t1;
+  if (ParseCivilTime(s, &t1)) {
+    *c = CivilT2(t1);
+    return true;
+  }
+  return false;
+}
+
+template <typename CivilT>
+bool ParseLenient(string_view s, CivilT* c) {
+  // A fastpath for when the given string data parses exactly into the given
+  // type T (e.g., s="YYYY-MM-DD" and CivilT=CivilDay).
+  if (ParseCivilTime(s, c)) return true;
+  // Try parsing as each of the 6 types, trying the most common types first
+  // (based on csearch results).
+  if (ParseAs<CivilDay>(s, c)) return true;
+  if (ParseAs<CivilSecond>(s, c)) return true;
+  if (ParseAs<CivilHour>(s, c)) return true;
+  if (ParseAs<CivilMonth>(s, c)) return true;
+  if (ParseAs<CivilMinute>(s, c)) return true;
+  if (ParseAs<CivilYear>(s, c)) return true;
+  return false;
+}
 }  // namespace
 
 std::string FormatCivilTime(CivilSecond c) {
-  return FormatYearAnd("-%m-%dT%H:%M:%S", c);
+  return FormatYearAnd("-%m-%d%ET%H:%M:%S", c);
 }
 std::string FormatCivilTime(CivilMinute c) {
-  return FormatYearAnd("-%m-%dT%H:%M", c);
+  return FormatYearAnd("-%m-%d%ET%H:%M", c);
 }
 std::string FormatCivilTime(CivilHour c) {
-  return FormatYearAnd("-%m-%dT%H", c);
+  return FormatYearAnd("-%m-%d%ET%H", c);
 }
 std::string FormatCivilTime(CivilDay c) { return FormatYearAnd("-%m-%d", c); }
 std::string FormatCivilTime(CivilMonth c) { return FormatYearAnd("-%m", c); }
 std::string FormatCivilTime(CivilYear c) { return FormatYearAnd("", c); }
 
+bool ParseCivilTime(string_view s, CivilSecond* c) {
+  return ParseYearAnd("-%m-%d%ET%H:%M:%S", s, c);
+}
+bool ParseCivilTime(string_view s, CivilMinute* c) {
+  return ParseYearAnd("-%m-%d%ET%H:%M", s, c);
+}
+bool ParseCivilTime(string_view s, CivilHour* c) {
+  return ParseYearAnd("-%m-%d%ET%H", s, c);
+}
+bool ParseCivilTime(string_view s, CivilDay* c) {
+  return ParseYearAnd("-%m-%d", s, c);
+}
+bool ParseCivilTime(string_view s, CivilMonth* c) {
+  return ParseYearAnd("-%m", s, c);
+}
+bool ParseCivilTime(string_view s, CivilYear* c) {
+  return ParseYearAnd("", s, c);
+}
+
+bool ParseLenientCivilTime(string_view s, CivilSecond* c) {
+  return ParseLenient(s, c);
+}
+bool ParseLenientCivilTime(string_view s, CivilMinute* c) {
+  return ParseLenient(s, c);
+}
+bool ParseLenientCivilTime(string_view s, CivilHour* c) {
+  return ParseLenient(s, c);
+}
+bool ParseLenientCivilTime(string_view s, CivilDay* c) {
+  return ParseLenient(s, c);
+}
+bool ParseLenientCivilTime(string_view s, CivilMonth* c) {
+  return ParseLenient(s, c);
+}
+bool ParseLenientCivilTime(string_view s, CivilYear* c) {
+  return ParseLenient(s, c);
+}
+
 namespace time_internal {
 
 std::ostream& operator<<(std::ostream& os, CivilYear y) {
@@ -80,4 +171,5 @@
 
 }  // namespace time_internal
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/civil_time.h b/absl/time/civil_time.h
index beaf7d8..bb46004 100644
--- a/absl/time/civil_time.h
+++ b/absl/time/civil_time.h
@@ -76,6 +76,7 @@
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace time_internal {
 struct second_tag : cctz::detail::second_tag {};
@@ -247,7 +248,7 @@
 // int          minute()
 // int          second()
 //
-// Recall that fields inferior to the type's aligment will be set to their
+// Recall that fields inferior to the type's alignment will be set to their
 // minimum valid value.
 //
 // Example:
@@ -459,6 +460,57 @@
 std::string FormatCivilTime(CivilMonth c);
 std::string FormatCivilTime(CivilYear c);
 
+// absl::ParseCivilTime()
+//
+// Parses a civil-time value from the specified `absl::string_view` into the
+// passed output parameter. Returns `true` upon successful parsing.
+//
+// The expected form of the input string is as follows:
+//
+//  Type        | Format
+//  ---------------------------------
+//  CivilSecond | YYYY-MM-DDTHH:MM:SS
+//  CivilMinute | YYYY-MM-DDTHH:MM
+//  CivilHour   | YYYY-MM-DDTHH
+//  CivilDay    | YYYY-MM-DD
+//  CivilMonth  | YYYY-MM
+//  CivilYear   | YYYY
+//
+// Example:
+//
+//   absl::CivilDay d;
+//   bool ok = absl::ParseCivilTime("2018-01-02", &d); // OK
+//
+// Note that parsing will fail if the string's format does not match the
+// expected type exactly. `ParseLenientCivilTime()` below is more lenient.
+//
+bool ParseCivilTime(absl::string_view s, CivilSecond* c);
+bool ParseCivilTime(absl::string_view s, CivilMinute* c);
+bool ParseCivilTime(absl::string_view s, CivilHour* c);
+bool ParseCivilTime(absl::string_view s, CivilDay* c);
+bool ParseCivilTime(absl::string_view s, CivilMonth* c);
+bool ParseCivilTime(absl::string_view s, CivilYear* c);
+
+// ParseLenientCivilTime()
+//
+// Parses any of the formats accepted by `absl::ParseCivilTime()`, but is more
+// lenient if the format of the string does not exactly match the associated
+// type.
+//
+// Example:
+//
+//   absl::CivilDay d;
+//   bool ok = absl::ParseLenientCivilTime("1969-07-20", &d); // OK
+//   ok = absl::ParseLenientCivilTime("1969-07-20T10", &d);   // OK: T10 floored
+//   ok = absl::ParseLenientCivilTime("1969-07", &d);   // OK: day defaults to 1
+//
+bool ParseLenientCivilTime(absl::string_view s, CivilSecond* c);
+bool ParseLenientCivilTime(absl::string_view s, CivilMinute* c);
+bool ParseLenientCivilTime(absl::string_view s, CivilHour* c);
+bool ParseLenientCivilTime(absl::string_view s, CivilDay* c);
+bool ParseLenientCivilTime(absl::string_view s, CivilMonth* c);
+bool ParseLenientCivilTime(absl::string_view s, CivilYear* c);
+
 namespace time_internal {  // For functions found via ADL on civil-time tags.
 
 // Streaming Operators
@@ -468,7 +520,7 @@
 //
 // Example:
 //
-//   absl::CivilDay d = absl::CivilDay("1969-07-20");
+//   absl::CivilDay d = absl::CivilDay(1969, 7, 20);
 //   std::cout << "Date is: " << d << "\n";
 //
 std::ostream& operator<<(std::ostream& os, CivilYear y);
@@ -480,6 +532,7 @@
 
 }  // namespace time_internal
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_CIVIL_TIME_H_
diff --git a/absl/time/civil_time_benchmark.cc b/absl/time/civil_time_benchmark.cc
index 4086983..f04dbe2 100644
--- a/absl/time/civil_time_benchmark.cc
+++ b/absl/time/civil_time_benchmark.cc
@@ -66,6 +66,26 @@
 }
 BENCHMARK(BM_Format);
 
+void BM_Parse(benchmark::State& state) {
+  const std::string f = "2014-01-02T03:04:05";
+  absl::CivilSecond c;
+  while (state.KeepRunning()) {
+    const bool b = absl::ParseCivilTime(f, &c);
+    benchmark::DoNotOptimize(b);
+  }
+}
+BENCHMARK(BM_Parse);
+
+void BM_RoundTripFormatParse(benchmark::State& state) {
+  const absl::CivilSecond c(2014, 1, 2, 3, 4, 5);
+  absl::CivilSecond out;
+  while (state.KeepRunning()) {
+    const bool b = absl::ParseCivilTime(absl::FormatCivilTime(c), &out);
+    benchmark::DoNotOptimize(b);
+  }
+}
+BENCHMARK(BM_RoundTripFormatParse);
+
 template <typename T>
 void BM_CivilTimeAbslHash(benchmark::State& state) {
   const int kSize = 100000;
diff --git a/absl/time/civil_time_test.cc b/absl/time/civil_time_test.cc
index 03cd1f1..0ebd97a 100644
--- a/absl/time/civil_time_test.cc
+++ b/absl/time/civil_time_test.cc
@@ -690,6 +690,69 @@
   EXPECT_EQ("1970", absl::FormatCivilTime(y));
 }
 
+TEST(CivilTime, Parse) {
+  absl::CivilSecond ss;
+  absl::CivilMinute mm;
+  absl::CivilHour hh;
+  absl::CivilDay d;
+  absl::CivilMonth m;
+  absl::CivilYear y;
+
+  // CivilSecond OK; others fail
+  EXPECT_TRUE(absl::ParseCivilTime("2015-01-02T03:04:05", &ss));
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(ss));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &mm));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &hh));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &d));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &m));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &y));
+
+  // CivilMinute OK; others fail
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &ss));
+  EXPECT_TRUE(absl::ParseCivilTime("2015-01-02T03:04", &mm));
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(mm));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &hh));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &d));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &m));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &y));
+
+  // CivilHour OK; others fail
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &ss));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &mm));
+  EXPECT_TRUE(absl::ParseCivilTime("2015-01-02T03", &hh));
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hh));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &d));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &m));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &y));
+
+  // CivilDay OK; others fail
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &ss));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &mm));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &hh));
+  EXPECT_TRUE(absl::ParseCivilTime("2015-01-02", &d));
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(d));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &m));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &y));
+
+  // CivilMonth OK; others fail
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01", &ss));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01", &mm));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01", &hh));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01", &d));
+  EXPECT_TRUE(absl::ParseCivilTime("2015-01", &m));
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(m));
+  EXPECT_FALSE(absl::ParseCivilTime("2015-01", &y));
+
+  // CivilYear OK; others fail
+  EXPECT_FALSE(absl::ParseCivilTime("2015", &ss));
+  EXPECT_FALSE(absl::ParseCivilTime("2015", &mm));
+  EXPECT_FALSE(absl::ParseCivilTime("2015", &hh));
+  EXPECT_FALSE(absl::ParseCivilTime("2015", &d));
+  EXPECT_FALSE(absl::ParseCivilTime("2015", &m));
+  EXPECT_TRUE(absl::ParseCivilTime("2015", &y));
+  EXPECT_EQ("2015", absl::FormatCivilTime(y));
+}
+
 TEST(CivilTime, FormatAndParseLenient) {
   absl::CivilSecond ss;
   EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(ss));
@@ -708,6 +771,101 @@
 
   absl::CivilYear y;
   EXPECT_EQ("1970", absl::FormatCivilTime(y));
+
+  EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &ss));
+  EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(ss));
+
+  EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &mm));
+  EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(mm));
+
+  EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &hh));
+  EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hh));
+
+  EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &d));
+  EXPECT_EQ("2015-01-02", absl::FormatCivilTime(d));
+
+  EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &m));
+  EXPECT_EQ("2015-01", absl::FormatCivilTime(m));
+
+  EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &y));
+  EXPECT_EQ("2015", absl::FormatCivilTime(y));
+}
+
+TEST(CivilTime, ParseEdgeCases) {
+  absl::CivilSecond ss;
+  EXPECT_TRUE(
+      absl::ParseLenientCivilTime("9223372036854775807-12-31T23:59:59", &ss));
+  EXPECT_EQ("9223372036854775807-12-31T23:59:59", absl::FormatCivilTime(ss));
+  EXPECT_TRUE(
+      absl::ParseLenientCivilTime("-9223372036854775808-01-01T00:00:00", &ss));
+  EXPECT_EQ("-9223372036854775808-01-01T00:00:00", absl::FormatCivilTime(ss));
+
+  absl::CivilMinute mm;
+  EXPECT_TRUE(
+      absl::ParseLenientCivilTime("9223372036854775807-12-31T23:59", &mm));
+  EXPECT_EQ("9223372036854775807-12-31T23:59", absl::FormatCivilTime(mm));
+  EXPECT_TRUE(
+      absl::ParseLenientCivilTime("-9223372036854775808-01-01T00:00", &mm));
+  EXPECT_EQ("-9223372036854775808-01-01T00:00", absl::FormatCivilTime(mm));
+
+  absl::CivilHour hh;
+  EXPECT_TRUE(
+      absl::ParseLenientCivilTime("9223372036854775807-12-31T23", &hh));
+  EXPECT_EQ("9223372036854775807-12-31T23", absl::FormatCivilTime(hh));
+  EXPECT_TRUE(
+      absl::ParseLenientCivilTime("-9223372036854775808-01-01T00", &hh));
+  EXPECT_EQ("-9223372036854775808-01-01T00", absl::FormatCivilTime(hh));
+
+  absl::CivilDay d;
+  EXPECT_TRUE(absl::ParseLenientCivilTime("9223372036854775807-12-31", &d));
+  EXPECT_EQ("9223372036854775807-12-31", absl::FormatCivilTime(d));
+  EXPECT_TRUE(absl::ParseLenientCivilTime("-9223372036854775808-01-01", &d));
+  EXPECT_EQ("-9223372036854775808-01-01", absl::FormatCivilTime(d));
+
+  absl::CivilMonth m;
+  EXPECT_TRUE(absl::ParseLenientCivilTime("9223372036854775807-12", &m));
+  EXPECT_EQ("9223372036854775807-12", absl::FormatCivilTime(m));
+  EXPECT_TRUE(absl::ParseLenientCivilTime("-9223372036854775808-01", &m));
+  EXPECT_EQ("-9223372036854775808-01", absl::FormatCivilTime(m));
+
+  absl::CivilYear y;
+  EXPECT_TRUE(absl::ParseLenientCivilTime("9223372036854775807", &y));
+  EXPECT_EQ("9223372036854775807", absl::FormatCivilTime(y));
+  EXPECT_TRUE(absl::ParseLenientCivilTime("-9223372036854775808", &y));
+  EXPECT_EQ("-9223372036854775808", absl::FormatCivilTime(y));
+
+  // Tests some valid, but interesting, cases
+  EXPECT_TRUE(absl::ParseLenientCivilTime("0", &ss)) << ss;
+  EXPECT_EQ(absl::CivilYear(0), ss);
+  EXPECT_TRUE(absl::ParseLenientCivilTime("0-1", &ss)) << ss;
+  EXPECT_EQ(absl::CivilMonth(0, 1), ss);
+  EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015 ", &ss)) << ss;
+  EXPECT_EQ(absl::CivilYear(2015), ss);
+  EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015-6 ", &ss)) << ss;
+  EXPECT_EQ(absl::CivilMonth(2015, 6), ss);
+  EXPECT_TRUE(absl::ParseLenientCivilTime("2015-6-7", &ss)) << ss;
+  EXPECT_EQ(absl::CivilDay(2015, 6, 7), ss);
+  EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015-6-7 ", &ss)) << ss;
+  EXPECT_EQ(absl::CivilDay(2015, 6, 7), ss);
+  EXPECT_TRUE(absl::ParseLenientCivilTime("2015-06-07T10:11:12 ", &ss)) << ss;
+  EXPECT_EQ(absl::CivilSecond(2015, 6, 7, 10, 11, 12), ss);
+  EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015-06-07T10:11:12 ", &ss)) << ss;
+  EXPECT_EQ(absl::CivilSecond(2015, 6, 7, 10, 11, 12), ss);
+  EXPECT_TRUE(absl::ParseLenientCivilTime("-01-01", &ss)) << ss;
+  EXPECT_EQ(absl::CivilMonth(-1, 1), ss);
+
+  // Tests some invalid cases
+  EXPECT_FALSE(absl::ParseLenientCivilTime("01-01-2015", &ss)) << ss;
+  EXPECT_FALSE(absl::ParseLenientCivilTime("2015-", &ss)) << ss;
+  EXPECT_FALSE(absl::ParseLenientCivilTime("0xff-01", &ss)) << ss;
+  EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-30T04:05:06", &ss)) << ss;
+  EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-03T04:05:96", &ss)) << ss;
+  EXPECT_FALSE(absl::ParseLenientCivilTime("X2015-02-03T04:05:06", &ss)) << ss;
+  EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-03T04:05:003", &ss)) << ss;
+  EXPECT_FALSE(absl::ParseLenientCivilTime("2015 -02-03T04:05:06", &ss)) << ss;
+  EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-03-04:05:06", &ss)) << ss;
+  EXPECT_FALSE(absl::ParseLenientCivilTime("2015:02:03T04-05-06", &ss)) << ss;
+  EXPECT_FALSE(absl::ParseLenientCivilTime("9223372036854775808", &y)) << y;
 }
 
 TEST(CivilTime, OutputStream) {
diff --git a/absl/time/clock.cc b/absl/time/clock.cc
index fa0ed34..6862e01 100644
--- a/absl/time/clock.cc
+++ b/absl/time/clock.cc
@@ -34,6 +34,7 @@
 #include "absl/base/thread_annotations.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 Time Now() {
   // TODO(bww): Get a timespec instead so we don't have to divide.
   int64_t n = absl::GetCurrentTimeNanos();
@@ -43,6 +44,7 @@
   }
   return time_internal::FromUnixDuration(absl::Nanoseconds(n));
 }
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 // Decide if we should use the fast GetCurrentTimeNanos() algorithm
@@ -71,9 +73,9 @@
 
 #if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS
 namespace absl {
-int64_t GetCurrentTimeNanos() {
-  return GET_CURRENT_TIME_NANOS_FROM_SYSTEM();
-}
+ABSL_NAMESPACE_BEGIN
+int64_t GetCurrentTimeNanos() { return GET_CURRENT_TIME_NANOS_FROM_SYSTEM(); }
+ABSL_NAMESPACE_END
 }  // namespace absl
 #else  // Use the cyclecounter-based implementation below.
 
@@ -91,6 +93,7 @@
 static int64_t stats_fast_slow_paths;
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 // This is a friend wrapper around UnscaledCycleClock::Now()
 // (needed to access UnscaledCycleClock).
@@ -221,9 +224,9 @@
 
 // A reader-writer lock protecting the static locations below.
 // See SeqAcquire() and SeqRelease() above.
-static absl::base_internal::SpinLock lock(
-    absl::base_internal::kLinkerInitialized);
-static std::atomic<uint64_t> seq(0);
+ABSL_CONST_INIT static absl::base_internal::SpinLock lock(
+    absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
+ABSL_CONST_INIT static std::atomic<uint64_t> seq(0);
 
 // data from a sample of the kernel's time value
 struct TimeSampleAtomic {
@@ -385,7 +388,7 @@
 // TODO(absl-team): Remove this attribute when our compiler is smart enough
 // to do the right thing.
 ABSL_ATTRIBUTE_NOINLINE
-static int64_t GetCurrentTimeNanosSlowPath() LOCKS_EXCLUDED(lock) {
+static int64_t GetCurrentTimeNanosSlowPath() ABSL_LOCKS_EXCLUDED(lock) {
   // Serialize access to slow-path.  Fast-path readers are not blocked yet, and
   // code below must not modify last_sample until the seqlock is acquired.
   lock.Lock();
@@ -430,7 +433,7 @@
 static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns,
                                  uint64_t delta_cycles,
                                  const struct TimeSample *sample)
-    EXCLUSIVE_LOCKS_REQUIRED(lock) {
+    ABSL_EXCLUSIVE_LOCKS_REQUIRED(lock) {
   uint64_t estimated_base_ns = now_ns;
   uint64_t lock_value = SeqAcquire(&seq);  // acquire seqlock to block readers
 
@@ -449,7 +452,7 @@
     last_sample.min_cycles_per_sample.store(0, std::memory_order_relaxed);
     stats_initializations++;
   } else if (sample->raw_ns + 500 * 1000 * 1000 < now_ns &&
-             sample->base_cycles + 100 < now_cycles) {
+             sample->base_cycles + 50 < now_cycles) {
     // Enough time has passed to compute the cycle time.
     if (sample->nsscaled_per_cycle != 0) {  // Have a cycle time estimate.
       // Compute time from counter reading, but avoiding overflow
@@ -515,10 +518,12 @@
 
   return estimated_base_ns;
 }
+ABSL_NAMESPACE_END
 }  // namespace absl
 #endif  // ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 // Returns the maximum duration that SleepOnce() can sleep for.
@@ -546,6 +551,7 @@
 }
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 extern "C" {
diff --git a/absl/time/clock.h b/absl/time/clock.h
index bb52e4f..27764a9 100644
--- a/absl/time/clock.h
+++ b/absl/time/clock.h
@@ -26,6 +26,7 @@
 #include "absl/time/time.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // Now()
 //
@@ -49,6 +50,7 @@
 // * Returns immediately when passed a nonpositive duration.
 void SleepFor(absl::Duration duration);
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 // -----------------------------------------------------------------------------
diff --git a/absl/time/duration.cc b/absl/time/duration.cc
index a3ac61a..4443109 100644
--- a/absl/time/duration.cc
+++ b/absl/time/duration.cc
@@ -67,10 +67,14 @@
 #include <string>
 
 #include "absl/base/casts.h"
+#include "absl/base/macros.h"
 #include "absl/numeric/int128.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
 #include "absl/time/time.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace {
 
@@ -197,11 +201,11 @@
 // double as overflow cases.
 inline bool SafeAddRepHi(double a_hi, double b_hi, Duration* d) {
   double c = a_hi + b_hi;
-  if (c >= kint64max) {
+  if (c >= static_cast<double>(kint64max)) {
     *d = InfiniteDuration();
     return false;
   }
-  if (c <= kint64min) {
+  if (c <= static_cast<double>(kint64min)) {
     *d = -InfiniteDuration();
     return false;
   }
@@ -352,7 +356,7 @@
 // the remainder.  If it does not saturate, the remainder remain accurate,
 // but the returned quotient will over/underflow int64_t and should not be used.
 int64_t IDivDuration(bool satq, const Duration num, const Duration den,
-                   Duration* rem) {
+                     Duration* rem) {
   int64_t q = 0;
   if (IDivFastPath(num, den, &q, rem)) {
     return q;
@@ -707,16 +711,17 @@
 // fractional digits, because it is in the noise of what a Duration can
 // represent.
 struct DisplayUnit {
-  const char* abbr;
+  absl::string_view abbr;
   int prec;
   double pow10;
 };
-const DisplayUnit kDisplayNano = {"ns", 2, 1e2};
-const DisplayUnit kDisplayMicro = {"us", 5, 1e5};
-const DisplayUnit kDisplayMilli = {"ms", 8, 1e8};
-const DisplayUnit kDisplaySec = {"s", 11, 1e11};
-const DisplayUnit kDisplayMin = {"m", -1, 0.0};   // prec ignored
-const DisplayUnit kDisplayHour = {"h", -1, 0.0};  // prec ignored
+ABSL_CONST_INIT const DisplayUnit kDisplayNano = {"ns", 2, 1e2};
+ABSL_CONST_INIT const DisplayUnit kDisplayMicro = {"us", 5, 1e5};
+ABSL_CONST_INIT const DisplayUnit kDisplayMilli = {"ms", 8, 1e8};
+ABSL_CONST_INIT const DisplayUnit kDisplaySec = {"s", 11, 1e11};
+ABSL_CONST_INIT const DisplayUnit kDisplayMin = {"m", -1, 0.0};  // prec ignored
+ABSL_CONST_INIT const DisplayUnit kDisplayHour = {"h", -1,
+                                                  0.0};  // prec ignored
 
 void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) {
   char buf[sizeof("2562047788015216")];  // hours in max duration
@@ -724,16 +729,16 @@
   char* bp = Format64(ep, 0, n);
   if (*bp != '0' || bp + 1 != ep) {
     out->append(bp, ep - bp);
-    out->append(unit.abbr);
+    out->append(unit.abbr.data(), unit.abbr.size());
   }
 }
 
 // Note: unit.prec is limited to double's digits10 value (typically 15) so it
 // always fits in buf[].
 void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) {
-  const int buf_size = std::numeric_limits<double>::digits10;
-  const int prec = std::min(buf_size, unit.prec);
-  char buf[buf_size];  // also large enough to hold integer part
+  constexpr int kBufferSize = std::numeric_limits<double>::digits10;
+  const int prec = std::min(kBufferSize, unit.prec);
+  char buf[kBufferSize];  // also large enough to hold integer part
   char* ep = buf + sizeof(buf);
   double d = 0;
   int64_t frac_part = Round(std::modf(n, &d) * unit.pow10);
@@ -747,7 +752,7 @@
       while (ep[-1] == '0') --ep;
       out->append(bp, ep - bp);
     }
-    out->append(unit.abbr);
+    out->append(unit.abbr.data(), unit.abbr.size());
   }
 }
 
@@ -758,7 +763,8 @@
 //   form "72h3m0.5s". Leading zero units are omitted.  As a special
 //   case, durations less than one second format use a smaller unit
 //   (milli-, micro-, or nanoseconds) to ensure that the leading digit
-//   is non-zero.  The zero duration formats as 0, with no unit.
+//   is non-zero.
+// Unlike Go, we format the zero duration as 0, with no unit.
 std::string FormatDuration(Duration d) {
   const Duration min_duration = Seconds(kint64min);
   if (d == min_duration) {
@@ -799,23 +805,27 @@
 // A helper for ParseDuration() that parses a leading number from the given
 // string and stores the result in *int_part/*frac_part/*frac_scale.  The
 // given string pointer is modified to point to the first unconsumed char.
-bool ConsumeDurationNumber(const char** dpp, int64_t* int_part,
+bool ConsumeDurationNumber(const char** dpp, const char* ep, int64_t* int_part,
                            int64_t* frac_part, int64_t* frac_scale) {
   *int_part = 0;
   *frac_part = 0;
   *frac_scale = 1;  // invariant: *frac_part < *frac_scale
   const char* start = *dpp;
-  for (; std::isdigit(**dpp); *dpp += 1) {
+  for (; *dpp != ep; *dpp += 1) {
     const int d = **dpp - '0';  // contiguous digits
+    if (d < 0 || 10 <= d) break;
+
     if (*int_part > kint64max / 10) return false;
     *int_part *= 10;
     if (*int_part > kint64max - d) return false;
     *int_part += d;
   }
   const bool int_part_empty = (*dpp == start);
-  if (**dpp != '.') return !int_part_empty;
-  for (*dpp += 1; std::isdigit(**dpp); *dpp += 1) {
+  if (*dpp == ep || **dpp != '.') return !int_part_empty;
+
+  for (*dpp += 1; *dpp != ep; *dpp += 1) {
     const int d = **dpp - '0';  // contiguous digits
+    if (d < 0 || 10 <= d) break;
     if (*frac_scale <= kint64max / 10) {
       *frac_part *= 10;
       *frac_part += d;
@@ -829,32 +839,56 @@
 // ns, us, ms, s, m, h) from the given string and stores the resulting unit
 // in "*unit".  The given string pointer is modified to point to the first
 // unconsumed char.
-bool ConsumeDurationUnit(const char** start, Duration* unit) {
-  const char *s = *start;
-  bool ok = true;
-  if (strncmp(s, "ns", 2) == 0) {
-    s += 2;
-    *unit = Nanoseconds(1);
-  } else if (strncmp(s, "us", 2) == 0) {
-    s += 2;
-    *unit = Microseconds(1);
-  } else if (strncmp(s, "ms", 2) == 0) {
-    s += 2;
-    *unit = Milliseconds(1);
-  } else if (strncmp(s, "s", 1) == 0) {
-    s += 1;
-    *unit = Seconds(1);
-  } else if (strncmp(s, "m", 1) == 0) {
-    s += 1;
-    *unit = Minutes(1);
-  } else if (strncmp(s, "h", 1) == 0) {
-    s += 1;
-    *unit = Hours(1);
-  } else {
-    ok = false;
+bool ConsumeDurationUnit(const char** start, const char* end, Duration* unit) {
+  size_t size = end - *start;
+  switch (size) {
+    case 0:
+      return false;
+    default:
+      switch (**start) {
+        case 'n':
+          if (*(*start + 1) == 's') {
+            *start += 2;
+            *unit = Nanoseconds(1);
+            return true;
+          }
+          break;
+        case 'u':
+          if (*(*start + 1) == 's') {
+            *start += 2;
+            *unit = Microseconds(1);
+            return true;
+          }
+          break;
+        case 'm':
+          if (*(*start + 1) == 's') {
+            *start += 2;
+            *unit = Milliseconds(1);
+            return true;
+          }
+          break;
+        default:
+          break;
+      }
+      ABSL_FALLTHROUGH_INTENDED;
+    case 1:
+      switch (**start) {
+        case 's':
+          *unit = Seconds(1);
+          *start += 1;
+          return true;
+        case 'm':
+          *unit = Minutes(1);
+          *start += 1;
+          return true;
+        case 'h':
+          *unit = Hours(1);
+          *start += 1;
+          return true;
+        default:
+          return false;
+      }
   }
-  *start = s;
-  return ok;
 }
 
 }  // namespace
@@ -864,39 +898,38 @@
 //   a possibly signed sequence of decimal numbers, each with optional
 //   fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".
 //   Valid time units are "ns", "us" "ms", "s", "m", "h".
-bool ParseDuration(const std::string& dur_string, Duration* d) {
-  const char* start = dur_string.c_str();
+bool ParseDuration(absl::string_view dur_sv, Duration* d) {
   int sign = 1;
-
-  if (*start == '-' || *start == '+') {
-    sign = *start == '-' ? -1 : 1;
-    ++start;
+  if (absl::ConsumePrefix(&dur_sv, "-")) {
+    sign = -1;
+  } else {
+    absl::ConsumePrefix(&dur_sv, "+");
   }
+  if (dur_sv.empty()) return false;
 
-  // Can't parse a duration from an empty std::string.
-  if (*start == '\0') {
-    return false;
-  }
-
-  // Special case for a std::string of "0".
-  if (*start == '0' && *(start + 1) == '\0') {
+  // Special case for a string of "0".
+  if (dur_sv == "0") {
     *d = ZeroDuration();
     return true;
   }
 
-  if (strcmp(start, "inf") == 0) {
+  if (dur_sv == "inf") {
     *d = sign * InfiniteDuration();
     return true;
   }
 
+  const char* start = dur_sv.data();
+  const char* end = start + dur_sv.size();
+
   Duration dur;
-  while (*start != '\0') {
+  while (start != end) {
     int64_t int_part;
     int64_t frac_part;
     int64_t frac_scale;
     Duration unit;
-    if (!ConsumeDurationNumber(&start, &int_part, &frac_part, &frac_scale) ||
-        !ConsumeDurationUnit(&start, &unit)) {
+    if (!ConsumeDurationNumber(&start, end, &int_part, &frac_part,
+                               &frac_scale) ||
+        !ConsumeDurationUnit(&start, end, &unit)) {
       return false;
     }
     if (int_part != 0) dur += sign * int_part * unit;
@@ -906,10 +939,16 @@
   return true;
 }
 
+bool AbslParseFlag(absl::string_view text, Duration* dst, std::string*) {
+  return ParseDuration(text, dst);
+}
+
+std::string AbslUnparseFlag(Duration d) { return FormatDuration(d); }
 bool ParseFlag(const std::string& text, Duration* dst, std::string* ) {
   return ParseDuration(text, dst);
 }
 
 std::string UnparseFlag(Duration d) { return FormatDuration(d); }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/duration_benchmark.cc b/absl/time/duration_benchmark.cc
index 83a836c..56820f3 100644
--- a/absl/time/duration_benchmark.cc
+++ b/absl/time/duration_benchmark.cc
@@ -18,9 +18,14 @@
 #include <string>
 
 #include "absl/base/attributes.h"
+#include "absl/flags/flag.h"
 #include "absl/time/time.h"
 #include "benchmark/benchmark.h"
 
+ABSL_FLAG(absl::Duration, absl_duration_flag_for_benchmark,
+          absl::Milliseconds(1),
+          "Flag to use for benchmarking duration flag access speed.");
+
 namespace {
 
 //
@@ -425,4 +430,15 @@
 }
 BENCHMARK(BM_Duration_ParseDuration)->DenseRange(0, kNumDurations - 1);
 
+//
+// Flag access
+//
+void BM_Duration_GetFlag(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(
+        absl::GetFlag(FLAGS_absl_duration_flag_for_benchmark));
+  }
+}
+BENCHMARK(BM_Duration_GetFlag);
+
 }  // namespace
diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc
index 5dce9ac..4d85a2c 100644
--- a/absl/time/duration_test.cc
+++ b/absl/time/duration_test.cc
@@ -762,11 +762,6 @@
   const double dbl_inf = std::numeric_limits<double>::infinity();
   const double dbl_denorm = std::numeric_limits<double>::denorm_min();
 
-  // IEEE 754 behavior
-  double z = 0.0, two = 2.0;
-  EXPECT_TRUE(std::isinf(two / z));
-  EXPECT_TRUE(std::isnan(z / z));  // We'll return inf
-
   // Operator/(Duration, double)
   EXPECT_EQ(inf, zero / 0.0);
   EXPECT_EQ(-inf, zero / -0.0);
@@ -1050,7 +1045,7 @@
   EXPECT_EQ(absl::Seconds(666666666) + absl::Nanoseconds(666666667) +
                 absl::Nanoseconds(1) / 2,
             sigfigs / 3);
-  sigfigs = absl::Seconds(7000000000LL);
+  sigfigs = absl::Seconds(int64_t{7000000000});
   EXPECT_EQ(absl::Seconds(2333333333) + absl::Nanoseconds(333333333) +
                 absl::Nanoseconds(1) / 4,
             sigfigs / 3);
diff --git a/absl/time/format.cc b/absl/time/format.cc
index d6ca860..4005fb7 100644
--- a/absl/time/format.cc
+++ b/absl/time/format.cc
@@ -13,21 +13,25 @@
 // limitations under the License.
 
 #include <string.h>
+
 #include <cctype>
 #include <cstdint>
 
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 #include "absl/time/time.h"
 
 namespace cctz = absl::time_internal::cctz;
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
-extern const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
-extern const char RFC3339_sec[] =  "%Y-%m-%dT%H:%M:%S%Ez";
+ABSL_DLL extern const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez";
+ABSL_DLL extern const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
 
-extern const char RFC1123_full[] = "%a, %d %b %E4Y %H:%M:%S %z";
-extern const char RFC1123_no_wday[] =  "%d %b %E4Y %H:%M:%S %z";
+ABSL_DLL extern const char RFC1123_full[] = "%a, %d %b %E4Y %H:%M:%S %z";
+ABSL_DLL extern const char RFC1123_no_wday[] = "%d %b %E4Y %H:%M:%S %z";
 
 namespace {
 
@@ -67,12 +71,12 @@
 
 }  // namespace
 
-std::string FormatTime(const std::string& format, absl::Time t,
+std::string FormatTime(absl::string_view format, absl::Time t,
                        absl::TimeZone tz) {
-  if (t == absl::InfiniteFuture()) return kInfiniteFutureStr;
-  if (t == absl::InfinitePast()) return kInfinitePastStr;
+  if (t == absl::InfiniteFuture()) return std::string(kInfiniteFutureStr);
+  if (t == absl::InfinitePast()) return std::string(kInfinitePastStr);
   const auto parts = Split(t);
-  return cctz::detail::format(format, parts.sec, parts.fem,
+  return cctz::detail::format(std::string(format), parts.sec, parts.fem,
                               cctz::time_zone(tz));
 }
 
@@ -84,42 +88,50 @@
   return absl::FormatTime(RFC3339_full, t, absl::LocalTimeZone());
 }
 
-bool ParseTime(const std::string& format, const std::string& input,
+bool ParseTime(absl::string_view format, absl::string_view input,
                absl::Time* time, std::string* err) {
   return absl::ParseTime(format, input, absl::UTCTimeZone(), time, err);
 }
 
 // If the input string does not contain an explicit UTC offset, interpret
 // the fields with respect to the given TimeZone.
-bool ParseTime(const std::string& format, const std::string& input,
+bool ParseTime(absl::string_view format, absl::string_view input,
                absl::TimeZone tz, absl::Time* time, std::string* err) {
-  const char* data = input.c_str();
-  while (std::isspace(*data)) ++data;
-
-  size_t inf_size = strlen(kInfiniteFutureStr);
-  if (strncmp(data, kInfiniteFutureStr, inf_size) == 0) {
-    const char* new_data = data + inf_size;
-    while (std::isspace(*new_data)) ++new_data;
-    if (*new_data == '\0') {
-      *time = InfiniteFuture();
-      return true;
+  auto strip_leading_space = [](absl::string_view* sv) {
+    while (!sv->empty()) {
+      if (!std::isspace(sv->front())) return;
+      sv->remove_prefix(1);
     }
-  }
+  };
 
-  inf_size = strlen(kInfinitePastStr);
-  if (strncmp(data, kInfinitePastStr, inf_size) == 0) {
-    const char* new_data = data + inf_size;
-    while (std::isspace(*new_data)) ++new_data;
-    if (*new_data == '\0') {
-      *time = InfinitePast();
-      return true;
+  // Portable toolchains means we don't get nice constexpr here.
+  struct Literal {
+    const char* name;
+    size_t size;
+    absl::Time value;
+  };
+  static Literal literals[] = {
+      {kInfiniteFutureStr, strlen(kInfiniteFutureStr), InfiniteFuture()},
+      {kInfinitePastStr, strlen(kInfinitePastStr), InfinitePast()},
+  };
+  strip_leading_space(&input);
+  for (const auto& lit : literals) {
+    if (absl::StartsWith(input, absl::string_view(lit.name, lit.size))) {
+      absl::string_view tail = input;
+      tail.remove_prefix(lit.size);
+      strip_leading_space(&tail);
+      if (tail.empty()) {
+        *time = lit.value;
+        return true;
+      }
     }
   }
 
   std::string error;
   cctz_parts parts;
-  const bool b = cctz::detail::parse(format, input, cctz::time_zone(tz),
-                                     &parts.sec, &parts.fem, &error);
+  const bool b =
+      cctz::detail::parse(std::string(format), std::string(input),
+                          cctz::time_zone(tz), &parts.sec, &parts.fem, &error);
   if (b) {
     *time = Join(parts);
   } else if (err != nullptr) {
@@ -129,6 +141,13 @@
 }
 
 // Functions required to support absl::Time flags.
+bool AbslParseFlag(absl::string_view text, absl::Time* t, std::string* error) {
+  return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error);
+}
+
+std::string AbslUnparseFlag(absl::Time t) {
+  return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone());
+}
 bool ParseFlag(const std::string& text, absl::Time* t, std::string* error) {
   return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error);
 }
@@ -137,4 +156,5 @@
   return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone());
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/format_benchmark.cc b/absl/time/format_benchmark.cc
index 249c51d..19e481d 100644
--- a/absl/time/format_benchmark.cc
+++ b/absl/time/format_benchmark.cc
@@ -26,7 +26,7 @@
     absl::RFC1123_no_wday,  // 1
     absl::RFC3339_full,     // 2
     absl::RFC3339_sec,      // 3
-    "%Y-%m-%dT%H:%M:%S",    // 4
+    "%Y-%m-%d%ET%H:%M:%S",  // 4
     "%Y-%m-%d",             // 5
 };
 const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
diff --git a/absl/time/format_test.cc b/absl/time/format_test.cc
index ab1f305..a9a1eb8 100644
--- a/absl/time/format_test.cc
+++ b/absl/time/format_test.cc
@@ -173,7 +173,7 @@
   absl::Time t;
   std::string e;
 
-  // We can parse a std::string without a UTC offset if we supply a timezone.
+  // We can parse a string without a UTC offset if we supply a timezone.
   EXPECT_TRUE(
       absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e))
       << e;
@@ -327,7 +327,7 @@
   EXPECT_TRUE(absl::ParseTime("%H:%M blah", "  infinite-past  ", &t, &err));
   EXPECT_EQ(absl::InfinitePast(), t);
 
-  // "infinite-future" as literal std::string
+  // "infinite-future" as literal string
   absl::TimeZone tz = absl::UTCTimeZone();
   EXPECT_TRUE(absl::ParseTime("infinite-future %H:%M", "infinite-future 03:04",
                               &t, &err));
@@ -335,7 +335,7 @@
   EXPECT_EQ(3, tz.At(t).cs.hour());
   EXPECT_EQ(4, tz.At(t).cs.minute());
 
-  // "infinite-past" as literal std::string
+  // "infinite-past" as literal string
   EXPECT_TRUE(
       absl::ParseTime("infinite-past %H:%M", "infinite-past 03:04", &t, &err));
   EXPECT_NE(absl::InfinitePast(), t);
diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel
index 9fceffe..45a9529 100644
--- a/absl/time/internal/cctz/BUILD.bazel
+++ b/absl/time/internal/cctz/BUILD.bazel
@@ -16,7 +16,12 @@
 
 package(features = ["-parse_headers"])
 
-licenses(["notice"])  # Apache License
+licenses(["notice"])
+
+filegroup(
+    name = "zoneinfo",
+    srcs = glob(["testdata/zoneinfo/**"]),
+)
 
 config_setting(
     name = "osx",
@@ -42,6 +47,7 @@
     ],
     textual_hdrs = ["include/cctz/civil_time_detail.h"],
     visibility = ["//visibility:public"],
+    deps = ["//absl/base:config"],
 )
 
 cc_library(
@@ -78,17 +84,26 @@
         "//conditions:default": [],
     }),
     visibility = ["//visibility:public"],
-    deps = [":civil_time"],
+    deps = [
+        ":civil_time",
+        "//absl/base:config",
+    ],
 )
 
 ### tests
 
+test_suite(
+    name = "all_tests",
+    visibility = ["//visibility:public"],
+)
+
 cc_test(
     name = "civil_time_test",
     size = "small",
     srcs = ["src/civil_time_test.cc"],
     deps = [
         ":civil_time",
+        "//absl/base:config",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -106,6 +121,7 @@
     deps = [
         ":civil_time",
         ":time_zone",
+        "//absl/base:config",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -124,6 +140,7 @@
     deps = [
         ":civil_time",
         ":time_zone",
+        "//absl/base:config",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -144,6 +161,7 @@
     deps = [
         ":civil_time",
         ":time_zone",
+        "//absl/base:config",
         "@com_github_google_benchmark//:benchmark_main",
     ],
 )
@@ -151,8 +169,3 @@
 ### examples
 
 ### binaries
-
-filegroup(
-    name = "zoneinfo",
-    srcs = glob(["testdata/zoneinfo/**"]),
-)
diff --git a/absl/time/internal/cctz/include/cctz/civil_time.h b/absl/time/internal/cctz/include/cctz/civil_time.h
index 85d0d3f..d47ff86 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time.h
@@ -15,9 +15,11 @@
 #ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_
 #define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_
 
+#include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/civil_time_detail.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -150,7 +152,7 @@
 //
 // All civil-time types have accessors for all six of the civil-time fields:
 // year, month, day, hour, minute, and second. Recall that fields inferior to
-// the type's aligment will be set to their minimum valid value.
+// the type's alignment will be set to their minimum valid value.
 //
 //   civil_day d(2015, 6, 28);
 //   // d.year() == 2015
@@ -324,6 +326,7 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_
diff --git a/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
index 433078a..8aadde5 100644
--- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h
+++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h
@@ -20,6 +20,8 @@
 #include <ostream>
 #include <type_traits>
 
+#include "absl/base/config.h"
+
 // Disable constexpr support unless we are in C++14 mode.
 #if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910)
 #define CONSTEXPR_D constexpr  // data
@@ -32,6 +34,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -53,8 +56,8 @@
 
 // Normalized civil-time fields: Y-M-D HH:MM:SS.
 struct fields {
-  CONSTEXPR_M fields(year_t year, month_t month, day_t day,
-                     hour_t hour, minute_t minute, second_t second)
+  CONSTEXPR_M fields(year_t year, month_t month, day_t day, hour_t hour,
+                     minute_t minute, second_t second)
       : y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {}
   std::int_least64_t y;
   std::int_least8_t m;
@@ -101,59 +104,69 @@
   return k_days_per_month[m] + (m == 2 && is_leap_year(y));
 }
 
-CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd,
-                         hour_t hh, minute_t mm, second_t ss) noexcept {
-  y += (cd / 146097) * 400;
+CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd, hour_t hh,
+                         minute_t mm, second_t ss) noexcept {
+  year_t ey = y % 400;
+  const year_t oey = ey;
+  ey += (cd / 146097) * 400;
   cd %= 146097;
   if (cd < 0) {
-    y -= 400;
+    ey -= 400;
     cd += 146097;
   }
-  y += (d / 146097) * 400;
+  ey += (d / 146097) * 400;
   d = d % 146097 + cd;
   if (d > 0) {
     if (d > 146097) {
-      y += 400;
+      ey += 400;
       d -= 146097;
     }
   } else {
     if (d > -365) {
       // We often hit the previous year when stepping a civil time backwards,
       // so special case it to avoid counting up by 100/4/1-year chunks.
-      y -= 1;
-      d += days_per_year(y, m);
+      ey -= 1;
+      d += days_per_year(ey, m);
     } else {
-      y -= 400;
+      ey -= 400;
       d += 146097;
     }
   }
   if (d > 365) {
-    for (int n = days_per_century(y, m); d > n; n = days_per_century(y, m)) {
+    for (;;) {
+      int n = days_per_century(ey, m);
+      if (d <= n) break;
       d -= n;
-      y += 100;
+      ey += 100;
     }
-    for (int n = days_per_4years(y, m); d > n; n = days_per_4years(y, m)) {
+    for (;;) {
+      int n = days_per_4years(ey, m);
+      if (d <= n) break;
       d -= n;
-      y += 4;
+      ey += 4;
     }
-    for (int n = days_per_year(y, m); d > n; n = days_per_year(y, m)) {
+    for (;;) {
+      int n = days_per_year(ey, m);
+      if (d <= n) break;
       d -= n;
-      ++y;
+      ++ey;
     }
   }
   if (d > 28) {
-    for (int n = days_per_month(y, m); d > n; n = days_per_month(y, m)) {
+    for (;;) {
+      int n = days_per_month(ey, m);
+      if (d <= n) break;
       d -= n;
       if (++m > 12) {
-        ++y;
+        ++ey;
         m = 1;
       }
     }
   }
-  return fields(y, m, static_cast<day_t>(d), hh, mm, ss);
+  return fields(y + (ey - oey), m, static_cast<day_t>(d), hh, mm, ss);
 }
-CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd,
-                         hour_t hh, minute_t mm, second_t ss) noexcept {
+CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, hour_t hh,
+                         minute_t mm, second_t ss) noexcept {
   if (m != 12) {
     y += m / 12;
     m %= 12;
@@ -164,8 +177,8 @@
   }
   return n_day(y, static_cast<month_t>(m), d, cd, hh, mm, ss);
 }
-CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd,
-                          diff_t hh, minute_t mm, second_t ss) noexcept {
+CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd, diff_t hh,
+                          minute_t mm, second_t ss) noexcept {
   cd += hh / 24;
   hh %= 24;
   if (hh < 0) {
@@ -264,8 +277,8 @@
 // yet the difference between two such extreme values may actually be
 // small, so we take a little care to avoid overflow when possible by
 // exploiting the 146097-day cycle.
-CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1,
-                                  year_t y2, month_t m2, day_t d2) noexcept {
+CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1, year_t y2,
+                                  month_t m2, day_t d2) noexcept {
   const diff_t a_c4_off = y1 % 400;
   const diff_t b_c4_off = y2 % 400;
   diff_t c4_diff = (y1 - a_c4_off) - (y2 - b_c4_off);
@@ -305,9 +318,7 @@
 ////////////////////////////////////////////////////////////////////////
 
 // Aligns the (normalized) fields struct to the indicated field.
-CONSTEXPR_F fields align(second_tag, fields f) noexcept {
-  return f;
-}
+CONSTEXPR_F fields align(second_tag, fields f) noexcept { return f; }
 CONSTEXPR_F fields align(minute_tag, fields f) noexcept {
   return fields{f.y, f.m, f.d, f.hh, f.mm, 0};
 }
@@ -386,11 +397,11 @@
       : civil_time(ct.f_) {}
 
   // Factories for the maximum/minimum representable civil_time.
-  static CONSTEXPR_F civil_time (max)() {
+  static CONSTEXPR_F civil_time(max)() {
     const auto max_year = (std::numeric_limits<std::int_least64_t>::max)();
     return civil_time(max_year, 12, 31, 23, 59, 59);
   }
-  static CONSTEXPR_F civil_time (min)() {
+  static CONSTEXPR_F civil_time(min)() {
     const auto min_year = (std::numeric_limits<std::int_least64_t>::min)();
     return civil_time(min_year, 1, 1, 0, 0, 0);
   }
@@ -405,28 +416,18 @@
 
   // Assigning arithmetic.
   CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept {
-    f_ = step(T{}, f_, n);
-    return *this;
+    return *this = *this + n;
   }
   CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {
-    if (n != (std::numeric_limits<diff_t>::min)()) {
-      f_ = step(T{}, f_, -n);
-    } else {
-      f_ = step(T{}, step(T{}, f_, -(n + 1)), 1);
-    }
-    return *this;
+    return *this = *this - n;
   }
-  CONSTEXPR_M civil_time& operator++() noexcept {
-    return *this += 1;
-  }
+  CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; }
   CONSTEXPR_M civil_time operator++(int) noexcept {
     const civil_time a = *this;
     ++*this;
     return a;
   }
-  CONSTEXPR_M civil_time& operator--() noexcept {
-    return *this -= 1;
-  }
+  CONSTEXPR_M civil_time& operator--() noexcept { return *this -= 1; }
   CONSTEXPR_M civil_time operator--(int) noexcept {
     const civil_time a = *this;
     --*this;
@@ -435,13 +436,15 @@
 
   // Binary arithmetic operators.
   friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept {
-    return a += n;
+    return civil_time(step(T{}, a.f_, n));
   }
   friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept {
-    return a += n;
+    return a + n;
   }
   friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept {
-    return a -= n;
+    return n != (std::numeric_limits<diff_t>::min)()
+               ? civil_time(step(T{}, a.f_, -n))
+               : civil_time(step(T{}, step(T{}, a.f_, -(n + 1)), 1));
   }
   friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept {
     return difference(T{}, lhs.f_, rhs.f_);
@@ -483,17 +486,17 @@
 template <typename T1, typename T2>
 CONSTEXPR_F bool operator<(const civil_time<T1>& lhs,
                            const civil_time<T2>& rhs) noexcept {
-  return (lhs.year() < rhs.year() ||
-          (lhs.year() == rhs.year() &&
-           (lhs.month() < rhs.month() ||
-            (lhs.month() == rhs.month() &&
-             (lhs.day() < rhs.day() ||
-              (lhs.day() == rhs.day() &&
-               (lhs.hour() < rhs.hour() ||
-                (lhs.hour() == rhs.hour() &&
-                 (lhs.minute() < rhs.minute() ||
-                  (lhs.minute() == rhs.minute() &&
-                   (lhs.second() < rhs.second())))))))))));
+  return (
+      lhs.year() < rhs.year() ||
+      (lhs.year() == rhs.year() &&
+       (lhs.month() < rhs.month() ||
+        (lhs.month() == rhs.month() &&
+         (lhs.day() < rhs.day() || (lhs.day() == rhs.day() &&
+                                    (lhs.hour() < rhs.hour() ||
+                                     (lhs.hour() == rhs.hour() &&
+                                      (lhs.minute() < rhs.minute() ||
+                                       (lhs.minute() == rhs.minute() &&
+                                        (lhs.second() < rhs.second())))))))))));
 }
 template <typename T1, typename T2>
 CONSTEXPR_F bool operator<=(const civil_time<T1>& lhs,
@@ -615,6 +618,7 @@
 }  // namespace detail
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #undef CONSTEXPR_M
diff --git a/absl/time/internal/cctz/include/cctz/time_zone.h b/absl/time/internal/cctz/include/cctz/time_zone.h
index ef6c4ba..5562a37 100644
--- a/absl/time/internal/cctz/include/cctz/time_zone.h
+++ b/absl/time/internal/cctz/include/cctz/time_zone.h
@@ -25,9 +25,11 @@
 #include <string>
 #include <utility>
 
+#include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -39,8 +41,8 @@
 
 namespace detail {
 template <typename D>
-inline std::pair<time_point<seconds>, D>
-split_seconds(const time_point<D>& tp) {
+inline std::pair<time_point<seconds>, D> split_seconds(
+    const time_point<D>& tp) {
   auto sec = std::chrono::time_point_cast<seconds>(tp);
   auto sub = tp - sec;
   if (sub.count() < 0) {
@@ -49,8 +51,8 @@
   }
   return {sec, std::chrono::duration_cast<D>(sub)};
 }
-inline std::pair<time_point<seconds>, seconds>
-split_seconds(const time_point<seconds>& tp) {
+inline std::pair<time_point<seconds>, seconds> split_seconds(
+    const time_point<seconds>& tp) {
   return {tp, seconds::zero()};
 }
 }  // namespace detail
@@ -194,22 +196,20 @@
   bool next_transition(const time_point<seconds>& tp,
                        civil_transition* trans) const;
   template <typename D>
-  bool next_transition(const time_point<D>& tp,
-                       civil_transition* trans) const {
+  bool next_transition(const time_point<D>& tp, civil_transition* trans) const {
     return next_transition(detail::split_seconds(tp).first, trans);
   }
   bool prev_transition(const time_point<seconds>& tp,
                        civil_transition* trans) const;
   template <typename D>
-  bool prev_transition(const time_point<D>& tp,
-                       civil_transition* trans) const {
+  bool prev_transition(const time_point<D>& tp, civil_transition* trans) const {
     return prev_transition(detail::split_seconds(tp).first, trans);
   }
 
   // version() and description() provide additional information about the
   // time zone. The content of each of the returned strings is unspecified,
   // however, when the IANA Time Zone Database is the underlying data source
-  // the version() std::string will be in the familar form (e.g, "2018e") or
+  // the version() string will be in the familar form (e.g, "2018e") or
   // empty when unavailable.
   //
   // Note: These functions are for informational or testing purposes only.
@@ -220,9 +220,7 @@
   friend bool operator==(time_zone lhs, time_zone rhs) {
     return &lhs.effective_impl() == &rhs.effective_impl();
   }
-  friend bool operator!=(time_zone lhs, time_zone rhs) {
-    return !(lhs == rhs);
-  }
+  friend bool operator!=(time_zone lhs, time_zone rhs) { return !(lhs == rhs); }
 
   template <typename H>
   friend H AbslHashValue(H h, time_zone tz) {
@@ -294,6 +292,7 @@
 //   - %E#f - Fractional seconds with # digits of precision
 //   - %E*f - Fractional seconds with full precision (a literal '*')
 //   - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
+//   - %ET  - The RFC3339 "date-time" separator "T"
 //
 // Note that %E0S behaves like %S, and %E0f produces no characters. In
 // contrast %E*f always produces at least one digit, which may be '0'.
@@ -323,7 +322,8 @@
 // returns the corresponding time_point. Uses strftime()-like formatting
 // options, with the same extensions as cctz::format(), but with the
 // exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez
-// and %E*z also accept the same inputs.
+// and %E*z also accept the same inputs, which (along with %z) includes
+// 'z' and 'Z' as synonyms for +00:00.  %ET accepts either 'T' or 't'.
 //
 // %Y consumes as many numeric characters as it can, so the matching data
 // should always be terminated with a non-numeric. %E4Y always consumes
@@ -380,6 +380,7 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_
diff --git a/absl/time/internal/cctz/include/cctz/zone_info_source.h b/absl/time/internal/cctz/include/cctz/zone_info_source.h
index 2b898d1..012eb4e 100644
--- a/absl/time/internal/cctz/include/cctz/zone_info_source.h
+++ b/absl/time/internal/cctz/include/cctz/zone_info_source.h
@@ -20,7 +20,10 @@
 #include <memory>
 #include <string>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -30,19 +33,21 @@
   virtual ~ZoneInfoSource();
 
   virtual std::size_t Read(void* ptr, std::size_t size) = 0;  // like fread()
-  virtual int Skip(std::size_t offset) = 0;  // like fseek()
+  virtual int Skip(std::size_t offset) = 0;                   // like fseek()
 
   // Until the zoneinfo data supports versioning information, we provide
   // a way for a ZoneInfoSource to indicate it out-of-band.  The default
-  // implementation returns an empty std::string.
+  // implementation returns an empty string.
   virtual std::string Version() const;
 };
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz_extension {
 
@@ -52,8 +57,8 @@
 using ZoneInfoSourceFactory =
     std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> (*)(
         const std::string&,
-        const std::function<std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource>(
-            const std::string&)>&);
+        const std::function<std::unique_ptr<
+            absl::time_internal::cctz::ZoneInfoSource>(const std::string&)>&);
 
 // The user can control the mapping of zone names to zoneinfo data by
 // providing a definition for cctz_extension::zone_info_source_factory.
@@ -91,6 +96,7 @@
 
 }  // namespace cctz_extension
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_
diff --git a/absl/time/internal/cctz/src/cctz_benchmark.cc b/absl/time/internal/cctz/src/cctz_benchmark.cc
index a40f504..4e39188 100644
--- a/absl/time/internal/cctz/src/cctz_benchmark.cc
+++ b/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -97,609 +97,608 @@
 }
 BENCHMARK(BM_PrevWeekday);
 
-const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
-const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
+const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez";
+const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
 
 const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
 const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z";
 
 // A list of known time-zone names.
 // TODO: Refactor with src/time_zone_lookup_test.cc.
-const char* const kTimeZoneNames[] = {
-  "Africa/Abidjan",
-  "Africa/Accra",
-  "Africa/Addis_Ababa",
-  "Africa/Algiers",
-  "Africa/Asmara",
-  "Africa/Asmera",
-  "Africa/Bamako",
-  "Africa/Bangui",
-  "Africa/Banjul",
-  "Africa/Bissau",
-  "Africa/Blantyre",
-  "Africa/Brazzaville",
-  "Africa/Bujumbura",
-  "Africa/Cairo",
-  "Africa/Casablanca",
-  "Africa/Ceuta",
-  "Africa/Conakry",
-  "Africa/Dakar",
-  "Africa/Dar_es_Salaam",
-  "Africa/Djibouti",
-  "Africa/Douala",
-  "Africa/El_Aaiun",
-  "Africa/Freetown",
-  "Africa/Gaborone",
-  "Africa/Harare",
-  "Africa/Johannesburg",
-  "Africa/Juba",
-  "Africa/Kampala",
-  "Africa/Khartoum",
-  "Africa/Kigali",
-  "Africa/Kinshasa",
-  "Africa/Lagos",
-  "Africa/Libreville",
-  "Africa/Lome",
-  "Africa/Luanda",
-  "Africa/Lubumbashi",
-  "Africa/Lusaka",
-  "Africa/Malabo",
-  "Africa/Maputo",
-  "Africa/Maseru",
-  "Africa/Mbabane",
-  "Africa/Mogadishu",
-  "Africa/Monrovia",
-  "Africa/Nairobi",
-  "Africa/Ndjamena",
-  "Africa/Niamey",
-  "Africa/Nouakchott",
-  "Africa/Ouagadougou",
-  "Africa/Porto-Novo",
-  "Africa/Sao_Tome",
-  "Africa/Timbuktu",
-  "Africa/Tripoli",
-  "Africa/Tunis",
-  "Africa/Windhoek",
-  "America/Adak",
-  "America/Anchorage",
-  "America/Anguilla",
-  "America/Antigua",
-  "America/Araguaina",
-  "America/Argentina/Buenos_Aires",
-  "America/Argentina/Catamarca",
-  "America/Argentina/ComodRivadavia",
-  "America/Argentina/Cordoba",
-  "America/Argentina/Jujuy",
-  "America/Argentina/La_Rioja",
-  "America/Argentina/Mendoza",
-  "America/Argentina/Rio_Gallegos",
-  "America/Argentina/Salta",
-  "America/Argentina/San_Juan",
-  "America/Argentina/San_Luis",
-  "America/Argentina/Tucuman",
-  "America/Argentina/Ushuaia",
-  "America/Aruba",
-  "America/Asuncion",
-  "America/Atikokan",
-  "America/Atka",
-  "America/Bahia",
-  "America/Bahia_Banderas",
-  "America/Barbados",
-  "America/Belem",
-  "America/Belize",
-  "America/Blanc-Sablon",
-  "America/Boa_Vista",
-  "America/Bogota",
-  "America/Boise",
-  "America/Buenos_Aires",
-  "America/Cambridge_Bay",
-  "America/Campo_Grande",
-  "America/Cancun",
-  "America/Caracas",
-  "America/Catamarca",
-  "America/Cayenne",
-  "America/Cayman",
-  "America/Chicago",
-  "America/Chihuahua",
-  "America/Coral_Harbour",
-  "America/Cordoba",
-  "America/Costa_Rica",
-  "America/Creston",
-  "America/Cuiaba",
-  "America/Curacao",
-  "America/Danmarkshavn",
-  "America/Dawson",
-  "America/Dawson_Creek",
-  "America/Denver",
-  "America/Detroit",
-  "America/Dominica",
-  "America/Edmonton",
-  "America/Eirunepe",
-  "America/El_Salvador",
-  "America/Ensenada",
-  "America/Fort_Nelson",
-  "America/Fort_Wayne",
-  "America/Fortaleza",
-  "America/Glace_Bay",
-  "America/Godthab",
-  "America/Goose_Bay",
-  "America/Grand_Turk",
-  "America/Grenada",
-  "America/Guadeloupe",
-  "America/Guatemala",
-  "America/Guayaquil",
-  "America/Guyana",
-  "America/Halifax",
-  "America/Havana",
-  "America/Hermosillo",
-  "America/Indiana/Indianapolis",
-  "America/Indiana/Knox",
-  "America/Indiana/Marengo",
-  "America/Indiana/Petersburg",
-  "America/Indiana/Tell_City",
-  "America/Indiana/Vevay",
-  "America/Indiana/Vincennes",
-  "America/Indiana/Winamac",
-  "America/Indianapolis",
-  "America/Inuvik",
-  "America/Iqaluit",
-  "America/Jamaica",
-  "America/Jujuy",
-  "America/Juneau",
-  "America/Kentucky/Louisville",
-  "America/Kentucky/Monticello",
-  "America/Knox_IN",
-  "America/Kralendijk",
-  "America/La_Paz",
-  "America/Lima",
-  "America/Los_Angeles",
-  "America/Louisville",
-  "America/Lower_Princes",
-  "America/Maceio",
-  "America/Managua",
-  "America/Manaus",
-  "America/Marigot",
-  "America/Martinique",
-  "America/Matamoros",
-  "America/Mazatlan",
-  "America/Mendoza",
-  "America/Menominee",
-  "America/Merida",
-  "America/Metlakatla",
-  "America/Mexico_City",
-  "America/Miquelon",
-  "America/Moncton",
-  "America/Monterrey",
-  "America/Montevideo",
-  "America/Montreal",
-  "America/Montserrat",
-  "America/Nassau",
-  "America/New_York",
-  "America/Nipigon",
-  "America/Nome",
-  "America/Noronha",
-  "America/North_Dakota/Beulah",
-  "America/North_Dakota/Center",
-  "America/North_Dakota/New_Salem",
-  "America/Ojinaga",
-  "America/Panama",
-  "America/Pangnirtung",
-  "America/Paramaribo",
-  "America/Phoenix",
-  "America/Port-au-Prince",
-  "America/Port_of_Spain",
-  "America/Porto_Acre",
-  "America/Porto_Velho",
-  "America/Puerto_Rico",
-  "America/Punta_Arenas",
-  "America/Rainy_River",
-  "America/Rankin_Inlet",
-  "America/Recife",
-  "America/Regina",
-  "America/Resolute",
-  "America/Rio_Branco",
-  "America/Rosario",
-  "America/Santa_Isabel",
-  "America/Santarem",
-  "America/Santiago",
-  "America/Santo_Domingo",
-  "America/Sao_Paulo",
-  "America/Scoresbysund",
-  "America/Shiprock",
-  "America/Sitka",
-  "America/St_Barthelemy",
-  "America/St_Johns",
-  "America/St_Kitts",
-  "America/St_Lucia",
-  "America/St_Thomas",
-  "America/St_Vincent",
-  "America/Swift_Current",
-  "America/Tegucigalpa",
-  "America/Thule",
-  "America/Thunder_Bay",
-  "America/Tijuana",
-  "America/Toronto",
-  "America/Tortola",
-  "America/Vancouver",
-  "America/Virgin",
-  "America/Whitehorse",
-  "America/Winnipeg",
-  "America/Yakutat",
-  "America/Yellowknife",
-  "Antarctica/Casey",
-  "Antarctica/Davis",
-  "Antarctica/DumontDUrville",
-  "Antarctica/Macquarie",
-  "Antarctica/Mawson",
-  "Antarctica/McMurdo",
-  "Antarctica/Palmer",
-  "Antarctica/Rothera",
-  "Antarctica/South_Pole",
-  "Antarctica/Syowa",
-  "Antarctica/Troll",
-  "Antarctica/Vostok",
-  "Arctic/Longyearbyen",
-  "Asia/Aden",
-  "Asia/Almaty",
-  "Asia/Amman",
-  "Asia/Anadyr",
-  "Asia/Aqtau",
-  "Asia/Aqtobe",
-  "Asia/Ashgabat",
-  "Asia/Ashkhabad",
-  "Asia/Atyrau",
-  "Asia/Baghdad",
-  "Asia/Bahrain",
-  "Asia/Baku",
-  "Asia/Bangkok",
-  "Asia/Barnaul",
-  "Asia/Beirut",
-  "Asia/Bishkek",
-  "Asia/Brunei",
-  "Asia/Calcutta",
-  "Asia/Chita",
-  "Asia/Choibalsan",
-  "Asia/Chongqing",
-  "Asia/Chungking",
-  "Asia/Colombo",
-  "Asia/Dacca",
-  "Asia/Damascus",
-  "Asia/Dhaka",
-  "Asia/Dili",
-  "Asia/Dubai",
-  "Asia/Dushanbe",
-  "Asia/Famagusta",
-  "Asia/Gaza",
-  "Asia/Harbin",
-  "Asia/Hebron",
-  "Asia/Ho_Chi_Minh",
-  "Asia/Hong_Kong",
-  "Asia/Hovd",
-  "Asia/Irkutsk",
-  "Asia/Istanbul",
-  "Asia/Jakarta",
-  "Asia/Jayapura",
-  "Asia/Jerusalem",
-  "Asia/Kabul",
-  "Asia/Kamchatka",
-  "Asia/Karachi",
-  "Asia/Kashgar",
-  "Asia/Kathmandu",
-  "Asia/Katmandu",
-  "Asia/Khandyga",
-  "Asia/Kolkata",
-  "Asia/Krasnoyarsk",
-  "Asia/Kuala_Lumpur",
-  "Asia/Kuching",
-  "Asia/Kuwait",
-  "Asia/Macao",
-  "Asia/Macau",
-  "Asia/Magadan",
-  "Asia/Makassar",
-  "Asia/Manila",
-  "Asia/Muscat",
-  "Asia/Nicosia",
-  "Asia/Novokuznetsk",
-  "Asia/Novosibirsk",
-  "Asia/Omsk",
-  "Asia/Oral",
-  "Asia/Phnom_Penh",
-  "Asia/Pontianak",
-  "Asia/Pyongyang",
-  "Asia/Qatar",
-  "Asia/Qostanay",
-  "Asia/Qyzylorda",
-  "Asia/Rangoon",
-  "Asia/Riyadh",
-  "Asia/Saigon",
-  "Asia/Sakhalin",
-  "Asia/Samarkand",
-  "Asia/Seoul",
-  "Asia/Shanghai",
-  "Asia/Singapore",
-  "Asia/Srednekolymsk",
-  "Asia/Taipei",
-  "Asia/Tashkent",
-  "Asia/Tbilisi",
-  "Asia/Tehran",
-  "Asia/Tel_Aviv",
-  "Asia/Thimbu",
-  "Asia/Thimphu",
-  "Asia/Tokyo",
-  "Asia/Tomsk",
-  "Asia/Ujung_Pandang",
-  "Asia/Ulaanbaatar",
-  "Asia/Ulan_Bator",
-  "Asia/Urumqi",
-  "Asia/Ust-Nera",
-  "Asia/Vientiane",
-  "Asia/Vladivostok",
-  "Asia/Yakutsk",
-  "Asia/Yangon",
-  "Asia/Yekaterinburg",
-  "Asia/Yerevan",
-  "Atlantic/Azores",
-  "Atlantic/Bermuda",
-  "Atlantic/Canary",
-  "Atlantic/Cape_Verde",
-  "Atlantic/Faeroe",
-  "Atlantic/Faroe",
-  "Atlantic/Jan_Mayen",
-  "Atlantic/Madeira",
-  "Atlantic/Reykjavik",
-  "Atlantic/South_Georgia",
-  "Atlantic/St_Helena",
-  "Atlantic/Stanley",
-  "Australia/ACT",
-  "Australia/Adelaide",
-  "Australia/Brisbane",
-  "Australia/Broken_Hill",
-  "Australia/Canberra",
-  "Australia/Currie",
-  "Australia/Darwin",
-  "Australia/Eucla",
-  "Australia/Hobart",
-  "Australia/LHI",
-  "Australia/Lindeman",
-  "Australia/Lord_Howe",
-  "Australia/Melbourne",
-  "Australia/NSW",
-  "Australia/North",
-  "Australia/Perth",
-  "Australia/Queensland",
-  "Australia/South",
-  "Australia/Sydney",
-  "Australia/Tasmania",
-  "Australia/Victoria",
-  "Australia/West",
-  "Australia/Yancowinna",
-  "Brazil/Acre",
-  "Brazil/DeNoronha",
-  "Brazil/East",
-  "Brazil/West",
-  "CET",
-  "CST6CDT",
-  "Canada/Atlantic",
-  "Canada/Central",
-  "Canada/Eastern",
-  "Canada/Mountain",
-  "Canada/Newfoundland",
-  "Canada/Pacific",
-  "Canada/Saskatchewan",
-  "Canada/Yukon",
-  "Chile/Continental",
-  "Chile/EasterIsland",
-  "Cuba",
-  "EET",
-  "EST",
-  "EST5EDT",
-  "Egypt",
-  "Eire",
-  "Etc/GMT",
-  "Etc/GMT+0",
-  "Etc/GMT+1",
-  "Etc/GMT+10",
-  "Etc/GMT+11",
-  "Etc/GMT+12",
-  "Etc/GMT+2",
-  "Etc/GMT+3",
-  "Etc/GMT+4",
-  "Etc/GMT+5",
-  "Etc/GMT+6",
-  "Etc/GMT+7",
-  "Etc/GMT+8",
-  "Etc/GMT+9",
-  "Etc/GMT-0",
-  "Etc/GMT-1",
-  "Etc/GMT-10",
-  "Etc/GMT-11",
-  "Etc/GMT-12",
-  "Etc/GMT-13",
-  "Etc/GMT-14",
-  "Etc/GMT-2",
-  "Etc/GMT-3",
-  "Etc/GMT-4",
-  "Etc/GMT-5",
-  "Etc/GMT-6",
-  "Etc/GMT-7",
-  "Etc/GMT-8",
-  "Etc/GMT-9",
-  "Etc/GMT0",
-  "Etc/Greenwich",
-  "Etc/UCT",
-  "Etc/UTC",
-  "Etc/Universal",
-  "Etc/Zulu",
-  "Europe/Amsterdam",
-  "Europe/Andorra",
-  "Europe/Astrakhan",
-  "Europe/Athens",
-  "Europe/Belfast",
-  "Europe/Belgrade",
-  "Europe/Berlin",
-  "Europe/Bratislava",
-  "Europe/Brussels",
-  "Europe/Bucharest",
-  "Europe/Budapest",
-  "Europe/Busingen",
-  "Europe/Chisinau",
-  "Europe/Copenhagen",
-  "Europe/Dublin",
-  "Europe/Gibraltar",
-  "Europe/Guernsey",
-  "Europe/Helsinki",
-  "Europe/Isle_of_Man",
-  "Europe/Istanbul",
-  "Europe/Jersey",
-  "Europe/Kaliningrad",
-  "Europe/Kiev",
-  "Europe/Kirov",
-  "Europe/Lisbon",
-  "Europe/Ljubljana",
-  "Europe/London",
-  "Europe/Luxembourg",
-  "Europe/Madrid",
-  "Europe/Malta",
-  "Europe/Mariehamn",
-  "Europe/Minsk",
-  "Europe/Monaco",
-  "Europe/Moscow",
-  "Europe/Nicosia",
-  "Europe/Oslo",
-  "Europe/Paris",
-  "Europe/Podgorica",
-  "Europe/Prague",
-  "Europe/Riga",
-  "Europe/Rome",
-  "Europe/Samara",
-  "Europe/San_Marino",
-  "Europe/Sarajevo",
-  "Europe/Saratov",
-  "Europe/Simferopol",
-  "Europe/Skopje",
-  "Europe/Sofia",
-  "Europe/Stockholm",
-  "Europe/Tallinn",
-  "Europe/Tirane",
-  "Europe/Tiraspol",
-  "Europe/Ulyanovsk",
-  "Europe/Uzhgorod",
-  "Europe/Vaduz",
-  "Europe/Vatican",
-  "Europe/Vienna",
-  "Europe/Vilnius",
-  "Europe/Volgograd",
-  "Europe/Warsaw",
-  "Europe/Zagreb",
-  "Europe/Zaporozhye",
-  "Europe/Zurich",
-  "GB",
-  "GB-Eire",
-  "GMT",
-  "GMT+0",
-  "GMT-0",
-  "GMT0",
-  "Greenwich",
-  "HST",
-  "Hongkong",
-  "Iceland",
-  "Indian/Antananarivo",
-  "Indian/Chagos",
-  "Indian/Christmas",
-  "Indian/Cocos",
-  "Indian/Comoro",
-  "Indian/Kerguelen",
-  "Indian/Mahe",
-  "Indian/Maldives",
-  "Indian/Mauritius",
-  "Indian/Mayotte",
-  "Indian/Reunion",
-  "Iran",
-  "Israel",
-  "Jamaica",
-  "Japan",
-  "Kwajalein",
-  "Libya",
-  "MET",
-  "MST",
-  "MST7MDT",
-  "Mexico/BajaNorte",
-  "Mexico/BajaSur",
-  "Mexico/General",
-  "NZ",
-  "NZ-CHAT",
-  "Navajo",
-  "PRC",
-  "PST8PDT",
-  "Pacific/Apia",
-  "Pacific/Auckland",
-  "Pacific/Bougainville",
-  "Pacific/Chatham",
-  "Pacific/Chuuk",
-  "Pacific/Easter",
-  "Pacific/Efate",
-  "Pacific/Enderbury",
-  "Pacific/Fakaofo",
-  "Pacific/Fiji",
-  "Pacific/Funafuti",
-  "Pacific/Galapagos",
-  "Pacific/Gambier",
-  "Pacific/Guadalcanal",
-  "Pacific/Guam",
-  "Pacific/Honolulu",
-  "Pacific/Johnston",
-  "Pacific/Kiritimati",
-  "Pacific/Kosrae",
-  "Pacific/Kwajalein",
-  "Pacific/Majuro",
-  "Pacific/Marquesas",
-  "Pacific/Midway",
-  "Pacific/Nauru",
-  "Pacific/Niue",
-  "Pacific/Norfolk",
-  "Pacific/Noumea",
-  "Pacific/Pago_Pago",
-  "Pacific/Palau",
-  "Pacific/Pitcairn",
-  "Pacific/Pohnpei",
-  "Pacific/Ponape",
-  "Pacific/Port_Moresby",
-  "Pacific/Rarotonga",
-  "Pacific/Saipan",
-  "Pacific/Samoa",
-  "Pacific/Tahiti",
-  "Pacific/Tarawa",
-  "Pacific/Tongatapu",
-  "Pacific/Truk",
-  "Pacific/Wake",
-  "Pacific/Wallis",
-  "Pacific/Yap",
-  "Poland",
-  "Portugal",
-  "ROC",
-  "ROK",
-  "Singapore",
-  "Turkey",
-  "UCT",
-  "US/Alaska",
-  "US/Aleutian",
-  "US/Arizona",
-  "US/Central",
-  "US/East-Indiana",
-  "US/Eastern",
-  "US/Hawaii",
-  "US/Indiana-Starke",
-  "US/Michigan",
-  "US/Mountain",
-  "US/Pacific",
-  "US/Samoa",
-  "UTC",
-  "Universal",
-  "W-SU",
-  "WET",
-  "Zulu",
-  nullptr
-};
+const char* const kTimeZoneNames[] = {"Africa/Abidjan",
+                                      "Africa/Accra",
+                                      "Africa/Addis_Ababa",
+                                      "Africa/Algiers",
+                                      "Africa/Asmara",
+                                      "Africa/Asmera",
+                                      "Africa/Bamako",
+                                      "Africa/Bangui",
+                                      "Africa/Banjul",
+                                      "Africa/Bissau",
+                                      "Africa/Blantyre",
+                                      "Africa/Brazzaville",
+                                      "Africa/Bujumbura",
+                                      "Africa/Cairo",
+                                      "Africa/Casablanca",
+                                      "Africa/Ceuta",
+                                      "Africa/Conakry",
+                                      "Africa/Dakar",
+                                      "Africa/Dar_es_Salaam",
+                                      "Africa/Djibouti",
+                                      "Africa/Douala",
+                                      "Africa/El_Aaiun",
+                                      "Africa/Freetown",
+                                      "Africa/Gaborone",
+                                      "Africa/Harare",
+                                      "Africa/Johannesburg",
+                                      "Africa/Juba",
+                                      "Africa/Kampala",
+                                      "Africa/Khartoum",
+                                      "Africa/Kigali",
+                                      "Africa/Kinshasa",
+                                      "Africa/Lagos",
+                                      "Africa/Libreville",
+                                      "Africa/Lome",
+                                      "Africa/Luanda",
+                                      "Africa/Lubumbashi",
+                                      "Africa/Lusaka",
+                                      "Africa/Malabo",
+                                      "Africa/Maputo",
+                                      "Africa/Maseru",
+                                      "Africa/Mbabane",
+                                      "Africa/Mogadishu",
+                                      "Africa/Monrovia",
+                                      "Africa/Nairobi",
+                                      "Africa/Ndjamena",
+                                      "Africa/Niamey",
+                                      "Africa/Nouakchott",
+                                      "Africa/Ouagadougou",
+                                      "Africa/Porto-Novo",
+                                      "Africa/Sao_Tome",
+                                      "Africa/Timbuktu",
+                                      "Africa/Tripoli",
+                                      "Africa/Tunis",
+                                      "Africa/Windhoek",
+                                      "America/Adak",
+                                      "America/Anchorage",
+                                      "America/Anguilla",
+                                      "America/Antigua",
+                                      "America/Araguaina",
+                                      "America/Argentina/Buenos_Aires",
+                                      "America/Argentina/Catamarca",
+                                      "America/Argentina/ComodRivadavia",
+                                      "America/Argentina/Cordoba",
+                                      "America/Argentina/Jujuy",
+                                      "America/Argentina/La_Rioja",
+                                      "America/Argentina/Mendoza",
+                                      "America/Argentina/Rio_Gallegos",
+                                      "America/Argentina/Salta",
+                                      "America/Argentina/San_Juan",
+                                      "America/Argentina/San_Luis",
+                                      "America/Argentina/Tucuman",
+                                      "America/Argentina/Ushuaia",
+                                      "America/Aruba",
+                                      "America/Asuncion",
+                                      "America/Atikokan",
+                                      "America/Atka",
+                                      "America/Bahia",
+                                      "America/Bahia_Banderas",
+                                      "America/Barbados",
+                                      "America/Belem",
+                                      "America/Belize",
+                                      "America/Blanc-Sablon",
+                                      "America/Boa_Vista",
+                                      "America/Bogota",
+                                      "America/Boise",
+                                      "America/Buenos_Aires",
+                                      "America/Cambridge_Bay",
+                                      "America/Campo_Grande",
+                                      "America/Cancun",
+                                      "America/Caracas",
+                                      "America/Catamarca",
+                                      "America/Cayenne",
+                                      "America/Cayman",
+                                      "America/Chicago",
+                                      "America/Chihuahua",
+                                      "America/Coral_Harbour",
+                                      "America/Cordoba",
+                                      "America/Costa_Rica",
+                                      "America/Creston",
+                                      "America/Cuiaba",
+                                      "America/Curacao",
+                                      "America/Danmarkshavn",
+                                      "America/Dawson",
+                                      "America/Dawson_Creek",
+                                      "America/Denver",
+                                      "America/Detroit",
+                                      "America/Dominica",
+                                      "America/Edmonton",
+                                      "America/Eirunepe",
+                                      "America/El_Salvador",
+                                      "America/Ensenada",
+                                      "America/Fort_Nelson",
+                                      "America/Fort_Wayne",
+                                      "America/Fortaleza",
+                                      "America/Glace_Bay",
+                                      "America/Godthab",
+                                      "America/Goose_Bay",
+                                      "America/Grand_Turk",
+                                      "America/Grenada",
+                                      "America/Guadeloupe",
+                                      "America/Guatemala",
+                                      "America/Guayaquil",
+                                      "America/Guyana",
+                                      "America/Halifax",
+                                      "America/Havana",
+                                      "America/Hermosillo",
+                                      "America/Indiana/Indianapolis",
+                                      "America/Indiana/Knox",
+                                      "America/Indiana/Marengo",
+                                      "America/Indiana/Petersburg",
+                                      "America/Indiana/Tell_City",
+                                      "America/Indiana/Vevay",
+                                      "America/Indiana/Vincennes",
+                                      "America/Indiana/Winamac",
+                                      "America/Indianapolis",
+                                      "America/Inuvik",
+                                      "America/Iqaluit",
+                                      "America/Jamaica",
+                                      "America/Jujuy",
+                                      "America/Juneau",
+                                      "America/Kentucky/Louisville",
+                                      "America/Kentucky/Monticello",
+                                      "America/Knox_IN",
+                                      "America/Kralendijk",
+                                      "America/La_Paz",
+                                      "America/Lima",
+                                      "America/Los_Angeles",
+                                      "America/Louisville",
+                                      "America/Lower_Princes",
+                                      "America/Maceio",
+                                      "America/Managua",
+                                      "America/Manaus",
+                                      "America/Marigot",
+                                      "America/Martinique",
+                                      "America/Matamoros",
+                                      "America/Mazatlan",
+                                      "America/Mendoza",
+                                      "America/Menominee",
+                                      "America/Merida",
+                                      "America/Metlakatla",
+                                      "America/Mexico_City",
+                                      "America/Miquelon",
+                                      "America/Moncton",
+                                      "America/Monterrey",
+                                      "America/Montevideo",
+                                      "America/Montreal",
+                                      "America/Montserrat",
+                                      "America/Nassau",
+                                      "America/New_York",
+                                      "America/Nipigon",
+                                      "America/Nome",
+                                      "America/Noronha",
+                                      "America/North_Dakota/Beulah",
+                                      "America/North_Dakota/Center",
+                                      "America/North_Dakota/New_Salem",
+                                      "America/Nuuk",
+                                      "America/Ojinaga",
+                                      "America/Panama",
+                                      "America/Pangnirtung",
+                                      "America/Paramaribo",
+                                      "America/Phoenix",
+                                      "America/Port-au-Prince",
+                                      "America/Port_of_Spain",
+                                      "America/Porto_Acre",
+                                      "America/Porto_Velho",
+                                      "America/Puerto_Rico",
+                                      "America/Punta_Arenas",
+                                      "America/Rainy_River",
+                                      "America/Rankin_Inlet",
+                                      "America/Recife",
+                                      "America/Regina",
+                                      "America/Resolute",
+                                      "America/Rio_Branco",
+                                      "America/Rosario",
+                                      "America/Santa_Isabel",
+                                      "America/Santarem",
+                                      "America/Santiago",
+                                      "America/Santo_Domingo",
+                                      "America/Sao_Paulo",
+                                      "America/Scoresbysund",
+                                      "America/Shiprock",
+                                      "America/Sitka",
+                                      "America/St_Barthelemy",
+                                      "America/St_Johns",
+                                      "America/St_Kitts",
+                                      "America/St_Lucia",
+                                      "America/St_Thomas",
+                                      "America/St_Vincent",
+                                      "America/Swift_Current",
+                                      "America/Tegucigalpa",
+                                      "America/Thule",
+                                      "America/Thunder_Bay",
+                                      "America/Tijuana",
+                                      "America/Toronto",
+                                      "America/Tortola",
+                                      "America/Vancouver",
+                                      "America/Virgin",
+                                      "America/Whitehorse",
+                                      "America/Winnipeg",
+                                      "America/Yakutat",
+                                      "America/Yellowknife",
+                                      "Antarctica/Casey",
+                                      "Antarctica/Davis",
+                                      "Antarctica/DumontDUrville",
+                                      "Antarctica/Macquarie",
+                                      "Antarctica/Mawson",
+                                      "Antarctica/McMurdo",
+                                      "Antarctica/Palmer",
+                                      "Antarctica/Rothera",
+                                      "Antarctica/South_Pole",
+                                      "Antarctica/Syowa",
+                                      "Antarctica/Troll",
+                                      "Antarctica/Vostok",
+                                      "Arctic/Longyearbyen",
+                                      "Asia/Aden",
+                                      "Asia/Almaty",
+                                      "Asia/Amman",
+                                      "Asia/Anadyr",
+                                      "Asia/Aqtau",
+                                      "Asia/Aqtobe",
+                                      "Asia/Ashgabat",
+                                      "Asia/Ashkhabad",
+                                      "Asia/Atyrau",
+                                      "Asia/Baghdad",
+                                      "Asia/Bahrain",
+                                      "Asia/Baku",
+                                      "Asia/Bangkok",
+                                      "Asia/Barnaul",
+                                      "Asia/Beirut",
+                                      "Asia/Bishkek",
+                                      "Asia/Brunei",
+                                      "Asia/Calcutta",
+                                      "Asia/Chita",
+                                      "Asia/Choibalsan",
+                                      "Asia/Chongqing",
+                                      "Asia/Chungking",
+                                      "Asia/Colombo",
+                                      "Asia/Dacca",
+                                      "Asia/Damascus",
+                                      "Asia/Dhaka",
+                                      "Asia/Dili",
+                                      "Asia/Dubai",
+                                      "Asia/Dushanbe",
+                                      "Asia/Famagusta",
+                                      "Asia/Gaza",
+                                      "Asia/Harbin",
+                                      "Asia/Hebron",
+                                      "Asia/Ho_Chi_Minh",
+                                      "Asia/Hong_Kong",
+                                      "Asia/Hovd",
+                                      "Asia/Irkutsk",
+                                      "Asia/Istanbul",
+                                      "Asia/Jakarta",
+                                      "Asia/Jayapura",
+                                      "Asia/Jerusalem",
+                                      "Asia/Kabul",
+                                      "Asia/Kamchatka",
+                                      "Asia/Karachi",
+                                      "Asia/Kashgar",
+                                      "Asia/Kathmandu",
+                                      "Asia/Katmandu",
+                                      "Asia/Khandyga",
+                                      "Asia/Kolkata",
+                                      "Asia/Krasnoyarsk",
+                                      "Asia/Kuala_Lumpur",
+                                      "Asia/Kuching",
+                                      "Asia/Kuwait",
+                                      "Asia/Macao",
+                                      "Asia/Macau",
+                                      "Asia/Magadan",
+                                      "Asia/Makassar",
+                                      "Asia/Manila",
+                                      "Asia/Muscat",
+                                      "Asia/Nicosia",
+                                      "Asia/Novokuznetsk",
+                                      "Asia/Novosibirsk",
+                                      "Asia/Omsk",
+                                      "Asia/Oral",
+                                      "Asia/Phnom_Penh",
+                                      "Asia/Pontianak",
+                                      "Asia/Pyongyang",
+                                      "Asia/Qatar",
+                                      "Asia/Qostanay",
+                                      "Asia/Qyzylorda",
+                                      "Asia/Rangoon",
+                                      "Asia/Riyadh",
+                                      "Asia/Saigon",
+                                      "Asia/Sakhalin",
+                                      "Asia/Samarkand",
+                                      "Asia/Seoul",
+                                      "Asia/Shanghai",
+                                      "Asia/Singapore",
+                                      "Asia/Srednekolymsk",
+                                      "Asia/Taipei",
+                                      "Asia/Tashkent",
+                                      "Asia/Tbilisi",
+                                      "Asia/Tehran",
+                                      "Asia/Tel_Aviv",
+                                      "Asia/Thimbu",
+                                      "Asia/Thimphu",
+                                      "Asia/Tokyo",
+                                      "Asia/Tomsk",
+                                      "Asia/Ujung_Pandang",
+                                      "Asia/Ulaanbaatar",
+                                      "Asia/Ulan_Bator",
+                                      "Asia/Urumqi",
+                                      "Asia/Ust-Nera",
+                                      "Asia/Vientiane",
+                                      "Asia/Vladivostok",
+                                      "Asia/Yakutsk",
+                                      "Asia/Yangon",
+                                      "Asia/Yekaterinburg",
+                                      "Asia/Yerevan",
+                                      "Atlantic/Azores",
+                                      "Atlantic/Bermuda",
+                                      "Atlantic/Canary",
+                                      "Atlantic/Cape_Verde",
+                                      "Atlantic/Faeroe",
+                                      "Atlantic/Faroe",
+                                      "Atlantic/Jan_Mayen",
+                                      "Atlantic/Madeira",
+                                      "Atlantic/Reykjavik",
+                                      "Atlantic/South_Georgia",
+                                      "Atlantic/St_Helena",
+                                      "Atlantic/Stanley",
+                                      "Australia/ACT",
+                                      "Australia/Adelaide",
+                                      "Australia/Brisbane",
+                                      "Australia/Broken_Hill",
+                                      "Australia/Canberra",
+                                      "Australia/Currie",
+                                      "Australia/Darwin",
+                                      "Australia/Eucla",
+                                      "Australia/Hobart",
+                                      "Australia/LHI",
+                                      "Australia/Lindeman",
+                                      "Australia/Lord_Howe",
+                                      "Australia/Melbourne",
+                                      "Australia/NSW",
+                                      "Australia/North",
+                                      "Australia/Perth",
+                                      "Australia/Queensland",
+                                      "Australia/South",
+                                      "Australia/Sydney",
+                                      "Australia/Tasmania",
+                                      "Australia/Victoria",
+                                      "Australia/West",
+                                      "Australia/Yancowinna",
+                                      "Brazil/Acre",
+                                      "Brazil/DeNoronha",
+                                      "Brazil/East",
+                                      "Brazil/West",
+                                      "CET",
+                                      "CST6CDT",
+                                      "Canada/Atlantic",
+                                      "Canada/Central",
+                                      "Canada/Eastern",
+                                      "Canada/Mountain",
+                                      "Canada/Newfoundland",
+                                      "Canada/Pacific",
+                                      "Canada/Saskatchewan",
+                                      "Canada/Yukon",
+                                      "Chile/Continental",
+                                      "Chile/EasterIsland",
+                                      "Cuba",
+                                      "EET",
+                                      "EST",
+                                      "EST5EDT",
+                                      "Egypt",
+                                      "Eire",
+                                      "Etc/GMT",
+                                      "Etc/GMT+0",
+                                      "Etc/GMT+1",
+                                      "Etc/GMT+10",
+                                      "Etc/GMT+11",
+                                      "Etc/GMT+12",
+                                      "Etc/GMT+2",
+                                      "Etc/GMT+3",
+                                      "Etc/GMT+4",
+                                      "Etc/GMT+5",
+                                      "Etc/GMT+6",
+                                      "Etc/GMT+7",
+                                      "Etc/GMT+8",
+                                      "Etc/GMT+9",
+                                      "Etc/GMT-0",
+                                      "Etc/GMT-1",
+                                      "Etc/GMT-10",
+                                      "Etc/GMT-11",
+                                      "Etc/GMT-12",
+                                      "Etc/GMT-13",
+                                      "Etc/GMT-14",
+                                      "Etc/GMT-2",
+                                      "Etc/GMT-3",
+                                      "Etc/GMT-4",
+                                      "Etc/GMT-5",
+                                      "Etc/GMT-6",
+                                      "Etc/GMT-7",
+                                      "Etc/GMT-8",
+                                      "Etc/GMT-9",
+                                      "Etc/GMT0",
+                                      "Etc/Greenwich",
+                                      "Etc/UCT",
+                                      "Etc/UTC",
+                                      "Etc/Universal",
+                                      "Etc/Zulu",
+                                      "Europe/Amsterdam",
+                                      "Europe/Andorra",
+                                      "Europe/Astrakhan",
+                                      "Europe/Athens",
+                                      "Europe/Belfast",
+                                      "Europe/Belgrade",
+                                      "Europe/Berlin",
+                                      "Europe/Bratislava",
+                                      "Europe/Brussels",
+                                      "Europe/Bucharest",
+                                      "Europe/Budapest",
+                                      "Europe/Busingen",
+                                      "Europe/Chisinau",
+                                      "Europe/Copenhagen",
+                                      "Europe/Dublin",
+                                      "Europe/Gibraltar",
+                                      "Europe/Guernsey",
+                                      "Europe/Helsinki",
+                                      "Europe/Isle_of_Man",
+                                      "Europe/Istanbul",
+                                      "Europe/Jersey",
+                                      "Europe/Kaliningrad",
+                                      "Europe/Kiev",
+                                      "Europe/Kirov",
+                                      "Europe/Lisbon",
+                                      "Europe/Ljubljana",
+                                      "Europe/London",
+                                      "Europe/Luxembourg",
+                                      "Europe/Madrid",
+                                      "Europe/Malta",
+                                      "Europe/Mariehamn",
+                                      "Europe/Minsk",
+                                      "Europe/Monaco",
+                                      "Europe/Moscow",
+                                      "Europe/Nicosia",
+                                      "Europe/Oslo",
+                                      "Europe/Paris",
+                                      "Europe/Podgorica",
+                                      "Europe/Prague",
+                                      "Europe/Riga",
+                                      "Europe/Rome",
+                                      "Europe/Samara",
+                                      "Europe/San_Marino",
+                                      "Europe/Sarajevo",
+                                      "Europe/Saratov",
+                                      "Europe/Simferopol",
+                                      "Europe/Skopje",
+                                      "Europe/Sofia",
+                                      "Europe/Stockholm",
+                                      "Europe/Tallinn",
+                                      "Europe/Tirane",
+                                      "Europe/Tiraspol",
+                                      "Europe/Ulyanovsk",
+                                      "Europe/Uzhgorod",
+                                      "Europe/Vaduz",
+                                      "Europe/Vatican",
+                                      "Europe/Vienna",
+                                      "Europe/Vilnius",
+                                      "Europe/Volgograd",
+                                      "Europe/Warsaw",
+                                      "Europe/Zagreb",
+                                      "Europe/Zaporozhye",
+                                      "Europe/Zurich",
+                                      "GB",
+                                      "GB-Eire",
+                                      "GMT",
+                                      "GMT+0",
+                                      "GMT-0",
+                                      "GMT0",
+                                      "Greenwich",
+                                      "HST",
+                                      "Hongkong",
+                                      "Iceland",
+                                      "Indian/Antananarivo",
+                                      "Indian/Chagos",
+                                      "Indian/Christmas",
+                                      "Indian/Cocos",
+                                      "Indian/Comoro",
+                                      "Indian/Kerguelen",
+                                      "Indian/Mahe",
+                                      "Indian/Maldives",
+                                      "Indian/Mauritius",
+                                      "Indian/Mayotte",
+                                      "Indian/Reunion",
+                                      "Iran",
+                                      "Israel",
+                                      "Jamaica",
+                                      "Japan",
+                                      "Kwajalein",
+                                      "Libya",
+                                      "MET",
+                                      "MST",
+                                      "MST7MDT",
+                                      "Mexico/BajaNorte",
+                                      "Mexico/BajaSur",
+                                      "Mexico/General",
+                                      "NZ",
+                                      "NZ-CHAT",
+                                      "Navajo",
+                                      "PRC",
+                                      "PST8PDT",
+                                      "Pacific/Apia",
+                                      "Pacific/Auckland",
+                                      "Pacific/Bougainville",
+                                      "Pacific/Chatham",
+                                      "Pacific/Chuuk",
+                                      "Pacific/Easter",
+                                      "Pacific/Efate",
+                                      "Pacific/Enderbury",
+                                      "Pacific/Fakaofo",
+                                      "Pacific/Fiji",
+                                      "Pacific/Funafuti",
+                                      "Pacific/Galapagos",
+                                      "Pacific/Gambier",
+                                      "Pacific/Guadalcanal",
+                                      "Pacific/Guam",
+                                      "Pacific/Honolulu",
+                                      "Pacific/Johnston",
+                                      "Pacific/Kiritimati",
+                                      "Pacific/Kosrae",
+                                      "Pacific/Kwajalein",
+                                      "Pacific/Majuro",
+                                      "Pacific/Marquesas",
+                                      "Pacific/Midway",
+                                      "Pacific/Nauru",
+                                      "Pacific/Niue",
+                                      "Pacific/Norfolk",
+                                      "Pacific/Noumea",
+                                      "Pacific/Pago_Pago",
+                                      "Pacific/Palau",
+                                      "Pacific/Pitcairn",
+                                      "Pacific/Pohnpei",
+                                      "Pacific/Ponape",
+                                      "Pacific/Port_Moresby",
+                                      "Pacific/Rarotonga",
+                                      "Pacific/Saipan",
+                                      "Pacific/Samoa",
+                                      "Pacific/Tahiti",
+                                      "Pacific/Tarawa",
+                                      "Pacific/Tongatapu",
+                                      "Pacific/Truk",
+                                      "Pacific/Wake",
+                                      "Pacific/Wallis",
+                                      "Pacific/Yap",
+                                      "Poland",
+                                      "Portugal",
+                                      "ROC",
+                                      "ROK",
+                                      "Singapore",
+                                      "Turkey",
+                                      "UCT",
+                                      "US/Alaska",
+                                      "US/Aleutian",
+                                      "US/Arizona",
+                                      "US/Central",
+                                      "US/East-Indiana",
+                                      "US/Eastern",
+                                      "US/Hawaii",
+                                      "US/Indiana-Starke",
+                                      "US/Michigan",
+                                      "US/Mountain",
+                                      "US/Pacific",
+                                      "US/Samoa",
+                                      "UTC",
+                                      "Universal",
+                                      "W-SU",
+                                      "WET",
+                                      "Zulu",
+                                      nullptr};
 
 std::vector<std::string> AllTimeZoneNames() {
   std::vector<std::string> names;
@@ -992,12 +991,12 @@
 BENCHMARK(BM_Time_FromCivilDay0_Libc);
 
 const char* const kFormats[] = {
-    RFC1123_full,         // 0
-    RFC1123_no_wday,      // 1
-    RFC3339_full,         // 2
-    RFC3339_sec,          // 3
-    "%Y-%m-%dT%H:%M:%S",  // 4
-    "%Y-%m-%d",           // 5
+    RFC1123_full,           // 0
+    RFC1123_no_wday,        // 1
+    RFC3339_full,           // 2
+    RFC3339_sec,            // 3
+    "%Y-%m-%d%ET%H:%M:%S",  // 4
+    "%Y-%m-%d",             // 5
 };
 const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
 
diff --git a/absl/time/internal/cctz/src/civil_time_detail.cc b/absl/time/internal/cctz/src/civil_time_detail.cc
index cb40b6b..0b07e39 100644
--- a/absl/time/internal/cctz/src/civil_time_detail.cc
+++ b/absl/time/internal/cctz/src/civil_time_detail.cc
@@ -18,7 +18,10 @@
 #include <ostream>
 #include <sstream>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 namespace detail {
@@ -87,4 +90,5 @@
 }  // namespace detail
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/civil_time_test.cc b/absl/time/internal/cctz/src/civil_time_test.cc
index 10a5ffe..a5a7123 100644
--- a/absl/time/internal/cctz/src/civil_time_test.cc
+++ b/absl/time/internal/cctz/src/civil_time_test.cc
@@ -21,8 +21,10 @@
 #include <type_traits>
 
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -233,6 +235,16 @@
 }
 
 // NOTE: Run this with --copt=-ftrapv to detect overflow problems.
+TEST(CivilTime, ConstructionWithHugeYear) {
+  constexpr civil_hour h(-9223372036854775807, 1, 1, -1);
+  static_assert(h.year() == -9223372036854775807 - 1,
+                "ConstructionWithHugeYear");
+  static_assert(h.month() == 12, "ConstructionWithHugeYear");
+  static_assert(h.day() == 31, "ConstructionWithHugeYear");
+  static_assert(h.hour() == 23, "ConstructionWithHugeYear");
+}
+
+// NOTE: Run this with --copt=-ftrapv to detect overflow problems.
 TEST(CivilTime, DifferenceWithHugeYear) {
   {
     constexpr civil_day d1(9223372036854775807, 1, 1);
@@ -1014,19 +1026,13 @@
       int day;
     } leap_day;  // The date of the day after Feb 28.
   } kLeapYearTable[]{
-      {1900, 365, {3, 1}},
-      {1999, 365, {3, 1}},
+      {1900, 365, {3, 1}},  {1999, 365, {3, 1}},
       {2000, 366, {2, 29}},  // leap year
-      {2001, 365, {3, 1}},
-      {2002, 365, {3, 1}},
-      {2003, 365, {3, 1}},
-      {2004, 366, {2, 29}},  // leap year
-      {2005, 365, {3, 1}},
-      {2006, 365, {3, 1}},
-      {2007, 365, {3, 1}},
-      {2008, 366, {2, 29}},  // leap year
-      {2009, 365, {3, 1}},
-      {2100, 365, {3, 1}},
+      {2001, 365, {3, 1}},  {2002, 365, {3, 1}},
+      {2003, 365, {3, 1}},  {2004, 366, {2, 29}},  // leap year
+      {2005, 365, {3, 1}},  {2006, 365, {3, 1}},
+      {2007, 365, {3, 1}},  {2008, 366, {2, 29}},  // leap year
+      {2009, 365, {3, 1}},  {2100, 365, {3, 1}},
   };
 
   for (const auto& e : kLeapYearTable) {
@@ -1056,4 +1062,5 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_fixed.cc b/absl/time/internal/cctz/src/time_zone_fixed.cc
index b0d159a..303c024 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.cc
+++ b/absl/time/internal/cctz/src/time_zone_fixed.cc
@@ -20,7 +20,10 @@
 #include <cstring>
 #include <string>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -59,11 +62,9 @@
   const char* const ep = kFixedZonePrefix + prefix_len;
   if (name.size() != prefix_len + 9)  // <prefix>+99:99:99
     return false;
-  if (!std::equal(kFixedZonePrefix, ep, name.begin()))
-    return false;
+  if (!std::equal(kFixedZonePrefix, ep, name.begin())) return false;
   const char* np = name.data() + prefix_len;
-  if (np[0] != '+' && np[0] != '-')
-    return false;
+  if (np[0] != '+' && np[0] != '-') return false;
   if (np[3] != ':' || np[6] != ':')  // see note below about large offsets
     return false;
 
@@ -88,29 +89,29 @@
     // offsets and to (somewhat) limit the total number of zones.
     return "UTC";
   }
-  int seconds = static_cast<int>(offset.count());
-  const char sign = (seconds < 0 ? '-' : '+');
-  int minutes = seconds / 60;
-  seconds %= 60;
+  int offset_seconds = static_cast<int>(offset.count());
+  const char sign = (offset_seconds < 0 ? '-' : '+');
+  int offset_minutes = offset_seconds / 60;
+  offset_seconds %= 60;
   if (sign == '-') {
-    if (seconds > 0) {
-      seconds -= 60;
-      minutes += 1;
+    if (offset_seconds > 0) {
+      offset_seconds -= 60;
+      offset_minutes += 1;
     }
-    seconds = -seconds;
-    minutes = -minutes;
+    offset_seconds = -offset_seconds;
+    offset_minutes = -offset_minutes;
   }
-  int hours = minutes / 60;
-  minutes %= 60;
+  int offset_hours = offset_minutes / 60;
+  offset_minutes %= 60;
   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 = Format02d(ep, offset_hours);
   *ep++ = ':';
-  ep = Format02d(ep, minutes);
+  ep = Format02d(ep, offset_minutes);
   *ep++ = ':';
-  ep = Format02d(ep, seconds);
+  ep = Format02d(ep, offset_seconds);
   *ep++ = '\0';
   assert(ep == buf + sizeof(buf));
   return buf;
@@ -135,4 +136,5 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_fixed.h b/absl/time/internal/cctz/src/time_zone_fixed.h
index 9c1f5e7..e74a0bb 100644
--- a/absl/time/internal/cctz/src/time_zone_fixed.h
+++ b/absl/time/internal/cctz/src/time_zone_fixed.h
@@ -17,9 +17,11 @@
 
 #include <string>
 
+#include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -44,6 +46,7 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_
diff --git a/absl/time/internal/cctz/src/time_zone_format.cc b/absl/time/internal/cctz/src/time_zone_format.cc
index 84e280b..d8cb047 100644
--- a/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/absl/time/internal/cctz/src/time_zone_format.cc
@@ -13,17 +13,18 @@
 //   limitations under the License.
 
 #if !defined(HAS_STRPTIME)
-# if !defined(_MSC_VER) && !defined(__MINGW32__)
-#  define HAS_STRPTIME 1  // assume everyone has strptime() except windows
-# endif
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#define HAS_STRPTIME 1  // assume everyone has strptime() except windows
+#endif
 #endif
 
 #if defined(HAS_STRPTIME) && HAS_STRPTIME
-# if !defined(_XOPEN_SOURCE)
-#  define _XOPEN_SOURCE  // Definedness suffices for strptime.
-# endif
+#if !defined(_XOPEN_SOURCE)
+#define _XOPEN_SOURCE  // Definedness suffices for strptime.
+#endif
 #endif
 
+#include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
 // Include time.h directly since, by C++ standards, ctime doesn't have to
@@ -48,6 +49,7 @@
 #include "time_zone_if.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 namespace detail {
@@ -65,6 +67,48 @@
 }
 #endif
 
+// Convert a cctz::weekday to a tm_wday value (0-6, Sunday = 0).
+int ToTmWday(weekday wd) {
+  switch (wd) {
+    case weekday::sunday:
+      return 0;
+    case weekday::monday:
+      return 1;
+    case weekday::tuesday:
+      return 2;
+    case weekday::wednesday:
+      return 3;
+    case weekday::thursday:
+      return 4;
+    case weekday::friday:
+      return 5;
+    case weekday::saturday:
+      return 6;
+  }
+  return 0; /*NOTREACHED*/
+}
+
+// Convert a tm_wday value (0-6, Sunday = 0) to a cctz::weekday.
+weekday FromTmWday(int tm_wday) {
+  switch (tm_wday) {
+    case 0:
+      return weekday::sunday;
+    case 1:
+      return weekday::monday;
+    case 2:
+      return weekday::tuesday;
+    case 3:
+      return weekday::wednesday;
+    case 4:
+      return weekday::thursday;
+    case 5:
+      return weekday::friday;
+    case 6:
+      return weekday::saturday;
+  }
+  return weekday::sunday; /*NOTREACHED*/
+}
+
 std::tm ToTM(const time_zone::absolute_lookup& al) {
   std::tm tm{};
   tm.tm_sec = al.cs.second();
@@ -82,34 +126,19 @@
     tm.tm_year = static_cast<int>(al.cs.year() - 1900);
   }
 
-  switch (get_weekday(al.cs)) {
-    case weekday::sunday:
-      tm.tm_wday = 0;
-      break;
-    case weekday::monday:
-      tm.tm_wday = 1;
-      break;
-    case weekday::tuesday:
-      tm.tm_wday = 2;
-      break;
-    case weekday::wednesday:
-      tm.tm_wday = 3;
-      break;
-    case weekday::thursday:
-      tm.tm_wday = 4;
-      break;
-    case weekday::friday:
-      tm.tm_wday = 5;
-      break;
-    case weekday::saturday:
-      tm.tm_wday = 6;
-      break;
-  }
+  tm.tm_wday = ToTmWday(get_weekday(al.cs));
   tm.tm_yday = get_yearday(al.cs) - 1;
   tm.tm_isdst = al.is_dst ? 1 : 0;
   return tm;
 }
 
+// Returns the week of the year [0:53] given a civil day and the day on
+// which weeks are defined to start.
+int ToWeek(const civil_day& cd, weekday week_start) {
+  const civil_day d(cd.year() % 400, cd.month(), cd.day());
+  return static_cast<int>((d - prev_weekday(civil_year(d), week_start)) / 7);
+}
+
 const char kDigits[] = "0123456789";
 
 // Formats a 64-bit integer in the given field width.  Note that it is up
@@ -187,7 +216,7 @@
   // strftime(3) returns the number of characters placed in the output
   // array (which may be 0 characters).  It also returns 0 to indicate
   // an error, like the array wasn't large enough.  To accommodate this,
-  // the following code grows the buffer size from 2x the format std::string
+  // the following code grows the buffer size from 2x the format string
   // length up to 32x.
   for (std::size_t i = 2; i != 32; i *= 2) {
     std::size_t buf_size = fmt.size() * i;
@@ -288,6 +317,7 @@
 //   - %E#S - Seconds with # digits of fractional precision
 //   - %E*S - Seconds with full fractional precision (a literal '*')
 //   - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
+//   - %ET  - The RFC3339 "date-time" separator "T"
 //
 // The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are
 // handled internally for performance reasons.  strftime(3) is slow due to
@@ -352,7 +382,7 @@
     if (cur == end || (cur - percent) % 2 == 0) continue;
 
     // Simple specifiers that we handle ourselves.
-    if (strchr("YmdeHMSzZs%", *cur)) {
+    if (strchr("YmdeUuWwHMSzZs%", *cur)) {
       if (cur - 1 != pending) {
         FormatTM(&result, std::string(pending, cur - 1), tm);
       }
@@ -373,6 +403,22 @@
           if (*cur == 'e' && *bp == '0') *bp = ' ';  // for Windows
           result.append(bp, static_cast<std::size_t>(ep - bp));
           break;
+        case 'U':
+          bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::sunday));
+          result.append(bp, static_cast<std::size_t>(ep - bp));
+          break;
+        case 'u':
+          bp = Format64(ep, 0, tm.tm_wday ? tm.tm_wday : 7);
+          result.append(bp, static_cast<std::size_t>(ep - bp));
+          break;
+        case 'W':
+          bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::monday));
+          result.append(bp, static_cast<std::size_t>(ep - bp));
+          break;
+        case 'w':
+          bp = Format64(ep, 0, tm.tm_wday);
+          result.append(bp, static_cast<std::size_t>(ep - bp));
+          break;
         case 'H':
           bp = Format02d(ep, al.cs.hour());
           result.append(bp, static_cast<std::size_t>(ep - bp));
@@ -446,7 +492,14 @@
     if (*cur != 'E' || ++cur == end) continue;
 
     // Format our extensions.
-    if (*cur == 'z') {
+    if (*cur == 'T') {
+      // Formats %ET.
+      if (cur - 2 != pending) {
+        FormatTM(&result, std::string(pending, cur - 2), tm);
+      }
+      result.append("T");
+      pending = ++cur;
+    } else if (*cur == 'z') {
       // Formats %Ez.
       if (cur - 2 != pending) {
         FormatTM(&result, std::string(pending, cur - 2), tm);
@@ -502,8 +555,9 @@
           bp = ep;
           if (n > 0) {
             if (n > kDigits10_64) n = kDigits10_64;
-            bp = Format64(bp, n, (n > 15) ? fs.count() * kExp10[n - 15]
-                                          : fs.count() / kExp10[15 - n]);
+            bp = Format64(bp, n,
+                          (n > 15) ? fs.count() * kExp10[n - 15]
+                                   : fs.count() / kExp10[15 - n]);
             if (*np == 'S') *--bp = '.';
           }
           if (*np == 'S') bp = Format02d(bp, al.cs.second());
@@ -548,7 +602,7 @@
       } else {
         dp = nullptr;
       }
-    } else if (first == 'Z') {  // Zulu
+    } else if (first == 'Z' || first == 'z') {  // Zulu
       *offset = 0;
     } else {
       dp = nullptr;
@@ -599,12 +653,32 @@
   return dp;
 }
 
+// Sets year, tm_mon and tm_mday given the year, week_num, and tm_wday,
+// and the day on which weeks are defined to start.  Returns false if year
+// would need to move outside its bounds.
+bool FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) {
+  const civil_year y(*year % 400);
+  civil_day cd = prev_weekday(y, week_start);  // week 0
+  cd = next_weekday(cd - 1, FromTmWday(tm->tm_wday)) + (week_num * 7);
+  if (const year_t shift = cd.year() - y.year()) {
+    if (shift > 0) {
+      if (*year > std::numeric_limits<year_t>::max() - shift) return false;
+    } else {
+      if (*year < std::numeric_limits<year_t>::min() - shift) return false;
+    }
+    *year += shift;
+  }
+  tm->tm_mon = cd.month() - 1;
+  tm->tm_mday = cd.day();
+  return true;
+}
+
 }  // namespace
 
 // Uses strptime(3) to parse the given input.  Supports the same extended
 // format specifiers as format(), although %E#S and %E*S are treated
 // identically (and similarly for %E#f and %E*f).  %Ez and %E*z also accept
-// the same inputs.
+// the same inputs. %ET accepts either 'T' or 't'.
 //
 // The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are
 // handled internally so that we can normally avoid strptime() altogether
@@ -648,6 +722,8 @@
   const char* fmt = format.c_str();  // NUL terminated
   bool twelve_hour = false;
   bool afternoon = false;
+  int week_num = -1;
+  weekday week_start = weekday::sunday;
 
   bool saw_percent_s = false;
   std::int_fast64_t percent_s = 0;
@@ -686,10 +762,27 @@
       case 'm':
         data = ParseInt(data, 2, 1, 12, &tm.tm_mon);
         if (data != nullptr) tm.tm_mon -= 1;
+        week_num = -1;
         continue;
       case 'd':
       case 'e':
         data = ParseInt(data, 2, 1, 31, &tm.tm_mday);
+        week_num = -1;
+        continue;
+      case 'U':
+        data = ParseInt(data, 0, 0, 53, &week_num);
+        week_start = weekday::sunday;
+        continue;
+      case 'W':
+        data = ParseInt(data, 0, 0, 53, &week_num);
+        week_start = weekday::monday;
+        continue;
+      case 'u':
+        data = ParseInt(data, 0, 1, 7, &tm.tm_wday);
+        if (data != nullptr) tm.tm_wday %= 7;
+        continue;
+      case 'w':
+        data = ParseInt(data, 0, 0, 6, &tm.tm_wday);
         continue;
       case 'H':
         data = ParseInt(data, 2, 0, 23, &tm.tm_hour);
@@ -720,10 +813,9 @@
         data = ParseZone(data, &zone);
         continue;
       case 's':
-        data = ParseInt(data, 0,
-                        std::numeric_limits<std::int_fast64_t>::min(),
-                        std::numeric_limits<std::int_fast64_t>::max(),
-                        &percent_s);
+        data =
+            ParseInt(data, 0, std::numeric_limits<std::int_fast64_t>::min(),
+                     std::numeric_limits<std::int_fast64_t>::max(), &percent_s);
         if (data != nullptr) saw_percent_s = true;
         continue;
       case ':':
@@ -740,6 +832,15 @@
         data = (*data == '%' ? data + 1 : nullptr);
         continue;
       case 'E':
+        if (fmt[0] == 'T') {
+          if (*data == 'T' || *data == 't') {
+            ++data;
+            ++fmt;
+          } else {
+            data = nullptr;
+          }
+          continue;
+        }
         if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) {
           data = ParseOffset(data, ":", &offset);
           if (data != nullptr) saw_offset = true;
@@ -837,7 +938,7 @@
   // Skip any remaining whitespace.
   while (std::isspace(*data)) ++data;
 
-  // parse() must consume the entire input std::string.
+  // parse() must consume the entire input string.
   if (*data != '\0') {
     if (err != nullptr) *err = "Illegal trailing data in input string";
     return false;
@@ -872,6 +973,14 @@
     year += 1900;
   }
 
+  // Compute year, tm.tm_mon and tm.tm_mday if we parsed a week number.
+  if (week_num != -1) {
+    if (!FromWeek(week_num, week_start, &year, &tm)) {
+      if (err != nullptr) *err = "Out-of-range field";
+      return false;
+    }
+  }
+
   const int month = tm.tm_mon + 1;
   civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
 
@@ -916,4 +1025,5 @@
 }  // namespace detail
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_format_test.cc b/absl/time/internal/cctz/src/time_zone_format_test.cc
index 705ccdc..a11f93e 100644
--- a/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -12,20 +12,21 @@
 //   See the License for the specific language governing permissions and
 //   limitations under the License.
 
-#include "absl/time/internal/cctz/include/cctz/time_zone.h"
-
 #include <chrono>
 #include <iomanip>
 #include <sstream>
 #include <string>
 
-#include "absl/time/internal/cctz/include/cctz/civil_time.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/time/internal/cctz/include/cctz/civil_time.h"
+#include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
 namespace chrono = std::chrono;
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -47,11 +48,11 @@
     EXPECT_STREQ(zone, al.abbr);                                  \
   } while (0)
 
-const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
-const char RFC3339_sec[] =  "%Y-%m-%dT%H:%M:%S%Ez";
+const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez";
+const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
 
 const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
-const char RFC1123_no_wday[] =  "%d %b %Y %H:%M:%S %z";
+const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z";
 
 // A helper that tests the given format specifier by itself, and with leading
 // and trailing characters.  For example: TestFormatSpecifier(tp, "%a", "Thu").
@@ -88,8 +89,11 @@
       format(kFmt, chrono::time_point_cast<chrono::milliseconds>(t0), utc));
   EXPECT_EQ("03:04:05",
             format(kFmt, chrono::time_point_cast<chrono::seconds>(t0), utc));
-  EXPECT_EQ("03:04:05",
-            format(kFmt, chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0), utc));
+  EXPECT_EQ(
+      "03:04:05",
+      format(kFmt,
+             chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0),
+             utc));
   EXPECT_EQ("03:04:00",
             format(kFmt, chrono::time_point_cast<chrono::minutes>(t0), utc));
   EXPECT_EQ("03:00:00",
@@ -110,12 +114,10 @@
   EXPECT_EQ(
       "12:34:56.012345678901234",
       detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc));
-  EXPECT_EQ(
-      "12:34:56.001234567890123",
-      detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc));
-  EXPECT_EQ(
-      "12:34:56.000123456789012",
-      detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc));
+  EXPECT_EQ("12:34:56.001234567890123",
+            detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc));
+  EXPECT_EQ("12:34:56.000123456789012",
+            detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc));
 
   EXPECT_EQ("12:34:56.000000000000123",
             detail::format(kFmt, tp, detail::femtoseconds(123), utc));
@@ -677,6 +679,34 @@
   EXPECT_EQ("28 Jun 1977 09:08:07 -0700", format(RFC1123_no_wday, tp, tz));
 }
 
+TEST(Format, Week) {
+  const time_zone utc = utc_time_zone();
+
+  auto tp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc);
+  EXPECT_EQ("2017-01-7", format("%Y-%U-%u", tp, utc));
+  EXPECT_EQ("2017-00-0", format("%Y-%W-%w", tp, utc));
+
+  tp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc);
+  EXPECT_EQ("2017-53-7", format("%Y-%U-%u", tp, utc));
+  EXPECT_EQ("2017-52-0", format("%Y-%W-%w", tp, utc));
+
+  tp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc);
+  EXPECT_EQ("2018-00-1", format("%Y-%U-%u", tp, utc));
+  EXPECT_EQ("2018-01-1", format("%Y-%W-%w", tp, utc));
+
+  tp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc);
+  EXPECT_EQ("2018-52-1", format("%Y-%U-%u", tp, utc));
+  EXPECT_EQ("2018-53-1", format("%Y-%W-%w", tp, utc));
+
+  tp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc);
+  EXPECT_EQ("2019-00-2", format("%Y-%U-%u", tp, utc));
+  EXPECT_EQ("2019-00-2", format("%Y-%W-%w", tp, utc));
+
+  tp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
+  EXPECT_EQ("2019-52-2", format("%Y-%U-%u", tp, utc));
+  EXPECT_EQ("2019-52-2", format("%Y-%W-%w", tp, utc));
+}
+
 //
 // Testing parse()
 //
@@ -765,7 +795,7 @@
   EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
   time_point<chrono::nanoseconds> tp;
 
-  // We can parse a std::string without a UTC offset if we supply a timezone.
+  // We can parse a string without a UTC offset if we supply a timezone.
   EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &tp));
   ExpectTime(tp, tz, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true, "PDT");
 
@@ -1250,9 +1280,9 @@
         const auto expected = chrono::system_clock::from_time_t(0) +
                               chrono::nanoseconds(micros * 1000 + ns);
         for (int ps = 0; ps < 1000; ps += 250) {
-          std::ostringstream oss;
+          std::ostringstream ps_oss;
           oss << std::setfill('0') << std::setw(3) << ps;
-          const std::string input = nanos + oss.str() + "999";
+          const std::string input = nanos + ps_oss.str() + "999";
           EXPECT_TRUE(parse("%E*f", input, tz, &tp));
           EXPECT_EQ(expected + chrono::nanoseconds(ps) / 1000, tp) << input;
         }
@@ -1377,10 +1407,85 @@
   EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00+00:00", tz, &tp));
   ExpectTime(tp, tz, 2014, 2, 12, 20, 21, 0, 0, false, "UTC");
 
-  // Check that %Ez also accepts "Z" as a synonym for "+00:00".
+  // Check that %ET also accepts "t".
   time_point<chrono::nanoseconds> tp2;
-  EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp2));
+  EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12t20:21:00+00:00", tz, &tp2));
   EXPECT_EQ(tp, tp2);
+
+  // Check that %Ez also accepts "Z" as a synonym for "+00:00".
+  time_point<chrono::nanoseconds> tp3;
+  EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp3));
+  EXPECT_EQ(tp, tp3);
+
+  // Check that %Ez also accepts "z" as a synonym for "+00:00".
+  time_point<chrono::nanoseconds> tp4;
+  EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00z", tz, &tp4));
+  EXPECT_EQ(tp, tp4);
+}
+
+TEST(Parse, Week) {
+  const time_zone utc = utc_time_zone();
+  time_point<absl::time_internal::cctz::seconds> tp;
+
+  auto exp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc);
+  EXPECT_TRUE(parse("%Y-%U-%u", "2017-01-7", utc, &tp));
+  EXPECT_EQ(exp, tp);
+  EXPECT_TRUE(parse("%Y-%W-%w", "2017-00-0", utc, &tp));
+  EXPECT_EQ(exp, tp);
+
+  exp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc);
+  EXPECT_TRUE(parse("%Y-%U-%u", "2017-53-7", utc, &tp));
+  EXPECT_EQ(exp, tp);
+  EXPECT_TRUE(parse("%Y-%W-%w", "2017-52-0", utc, &tp));
+  EXPECT_EQ(exp, tp);
+
+  exp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc);
+  EXPECT_TRUE(parse("%Y-%U-%u", "2018-00-1", utc, &tp));
+  EXPECT_EQ(exp, tp);
+  EXPECT_TRUE(parse("%Y-%W-%w", "2018-01-1", utc, &tp));
+  EXPECT_EQ(exp, tp);
+
+  exp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc);
+  EXPECT_TRUE(parse("%Y-%U-%u", "2018-52-1", utc, &tp));
+  EXPECT_EQ(exp, tp);
+  EXPECT_TRUE(parse("%Y-%W-%w", "2018-53-1", utc, &tp));
+  EXPECT_EQ(exp, tp);
+
+  exp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc);
+  EXPECT_TRUE(parse("%Y-%U-%u", "2019-00-2", utc, &tp));
+  EXPECT_EQ(exp, tp);
+  EXPECT_TRUE(parse("%Y-%W-%w", "2019-00-2", utc, &tp));
+  EXPECT_EQ(exp, tp);
+
+  exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
+  EXPECT_TRUE(parse("%Y-%U-%u", "2019-52-2", utc, &tp));
+  EXPECT_EQ(exp, tp);
+  EXPECT_TRUE(parse("%Y-%W-%w", "2019-52-2", utc, &tp));
+  EXPECT_EQ(exp, tp);
+}
+
+TEST(Parse, WeekYearShift) {
+  // %U/%W conversions with week values in {0, 52, 53} can slip
+  // into the previous/following calendar years.
+  const time_zone utc = utc_time_zone();
+  time_point<absl::time_internal::cctz::seconds> tp;
+
+  auto exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
+  EXPECT_TRUE(parse("%Y-%U-%u", "2020-00-2", utc, &tp));
+  EXPECT_EQ(exp, tp);
+  EXPECT_TRUE(parse("%Y-%W-%w", "2020-00-2", utc, &tp));
+  EXPECT_EQ(exp, tp);
+
+  exp = convert(civil_second(2021, 1, 1, 0, 0, 0), utc);
+  EXPECT_TRUE(parse("%Y-%U-%u", "2020-52-5", utc, &tp));
+  EXPECT_EQ(exp, tp);
+  EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp));
+  EXPECT_EQ(exp, tp);
+
+  // Slipping into the previous/following calendar years should fail when
+  // we're already at the extremes.
+  EXPECT_FALSE(parse("%Y-%U-%u", "-9223372036854775808-0-7", utc, &tp));
+  EXPECT_FALSE(parse("%Y-%U-%u", "9223372036854775807-53-7", utc, &tp));
 }
 
 TEST(Parse, MaxRange) {
@@ -1416,8 +1521,8 @@
       parse(RFC3339_sec, "-292277022657-01-27T08:29:51+01:00", utc, &tp));
 
   // tests max/min civil-second overflow
-  EXPECT_FALSE(parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01",
-                     utc, &tp));
+  EXPECT_FALSE(
+      parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01", utc, &tp));
   EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01",
                      utc, &tp));
 
@@ -1474,7 +1579,8 @@
 
 TEST(FormatParse, RoundTripDistantFuture) {
   const time_zone utc = utc_time_zone();
-  const time_point<absl::time_internal::cctz::seconds> in = time_point<absl::time_internal::cctz::seconds>::max();
+  const time_point<absl::time_internal::cctz::seconds> in =
+      time_point<absl::time_internal::cctz::seconds>::max();
   const std::string s = format(RFC3339_full, in, utc);
   time_point<absl::time_internal::cctz::seconds> out;
   EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
@@ -1483,7 +1589,8 @@
 
 TEST(FormatParse, RoundTripDistantPast) {
   const time_zone utc = utc_time_zone();
-  const time_point<absl::time_internal::cctz::seconds> in = time_point<absl::time_internal::cctz::seconds>::min();
+  const time_point<absl::time_internal::cctz::seconds> in =
+      time_point<absl::time_internal::cctz::seconds>::min();
   const std::string s = format(RFC3339_full, in, utc);
   time_point<absl::time_internal::cctz::seconds> out;
   EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
@@ -1492,4 +1599,5 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_if.cc b/absl/time/internal/cctz/src/time_zone_if.cc
index 09aaee5..0319b2f 100644
--- a/absl/time/internal/cctz/src/time_zone_if.cc
+++ b/absl/time/internal/cctz/src/time_zone_if.cc
@@ -13,10 +13,13 @@
 //   limitations under the License.
 
 #include "time_zone_if.h"
+
+#include "absl/base/config.h"
 #include "time_zone_info.h"
 #include "time_zone_libc.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -38,4 +41,5 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_if.h b/absl/time/internal/cctz/src/time_zone_if.h
index d000b7a..32c0891 100644
--- a/absl/time/internal/cctz/src/time_zone_if.h
+++ b/absl/time/internal/cctz/src/time_zone_if.h
@@ -20,10 +20,12 @@
 #include <memory>
 #include <string>
 
+#include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -38,8 +40,7 @@
 
   virtual time_zone::absolute_lookup BreakTime(
       const time_point<seconds>& tp) const = 0;
-  virtual time_zone::civil_lookup MakeTime(
-      const civil_second& cs) const = 0;
+  virtual time_zone::civil_lookup MakeTime(const civil_second& cs) const = 0;
 
   virtual bool NextTransition(const time_point<seconds>& tp,
                               time_zone::civil_transition* trans) const = 0;
@@ -58,15 +59,18 @@
 // Unix clock are second aligned, but not that they share an epoch.
 inline std::int_fast64_t ToUnixSeconds(const time_point<seconds>& tp) {
   return (tp - std::chrono::time_point_cast<seconds>(
-                   std::chrono::system_clock::from_time_t(0))).count();
+                   std::chrono::system_clock::from_time_t(0)))
+      .count();
 }
 inline time_point<seconds> FromUnixSeconds(std::int_fast64_t t) {
   return std::chrono::time_point_cast<seconds>(
-             std::chrono::system_clock::from_time_t(0)) + seconds(t);
+             std::chrono::system_clock::from_time_t(0)) +
+         seconds(t);
 }
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_
diff --git a/absl/time/internal/cctz/src/time_zone_impl.cc b/absl/time/internal/cctz/src/time_zone_impl.cc
index a26151d..f34e3ae 100644
--- a/absl/time/internal/cctz/src/time_zone_impl.cc
+++ b/absl/time/internal/cctz/src/time_zone_impl.cc
@@ -14,14 +14,18 @@
 
 #include "time_zone_impl.h"
 
+#include <deque>
+#include <memory>
 #include <mutex>
 #include <string>
 #include <unordered_map>
 #include <utility>
 
+#include "absl/base/config.h"
 #include "time_zone_fixed.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -42,22 +46,19 @@
 
 }  // namespace
 
-time_zone time_zone::Impl::UTC() {
-  return time_zone(UTCImpl());
-}
+time_zone time_zone::Impl::UTC() { return time_zone(UTCImpl()); }
 
 bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) {
-  const time_zone::Impl* const utc_impl = UTCImpl();
+  const Impl* const utc_impl = UTCImpl();
 
-  // First check for UTC (which is never a key in time_zone_map).
+  // Check for UTC (which is never a key in time_zone_map).
   auto offset = seconds::zero();
   if (FixedOffsetFromName(name, &offset) && offset == seconds::zero()) {
     *tz = time_zone(utc_impl);
     return true;
   }
 
-  // Then check, under a shared lock, whether the time zone has already
-  // been loaded. This is the common path. TODO: Move to shared_mutex.
+  // Check whether the time zone has already been loaded.
   {
     std::lock_guard<std::mutex> lock(TimeZoneMutex());
     if (time_zone_map != nullptr) {
@@ -69,20 +70,15 @@
     }
   }
 
-  // Now check again, under an exclusive lock.
+  // Load the new time zone (outside the lock).
+  std::unique_ptr<const Impl> new_impl(new Impl(name));
+
+  // Add the new time zone to the map.
   std::lock_guard<std::mutex> lock(TimeZoneMutex());
   if (time_zone_map == nullptr) time_zone_map = new TimeZoneImplByName;
   const Impl*& impl = (*time_zone_map)[name];
-  if (impl == nullptr) {
-    // The first thread in loads the new time zone.
-    Impl* new_impl = new Impl(name);
-    new_impl->zone_ = TimeZoneIf::Load(new_impl->name_);
-    if (new_impl->zone_ == nullptr) {
-      delete new_impl;  // free the nascent Impl
-      impl = utc_impl;  // and fallback to UTC
-    } else {
-      impl = new_impl;  // install new time zone
-    }
+  if (impl == nullptr) {  // this thread won any load race
+    impl = new_impl->zone_ ? new_impl.release() : utc_impl;
   }
   *tz = time_zone(impl);
   return impl != utc_impl;
@@ -91,23 +87,27 @@
 void time_zone::Impl::ClearTimeZoneMapTestOnly() {
   std::lock_guard<std::mutex> lock(TimeZoneMutex());
   if (time_zone_map != nullptr) {
-    // Existing time_zone::Impl* entries are in the wild, so we simply
-    // leak them.  Future requests will result in reloading the data.
+    // Existing time_zone::Impl* entries are in the wild, so we can't delete
+    // them. Instead, we move them to a private container, where they are
+    // logically unreachable but not "leaked".  Future requests will result
+    // in reloading the data.
+    static auto* cleared = new std::deque<const time_zone::Impl*>;
+    for (const auto& element : *time_zone_map) {
+      cleared->push_back(element.second);
+    }
     time_zone_map->clear();
   }
 }
 
-time_zone::Impl::Impl(const std::string& name) : name_(name) {}
+time_zone::Impl::Impl(const std::string& name)
+    : name_(name), zone_(TimeZoneIf::Load(name_)) {}
 
 const time_zone::Impl* time_zone::Impl::UTCImpl() {
-  static Impl* utc_impl = [] {
-    Impl* impl = new Impl("UTC");
-    impl->zone_ = TimeZoneIf::Load(impl->name_);  // never fails
-    return impl;
-  }();
+  static const Impl* utc_impl = new Impl("UTC");  // never fails
   return utc_impl;
 }
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_impl.h b/absl/time/internal/cctz/src/time_zone_impl.h
index b73fad9..7d747ba 100644
--- a/absl/time/internal/cctz/src/time_zone_impl.h
+++ b/absl/time/internal/cctz/src/time_zone_impl.h
@@ -18,12 +18,14 @@
 #include <memory>
 #include <string>
 
+#include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 #include "time_zone_if.h"
 #include "time_zone_info.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -69,7 +71,7 @@
     return zone_->PrevTransition(tp, trans);
   }
 
-  // Returns an implementation-defined version std::string for this time zone.
+  // Returns an implementation-defined version string for this time zone.
   std::string Version() const { return zone_->Version(); }
 
   // Returns an implementation-defined description of this time zone.
@@ -85,6 +87,7 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_
diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc
index 9db72e0..8039353 100644
--- a/absl/time/internal/cctz/src/time_zone_info.cc
+++ b/absl/time/internal/cctz/src/time_zone_info.cc
@@ -40,16 +40,17 @@
 #include <cstdlib>
 #include <cstring>
 #include <functional>
-#include <iostream>
 #include <memory>
 #include <sstream>
 #include <string>
 
+#include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
 #include "time_zone_fixed.h"
 #include "time_zone_posix.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -65,8 +66,8 @@
 // The day offsets of the beginning of each (1-based) month in non-leap and
 // leap years respectively (e.g., 335 days before December in a leap year).
 const std::int_least16_t kMonthOffsets[2][1 + 12 + 1] = {
-  {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
-  {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
+    {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
+    {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
 };
 
 // We reject leap-second encoded zoneinfo and so assume 60-second minutes.
@@ -77,10 +78,31 @@
 
 // Like kDaysPerYear[] but scaled up by a factor of kSecsPerDay.
 const std::int_least32_t kSecsPerYear[2] = {
-  365 * kSecsPerDay,
-  366 * kSecsPerDay,
+    365 * kSecsPerDay,
+    366 * kSecsPerDay,
 };
 
+// Convert a cctz::weekday to a POSIX TZ weekday number (0==Sun, ..., 6=Sat).
+inline int ToPosixWeekday(weekday wd) {
+  switch (wd) {
+    case weekday::sunday:
+      return 0;
+    case weekday::monday:
+      return 1;
+    case weekday::tuesday:
+      return 2;
+    case weekday::wednesday:
+      return 3;
+    case weekday::thursday:
+      return 4;
+    case weekday::friday:
+      return 5;
+    case weekday::saturday:
+      return 6;
+  }
+  return 0; /*NOTREACHED*/
+}
+
 // Single-byte, unsigned numeric values are encoded directly.
 inline std::uint_fast8_t Decode8(const char* cp) {
   return static_cast<std::uint_fast8_t>(*cp) & 0xff;
@@ -172,8 +194,8 @@
 }
 
 inline civil_second YearShift(const civil_second& cs, year_t shift) {
-  return civil_second(cs.year() + shift, cs.month(), cs.day(),
-                      cs.hour(), cs.minute(), cs.second());
+  return civil_second(cs.year() + shift, cs.month(), cs.day(), cs.hour(),
+                      cs.minute(), cs.second());
 }
 
 }  // namespace
@@ -186,15 +208,13 @@
   tt.is_dst = false;
   tt.abbr_index = 0;
 
-  // We temporarily add some redundant, contemporary (2013 through 2023)
+  // We temporarily add some redundant, contemporary (2015 through 2025)
   // transitions for performance reasons.  See TimeZoneInfo::LocalTime().
   // TODO: Fix the performance issue and remove the extra transitions.
   transitions_.clear();
   transitions_.reserve(12);
   for (const std::int_fast64_t unix_time : {
-           -(1LL << 59),  // BIG_BANG
-           1356998400LL,  // 2013-01-01T00:00:00+00:00
-           1388534400LL,  // 2014-01-01T00:00:00+00:00
+           -(1LL << 59),  // a "first half" transition
            1420070400LL,  // 2015-01-01T00:00:00+00:00
            1451606400LL,  // 2016-01-01T00:00:00+00:00
            1483228800LL,  // 2017-01-01T00:00:00+00:00
@@ -204,7 +224,8 @@
            1609459200LL,  // 2021-01-01T00:00:00+00:00
            1640995200LL,  // 2022-01-01T00:00:00+00:00
            1672531200LL,  // 2023-01-01T00:00:00+00:00
-           2147483647LL,  // 2^31 - 1
+           1704067200LL,  // 2024-01-01T00:00:00+00:00
+           1735689600LL,  // 2025-01-01T00:00:00+00:00
        }) {
     Transition& tr(*transitions_.emplace(transitions_.end()));
     tr.unix_time = unix_time;
@@ -215,7 +236,7 @@
 
   default_transition_type_ = 0;
   abbreviations_ = FixedOffsetToAbbr(offset);
-  abbreviations_.append(1, '\0');  // add NUL
+  abbreviations_.append(1, '\0');
   future_spec_.clear();  // never needed for a fixed-offset zone
   extended_ = false;
 
@@ -257,21 +278,6 @@
   return len;
 }
 
-// Check that the TransitionType has the expected offset/is_dst/abbreviation.
-void TimeZoneInfo::CheckTransition(const std::string& name,
-                                   const TransitionType& tt,
-                                   std::int_fast32_t offset, bool is_dst,
-                                   const std::string& abbr) const {
-  if (tt.utc_offset != offset || tt.is_dst != is_dst ||
-      &abbreviations_[tt.abbr_index] != abbr) {
-    std::clog << name << ": Transition"
-              << " offset=" << tt.utc_offset << "/"
-              << (tt.is_dst ? "DST" : "STD")
-              << "/abbr=" << &abbreviations_[tt.abbr_index]
-              << " does not match POSIX spec '" << future_spec_ << "'\n";
-  }
-}
-
 // zic(8) can generate no-op transitions when a zone changes rules at an
 // instant when there is actually no discontinuity.  So we check whether
 // two transitions have equivalent types (same offset/is_dst/abbr).
@@ -280,144 +286,128 @@
   if (tt1_index == tt2_index) return true;
   const TransitionType& tt1(transition_types_[tt1_index]);
   const TransitionType& tt2(transition_types_[tt2_index]);
-  if (tt1.is_dst != tt2.is_dst) return false;
   if (tt1.utc_offset != tt2.utc_offset) return false;
+  if (tt1.is_dst != tt2.is_dst) return false;
   if (tt1.abbr_index != tt2.abbr_index) return false;
   return true;
 }
 
+// Find/make a transition type with these attributes.
+bool TimeZoneInfo::GetTransitionType(std::int_fast32_t utc_offset, bool is_dst,
+                                     const std::string& abbr,
+                                     std::uint_least8_t* index) {
+  std::size_t type_index = 0;
+  std::size_t abbr_index = abbreviations_.size();
+  for (; type_index != transition_types_.size(); ++type_index) {
+    const TransitionType& tt(transition_types_[type_index]);
+    const char* tt_abbr = &abbreviations_[tt.abbr_index];
+    if (tt_abbr == abbr) abbr_index = tt.abbr_index;
+    if (tt.utc_offset == utc_offset && tt.is_dst == is_dst) {
+      if (abbr_index == tt.abbr_index) break;  // reuse
+    }
+  }
+  if (type_index > 255 || abbr_index > 255) {
+    // No index space (8 bits) available for a new type or abbreviation.
+    return false;
+  }
+  if (type_index == transition_types_.size()) {
+    TransitionType& tt(*transition_types_.emplace(transition_types_.end()));
+    tt.utc_offset = static_cast<std::int_least32_t>(utc_offset);
+    tt.is_dst = is_dst;
+    if (abbr_index == abbreviations_.size()) {
+      abbreviations_.append(abbr);
+      abbreviations_.append(1, '\0');
+    }
+    tt.abbr_index = static_cast<std::uint_least8_t>(abbr_index);
+  }
+  *index = static_cast<std::uint_least8_t>(type_index);
+  return true;
+}
+
 // Use the POSIX-TZ-environment-variable-style string to handle times
 // in years after the last transition stored in the zoneinfo data.
-void TimeZoneInfo::ExtendTransitions(const std::string& name,
-                                     const Header& hdr) {
+bool TimeZoneInfo::ExtendTransitions() {
   extended_ = false;
-  bool extending = !future_spec_.empty();
+  if (future_spec_.empty()) return true;  // last transition prevails
 
   PosixTimeZone posix;
-  if (extending && !ParsePosixSpec(future_spec_, &posix)) {
-    std::clog << name << ": Failed to parse '" << future_spec_ << "'\n";
-    extending = false;
+  if (!ParsePosixSpec(future_spec_, &posix)) return false;
+
+  // Find transition type for the future std specification.
+  std::uint_least8_t std_ti;
+  if (!GetTransitionType(posix.std_offset, false, posix.std_abbr, &std_ti))
+    return false;
+
+  if (posix.dst_abbr.empty()) {  // std only
+    // The future specification should match the last transition, and
+    // that means that handling the future will fall out naturally.
+    return EquivTransitions(transitions_.back().type_index, std_ti);
   }
 
-  if (extending && posix.dst_abbr.empty()) {  // std only
-    // The future specification should match the last/default transition,
-    // and that means that handling the future will fall out naturally.
-    std::uint_fast8_t index = default_transition_type_;
-    if (hdr.timecnt != 0) index = transitions_[hdr.timecnt - 1].type_index;
-    const TransitionType& tt(transition_types_[index]);
-    CheckTransition(name, tt, posix.std_offset, false, posix.std_abbr);
-    extending = false;
-  }
-
-  if (extending && hdr.timecnt < 2) {
-    std::clog << name << ": Too few transitions for POSIX spec\n";
-    extending = false;
-  }
-
-  if (!extending) {
-    // Ensure that there is always a transition in the second half of the
-    // time line (the BIG_BANG transition is in the first half) so that the
-    // signed difference between a civil_second and the civil_second of its
-    // previous transition is always representable, without overflow.
-    const Transition& last(transitions_.back());
-    if (last.unix_time < 0) {
-      const std::uint_fast8_t type_index = last.type_index;
-      Transition& tr(*transitions_.emplace(transitions_.end()));
-      tr.unix_time = 2147483647;  // 2038-01-19T03:14:07+00:00
-      tr.type_index = type_index;
-    }
-    return;  // last transition wins
-  }
+  // Find transition type for the future dst specification.
+  std::uint_least8_t dst_ti;
+  if (!GetTransitionType(posix.dst_offset, true, posix.dst_abbr, &dst_ti))
+    return false;
 
   // Extend the transitions for an additional 400 years using the
   // future specification. Years beyond those can be handled by
   // mapping back to a cycle-equivalent year within that range.
-  // zic(8) should probably do this so that we don't have to.
-  // TODO: Reduce the extension by the number of compatible
-  // transitions already in place.
-  transitions_.reserve(hdr.timecnt + 400 * 2 + 1);
-  transitions_.resize(hdr.timecnt + 400 * 2);
+  // We may need two additional transitions for the current year.
+  transitions_.reserve(transitions_.size() + 400 * 2 + 2);
   extended_ = true;
 
-  // The future specification should match the last two transitions,
-  // and those transitions should have different is_dst flags.  Note
-  // that nothing says the UTC offset used by the is_dst transition
-  // must be greater than that used by the !is_dst transition.  (See
-  // Europe/Dublin, for example.)
-  const Transition* tr0 = &transitions_[hdr.timecnt - 1];
-  const Transition* tr1 = &transitions_[hdr.timecnt - 2];
-  const TransitionType* tt0 = &transition_types_[tr0->type_index];
-  const TransitionType* tt1 = &transition_types_[tr1->type_index];
-  const TransitionType& dst(tt0->is_dst ? *tt0 : *tt1);
-  const TransitionType& std(tt0->is_dst ? *tt1 : *tt0);
-  CheckTransition(name, dst, posix.dst_offset, true, posix.dst_abbr);
-  CheckTransition(name, std, posix.std_offset, false, posix.std_abbr);
-
-  // Add the transitions to tr1 and back to tr0 for each extra year.
-  last_year_ = LocalTime(tr0->unix_time, *tt0).cs.year();
+  const Transition& last(transitions_.back());
+  const std::int_fast64_t last_time = last.unix_time;
+  const TransitionType& last_tt(transition_types_[last.type_index]);
+  last_year_ = LocalTime(last_time, last_tt).cs.year();
   bool leap_year = IsLeap(last_year_);
-  const civil_day jan1(last_year_, 1, 1);
-  std::int_fast64_t jan1_time = civil_second(jan1) - civil_second();
-  int jan1_weekday = (static_cast<int>(get_weekday(jan1)) + 1) % 7;
-  Transition* tr = &transitions_[hdr.timecnt];  // next trans to fill
-  if (LocalTime(tr1->unix_time, *tt1).cs.year() != last_year_) {
-    // Add a single extra transition to align to a calendar year.
-    transitions_.resize(transitions_.size() + 1);
-    assert(tr == &transitions_[hdr.timecnt]);  // no reallocation
-    const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start);
-    std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1);
-    tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset;
-    tr++->type_index = tr1->type_index;
-    tr0 = &transitions_[hdr.timecnt];
-    tr1 = &transitions_[hdr.timecnt - 1];
-    tt0 = &transition_types_[tr0->type_index];
-    tt1 = &transition_types_[tr1->type_index];
-  }
-  const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start);
-  const PosixTransition& pt0(tt0->is_dst ? posix.dst_start : posix.dst_end);
-  for (const year_t limit = last_year_ + 400; last_year_ < limit;) {
-    last_year_ += 1;  // an additional year of generated transitions
+  const civil_second jan1(last_year_);
+  std::int_fast64_t jan1_time = jan1 - civil_second();
+  int jan1_weekday = ToPosixWeekday(get_weekday(jan1));
+
+  Transition dst = {0, dst_ti, civil_second(), civil_second()};
+  Transition std = {0, std_ti, civil_second(), civil_second()};
+  for (const year_t limit = last_year_ + 400;; ++last_year_) {
+    auto dst_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_start);
+    auto std_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_end);
+    dst.unix_time = jan1_time + dst_trans_off - posix.std_offset;
+    std.unix_time = jan1_time + std_trans_off - posix.dst_offset;
+    const auto* ta = dst.unix_time < std.unix_time ? &dst : &std;
+    const auto* tb = dst.unix_time < std.unix_time ? &std : &dst;
+    if (last_time < tb->unix_time) {
+      if (last_time < ta->unix_time) transitions_.push_back(*ta);
+      transitions_.push_back(*tb);
+    }
+    if (last_year_ == limit) break;
     jan1_time += kSecsPerYear[leap_year];
     jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7;
-    leap_year = !leap_year && IsLeap(last_year_);
-    std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1);
-    tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset;
-    tr++->type_index = tr1->type_index;
-    std::int_fast64_t tr0_offset = TransOffset(leap_year, jan1_weekday, pt0);
-    tr->unix_time = jan1_time + tr0_offset - tt1->utc_offset;
-    tr++->type_index = tr0->type_index;
+    leap_year = !leap_year && IsLeap(last_year_ + 1);
   }
-  assert(tr == &transitions_[0] + transitions_.size());
+
+  return true;
 }
 
-bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
+bool TimeZoneInfo::Load(ZoneInfoSource* zip) {
   // Read and validate the header.
   tzhead tzh;
-  if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh))
-    return false;
+  if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;
   if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)
     return false;
   Header hdr;
-  if (!hdr.Build(tzh))
-    return false;
+  if (!hdr.Build(tzh)) return false;
   std::size_t time_len = 4;
   if (tzh.tzh_version[0] != '\0') {
     // Skip the 4-byte data.
-    if (zip->Skip(hdr.DataLength(time_len)) != 0)
-      return false;
+    if (zip->Skip(hdr.DataLength(time_len)) != 0) return false;
     // Read and validate the header for the 8-byte data.
-    if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh))
-      return false;
+    if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;
     if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)
       return false;
-    if (tzh.tzh_version[0] == '\0')
-      return false;
-    if (!hdr.Build(tzh))
-      return false;
+    if (tzh.tzh_version[0] == '\0') return false;
+    if (!hdr.Build(tzh)) return false;
     time_len = 8;
   }
-  if (hdr.typecnt == 0)
-    return false;
+  if (hdr.typecnt == 0) return false;
   if (hdr.leapcnt != 0) {
     // This code assumes 60-second minutes so we do not want
     // the leap-second encoded zoneinfo. We could reverse the
@@ -425,20 +415,17 @@
     // so currently we simply reject such data.
     return false;
   }
-  if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt)
-    return false;
-  if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt)
-    return false;
+  if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt) return false;
+  if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt) return false;
 
   // Read the data into a local buffer.
   std::size_t len = hdr.DataLength(time_len);
   std::vector<char> tbuf(len);
-  if (zip->Read(tbuf.data(), len) != len)
-    return false;
+  if (zip->Read(tbuf.data(), len) != len) return false;
   const char* bp = tbuf.data();
 
   // Decode and validate the transitions.
-  transitions_.reserve(hdr.timecnt + 2);  // We might add a couple.
+  transitions_.reserve(hdr.timecnt + 2);
   transitions_.resize(hdr.timecnt);
   for (std::size_t i = 0; i != hdr.timecnt; ++i) {
     transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp);
@@ -452,13 +439,12 @@
   bool seen_type_0 = false;
   for (std::size_t i = 0; i != hdr.timecnt; ++i) {
     transitions_[i].type_index = Decode8(bp++);
-    if (transitions_[i].type_index >= hdr.typecnt)
-      return false;
-    if (transitions_[i].type_index == 0)
-      seen_type_0 = true;
+    if (transitions_[i].type_index >= hdr.typecnt) return false;
+    if (transitions_[i].type_index == 0) seen_type_0 = true;
   }
 
   // Decode and validate the transition types.
+  transition_types_.reserve(hdr.typecnt + 2);
   transition_types_.resize(hdr.typecnt);
   for (std::size_t i = 0; i != hdr.typecnt; ++i) {
     transition_types_[i].utc_offset =
@@ -469,8 +455,7 @@
     bp += 4;
     transition_types_[i].is_dst = (Decode8(bp++) != 0);
     transition_types_[i].abbr_index = Decode8(bp++);
-    if (transition_types_[i].abbr_index >= hdr.charcnt)
-      return false;
+    if (transition_types_[i].abbr_index >= hdr.charcnt) return false;
   }
 
   // Determine the before-first-transition type.
@@ -479,16 +464,14 @@
     std::uint_fast8_t index = 0;
     if (transition_types_[0].is_dst) {
       index = transitions_[0].type_index;
-      while (index != 0 && transition_types_[index].is_dst)
-        --index;
+      while (index != 0 && transition_types_[index].is_dst) --index;
     }
-    while (index != hdr.typecnt && transition_types_[index].is_dst)
-      ++index;
-    if (index != hdr.typecnt)
-      default_transition_type_ = index;
+    while (index != hdr.typecnt && transition_types_[index].is_dst) ++index;
+    if (index != hdr.typecnt) default_transition_type_ = index;
   }
 
   // Copy all the abbreviations.
+  abbreviations_.reserve(hdr.charcnt + 10);
   abbreviations_.assign(bp, hdr.charcnt);
   bp += hdr.charcnt;
 
@@ -509,11 +492,9 @@
       unsigned char ch;  // all non-EOF results are positive
       return (azip->Read(&ch, 1) == 1) ? ch : EOF;
     };
-    if (get_char(zip) != '\n')
-      return false;
+    if (get_char(zip) != '\n') return false;
     for (int c = get_char(zip); c != '\n'; c = get_char(zip)) {
-      if (c == EOF)
-        return false;
+      if (c == EOF) return false;
       future_spec_.push_back(static_cast<char>(c));
     }
   }
@@ -522,7 +503,7 @@
 
   // If we did not find version information during the standard loading
   // process (as of tzh_version '3' that is unsupported), then ask the
-  // ZoneInfoSource for any out-of-bound version std::string it may be privy to.
+  // ZoneInfoSource for any out-of-bound version string it may be privy to.
   if (version_.empty()) {
     version_ = zip->Version();
   }
@@ -541,19 +522,29 @@
   transitions_.resize(hdr.timecnt);
 
   // Ensure that there is always a transition in the first half of the
-  // time line (the second half is handled in ExtendTransitions()) so that
-  // the signed difference between a civil_second and the civil_second of
-  // its previous transition is always representable, without overflow.
-  // A contemporary zic will usually have already done this for us.
+  // time line (the second half is handled below) so that the signed
+  // difference between a civil_second and the civil_second of its
+  // previous transition is always representable, without overflow.
   if (transitions_.empty() || transitions_.front().unix_time >= 0) {
     Transition& tr(*transitions_.emplace(transitions_.begin()));
-    tr.unix_time = -(1LL << 59);  // see tz/zic.c "BIG_BANG"
+    tr.unix_time = -(1LL << 59);  // -18267312070-10-26T17:01:52+00:00
     tr.type_index = default_transition_type_;
-    hdr.timecnt += 1;
   }
 
   // Extend the transitions using the future specification.
-  ExtendTransitions(name, hdr);
+  if (!ExtendTransitions()) return false;
+
+  // Ensure that there is always a transition in the second half of the
+  // time line (the first half is handled above) so that the signed
+  // difference between a civil_second and the civil_second of its
+  // previous transition is always representable, without overflow.
+  const Transition& last(transitions_.back());
+  if (last.unix_time < 0) {
+    const std::uint_fast8_t type_index = last.type_index;
+    Transition& tr(*transitions_.emplace(transitions_.end()));
+    tr.unix_time = 2147483647;  // 2038-01-19T03:14:07+00:00
+    tr.type_index = type_index;
+  }
 
   // Compute the local civil time for each transition and the preceding
   // second. These will be used for reverse conversions in MakeTime().
@@ -624,18 +615,18 @@
       : fp_(fp, fclose), len_(len) {}
 
  private:
-  std::unique_ptr<FILE, int(*)(FILE*)> fp_;
+  std::unique_ptr<FILE, int (*)(FILE*)> fp_;
   std::size_t len_;
 };
 
 std::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open(
     const std::string& name) {
   // Use of the "file:" prefix is intended for testing purposes only.
-  if (name.compare(0, 5, "file:") == 0) return Open(name.substr(5));
+  const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0;
 
   // Map the time-zone name to a path name.
   std::string path;
-  if (name.empty() || name[0] != '/') {
+  if (pos == name.size() || name[pos] != '/') {
     const char* tzdir = "/usr/share/zoneinfo";
     char* tzdir_env = nullptr;
 #if defined(_MSC_VER)
@@ -650,16 +641,16 @@
     free(tzdir_env);
 #endif
   }
-  path += name;
+  path.append(name, pos, std::string::npos);
 
   // Open the zoneinfo file.
   FILE* fp = FOpen(path.c_str(), "rb");
   if (fp == nullptr) return nullptr;
   std::size_t length = 0;
   if (fseek(fp, 0, SEEK_END) == 0) {
-    long pos = ftell(fp);
-    if (pos >= 0) {
-      length = static_cast<std::size_t>(pos);
+    long offset = ftell(fp);
+    if (offset >= 0) {
+      length = static_cast<std::size_t>(offset);
     }
     rewind(fp);
   }
@@ -680,7 +671,7 @@
 std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
     const std::string& name) {
   // Use of the "file:" prefix is intended for testing purposes only.
-  if (name.compare(0, 5, "file:") == 0) return Open(name.substr(5));
+  const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0;
 
   // See Android's libc/tzcode/bionic.cpp for additional information.
   for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata",
@@ -709,7 +700,7 @@
       const std::int_fast32_t length = Decode32(ebuf + 44);
       if (start < 0 || length < 0) break;
       ebuf[40] = '\0';  // ensure zone name is NUL terminated
-      if (strcmp(name.c_str(), ebuf) == 0) {
+      if (strcmp(name.c_str() + pos, ebuf) == 0) {
         if (fseek(fp.get(), static_cast<long>(start), SEEK_SET) != 0) break;
         return std::unique_ptr<ZoneInfoSource>(new AndroidZoneInfoSource(
             fp.release(), static_cast<std::size_t>(length), vers));
@@ -734,12 +725,12 @@
 
   // Find and use a ZoneInfoSource to load the named zone.
   auto zip = cctz_extension::zone_info_source_factory(
-      name, [](const std::string& name) -> std::unique_ptr<ZoneInfoSource> {
-        if (auto zip = FileZoneInfoSource::Open(name)) return zip;
-        if (auto zip = AndroidZoneInfoSource::Open(name)) return zip;
+      name, [](const std::string& n) -> std::unique_ptr<ZoneInfoSource> {
+        if (auto z = FileZoneInfoSource::Open(n)) return z;
+        if (auto z = AndroidZoneInfoSource::Open(n)) return z;
         return nullptr;
       });
-  return zip != nullptr && Load(name, zip.get());
+  return zip != nullptr && Load(zip.get());
 }
 
 // BreakTime() translation for a particular transition type.
@@ -748,13 +739,13 @@
   // A civil time in "+offset" looks like (time+offset) in UTC.
   // Note: We perform two additions in the civil_second domain to
   // sidestep the chance of overflow in (unix_time + tt.utc_offset).
-  return {(civil_second() + unix_time) + tt.utc_offset,
-          tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};
+  return {(civil_second() + unix_time) + tt.utc_offset, tt.utc_offset,
+          tt.is_dst, &abbreviations_[tt.abbr_index]};
 }
 
 // BreakTime() translation for a particular transition.
-time_zone::absolute_lookup TimeZoneInfo::LocalTime(
-    std::int_fast64_t unix_time, const Transition& tr) const {
+time_zone::absolute_lookup TimeZoneInfo::LocalTime(std::int_fast64_t unix_time,
+                                                   const Transition& tr) const {
   const TransitionType& tt = transition_types_[tr.type_index];
   // Note: (unix_time - tr.unix_time) will never overflow as we
   // have ensured that there is always a "nearby" transition.
@@ -897,9 +888,7 @@
   return MakeUnique(tr->unix_time + (cs - tr->civil_sec));
 }
 
-std::string TimeZoneInfo::Version() const {
-  return version_;
-}
+std::string TimeZoneInfo::Version() const { return version_; }
 
 std::string TimeZoneInfo::Description() const {
   std::ostringstream oss;
@@ -915,14 +904,14 @@
   const Transition* begin = &transitions_[0];
   const Transition* end = begin + transitions_.size();
   if (begin->unix_time <= -(1LL << 59)) {
-    // Do not report the BIG_BANG found in recent zoneinfo data as it is
-    // really a sentinel, not a transition.  See tz/zic.c.
+    // Do not report the BIG_BANG found in some zoneinfo data as it is
+    // really a sentinel, not a transition.  See pre-2018f tz/zic.c.
     ++begin;
   }
   std::int_fast64_t unix_time = ToUnixSeconds(tp);
   const Transition target = {unix_time, 0, civil_second(), civil_second()};
-  const Transition* tr = std::upper_bound(begin, end, target,
-                                          Transition::ByUnixTime());
+  const Transition* tr =
+      std::upper_bound(begin, end, target, Transition::ByUnixTime());
   for (; tr != end; ++tr) {  // skip no-op transitions
     std::uint_fast8_t prev_type_index =
         (tr == begin) ? default_transition_type_ : tr[-1].type_index;
@@ -941,8 +930,8 @@
   const Transition* begin = &transitions_[0];
   const Transition* end = begin + transitions_.size();
   if (begin->unix_time <= -(1LL << 59)) {
-    // Do not report the BIG_BANG found in recent zoneinfo data as it is
-    // really a sentinel, not a transition.  See tz/zic.c.
+    // Do not report the BIG_BANG found in some zoneinfo data as it is
+    // really a sentinel, not a transition.  See pre-2018f tz/zic.c.
     ++begin;
   }
   std::int_fast64_t unix_time = ToUnixSeconds(tp);
@@ -956,8 +945,8 @@
     unix_time += 1;  // ceils
   }
   const Transition target = {unix_time, 0, civil_second(), civil_second()};
-  const Transition* tr = std::lower_bound(begin, end, target,
-                                          Transition::ByUnixTime());
+  const Transition* tr =
+      std::lower_bound(begin, end, target, Transition::ByUnixTime());
   for (; tr != begin; --tr) {  // skip no-op transitions
     std::uint_fast8_t prev_type_index =
         (tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index;
@@ -972,4 +961,5 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_info.h b/absl/time/internal/cctz/src/time_zone_info.h
index 81cd402..2467ff5 100644
--- a/absl/time/internal/cctz/src/time_zone_info.h
+++ b/absl/time/internal/cctz/src/time_zone_info.h
@@ -21,6 +21,7 @@
 #include <string>
 #include <vector>
 
+#include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 #include "absl/time/internal/cctz/include/cctz/zone_info_source.h"
@@ -28,6 +29,7 @@
 #include "tzfile.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -72,8 +74,7 @@
   // TimeZoneIf implementations.
   time_zone::absolute_lookup BreakTime(
       const time_point<seconds>& tp) const override;
-  time_zone::civil_lookup MakeTime(
-      const civil_second& cs) const override;
+  time_zone::civil_lookup MakeTime(const civil_second& cs) const override;
   bool NextTransition(const time_point<seconds>& tp,
                       time_zone::civil_transition* trans) const override;
   bool PrevTransition(const time_point<seconds>& tp,
@@ -82,7 +83,7 @@
   std::string Description() const override;
 
  private:
-  struct Header {  // counts of:
+  struct Header {            // counts of:
     std::size_t timecnt;     // transition times
     std::size_t typecnt;     // transition types
     std::size_t charcnt;     // zone abbreviation characters
@@ -94,15 +95,14 @@
     std::size_t DataLength(std::size_t time_len) const;
   };
 
-  void CheckTransition(const std::string& name, const TransitionType& tt,
-                       std::int_fast32_t offset, bool is_dst,
-                       const std::string& abbr) const;
+  bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst,
+                         const std::string& abbr, std::uint_least8_t* index);
   bool EquivTransitions(std::uint_fast8_t tt1_index,
                         std::uint_fast8_t tt2_index) const;
-  void ExtendTransitions(const std::string& name, const Header& hdr);
+  bool ExtendTransitions();
 
   bool ResetToBuiltinUTC(const seconds& offset);
-  bool Load(const std::string& name, ZoneInfoSource* zip);
+  bool Load(ZoneInfoSource* zip);
 
   // Helpers for BreakTime() and MakeTime().
   time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time,
@@ -114,7 +114,7 @@
 
   std::vector<Transition> transitions_;  // ordered by unix_time and civil_sec
   std::vector<TransitionType> transition_types_;  // distinct transition types
-  std::uint_fast8_t default_transition_type_;  // for before first transition
+  std::uint_fast8_t default_transition_type_;     // for before first transition
   std::string abbreviations_;  // all the NUL-terminated abbreviations
 
   std::string version_;      // the tzdata version if available
@@ -131,6 +131,7 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_
diff --git a/absl/time/internal/cctz/src/time_zone_libc.cc b/absl/time/internal/cctz/src/time_zone_libc.cc
index 6095e76..887dd09 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.cc
+++ b/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -23,10 +23,18 @@
 #include <limits>
 #include <utility>
 
+#include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
+#if defined(_AIX)
+extern "C" {
+extern long altzone;
+}
+#endif
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -42,7 +50,7 @@
   const bool is_dst = tm.tm_isdst > 0;
   return _tzname[is_dst];
 }
-#elif defined(__sun)
+#elif defined(__sun) || defined(_AIX)
 // Uses the globals: 'timezone', 'altzone' and 'tzname'.
 auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) {
   const bool is_dst = tm.tm_isdst > 0;
@@ -84,9 +92,7 @@
 }
 #endif  // tm_gmtoff
 #if defined(tm_zone)
-auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) {
-  return tm.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;
@@ -103,19 +109,19 @@
 #endif  // tm_zone
 #endif
 
-inline std::tm* gm_time(const std::time_t *timep, std::tm *result) {
+inline std::tm* gm_time(const std::time_t* timep, std::tm* result) {
 #if defined(_WIN32) || defined(_WIN64)
-    return gmtime_s(result, timep) ? nullptr : result;
+  return gmtime_s(result, timep) ? nullptr : result;
 #else
-    return gmtime_r(timep, result);
+  return gmtime_r(timep, result);
 #endif
 }
 
-inline std::tm* local_time(const std::time_t *timep, std::tm *result) {
+inline std::tm* local_time(const std::time_t* timep, std::tm* result) {
 #if defined(_WIN32) || defined(_WIN64)
-    return localtime_s(result, timep) ? nullptr : result;
+  return localtime_s(result, timep) ? nullptr : result;
 #else
-    return localtime_r(timep, result);
+  return localtime_r(timep, result);
 #endif
 }
 
@@ -153,7 +159,8 @@
   std::tm tm;
   while (lo + 1 != hi) {
     const std::time_t mid = lo + (hi - lo) / 2;
-    if (std::tm* tmp = local_time(&mid, &tm)) {
+    std::tm* tmp = local_time(&mid, &tm);
+    if (tmp != nullptr) {
       if (tm_gmtoff(*tmp) == offset) {
         hi = mid;
       } else {
@@ -163,7 +170,8 @@
       // If std::tm cannot hold some result we resort to a linear search,
       // ignoring all failed conversions.  Slow, but never really happens.
       while (++lo != hi) {
-        if (std::tm* tmp = local_time(&lo, &tm)) {
+        tmp = local_time(&lo, &tm);
+        if (tmp != nullptr) {
           if (tm_gmtoff(*tmp) == offset) break;
         }
       }
@@ -208,8 +216,8 @@
   }
 
   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);
+  al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour,
+                       tmp->tm_min, tmp->tm_sec);
   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;
@@ -223,11 +231,10 @@
         civil_second() + ToUnixSeconds(time_point<seconds>::min());
     static const civil_second max_tp_cs =
         civil_second() + ToUnixSeconds(time_point<seconds>::max());
-    const time_point<seconds> tp =
-        (cs < min_tp_cs)
-            ? time_point<seconds>::min()
-            : (cs > max_tp_cs) ? time_point<seconds>::max()
-                               : FromUnixSeconds(cs - civil_second());
+    const time_point<seconds> tp = (cs < min_tp_cs) ? time_point<seconds>::min()
+                                   : (cs > max_tp_cs)
+                                       ? time_point<seconds>::max()
+                                       : FromUnixSeconds(cs - civil_second());
     return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
   }
 
@@ -304,4 +311,5 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_libc.h b/absl/time/internal/cctz/src/time_zone_libc.h
index 0d18e9a..1da9039 100644
--- a/absl/time/internal/cctz/src/time_zone_libc.h
+++ b/absl/time/internal/cctz/src/time_zone_libc.h
@@ -17,9 +17,11 @@
 
 #include <string>
 
+#include "absl/base/config.h"
 #include "time_zone_if.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -33,8 +35,7 @@
   // TimeZoneIf implementations.
   time_zone::absolute_lookup BreakTime(
       const time_point<seconds>& tp) const override;
-  time_zone::civil_lookup MakeTime(
-      const civil_second& cs) const override;
+  time_zone::civil_lookup MakeTime(const civil_second& cs) const override;
   bool NextTransition(const time_point<seconds>& tp,
                       time_zone::civil_transition* trans) const override;
   bool PrevTransition(const time_point<seconds>& tp,
@@ -48,6 +49,7 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_
diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc
index 3c53dd1..efdea64 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup.cc
@@ -12,6 +12,7 @@
 //   See the License for the specific language governing permissions and
 //   limitations under the License.
 
+#include "absl/base/config.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
 #if defined(__ANDROID__)
@@ -23,6 +24,7 @@
 
 #if defined(__APPLE__)
 #include <CoreFoundation/CFTimeZone.h>
+
 #include <vector>
 #endif
 
@@ -34,6 +36,7 @@
 #include "time_zone_impl.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -66,9 +69,7 @@
 }  // namespace
 #endif
 
-std::string time_zone::name() const {
-  return effective_impl().Name();
-}
+std::string time_zone::name() const { return effective_impl().Name(); }
 
 time_zone::absolute_lookup time_zone::lookup(
     const time_point<seconds>& tp) const {
@@ -89,9 +90,7 @@
   return effective_impl().PrevTransition(tp, trans);
 }
 
-std::string time_zone::version() const {
-  return effective_impl().Version();
-}
+std::string time_zone::version() const { return effective_impl().Version(); }
 
 std::string time_zone::description() const {
   return effective_impl().Description();
@@ -184,4 +183,5 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
index 42dd6d5..9a1a8d6 100644
--- a/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -12,8 +12,6 @@
 //   See the License for the specific language governing permissions and
 //   limitations under the License.
 
-#include "absl/time/internal/cctz/include/cctz/time_zone.h"
-
 #include <chrono>
 #include <cstddef>
 #include <cstdlib>
@@ -23,613 +21,615 @@
 #include <thread>
 #include <vector>
 
-#include "absl/time/internal/cctz/include/cctz/civil_time.h"
 #include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/time/internal/cctz/include/cctz/civil_time.h"
+#include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
 namespace chrono = std::chrono;
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
 namespace {
 
 // A list of known time-zone names.
-const char* const kTimeZoneNames[] = {
-  "Africa/Abidjan",
-  "Africa/Accra",
-  "Africa/Addis_Ababa",
-  "Africa/Algiers",
-  "Africa/Asmara",
-  "Africa/Asmera",
-  "Africa/Bamako",
-  "Africa/Bangui",
-  "Africa/Banjul",
-  "Africa/Bissau",
-  "Africa/Blantyre",
-  "Africa/Brazzaville",
-  "Africa/Bujumbura",
-  "Africa/Cairo",
-  "Africa/Casablanca",
-  "Africa/Ceuta",
-  "Africa/Conakry",
-  "Africa/Dakar",
-  "Africa/Dar_es_Salaam",
-  "Africa/Djibouti",
-  "Africa/Douala",
-  "Africa/El_Aaiun",
-  "Africa/Freetown",
-  "Africa/Gaborone",
-  "Africa/Harare",
-  "Africa/Johannesburg",
-  "Africa/Juba",
-  "Africa/Kampala",
-  "Africa/Khartoum",
-  "Africa/Kigali",
-  "Africa/Kinshasa",
-  "Africa/Lagos",
-  "Africa/Libreville",
-  "Africa/Lome",
-  "Africa/Luanda",
-  "Africa/Lubumbashi",
-  "Africa/Lusaka",
-  "Africa/Malabo",
-  "Africa/Maputo",
-  "Africa/Maseru",
-  "Africa/Mbabane",
-  "Africa/Mogadishu",
-  "Africa/Monrovia",
-  "Africa/Nairobi",
-  "Africa/Ndjamena",
-  "Africa/Niamey",
-  "Africa/Nouakchott",
-  "Africa/Ouagadougou",
-  "Africa/Porto-Novo",
-  "Africa/Sao_Tome",
-  "Africa/Timbuktu",
-  "Africa/Tripoli",
-  "Africa/Tunis",
-  "Africa/Windhoek",
-  "America/Adak",
-  "America/Anchorage",
-  "America/Anguilla",
-  "America/Antigua",
-  "America/Araguaina",
-  "America/Argentina/Buenos_Aires",
-  "America/Argentina/Catamarca",
-  "America/Argentina/ComodRivadavia",
-  "America/Argentina/Cordoba",
-  "America/Argentina/Jujuy",
-  "America/Argentina/La_Rioja",
-  "America/Argentina/Mendoza",
-  "America/Argentina/Rio_Gallegos",
-  "America/Argentina/Salta",
-  "America/Argentina/San_Juan",
-  "America/Argentina/San_Luis",
-  "America/Argentina/Tucuman",
-  "America/Argentina/Ushuaia",
-  "America/Aruba",
-  "America/Asuncion",
-  "America/Atikokan",
-  "America/Atka",
-  "America/Bahia",
-  "America/Bahia_Banderas",
-  "America/Barbados",
-  "America/Belem",
-  "America/Belize",
-  "America/Blanc-Sablon",
-  "America/Boa_Vista",
-  "America/Bogota",
-  "America/Boise",
-  "America/Buenos_Aires",
-  "America/Cambridge_Bay",
-  "America/Campo_Grande",
-  "America/Cancun",
-  "America/Caracas",
-  "America/Catamarca",
-  "America/Cayenne",
-  "America/Cayman",
-  "America/Chicago",
-  "America/Chihuahua",
-  "America/Coral_Harbour",
-  "America/Cordoba",
-  "America/Costa_Rica",
-  "America/Creston",
-  "America/Cuiaba",
-  "America/Curacao",
-  "America/Danmarkshavn",
-  "America/Dawson",
-  "America/Dawson_Creek",
-  "America/Denver",
-  "America/Detroit",
-  "America/Dominica",
-  "America/Edmonton",
-  "America/Eirunepe",
-  "America/El_Salvador",
-  "America/Ensenada",
-  "America/Fort_Nelson",
-  "America/Fort_Wayne",
-  "America/Fortaleza",
-  "America/Glace_Bay",
-  "America/Godthab",
-  "America/Goose_Bay",
-  "America/Grand_Turk",
-  "America/Grenada",
-  "America/Guadeloupe",
-  "America/Guatemala",
-  "America/Guayaquil",
-  "America/Guyana",
-  "America/Halifax",
-  "America/Havana",
-  "America/Hermosillo",
-  "America/Indiana/Indianapolis",
-  "America/Indiana/Knox",
-  "America/Indiana/Marengo",
-  "America/Indiana/Petersburg",
-  "America/Indiana/Tell_City",
-  "America/Indiana/Vevay",
-  "America/Indiana/Vincennes",
-  "America/Indiana/Winamac",
-  "America/Indianapolis",
-  "America/Inuvik",
-  "America/Iqaluit",
-  "America/Jamaica",
-  "America/Jujuy",
-  "America/Juneau",
-  "America/Kentucky/Louisville",
-  "America/Kentucky/Monticello",
-  "America/Knox_IN",
-  "America/Kralendijk",
-  "America/La_Paz",
-  "America/Lima",
-  "America/Los_Angeles",
-  "America/Louisville",
-  "America/Lower_Princes",
-  "America/Maceio",
-  "America/Managua",
-  "America/Manaus",
-  "America/Marigot",
-  "America/Martinique",
-  "America/Matamoros",
-  "America/Mazatlan",
-  "America/Mendoza",
-  "America/Menominee",
-  "America/Merida",
-  "America/Metlakatla",
-  "America/Mexico_City",
-  "America/Miquelon",
-  "America/Moncton",
-  "America/Monterrey",
-  "America/Montevideo",
-  "America/Montreal",
-  "America/Montserrat",
-  "America/Nassau",
-  "America/New_York",
-  "America/Nipigon",
-  "America/Nome",
-  "America/Noronha",
-  "America/North_Dakota/Beulah",
-  "America/North_Dakota/Center",
-  "America/North_Dakota/New_Salem",
-  "America/Ojinaga",
-  "America/Panama",
-  "America/Pangnirtung",
-  "America/Paramaribo",
-  "America/Phoenix",
-  "America/Port-au-Prince",
-  "America/Port_of_Spain",
-  "America/Porto_Acre",
-  "America/Porto_Velho",
-  "America/Puerto_Rico",
-  "America/Punta_Arenas",
-  "America/Rainy_River",
-  "America/Rankin_Inlet",
-  "America/Recife",
-  "America/Regina",
-  "America/Resolute",
-  "America/Rio_Branco",
-  "America/Rosario",
-  "America/Santa_Isabel",
-  "America/Santarem",
-  "America/Santiago",
-  "America/Santo_Domingo",
-  "America/Sao_Paulo",
-  "America/Scoresbysund",
-  "America/Shiprock",
-  "America/Sitka",
-  "America/St_Barthelemy",
-  "America/St_Johns",
-  "America/St_Kitts",
-  "America/St_Lucia",
-  "America/St_Thomas",
-  "America/St_Vincent",
-  "America/Swift_Current",
-  "America/Tegucigalpa",
-  "America/Thule",
-  "America/Thunder_Bay",
-  "America/Tijuana",
-  "America/Toronto",
-  "America/Tortola",
-  "America/Vancouver",
-  "America/Virgin",
-  "America/Whitehorse",
-  "America/Winnipeg",
-  "America/Yakutat",
-  "America/Yellowknife",
-  "Antarctica/Casey",
-  "Antarctica/Davis",
-  "Antarctica/DumontDUrville",
-  "Antarctica/Macquarie",
-  "Antarctica/Mawson",
-  "Antarctica/McMurdo",
-  "Antarctica/Palmer",
-  "Antarctica/Rothera",
-  "Antarctica/South_Pole",
-  "Antarctica/Syowa",
-  "Antarctica/Troll",
-  "Antarctica/Vostok",
-  "Arctic/Longyearbyen",
-  "Asia/Aden",
-  "Asia/Almaty",
-  "Asia/Amman",
-  "Asia/Anadyr",
-  "Asia/Aqtau",
-  "Asia/Aqtobe",
-  "Asia/Ashgabat",
-  "Asia/Ashkhabad",
-  "Asia/Atyrau",
-  "Asia/Baghdad",
-  "Asia/Bahrain",
-  "Asia/Baku",
-  "Asia/Bangkok",
-  "Asia/Barnaul",
-  "Asia/Beirut",
-  "Asia/Bishkek",
-  "Asia/Brunei",
-  "Asia/Calcutta",
-  "Asia/Chita",
-  "Asia/Choibalsan",
-  "Asia/Chongqing",
-  "Asia/Chungking",
-  "Asia/Colombo",
-  "Asia/Dacca",
-  "Asia/Damascus",
-  "Asia/Dhaka",
-  "Asia/Dili",
-  "Asia/Dubai",
-  "Asia/Dushanbe",
-  "Asia/Famagusta",
-  "Asia/Gaza",
-  "Asia/Harbin",
-  "Asia/Hebron",
-  "Asia/Ho_Chi_Minh",
-  "Asia/Hong_Kong",
-  "Asia/Hovd",
-  "Asia/Irkutsk",
-  "Asia/Istanbul",
-  "Asia/Jakarta",
-  "Asia/Jayapura",
-  "Asia/Jerusalem",
-  "Asia/Kabul",
-  "Asia/Kamchatka",
-  "Asia/Karachi",
-  "Asia/Kashgar",
-  "Asia/Kathmandu",
-  "Asia/Katmandu",
-  "Asia/Khandyga",
-  "Asia/Kolkata",
-  "Asia/Krasnoyarsk",
-  "Asia/Kuala_Lumpur",
-  "Asia/Kuching",
-  "Asia/Kuwait",
-  "Asia/Macao",
-  "Asia/Macau",
-  "Asia/Magadan",
-  "Asia/Makassar",
-  "Asia/Manila",
-  "Asia/Muscat",
-  "Asia/Nicosia",
-  "Asia/Novokuznetsk",
-  "Asia/Novosibirsk",
-  "Asia/Omsk",
-  "Asia/Oral",
-  "Asia/Phnom_Penh",
-  "Asia/Pontianak",
-  "Asia/Pyongyang",
-  "Asia/Qatar",
-  "Asia/Qostanay",
-  "Asia/Qyzylorda",
-  "Asia/Rangoon",
-  "Asia/Riyadh",
-  "Asia/Saigon",
-  "Asia/Sakhalin",
-  "Asia/Samarkand",
-  "Asia/Seoul",
-  "Asia/Shanghai",
-  "Asia/Singapore",
-  "Asia/Srednekolymsk",
-  "Asia/Taipei",
-  "Asia/Tashkent",
-  "Asia/Tbilisi",
-  "Asia/Tehran",
-  "Asia/Tel_Aviv",
-  "Asia/Thimbu",
-  "Asia/Thimphu",
-  "Asia/Tokyo",
-  "Asia/Tomsk",
-  "Asia/Ujung_Pandang",
-  "Asia/Ulaanbaatar",
-  "Asia/Ulan_Bator",
-  "Asia/Urumqi",
-  "Asia/Ust-Nera",
-  "Asia/Vientiane",
-  "Asia/Vladivostok",
-  "Asia/Yakutsk",
-  "Asia/Yangon",
-  "Asia/Yekaterinburg",
-  "Asia/Yerevan",
-  "Atlantic/Azores",
-  "Atlantic/Bermuda",
-  "Atlantic/Canary",
-  "Atlantic/Cape_Verde",
-  "Atlantic/Faeroe",
-  "Atlantic/Faroe",
-  "Atlantic/Jan_Mayen",
-  "Atlantic/Madeira",
-  "Atlantic/Reykjavik",
-  "Atlantic/South_Georgia",
-  "Atlantic/St_Helena",
-  "Atlantic/Stanley",
-  "Australia/ACT",
-  "Australia/Adelaide",
-  "Australia/Brisbane",
-  "Australia/Broken_Hill",
-  "Australia/Canberra",
-  "Australia/Currie",
-  "Australia/Darwin",
-  "Australia/Eucla",
-  "Australia/Hobart",
-  "Australia/LHI",
-  "Australia/Lindeman",
-  "Australia/Lord_Howe",
-  "Australia/Melbourne",
-  "Australia/NSW",
-  "Australia/North",
-  "Australia/Perth",
-  "Australia/Queensland",
-  "Australia/South",
-  "Australia/Sydney",
-  "Australia/Tasmania",
-  "Australia/Victoria",
-  "Australia/West",
-  "Australia/Yancowinna",
-  "Brazil/Acre",
-  "Brazil/DeNoronha",
-  "Brazil/East",
-  "Brazil/West",
-  "CET",
-  "CST6CDT",
-  "Canada/Atlantic",
-  "Canada/Central",
-  "Canada/Eastern",
-  "Canada/Mountain",
-  "Canada/Newfoundland",
-  "Canada/Pacific",
-  "Canada/Saskatchewan",
-  "Canada/Yukon",
-  "Chile/Continental",
-  "Chile/EasterIsland",
-  "Cuba",
-  "EET",
-  "EST",
-  "EST5EDT",
-  "Egypt",
-  "Eire",
-  "Etc/GMT",
-  "Etc/GMT+0",
-  "Etc/GMT+1",
-  "Etc/GMT+10",
-  "Etc/GMT+11",
-  "Etc/GMT+12",
-  "Etc/GMT+2",
-  "Etc/GMT+3",
-  "Etc/GMT+4",
-  "Etc/GMT+5",
-  "Etc/GMT+6",
-  "Etc/GMT+7",
-  "Etc/GMT+8",
-  "Etc/GMT+9",
-  "Etc/GMT-0",
-  "Etc/GMT-1",
-  "Etc/GMT-10",
-  "Etc/GMT-11",
-  "Etc/GMT-12",
-  "Etc/GMT-13",
-  "Etc/GMT-14",
-  "Etc/GMT-2",
-  "Etc/GMT-3",
-  "Etc/GMT-4",
-  "Etc/GMT-5",
-  "Etc/GMT-6",
-  "Etc/GMT-7",
-  "Etc/GMT-8",
-  "Etc/GMT-9",
-  "Etc/GMT0",
-  "Etc/Greenwich",
-  "Etc/UCT",
-  "Etc/UTC",
-  "Etc/Universal",
-  "Etc/Zulu",
-  "Europe/Amsterdam",
-  "Europe/Andorra",
-  "Europe/Astrakhan",
-  "Europe/Athens",
-  "Europe/Belfast",
-  "Europe/Belgrade",
-  "Europe/Berlin",
-  "Europe/Bratislava",
-  "Europe/Brussels",
-  "Europe/Bucharest",
-  "Europe/Budapest",
-  "Europe/Busingen",
-  "Europe/Chisinau",
-  "Europe/Copenhagen",
-  "Europe/Dublin",
-  "Europe/Gibraltar",
-  "Europe/Guernsey",
-  "Europe/Helsinki",
-  "Europe/Isle_of_Man",
-  "Europe/Istanbul",
-  "Europe/Jersey",
-  "Europe/Kaliningrad",
-  "Europe/Kiev",
-  "Europe/Kirov",
-  "Europe/Lisbon",
-  "Europe/Ljubljana",
-  "Europe/London",
-  "Europe/Luxembourg",
-  "Europe/Madrid",
-  "Europe/Malta",
-  "Europe/Mariehamn",
-  "Europe/Minsk",
-  "Europe/Monaco",
-  "Europe/Moscow",
-  "Europe/Nicosia",
-  "Europe/Oslo",
-  "Europe/Paris",
-  "Europe/Podgorica",
-  "Europe/Prague",
-  "Europe/Riga",
-  "Europe/Rome",
-  "Europe/Samara",
-  "Europe/San_Marino",
-  "Europe/Sarajevo",
-  "Europe/Saratov",
-  "Europe/Simferopol",
-  "Europe/Skopje",
-  "Europe/Sofia",
-  "Europe/Stockholm",
-  "Europe/Tallinn",
-  "Europe/Tirane",
-  "Europe/Tiraspol",
-  "Europe/Ulyanovsk",
-  "Europe/Uzhgorod",
-  "Europe/Vaduz",
-  "Europe/Vatican",
-  "Europe/Vienna",
-  "Europe/Vilnius",
-  "Europe/Volgograd",
-  "Europe/Warsaw",
-  "Europe/Zagreb",
-  "Europe/Zaporozhye",
-  "Europe/Zurich",
-  "GB",
-  "GB-Eire",
-  "GMT",
-  "GMT+0",
-  "GMT-0",
-  "GMT0",
-  "Greenwich",
-  "HST",
-  "Hongkong",
-  "Iceland",
-  "Indian/Antananarivo",
-  "Indian/Chagos",
-  "Indian/Christmas",
-  "Indian/Cocos",
-  "Indian/Comoro",
-  "Indian/Kerguelen",
-  "Indian/Mahe",
-  "Indian/Maldives",
-  "Indian/Mauritius",
-  "Indian/Mayotte",
-  "Indian/Reunion",
-  "Iran",
-  "Israel",
-  "Jamaica",
-  "Japan",
-  "Kwajalein",
-  "Libya",
-  "MET",
-  "MST",
-  "MST7MDT",
-  "Mexico/BajaNorte",
-  "Mexico/BajaSur",
-  "Mexico/General",
-  "NZ",
-  "NZ-CHAT",
-  "Navajo",
-  "PRC",
-  "PST8PDT",
-  "Pacific/Apia",
-  "Pacific/Auckland",
-  "Pacific/Bougainville",
-  "Pacific/Chatham",
-  "Pacific/Chuuk",
-  "Pacific/Easter",
-  "Pacific/Efate",
-  "Pacific/Enderbury",
-  "Pacific/Fakaofo",
-  "Pacific/Fiji",
-  "Pacific/Funafuti",
-  "Pacific/Galapagos",
-  "Pacific/Gambier",
-  "Pacific/Guadalcanal",
-  "Pacific/Guam",
-  "Pacific/Honolulu",
-  "Pacific/Johnston",
-  "Pacific/Kiritimati",
-  "Pacific/Kosrae",
-  "Pacific/Kwajalein",
-  "Pacific/Majuro",
-  "Pacific/Marquesas",
-  "Pacific/Midway",
-  "Pacific/Nauru",
-  "Pacific/Niue",
-  "Pacific/Norfolk",
-  "Pacific/Noumea",
-  "Pacific/Pago_Pago",
-  "Pacific/Palau",
-  "Pacific/Pitcairn",
-  "Pacific/Pohnpei",
-  "Pacific/Ponape",
-  "Pacific/Port_Moresby",
-  "Pacific/Rarotonga",
-  "Pacific/Saipan",
-  "Pacific/Samoa",
-  "Pacific/Tahiti",
-  "Pacific/Tarawa",
-  "Pacific/Tongatapu",
-  "Pacific/Truk",
-  "Pacific/Wake",
-  "Pacific/Wallis",
-  "Pacific/Yap",
-  "Poland",
-  "Portugal",
-  "ROC",
-  "ROK",
-  "Singapore",
-  "Turkey",
-  "UCT",
-  "US/Alaska",
-  "US/Aleutian",
-  "US/Arizona",
-  "US/Central",
-  "US/East-Indiana",
-  "US/Eastern",
-  "US/Hawaii",
-  "US/Indiana-Starke",
-  "US/Michigan",
-  "US/Mountain",
-  "US/Pacific",
-  "US/Samoa",
-  "UTC",
-  "Universal",
-  "W-SU",
-  "WET",
-  "Zulu",
-  nullptr
-};
+const char* const kTimeZoneNames[] = {"Africa/Abidjan",
+                                      "Africa/Accra",
+                                      "Africa/Addis_Ababa",
+                                      "Africa/Algiers",
+                                      "Africa/Asmara",
+                                      "Africa/Asmera",
+                                      "Africa/Bamako",
+                                      "Africa/Bangui",
+                                      "Africa/Banjul",
+                                      "Africa/Bissau",
+                                      "Africa/Blantyre",
+                                      "Africa/Brazzaville",
+                                      "Africa/Bujumbura",
+                                      "Africa/Cairo",
+                                      "Africa/Casablanca",
+                                      "Africa/Ceuta",
+                                      "Africa/Conakry",
+                                      "Africa/Dakar",
+                                      "Africa/Dar_es_Salaam",
+                                      "Africa/Djibouti",
+                                      "Africa/Douala",
+                                      "Africa/El_Aaiun",
+                                      "Africa/Freetown",
+                                      "Africa/Gaborone",
+                                      "Africa/Harare",
+                                      "Africa/Johannesburg",
+                                      "Africa/Juba",
+                                      "Africa/Kampala",
+                                      "Africa/Khartoum",
+                                      "Africa/Kigali",
+                                      "Africa/Kinshasa",
+                                      "Africa/Lagos",
+                                      "Africa/Libreville",
+                                      "Africa/Lome",
+                                      "Africa/Luanda",
+                                      "Africa/Lubumbashi",
+                                      "Africa/Lusaka",
+                                      "Africa/Malabo",
+                                      "Africa/Maputo",
+                                      "Africa/Maseru",
+                                      "Africa/Mbabane",
+                                      "Africa/Mogadishu",
+                                      "Africa/Monrovia",
+                                      "Africa/Nairobi",
+                                      "Africa/Ndjamena",
+                                      "Africa/Niamey",
+                                      "Africa/Nouakchott",
+                                      "Africa/Ouagadougou",
+                                      "Africa/Porto-Novo",
+                                      "Africa/Sao_Tome",
+                                      "Africa/Timbuktu",
+                                      "Africa/Tripoli",
+                                      "Africa/Tunis",
+                                      "Africa/Windhoek",
+                                      "America/Adak",
+                                      "America/Anchorage",
+                                      "America/Anguilla",
+                                      "America/Antigua",
+                                      "America/Araguaina",
+                                      "America/Argentina/Buenos_Aires",
+                                      "America/Argentina/Catamarca",
+                                      "America/Argentina/ComodRivadavia",
+                                      "America/Argentina/Cordoba",
+                                      "America/Argentina/Jujuy",
+                                      "America/Argentina/La_Rioja",
+                                      "America/Argentina/Mendoza",
+                                      "America/Argentina/Rio_Gallegos",
+                                      "America/Argentina/Salta",
+                                      "America/Argentina/San_Juan",
+                                      "America/Argentina/San_Luis",
+                                      "America/Argentina/Tucuman",
+                                      "America/Argentina/Ushuaia",
+                                      "America/Aruba",
+                                      "America/Asuncion",
+                                      "America/Atikokan",
+                                      "America/Atka",
+                                      "America/Bahia",
+                                      "America/Bahia_Banderas",
+                                      "America/Barbados",
+                                      "America/Belem",
+                                      "America/Belize",
+                                      "America/Blanc-Sablon",
+                                      "America/Boa_Vista",
+                                      "America/Bogota",
+                                      "America/Boise",
+                                      "America/Buenos_Aires",
+                                      "America/Cambridge_Bay",
+                                      "America/Campo_Grande",
+                                      "America/Cancun",
+                                      "America/Caracas",
+                                      "America/Catamarca",
+                                      "America/Cayenne",
+                                      "America/Cayman",
+                                      "America/Chicago",
+                                      "America/Chihuahua",
+                                      "America/Coral_Harbour",
+                                      "America/Cordoba",
+                                      "America/Costa_Rica",
+                                      "America/Creston",
+                                      "America/Cuiaba",
+                                      "America/Curacao",
+                                      "America/Danmarkshavn",
+                                      "America/Dawson",
+                                      "America/Dawson_Creek",
+                                      "America/Denver",
+                                      "America/Detroit",
+                                      "America/Dominica",
+                                      "America/Edmonton",
+                                      "America/Eirunepe",
+                                      "America/El_Salvador",
+                                      "America/Ensenada",
+                                      "America/Fort_Nelson",
+                                      "America/Fort_Wayne",
+                                      "America/Fortaleza",
+                                      "America/Glace_Bay",
+                                      "America/Godthab",
+                                      "America/Goose_Bay",
+                                      "America/Grand_Turk",
+                                      "America/Grenada",
+                                      "America/Guadeloupe",
+                                      "America/Guatemala",
+                                      "America/Guayaquil",
+                                      "America/Guyana",
+                                      "America/Halifax",
+                                      "America/Havana",
+                                      "America/Hermosillo",
+                                      "America/Indiana/Indianapolis",
+                                      "America/Indiana/Knox",
+                                      "America/Indiana/Marengo",
+                                      "America/Indiana/Petersburg",
+                                      "America/Indiana/Tell_City",
+                                      "America/Indiana/Vevay",
+                                      "America/Indiana/Vincennes",
+                                      "America/Indiana/Winamac",
+                                      "America/Indianapolis",
+                                      "America/Inuvik",
+                                      "America/Iqaluit",
+                                      "America/Jamaica",
+                                      "America/Jujuy",
+                                      "America/Juneau",
+                                      "America/Kentucky/Louisville",
+                                      "America/Kentucky/Monticello",
+                                      "America/Knox_IN",
+                                      "America/Kralendijk",
+                                      "America/La_Paz",
+                                      "America/Lima",
+                                      "America/Los_Angeles",
+                                      "America/Louisville",
+                                      "America/Lower_Princes",
+                                      "America/Maceio",
+                                      "America/Managua",
+                                      "America/Manaus",
+                                      "America/Marigot",
+                                      "America/Martinique",
+                                      "America/Matamoros",
+                                      "America/Mazatlan",
+                                      "America/Mendoza",
+                                      "America/Menominee",
+                                      "America/Merida",
+                                      "America/Metlakatla",
+                                      "America/Mexico_City",
+                                      "America/Miquelon",
+                                      "America/Moncton",
+                                      "America/Monterrey",
+                                      "America/Montevideo",
+                                      "America/Montreal",
+                                      "America/Montserrat",
+                                      "America/Nassau",
+                                      "America/New_York",
+                                      "America/Nipigon",
+                                      "America/Nome",
+                                      "America/Noronha",
+                                      "America/North_Dakota/Beulah",
+                                      "America/North_Dakota/Center",
+                                      "America/North_Dakota/New_Salem",
+                                      "America/Nuuk",
+                                      "America/Ojinaga",
+                                      "America/Panama",
+                                      "America/Pangnirtung",
+                                      "America/Paramaribo",
+                                      "America/Phoenix",
+                                      "America/Port-au-Prince",
+                                      "America/Port_of_Spain",
+                                      "America/Porto_Acre",
+                                      "America/Porto_Velho",
+                                      "America/Puerto_Rico",
+                                      "America/Punta_Arenas",
+                                      "America/Rainy_River",
+                                      "America/Rankin_Inlet",
+                                      "America/Recife",
+                                      "America/Regina",
+                                      "America/Resolute",
+                                      "America/Rio_Branco",
+                                      "America/Rosario",
+                                      "America/Santa_Isabel",
+                                      "America/Santarem",
+                                      "America/Santiago",
+                                      "America/Santo_Domingo",
+                                      "America/Sao_Paulo",
+                                      "America/Scoresbysund",
+                                      "America/Shiprock",
+                                      "America/Sitka",
+                                      "America/St_Barthelemy",
+                                      "America/St_Johns",
+                                      "America/St_Kitts",
+                                      "America/St_Lucia",
+                                      "America/St_Thomas",
+                                      "America/St_Vincent",
+                                      "America/Swift_Current",
+                                      "America/Tegucigalpa",
+                                      "America/Thule",
+                                      "America/Thunder_Bay",
+                                      "America/Tijuana",
+                                      "America/Toronto",
+                                      "America/Tortola",
+                                      "America/Vancouver",
+                                      "America/Virgin",
+                                      "America/Whitehorse",
+                                      "America/Winnipeg",
+                                      "America/Yakutat",
+                                      "America/Yellowknife",
+                                      "Antarctica/Casey",
+                                      "Antarctica/Davis",
+                                      "Antarctica/DumontDUrville",
+                                      "Antarctica/Macquarie",
+                                      "Antarctica/Mawson",
+                                      "Antarctica/McMurdo",
+                                      "Antarctica/Palmer",
+                                      "Antarctica/Rothera",
+                                      "Antarctica/South_Pole",
+                                      "Antarctica/Syowa",
+                                      "Antarctica/Troll",
+                                      "Antarctica/Vostok",
+                                      "Arctic/Longyearbyen",
+                                      "Asia/Aden",
+                                      "Asia/Almaty",
+                                      "Asia/Amman",
+                                      "Asia/Anadyr",
+                                      "Asia/Aqtau",
+                                      "Asia/Aqtobe",
+                                      "Asia/Ashgabat",
+                                      "Asia/Ashkhabad",
+                                      "Asia/Atyrau",
+                                      "Asia/Baghdad",
+                                      "Asia/Bahrain",
+                                      "Asia/Baku",
+                                      "Asia/Bangkok",
+                                      "Asia/Barnaul",
+                                      "Asia/Beirut",
+                                      "Asia/Bishkek",
+                                      "Asia/Brunei",
+                                      "Asia/Calcutta",
+                                      "Asia/Chita",
+                                      "Asia/Choibalsan",
+                                      "Asia/Chongqing",
+                                      "Asia/Chungking",
+                                      "Asia/Colombo",
+                                      "Asia/Dacca",
+                                      "Asia/Damascus",
+                                      "Asia/Dhaka",
+                                      "Asia/Dili",
+                                      "Asia/Dubai",
+                                      "Asia/Dushanbe",
+                                      "Asia/Famagusta",
+                                      "Asia/Gaza",
+                                      "Asia/Harbin",
+                                      "Asia/Hebron",
+                                      "Asia/Ho_Chi_Minh",
+                                      "Asia/Hong_Kong",
+                                      "Asia/Hovd",
+                                      "Asia/Irkutsk",
+                                      "Asia/Istanbul",
+                                      "Asia/Jakarta",
+                                      "Asia/Jayapura",
+                                      "Asia/Jerusalem",
+                                      "Asia/Kabul",
+                                      "Asia/Kamchatka",
+                                      "Asia/Karachi",
+                                      "Asia/Kashgar",
+                                      "Asia/Kathmandu",
+                                      "Asia/Katmandu",
+                                      "Asia/Khandyga",
+                                      "Asia/Kolkata",
+                                      "Asia/Krasnoyarsk",
+                                      "Asia/Kuala_Lumpur",
+                                      "Asia/Kuching",
+                                      "Asia/Kuwait",
+                                      "Asia/Macao",
+                                      "Asia/Macau",
+                                      "Asia/Magadan",
+                                      "Asia/Makassar",
+                                      "Asia/Manila",
+                                      "Asia/Muscat",
+                                      "Asia/Nicosia",
+                                      "Asia/Novokuznetsk",
+                                      "Asia/Novosibirsk",
+                                      "Asia/Omsk",
+                                      "Asia/Oral",
+                                      "Asia/Phnom_Penh",
+                                      "Asia/Pontianak",
+                                      "Asia/Pyongyang",
+                                      "Asia/Qatar",
+                                      "Asia/Qostanay",
+                                      "Asia/Qyzylorda",
+                                      "Asia/Rangoon",
+                                      "Asia/Riyadh",
+                                      "Asia/Saigon",
+                                      "Asia/Sakhalin",
+                                      "Asia/Samarkand",
+                                      "Asia/Seoul",
+                                      "Asia/Shanghai",
+                                      "Asia/Singapore",
+                                      "Asia/Srednekolymsk",
+                                      "Asia/Taipei",
+                                      "Asia/Tashkent",
+                                      "Asia/Tbilisi",
+                                      "Asia/Tehran",
+                                      "Asia/Tel_Aviv",
+                                      "Asia/Thimbu",
+                                      "Asia/Thimphu",
+                                      "Asia/Tokyo",
+                                      "Asia/Tomsk",
+                                      "Asia/Ujung_Pandang",
+                                      "Asia/Ulaanbaatar",
+                                      "Asia/Ulan_Bator",
+                                      "Asia/Urumqi",
+                                      "Asia/Ust-Nera",
+                                      "Asia/Vientiane",
+                                      "Asia/Vladivostok",
+                                      "Asia/Yakutsk",
+                                      "Asia/Yangon",
+                                      "Asia/Yekaterinburg",
+                                      "Asia/Yerevan",
+                                      "Atlantic/Azores",
+                                      "Atlantic/Bermuda",
+                                      "Atlantic/Canary",
+                                      "Atlantic/Cape_Verde",
+                                      "Atlantic/Faeroe",
+                                      "Atlantic/Faroe",
+                                      "Atlantic/Jan_Mayen",
+                                      "Atlantic/Madeira",
+                                      "Atlantic/Reykjavik",
+                                      "Atlantic/South_Georgia",
+                                      "Atlantic/St_Helena",
+                                      "Atlantic/Stanley",
+                                      "Australia/ACT",
+                                      "Australia/Adelaide",
+                                      "Australia/Brisbane",
+                                      "Australia/Broken_Hill",
+                                      "Australia/Canberra",
+                                      "Australia/Currie",
+                                      "Australia/Darwin",
+                                      "Australia/Eucla",
+                                      "Australia/Hobart",
+                                      "Australia/LHI",
+                                      "Australia/Lindeman",
+                                      "Australia/Lord_Howe",
+                                      "Australia/Melbourne",
+                                      "Australia/NSW",
+                                      "Australia/North",
+                                      "Australia/Perth",
+                                      "Australia/Queensland",
+                                      "Australia/South",
+                                      "Australia/Sydney",
+                                      "Australia/Tasmania",
+                                      "Australia/Victoria",
+                                      "Australia/West",
+                                      "Australia/Yancowinna",
+                                      "Brazil/Acre",
+                                      "Brazil/DeNoronha",
+                                      "Brazil/East",
+                                      "Brazil/West",
+                                      "CET",
+                                      "CST6CDT",
+                                      "Canada/Atlantic",
+                                      "Canada/Central",
+                                      "Canada/Eastern",
+                                      "Canada/Mountain",
+                                      "Canada/Newfoundland",
+                                      "Canada/Pacific",
+                                      "Canada/Saskatchewan",
+                                      "Canada/Yukon",
+                                      "Chile/Continental",
+                                      "Chile/EasterIsland",
+                                      "Cuba",
+                                      "EET",
+                                      "EST",
+                                      "EST5EDT",
+                                      "Egypt",
+                                      "Eire",
+                                      "Etc/GMT",
+                                      "Etc/GMT+0",
+                                      "Etc/GMT+1",
+                                      "Etc/GMT+10",
+                                      "Etc/GMT+11",
+                                      "Etc/GMT+12",
+                                      "Etc/GMT+2",
+                                      "Etc/GMT+3",
+                                      "Etc/GMT+4",
+                                      "Etc/GMT+5",
+                                      "Etc/GMT+6",
+                                      "Etc/GMT+7",
+                                      "Etc/GMT+8",
+                                      "Etc/GMT+9",
+                                      "Etc/GMT-0",
+                                      "Etc/GMT-1",
+                                      "Etc/GMT-10",
+                                      "Etc/GMT-11",
+                                      "Etc/GMT-12",
+                                      "Etc/GMT-13",
+                                      "Etc/GMT-14",
+                                      "Etc/GMT-2",
+                                      "Etc/GMT-3",
+                                      "Etc/GMT-4",
+                                      "Etc/GMT-5",
+                                      "Etc/GMT-6",
+                                      "Etc/GMT-7",
+                                      "Etc/GMT-8",
+                                      "Etc/GMT-9",
+                                      "Etc/GMT0",
+                                      "Etc/Greenwich",
+                                      "Etc/UCT",
+                                      "Etc/UTC",
+                                      "Etc/Universal",
+                                      "Etc/Zulu",
+                                      "Europe/Amsterdam",
+                                      "Europe/Andorra",
+                                      "Europe/Astrakhan",
+                                      "Europe/Athens",
+                                      "Europe/Belfast",
+                                      "Europe/Belgrade",
+                                      "Europe/Berlin",
+                                      "Europe/Bratislava",
+                                      "Europe/Brussels",
+                                      "Europe/Bucharest",
+                                      "Europe/Budapest",
+                                      "Europe/Busingen",
+                                      "Europe/Chisinau",
+                                      "Europe/Copenhagen",
+                                      "Europe/Dublin",
+                                      "Europe/Gibraltar",
+                                      "Europe/Guernsey",
+                                      "Europe/Helsinki",
+                                      "Europe/Isle_of_Man",
+                                      "Europe/Istanbul",
+                                      "Europe/Jersey",
+                                      "Europe/Kaliningrad",
+                                      "Europe/Kiev",
+                                      "Europe/Kirov",
+                                      "Europe/Lisbon",
+                                      "Europe/Ljubljana",
+                                      "Europe/London",
+                                      "Europe/Luxembourg",
+                                      "Europe/Madrid",
+                                      "Europe/Malta",
+                                      "Europe/Mariehamn",
+                                      "Europe/Minsk",
+                                      "Europe/Monaco",
+                                      "Europe/Moscow",
+                                      "Europe/Nicosia",
+                                      "Europe/Oslo",
+                                      "Europe/Paris",
+                                      "Europe/Podgorica",
+                                      "Europe/Prague",
+                                      "Europe/Riga",
+                                      "Europe/Rome",
+                                      "Europe/Samara",
+                                      "Europe/San_Marino",
+                                      "Europe/Sarajevo",
+                                      "Europe/Saratov",
+                                      "Europe/Simferopol",
+                                      "Europe/Skopje",
+                                      "Europe/Sofia",
+                                      "Europe/Stockholm",
+                                      "Europe/Tallinn",
+                                      "Europe/Tirane",
+                                      "Europe/Tiraspol",
+                                      "Europe/Ulyanovsk",
+                                      "Europe/Uzhgorod",
+                                      "Europe/Vaduz",
+                                      "Europe/Vatican",
+                                      "Europe/Vienna",
+                                      "Europe/Vilnius",
+                                      "Europe/Volgograd",
+                                      "Europe/Warsaw",
+                                      "Europe/Zagreb",
+                                      "Europe/Zaporozhye",
+                                      "Europe/Zurich",
+                                      "GB",
+                                      "GB-Eire",
+                                      "GMT",
+                                      "GMT+0",
+                                      "GMT-0",
+                                      "GMT0",
+                                      "Greenwich",
+                                      "HST",
+                                      "Hongkong",
+                                      "Iceland",
+                                      "Indian/Antananarivo",
+                                      "Indian/Chagos",
+                                      "Indian/Christmas",
+                                      "Indian/Cocos",
+                                      "Indian/Comoro",
+                                      "Indian/Kerguelen",
+                                      "Indian/Mahe",
+                                      "Indian/Maldives",
+                                      "Indian/Mauritius",
+                                      "Indian/Mayotte",
+                                      "Indian/Reunion",
+                                      "Iran",
+                                      "Israel",
+                                      "Jamaica",
+                                      "Japan",
+                                      "Kwajalein",
+                                      "Libya",
+                                      "MET",
+                                      "MST",
+                                      "MST7MDT",
+                                      "Mexico/BajaNorte",
+                                      "Mexico/BajaSur",
+                                      "Mexico/General",
+                                      "NZ",
+                                      "NZ-CHAT",
+                                      "Navajo",
+                                      "PRC",
+                                      "PST8PDT",
+                                      "Pacific/Apia",
+                                      "Pacific/Auckland",
+                                      "Pacific/Bougainville",
+                                      "Pacific/Chatham",
+                                      "Pacific/Chuuk",
+                                      "Pacific/Easter",
+                                      "Pacific/Efate",
+                                      "Pacific/Enderbury",
+                                      "Pacific/Fakaofo",
+                                      "Pacific/Fiji",
+                                      "Pacific/Funafuti",
+                                      "Pacific/Galapagos",
+                                      "Pacific/Gambier",
+                                      "Pacific/Guadalcanal",
+                                      "Pacific/Guam",
+                                      "Pacific/Honolulu",
+                                      "Pacific/Johnston",
+                                      "Pacific/Kiritimati",
+                                      "Pacific/Kosrae",
+                                      "Pacific/Kwajalein",
+                                      "Pacific/Majuro",
+                                      "Pacific/Marquesas",
+                                      "Pacific/Midway",
+                                      "Pacific/Nauru",
+                                      "Pacific/Niue",
+                                      "Pacific/Norfolk",
+                                      "Pacific/Noumea",
+                                      "Pacific/Pago_Pago",
+                                      "Pacific/Palau",
+                                      "Pacific/Pitcairn",
+                                      "Pacific/Pohnpei",
+                                      "Pacific/Ponape",
+                                      "Pacific/Port_Moresby",
+                                      "Pacific/Rarotonga",
+                                      "Pacific/Saipan",
+                                      "Pacific/Samoa",
+                                      "Pacific/Tahiti",
+                                      "Pacific/Tarawa",
+                                      "Pacific/Tongatapu",
+                                      "Pacific/Truk",
+                                      "Pacific/Wake",
+                                      "Pacific/Wallis",
+                                      "Pacific/Yap",
+                                      "Poland",
+                                      "Portugal",
+                                      "ROC",
+                                      "ROK",
+                                      "Singapore",
+                                      "Turkey",
+                                      "UCT",
+                                      "US/Alaska",
+                                      "US/Aleutian",
+                                      "US/Arizona",
+                                      "US/Central",
+                                      "US/East-Indiana",
+                                      "US/Eastern",
+                                      "US/Hawaii",
+                                      "US/Indiana-Starke",
+                                      "US/Michigan",
+                                      "US/Mountain",
+                                      "US/Pacific",
+                                      "US/Samoa",
+                                      "UTC",
+                                      "Universal",
+                                      "W-SU",
+                                      "WET",
+                                      "Zulu",
+                                      nullptr};
 
 // Helper to return a loaded time zone by value (UTC on error).
 time_zone LoadZone(const std::string& name) {
@@ -724,7 +724,8 @@
   EXPECT_EQ("America/New_York", nyc.name());
   const time_zone syd = LoadZone("Australia/Sydney");
   EXPECT_EQ("Australia/Sydney", syd.name());
-  const time_zone fixed0 = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+  const time_zone fixed0 =
+      fixed_time_zone(absl::time_internal::cctz::seconds::zero());
   EXPECT_EQ("UTC", fixed0.name());
   const time_zone fixed_pos = fixed_time_zone(
       chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45));
@@ -749,7 +750,7 @@
   EXPECT_EQ(chrono::system_clock::from_time_t(0),
             convert(civil_second(1970, 1, 1, 0, 0, 0), tz));  // UTC
 
-  // Loading an empty std::string timezone should fail.
+  // Loading an empty string timezone should fail.
   tz = LoadZone("America/Los_Angeles");
   EXPECT_FALSE(load_time_zone("", &tz));
   EXPECT_EQ(chrono::system_clock::from_time_t(0),
@@ -767,7 +768,8 @@
   EXPECT_EQ(implicit_utc, explicit_utc);
   EXPECT_EQ(implicit_utc.name(), explicit_utc.name());
 
-  const time_zone fixed_zero = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+  const time_zone fixed_zero =
+      fixed_time_zone(absl::time_internal::cctz::seconds::zero());
   EXPECT_EQ(fixed_zero, LoadZone(fixed_zero.name()));
   EXPECT_EQ(fixed_zero, explicit_utc);
 
@@ -806,8 +808,8 @@
 TEST(StdChronoTimePoint, TimeTAlignment) {
   // Ensures that the Unix epoch and the system clock epoch are an integral
   // number of seconds apart. This simplifies conversions to/from time_t.
-  auto diff = chrono::system_clock::time_point() -
-              chrono::system_clock::from_time_t(0);
+  auto diff =
+      chrono::system_clock::time_point() - chrono::system_clock::from_time_t(0);
   EXPECT_EQ(chrono::system_clock::time_point::duration::zero(),
             diff % chrono::seconds(1));
 }
@@ -816,20 +818,20 @@
   const time_zone utc = utc_time_zone();
   const auto t0 = chrono::system_clock::from_time_t(0);
 
-  ExpectTime(chrono::time_point_cast<chrono::nanoseconds>(t0), utc,
-             1970, 1, 1, 0, 0, 0, 0, false, "UTC");
-  ExpectTime(chrono::time_point_cast<chrono::microseconds>(t0), utc,
-             1970, 1, 1, 0, 0, 0, 0, false, "UTC");
-  ExpectTime(chrono::time_point_cast<chrono::milliseconds>(t0), utc,
-             1970, 1, 1, 0, 0, 0, 0, false, "UTC");
-  ExpectTime(chrono::time_point_cast<chrono::seconds>(t0), utc,
-             1970, 1, 1, 0, 0, 0, 0, false, "UTC");
-  ExpectTime(chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0), utc,
-             1970, 1, 1, 0, 0, 0, 0, false, "UTC");
-  ExpectTime(chrono::time_point_cast<chrono::minutes>(t0), utc,
-             1970, 1, 1, 0, 0, 0, 0, false, "UTC");
-  ExpectTime(chrono::time_point_cast<chrono::hours>(t0), utc,
-             1970, 1, 1, 0, 0, 0, 0, false, "UTC");
+  ExpectTime(chrono::time_point_cast<chrono::nanoseconds>(t0), utc, 1970, 1, 1,
+             0, 0, 0, 0, false, "UTC");
+  ExpectTime(chrono::time_point_cast<chrono::microseconds>(t0), utc, 1970, 1, 1,
+             0, 0, 0, 0, false, "UTC");
+  ExpectTime(chrono::time_point_cast<chrono::milliseconds>(t0), utc, 1970, 1, 1,
+             0, 0, 0, 0, false, "UTC");
+  ExpectTime(chrono::time_point_cast<chrono::seconds>(t0), utc, 1970, 1, 1, 0,
+             0, 0, 0, false, "UTC");
+  ExpectTime(chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0),
+             utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
+  ExpectTime(chrono::time_point_cast<chrono::minutes>(t0), utc, 1970, 1, 1, 0,
+             0, 0, 0, false, "UTC");
+  ExpectTime(chrono::time_point_cast<chrono::hours>(t0), utc, 1970, 1, 1, 0, 0,
+             0, 0, false, "UTC");
 }
 
 TEST(BreakTime, LocalTimeInUTC) {
@@ -911,9 +913,8 @@
       chrono::time_point_cast<chrono::minutes>(
           convert(civil_second(2015, 1, 2, 3, 4, 5), utc));
   EXPECT_EQ("04:00", format("%M:%E*S", tp_m, utc));
-  const time_point<chrono::hours> tp_h =
-      chrono::time_point_cast<chrono::hours>(
-          convert(civil_second(2015, 1, 2, 3, 4, 5), utc));
+  const time_point<chrono::hours> tp_h = chrono::time_point_cast<chrono::hours>(
+      convert(civil_second(2015, 1, 2, 3, 4, 5), utc));
   EXPECT_EQ("00:00", format("%M:%E*S", tp_h, utc));
 }
 
@@ -932,7 +933,7 @@
 
 // NOTE: Run this with -ftrapv to detect overflow problems.
 TEST(MakeTime, SysSecondsLimits) {
-  const char RFC3339[] =  "%Y-%m-%dT%H:%M:%S%Ez";
+  const char RFC3339[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
   const time_zone utc = utc_time_zone();
   const time_zone east = fixed_time_zone(chrono::hours(14));
   const time_zone west = fixed_time_zone(-chrono::hours(14));
@@ -1003,13 +1004,17 @@
 #if defined(_WIN32) || defined(_WIN64)
     // localtime_s() and gmtime_s() don't believe in years outside [1970:3000].
 #else
-    const time_zone utc = LoadZone("libc:UTC");
+    const time_zone cut = LoadZone("libc:UTC");
     const year_t max_tm_year = year_t{std::numeric_limits<int>::max()} + 1900;
-    tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), utc);
-    EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, utc));
+    tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), cut);
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+    // The BSD gmtime_r() fails on extreme positive tm_year values.
+#else
+    EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, cut));
+#endif
     const year_t min_tm_year = year_t{std::numeric_limits<int>::min()} + 1900;
-    tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), utc);
-    EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, utc));
+    tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), cut);
+    EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, cut));
 #endif
   }
 }
@@ -1028,17 +1033,17 @@
     ASSERT_EQ(0, setenv("TZ", *np, 1));  // change what "localtime" means
     const auto zi = local_time_zone();
     const auto lc = LoadZone("libc:localtime");
-    time_zone::civil_transition trans;
+    time_zone::civil_transition transition;
     for (auto tp = zi.lookup(civil_second()).trans;
-         zi.next_transition(tp, &trans);
-         tp = zi.lookup(trans.to).trans) {
-      const auto fcl = zi.lookup(trans.from);
-      const auto tcl = zi.lookup(trans.to);
+         zi.next_transition(tp, &transition);
+         tp = zi.lookup(transition.to).trans) {
+      const auto fcl = zi.lookup(transition.from);
+      const auto tcl = zi.lookup(transition.to);
       civil_second cs;  // compare cs in zi and lc
       if (fcl.kind == time_zone::civil_lookup::UNIQUE) {
         if (tcl.kind == time_zone::civil_lookup::UNIQUE) {
           // Both unique; must be an is_dst or abbr change.
-          ASSERT_EQ(trans.from, trans.to);
+          ASSERT_EQ(transition.from, transition.to);
           const auto trans = fcl.trans;
           const auto tal = zi.lookup(trans);
           const auto tprev = trans - absl::time_internal::cctz::seconds(1);
@@ -1049,11 +1054,11 @@
           continue;
         }
         ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind);
-        cs = trans.to;
+        cs = transition.to;
       } else {
         ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind);
         ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind);
-        cs = trans.from;
+        cs = transition.from;
       }
       if (cs.year() > 2037) break;  // limit test time (and to 32-bit time_t)
       const auto cl_zi = zi.lookup(cs);
@@ -1433,4 +1438,5 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_posix.cc b/absl/time/internal/cctz/src/time_zone_posix.cc
index 038740e..5cdd09e 100644
--- a/absl/time/internal/cctz/src/time_zone_posix.cc
+++ b/absl/time/internal/cctz/src/time_zone_posix.cc
@@ -19,7 +19,10 @@
 #include <limits>
 #include <string>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -152,4 +155,5 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/src/time_zone_posix.h b/absl/time/internal/cctz/src/time_zone_posix.h
index 6a60022..0cf2905 100644
--- a/absl/time/internal/cctz/src/time_zone_posix.h
+++ b/absl/time/internal/cctz/src/time_zone_posix.h
@@ -55,7 +55,10 @@
 #include <cstdint>
 #include <string>
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -123,6 +126,7 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_
diff --git a/absl/time/internal/cctz/src/tzfile.h b/absl/time/internal/cctz/src/tzfile.h
index 51b1f1f..269fa36 100644
--- a/absl/time/internal/cctz/src/tzfile.h
+++ b/absl/time/internal/cctz/src/tzfile.h
@@ -22,36 +22,35 @@
 */
 
 #ifndef TZDIR
-#define TZDIR	"/usr/share/zoneinfo" /* Time zone object file directory */
-#endif /* !defined TZDIR */
+#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
+#endif                              /* !defined TZDIR */
 
 #ifndef TZDEFAULT
-#define TZDEFAULT	"/etc/localtime"
+#define TZDEFAULT "/etc/localtime"
 #endif /* !defined TZDEFAULT */
 
 #ifndef TZDEFRULES
-#define TZDEFRULES	"posixrules"
+#define TZDEFRULES "posixrules"
 #endif /* !defined TZDEFRULES */
 
-
 /* See Internet RFC 8536 for more details about the following format.  */
 
 /*
 ** Each file begins with. . .
 */
 
-#define	TZ_MAGIC	"TZif"
+#define TZ_MAGIC "TZif"
 
 struct tzhead {
-	char	tzh_magic[4];		/* TZ_MAGIC */
-	char	tzh_version[1];		/* '\0' or '2' or '3' as of 2013 */
-	char	tzh_reserved[15];	/* reserved; must be zero */
-	char	tzh_ttisutcnt[4];	/* coded number of trans. time flags */
-	char	tzh_ttisstdcnt[4];	/* coded number of trans. time flags */
-	char	tzh_leapcnt[4];		/* coded number of leap seconds */
-	char	tzh_timecnt[4];		/* coded number of transition times */
-	char	tzh_typecnt[4];		/* coded number of local time types */
-	char	tzh_charcnt[4];		/* coded number of abbr. chars */
+  char tzh_magic[4];      /* TZ_MAGIC */
+  char tzh_version[1];    /* '\0' or '2' or '3' as of 2013 */
+  char tzh_reserved[15];  /* reserved; must be zero */
+  char tzh_ttisutcnt[4];  /* coded number of trans. time flags */
+  char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
+  char tzh_leapcnt[4];    /* coded number of leap seconds */
+  char tzh_timecnt[4];    /* coded number of transition times */
+  char tzh_typecnt[4];    /* coded number of local time types */
+  char tzh_charcnt[4];    /* coded number of abbr. chars */
 };
 
 /*
@@ -84,13 +83,13 @@
 ** If tzh_version is '2' or greater, the above is followed by a second instance
 ** of tzhead and a second instance of the data in which each coded transition
 ** time uses 8 rather than 4 chars,
-** then a POSIX-TZ-environment-variable-style std::string for use in handling
+** then a POSIX-TZ-environment-variable-style string for use in handling
 ** instants after the last transition time stored in the file
 ** (with nothing between the newlines if there is no POSIX representation for
 ** such instants).
 **
 ** If tz_version is '3' or greater, the above is extended as follows.
-** First, the POSIX TZ std::string's hour offset may range from -167
+** First, the POSIX TZ string's hour offset may range from -167
 ** through 167 as compared to the POSIX-required 0 through 24.
 ** Second, its DST start time may be January 1 at 00:00 and its stop
 ** time December 31 at 24:00 plus the difference between DST and
@@ -103,21 +102,21 @@
 */
 
 #ifndef TZ_MAX_TIMES
-#define TZ_MAX_TIMES	2000
+#define TZ_MAX_TIMES 2000
 #endif /* !defined TZ_MAX_TIMES */
 
 #ifndef TZ_MAX_TYPES
 /* This must be at least 17 for Europe/Samara and Europe/Vilnius.  */
-#define TZ_MAX_TYPES	256 /* Limited by what (unsigned char)'s can hold */
-#endif /* !defined TZ_MAX_TYPES */
+#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
+#endif                   /* !defined TZ_MAX_TYPES */
 
 #ifndef TZ_MAX_CHARS
-#define TZ_MAX_CHARS	50	/* Maximum number of abbreviation characters */
-				/* (limited by what unsigned chars can hold) */
-#endif /* !defined TZ_MAX_CHARS */
+#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
+                        /* (limited by what unsigned chars can hold) */
+#endif                  /* !defined TZ_MAX_CHARS */
 
 #ifndef TZ_MAX_LEAPS
-#define TZ_MAX_LEAPS	50	/* Maximum number of leap second corrections */
-#endif /* !defined TZ_MAX_LEAPS */
+#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
+#endif                  /* !defined TZ_MAX_LEAPS */
 
 #endif /* !defined TZFILE_H */
diff --git a/absl/time/internal/cctz/src/zone_info_source.cc b/absl/time/internal/cctz/src/zone_info_source.cc
index 42f50c5..7209533 100644
--- a/absl/time/internal/cctz/src/zone_info_source.cc
+++ b/absl/time/internal/cctz/src/zone_info_source.cc
@@ -14,7 +14,10 @@
 
 #include "absl/time/internal/cctz/include/cctz/zone_info_source.h"
 
+#include "absl/base/config.h"
+
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz {
 
@@ -24,9 +27,11 @@
 
 }  // namespace cctz
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz_extension {
 
@@ -36,8 +41,9 @@
 // defers to the fallback factory.
 std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory(
     const std::string& name,
-    const std::function<std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource>(
-        const std::string& name)>& fallback_factory) {
+    const std::function<
+        std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource>(
+            const std::string& name)>& fallback_factory) {
   return fallback_factory(name);
 }
 
@@ -49,21 +55,53 @@
 #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)
+// MinGW is GCC on Windows, so while it asserts __has_attribute(weak), the
+// Windows linker cannot handle that. Nor does the MinGW compiler know how to
+// pass "#pragma comment(linker, ...)" to the Windows linker.
+#if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__)
+ZoneInfoSourceFactory zone_info_source_factory __attribute__((weak)) =
+    DefaultFactory;
+#elif defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_LIBCPP_VERSION)
 extern ZoneInfoSourceFactory zone_info_source_factory;
 extern ZoneInfoSourceFactory default_factory;
 ZoneInfoSourceFactory default_factory = DefaultFactory;
 #if defined(_M_IX86)
-#pragma comment( \
-    linker,      \
-    "/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@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZA=?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@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZA")
-#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM64)
-#pragma comment( \
-    linker,      \
-    "/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")
+#pragma comment(                                                                                                         \
+    linker,                                                                                                              \
+    "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS                    \
+    "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                 \
+    "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                   \
+    "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE      \
+    "@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                   \
+    "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                   \
+    "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+    "@@ZA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS                                       \
+    "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                 \
+    "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                   \
+    "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE      \
+    "@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                   \
+    "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                   \
+    "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+    "@@ZA")
+#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM) || \
+    defined(_M_ARM64)
+#pragma comment(                                                                                                          \
+    linker,                                                                                                               \
+    "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS                     \
+    "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                  \
+    "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                    \
+    "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE      \
+    "@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                   \
+    "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                    \
+    "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+    "@@ZEA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS                                       \
+    "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                  \
+    "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                    \
+    "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE      \
+    "@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                   \
+    "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS                                    \
+    "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+    "@@ZEA")
 #else
 #error Unsupported MSVC platform
 #endif  // _M_<PLATFORM>
@@ -74,4 +112,5 @@
 
 }  // namespace cctz_extension
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/cctz/testdata/version b/absl/time/internal/cctz/testdata/version
index db18f83..b4410dc 100644
--- a/absl/time/internal/cctz/testdata/version
+++ b/absl/time/internal/cctz/testdata/version
@@ -1 +1 @@
-2019c
+2020d
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
index 697b993..9ca907b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
index ae04342..56a4dd2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
index 82ea5aa..0da1d1e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
index d3f8196..ea38c97 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
index 245f4eb..0263c90 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
index 850c8f0..a461dce 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun b/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
index a91f65f..772e23c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
index b1c425d..bada063 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
index 625b1ac..36b0522 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
index 8ee8cb9..3f8e44b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
index 52753c0..651e5cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
index b1c425d..bada063 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
index b1c425d..bada063 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
index 6d68850..8377809 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
index a968845..ecbc096 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
index 0c80137..2f2ce2f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
index 59f3759..425ad3f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
index 07b393b..e0c8997 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
index 427fa56..ca324cb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
index abecd13..0edc52b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Adak b/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
index 4323649..b1497bd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage b/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
index 9bbb2fd..cdf0572 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla b/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua b/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina b/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
index 49381b4..f66c9f7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
index 260f86a..d6f999b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
index 0ae222a..1dcc8d8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
index 0ae222a..1dcc8d8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
index da4c23a..35a52e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
index 604b856..b275f27 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
index 2218e36..23fca12 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
index f9e677f..691c569 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
index c36587e..991d1fa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
index 0e797f2..58863e0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
index 2698495..7eba33c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
index fe50f62..0a81cbd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
index c954000..10556d5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
index 3643628..e031750 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba b/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
index f7ab6ef..d6ddf7d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion b/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
index 2f3bbda..6225036 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan b/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
index 629ed42..c828715 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Atka b/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
index 4323649..b1497bd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
index 15808d3..7969e30 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
index 896af3f..cbe22a7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados b/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
index 9b90e30..9d3afa6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Belem b/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
index 60b5924..e0d7653 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Belize b/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
index 851051a..de99b84 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon b/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
index f9f13a1..7096b69 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista b/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
index 978c331..fca9720 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota b/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
index b2647d7a..6cb53d4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Boise b/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
index f8d54e2..72fec9e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires b/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
index 260f86a..d6f999b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
index f8db4b6..0a22252 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande b/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
index 8120624..6855e4e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun b/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
index f907f0a..640b259 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas b/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
index eedf725..8dbe6ff 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca b/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
index 0ae222a..1dcc8d8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
index e5bc06f..cd49f05 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
index 9964b9a..9154643 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago b/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
index a5b1617..b016880 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua b/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
index 8ed5f93..e1780a5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour b/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
index 629ed42..c828715 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba b/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
index da4c23a..35a52e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica b/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
index 37cb85e..08f0128 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Creston b/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
index ca64857..9d69a0a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba b/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
index 9bea3d4..c09a875 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao b/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
index f7ab6ef..d6ddf7d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn b/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
index 9549adc..8718efc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
index db9cead..07e4c5f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
index db9e339..761d1d9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Denver b/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
index 5fbe26b..09e54e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit b/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
index e104faa..6eb3ac4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica b/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton b/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
index cd78a6f..645ee94 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe b/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
index 39d6dae..7da4b98 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador b/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
index e2f2230..4348411 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada b/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
index ada6bf7..19ccd35 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
index 5a0b7f1..2a49c6c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
index 09511cc..6b08d15 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza b/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
index be57dc2..092e40d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
index 48412a4..f85eb34 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab b/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
index 0160308..4ddc99d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
index a3f2990..820e0dd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk b/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
index b9bb063..062fcae 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada b/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe b/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala b/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
index 407138c..8aa8e58 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil b/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
index 0559a7a..381ae6c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana b/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
index d5dab14..ebd85d0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax b/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
index 756099a..9fa850a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Havana b/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
index b69ac45..e06629d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo b/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
index 791a9fa..8283239 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
index 09511cc..6b08d15 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
index fcd408d..b187d5f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
index 1abf75e..a730fe6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
index 0133548..341a023 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
index 7bbb653..76e1f62 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
index d236b7c..f2acf6c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
index c818929..c255f89 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
index 630935c..8700ed9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis b/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
index 09511cc..6b08d15 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik b/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
index 87bb355..af3107d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit b/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
index c8138bd..eb2c99c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica b/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
index 2a9b7fd..be6b1b6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy b/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
index 604b856..b275f27 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau b/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
index 451f349..e347b36 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
index 177836e..f2136d6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
index 438e3ea..d9f54a1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN b/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
index fcd408d..b187d5f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk b/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
index f7ab6ef..d6ddf7d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz b/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
index a101372..68ddaae 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Lima b/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
index 3c6529b..b643c55 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles b/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
index 9dad4f4..aaf0778 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville b/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
index 177836e..f2136d6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes b/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
index f7ab6ef..d6ddf7d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio b/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
index bc8b951..dbb8d57 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Managua b/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
index e0242bf..86ef76b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus b/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
index 63d58f8..59c952e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot b/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique b/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
index 8df43dc..25c0232 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros b/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
index 047968d..722751b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan b/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
index e4a7857..4c819fa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza b/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
index f9e677f..691c569 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee b/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
index 3146138..28d2c56 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Merida b/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
index ea852da..d3b0ca1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla b/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
index 1e94be3..9fefee3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City b/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
index e7fb6f2..ffcf8be 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon b/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
index b924b71..3b62585 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton b/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
index 9df8d0f..ecb69ef 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey b/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
index a8928c8..dea9e3f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo b/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
index 2f357bc..4b2fb3e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal b/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
index 6752c5b..fe6be8e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat b/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau b/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
index 33cc6c6..cf1e92d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/New_York b/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
index 2f75480..2b6c2ee 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon b/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
index f6a856e..b9f67a9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Nome b/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
index 10998df..23ead1c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha b/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
index f140726..9e74745 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
index 246345d..becf438 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
index 1fa0703..d03bda0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
index 123f2ae..ecefc15 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Nuuk b/absl/time/internal/cctz/testdata/zoneinfo/America/Nuuk
new file mode 100644
index 0000000..4ddc99d
--- /dev/null
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Nuuk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga b/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
index fc4a03e..da0909c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Panama b/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
index 9964b9a..9154643 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung b/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
index 3e4e0db..5be6f9b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo b/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
index bc8a6ed..24f925a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix b/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
index ac6bb0c..c2bd2f9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince b/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
index 287f143..3e75731 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain b/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
index a374cb4..fb5185c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
index 2e873a5..7f8047d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico b/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
index a662a57..47b4dc3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas b/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
index a5a8af5..5c9a20b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River b/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
index ea66099..d6ddda4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet b/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
index 3a70587..92e2ed2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Recife b/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
index d7abb16..305abcb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Regina b/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
index 20c9c84..a3f8217 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute b/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
index 0a73b75..a84d1df 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco b/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
index a374cb4..fb5185c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario b/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
index da4c23a..35a52e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel b/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
index ada6bf7..19ccd35 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem b/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
index c28f360..f81d144 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago b/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
index 816a042..8d60322 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo b/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
index 4fe36fd..3e07850 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo b/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
index 13ff083..a16da2c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund b/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
index e20e9e1..6db4912 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock b/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
index 5fbe26b..09e54e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka b/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
index 31f7061..36681ed 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
index 65a5b0c..e5f2aec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current b/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
index 8e9ef25..bdbb494 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa b/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
index 2adacb2..38036a3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Thule b/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
index 6f802f1..f38dc56 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay b/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
index e504c9a..fcb0328 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana b/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
index ada6bf7..19ccd35 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto b/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
index 6752c5b..fe6be8e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola b/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver b/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
index bb60cbc..c998491 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin b/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
index 697cf5b..f4fe590 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse b/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
index fb3cd71..878b6a9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg b/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
index ac40299..7e646d1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat b/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
index da209f9..773feba 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife b/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
index e6afa39..c779cef 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
+++ b/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
index f100f47..30315cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
index 916f2c2..3ec3222 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
index a71b39c..c0cfc85 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
index 616afd9..232717b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
index b32e7fd..05e4c6c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
index 6575fdc..afb3929 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
index 3dd85f8..32c1941 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
index 8b2430a..ea49c00 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
index 6575fdc..afb3929 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
index 254af7d..97d80d7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
index 5e565da..4e31aff 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
index 7283053..6e32907 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen b/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
index 15a34c3..dfc5095 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
index 2aea25f..01c47cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
index a4b0077..3ec4fc8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
index c9e8707..1bd09fe 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
index 6ed8b7c..551884d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
index e2d0f91..3a40d11 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
index 06f0a13..62c5840 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
index 73891af..8482167 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
index 73891af..8482167 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
index 8b5153e..cb2c82f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
index f7162ed..a3ce975 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
index 63188b2..7409d74 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
index a0de74b..96203d7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
index c292ac5..ed687d2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
index 759592a..ff976dd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
index fb266ed..55dce57 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
index f6e20dd..fe7832c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
index 3dab0ab..e67b411 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
index 0014046..00bc80a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
index c4149c0..9d49cd3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
index e48daa8..0a948c2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
index 3c0bef2..d6b6698 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
index 3c0bef2..d6b6698 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
index 62c64d8..3eeb1b7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
index b11c928..2813680 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
index d9104a7..168ef9b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
index b11c928..2813680 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
index 30943bb..bb7be9f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
index fc0a589..58d75bc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
index 82d85b8..d83fb07 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
index 653b146..cc44179 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
index 592b632..4278ffa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
index 3c0bef2..d6b6698 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
index ae82f9b..e55318a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
index e2934e3..7ca9972 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
index 23d0375..c80e364 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
index 4cb800a..6e08a26 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
index 4dcbbb7..550e2a0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
index 508446b..c891866 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
index 5baa3a8..c9752d2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
index 3002c82..7c22f53 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
index 440ef06..e6e6cc6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
index d19b9bd..660ce4c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
index 3e80b4e..c651554 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
index ba65c0e..e56d5af 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
index faa14d9..69ff7f6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
index a5d5107..3a0d330 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
index a5d5107..3a0d330 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
index 72bea64..aeb7332 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
index 0014046..00bc80a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
index 30c6f16..e0d4fcb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
index 612b01e..e93dd51 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
index c86750c..59bc6e4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
index 2aea25f..01c47cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
index cac6506..c22f75e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
index cac6506..c22f75e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
index b4fcac1..16bac84 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
index 556ba86..5990010 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
index f4f4b04..3c3584e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
index fc0a589..58d75bc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
index f7f10ab..c210d0a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
index d983276..9378d50 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
index e0ee5fc..65a9fa2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
index b29b769..dc0ed42 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
index ad1f9ca..25a63ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
index c292ac5..ed687d2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
index 12ce24c..285bed2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
index 7ad7e0b..57240cf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
index 63188b2..7409d74 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
index 73b9d96..ff6fe61 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
index c2fe4c1..fe4d6c6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
index dd77395..14b2ad0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
index 2aea25f..01c47cc 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
index e2934e3..7ca9972 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
index 485459c..69f0faa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
index 030d47c..c43e27c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
index 96199e7..1755147 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
index 3c0bef2..d6b6698 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
index 2364b21..350d77e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
index 261a983..7fdee5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
index 24c4344..35d89d0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
index 32a9d7d..65ee428 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
index b608d79..166e434 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
index 8cec5ad..f1555f0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
index 440ef06..e6e6cc6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
index fe409c7..0edc72c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
index fe409c7..0edc72c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
index 26f4d34..1aa066c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
index 670e2ad..c3c307d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
index 556ba86..5990010 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
index 2e20cc3..6f5d3a1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
index 2e20cc3..6f5d3a1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
index faa14d9..69ff7f6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
index 9e4a78f..c39331e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
index c292ac5..ed687d2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
index 8ab253c..72a3d4e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
index c815e99..336f932 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
index dd77395..14b2ad0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
index 6958d7e..a3bf7f2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
index 250bfe0..6dd927c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
index 56593db..b7f75a9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
index 419c660..aa33014 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
index f319215..5ab3243 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
index e2a49d2..8f7de1c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
index 4dab7ef..9558bf7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
index 4dab7ef..9558bf7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
index 15a34c3..dfc5095 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
index 5213761..7c3a49c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
index 10e0fc8..2451aca 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
index 4466608..7fa5f46 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
index 28b32ab..8906e88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
index 88077f1..1a4c8ea 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT b/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
index 7636592..f235d0d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
index 0b1252a..f397b3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
index 3021bdb..c7915db 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
index 1ac3fc8..ed0d17a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
index 7636592..f235d0d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
index f65a990..55ceaef 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
index 1cf5029..7114153 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
index 98ae557..9fbc01f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
index 02b07ca..21ef2d3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI b/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
index 9e04a80..4d4ec8c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
index eab0fb9..e271d5b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
index 9e04a80..4d4ec8c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
index ba45733..c7160da 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW b/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
index 7636592..f235d0d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/North b/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
index 1cf5029..7114153 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
index a876b9e..e449b03 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
index 3021bdb..c7915db 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/South b/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
index 0b1252a..f397b3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
index 7636592..f235d0d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
index 02b07ca..21ef2d3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
index ba45733..c7160da 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/West b/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
index a876b9e..e449b03 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
index 1ac3fc8..ed0d17a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
index a374cb4..fb5185c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
index f140726..9e74745 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
index 13ff083..a16da2c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
index 63d58f8..59c952e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/CET b/absl/time/internal/cctz/testdata/zoneinfo/CET
index 122e934..546748d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/CET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/CET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT b/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
index ca67929..d931558 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
index 756099a..9fa850a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
index ac40299..7e646d1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
index 6752c5b..fe6be8e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
index cd78a6f..645ee94 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
index 65a5b0c..e5f2aec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
index bb60cbc..c998491 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
index 20c9c84..a3f8217 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
index fb3cd71..878b6a9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental b/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
index 816a042..8d60322 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland b/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
index cae3744..d29bcd6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Cuba b/absl/time/internal/cctz/testdata/zoneinfo/Cuba
index b69ac45..e06629d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Cuba
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Cuba
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EET b/absl/time/internal/cctz/testdata/zoneinfo/EET
index cbdb71d..378919e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EST b/absl/time/internal/cctz/testdata/zoneinfo/EST
index 21ebc00..3ae9691 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT b/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
index 9bce500..50c95e0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Egypt b/absl/time/internal/cctz/testdata/zoneinfo/Egypt
index d3f8196..ea38c97 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Egypt
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Egypt
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Eire b/absl/time/internal/cctz/testdata/zoneinfo/Eire
index 1d99490..4a45ea8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Eire
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Eire
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
index 4dab6f9..98d5dcf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
index c749290..ecb287e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
index d969982..e941412 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
index cdeec90..9c95bd0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
index fbd2a94..6d5ce3d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
index ee246ef..5ef7be7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
index 5a25ff2..75f1621 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
index c0b745f..589990a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
index 06e777d..fcb60ca 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
index 4e0b53a..c0427a4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
index 714b0c5..9bdc228 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
index 78b9daa..ca7a81f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
index a838beb..cb45601 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
index 68ff77d..11d988e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
index 66af5a4..f4c5d5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
index 17ba505..cd397b0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
index 5f3706c..8fad7c6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
index 7e9f9c4..a595e60 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
index fcef6d9..97b44a9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
index 27973bc..4eb17ff 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
index 1efd841..13aef80 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
index 1f76184..83a2816 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
index 952681e..79a983e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
index cefc912..e136690 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
index afb093d..bc70fe4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
index 9265fb7..d18cedd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0 b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
index c3ff07b..4a6fa1d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
index 5962550..38685d4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
index 73a4d01..aff8d82 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
index 9f3a067..231bf9c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
index 7f6d958..465546b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
index ce8f433..fb7c145 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
index 40d7124..3197327 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
index 4303b90..efa689b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
index 6b94a4f..940be46 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
index ad6cf59..388df29 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
index 5ee23fe..6970b14 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
index 776be6e..45984a7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
index 1d99490..4a45ea8 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
index 117aadb..017bb2e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
index b4f8f9c..ff5e565 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
index 508446b..c891866 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
index cc99bea..0ec4756 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
index 9337c9e..8f83cef 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
index a3b5320..d1c93c5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
index 355817b..6484166 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/London b/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
index c4ca733..682bcbf 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
index 16f6420..60bdf4d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
index bf2452d..27539c2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
index b4f8f9c..ff5e565 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
index 453306c..30d3a67 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
index 686ae88..f30dfc7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
index ddb3f4e..5e6b6de 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
index f7f10ab..c210d0a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
index 15a34c3..dfc5095 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
index ca85435..00a2726 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
index ce8f433..fb7c145 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
index 8db477d..26af4c9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
index ac4c163..639ca3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
index 97d5dd9..8d0c26e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino b/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
index ac4c163..639ca3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
index 8fd5f6d..2684d8f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
index 432e831..88a6f3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
index 0e4d879..eabc972 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
index f3e0c7f..dd3eb32 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
index b5acca3..5321bbd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
index 0b86017..743a733 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
index 5ee23fe..6970b14 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
index 7b61bdc..bb842cb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
index 66ae8d6..a575568 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
index ad6cf59..388df29 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
index ac4c163..639ca3b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
index 3582bb1..75339e9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
index 7abd63f..75b2eeb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
index d1cfac0..a486ad4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
index e33cf67..efe1a40 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
index 27de456..a1bf928 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
index e42edfc..4ea8dae 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
index ad6cf59..388df29 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Factory b/absl/time/internal/cctz/testdata/zoneinfo/Factory
index 60aa2a0..b4dd773 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Factory
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Factory
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GB b/absl/time/internal/cctz/testdata/zoneinfo/GB
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GB
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GB
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire b/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
index ac02a81..323cd38 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT b/absl/time/internal/cctz/testdata/zoneinfo/GMT
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT+0 b/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT-0 b/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/GMT0 b/absl/time/internal/cctz/testdata/zoneinfo/GMT0
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/GMT0
+++ b/absl/time/internal/cctz/testdata/zoneinfo/GMT0
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Greenwich b/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
index c634746..157573b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/HST b/absl/time/internal/cctz/testdata/zoneinfo/HST
index cccd45e..160a53e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/HST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/HST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Hongkong b/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
index 23d0375..c80e364 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Iceland b/absl/time/internal/cctz/testdata/zoneinfo/Iceland
index 10e0fc8..2451aca 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Iceland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Iceland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
index 93d6dda..8b8ce22 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
index d18c381..766024b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
index f8116e7..1175034 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
index cde4cf7..8ce93e0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
index cba7dfe..75362bb 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
index 7c839cf..58a82e4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
index 17f2616..7c11134 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
index 9a2918f..d3c0bb3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
index dfe0831..248a7c9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Iran b/absl/time/internal/cctz/testdata/zoneinfo/Iran
index 8cec5ad..f1555f0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Iran
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Iran
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Israel b/absl/time/internal/cctz/testdata/zoneinfo/Israel
index 440ef06..e6e6cc6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Israel
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Israel
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Jamaica b/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
index 2a9b7fd..be6b1b6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Japan b/absl/time/internal/cctz/testdata/zoneinfo/Japan
index 26f4d34..1aa066c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Japan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Japan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein b/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
index 1a7975f..9416d52 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Libya b/absl/time/internal/cctz/testdata/zoneinfo/Libya
index 07b393b..e0c8997 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Libya
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Libya
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MET b/absl/time/internal/cctz/testdata/zoneinfo/MET
index 4a826bb..6f0558c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MST b/absl/time/internal/cctz/testdata/zoneinfo/MST
index c93a58e..a0953d1 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MST
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MST
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT b/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
index 4506a6e..137867c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
index ada6bf7..19ccd35 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
index e4a7857..4c819fa 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
index e7fb6f2..ffcf8be 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/NZ b/absl/time/internal/cctz/testdata/zoneinfo/NZ
index 6575fdc..afb3929 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/NZ
+++ b/absl/time/internal/cctz/testdata/zoneinfo/NZ
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT b/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
index c004109..f06065e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Navajo b/absl/time/internal/cctz/testdata/zoneinfo/Navajo
index 5fbe26b..09e54e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Navajo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Navajo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/PRC b/absl/time/internal/cctz/testdata/zoneinfo/PRC
index 3c0bef2..d6b6698 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/PRC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/PRC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT b/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
index 99d246b..fde4833 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
index dab1f3f..244af26 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
index 6575fdc..afb3929 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
index 2892d26..7c66709 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
index c004109..f06065e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
index 07c84b7..ea3fb5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
index cae3744..d29bcd6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
index 6015017..906971e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
index f0b8252..b22ab14 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
index e40307f..b7b3021 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
index d39bf53..e3934e4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
index ea72863..78ab35b 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
index 31f0921..a9403ec 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
index e1fc3da..ddfc34f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
index 7e9d10a..720c679 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
index 66490d2..bf9a2d9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
index c7cd060..40e3d49 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
index c7cd060..40e3d49 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
index 7cae0cb..2f676d3 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
index a584aae..f5d5824 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
index 1a7975f..9416d52 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
index 9ef8374..9228ee0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
index 74d6792..6ea24b7 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
index cb56709..001289c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
index acec042..ae13aac 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
index 684b010..7b35793 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
index 53c1aad..79e2a94 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
index 931a1a3..824f814 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
index cb56709..001289c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
index 146b351..bc8eb7a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
index ef91b06..8a4ba4d 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
index c298ddd..b92b254 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
index c298ddd..b92b254 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
index 920ad27..5d8fc3a 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
index da6b0fa..143a188 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
index 66490d2..bf9a2d9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
index cb56709..001289c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
index 442b8eb..50a064f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
index 3db6c75..6bc2168 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
index 5553c60..54aeb0f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
index 07c84b7..ea3fb5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
index c9e3106..71cca88 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
index b35344b..4bce893 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
index 07c84b7..ea3fb5c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Poland b/absl/time/internal/cctz/testdata/zoneinfo/Poland
index e33cf67..efe1a40 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Poland
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Poland
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Portugal b/absl/time/internal/cctz/testdata/zoneinfo/Portugal
index 355817b..6484166 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Portugal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Portugal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/ROC b/absl/time/internal/cctz/testdata/zoneinfo/ROC
index 24c4344..35d89d0 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/ROC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/ROC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/ROK b/absl/time/internal/cctz/testdata/zoneinfo/ROK
index 96199e7..1755147 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/ROK
+++ b/absl/time/internal/cctz/testdata/zoneinfo/ROK
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Singapore b/absl/time/internal/cctz/testdata/zoneinfo/Singapore
index 2364b21..350d77e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Singapore
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Singapore
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Turkey b/absl/time/internal/cctz/testdata/zoneinfo/Turkey
index 508446b..c891866 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Turkey
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Turkey
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/UCT b/absl/time/internal/cctz/testdata/zoneinfo/UCT
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/UCT
+++ b/absl/time/internal/cctz/testdata/zoneinfo/UCT
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska b/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
index 9bbb2fd..cdf0572 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian b/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
index 4323649..b1497bd 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona b/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
index ac6bb0c..c2bd2f9 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Central b/absl/time/internal/cctz/testdata/zoneinfo/US/Central
index a5b1617..b016880 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Central
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Central
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana b/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
index 09511cc..6b08d15 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern b/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
index 2f75480..2b6c2ee 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii b/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
index c7cd060..40e3d49 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke b/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
index fcd408d..b187d5f 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan b/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
index e104faa..6eb3ac4 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain b/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
index 5fbe26b..09e54e5 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific b/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
index 9dad4f4..aaf0778 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa b/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
index cb56709..001289c 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
+++ b/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/UTC b/absl/time/internal/cctz/testdata/zoneinfo/UTC
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/UTC
+++ b/absl/time/internal/cctz/testdata/zoneinfo/UTC
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Universal b/absl/time/internal/cctz/testdata/zoneinfo/Universal
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Universal
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Universal
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/W-SU b/absl/time/internal/cctz/testdata/zoneinfo/W-SU
index ddb3f4e..5e6b6de 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/W-SU
+++ b/absl/time/internal/cctz/testdata/zoneinfo/W-SU
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/WET b/absl/time/internal/cctz/testdata/zoneinfo/WET
index c27390b..423c6c2 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/WET
+++ b/absl/time/internal/cctz/testdata/zoneinfo/WET
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/Zulu b/absl/time/internal/cctz/testdata/zoneinfo/Zulu
index 91558be..00841a6 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/Zulu
+++ b/absl/time/internal/cctz/testdata/zoneinfo/Zulu
Binary files differ
diff --git a/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab b/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
index 822ffa1..53ee77e 100644
--- a/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
+++ b/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
@@ -128,8 +128,8 @@
 CA	+5946-12014	America/Dawson_Creek	MST - BC (Dawson Cr, Ft St John)
 CA	+5848-12242	America/Fort_Nelson	MST - BC (Ft Nelson)
 CA	+4916-12307	America/Vancouver	Pacific - BC (most areas)
-CA	+6043-13503	America/Whitehorse	Pacific - Yukon (south)
-CA	+6404-13925	America/Dawson	Pacific - Yukon (north)
+CA	+6043-13503	America/Whitehorse	Pacific - Yukon (east)
+CA	+6404-13925	America/Dawson	Pacific - Yukon (west)
 CC	-1210+09655	Indian/Cocos
 CH,DE,LI	+4723+00832	Europe/Zurich	Swiss time
 CI,BF,GM,GN,ML,MR,SH,SL,SN,TG	+0519-00402	Africa/Abidjan
@@ -173,7 +173,7 @@
 GF	+0456-05220	America/Cayenne
 GH	+0533-00013	Africa/Accra
 GI	+3608-00521	Europe/Gibraltar
-GL	+6411-05144	America/Godthab	Greenland (most areas)
+GL	+6411-05144	America/Nuuk	Greenland (most areas)
 GL	+7646-01840	America/Danmarkshavn	National Park (east coast)
 GL	+7029-02158	America/Scoresbysund	Scoresbysund/Ittoqqortoormiit
 GL	+7634-06847	America/Thule	Thule/Pituffik
@@ -290,7 +290,7 @@
 RU	+5443+02030	Europe/Kaliningrad	MSK-01 - Kaliningrad
 RU	+554521+0373704	Europe/Moscow	MSK+00 - Moscow area
 # Mention RU and UA alphabetically.  See "territorial claims" above.
-RU,UA	+4457+03406	Europe/Simferopol	MSK+00 - Crimea
+RU,UA	+4457+03406	Europe/Simferopol	Crimea
 RU	+5836+04939	Europe/Kirov	MSK+00 - Kirov
 RU	+4621+04803	Europe/Astrakhan	MSK+01 - Astrakhan
 RU	+4844+04425	Europe/Volgograd	MSK+01 - Volgograd
@@ -341,8 +341,8 @@
 TV	-0831+17913	Pacific/Funafuti
 TW	+2503+12130	Asia/Taipei
 UA	+5026+03031	Europe/Kiev	Ukraine (most areas)
-UA	+4837+02218	Europe/Uzhgorod	Ruthenia
-UA	+4750+03510	Europe/Zaporozhye	Zaporozh'ye/Zaporizhia; Lugansk/Luhansk (east)
+UA	+4837+02218	Europe/Uzhgorod	Transcarpathia
+UA	+4750+03510	Europe/Zaporozhye	Zaporozhye and east Lugansk
 UM	+1917+16637	Pacific/Wake	Wake Island
 US	+404251-0740023	America/New_York	Eastern (most areas)
 US	+421953-0830245	America/Detroit	Eastern - MI (most areas)
diff --git a/absl/time/internal/get_current_time_chrono.inc b/absl/time/internal/get_current_time_chrono.inc
index 5180230..5eeb640 100644
--- a/absl/time/internal/get_current_time_chrono.inc
+++ b/absl/time/internal/get_current_time_chrono.inc
@@ -16,6 +16,7 @@
 #include <cstdint>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 
 static int64_t GetCurrentTimeNanosFromSystem() {
@@ -26,4 +27,5 @@
 }
 
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/get_current_time_posix.inc b/absl/time/internal/get_current_time_posix.inc
index 65474ca..4207200 100644
--- a/absl/time/internal/get_current_time_posix.inc
+++ b/absl/time/internal/get_current_time_posix.inc
@@ -7,6 +7,7 @@
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 
 static int64_t GetCurrentTimeNanosFromSystem() {
@@ -19,4 +20,5 @@
 }
 
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/test_util.cc b/absl/time/internal/test_util.cc
index 59166a7..9a485a0 100644
--- a/absl/time/internal/test_util.cc
+++ b/absl/time/internal/test_util.cc
@@ -18,12 +18,14 @@
 #include <cstddef>
 #include <cstring>
 
+#include "absl/base/config.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/time/internal/cctz/include/cctz/zone_info_source.h"
 
 namespace cctz = absl::time_internal::cctz;
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 
 TimeZone LoadTimeZone(const std::string& name) {
@@ -33,9 +35,11 @@
 }
 
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 namespace cctz_extension {
 namespace {
@@ -116,8 +120,12 @@
 
 }  // namespace
 
+#if !defined(__MINGW32__)
+// MinGW does not support the weak symbol extension mechanism.
 ZoneInfoSourceFactory zone_info_source_factory = TestFactory;
+#endif
 
 }  // namespace cctz_extension
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/internal/test_util.h b/absl/time/internal/test_util.h
index d7319ea..5c4bf1f 100644
--- a/absl/time/internal/test_util.h
+++ b/absl/time/internal/test_util.h
@@ -20,12 +20,14 @@
 #include "absl/time/time.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace time_internal {
 
 // Loads the named timezone, but dies on any failure.
 absl::TimeZone LoadTimeZone(const std::string& name);
 
 }  // namespace time_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_INTERNAL_TEST_UTIL_H_
diff --git a/absl/time/time.cc b/absl/time/time.cc
index 6a387bc..1ec2026 100644
--- a/absl/time/time.cc
+++ b/absl/time/time.cc
@@ -47,6 +47,7 @@
 namespace cctz = absl::time_internal::cctz;
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace {
 
@@ -59,9 +60,10 @@
 inline int64_t FloorToUnit(absl::Duration d, absl::Duration unit) {
   absl::Duration rem;
   int64_t q = absl::IDivDuration(d, unit, &rem);
-  return (q > 0 ||
-          rem >= ZeroDuration() ||
-          q == std::numeric_limits<int64_t>::min()) ? q : q - 1;
+  return (q > 0 || rem >= ZeroDuration() ||
+          q == std::numeric_limits<int64_t>::min())
+             ? q
+             : q - 1;
 }
 
 inline absl::Time::Breakdown InfiniteFutureBreakdown() {
@@ -430,9 +432,17 @@
 }
 
 absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
-  const CivilSecond cs(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
-                       tm.tm_hour, tm.tm_min, tm.tm_sec);
-  const auto ti = tz.At(cs);
+  civil_year_t tm_year = tm.tm_year;
+  // Avoids years that are too extreme for CivilSecond to normalize.
+  if (tm_year > 300000000000ll) return InfiniteFuture();
+  if (tm_year < -300000000000ll) return InfinitePast();
+  int tm_mon = tm.tm_mon;
+  if (tm_mon == std::numeric_limits<int>::max()) {
+    tm_mon -= 12;
+    tm_year += 1;
+  }
+  const auto ti = tz.At(CivilSecond(tm_year + 1900, tm_mon + 1, tm.tm_mday,
+                                    tm.tm_hour, tm.tm_min, tm.tm_sec));
   return tm.tm_isdst == 0 ? ti.post : ti.pre;
 }
 
@@ -486,4 +496,5 @@
   return tm;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/time/time.h b/absl/time/time.h
index 9c8f317..7250803 100644
--- a/absl/time/time.h
+++ b/absl/time/time.h
@@ -83,11 +83,13 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/base/macros.h"
 #include "absl/strings/string_view.h"
 #include "absl/time/civil_time.h"
 #include "absl/time/internal/cctz/include/cctz/time_zone.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 class Duration;  // Defined below
 class Time;      // Defined below
@@ -421,7 +423,9 @@
 template <typename T, time_internal::EnableIfFloat<T> = 0>
 Duration Seconds(T n) {
   if (n >= 0) {  // Note: `NaN >= 0` is false.
-    if (n >= (std::numeric_limits<int64_t>::max)()) return InfiniteDuration();
+    if (n >= static_cast<T>((std::numeric_limits<int64_t>::max)())) {
+      return InfiniteDuration();
+    }
     return time_internal::MakePosDoubleDuration(n);
   } else {
     if (std::isnan(n))
@@ -541,11 +545,15 @@
 // suffix.  The valid suffixes are "ns", "us" "ms", "s", "m", and "h".
 // Simple examples include "300ms", "-1.5h", and "2h45m".  Parses "0" as
 // `ZeroDuration()`. Parses "inf" and "-inf" as +/- `InfiniteDuration()`.
-bool ParseDuration(const std::string& dur_string, Duration* d);
+bool ParseDuration(absl::string_view dur_string, Duration* d);
 
 // Support for flag values of type Duration. Duration flags must be specified
 // in a format that is valid input for absl::ParseDuration().
+bool AbslParseFlag(absl::string_view text, Duration* dst, std::string* error);
+std::string AbslUnparseFlag(Duration d);
+ABSL_DEPRECATED("Use AbslParseFlag() instead.")
 bool ParseFlag(const std::string& text, Duration* dst, std::string* error);
+ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
 std::string UnparseFlag(Duration d);
 
 // Time
@@ -631,7 +639,7 @@
   // Deprecated. Use `absl::TimeZone::CivilInfo`.
   struct
       Breakdown {
-    int64_t year;          // year (e.g., 2013)
+    int64_t year;        // year (e.g., 2013)
     int month;           // month of year [1:12]
     int day;             // day of month [1:31]
     int hour;            // hour of day [0:23]
@@ -815,7 +823,11 @@
 // Additionally, if you'd like to specify a time as a count of
 // seconds/milliseconds/etc from the Unix epoch, use an absl::Duration flag
 // and add that duration to absl::UnixEpoch() to get an absl::Time.
+bool AbslParseFlag(absl::string_view text, Time* t, std::string* error);
+std::string AbslUnparseFlag(Time t);
+ABSL_DEPRECATED("Use AbslParseFlag() instead.")
 bool ParseFlag(const std::string& text, Time* t, std::string* error);
+ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
 std::string UnparseFlag(Time t);
 
 // TimeZone
@@ -1009,13 +1021,13 @@
 // Loads the named zone. May perform I/O on the initial load of the named
 // zone. If the name is invalid, or some other kind of error occurs, returns
 // `false` and `*tz` is set to the UTC time zone.
-inline bool LoadTimeZone(const std::string& name, TimeZone* tz) {
+inline bool LoadTimeZone(absl::string_view name, TimeZone* tz) {
   if (name == "localtime") {
     *tz = TimeZone(time_internal::cctz::local_time_zone());
     return true;
   }
   time_internal::cctz::time_zone cz;
-  const bool b = time_internal::cctz::load_time_zone(name, &cz);
+  const bool b = time_internal::cctz::load_time_zone(std::string(name), &cz);
   *tz = TimeZone(cz);
   return b;
 }
@@ -1191,15 +1203,15 @@
 // time with UTC offset.  Also note the use of "%Y": RFC3339 mandates that
 // years have exactly four digits, but we allow them to take their natural
 // width.
-extern const char RFC3339_full[];  // %Y-%m-%dT%H:%M:%E*S%Ez
-extern const char RFC3339_sec[];   // %Y-%m-%dT%H:%M:%S%Ez
+ABSL_DLL extern const char RFC3339_full[];  // %Y-%m-%d%ET%H:%M:%E*S%Ez
+ABSL_DLL extern const char RFC3339_sec[];   // %Y-%m-%d%ET%H:%M:%S%Ez
 
 // RFC1123_full
 // RFC1123_no_wday
 //
 // FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings.
-extern const char RFC1123_full[];     // %a, %d %b %E4Y %H:%M:%S %z
-extern const char RFC1123_no_wday[];  // %d %b %E4Y %H:%M:%S %z
+ABSL_DLL extern const char RFC1123_full[];     // %a, %d %b %E4Y %H:%M:%S %z
+ABSL_DLL extern const char RFC1123_no_wday[];  // %d %b %E4Y %H:%M:%S %z
 
 // FormatTime()
 //
@@ -1214,6 +1226,7 @@
 //   - %E#f - Fractional seconds with # digits of precision
 //   - %E*f - Fractional seconds with full precision (a literal '*')
 //   - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
+//   - %ET  - The RFC3339 "date-time" separator "T"
 //
 // Note that %E0S behaves like %S, and %E0f produces no characters.  In
 // contrast %E*f always produces at least one digit, which may be '0'.
@@ -1237,7 +1250,7 @@
 // `absl::InfinitePast()`, the returned string will be exactly "infinite-past".
 // In both cases the given format string and `absl::TimeZone` are ignored.
 //
-std::string FormatTime(const std::string& format, Time t, TimeZone tz);
+std::string FormatTime(absl::string_view format, Time t, TimeZone tz);
 
 // Convenience functions that format the given time using the RFC3339_full
 // format.  The first overload uses the provided TimeZone, while the second
@@ -1256,7 +1269,8 @@
 // returns the corresponding `absl::Time`. Uses strftime()-like formatting
 // options, with the same extensions as FormatTime(), but with the
 // exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f.  %Ez
-// and %E*z also accept the same inputs.
+// and %E*z also accept the same inputs, which (along with %z) includes
+// 'z' and 'Z' as synonyms for +00:00.  %ET accepts either 'T' or 't'.
 //
 // %Y consumes as many numeric characters as it can, so the matching data
 // should always be terminated with a non-numeric.  %E4Y always consumes
@@ -1298,7 +1312,7 @@
 // If the input string is "infinite-past", the returned `absl::Time` will be
 // `absl::InfinitePast()` and `true` will be returned.
 //
-bool ParseTime(const std::string& format, const std::string& input, Time* time,
+bool ParseTime(absl::string_view format, absl::string_view input, Time* time,
                std::string* err);
 
 // Like ParseTime() above, but if the format string does not contain a UTC
@@ -1308,7 +1322,7 @@
 // of ambiguity or non-existence, in which case the "pre" time (as defined
 // by TimeZone::TimeInfo) is returned.  For these reasons we recommend that
 // all date/time strings include a UTC offset so they're context independent.
-bool ParseTime(const std::string& format, const std::string& input, TimeZone tz,
+bool ParseTime(absl::string_view format, absl::string_view input, TimeZone tz,
                Time* time, std::string* err);
 
 // ============================================================================
@@ -1333,8 +1347,8 @@
 // it's positive and can be converted to int64_t without risk of UB.
 inline Duration MakePosDoubleDuration(double n) {
   const int64_t int_secs = static_cast<int64_t>(n);
-  const uint32_t ticks =
-      static_cast<uint32_t>((n - int_secs) * kTicksPerSecond + 0.5);
+  const uint32_t ticks = static_cast<uint32_t>(
+      (n - static_cast<double>(int_secs)) * kTicksPerSecond + 0.5);
   return ticks < kTicksPerSecond
              ? MakeDuration(int_secs, ticks)
              : MakeDuration(int_secs + 1, ticks - kTicksPerSecond);
@@ -1401,8 +1415,7 @@
 // IsValidRep64<T>(0) is true if the expression `int64_t{std::declval<T>()}` is
 // valid. That is, if a T can be assigned to an int64_t without narrowing.
 template <typename T>
-constexpr auto IsValidRep64(int)
-    -> decltype(int64_t{std::declval<T>()}, bool()) {
+constexpr auto IsValidRep64(int) -> decltype(int64_t{std::declval<T>()} == 0) {
   return true;
 }
 template <typename T>
@@ -1481,12 +1494,10 @@
 constexpr bool operator<(Duration lhs, Duration rhs) {
   return time_internal::GetRepHi(lhs) != time_internal::GetRepHi(rhs)
              ? time_internal::GetRepHi(lhs) < time_internal::GetRepHi(rhs)
-             : time_internal::GetRepHi(lhs) ==
-                       (std::numeric_limits<int64_t>::min)()
-                   ? time_internal::GetRepLo(lhs) + 1 <
-                         time_internal::GetRepLo(rhs) + 1
-                   : time_internal::GetRepLo(lhs) <
-                         time_internal::GetRepLo(rhs);
+         : time_internal::GetRepHi(lhs) == (std::numeric_limits<int64_t>::min)()
+             ? time_internal::GetRepLo(lhs) + 1 <
+                   time_internal::GetRepLo(rhs) + 1
+             : time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs);
 }
 
 constexpr bool operator==(Duration lhs, Duration rhs) {
@@ -1564,6 +1575,7 @@
   return time_internal::FromUnixDuration(Seconds(t));
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TIME_TIME_H_
diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc
index 37af39d..cde9423 100644
--- a/absl/time/time_test.cc
+++ b/absl/time/time_test.cc
@@ -27,6 +27,7 @@
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/numeric/int128.h"
 #include "absl/time/clock.h"
 #include "absl/time/internal/test_util.h"
 
@@ -57,8 +58,7 @@
 // timespec ts1, ts2;
 // EXPECT_THAT(ts1, TimespecMatcher(ts2));
 MATCHER_P(TimespecMatcher, ts, "") {
-  if (ts.tv_sec == arg.tv_sec && ts.tv_nsec == arg.tv_nsec)
-    return true;
+  if (ts.tv_sec == arg.tv_sec && ts.tv_nsec == arg.tv_nsec) return true;
   *result_listener << "expected: {" << ts.tv_sec << ", " << ts.tv_nsec << "} ";
   *result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_nsec << "}";
   return false;
@@ -68,8 +68,7 @@
 // timeval tv1, tv2;
 // EXPECT_THAT(tv1, TimevalMatcher(tv2));
 MATCHER_P(TimevalMatcher, tv, "") {
-  if (tv.tv_sec == arg.tv_sec && tv.tv_usec == arg.tv_usec)
-    return true;
+  if (tv.tv_sec == arg.tv_sec && tv.tv_usec == arg.tv_usec) return true;
   *result_listener << "expected: {" << tv.tv_sec << ", " << tv.tv_usec << "} ";
   *result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_usec << "}";
   return false;
@@ -102,7 +101,7 @@
   EXPECT_EQ(a, b);
   EXPECT_EQ(a, c);
   EXPECT_EQ(b, c);
-  b = c;       // Assignment
+  b = c;  // Assignment
   EXPECT_EQ(a, b);
   EXPECT_EQ(a, c);
   EXPECT_EQ(b, c);
@@ -227,6 +226,9 @@
   constexpr absl::Time t = absl::UnixEpoch();  // Any finite time.
   static_assert(t < ifuture, "");
   static_assert(t > ipast, "");
+
+  EXPECT_EQ(ifuture, t + absl::InfiniteDuration());
+  EXPECT_EQ(ipast, t - absl::InfiniteDuration());
 }
 
 TEST(Time, FloorConversion) {
@@ -357,19 +359,21 @@
   const int64_t min_plus_1 = std::numeric_limits<int64_t>::min() + 1;
   EXPECT_EQ(min_plus_1, absl::ToUnixSeconds(absl::FromUnixSeconds(min_plus_1)));
   EXPECT_EQ(std::numeric_limits<int64_t>::min(),
-            absl::ToUnixSeconds(
-                absl::FromUnixSeconds(min_plus_1) - absl::Nanoseconds(1) / 2));
+            absl::ToUnixSeconds(absl::FromUnixSeconds(min_plus_1) -
+                                absl::Nanoseconds(1) / 2));
 
   // Tests flooring near positive infinity.
   EXPECT_EQ(std::numeric_limits<int64_t>::max(),
-            absl::ToUnixSeconds(absl::FromUnixSeconds(
-                std::numeric_limits<int64_t>::max()) + absl::Nanoseconds(1) / 2));
+            absl::ToUnixSeconds(
+                absl::FromUnixSeconds(std::numeric_limits<int64_t>::max()) +
+                absl::Nanoseconds(1) / 2));
   EXPECT_EQ(std::numeric_limits<int64_t>::max(),
             absl::ToUnixSeconds(
                 absl::FromUnixSeconds(std::numeric_limits<int64_t>::max())));
   EXPECT_EQ(std::numeric_limits<int64_t>::max() - 1,
-            absl::ToUnixSeconds(absl::FromUnixSeconds(
-                std::numeric_limits<int64_t>::max()) - absl::Nanoseconds(1) / 2));
+            absl::ToUnixSeconds(
+                absl::FromUnixSeconds(std::numeric_limits<int64_t>::max()) -
+                absl::Nanoseconds(1) / 2));
 }
 
 TEST(Time, RoundtripConversion) {
@@ -575,6 +579,50 @@
             absl::ToChronoTime(absl::UnixEpoch() - tick));
 }
 
+// Check that absl::int128 works as a std::chrono::duration representation.
+TEST(Time, Chrono128) {
+  // Define a std::chrono::time_point type whose time[sic]_since_epoch() is
+  // a signed 128-bit count of attoseconds. This has a range and resolution
+  // (currently) beyond those of absl::Time, and undoubtedly also beyond those
+  // of std::chrono::system_clock::time_point.
+  //
+  // Note: The to/from-chrono support should probably be updated to handle
+  // such wide representations.
+  using Timestamp =
+      std::chrono::time_point<std::chrono::system_clock,
+                              std::chrono::duration<absl::int128, std::atto>>;
+
+  // Expect that we can round-trip the std::chrono::system_clock::time_point
+  // extremes through both absl::Time and Timestamp, and that Timestamp can
+  // handle the (current) absl::Time extremes.
+  //
+  // Note: We should use std::chrono::floor() instead of time_point_cast(),
+  // but floor() is only available since c++17.
+  for (const auto tp : {std::chrono::system_clock::time_point::min(),
+                        std::chrono::system_clock::time_point::max()}) {
+    EXPECT_EQ(tp, absl::ToChronoTime(absl::FromChrono(tp)));
+    EXPECT_EQ(tp, std::chrono::time_point_cast<
+                      std::chrono::system_clock::time_point::duration>(
+                      std::chrono::time_point_cast<Timestamp::duration>(tp)));
+  }
+  Timestamp::duration::rep v = std::numeric_limits<int64_t>::min();
+  v *= Timestamp::duration::period::den;
+  auto ts = Timestamp(Timestamp::duration(v));
+  ts += std::chrono::duration<int64_t, std::atto>(0);
+  EXPECT_EQ(std::numeric_limits<int64_t>::min(),
+            ts.time_since_epoch().count() / Timestamp::duration::period::den);
+  EXPECT_EQ(0,
+            ts.time_since_epoch().count() % Timestamp::duration::period::den);
+  v = std::numeric_limits<int64_t>::max();
+  v *= Timestamp::duration::period::den;
+  ts = Timestamp(Timestamp::duration(v));
+  ts += std::chrono::duration<int64_t, std::atto>(999999999750000000);
+  EXPECT_EQ(std::numeric_limits<int64_t>::max(),
+            ts.time_since_epoch().count() / Timestamp::duration::period::den);
+  EXPECT_EQ(999999999750000000,
+            ts.time_since_epoch().count() % Timestamp::duration::period::den);
+}
+
 TEST(Time, TimeZoneAt) {
   const absl::TimeZone nyc =
       absl::time_internal::LoadTimeZone("America/New_York");
@@ -795,6 +843,30 @@
   tm.tm_isdst = 1;
   t = FromTM(tm, nyc);
   EXPECT_EQ("2014-03-09T03:30:42-04:00", absl::FormatTime(t, nyc));  // DST
+
+  // Adjusts tm to refer to a time with a year larger than 2147483647.
+  tm.tm_year = 2147483647 - 1900 + 1;
+  tm.tm_mon = 6 - 1;
+  tm.tm_mday = 28;
+  tm.tm_hour = 1;
+  tm.tm_min = 2;
+  tm.tm_sec = 3;
+  tm.tm_isdst = -1;
+  t = FromTM(tm, absl::UTCTimeZone());
+  EXPECT_EQ("2147483648-06-28T01:02:03+00:00",
+            absl::FormatTime(t, absl::UTCTimeZone()));
+
+  // Adjusts tm to refer to a time with a very large month.
+  tm.tm_year = 2019 - 1900;
+  tm.tm_mon = 2147483647;
+  tm.tm_mday = 28;
+  tm.tm_hour = 1;
+  tm.tm_min = 2;
+  tm.tm_sec = 3;
+  tm.tm_isdst = -1;
+  t = FromTM(tm, absl::UTCTimeZone());
+  EXPECT_EQ("178958989-08-28T01:02:03+00:00",
+            absl::FormatTime(t, absl::UTCTimeZone()));
 }
 
 TEST(Time, TMRoundTrip) {
@@ -976,15 +1048,15 @@
 
   // Checks how TimeZone::At() saturates on infinities.
   auto ci = utc.At(absl::InfiniteFuture());
-  EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::max(), 12, 31, 23,
-                            59, 59, 0, false);
+  EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::max(), 12, 31, 23, 59, 59,
+                    0, false);
   EXPECT_EQ(absl::InfiniteDuration(), ci.subsecond);
   EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(ci.cs));
   EXPECT_EQ(365, absl::GetYearDay(ci.cs));
   EXPECT_STREQ("-00", ci.zone_abbr);  // artifact of TimeZone::At()
   ci = utc.At(absl::InfinitePast());
-  EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::min(), 1, 1, 0, 0,
-                            0, 0, false);
+  EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::min(), 1, 1, 0, 0, 0, 0,
+                    false);
   EXPECT_EQ(-absl::InfiniteDuration(), ci.subsecond);
   EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(ci.cs));
   EXPECT_EQ(1, absl::GetYearDay(ci.cs));
@@ -998,7 +1070,8 @@
   EXPECT_EQ("292277026596-12-04T15:30:07+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
   EXPECT_EQ(
-      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()), t);
+      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()),
+      t);
 
   // Checks that we can also get the maximal Time value for a far-east zone.
   const absl::TimeZone plus14 = absl::FixedTimeZone(14 * 60 * 60);
@@ -1006,7 +1079,8 @@
   EXPECT_EQ("292277026596-12-05T05:30:07+14:00",
             absl::FormatTime(absl::RFC3339_full, t, plus14));
   EXPECT_EQ(
-      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()), t);
+      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()),
+      t);
 
   // One second later should push us to infinity.
   t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 8), utc);
@@ -1020,7 +1094,8 @@
   EXPECT_EQ("-292277022657-01-27T08:29:52+00:00",
             absl::FormatTime(absl::RFC3339_full, t, utc));
   EXPECT_EQ(
-      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()), t);
+      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()),
+      t);
 
   // Checks that we can also get the minimal Time value for a far-west zone.
   const absl::TimeZone minus12 = absl::FixedTimeZone(-12 * 60 * 60);
@@ -1029,7 +1104,8 @@
   EXPECT_EQ("-292277022657-01-26T20:29:52-12:00",
             absl::FormatTime(absl::RFC3339_full, t, minus12));
   EXPECT_EQ(
-      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()), t);
+      absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()),
+      t);
 
   // One second before should push us to -infinity.
   t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 51), utc);
@@ -1102,14 +1178,13 @@
   const int kMin = std::numeric_limits<int>::min();
   absl::Time t;
 
-  t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::max(),
-                         kMax, kMax, kMax, kMax, kMax, utc);
+  t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::max(), kMax,
+                         kMax, kMax, kMax, kMax, utc);
   EXPECT_EQ("infinite-future",
             absl::FormatTime(ymdhms, t, utc));  // no overflow
-  t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::min(),
-                         kMin, kMin, kMin, kMin, kMin, utc);
-  EXPECT_EQ("infinite-past",
-            absl::FormatTime(ymdhms, t, utc));  // no overflow
+  t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::min(), kMin,
+                         kMin, kMin, kMin, kMin, utc);
+  EXPECT_EQ("infinite-past", absl::FormatTime(ymdhms, t, utc));  // no overflow
 
   // Check normalization.
   EXPECT_TRUE(absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, utc).normalized);
diff --git a/absl/time/time_zone_test.cc b/absl/time/time_zone_test.cc
index 8f1e74a..229fcfc 100644
--- a/absl/time/time_zone_test.cc
+++ b/absl/time/time_zone_test.cc
@@ -88,7 +88,7 @@
   EXPECT_FALSE(LoadTimeZone("Invalid/TimeZone", &tz));
   EXPECT_EQ(absl::UTCTimeZone(), tz);  // guaranteed fallback to UTC
 
-  // Loading an empty std::string timezone should fail.
+  // Loading an empty string timezone should fail.
   tz = absl::time_internal::LoadTimeZone("America/Los_Angeles");
   EXPECT_FALSE(LoadTimeZone("", &tz));
   EXPECT_EQ(absl::UTCTimeZone(), tz);  // guaranteed fallback to UTC
diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel
index 236c24b..83be936 100644
--- a/absl/types/BUILD.bazel
+++ b/absl/types/BUILD.bazel
@@ -12,7 +12,6 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
 
 load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
 load(
@@ -24,7 +23,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "any",
@@ -35,6 +34,7 @@
         ":bad_any_cast",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/base:fast_type_id",
         "//absl/meta:type_traits",
         "//absl/utility",
     ],
@@ -209,6 +209,44 @@
 )
 
 cc_library(
+    name = "conformance_testing",
+    testonly = 1,
+    hdrs = [
+        "internal/conformance_aliases.h",
+        "internal/conformance_archetype.h",
+        "internal/conformance_profile.h",
+        "internal/conformance_testing.h",
+        "internal/conformance_testing_helpers.h",
+        "internal/parentheses.h",
+        "internal/transform_args.h",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/algorithm:container",
+        "//absl/meta:type_traits",
+        "//absl/strings",
+        "//absl/utility",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+cc_test(
+    name = "conformance_testing_test",
+    size = "small",
+    srcs = [
+        "internal/conformance_testing_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":conformance_testing",
+        "//absl/meta:type_traits",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
     name = "variant",
     srcs = ["internal/variant.h"],
     hdrs = ["variant.h"],
diff --git a/absl/types/CMakeLists.txt b/absl/types/CMakeLists.txt
index 952efc3..3f99ad8 100644
--- a/absl/types/CMakeLists.txt
+++ b/absl/types/CMakeLists.txt
@@ -24,6 +24,7 @@
     absl::bad_any_cast
     absl::config
     absl::core_headers
+    absl::fast_type_id
     absl::type_traits
     absl::utility
   PUBLIC
@@ -240,6 +241,58 @@
 
 absl_cc_library(
   NAME
+    conformance_testing
+  HDRS
+    "internal/conformance_aliases.h"
+    "internal/conformance_archetype.h"
+    "internal/conformance_profile.h"
+    "internal/conformance_testing.h"
+    "internal/conformance_testing_helpers.h"
+    "internal/parentheses.h"
+    "internal/transform_args.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  DEPS
+    absl::algorithm
+    absl::debugging
+    absl::type_traits
+    absl::strings
+    absl::utility
+    gmock_main
+  TESTONLY
+)
+
+absl_cc_test(
+  NAME
+    conformance_testing_test
+  SRCS
+    "internal/conformance_testing_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+    ${ABSL_EXCEPTIONS_FLAG}
+  LINKOPTS
+    ${ABSL_EXCEPTIONS_FLAG_LINKOPTS}
+  DEPS
+    absl::conformance_testing
+    absl::type_traits
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    conformance_testing_test_no_exceptions
+  SRCS
+    "internal/conformance_testing_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::conformance_testing
+    absl::type_traits
+    gmock_main
+)
+
+absl_cc_library(
+  NAME
     variant
   HDRS
     "variant.h"
diff --git a/absl/types/any.h b/absl/types/any.h
index d2e2533..fc5a074 100644
--- a/absl/types/any.h
+++ b/absl/types/any.h
@@ -47,27 +47,29 @@
 // this abstraction, make sure that you should not instead be rewriting your
 // code to be more specific.
 //
-// Abseil expects to release an `absl::variant` type shortly (a C++11 compatible
-// version of the C++17 `std::variant), which is generally preferred for use
-// over `absl::any`.
+// Abseil has also released an `absl::variant` type (a C++11 compatible version
+// of the C++17 `std::variant`), which is generally preferred for use over
+// `absl::any`.
 #ifndef ABSL_TYPES_ANY_H_
 #define ABSL_TYPES_ANY_H_
 
 #include "absl/base/config.h"
 #include "absl/utility/utility.h"
 
-#ifdef ABSL_HAVE_STD_ANY
+#ifdef ABSL_USES_STD_ANY
 
 #include <any>  // IWYU pragma: export
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 using std::any;
 using std::any_cast;
 using std::bad_any_cast;
 using std::make_any;
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#else  // ABSL_HAVE_STD_ANY
+#else  // ABSL_USES_STD_ANY
 
 #include <algorithm>
 #include <cstddef>
@@ -78,6 +80,7 @@
 #include <typeinfo>
 #include <utility>
 
+#include "absl/base/internal/fast_type_id.h"
 #include "absl/base/macros.h"
 #include "absl/meta/type_traits.h"
 #include "absl/types/bad_any_cast.h"
@@ -91,26 +94,7 @@
 #endif  // !defined(__GNUC__) || defined(__GXX_RTTI)
 
 namespace absl {
-
-namespace any_internal {
-
-template <typename Type>
-struct TypeTag {
-  constexpr static char dummy_var = 0;
-};
-
-template <typename Type>
-constexpr char TypeTag<Type>::dummy_var;
-
-// FastTypeId<Type>() evaluates at compile/link-time to a unique pointer for the
-// passed in type. These are meant to be good match for keys into maps or
-// straight up comparisons.
-template<typename Type>
-constexpr inline const void* FastTypeId() {
-  return &TypeTag<Type>::dummy_var;
-}
-
-}  // namespace any_internal
+ABSL_NAMESPACE_BEGIN
 
 class any;
 
@@ -182,7 +166,7 @@
 // object, when containing a value, must contain a value type; storing a
 // reference type is neither desired nor supported.
 //
-// An `absl::any` can only store a type that is copy-constructable; move-only
+// An `absl::any` can only store a type that is copy-constructible; move-only
 // types are not allowed within an `any` object.
 //
 // Example:
@@ -190,7 +174,7 @@
 //   auto a = absl::any(65);                 // Literal, copyable
 //   auto b = absl::any(std::vector<int>()); // Default-initialized, copyable
 //   std::unique_ptr<Foo> my_foo;
-//   auto c = absl::any(std::move(my_foo));  // Error, not copy-constructable
+//   auto c = absl::any(std::move(my_foo));  // Error, not copy-constructible
 //
 // Note that `absl::any` makes use of decayed types (`absl::decay_t` in this
 // context) to remove const-volatile qualifiers (known as "cv qualifiers"),
@@ -420,11 +404,11 @@
     using NormalizedType =
         typename std::remove_cv<typename std::remove_reference<T>::type>::type;
 
-    return any_internal::FastTypeId<NormalizedType>();
+    return base_internal::FastTypeId<NormalizedType>();
   }
 
   const void* GetObjTypeId() const {
-    return obj_ ? obj_->ObjTypeId() : any_internal::FastTypeId<void>();
+    return obj_ ? obj_->ObjTypeId() : base_internal::FastTypeId<void>();
   }
 
   // `absl::any` nonmember functions //
@@ -534,10 +518,11 @@
              : nullptr;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #undef ABSL_ANY_DETAIL_HAS_RTTI
 
-#endif  // ABSL_HAVE_STD_ANY
+#endif  // ABSL_USES_STD_ANY
 
 #endif  // ABSL_TYPES_ANY_H_
diff --git a/absl/types/any_exception_safety_test.cc b/absl/types/any_exception_safety_test.cc
index 17d7f5d..31c1140 100644
--- a/absl/types/any_exception_safety_test.cc
+++ b/absl/types/any_exception_safety_test.cc
@@ -18,7 +18,7 @@
 
 // This test is a no-op when absl::any is an alias for std::any and when
 // exceptions are not enabled.
-#if !defined(ABSL_HAVE_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)
+#if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)
 
 #include <typeinfo>
 #include <vector>
@@ -170,4 +170,4 @@
 
 }  // namespace
 
-#endif  // #if !defined(ABSL_HAVE_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)
+#endif  // #if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/absl/types/any_test.cc b/absl/types/any_test.cc
index 4a848ae..70e4ba2 100644
--- a/absl/types/any_test.cc
+++ b/absl/types/any_test.cc
@@ -15,7 +15,7 @@
 #include "absl/types/any.h"
 
 // This test is a no-op when absl::any is an alias for std::any.
-#if !defined(ABSL_HAVE_STD_ANY)
+#if !defined(ABSL_USES_STD_ANY)
 
 #include <initializer_list>
 #include <type_traits>
@@ -642,7 +642,7 @@
 // Tests for Exception Behavior //
 //////////////////////////////////
 
-#if defined(ABSL_HAVE_STD_ANY)
+#if defined(ABSL_USES_STD_ANY)
 
 // If using a std `any` implementation, we can't check for a specific message.
 #define ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(...)                      \
@@ -656,7 +656,7 @@
   ABSL_BASE_INTERNAL_EXPECT_FAIL((__VA_ARGS__), absl::bad_any_cast, \
                                  "Bad any cast")
 
-#endif  // defined(ABSL_HAVE_STD_ANY)
+#endif  // defined(ABSL_USES_STD_ANY)
 
 TEST(AnyTest, ThrowBadAlloc) {
   {
@@ -764,7 +764,7 @@
     BadCopyable bad;
     absl::any target(absl::in_place_type<int>);
     ABSL_ANY_TEST_EXPECT_BAD_COPY(target.emplace<BadCopyable>(bad));
-#if defined(ABSL_HAVE_STD_ANY) && defined(__GLIBCXX__)
+#if defined(ABSL_USES_STD_ANY) && defined(__GLIBCXX__)
     // libstdc++ std::any::emplace() implementation (as of 7.2) has a bug: if an
     // exception is thrown, *this contains a value.
 #define ABSL_GLIBCXX_ANY_EMPLACE_EXCEPTION_BUG 1
@@ -778,4 +778,4 @@
 
 }  // namespace
 
-#endif  // #if !defined(ABSL_HAVE_STD_ANY)
+#endif  // #if !defined(ABSL_USES_STD_ANY)
diff --git a/absl/types/bad_any_cast.cc b/absl/types/bad_any_cast.cc
index 505919a..b0592cc 100644
--- a/absl/types/bad_any_cast.cc
+++ b/absl/types/bad_any_cast.cc
@@ -14,7 +14,7 @@
 
 #include "absl/types/bad_any_cast.h"
 
-#ifndef ABSL_HAVE_STD_ANY
+#ifndef ABSL_USES_STD_ANY
 
 #include <cstdlib>
 
@@ -22,6 +22,7 @@
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 bad_any_cast::~bad_any_cast() = default;
 
@@ -39,6 +40,7 @@
 }
 
 }  // namespace any_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_HAVE_STD_ANY
+#endif  // ABSL_USES_STD_ANY
diff --git a/absl/types/bad_any_cast.h b/absl/types/bad_any_cast.h
index 8d020ed..114cef8 100644
--- a/absl/types/bad_any_cast.h
+++ b/absl/types/bad_any_cast.h
@@ -25,17 +25,20 @@
 
 #include "absl/base/config.h"
 
-#ifdef ABSL_HAVE_STD_ANY
+#ifdef ABSL_USES_STD_ANY
 
 #include <any>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 using std::bad_any_cast;
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#else  // ABSL_HAVE_STD_ANY
+#else  // ABSL_USES_STD_ANY
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // -----------------------------------------------------------------------------
 // bad_any_cast
@@ -64,8 +67,9 @@
 [[noreturn]] void ThrowBadAnyCast();
 
 }  // namespace any_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_HAVE_STD_ANY
+#endif  // ABSL_USES_STD_ANY
 
 #endif  // ABSL_TYPES_BAD_ANY_CAST_H_
diff --git a/absl/types/bad_optional_access.cc b/absl/types/bad_optional_access.cc
index a791c7c..26aca70 100644
--- a/absl/types/bad_optional_access.cc
+++ b/absl/types/bad_optional_access.cc
@@ -14,7 +14,7 @@
 
 #include "absl/types/bad_optional_access.h"
 
-#ifndef ABSL_HAVE_STD_OPTIONAL
+#ifndef ABSL_USES_STD_OPTIONAL
 
 #include <cstdlib>
 
@@ -22,6 +22,7 @@
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 bad_optional_access::~bad_optional_access() = default;
 
@@ -41,6 +42,7 @@
 }
 
 }  // namespace optional_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_HAVE_STD_OPTIONAL
+#endif  // ABSL_USES_STD_OPTIONAL
diff --git a/absl/types/bad_optional_access.h b/absl/types/bad_optional_access.h
index add5c45..a500286 100644
--- a/absl/types/bad_optional_access.h
+++ b/absl/types/bad_optional_access.h
@@ -25,17 +25,20 @@
 
 #include "absl/base/config.h"
 
-#ifdef ABSL_HAVE_STD_OPTIONAL
+#ifdef ABSL_USES_STD_OPTIONAL
 
 #include <optional>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 using std::bad_optional_access;
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#else  // ABSL_HAVE_STD_OPTIONAL
+#else  // ABSL_USES_STD_OPTIONAL
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // -----------------------------------------------------------------------------
 // bad_optional_access
@@ -67,8 +70,9 @@
 [[noreturn]] void throw_bad_optional_access();
 
 }  // namespace optional_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_HAVE_STD_OPTIONAL
+#endif  // ABSL_USES_STD_OPTIONAL
 
 #endif  // ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
diff --git a/absl/types/bad_variant_access.cc b/absl/types/bad_variant_access.cc
index a4325c8..3dc88cc 100644
--- a/absl/types/bad_variant_access.cc
+++ b/absl/types/bad_variant_access.cc
@@ -14,7 +14,7 @@
 
 #include "absl/types/bad_variant_access.h"
 
-#ifndef ABSL_HAVE_STD_VARIANT
+#ifndef ABSL_USES_STD_VARIANT
 
 #include <cstdlib>
 #include <stdexcept>
@@ -23,6 +23,7 @@
 #include "absl/base/internal/raw_logging.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 //////////////////////////
 // [variant.bad.access] //
@@ -57,6 +58,7 @@
 }
 
 }  // namespace variant_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_HAVE_STD_VARIANT
+#endif  // ABSL_USES_STD_VARIANT
diff --git a/absl/types/bad_variant_access.h b/absl/types/bad_variant_access.h
index 637db43..095969f 100644
--- a/absl/types/bad_variant_access.h
+++ b/absl/types/bad_variant_access.h
@@ -25,17 +25,20 @@
 
 #include "absl/base/config.h"
 
-#ifdef ABSL_HAVE_STD_VARIANT
+#ifdef ABSL_USES_STD_VARIANT
 
 #include <variant>
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 using std::bad_variant_access;
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#else  // ABSL_HAVE_STD_VARIANT
+#else  // ABSL_USES_STD_VARIANT
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // -----------------------------------------------------------------------------
 // bad_variant_access
@@ -71,8 +74,9 @@
 [[noreturn]] void Rethrow();
 
 }  // namespace variant_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // ABSL_HAVE_STD_VARIANT
+#endif  // ABSL_USES_STD_VARIANT
 
 #endif  // ABSL_TYPES_BAD_VARIANT_ACCESS_H_
diff --git a/absl/types/compare.h b/absl/types/compare.h
index a213e0b..19b076e 100644
--- a/absl/types/compare.h
+++ b/absl/types/compare.h
@@ -39,6 +39,7 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace compare_internal {
 
 using value_type = int8_t;
@@ -85,7 +86,8 @@
 // incomplete types so they need to be defined after the types are complete.
 #ifdef __cpp_inline_variables
 
-#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name)
+// A no-op expansion that can be followed by a semicolon at class level.
+#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) static_assert(true, "")
 
 #define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \
   static const type name
@@ -98,7 +100,8 @@
 #define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) \
   ABSL_CONST_INIT static const T name
 
-#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name)
+// A no-op expansion that can be followed by a semicolon at class level.
+#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) static_assert(true, "")
 
 #define ABSL_COMPARE_INLINE_INIT(type, name, init) \
   template <typename T>                            \
@@ -175,6 +178,14 @@
                                    weak_equality v) noexcept {
     return 0 != v.value_;
   }
+  friend constexpr bool operator==(weak_equality v1,
+                                   weak_equality v2) noexcept {
+    return v1.value_ == v2.value_;
+  }
+  friend constexpr bool operator!=(weak_equality v1,
+                                   weak_equality v2) noexcept {
+    return v1.value_ != v2.value_;
+  }
 
  private:
   compare_internal::value_type value_;
@@ -218,6 +229,14 @@
                                    strong_equality v) noexcept {
     return 0 != v.value_;
   }
+  friend constexpr bool operator==(strong_equality v1,
+                                   strong_equality v2) noexcept {
+    return v1.value_ == v2.value_;
+  }
+  friend constexpr bool operator!=(strong_equality v1,
+                                   strong_equality v2) noexcept {
+    return v1.value_ != v2.value_;
+  }
 
  private:
   compare_internal::value_type value_;
@@ -305,6 +324,14 @@
                                    partial_ordering v) noexcept {
     return v.is_ordered() && 0 >= v.value_;
   }
+  friend constexpr bool operator==(partial_ordering v1,
+                                   partial_ordering v2) noexcept {
+    return v1.value_ == v2.value_;
+  }
+  friend constexpr bool operator!=(partial_ordering v1,
+                                   partial_ordering v2) noexcept {
+    return v1.value_ != v2.value_;
+  }
 
  private:
   compare_internal::value_type value_;
@@ -389,6 +416,14 @@
                                    weak_ordering v) noexcept {
     return 0 >= v.value_;
   }
+  friend constexpr bool operator==(weak_ordering v1,
+                                   weak_ordering v2) noexcept {
+    return v1.value_ == v2.value_;
+  }
+  friend constexpr bool operator!=(weak_ordering v1,
+                                   weak_ordering v2) noexcept {
+    return v1.value_ != v2.value_;
+  }
 
  private:
   compare_internal::value_type value_;
@@ -480,6 +515,14 @@
                                    strong_ordering v) noexcept {
     return 0 >= v.value_;
   }
+  friend constexpr bool operator==(strong_ordering v1,
+                                   strong_ordering v2) noexcept {
+    return v1.value_ == v2.value_;
+  }
+  friend constexpr bool operator!=(strong_ordering v1,
+                                   strong_ordering v2) noexcept {
+    return v1.value_ != v2.value_;
+  }
 
  private:
   compare_internal::value_type value_;
@@ -551,6 +594,7 @@
 }
 
 }  // namespace compare_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TYPES_COMPARE_H_
diff --git a/absl/types/compare_test.cc b/absl/types/compare_test.cc
index ee396fc..8095baf 100644
--- a/absl/types/compare_test.cc
+++ b/absl/types/compare_test.cc
@@ -18,6 +18,7 @@
 #include "absl/base/casts.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 // This is necessary to avoid a bunch of lint warnings suggesting that we use
@@ -30,6 +31,15 @@
   EXPECT_TRUE(Identity(0 == weak_equality::equivalent));
   EXPECT_TRUE(Identity(weak_equality::nonequivalent != 0));
   EXPECT_TRUE(Identity(0 != weak_equality::nonequivalent));
+  const weak_equality values[] = {weak_equality::equivalent,
+                                  weak_equality::nonequivalent};
+  for (const auto& lhs : values) {
+    for (const auto& rhs : values) {
+      const bool are_equal = &lhs == &rhs;
+      EXPECT_EQ(lhs == rhs, are_equal);
+      EXPECT_EQ(lhs != rhs, !are_equal);
+    }
+  }
 }
 
 TEST(Compare, StrongEquality) {
@@ -41,6 +51,18 @@
   EXPECT_TRUE(Identity(0 == strong_equality::equivalent));
   EXPECT_TRUE(Identity(strong_equality::nonequivalent != 0));
   EXPECT_TRUE(Identity(0 != strong_equality::nonequivalent));
+  const strong_equality values[] = {strong_equality::equal,
+                                    strong_equality::nonequal};
+  for (const auto& lhs : values) {
+    for (const auto& rhs : values) {
+      const bool are_equal = &lhs == &rhs;
+      EXPECT_EQ(lhs == rhs, are_equal);
+      EXPECT_EQ(lhs != rhs, !are_equal);
+    }
+  }
+  EXPECT_TRUE(Identity(strong_equality::equivalent == strong_equality::equal));
+  EXPECT_TRUE(
+      Identity(strong_equality::nonequivalent == strong_equality::nonequal));
 }
 
 TEST(Compare, PartialOrdering) {
@@ -64,6 +86,16 @@
   EXPECT_FALSE(Identity(0 > partial_ordering::unordered));
   EXPECT_FALSE(Identity(partial_ordering::unordered >= 0));
   EXPECT_FALSE(Identity(0 >= partial_ordering::unordered));
+  const partial_ordering values[] = {
+      partial_ordering::less, partial_ordering::equivalent,
+      partial_ordering::greater, partial_ordering::unordered};
+  for (const auto& lhs : values) {
+    for (const auto& rhs : values) {
+      const bool are_equal = &lhs == &rhs;
+      EXPECT_EQ(lhs == rhs, are_equal);
+      EXPECT_EQ(lhs != rhs, !are_equal);
+    }
+  }
 }
 
 TEST(Compare, WeakOrdering) {
@@ -77,6 +109,15 @@
   EXPECT_TRUE(Identity(0 < weak_ordering::greater));
   EXPECT_TRUE(Identity(weak_ordering::greater >= 0));
   EXPECT_TRUE(Identity(0 <= weak_ordering::greater));
+  const weak_ordering values[] = {
+      weak_ordering::less, weak_ordering::equivalent, weak_ordering::greater};
+  for (const auto& lhs : values) {
+    for (const auto& rhs : values) {
+      const bool are_equal = &lhs == &rhs;
+      EXPECT_EQ(lhs == rhs, are_equal);
+      EXPECT_EQ(lhs != rhs, !are_equal);
+    }
+  }
 }
 
 TEST(Compare, StrongOrdering) {
@@ -92,6 +133,16 @@
   EXPECT_TRUE(Identity(0 < strong_ordering::greater));
   EXPECT_TRUE(Identity(strong_ordering::greater >= 0));
   EXPECT_TRUE(Identity(0 <= strong_ordering::greater));
+  const strong_ordering values[] = {
+      strong_ordering::less, strong_ordering::equal, strong_ordering::greater};
+  for (const auto& lhs : values) {
+    for (const auto& rhs : values) {
+      const bool are_equal = &lhs == &rhs;
+      EXPECT_EQ(lhs == rhs, are_equal);
+      EXPECT_EQ(lhs != rhs, !are_equal);
+    }
+  }
+  EXPECT_TRUE(Identity(strong_ordering::equivalent == strong_ordering::equal));
 }
 
 TEST(Compare, Conversions) {
@@ -189,7 +240,7 @@
 
 struct WeakOrderingLess {
   template <typename T>
-  absl::weak_ordering operator()(const T &a, const T &b) const {
+  absl::weak_ordering operator()(const T& a, const T& b) const {
     return a < b ? absl::weak_ordering::less
                  : a == b ? absl::weak_ordering::equivalent
                           : absl::weak_ordering::greater;
@@ -223,10 +274,10 @@
 }
 
 TEST(CompareResultAsOrdering, SanityTest) {
-  EXPECT_TRUE(Identity(
-      absl::compare_internal::compare_result_as_ordering(-1) < 0));
-  EXPECT_FALSE(Identity(
-      absl::compare_internal::compare_result_as_ordering(-1) == 0));
+  EXPECT_TRUE(
+      Identity(absl::compare_internal::compare_result_as_ordering(-1) < 0));
+  EXPECT_FALSE(
+      Identity(absl::compare_internal::compare_result_as_ordering(-1) == 0));
   EXPECT_FALSE(
       Identity(absl::compare_internal::compare_result_as_ordering(-1) > 0));
   EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
@@ -236,31 +287,31 @@
   EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
                             weak_ordering::less) > 0));
 
-  EXPECT_FALSE(Identity(
-      absl::compare_internal::compare_result_as_ordering(0) < 0));
-  EXPECT_TRUE(Identity(
-      absl::compare_internal::compare_result_as_ordering(0) == 0));
-  EXPECT_FALSE(Identity(
-      absl::compare_internal::compare_result_as_ordering(0) > 0));
+  EXPECT_FALSE(
+      Identity(absl::compare_internal::compare_result_as_ordering(0) < 0));
+  EXPECT_TRUE(
+      Identity(absl::compare_internal::compare_result_as_ordering(0) == 0));
+  EXPECT_FALSE(
+      Identity(absl::compare_internal::compare_result_as_ordering(0) > 0));
   EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
-                           weak_ordering::equivalent) < 0));
+                            weak_ordering::equivalent) < 0));
   EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
-                            weak_ordering::equivalent) == 0));
+                           weak_ordering::equivalent) == 0));
   EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
                             weak_ordering::equivalent) > 0));
 
-  EXPECT_FALSE(Identity(
-      absl::compare_internal::compare_result_as_ordering(1) < 0));
-  EXPECT_FALSE(Identity(
-      absl::compare_internal::compare_result_as_ordering(1) == 0));
-  EXPECT_TRUE(Identity(
-      absl::compare_internal::compare_result_as_ordering(1) > 0));
+  EXPECT_FALSE(
+      Identity(absl::compare_internal::compare_result_as_ordering(1) < 0));
+  EXPECT_FALSE(
+      Identity(absl::compare_internal::compare_result_as_ordering(1) == 0));
+  EXPECT_TRUE(
+      Identity(absl::compare_internal::compare_result_as_ordering(1) > 0));
   EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
-                           weak_ordering::greater) < 0));
+                            weak_ordering::greater) < 0));
   EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
                             weak_ordering::greater) == 0));
   EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
-                            weak_ordering::greater) > 0));
+                           weak_ordering::greater) > 0));
 }
 
 TEST(DoThreeWayComparison, SanityTest) {
@@ -334,4 +385,5 @@
 #endif  // __cpp_inline_variables
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/types/internal/conformance_aliases.h b/absl/types/internal/conformance_aliases.h
new file mode 100644
index 0000000..0cc6884
--- /dev/null
+++ b/absl/types/internal/conformance_aliases.h
@@ -0,0 +1,447 @@
+// Copyright 2018 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// regularity_aliases.h
+// -----------------------------------------------------------------------------
+//
+// This file contains type aliases of common ConformanceProfiles and Archetypes
+// so that they can be directly used by name without creating them from scratch.
+
+#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_
+#define ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_
+
+#include "absl/types/internal/conformance_archetype.h"
+#include "absl/types/internal/conformance_profile.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace types_internal {
+
+// Creates both a Profile and a corresponding Archetype with root name "name".
+#define ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(name, ...)                \
+  struct name##Profile : __VA_ARGS__ {};                                    \
+                                                                            \
+  using name##Archetype = ::absl::types_internal::Archetype<name##Profile>; \
+                                                                            \
+  template <class AbslInternalProfileTag>                                   \
+  using name##Archetype##_ = ::absl::types_internal::Archetype<             \
+      ::absl::types_internal::StrongProfileTypedef<name##Profile,           \
+                                                   AbslInternalProfileTag>>
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasTrivialDefaultConstructor,
+    ConformanceProfile<default_constructible::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowDefaultConstructor,
+    ConformanceProfile<default_constructible::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasDefaultConstructor, ConformanceProfile<default_constructible::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasTrivialMoveConstructor, ConformanceProfile<default_constructible::maybe,
+                                                  move_constructible::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowMoveConstructor, ConformanceProfile<default_constructible::maybe,
+                                                  move_constructible::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasMoveConstructor,
+    ConformanceProfile<default_constructible::maybe, move_constructible::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasTrivialCopyConstructor,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowCopyConstructor,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasCopyConstructor,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasTrivialMoveAssign,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowMoveAssign,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasMoveAssign,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasTrivialCopyAssign,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowCopyAssign,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasCopyAssign,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasTrivialDestructor,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::maybe, destructible::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowDestructor,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::maybe, destructible::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasDestructor,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::maybe, destructible::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowEquality,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::maybe, destructible::maybe,
+                       equality_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasEquality,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::maybe, destructible::maybe,
+                       equality_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowInequality,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::maybe, destructible::maybe,
+                       equality_comparable::maybe,
+                       inequality_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasInequality,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::maybe, destructible::maybe,
+                       equality_comparable::maybe, inequality_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowLessThan,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::maybe, destructible::maybe,
+                       equality_comparable::maybe, inequality_comparable::maybe,
+                       less_than_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasLessThan,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::maybe, destructible::maybe,
+                       equality_comparable::maybe, inequality_comparable::maybe,
+                       less_than_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowLessEqual,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::maybe, destructible::maybe,
+                       equality_comparable::maybe, inequality_comparable::maybe,
+                       less_than_comparable::maybe,
+                       less_equal_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasLessEqual,
+    ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+                       copy_constructible::maybe, move_assignable::maybe,
+                       copy_assignable::maybe, destructible::maybe,
+                       equality_comparable::maybe, inequality_comparable::maybe,
+                       less_than_comparable::maybe,
+                       less_equal_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowGreaterEqual,
+    ConformanceProfile<
+        default_constructible::maybe, move_constructible::maybe,
+        copy_constructible::maybe, move_assignable::maybe,
+        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+        inequality_comparable::maybe, less_than_comparable::maybe,
+        less_equal_comparable::maybe, greater_equal_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasGreaterEqual,
+    ConformanceProfile<
+        default_constructible::maybe, move_constructible::maybe,
+        copy_constructible::maybe, move_assignable::maybe,
+        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+        inequality_comparable::maybe, less_than_comparable::maybe,
+        less_equal_comparable::maybe, greater_equal_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowGreaterThan,
+    ConformanceProfile<
+        default_constructible::maybe, move_constructible::maybe,
+        copy_constructible::maybe, move_assignable::maybe,
+        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+        inequality_comparable::maybe, less_than_comparable::maybe,
+        less_equal_comparable::maybe, greater_equal_comparable::maybe,
+        greater_than_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasGreaterThan,
+    ConformanceProfile<
+        default_constructible::maybe, move_constructible::maybe,
+        copy_constructible::maybe, move_assignable::maybe,
+        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+        inequality_comparable::maybe, less_than_comparable::maybe,
+        less_equal_comparable::maybe, greater_equal_comparable::maybe,
+        greater_than_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasNothrowSwap,
+    ConformanceProfile<
+        default_constructible::maybe, move_constructible::maybe,
+        copy_constructible::maybe, move_assignable::maybe,
+        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+        inequality_comparable::maybe, less_than_comparable::maybe,
+        less_equal_comparable::maybe, greater_equal_comparable::maybe,
+        greater_than_comparable::maybe, swappable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasSwap,
+    ConformanceProfile<
+        default_constructible::maybe, move_constructible::maybe,
+        copy_constructible::maybe, move_assignable::maybe,
+        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+        inequality_comparable::maybe, less_than_comparable::maybe,
+        less_equal_comparable::maybe, greater_equal_comparable::maybe,
+        greater_than_comparable::maybe, swappable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HasStdHashSpecialization,
+    ConformanceProfile<
+        default_constructible::maybe, move_constructible::maybe,
+        copy_constructible::maybe, move_assignable::maybe,
+        copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+        inequality_comparable::maybe, less_than_comparable::maybe,
+        less_equal_comparable::maybe, greater_equal_comparable::maybe,
+        greater_than_comparable::maybe, swappable::maybe, hashable::yes>);
+
+////////////////////////////////////////////////////////////////////////////////
+////     The remaining aliases are combinations of the previous aliases.    ////
+////////////////////////////////////////////////////////////////////////////////
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    Equatable, CombineProfiles<HasEqualityProfile, HasInequalityProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    Comparable,
+    CombineProfiles<EquatableProfile, HasLessThanProfile, HasLessEqualProfile,
+                    HasGreaterEqualProfile, HasGreaterThanProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    NothrowEquatable,
+    CombineProfiles<HasNothrowEqualityProfile, HasNothrowInequalityProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    NothrowComparable,
+    CombineProfiles<NothrowEquatableProfile, HasNothrowLessThanProfile,
+                    HasNothrowLessEqualProfile, HasNothrowGreaterEqualProfile,
+                    HasNothrowGreaterThanProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    Value,
+    CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile,
+                    HasNothrowMoveAssignProfile, HasCopyAssignProfile,
+                    HasNothrowDestructorProfile, HasNothrowSwapProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    EquatableValue, CombineProfiles<EquatableProfile, ValueProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    ComparableValue, CombineProfiles<ComparableProfile, ValueProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    DefaultConstructibleValue,
+    CombineProfiles<HasDefaultConstructorProfile, ValueProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    NothrowMoveConstructible, CombineProfiles<HasNothrowMoveConstructorProfile,
+                                              HasNothrowDestructorProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    EquatableNothrowMoveConstructible,
+    CombineProfiles<EquatableProfile, NothrowMoveConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    ComparableNothrowMoveConstructible,
+    CombineProfiles<ComparableProfile, NothrowMoveConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    DefaultConstructibleNothrowMoveConstructible,
+    CombineProfiles<HasDefaultConstructorProfile,
+                    NothrowMoveConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    CopyConstructible,
+    CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile,
+                    HasNothrowDestructorProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    EquatableCopyConstructible,
+    CombineProfiles<EquatableProfile, CopyConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    ComparableCopyConstructible,
+    CombineProfiles<ComparableProfile, CopyConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    DefaultConstructibleCopyConstructible,
+    CombineProfiles<HasDefaultConstructorProfile, CopyConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    NothrowMovable,
+    CombineProfiles<HasNothrowMoveConstructorProfile,
+                    HasNothrowMoveAssignProfile, HasNothrowDestructorProfile,
+                    HasNothrowSwapProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    EquatableNothrowMovable,
+    CombineProfiles<EquatableProfile, NothrowMovableProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    ComparableNothrowMovable,
+    CombineProfiles<ComparableProfile, NothrowMovableProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    DefaultConstructibleNothrowMovable,
+    CombineProfiles<HasDefaultConstructorProfile, NothrowMovableProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    TrivialSpecialMemberFunctions,
+    CombineProfiles<HasTrivialDefaultConstructorProfile,
+                    HasTrivialMoveConstructorProfile,
+                    HasTrivialCopyConstructorProfile,
+                    HasTrivialMoveAssignProfile, HasTrivialCopyAssignProfile,
+                    HasTrivialDestructorProfile, HasNothrowSwapProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    TriviallyComplete,
+    CombineProfiles<TrivialSpecialMemberFunctionsProfile, ComparableProfile,
+                    HasStdHashSpecializationProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HashableNothrowMoveConstructible,
+    CombineProfiles<HasStdHashSpecializationProfile,
+                    NothrowMoveConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HashableCopyConstructible,
+    CombineProfiles<HasStdHashSpecializationProfile, CopyConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HashableNothrowMovable,
+    CombineProfiles<HasStdHashSpecializationProfile, NothrowMovableProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    HashableValue,
+    CombineProfiles<HasStdHashSpecializationProfile, ValueProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+    ComparableHashableValue,
+    CombineProfiles<HashableValueProfile, ComparableProfile>);
+
+// The "preferred" profiles that we support in Abseil.
+template <template <class...> class Receiver>
+using ExpandBasicProfiles =
+    Receiver<NothrowMoveConstructibleProfile, CopyConstructibleProfile,
+             NothrowMovableProfile, ValueProfile>;
+
+// The basic profiles except that they are also all Equatable.
+template <template <class...> class Receiver>
+using ExpandBasicEquatableProfiles =
+    Receiver<EquatableNothrowMoveConstructibleProfile,
+             EquatableCopyConstructibleProfile, EquatableNothrowMovableProfile,
+             EquatableValueProfile>;
+
+// The basic profiles except that they are also all Comparable.
+template <template <class...> class Receiver>
+using ExpandBasicComparableProfiles =
+    Receiver<ComparableNothrowMoveConstructibleProfile,
+             ComparableCopyConstructibleProfile,
+             ComparableNothrowMovableProfile, ComparableValueProfile>;
+
+// The basic profiles except that they are also all Hashable.
+template <template <class...> class Receiver>
+using ExpandBasicHashableProfiles =
+    Receiver<HashableNothrowMoveConstructibleProfile,
+             HashableCopyConstructibleProfile, HashableNothrowMovableProfile,
+             HashableValueProfile>;
+
+// The basic profiles except that they are also all DefaultConstructible.
+template <template <class...> class Receiver>
+using ExpandBasicDefaultConstructibleProfiles =
+    Receiver<DefaultConstructibleNothrowMoveConstructibleProfile,
+             DefaultConstructibleCopyConstructibleProfile,
+             DefaultConstructibleNothrowMovableProfile,
+             DefaultConstructibleValueProfile>;
+
+// The type profiles that we support in Abseil (all of the previous lists).
+template <template <class...> class Receiver>
+using ExpandSupportedProfiles = Receiver<
+    NothrowMoveConstructibleProfile, CopyConstructibleProfile,
+    NothrowMovableProfile, ValueProfile,
+    EquatableNothrowMoveConstructibleProfile, EquatableCopyConstructibleProfile,
+    EquatableNothrowMovableProfile, EquatableValueProfile,
+    ComparableNothrowMoveConstructibleProfile,
+    ComparableCopyConstructibleProfile, ComparableNothrowMovableProfile,
+    ComparableValueProfile, DefaultConstructibleNothrowMoveConstructibleProfile,
+    DefaultConstructibleCopyConstructibleProfile,
+    DefaultConstructibleNothrowMovableProfile, DefaultConstructibleValueProfile,
+    HashableNothrowMoveConstructibleProfile, HashableCopyConstructibleProfile,
+    HashableNothrowMovableProfile, HashableValueProfile>;
+
+// TODO(calabrese) Include types that have throwing move constructors, since in
+// practice we still need to support them because of standard library types with
+// (potentially) non-noexcept moves.
+
+}  // namespace types_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#undef ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS
+
+#endif  // ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_
diff --git a/absl/types/internal/conformance_archetype.h b/absl/types/internal/conformance_archetype.h
new file mode 100644
index 0000000..2349e0f
--- /dev/null
+++ b/absl/types/internal/conformance_archetype.h
@@ -0,0 +1,978 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// conformance_archetype.h
+// -----------------------------------------------------------------------------
+//
+// This file contains a facility for generating "archetypes" of out of
+// "Conformance Profiles" (see "conformance_profiles.h" for more information
+// about Conformance Profiles). An archetype is a type that aims to support the
+// bare minimum requirements of a given Conformance Profile. For instance, an
+// archetype that corresponds to an ImmutableProfile has exactly a nothrow
+// move-constructor, a potentially-throwing copy constructor, a nothrow
+// destructor, with all other special-member-functions deleted. These archetypes
+// are useful for testing to make sure that templates are able to work with the
+// kinds of types that they claim to support (i.e. that they do not accidentally
+// under-constrain),
+//
+// The main type template in this file is the Archetype template, which takes
+// a Conformance Profile as a template argument and its instantiations are a
+// minimum-conforming model of that profile.
+
+#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_
+#define ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_
+
+#include <cstddef>
+#include <functional>
+#include <type_traits>
+#include <utility>
+
+#include "absl/meta/type_traits.h"
+#include "absl/types/internal/conformance_profile.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace types_internal {
+
+// A minimum-conforming implementation of a type with properties specified in
+// `Prof`, where `Prof` is a valid Conformance Profile.
+template <class Prof, class /*Enabler*/ = void>
+class Archetype;
+
+// Given an Archetype, obtain the properties of the profile associated with that
+// archetype.
+template <class Archetype>
+struct PropertiesOfArchetype;
+
+template <class Prof>
+struct PropertiesOfArchetype<Archetype<Prof>> {
+  using type = PropertiesOfT<Prof>;
+};
+
+template <class Archetype>
+using PropertiesOfArchetypeT = typename PropertiesOfArchetype<Archetype>::type;
+
+// A metafunction to determine if a type is an `Archetype`.
+template <class T>
+struct IsArchetype : std::false_type {};
+
+template <class Prof>
+struct IsArchetype<Archetype<Prof>> : std::true_type {};
+
+// A constructor tag type used when creating an Archetype with internal state.
+struct MakeArchetypeState {};
+
+// Data stored within an archetype that is copied/compared/hashed when the
+// corresponding operations are used.
+using ArchetypeState = std::size_t;
+
+////////////////////////////////////////////////////////////////////////////////
+//   This section of the file defines a chain of base classes for Archetype,  //
+//   where each base defines a specific special member function with the      //
+//   appropriate properties (deleted, noexcept(false), noexcept, or trivial). //
+////////////////////////////////////////////////////////////////////////////////
+
+// The bottom-most base, which contains the state and the default constructor.
+template <default_constructible DefaultConstructibleValue>
+struct ArchetypeStateBase {
+  static_assert(DefaultConstructibleValue == default_constructible::yes ||
+                    DefaultConstructibleValue == default_constructible::nothrow,
+                "");
+
+  ArchetypeStateBase() noexcept(
+      DefaultConstructibleValue ==
+      default_constructible::
+          nothrow) /*Vacuous archetype_state initialization*/ {}
+  explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept
+      : archetype_state(state) {}
+
+  ArchetypeState archetype_state;
+};
+
+template <>
+struct ArchetypeStateBase<default_constructible::maybe> {
+  explicit ArchetypeStateBase() = delete;
+  explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept
+      : archetype_state(state) {}
+
+  ArchetypeState archetype_state;
+};
+
+template <>
+struct ArchetypeStateBase<default_constructible::trivial> {
+  ArchetypeStateBase() = default;
+  explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept
+      : archetype_state(state) {}
+
+  ArchetypeState archetype_state;
+};
+
+// The move-constructor base
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue>
+struct ArchetypeMoveConstructor
+    : ArchetypeStateBase<DefaultConstructibleValue> {
+  static_assert(MoveConstructibleValue == move_constructible::yes ||
+                    MoveConstructibleValue == move_constructible::nothrow,
+                "");
+
+  explicit ArchetypeMoveConstructor(MakeArchetypeState,
+                                    ArchetypeState state) noexcept
+      : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(),
+                                                      state) {}
+
+  ArchetypeMoveConstructor() = default;
+  ArchetypeMoveConstructor(ArchetypeMoveConstructor&& other) noexcept(
+      MoveConstructibleValue == move_constructible::nothrow)
+      : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(),
+                                                      other.archetype_state) {}
+  ArchetypeMoveConstructor(const ArchetypeMoveConstructor&) = default;
+  ArchetypeMoveConstructor& operator=(ArchetypeMoveConstructor&&) = default;
+  ArchetypeMoveConstructor& operator=(const ArchetypeMoveConstructor&) =
+      default;
+};
+
+template <default_constructible DefaultConstructibleValue>
+struct ArchetypeMoveConstructor<DefaultConstructibleValue,
+                                move_constructible::trivial>
+    : ArchetypeStateBase<DefaultConstructibleValue> {
+  explicit ArchetypeMoveConstructor(MakeArchetypeState,
+                                    ArchetypeState state) noexcept
+      : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(),
+                                                      state) {}
+
+  ArchetypeMoveConstructor() = default;
+};
+
+// The copy-constructor base
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue,
+          copy_constructible CopyConstructibleValue>
+struct ArchetypeCopyConstructor
+    : ArchetypeMoveConstructor<DefaultConstructibleValue,
+                               MoveConstructibleValue> {
+  static_assert(CopyConstructibleValue == copy_constructible::yes ||
+                    CopyConstructibleValue == copy_constructible::nothrow,
+                "");
+  explicit ArchetypeCopyConstructor(MakeArchetypeState,
+                                    ArchetypeState state) noexcept
+      : ArchetypeMoveConstructor<DefaultConstructibleValue,
+                                 MoveConstructibleValue>(MakeArchetypeState(),
+                                                         state) {}
+
+  ArchetypeCopyConstructor() = default;
+  ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default;
+  ArchetypeCopyConstructor(const ArchetypeCopyConstructor& other) noexcept(
+      CopyConstructibleValue == copy_constructible::nothrow)
+      : ArchetypeMoveConstructor<DefaultConstructibleValue,
+                                 MoveConstructibleValue>(
+            MakeArchetypeState(), other.archetype_state) {}
+  ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default;
+  ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) =
+      default;
+};
+
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue>
+struct ArchetypeCopyConstructor<DefaultConstructibleValue,
+                                MoveConstructibleValue,
+                                copy_constructible::maybe>
+    : ArchetypeMoveConstructor<DefaultConstructibleValue,
+                               MoveConstructibleValue> {
+  explicit ArchetypeCopyConstructor(MakeArchetypeState,
+                                    ArchetypeState state) noexcept
+      : ArchetypeMoveConstructor<DefaultConstructibleValue,
+                                 MoveConstructibleValue>(MakeArchetypeState(),
+                                                         state) {}
+
+  ArchetypeCopyConstructor() = default;
+  ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default;
+  ArchetypeCopyConstructor(const ArchetypeCopyConstructor&) = delete;
+  ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default;
+  ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) =
+      default;
+};
+
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue>
+struct ArchetypeCopyConstructor<DefaultConstructibleValue,
+                                MoveConstructibleValue,
+                                copy_constructible::trivial>
+    : ArchetypeMoveConstructor<DefaultConstructibleValue,
+                               MoveConstructibleValue> {
+  explicit ArchetypeCopyConstructor(MakeArchetypeState,
+                                    ArchetypeState state) noexcept
+      : ArchetypeMoveConstructor<DefaultConstructibleValue,
+                                 MoveConstructibleValue>(MakeArchetypeState(),
+                                                         state) {}
+
+  ArchetypeCopyConstructor() = default;
+};
+
+// The move-assign base
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue,
+          copy_constructible CopyConstructibleValue,
+          move_assignable MoveAssignableValue>
+struct ArchetypeMoveAssign
+    : ArchetypeCopyConstructor<DefaultConstructibleValue,
+                               MoveConstructibleValue, CopyConstructibleValue> {
+  static_assert(MoveAssignableValue == move_assignable::yes ||
+                    MoveAssignableValue == move_assignable::nothrow,
+                "");
+  explicit ArchetypeMoveAssign(MakeArchetypeState,
+                               ArchetypeState state) noexcept
+      : ArchetypeCopyConstructor<DefaultConstructibleValue,
+                                 MoveConstructibleValue,
+                                 CopyConstructibleValue>(MakeArchetypeState(),
+                                                         state) {}
+
+  ArchetypeMoveAssign() = default;
+  ArchetypeMoveAssign(ArchetypeMoveAssign&&) = default;
+  ArchetypeMoveAssign(const ArchetypeMoveAssign&) = default;
+  ArchetypeMoveAssign& operator=(ArchetypeMoveAssign&& other) noexcept(
+      MoveAssignableValue == move_assignable::nothrow) {
+    this->archetype_state = other.archetype_state;
+    return *this;
+  }
+
+  ArchetypeMoveAssign& operator=(const ArchetypeMoveAssign&) = default;
+};
+
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue,
+          copy_constructible CopyConstructibleValue>
+struct ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                           CopyConstructibleValue, move_assignable::trivial>
+    : ArchetypeCopyConstructor<DefaultConstructibleValue,
+                               MoveConstructibleValue, CopyConstructibleValue> {
+  explicit ArchetypeMoveAssign(MakeArchetypeState,
+                               ArchetypeState state) noexcept
+      : ArchetypeCopyConstructor<DefaultConstructibleValue,
+                                 MoveConstructibleValue,
+                                 CopyConstructibleValue>(MakeArchetypeState(),
+                                                         state) {}
+
+  ArchetypeMoveAssign() = default;
+};
+
+// The copy-assign base
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue,
+          copy_constructible CopyConstructibleValue,
+          move_assignable MoveAssignableValue,
+          copy_assignable CopyAssignableValue>
+struct ArchetypeCopyAssign
+    : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                          CopyConstructibleValue, MoveAssignableValue> {
+  static_assert(CopyAssignableValue == copy_assignable::yes ||
+                    CopyAssignableValue == copy_assignable::nothrow,
+                "");
+  explicit ArchetypeCopyAssign(MakeArchetypeState,
+                               ArchetypeState state) noexcept
+      : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                            CopyConstructibleValue, MoveAssignableValue>(
+            MakeArchetypeState(), state) {}
+
+  ArchetypeCopyAssign() = default;
+  ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default;
+  ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default;
+  ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default;
+
+  ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign& other) noexcept(
+      CopyAssignableValue == copy_assignable::nothrow) {
+    this->archetype_state = other.archetype_state;
+    return *this;
+  }
+};
+
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue,
+          copy_constructible CopyConstructibleValue,
+          move_assignable MoveAssignableValue>
+struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                           CopyConstructibleValue, MoveAssignableValue,
+                           copy_assignable::maybe>
+    : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                          CopyConstructibleValue, MoveAssignableValue> {
+  explicit ArchetypeCopyAssign(MakeArchetypeState,
+                               ArchetypeState state) noexcept
+      : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                            CopyConstructibleValue, MoveAssignableValue>(
+            MakeArchetypeState(), state) {}
+
+  ArchetypeCopyAssign() = default;
+  ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default;
+  ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default;
+  ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default;
+  ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign&) = delete;
+};
+
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue,
+          copy_constructible CopyConstructibleValue,
+          move_assignable MoveAssignableValue>
+struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                           CopyConstructibleValue, MoveAssignableValue,
+                           copy_assignable::trivial>
+    : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                          CopyConstructibleValue, MoveAssignableValue> {
+  explicit ArchetypeCopyAssign(MakeArchetypeState,
+                               ArchetypeState state) noexcept
+      : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                            CopyConstructibleValue, MoveAssignableValue>(
+            MakeArchetypeState(), state) {}
+
+  ArchetypeCopyAssign() = default;
+};
+
+// The destructor base
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue,
+          copy_constructible CopyConstructibleValue,
+          move_assignable MoveAssignableValue,
+          copy_assignable CopyAssignableValue, destructible DestructibleValue>
+struct ArchetypeDestructor
+    : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                          CopyConstructibleValue, MoveAssignableValue,
+                          CopyAssignableValue> {
+  static_assert(DestructibleValue == destructible::yes ||
+                    DestructibleValue == destructible::nothrow,
+                "");
+
+  explicit ArchetypeDestructor(MakeArchetypeState,
+                               ArchetypeState state) noexcept
+      : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                            CopyConstructibleValue, MoveAssignableValue,
+                            CopyAssignableValue>(MakeArchetypeState(), state) {}
+
+  ArchetypeDestructor() = default;
+  ArchetypeDestructor(ArchetypeDestructor&&) = default;
+  ArchetypeDestructor(const ArchetypeDestructor&) = default;
+  ArchetypeDestructor& operator=(ArchetypeDestructor&&) = default;
+  ArchetypeDestructor& operator=(const ArchetypeDestructor&) = default;
+  ~ArchetypeDestructor() noexcept(DestructibleValue == destructible::nothrow) {}
+};
+
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue,
+          copy_constructible CopyConstructibleValue,
+          move_assignable MoveAssignableValue,
+          copy_assignable CopyAssignableValue>
+struct ArchetypeDestructor<DefaultConstructibleValue, MoveConstructibleValue,
+                           CopyConstructibleValue, MoveAssignableValue,
+                           CopyAssignableValue, destructible::trivial>
+    : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                          CopyConstructibleValue, MoveAssignableValue,
+                          CopyAssignableValue> {
+  explicit ArchetypeDestructor(MakeArchetypeState,
+                               ArchetypeState state) noexcept
+      : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+                            CopyConstructibleValue, MoveAssignableValue,
+                            CopyAssignableValue>(MakeArchetypeState(), state) {}
+
+  ArchetypeDestructor() = default;
+};
+
+// An alias to the top of the chain of bases for special-member functions.
+// NOTE: move_constructible::maybe, move_assignable::maybe, and
+// destructible::maybe are handled in the top-level type by way of SFINAE.
+// Because of this, we never instantiate the base classes with
+// move_constructible::maybe, move_assignable::maybe, or destructible::maybe so
+// that we minimize the number of different possible type-template
+// instantiations.
+template <default_constructible DefaultConstructibleValue,
+          move_constructible MoveConstructibleValue,
+          copy_constructible CopyConstructibleValue,
+          move_assignable MoveAssignableValue,
+          copy_assignable CopyAssignableValue, destructible DestructibleValue>
+using ArchetypeSpecialMembersBase = ArchetypeDestructor<
+    DefaultConstructibleValue,
+    MoveConstructibleValue != move_constructible::maybe
+        ? MoveConstructibleValue
+        : move_constructible::nothrow,
+    CopyConstructibleValue,
+    MoveAssignableValue != move_assignable::maybe ? MoveAssignableValue
+                                                  : move_assignable::nothrow,
+    CopyAssignableValue,
+    DestructibleValue != destructible::maybe ? DestructibleValue
+                                             : destructible::nothrow>;
+
+// A function that is used to create an archetype with some associated state.
+template <class Arch>
+Arch MakeArchetype(ArchetypeState state) noexcept {
+  static_assert(IsArchetype<Arch>::value,
+                "The explicit template argument to MakeArchetype is required "
+                "to be an Archetype.");
+  return Arch(MakeArchetypeState(), state);
+}
+
+// This is used to conditionally delete "copy" and "move" constructors in a way
+// that is consistent with what the ConformanceProfile requires and that also
+// strictly enforces the arguments to the copy/move to not come from implicit
+// conversions when dealing with the Archetype.
+template <class Prof, class T>
+constexpr bool ShouldDeleteConstructor() {
+  return !((PropertiesOfT<Prof>::move_constructible_support !=
+                move_constructible::maybe &&
+            std::is_same<T, Archetype<Prof>>::value) ||
+           (PropertiesOfT<Prof>::copy_constructible_support !=
+                copy_constructible::maybe &&
+            (std::is_same<T, const Archetype<Prof>&>::value ||
+             std::is_same<T, Archetype<Prof>&>::value ||
+             std::is_same<T, const Archetype<Prof>>::value)));
+}
+
+// This is used to conditionally delete "copy" and "move" assigns in a way
+// that is consistent with what the ConformanceProfile requires and that also
+// strictly enforces the arguments to the copy/move to not come from implicit
+// conversions when dealing with the Archetype.
+template <class Prof, class T>
+constexpr bool ShouldDeleteAssign() {
+  return !(
+      (PropertiesOfT<Prof>::move_assignable_support != move_assignable::maybe &&
+       std::is_same<T, Archetype<Prof>>::value) ||
+      (PropertiesOfT<Prof>::copy_assignable_support != copy_assignable::maybe &&
+       (std::is_same<T, const Archetype<Prof>&>::value ||
+        std::is_same<T, Archetype<Prof>&>::value ||
+        std::is_same<T, const Archetype<Prof>>::value)));
+}
+
+// TODO(calabrese) Inherit from a chain of secondary bases to pull in the
+// associated functions of other concepts.
+template <class Prof, class Enabler>
+class Archetype : ArchetypeSpecialMembersBase<
+                      PropertiesOfT<Prof>::default_constructible_support,
+                      PropertiesOfT<Prof>::move_constructible_support,
+                      PropertiesOfT<Prof>::copy_constructible_support,
+                      PropertiesOfT<Prof>::move_assignable_support,
+                      PropertiesOfT<Prof>::copy_assignable_support,
+                      PropertiesOfT<Prof>::destructible_support> {
+  static_assert(std::is_same<Enabler, void>::value,
+                "An explicit type must not be passed as the second template "
+                "argument to 'Archetype`.");
+
+  // The cases mentioned in these static_asserts are expected to be handled in
+  // the partial template specializations of Archetype that follow this
+  // definition.
+  static_assert(PropertiesOfT<Prof>::destructible_support !=
+                    destructible::maybe,
+                "");
+  static_assert(PropertiesOfT<Prof>::move_constructible_support !=
+                        move_constructible::maybe ||
+                    PropertiesOfT<Prof>::copy_constructible_support ==
+                        copy_constructible::maybe,
+                "");
+  static_assert(PropertiesOfT<Prof>::move_assignable_support !=
+                        move_assignable::maybe ||
+                    PropertiesOfT<Prof>::copy_assignable_support ==
+                        copy_assignable::maybe,
+                "");
+
+ public:
+  Archetype() = default;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+  Archetype(T&&) = delete;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+  Archetype& operator=(T&&) = delete;
+
+  using ArchetypeSpecialMembersBase<
+      PropertiesOfT<Prof>::default_constructible_support,
+      PropertiesOfT<Prof>::move_constructible_support,
+      PropertiesOfT<Prof>::copy_constructible_support,
+      PropertiesOfT<Prof>::move_assignable_support,
+      PropertiesOfT<Prof>::copy_assignable_support,
+      PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+      : ArchetypeSpecialMembersBase<
+            PropertiesOfT<Prof>::default_constructible_support,
+            PropertiesOfT<Prof>::move_constructible_support,
+            PropertiesOfT<Prof>::copy_constructible_support,
+            PropertiesOfT<Prof>::move_assignable_support,
+            PropertiesOfT<Prof>::copy_assignable_support,
+            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+                                                       state) {}
+
+  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+                          PropertiesOfT<Prof>::move_constructible_support !=
+                              move_constructible::maybe &&
+                          PropertiesOfT<Prof>::move_assignable_support ==
+                              move_assignable::maybe &&
+                          PropertiesOfT<Prof>::destructible_support !=
+                              destructible::maybe>::type>
+    : ArchetypeSpecialMembersBase<
+          PropertiesOfT<Prof>::default_constructible_support,
+          PropertiesOfT<Prof>::move_constructible_support,
+          PropertiesOfT<Prof>::copy_constructible_support,
+          PropertiesOfT<Prof>::move_assignable_support,
+          PropertiesOfT<Prof>::copy_assignable_support,
+          PropertiesOfT<Prof>::destructible_support> {
+ public:
+  Archetype() = default;
+  Archetype(Archetype&&) = default;
+  Archetype(const Archetype&) = default;
+  Archetype& operator=(Archetype&&) = delete;
+  Archetype& operator=(const Archetype&) = default;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+  Archetype(T&&) = delete;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+  Archetype& operator=(T&&) = delete;
+
+  using ArchetypeSpecialMembersBase<
+      PropertiesOfT<Prof>::default_constructible_support,
+      PropertiesOfT<Prof>::move_constructible_support,
+      PropertiesOfT<Prof>::copy_constructible_support,
+      PropertiesOfT<Prof>::move_assignable_support,
+      PropertiesOfT<Prof>::copy_assignable_support,
+      PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+      : ArchetypeSpecialMembersBase<
+            PropertiesOfT<Prof>::default_constructible_support,
+            PropertiesOfT<Prof>::move_constructible_support,
+            PropertiesOfT<Prof>::copy_constructible_support,
+            PropertiesOfT<Prof>::move_assignable_support,
+            PropertiesOfT<Prof>::copy_assignable_support,
+            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+                                                       state) {}
+
+  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+                          PropertiesOfT<Prof>::move_constructible_support ==
+                              move_constructible::maybe &&
+                          PropertiesOfT<Prof>::move_assignable_support ==
+                              move_assignable::maybe &&
+                          PropertiesOfT<Prof>::destructible_support !=
+                              destructible::maybe>::type>
+    : ArchetypeSpecialMembersBase<
+          PropertiesOfT<Prof>::default_constructible_support,
+          PropertiesOfT<Prof>::move_constructible_support,
+          PropertiesOfT<Prof>::copy_constructible_support,
+          PropertiesOfT<Prof>::move_assignable_support,
+          PropertiesOfT<Prof>::copy_assignable_support,
+          PropertiesOfT<Prof>::destructible_support> {
+ public:
+  Archetype() = default;
+  Archetype(Archetype&&) = delete;
+  Archetype(const Archetype&) = default;
+  Archetype& operator=(Archetype&&) = delete;
+  Archetype& operator=(const Archetype&) = default;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+  Archetype(T&&) = delete;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+  Archetype& operator=(T&&) = delete;
+
+  using ArchetypeSpecialMembersBase<
+      PropertiesOfT<Prof>::default_constructible_support,
+      PropertiesOfT<Prof>::move_constructible_support,
+      PropertiesOfT<Prof>::copy_constructible_support,
+      PropertiesOfT<Prof>::move_assignable_support,
+      PropertiesOfT<Prof>::copy_assignable_support,
+      PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+      : ArchetypeSpecialMembersBase<
+            PropertiesOfT<Prof>::default_constructible_support,
+            PropertiesOfT<Prof>::move_constructible_support,
+            PropertiesOfT<Prof>::copy_constructible_support,
+            PropertiesOfT<Prof>::move_assignable_support,
+            PropertiesOfT<Prof>::copy_assignable_support,
+            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+                                                       state) {}
+
+  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+                          PropertiesOfT<Prof>::move_constructible_support ==
+                              move_constructible::maybe &&
+                          PropertiesOfT<Prof>::move_assignable_support !=
+                              move_assignable::maybe &&
+                          PropertiesOfT<Prof>::destructible_support !=
+                              destructible::maybe>::type>
+    : ArchetypeSpecialMembersBase<
+          PropertiesOfT<Prof>::default_constructible_support,
+          PropertiesOfT<Prof>::move_constructible_support,
+          PropertiesOfT<Prof>::copy_constructible_support,
+          PropertiesOfT<Prof>::move_assignable_support,
+          PropertiesOfT<Prof>::copy_assignable_support,
+          PropertiesOfT<Prof>::destructible_support> {
+ public:
+  Archetype() = default;
+  Archetype(Archetype&&) = delete;
+  Archetype(const Archetype&) = default;
+  Archetype& operator=(Archetype&&) = default;
+  Archetype& operator=(const Archetype&) = default;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+  Archetype(T&&) = delete;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+  Archetype& operator=(T&&) = delete;
+
+  using ArchetypeSpecialMembersBase<
+      PropertiesOfT<Prof>::default_constructible_support,
+      PropertiesOfT<Prof>::move_constructible_support,
+      PropertiesOfT<Prof>::copy_constructible_support,
+      PropertiesOfT<Prof>::move_assignable_support,
+      PropertiesOfT<Prof>::copy_assignable_support,
+      PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+      : ArchetypeSpecialMembersBase<
+            PropertiesOfT<Prof>::default_constructible_support,
+            PropertiesOfT<Prof>::move_constructible_support,
+            PropertiesOfT<Prof>::copy_constructible_support,
+            PropertiesOfT<Prof>::move_assignable_support,
+            PropertiesOfT<Prof>::copy_assignable_support,
+            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+                                                       state) {}
+
+  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+                          PropertiesOfT<Prof>::move_constructible_support !=
+                              move_constructible::maybe &&
+                          PropertiesOfT<Prof>::move_assignable_support ==
+                              move_assignable::maybe &&
+                          PropertiesOfT<Prof>::destructible_support ==
+                              destructible::maybe>::type>
+    : ArchetypeSpecialMembersBase<
+          PropertiesOfT<Prof>::default_constructible_support,
+          PropertiesOfT<Prof>::move_constructible_support,
+          PropertiesOfT<Prof>::copy_constructible_support,
+          PropertiesOfT<Prof>::move_assignable_support,
+          PropertiesOfT<Prof>::copy_assignable_support,
+          PropertiesOfT<Prof>::destructible_support> {
+ public:
+  Archetype() = default;
+  Archetype(Archetype&&) = default;
+  Archetype(const Archetype&) = default;
+  Archetype& operator=(Archetype&&) = delete;
+  Archetype& operator=(const Archetype&) = default;
+  ~Archetype() = delete;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+  Archetype(T&&) = delete;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+  Archetype& operator=(T&&) = delete;
+
+  using ArchetypeSpecialMembersBase<
+      PropertiesOfT<Prof>::default_constructible_support,
+      PropertiesOfT<Prof>::move_constructible_support,
+      PropertiesOfT<Prof>::copy_constructible_support,
+      PropertiesOfT<Prof>::move_assignable_support,
+      PropertiesOfT<Prof>::copy_assignable_support,
+      PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+      : ArchetypeSpecialMembersBase<
+            PropertiesOfT<Prof>::default_constructible_support,
+            PropertiesOfT<Prof>::move_constructible_support,
+            PropertiesOfT<Prof>::copy_constructible_support,
+            PropertiesOfT<Prof>::move_assignable_support,
+            PropertiesOfT<Prof>::copy_assignable_support,
+            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+                                                       state) {}
+
+  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+                          PropertiesOfT<Prof>::move_constructible_support ==
+                              move_constructible::maybe &&
+                          PropertiesOfT<Prof>::move_assignable_support ==
+                              move_assignable::maybe &&
+                          PropertiesOfT<Prof>::destructible_support ==
+                              destructible::maybe>::type>
+    : ArchetypeSpecialMembersBase<
+          PropertiesOfT<Prof>::default_constructible_support,
+          PropertiesOfT<Prof>::move_constructible_support,
+          PropertiesOfT<Prof>::copy_constructible_support,
+          PropertiesOfT<Prof>::move_assignable_support,
+          PropertiesOfT<Prof>::copy_assignable_support,
+          PropertiesOfT<Prof>::destructible_support> {
+ public:
+  Archetype() = default;
+  Archetype(Archetype&&) = delete;
+  Archetype(const Archetype&) = default;
+  Archetype& operator=(Archetype&&) = delete;
+  Archetype& operator=(const Archetype&) = default;
+  ~Archetype() = delete;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+  Archetype(T&&) = delete;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+  Archetype& operator=(T&&) = delete;
+
+  using ArchetypeSpecialMembersBase<
+      PropertiesOfT<Prof>::default_constructible_support,
+      PropertiesOfT<Prof>::move_constructible_support,
+      PropertiesOfT<Prof>::copy_constructible_support,
+      PropertiesOfT<Prof>::move_assignable_support,
+      PropertiesOfT<Prof>::copy_assignable_support,
+      PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+      : ArchetypeSpecialMembersBase<
+            PropertiesOfT<Prof>::default_constructible_support,
+            PropertiesOfT<Prof>::move_constructible_support,
+            PropertiesOfT<Prof>::copy_constructible_support,
+            PropertiesOfT<Prof>::move_assignable_support,
+            PropertiesOfT<Prof>::copy_assignable_support,
+            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+                                                       state) {}
+
+  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+                          PropertiesOfT<Prof>::move_constructible_support ==
+                              move_constructible::maybe &&
+                          PropertiesOfT<Prof>::move_assignable_support !=
+                              move_assignable::maybe &&
+                          PropertiesOfT<Prof>::destructible_support ==
+                              destructible::maybe>::type>
+    : ArchetypeSpecialMembersBase<
+          PropertiesOfT<Prof>::default_constructible_support,
+          PropertiesOfT<Prof>::move_constructible_support,
+          PropertiesOfT<Prof>::copy_constructible_support,
+          PropertiesOfT<Prof>::move_assignable_support,
+          PropertiesOfT<Prof>::copy_assignable_support,
+          PropertiesOfT<Prof>::destructible_support> {
+ public:
+  Archetype() = default;
+  Archetype(Archetype&&) = delete;
+  Archetype(const Archetype&) = default;
+  Archetype& operator=(Archetype&&) = default;
+  Archetype& operator=(const Archetype&) = default;
+  ~Archetype() = delete;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+  Archetype(T&&) = delete;
+
+  // Disallow moves when requested, and disallow implicit conversions.
+  template <class T, typename std::enable_if<
+                         ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+  Archetype& operator=(T&&) = delete;
+
+  using ArchetypeSpecialMembersBase<
+      PropertiesOfT<Prof>::default_constructible_support,
+      PropertiesOfT<Prof>::move_constructible_support,
+      PropertiesOfT<Prof>::copy_constructible_support,
+      PropertiesOfT<Prof>::move_assignable_support,
+      PropertiesOfT<Prof>::copy_assignable_support,
+      PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+  explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+      : ArchetypeSpecialMembersBase<
+            PropertiesOfT<Prof>::default_constructible_support,
+            PropertiesOfT<Prof>::move_constructible_support,
+            PropertiesOfT<Prof>::copy_constructible_support,
+            PropertiesOfT<Prof>::move_assignable_support,
+            PropertiesOfT<Prof>::copy_assignable_support,
+            PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+                                                       state) {}
+
+  friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+// Explicitly deleted swap for Archetype if the profile does not require swap.
+// It is important to delete it rather than simply leave it out so that the
+// "using std::swap;" idiom will result in this deleted overload being picked.
+template <class Prof,
+          absl::enable_if_t<!PropertiesOfT<Prof>::is_swappable, int> = 0>
+void swap(Archetype<Prof>&, Archetype<Prof>&) = delete;  // NOLINT
+
+// A conditionally-noexcept swap implementation for Archetype when the profile
+// supports swap.
+template <class Prof,
+          absl::enable_if_t<PropertiesOfT<Prof>::is_swappable, int> = 0>
+void swap(Archetype<Prof>& lhs, Archetype<Prof>& rhs)  // NOLINT
+    noexcept(PropertiesOfT<Prof>::swappable_support != swappable::yes) {
+  std::swap(lhs.archetype_state, rhs.archetype_state);
+}
+
+// A convertible-to-bool type that is used as the return type of comparison
+// operators since the standard doesn't always require exactly bool.
+struct NothrowBool {
+  explicit NothrowBool() = delete;
+  ~NothrowBool() = default;
+
+  // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed
+  // elision makes it not required when returning from a function.
+  // NothrowBool(NothrowBool const&) = delete;
+
+  NothrowBool& operator=(NothrowBool const&) = delete;
+
+  explicit operator bool() const noexcept { return value; }
+
+  static NothrowBool make(bool const value) noexcept {
+    return NothrowBool(value);
+  }
+
+ private:
+  explicit NothrowBool(bool const value) noexcept : value(value) {}
+
+  bool value;
+};
+
+// A convertible-to-bool type that is used as the return type of comparison
+// operators since the standard doesn't always require exactly bool.
+// Note: ExceptionalBool has a conversion operator that is not noexcept, so
+// that even when a comparison operator is noexcept, that operation may still
+// potentially throw when converted to bool.
+struct ExceptionalBool {
+  explicit ExceptionalBool() = delete;
+  ~ExceptionalBool() = default;
+
+  // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed
+  // elision makes it not required when returning from a function.
+  // ExceptionalBool(ExceptionalBool const&) = delete;
+
+  ExceptionalBool& operator=(ExceptionalBool const&) = delete;
+
+  explicit operator bool() const { return value; }  // NOLINT
+
+  static ExceptionalBool make(bool const value) noexcept {
+    return ExceptionalBool(value);
+  }
+
+ private:
+  explicit ExceptionalBool(bool const value) noexcept : value(value) {}
+
+  bool value;
+};
+
+// The following macro is only used as a helper in this file to stamp out
+// comparison operator definitions. It is undefined after usage.
+//
+// NOTE: Non-nothrow operators throw via their result's conversion to bool even
+// though the operation itself is noexcept.
+#define ABSL_TYPES_INTERNAL_OP(enum_name, op)                                \
+  template <class Prof>                                                      \
+  absl::enable_if_t<!PropertiesOfT<Prof>::is_##enum_name, bool> operator op( \
+      const Archetype<Prof>&, const Archetype<Prof>&) = delete;              \
+                                                                             \
+  template <class Prof>                                                      \
+  typename absl::enable_if_t<                                                \
+      PropertiesOfT<Prof>::is_##enum_name,                                   \
+      std::conditional<PropertiesOfT<Prof>::enum_name##_support ==           \
+                           enum_name::nothrow,                               \
+                       NothrowBool, ExceptionalBool>>::type                  \
+  operator op(const Archetype<Prof>& lhs,                                    \
+              const Archetype<Prof>& rhs) noexcept {                         \
+    return absl::conditional_t<                                              \
+        PropertiesOfT<Prof>::enum_name##_support == enum_name::nothrow,      \
+        NothrowBool, ExceptionalBool>::make(lhs.archetype_state op           \
+                                                rhs.archetype_state);        \
+  }
+
+ABSL_TYPES_INTERNAL_OP(equality_comparable, ==);
+ABSL_TYPES_INTERNAL_OP(inequality_comparable, !=);
+ABSL_TYPES_INTERNAL_OP(less_than_comparable, <);
+ABSL_TYPES_INTERNAL_OP(less_equal_comparable, <=);
+ABSL_TYPES_INTERNAL_OP(greater_equal_comparable, >=);
+ABSL_TYPES_INTERNAL_OP(greater_than_comparable, >);
+
+#undef ABSL_TYPES_INTERNAL_OP
+
+// Base class for std::hash specializations when an Archetype doesn't support
+// hashing.
+struct PoisonedHash {
+  PoisonedHash() = delete;
+  PoisonedHash(const PoisonedHash&) = delete;
+  PoisonedHash& operator=(const PoisonedHash&) = delete;
+};
+
+// Base class for std::hash specializations when an Archetype supports hashing.
+template <class Prof>
+struct EnabledHash {
+  using argument_type = Archetype<Prof>;
+  using result_type = std::size_t;
+  result_type operator()(const argument_type& arg) const {
+    return std::hash<ArchetypeState>()(arg.archetype_state);
+  }
+};
+
+}  // namespace types_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+namespace std {
+
+template <class Prof>  // NOLINT
+struct hash<::absl::types_internal::Archetype<Prof>>
+    : conditional<::absl::types_internal::PropertiesOfT<Prof>::is_hashable,
+                  ::absl::types_internal::EnabledHash<Prof>,
+                  ::absl::types_internal::PoisonedHash>::type {};
+
+}  // namespace std
+
+#endif  // ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_
diff --git a/absl/types/internal/conformance_profile.h b/absl/types/internal/conformance_profile.h
new file mode 100644
index 0000000..cf64ff4
--- /dev/null
+++ b/absl/types/internal/conformance_profile.h
@@ -0,0 +1,931 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// conformance_profiles.h
+// -----------------------------------------------------------------------------
+//
+// This file contains templates for representing "Regularity Profiles" and
+// concisely-named versions of commonly used Regularity Profiles.
+//
+// A Regularity Profile is a compile-time description of the types of operations
+// that a given type supports, along with properties of those operations when
+// they do exist. For instance, a Regularity Profile may describe a type that
+// has a move-constructor that is noexcept and a copy constructor that is not
+// noexcept. This description can then be examined and passed around to other
+// templates for the purposes of asserting expectations on user-defined types
+// via a series trait checks, or for determining what kinds of run-time tests
+// are able to be performed.
+//
+// Regularity Profiles are also used when creating "archetypes," which are
+// minimum-conforming types that meet all of the requirements of a given
+// Regularity Profile. For more information regarding archetypes, see
+// "conformance_archetypes.h".
+
+#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_
+#define ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_
+
+#include <set>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/algorithm/container.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/internal/conformance_testing_helpers.h"
+#include "absl/utility/utility.h"
+
+// TODO(calabrese) Add support for extending profiles.
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace types_internal {
+
+// Converts an enum to its underlying integral value.
+template <typename Enum>
+constexpr absl::underlying_type_t<Enum> UnderlyingValue(Enum value) {
+  return static_cast<absl::underlying_type_t<Enum>>(value);
+}
+
+// A tag type used in place of a matcher when checking that an assertion result
+// does not actually contain any errors.
+struct NoError {};
+
+// -----------------------------------------------------------------------------
+// ConformanceErrors
+// -----------------------------------------------------------------------------
+class ConformanceErrors {
+ public:
+  // Setup the error reporting mechanism by seeding it with the name of the type
+  // that is being tested.
+  explicit ConformanceErrors(std::string type_name)
+      : assertion_result_(false), type_name_(std::move(type_name)) {
+    assertion_result_ << "\n\n"
+                         "Assuming the following type alias:\n"
+                         "\n"
+                         "  using _T = "
+                      << type_name_ << ";\n\n";
+    outputDivider();
+  }
+
+  // Adds the test name to the list of successfully run tests iff it was not
+  // previously reported as failing. This behavior is useful for tests that
+  // have multiple parts, where failures and successes are reported individually
+  // with the same test name.
+  void addTestSuccess(absl::string_view test_name) {
+    auto normalized_test_name = absl::AsciiStrToLower(test_name);
+
+    // If the test is already reported as failing, do not add it to the list of
+    // successes.
+    if (test_failures_.find(normalized_test_name) == test_failures_.end()) {
+      test_successes_.insert(std::move(normalized_test_name));
+    }
+  }
+
+  // Streams a single error description into the internal buffer (a visual
+  // divider is automatically inserted after the error so that multiple errors
+  // are visibly distinct).
+  //
+  // This function increases the error count by 1.
+  //
+  // TODO(calabrese) Determine desired behavior when if this function throws.
+  template <class... P>
+  void addTestFailure(absl::string_view test_name, const P&... args) {
+    // Output a message related to the test failure.
+    assertion_result_ << "\n\n"
+                         "Failed test: "
+                      << test_name << "\n\n";
+    addTestFailureImpl(args...);
+    assertion_result_ << "\n\n";
+    outputDivider();
+
+    auto normalized_test_name = absl::AsciiStrToLower(test_name);
+
+    // If previous parts of this test succeeded, remove it from that set.
+    test_successes_.erase(normalized_test_name);
+
+    // Add the test name to the list of failed tests.
+    test_failures_.insert(std::move(normalized_test_name));
+
+    has_error_ = true;
+  }
+
+  // Convert this object into a testing::AssertionResult instance such that it
+  // can be used with gtest.
+  ::testing::AssertionResult assertionResult() const {
+    return has_error_ ? assertion_result_ : ::testing::AssertionSuccess();
+  }
+
+  // Convert this object into a testing::AssertionResult instance such that it
+  // can be used with gtest. This overload expects errors, using the specified
+  // matcher.
+  ::testing::AssertionResult expectFailedTests(
+      const std::set<std::string>& test_names) const {
+    // Since we are expecting nonconformance, output an error message when the
+    // type actually conformed to the specified profile.
+    if (!has_error_) {
+      return ::testing::AssertionFailure()
+             << "Unexpected conformance of type:\n"
+                "    "
+             << type_name_ << "\n\n";
+    }
+
+    // Get a list of all expected failures that did not actually fail
+    // (or that were not run).
+    std::vector<std::string> nonfailing_tests;
+    absl::c_set_difference(test_names, test_failures_,
+                           std::back_inserter(nonfailing_tests));
+
+    // Get a list of all "expected failures" that were never actually run.
+    std::vector<std::string> unrun_tests;
+    absl::c_set_difference(nonfailing_tests, test_successes_,
+                           std::back_inserter(unrun_tests));
+
+    // Report when the user specified tests that were not run.
+    if (!unrun_tests.empty()) {
+      const bool tests_were_run =
+          !(test_failures_.empty() && test_successes_.empty());
+
+      // Prepare an assertion result used in the case that tests pass that were
+      // expected to fail.
+      ::testing::AssertionResult result = ::testing::AssertionFailure();
+      result << "When testing type:\n    " << type_name_
+             << "\n\nThe following tests were expected to fail but were not "
+                "run";
+
+      if (tests_were_run) result << " (was the test name spelled correctly?)";
+
+      result << ":\n\n";
+
+      // List all of the tests that unexpectedly passed.
+      for (const auto& test_name : unrun_tests) {
+        result << "    " << test_name << "\n";
+      }
+
+      if (!tests_were_run) result << "\nNo tests were run.";
+
+      if (!test_failures_.empty()) {
+        // List test failures
+        result << "\nThe tests that were run and failed are:\n\n";
+        for (const auto& test_name : test_failures_) {
+          result << "    " << test_name << "\n";
+        }
+      }
+
+      if (!test_successes_.empty()) {
+        // List test successes
+        result << "\nThe tests that were run and succeeded are:\n\n";
+        for (const auto& test_name : test_successes_) {
+          result << "    " << test_name << "\n";
+        }
+      }
+
+      return result;
+    }
+
+    // If some tests passed when they were expected to fail, alert the caller.
+    if (nonfailing_tests.empty()) return ::testing::AssertionSuccess();
+
+    // Prepare an assertion result used in the case that tests pass that were
+    // expected to fail.
+    ::testing::AssertionResult unexpected_successes =
+        ::testing::AssertionFailure();
+    unexpected_successes << "When testing type:\n    " << type_name_
+                         << "\n\nThe following tests passed when they were "
+                            "expected to fail:\n\n";
+
+    // List all of the tests that unexpectedly passed.
+    for (const auto& test_name : nonfailing_tests) {
+      unexpected_successes << "    " << test_name << "\n";
+    }
+
+    return unexpected_successes;
+  }
+
+ private:
+  void outputDivider() {
+    assertion_result_ << "========================================";
+  }
+
+  void addTestFailureImpl() {}
+
+  template <class H, class... T>
+  void addTestFailureImpl(const H& head, const T&... tail) {
+    assertion_result_ << head;
+    addTestFailureImpl(tail...);
+  }
+
+  ::testing::AssertionResult assertion_result_;
+  std::set<std::string> test_failures_;
+  std::set<std::string> test_successes_;
+  std::string type_name_;
+  bool has_error_ = false;
+};
+
+template <class T, class /*Enabler*/ = void>
+struct PropertiesOfImpl {};
+
+template <class T>
+struct PropertiesOfImpl<T, absl::void_t<typename T::properties>> {
+  using type = typename T::properties;
+};
+
+template <class T>
+struct PropertiesOfImpl<T, absl::void_t<typename T::profile_alias_of>> {
+  using type = typename PropertiesOfImpl<typename T::profile_alias_of>::type;
+};
+
+template <class T>
+struct PropertiesOf : PropertiesOfImpl<T> {};
+
+template <class T>
+using PropertiesOfT = typename PropertiesOf<T>::type;
+
+// NOTE: These enums use this naming convention to be consistent with the
+// standard trait names, which is useful since it allows us to match up each
+// enum name with a corresponding trait name in macro definitions.
+
+// An enum that describes the various expectations on an operations existence.
+enum class function_support { maybe, yes, nothrow, trivial };
+
+constexpr const char* PessimisticPropertyDescription(function_support v) {
+  return v == function_support::maybe
+             ? "no"
+             : v == function_support::yes
+                   ? "yes, potentially throwing"
+                   : v == function_support::nothrow ? "yes, nothrow"
+                                                    : "yes, trivial";
+}
+
+// Return a string that describes the kind of property support that was
+// expected.
+inline std::string ExpectedFunctionKindList(function_support min,
+                                            function_support max) {
+  if (min == max) {
+    std::string result =
+        absl::StrCat("Expected:\n  ",
+                     PessimisticPropertyDescription(
+                         static_cast<function_support>(UnderlyingValue(min))),
+                     "\n");
+    return result;
+  }
+
+  std::string result = "Expected one of:\n";
+  for (auto curr_support = UnderlyingValue(min);
+       curr_support <= UnderlyingValue(max); ++curr_support) {
+    absl::StrAppend(&result, "  ",
+                    PessimisticPropertyDescription(
+                        static_cast<function_support>(curr_support)),
+                    "\n");
+  }
+
+  return result;
+}
+
+template <class Enum>
+void ExpectModelOfImpl(ConformanceErrors* errors, Enum min_support,
+                       Enum max_support, Enum kind) {
+  const auto kind_value = UnderlyingValue(kind);
+  const auto min_support_value = UnderlyingValue(min_support);
+  const auto max_support_value = UnderlyingValue(max_support);
+
+  if (!(kind_value >= min_support_value && kind_value <= max_support_value)) {
+    errors->addTestFailure(
+        PropertyName(kind), "**Failed property expectation**\n\n",
+        ExpectedFunctionKindList(
+            static_cast<function_support>(min_support_value),
+            static_cast<function_support>(max_support_value)),
+        '\n', "Actual:\n  ",
+        PessimisticPropertyDescription(
+            static_cast<function_support>(kind_value)));
+  } else {
+    errors->addTestSuccess(PropertyName(kind));
+  }
+}
+
+#define ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(description, name) \
+  enum class name { maybe, yes, nothrow, trivial };                   \
+                                                                      \
+  constexpr const char* PropertyName(name v) { return description; }  \
+  static_assert(true, "")  // Force a semicolon when using this macro.
+
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for default construction",
+                                           default_constructible);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move construction",
+                                           move_constructible);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy construction",
+                                           copy_constructible);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move assignment",
+                                           move_assignable);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy assignment",
+                                           copy_assignable);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for destruction",
+                                           destructible);
+
+#undef ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM
+
+#define ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(description, name)     \
+  enum class name { maybe, yes, nothrow };                           \
+                                                                     \
+  constexpr const char* PropertyName(name v) { return description; } \
+  static_assert(true, "")  // Force a semicolon when using this macro.
+
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for ==", equality_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for !=", inequality_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <", less_than_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <=", less_equal_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >=",
+                                      greater_equal_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >", greater_than_comparable);
+
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for swap", swappable);
+
+#undef ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM
+
+enum class hashable { maybe, yes };
+
+constexpr const char* PropertyName(hashable v) {
+  return "support for std::hash";
+}
+
+template <class T>
+using AlwaysFalse = std::false_type;
+
+#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(name, property)   \
+  template <class T>                                                        \
+  constexpr property property##_support_of() {                              \
+    return std::is_##property<T>::value                                     \
+               ? std::is_nothrow_##property<T>::value                       \
+                     ? absl::is_trivially_##property<T>::value              \
+                           ? property::trivial                              \
+                           : property::nothrow                              \
+                     : property::yes                                        \
+               : property::maybe;                                           \
+  }                                                                         \
+                                                                            \
+  template <class T, class MinProf, class MaxProf>                          \
+  void ExpectModelOf##name(ConformanceErrors* errors) {                     \
+    (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support, \
+                        PropertiesOfT<MaxProf>::property##_support,         \
+                        property##_support_of<T>());                        \
+  }
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(DefaultConstructible,
+                                                  default_constructible);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveConstructible,
+                                                  move_constructible);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyConstructible,
+                                                  copy_constructible);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveAssignable,
+                                                  move_assignable);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyAssignable,
+                                                  copy_assignable);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(Destructible, destructible);
+
+#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER
+
+void BoolFunction(bool) noexcept;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction for checking if an operation exists through SFINAE.
+//
+// `T` is the type to test and Op is an alias containing the expression to test.
+template <class T, template <class...> class Op, class = void>
+struct IsOpableImpl : std::false_type {};
+
+template <class T, template <class...> class Op>
+struct IsOpableImpl<T, Op, absl::void_t<Op<T>>> : std::true_type {};
+
+template <template <class...> class Op>
+struct IsOpable {
+  template <class T>
+  using apply = typename IsOpableImpl<T, Op>::type;
+};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction for checking if an operation exists and is also noexcept
+// through SFINAE and the noexcept operator.
+///
+// `T` is the type to test and Op is an alias containing the expression to test.
+template <class T, template <class...> class Op, class = void>
+struct IsNothrowOpableImpl : std::false_type {};
+
+template <class T, template <class...> class Op>
+struct IsNothrowOpableImpl<T, Op, absl::enable_if_t<Op<T>::value>>
+    : std::true_type {};
+
+template <template <class...> class Op>
+struct IsNothrowOpable {
+  template <class T>
+  using apply = typename IsNothrowOpableImpl<T, Op>::type;
+};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A macro that produces the necessary function for reporting what kind of
+// support a specific comparison operation has and a function for reporting an
+// error if a given type's support for that operation does not meet the expected
+// requirements.
+#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(name, property, op)      \
+  template <class T,                                                           \
+            class Result = std::integral_constant<                             \
+                bool, noexcept((BoolFunction)(std::declval<const T&>() op      \
+                                                  std::declval<const T&>()))>> \
+  using name = Result;                                                         \
+                                                                               \
+  template <class T>                                                           \
+  constexpr property property##_support_of() {                                 \
+    return IsOpable<name>::apply<T>::value                                     \
+               ? IsNothrowOpable<name>::apply<T>::value ? property::nothrow    \
+                                                        : property::yes        \
+               : property::maybe;                                              \
+  }                                                                            \
+                                                                               \
+  template <class T, class MinProf, class MaxProf>                             \
+  void ExpectModelOf##name(ConformanceErrors* errors) {                        \
+    (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support,    \
+                        PropertiesOfT<MaxProf>::property##_support,            \
+                        property##_support_of<T>());                           \
+  }
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Generate the necessary support-checking and error reporting functions for
+// each of the comparison operators.
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(EqualityComparable,
+                                              equality_comparable, ==);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(InequalityComparable,
+                                              inequality_comparable, !=);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessThanComparable,
+                                              less_than_comparable, <);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessEqualComparable,
+                                              less_equal_comparable, <=);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterEqualComparable,
+                                              greater_equal_comparable, >=);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterThanComparable,
+                                              greater_than_comparable, >);
+
+#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// The necessary support-checking and error-reporting functions for swap.
+template <class T>
+constexpr swappable swappable_support_of() {
+  return type_traits_internal::IsSwappable<T>::value
+             ? type_traits_internal::IsNothrowSwappable<T>::value
+                   ? swappable::nothrow
+                   : swappable::yes
+             : swappable::maybe;
+}
+
+template <class T, class MinProf, class MaxProf>
+void ExpectModelOfSwappable(ConformanceErrors* errors) {
+  (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::swappable_support,
+                      PropertiesOfT<MaxProf>::swappable_support,
+                      swappable_support_of<T>());
+}
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// The necessary support-checking and error-reporting functions for std::hash.
+template <class T>
+constexpr hashable hashable_support_of() {
+  return type_traits_internal::IsHashable<T>::value ? hashable::yes
+                                                    : hashable::maybe;
+}
+
+template <class T, class MinProf, class MaxProf>
+void ExpectModelOfHashable(ConformanceErrors* errors) {
+  (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::hashable_support,
+                      PropertiesOfT<MaxProf>::hashable_support,
+                      hashable_support_of<T>());
+}
+//
+////////////////////////////////////////////////////////////////////////////////
+
+template <
+    default_constructible DefaultConstructibleValue =
+        default_constructible::maybe,
+    move_constructible MoveConstructibleValue = move_constructible::maybe,
+    copy_constructible CopyConstructibleValue = copy_constructible::maybe,
+    move_assignable MoveAssignableValue = move_assignable::maybe,
+    copy_assignable CopyAssignableValue = copy_assignable::maybe,
+    destructible DestructibleValue = destructible::maybe,
+    equality_comparable EqualityComparableValue = equality_comparable::maybe,
+    inequality_comparable InequalityComparableValue =
+        inequality_comparable::maybe,
+    less_than_comparable LessThanComparableValue = less_than_comparable::maybe,
+    less_equal_comparable LessEqualComparableValue =
+        less_equal_comparable::maybe,
+    greater_equal_comparable GreaterEqualComparableValue =
+        greater_equal_comparable::maybe,
+    greater_than_comparable GreaterThanComparableValue =
+        greater_than_comparable::maybe,
+    swappable SwappableValue = swappable::maybe,
+    hashable HashableValue = hashable::maybe>
+struct ConformanceProfile {
+  using properties = ConformanceProfile;
+
+  static constexpr default_constructible
+      default_constructible_support =  // NOLINT
+      DefaultConstructibleValue;
+
+  static constexpr move_constructible move_constructible_support =  // NOLINT
+      MoveConstructibleValue;
+
+  static constexpr copy_constructible copy_constructible_support =  // NOLINT
+      CopyConstructibleValue;
+
+  static constexpr move_assignable move_assignable_support =  // NOLINT
+      MoveAssignableValue;
+
+  static constexpr copy_assignable copy_assignable_support =  // NOLINT
+      CopyAssignableValue;
+
+  static constexpr destructible destructible_support =  // NOLINT
+      DestructibleValue;
+
+  static constexpr equality_comparable equality_comparable_support =  // NOLINT
+      EqualityComparableValue;
+
+  static constexpr inequality_comparable
+      inequality_comparable_support =  // NOLINT
+      InequalityComparableValue;
+
+  static constexpr less_than_comparable
+      less_than_comparable_support =  // NOLINT
+      LessThanComparableValue;
+
+  static constexpr less_equal_comparable
+      less_equal_comparable_support =  // NOLINT
+      LessEqualComparableValue;
+
+  static constexpr greater_equal_comparable
+      greater_equal_comparable_support =  // NOLINT
+      GreaterEqualComparableValue;
+
+  static constexpr greater_than_comparable
+      greater_than_comparable_support =  // NOLINT
+      GreaterThanComparableValue;
+
+  static constexpr swappable swappable_support = SwappableValue;  // NOLINT
+
+  static constexpr hashable hashable_support = HashableValue;  // NOLINT
+
+  static constexpr bool is_default_constructible =  // NOLINT
+      DefaultConstructibleValue != default_constructible::maybe;
+
+  static constexpr bool is_move_constructible =  // NOLINT
+      MoveConstructibleValue != move_constructible::maybe;
+
+  static constexpr bool is_copy_constructible =  // NOLINT
+      CopyConstructibleValue != copy_constructible::maybe;
+
+  static constexpr bool is_move_assignable =  // NOLINT
+      MoveAssignableValue != move_assignable::maybe;
+
+  static constexpr bool is_copy_assignable =  // NOLINT
+      CopyAssignableValue != copy_assignable::maybe;
+
+  static constexpr bool is_destructible =  // NOLINT
+      DestructibleValue != destructible::maybe;
+
+  static constexpr bool is_equality_comparable =  // NOLINT
+      EqualityComparableValue != equality_comparable::maybe;
+
+  static constexpr bool is_inequality_comparable =  // NOLINT
+      InequalityComparableValue != inequality_comparable::maybe;
+
+  static constexpr bool is_less_than_comparable =  // NOLINT
+      LessThanComparableValue != less_than_comparable::maybe;
+
+  static constexpr bool is_less_equal_comparable =  // NOLINT
+      LessEqualComparableValue != less_equal_comparable::maybe;
+
+  static constexpr bool is_greater_equal_comparable =  // NOLINT
+      GreaterEqualComparableValue != greater_equal_comparable::maybe;
+
+  static constexpr bool is_greater_than_comparable =  // NOLINT
+      GreaterThanComparableValue != greater_than_comparable::maybe;
+
+  static constexpr bool is_swappable =  // NOLINT
+      SwappableValue != swappable::maybe;
+
+  static constexpr bool is_hashable =  // NOLINT
+      HashableValue != hashable::maybe;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Compliant SFINAE-friendliness is not always present on the standard library
+// implementations that we support. This helper-struct (and associated enum) is
+// used as a means to conditionally check the hashability support of a type.
+enum class CheckHashability { no, yes };
+
+template <class T, CheckHashability ShouldCheckHashability>
+struct conservative_hashable_support_of;
+
+template <class T>
+struct conservative_hashable_support_of<T, CheckHashability::no> {
+  static constexpr hashable Invoke() { return hashable::maybe; }
+};
+
+template <class T>
+struct conservative_hashable_support_of<T, CheckHashability::yes> {
+  static constexpr hashable Invoke() { return hashable_support_of<T>(); }
+};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// The ConformanceProfile that is expected based on introspection into the type
+// by way of trait checks.
+template <class T, CheckHashability ShouldCheckHashability>
+struct SyntacticConformanceProfileOf {
+  using properties = ConformanceProfile<
+      default_constructible_support_of<T>(), move_constructible_support_of<T>(),
+      copy_constructible_support_of<T>(), move_assignable_support_of<T>(),
+      copy_assignable_support_of<T>(), destructible_support_of<T>(),
+      equality_comparable_support_of<T>(),
+      inequality_comparable_support_of<T>(),
+      less_than_comparable_support_of<T>(),
+      less_equal_comparable_support_of<T>(),
+      greater_equal_comparable_support_of<T>(),
+      greater_than_comparable_support_of<T>(), swappable_support_of<T>(),
+      conservative_hashable_support_of<T, ShouldCheckHashability>::Invoke()>;
+};
+
+#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, name)     \
+  template <default_constructible DefaultConstructibleValue,                   \
+            move_constructible MoveConstructibleValue,                         \
+            copy_constructible CopyConstructibleValue,                         \
+            move_assignable MoveAssignableValue,                               \
+            copy_assignable CopyAssignableValue,                               \
+            destructible DestructibleValue,                                    \
+            equality_comparable EqualityComparableValue,                       \
+            inequality_comparable InequalityComparableValue,                   \
+            less_than_comparable LessThanComparableValue,                      \
+            less_equal_comparable LessEqualComparableValue,                    \
+            greater_equal_comparable GreaterEqualComparableValue,              \
+            greater_than_comparable GreaterThanComparableValue,                \
+            swappable SwappableValue, hashable HashableValue>                  \
+  constexpr type ConformanceProfile<                                           \
+      DefaultConstructibleValue, MoveConstructibleValue,                       \
+      CopyConstructibleValue, MoveAssignableValue, CopyAssignableValue,        \
+      DestructibleValue, EqualityComparableValue, InequalityComparableValue,   \
+      LessThanComparableValue, LessEqualComparableValue,                       \
+      GreaterEqualComparableValue, GreaterThanComparableValue, SwappableValue, \
+      HashableValue>::name
+
+#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(type)           \
+  ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type,            \
+                                                         type##_support); \
+  ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(bool, is_##type)
+
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(default_constructible);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_constructible);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_constructible);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_assignable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_assignable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(destructible);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(equality_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(inequality_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_than_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_equal_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_equal_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_than_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(swappable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(hashable);
+
+#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF
+#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL
+
+// Retrieve the enum with the minimum underlying value.
+// Note: std::min is not constexpr in C++11, which is why this is necessary.
+template <class H>
+constexpr H MinEnum(H head) {
+  return head;
+}
+
+template <class H, class N, class... T>
+constexpr H MinEnum(H head, N next, T... tail) {
+  return (UnderlyingValue)(head) < (UnderlyingValue)(next)
+             ? (MinEnum)(head, tail...)
+             : (MinEnum)(next, tail...);
+}
+
+template <class... Profs>
+struct MinimalProfiles {
+  static constexpr default_constructible
+      default_constructible_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::default_constructible_support...);
+
+  static constexpr move_constructible move_constructible_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::move_constructible_support...);
+
+  static constexpr copy_constructible copy_constructible_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::copy_constructible_support...);
+
+  static constexpr move_assignable move_assignable_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::move_assignable_support...);
+
+  static constexpr copy_assignable copy_assignable_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::copy_assignable_support...);
+
+  static constexpr destructible destructible_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::destructible_support...);
+
+  static constexpr equality_comparable equality_comparable_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::equality_comparable_support...);
+
+  static constexpr inequality_comparable
+      inequality_comparable_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::inequality_comparable_support...);
+
+  static constexpr less_than_comparable
+      less_than_comparable_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::less_than_comparable_support...);
+
+  static constexpr less_equal_comparable
+      less_equal_comparable_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...);
+
+  static constexpr greater_equal_comparable
+      greater_equal_comparable_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...);
+
+  static constexpr greater_than_comparable
+      greater_than_comparable_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...);
+
+  static constexpr swappable swappable_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::swappable_support...);
+
+  static constexpr hashable hashable_support =  // NOLINT
+      (MinEnum)(PropertiesOfT<Profs>::hashable_support...);
+
+  using properties = ConformanceProfile<
+      default_constructible_support, move_constructible_support,
+      copy_constructible_support, move_assignable_support,
+      copy_assignable_support, destructible_support,
+      equality_comparable_support, inequality_comparable_support,
+      less_than_comparable_support, less_equal_comparable_support,
+      greater_equal_comparable_support, greater_than_comparable_support,
+      swappable_support, hashable_support>;
+};
+
+// Retrieve the enum with the greatest underlying value.
+// Note: std::max is not constexpr in C++11, which is why this is necessary.
+template <class H>
+constexpr H MaxEnum(H head) {
+  return head;
+}
+
+template <class H, class N, class... T>
+constexpr H MaxEnum(H head, N next, T... tail) {
+  return (UnderlyingValue)(next) < (UnderlyingValue)(head)
+             ? (MaxEnum)(head, tail...)
+             : (MaxEnum)(next, tail...);
+}
+
+template <class... Profs>
+struct CombineProfilesImpl {
+  static constexpr default_constructible
+      default_constructible_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::default_constructible_support...);
+
+  static constexpr move_constructible move_constructible_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::move_constructible_support...);
+
+  static constexpr copy_constructible copy_constructible_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::copy_constructible_support...);
+
+  static constexpr move_assignable move_assignable_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::move_assignable_support...);
+
+  static constexpr copy_assignable copy_assignable_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::copy_assignable_support...);
+
+  static constexpr destructible destructible_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::destructible_support...);
+
+  static constexpr equality_comparable equality_comparable_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::equality_comparable_support...);
+
+  static constexpr inequality_comparable
+      inequality_comparable_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::inequality_comparable_support...);
+
+  static constexpr less_than_comparable
+      less_than_comparable_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::less_than_comparable_support...);
+
+  static constexpr less_equal_comparable
+      less_equal_comparable_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...);
+
+  static constexpr greater_equal_comparable
+      greater_equal_comparable_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...);
+
+  static constexpr greater_than_comparable
+      greater_than_comparable_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...);
+
+  static constexpr swappable swappable_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::swappable_support...);
+
+  static constexpr hashable hashable_support =  // NOLINT
+      (MaxEnum)(PropertiesOfT<Profs>::hashable_support...);
+
+  using properties = ConformanceProfile<
+      default_constructible_support, move_constructible_support,
+      copy_constructible_support, move_assignable_support,
+      copy_assignable_support, destructible_support,
+      equality_comparable_support, inequality_comparable_support,
+      less_than_comparable_support, less_equal_comparable_support,
+      greater_equal_comparable_support, greater_than_comparable_support,
+      swappable_support, hashable_support>;
+};
+
+// NOTE: We use this as opposed to a direct alias of CombineProfilesImpl so that
+// when named aliases of CombineProfiles are created (such as in
+// conformance_aliases.h), we only pay for the combination algorithm on the
+// profiles that are actually used.
+template <class... Profs>
+struct CombineProfiles {
+  using profile_alias_of = CombineProfilesImpl<Profs...>;
+};
+
+template <>
+struct CombineProfiles<> {
+  using properties = ConformanceProfile<>;
+};
+
+template <class Profile, class Tag>
+struct StrongProfileTypedef {
+  using properties = PropertiesOfT<Profile>;
+};
+
+template <class T, class /*Enabler*/ = void>
+struct IsProfileImpl : std::false_type {};
+
+template <class T>
+struct IsProfileImpl<T, absl::void_t<PropertiesOfT<T>>> : std::true_type {};
+
+template <class T>
+struct IsProfile : IsProfileImpl<T>::type {};
+
+// A tag that describes which set of properties we will check when the user
+// requires a strict match in conformance (as opposed to a loose match which
+// allows more-refined support of any given operation).
+//
+// Currently only the RegularityDomain exists and it includes all operations
+// that the conformance testing suite knows about. The intent is that if the
+// suite is expanded to support extension, such as for checking conformance of
+// concepts like Iterators or Containers, additional corresponding domains can
+// be created.
+struct RegularityDomain {};
+
+}  // namespace types_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_
diff --git a/absl/types/internal/conformance_testing.h b/absl/types/internal/conformance_testing.h
new file mode 100644
index 0000000..487b0f7
--- /dev/null
+++ b/absl/types/internal/conformance_testing.h
@@ -0,0 +1,1386 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// conformance_testing.h
+// -----------------------------------------------------------------------------
+//
+
+#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_
+#define ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_
+
+////////////////////////////////////////////////////////////////////////////////
+//                                                                            //
+// Many templates in this file take a `T` and a `Prof` type as explicit       //
+// template arguments. These are a type to be checked and a                   //
+// "Regularity Profile" that describes what operations that type `T` is       //
+// expected to support. See "regularity_profiles.h" for more details          //
+// regarding Regularity Profiles.                                             //
+//                                                                            //
+////////////////////////////////////////////////////////////////////////////////
+
+#include <cstddef>
+#include <set>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/internal/conformance_aliases.h"
+#include "absl/types/internal/conformance_archetype.h"
+#include "absl/types/internal/conformance_profile.h"
+#include "absl/types/internal/conformance_testing_helpers.h"
+#include "absl/types/internal/parentheses.h"
+#include "absl/types/internal/transform_args.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace types_internal {
+
+// Returns true if the compiler incorrectly greedily instantiates constexpr
+// templates in any unevaluated context.
+constexpr bool constexpr_instantiation_when_unevaluated() {
+#if defined(__apple_build_version__)  // TODO(calabrese) Make more specific
+  return true;
+#elif defined(__clang__)
+  return __clang_major__ < 4;
+#elif defined(__GNUC__)
+  // TODO(calabrese) Figure out why gcc 7 fails (seems like a different bug)
+  return __GNUC__ < 5 || (__GNUC__ == 5 && __GNUC_MINOR__ < 2) || __GNUC__ >= 7;
+#else
+  return false;
+#endif
+}
+
+// Returns true if the standard library being used incorrectly produces an error
+// when instantiating the definition of a poisoned std::hash specialization.
+constexpr bool poisoned_hash_fails_instantiation() {
+#if defined(_MSC_VER) && !defined(_LIBCPP_VERSION)
+  return _MSC_VER < 1914;
+#else
+  return false;
+#endif
+}
+
+template <class Fun>
+struct GeneratorType {
+  decltype(std::declval<const Fun&>()()) operator()() const
+      noexcept(noexcept(std::declval<const Fun&>()())) {
+    return fun();
+  }
+
+  Fun fun;
+  const char* description;
+};
+
+// A "make" function for the GeneratorType template that deduces the function
+// object type.
+template <class Fun,
+          absl::enable_if_t<IsNullaryCallable<Fun>::value>** = nullptr>
+GeneratorType<Fun> Generator(Fun fun, const char* description) {
+  return GeneratorType<Fun>{absl::move(fun), description};
+}
+
+// A type that contains a set of nullary function objects that each return an
+// instance of the same type and value (though possibly different
+// representations, such as +0 and -0 or two vectors with the same elements but
+// with different capacities).
+template <class... Funs>
+struct EquivalenceClassType {
+  std::tuple<GeneratorType<Funs>...> generators;
+};
+
+// A "make" function for the EquivalenceClassType template that deduces the
+// function object types and is constrained such that a user can only pass in
+// function objects that all have the same return type.
+template <class... Funs, absl::enable_if_t<AreGeneratorsWithTheSameReturnType<
+                             Funs...>::value>** = nullptr>
+EquivalenceClassType<Funs...> EquivalenceClass(GeneratorType<Funs>... funs) {
+  return {std::make_tuple(absl::move(funs)...)};
+}
+
+// A type that contains an ordered series of EquivalenceClassTypes, from
+// smallest value to largest value.
+template <class... EqClasses>
+struct OrderedEquivalenceClasses {
+  std::tuple<EqClasses...> eq_classes;
+};
+
+// An object containing the parts of a given (name, initialization expression),
+// and is capable of generating a string that describes the given.
+struct GivenDeclaration {
+  std::string outputDeclaration(std::size_t width) const {
+    const std::size_t indent_size = 2;
+    std::string result = absl::StrCat("  ", name);
+
+    if (!expression.empty()) {
+      // Indent
+      result.resize(indent_size + width, ' ');
+      absl::StrAppend(&result, " = ", expression, ";\n");
+    } else {
+      absl::StrAppend(&result, ";\n");
+    }
+
+    return result;
+  }
+
+  std::string name;
+  std::string expression;
+};
+
+// Produce a string that contains all of the givens of an error report.
+template <class... Decls>
+std::string PrepareGivenContext(const Decls&... decls) {
+  const std::size_t width = (std::max)({decls.name.size()...});
+  return absl::StrCat("Given:\n", decls.outputDeclaration(width)..., "\n");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Function objects that perform a check for each comparison operator         //
+////////////////////////////////////////////////////////////////////////////////
+
+#define ABSL_INTERNAL_EXPECT_OP(name, op)                                   \
+  struct Expect##name {                                                     \
+    template <class T>                                                      \
+    void operator()(absl::string_view test_name, absl::string_view context, \
+                    const T& lhs, const T& rhs, absl::string_view lhs_name, \
+                    absl::string_view rhs_name) const {                     \
+      if (!static_cast<bool>(lhs op rhs)) {                                 \
+        errors->addTestFailure(                                             \
+            test_name, absl::StrCat(context,                                \
+                                    "**Unexpected comparison result**\n"    \
+                                    "\n"                                    \
+                                    "Expression:\n"                         \
+                                    "  ",                                   \
+                                    lhs_name, " " #op " ", rhs_name,        \
+                                    "\n"                                    \
+                                    "\n"                                    \
+                                    "Expected: true\n"                      \
+                                    "  Actual: false"));                    \
+      } else {                                                              \
+        errors->addTestSuccess(test_name);                                  \
+      }                                                                     \
+    }                                                                       \
+                                                                            \
+    ConformanceErrors* errors;                                              \
+  };                                                                        \
+                                                                            \
+  struct ExpectNot##name {                                                  \
+    template <class T>                                                      \
+    void operator()(absl::string_view test_name, absl::string_view context, \
+                    const T& lhs, const T& rhs, absl::string_view lhs_name, \
+                    absl::string_view rhs_name) const {                     \
+      if (lhs op rhs) {                                                     \
+        errors->addTestFailure(                                             \
+            test_name, absl::StrCat(context,                                \
+                                    "**Unexpected comparison result**\n"    \
+                                    "\n"                                    \
+                                    "Expression:\n"                         \
+                                    "  ",                                   \
+                                    lhs_name, " " #op " ", rhs_name,        \
+                                    "\n"                                    \
+                                    "\n"                                    \
+                                    "Expected: false\n"                     \
+                                    "  Actual: true"));                     \
+      } else {                                                              \
+        errors->addTestSuccess(test_name);                                  \
+      }                                                                     \
+    }                                                                       \
+                                                                            \
+    ConformanceErrors* errors;                                              \
+  }
+
+ABSL_INTERNAL_EXPECT_OP(Eq, ==);
+ABSL_INTERNAL_EXPECT_OP(Ne, !=);
+ABSL_INTERNAL_EXPECT_OP(Lt, <);
+ABSL_INTERNAL_EXPECT_OP(Le, <=);
+ABSL_INTERNAL_EXPECT_OP(Ge, >=);
+ABSL_INTERNAL_EXPECT_OP(Gt, >);
+
+#undef ABSL_INTERNAL_EXPECT_OP
+
+// A function object that verifies that two objects hash to the same value by
+// way of the std::hash specialization.
+struct ExpectSameHash {
+  template <class T>
+  void operator()(absl::string_view test_name, absl::string_view context,
+                  const T& lhs, const T& rhs, absl::string_view lhs_name,
+                  absl::string_view rhs_name) const {
+    if (std::hash<T>()(lhs) != std::hash<T>()(rhs)) {
+      errors->addTestFailure(
+          test_name, absl::StrCat(context,
+                                  "**Unexpected hash result**\n"
+                                  "\n"
+                                  "Expression:\n"
+                                  "  std::hash<T>()(",
+                                  lhs_name, ") == std::hash<T>()(", rhs_name,
+                                  ")\n"
+                                  "\n"
+                                  "Expected: true\n"
+                                  "  Actual: false"));
+    } else {
+      errors->addTestSuccess(test_name);
+    }
+  }
+
+  ConformanceErrors* errors;
+};
+
+// A function template that takes two objects and verifies that each comparison
+// operator behaves in a way that is consistent with equality. It has "OneWay"
+// in the name because the first argument will always be the left-hand operand
+// of the corresponding comparison operator and the second argument will
+// always be the right-hand operand. It will never switch that order.
+// At a higher level in the test suite, the one-way form is called once for each
+// of the two possible orders whenever lhs and rhs are not the same initializer.
+template <class T, class Prof>
+void ExpectOneWayEquality(ConformanceErrors* errors,
+                          absl::string_view test_name,
+                          absl::string_view context, const T& lhs, const T& rhs,
+                          absl::string_view lhs_name,
+                          absl::string_view rhs_name) {
+  If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke(
+      ExpectEq{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+  If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke(
+      ExpectNotNe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+  If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke(
+      ExpectNotLt{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+  If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke(
+      ExpectLe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+  If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke(
+      ExpectGe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+  If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke(
+      ExpectNotGt{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+  If<PropertiesOfT<Prof>::is_hashable>::Invoke(
+      ExpectSameHash{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+}
+
+// A function template that takes two objects and verifies that each comparison
+// operator behaves in a way that is consistent with equality. This function
+// differs from ExpectOneWayEquality in that this will do checks with argument
+// order reversed in addition to in-order.
+template <class T, class Prof>
+void ExpectEquality(ConformanceErrors* errors, absl::string_view test_name,
+                    absl::string_view context, const T& lhs, const T& rhs,
+                    absl::string_view lhs_name, absl::string_view rhs_name) {
+  (ExpectOneWayEquality<T, Prof>)(errors, test_name, context, lhs, rhs,
+                                  lhs_name, rhs_name);
+  (ExpectOneWayEquality<T, Prof>)(errors, test_name, context, rhs, lhs,
+                                  rhs_name, lhs_name);
+}
+
+// Given a generator, makes sure that a generated value and a moved-from
+// generated value are equal.
+template <class T, class Prof>
+struct ExpectMoveConstructOneGenerator {
+  template <class Fun>
+  void operator()(const Fun& generator) const {
+    const T object = generator();
+    const T moved_object = absl::move(generator());  // Force no elision.
+
+    (ExpectEquality<T, Prof>)(errors, "Move construction",
+                              PrepareGivenContext(
+                                  GivenDeclaration{"const _T object",
+                                                   generator.description},
+                                  GivenDeclaration{"const _T moved_object",
+                                                   std::string("std::move(") +
+                                                       generator.description +
+                                                       ")"}),
+                              object, moved_object, "object", "moved_object");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Given a generator, makes sure that a generated value and a copied-from
+// generated value are equal.
+template <class T, class Prof>
+struct ExpectCopyConstructOneGenerator {
+  template <class Fun>
+  void operator()(const Fun& generator) const {
+    const T object = generator();
+    const T copied_object = static_cast<const T&>(generator());
+
+    (ExpectEquality<T, Prof>)(errors, "Copy construction",
+                              PrepareGivenContext(
+                                  GivenDeclaration{"const _T object",
+                                                   generator.description},
+                                  GivenDeclaration{
+                                      "const _T copied_object",
+                                      std::string("static_cast<const _T&>(") +
+                                          generator.description + ")"}),
+                              object, copied_object, "object", "copied_object");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Default-construct and do nothing before destruction.
+//
+// This is useful in exercising the codepath of default construction followed by
+// destruction, but does not explicitly test anything. An example of where this
+// might fail is a default destructor that default-initializes a scalar and a
+// destructor reads the value of that member. Sanitizers can catch this as long
+// as our test attempts to execute such a case.
+template <class T>
+struct ExpectDefaultConstructWithDestruct {
+  void operator()() const {
+    // Scoped so that destructor gets called before reporting success.
+    {
+      T object;
+      static_cast<void>(object);
+    }
+
+    errors->addTestSuccess("Default construction");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Check move-assign into a default-constructed object.
+template <class T, class Prof>
+struct ExpectDefaultConstructWithMoveAssign {
+  template <class Fun>
+  void operator()(const Fun& generator) const {
+    const T source_of_truth = generator();
+    T object;
+    object = generator();
+
+    (ExpectEquality<T, Prof>)(errors, "Move assignment",
+                              PrepareGivenContext(
+                                  GivenDeclaration{"const _T object",
+                                                   generator.description},
+                                  GivenDeclaration{"_T object", ""},
+                                  GivenDeclaration{"object",
+                                                   generator.description}),
+                              object, source_of_truth, "std::as_const(object)",
+                              "source_of_truth");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Check copy-assign into a default-constructed object.
+template <class T, class Prof>
+struct ExpectDefaultConstructWithCopyAssign {
+  template <class Fun>
+  void operator()(const Fun& generator) const {
+    const T source_of_truth = generator();
+    T object;
+    object = static_cast<const T&>(generator());
+
+    (ExpectEquality<T, Prof>)(errors, "Copy assignment",
+                              PrepareGivenContext(
+                                  GivenDeclaration{"const _T source_of_truth",
+                                                   generator.description},
+                                  GivenDeclaration{"_T object", ""},
+                                  GivenDeclaration{
+                                      "object",
+                                      std::string("static_cast<const _T&>(") +
+                                          generator.description + ")"}),
+                              object, source_of_truth, "std::as_const(object)",
+                              "source_of_truth");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Perform a self move-assign.
+template <class T, class Prof>
+struct ExpectSelfMoveAssign {
+  template <class Fun>
+  void operator()(const Fun& generator) const {
+    T object = generator();
+    object = absl::move(object);
+
+    // NOTE: Self move-assign results in a valid-but-unspecified state.
+
+    (ExpectEquality<T, Prof>)(errors, "Move assignment",
+                              PrepareGivenContext(
+                                  GivenDeclaration{"_T object",
+                                                   generator.description},
+                                  GivenDeclaration{"object",
+                                                   "std::move(object)"}),
+                              object, object, "object", "object");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Perform a self copy-assign.
+template <class T, class Prof>
+struct ExpectSelfCopyAssign {
+  template <class Fun>
+  void operator()(const Fun& generator) const {
+    const T source_of_truth = generator();
+    T object = generator();
+    const T& const_object = object;
+    object = const_object;
+
+    (ExpectEquality<T, Prof>)(errors, "Copy assignment",
+                              PrepareGivenContext(
+                                  GivenDeclaration{"const _T source_of_truth",
+                                                   generator.description},
+                                  GivenDeclaration{"_T object",
+                                                   generator.description},
+                                  GivenDeclaration{"object",
+                                                   "std::as_const(object)"}),
+                              const_object, source_of_truth,
+                              "std::as_const(object)", "source_of_truth");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Perform a self-swap.
+template <class T, class Prof>
+struct ExpectSelfSwap {
+  template <class Fun>
+  void operator()(const Fun& generator) const {
+    const T source_of_truth = generator();
+    T object = generator();
+
+    type_traits_internal::Swap(object, object);
+
+    std::string preliminary_info = absl::StrCat(
+        PrepareGivenContext(
+            GivenDeclaration{"const _T source_of_truth", generator.description},
+            GivenDeclaration{"_T object", generator.description}),
+        "After performing a self-swap:\n"
+        "  using std::swap;\n"
+        "  swap(object, object);\n"
+        "\n");
+
+    (ExpectEquality<T, Prof>)(errors, "Swap", std::move(preliminary_info),
+                              object, source_of_truth, "std::as_const(object)",
+                              "source_of_truth");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Perform each of the single-generator checks when necessary operations are
+// supported.
+template <class T, class Prof>
+struct ExpectSelfComparison {
+  template <class Fun>
+  void operator()(const Fun& generator) const {
+    const T object = generator();
+    (ExpectOneWayEquality<T, Prof>)(errors, "Comparison",
+                                    PrepareGivenContext(GivenDeclaration{
+                                        "const _T object",
+                                        generator.description}),
+                                    object, object, "object", "object");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Perform each of the single-generator checks when necessary operations are
+// supported.
+template <class T, class Prof>
+struct ExpectConsistency {
+  template <class Fun>
+  void operator()(const Fun& generator) const {
+    If<PropertiesOfT<Prof>::is_move_constructible>::Invoke(
+        ExpectMoveConstructOneGenerator<T, Prof>{errors}, generator);
+
+    If<PropertiesOfT<Prof>::is_copy_constructible>::Invoke(
+        ExpectCopyConstructOneGenerator<T, Prof>{errors}, generator);
+
+    If<PropertiesOfT<Prof>::is_default_constructible &&
+       PropertiesOfT<Prof>::is_move_assignable>::
+        Invoke(ExpectDefaultConstructWithMoveAssign<T, Prof>{errors},
+               generator);
+
+    If<PropertiesOfT<Prof>::is_default_constructible &&
+       PropertiesOfT<Prof>::is_copy_assignable>::
+        Invoke(ExpectDefaultConstructWithCopyAssign<T, Prof>{errors},
+               generator);
+
+    If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
+        ExpectSelfMoveAssign<T, Prof>{errors}, generator);
+
+    If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
+        ExpectSelfCopyAssign<T, Prof>{errors}, generator);
+
+    If<PropertiesOfT<Prof>::is_swappable>::Invoke(
+        ExpectSelfSwap<T, Prof>{errors}, generator);
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Check move-assign with two different values.
+template <class T, class Prof>
+struct ExpectMoveAssign {
+  template <class Fun0, class Fun1>
+  void operator()(const Fun0& generator0, const Fun1& generator1) const {
+    const T source_of_truth1 = generator1();
+    T object = generator0();
+    object = generator1();
+
+    (ExpectEquality<T, Prof>)(errors, "Move assignment",
+                              PrepareGivenContext(
+                                  GivenDeclaration{"const _T source_of_truth1",
+                                                   generator1.description},
+                                  GivenDeclaration{"_T object",
+                                                   generator0.description},
+                                  GivenDeclaration{"object",
+                                                   generator1.description}),
+                              object, source_of_truth1, "std::as_const(object)",
+                              "source_of_truth1");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Check copy-assign with two different values.
+template <class T, class Prof>
+struct ExpectCopyAssign {
+  template <class Fun0, class Fun1>
+  void operator()(const Fun0& generator0, const Fun1& generator1) const {
+    const T source_of_truth1 = generator1();
+    T object = generator0();
+    object = static_cast<const T&>(generator1());
+
+    (ExpectEquality<T, Prof>)(errors, "Copy assignment",
+                              PrepareGivenContext(
+                                  GivenDeclaration{"const _T source_of_truth1",
+                                                   generator1.description},
+                                  GivenDeclaration{"_T object",
+                                                   generator0.description},
+                                  GivenDeclaration{
+                                      "object",
+                                      std::string("static_cast<const _T&>(") +
+                                          generator1.description + ")"}),
+                              object, source_of_truth1, "std::as_const(object)",
+                              "source_of_truth1");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Check swap with two different values.
+template <class T, class Prof>
+struct ExpectSwap {
+  template <class Fun0, class Fun1>
+  void operator()(const Fun0& generator0, const Fun1& generator1) const {
+    const T source_of_truth0 = generator0();
+    const T source_of_truth1 = generator1();
+    T object0 = generator0();
+    T object1 = generator1();
+
+    type_traits_internal::Swap(object0, object1);
+
+    const std::string context =
+        PrepareGivenContext(
+            GivenDeclaration{"const _T source_of_truth0",
+                             generator0.description},
+            GivenDeclaration{"const _T source_of_truth1",
+                             generator1.description},
+            GivenDeclaration{"_T object0", generator0.description},
+            GivenDeclaration{"_T object1", generator1.description}) +
+        "After performing a swap:\n"
+        "  using std::swap;\n"
+        "  swap(object0, object1);\n"
+        "\n";
+
+    (ExpectEquality<T, Prof>)(errors, "Swap", context, object0,
+                              source_of_truth1, "std::as_const(object0)",
+                              "source_of_truth1");
+    (ExpectEquality<T, Prof>)(errors, "Swap", context, object1,
+                              source_of_truth0, "std::as_const(object1)",
+                              "source_of_truth0");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Validate that `generator0` and `generator1` produce values that are equal.
+template <class T, class Prof>
+struct ExpectEquivalenceClassComparison {
+  template <class Fun0, class Fun1>
+  void operator()(const Fun0& generator0, const Fun1& generator1) const {
+    const T object0 = generator0();
+    const T object1 = generator1();
+
+    (ExpectEquality<T, Prof>)(errors, "Comparison",
+                              PrepareGivenContext(
+                                  GivenDeclaration{"const _T object0",
+                                                   generator0.description},
+                                  GivenDeclaration{"const _T object1",
+                                                   generator1.description}),
+                              object0, object1, "object0", "object1");
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Validate that all objects in the same equivalence-class have the same value.
+template <class T, class Prof>
+struct ExpectEquivalenceClassConsistency {
+  template <class Fun0, class Fun1>
+  void operator()(const Fun0& generator0, const Fun1& generator1) const {
+    If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
+        ExpectMoveAssign<T, Prof>{errors}, generator0, generator1);
+
+    If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
+        ExpectCopyAssign<T, Prof>{errors}, generator0, generator1);
+
+    If<PropertiesOfT<Prof>::is_swappable>::Invoke(ExpectSwap<T, Prof>{errors},
+                                                  generator0, generator1);
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Given a "lesser" object and a "greater" object, perform every combination of
+// comparison operators supported for the type, expecting consistent results.
+template <class T, class Prof>
+void ExpectOrdered(ConformanceErrors* errors, absl::string_view context,
+                   const T& small, const T& big, absl::string_view small_name,
+                   absl::string_view big_name) {
+  const absl::string_view test_name = "Comparison";
+
+  If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke(
+      ExpectNotEq{errors}, test_name, context, small, big, small_name,
+      big_name);
+  If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke(
+      ExpectNotEq{errors}, test_name, context, big, small, big_name,
+      small_name);
+
+  If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke(
+      ExpectNe{errors}, test_name, context, small, big, small_name, big_name);
+  If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke(
+      ExpectNe{errors}, test_name, context, big, small, big_name, small_name);
+
+  If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke(
+      ExpectLt{errors}, test_name, context, small, big, small_name, big_name);
+  If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke(
+      ExpectNotLt{errors}, test_name, context, big, small, big_name,
+      small_name);
+
+  If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke(
+      ExpectLe{errors}, test_name, context, small, big, small_name, big_name);
+  If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke(
+      ExpectNotLe{errors}, test_name, context, big, small, big_name,
+      small_name);
+
+  If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke(
+      ExpectNotGe{errors}, test_name, context, small, big, small_name,
+      big_name);
+  If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke(
+      ExpectGe{errors}, test_name, context, big, small, big_name, small_name);
+
+  If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke(
+      ExpectNotGt{errors}, test_name, context, small, big, small_name,
+      big_name);
+  If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke(
+      ExpectGt{errors}, test_name, context, big, small, big_name, small_name);
+}
+
+// For every two elements of an equivalence class, makes sure that those two
+// elements compare equal, including checks with the same argument passed as
+// both operands.
+template <class T, class Prof>
+struct ExpectEquivalenceClassComparisons {
+  template <class... Funs>
+  void operator()(EquivalenceClassType<Funs...> eq_class) const {
+    (ForEachTupleElement)(ExpectSelfComparison<T, Prof>{errors},
+                          eq_class.generators);
+
+    (ForEveryTwo)(ExpectEquivalenceClassComparison<T, Prof>{errors},
+                  eq_class.generators);
+  }
+
+  ConformanceErrors* errors;
+};
+
+// For every element of an equivalence class, makes sure that the element is
+// self-consistent (in other words, if any of move/copy/swap are defined,
+// perform those operations and make such that results and operands still
+// compare equal to known values whenever it is required for that operation.
+template <class T, class Prof>
+struct ExpectEquivalenceClass {
+  template <class... Funs>
+  void operator()(EquivalenceClassType<Funs...> eq_class) const {
+    (ForEachTupleElement)(ExpectConsistency<T, Prof>{errors},
+                          eq_class.generators);
+
+    (ForEveryTwo)(ExpectEquivalenceClassConsistency<T, Prof>{errors},
+                  eq_class.generators);
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Validate that the passed-in argument is a generator of a greater value than
+// the one produced by the "small_gen" datamember with respect to all of the
+// comparison operators that Prof requires, with both argument orders to test.
+template <class T, class Prof, class SmallGenerator>
+struct ExpectBiggerGeneratorThanComparisons {
+  template <class BigGenerator>
+  void operator()(BigGenerator big_gen) const {
+    const T small = small_gen();
+    const T big = big_gen();
+
+    (ExpectOrdered<T, Prof>)(errors,
+                             PrepareGivenContext(
+                                 GivenDeclaration{"const _T small",
+                                                  small_gen.description},
+                                 GivenDeclaration{"const _T big",
+                                                  big_gen.description}),
+                             small, big, "small", "big");
+  }
+
+  SmallGenerator small_gen;
+  ConformanceErrors* errors;
+};
+
+// Perform all of the move, copy, and swap checks on the value generated by
+// `small_gen` and the value generated by `big_gen`.
+template <class T, class Prof, class SmallGenerator>
+struct ExpectBiggerGeneratorThan {
+  template <class BigGenerator>
+  void operator()(BigGenerator big_gen) const {
+    If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
+        ExpectMoveAssign<T, Prof>{errors}, small_gen, big_gen);
+    If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
+        ExpectMoveAssign<T, Prof>{errors}, big_gen, small_gen);
+
+    If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
+        ExpectCopyAssign<T, Prof>{errors}, small_gen, big_gen);
+    If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
+        ExpectCopyAssign<T, Prof>{errors}, big_gen, small_gen);
+
+    If<PropertiesOfT<Prof>::is_swappable>::Invoke(ExpectSwap<T, Prof>{errors},
+                                                  small_gen, big_gen);
+  }
+
+  SmallGenerator small_gen;
+  ConformanceErrors* errors;
+};
+
+// Validate that the result of a generator is greater than the results of all
+// generators in an equivalence class with respect to comparisons.
+template <class T, class Prof, class SmallGenerator>
+struct ExpectBiggerGeneratorThanEqClassesComparisons {
+  template <class BigEqClass>
+  void operator()(BigEqClass big_eq_class) const {
+    (ForEachTupleElement)(
+        ExpectBiggerGeneratorThanComparisons<T, Prof, SmallGenerator>{small_gen,
+                                                                      errors},
+        big_eq_class.generators);
+  }
+
+  SmallGenerator small_gen;
+  ConformanceErrors* errors;
+};
+
+// Validate that the non-comparison binary operations required by Prof are
+// correct for the result of each generator of big_eq_class and a generator of
+// the logically smaller value returned by small_gen.
+template <class T, class Prof, class SmallGenerator>
+struct ExpectBiggerGeneratorThanEqClasses {
+  template <class BigEqClass>
+  void operator()(BigEqClass big_eq_class) const {
+    (ForEachTupleElement)(
+        ExpectBiggerGeneratorThan<T, Prof, SmallGenerator>{small_gen, errors},
+        big_eq_class.generators);
+  }
+
+  SmallGenerator small_gen;
+  ConformanceErrors* errors;
+};
+
+// Validate that each equivalence class that is passed is logically less than
+// the equivalence classes that comes later on in the argument list.
+template <class T, class Prof>
+struct ExpectOrderedEquivalenceClassesComparisons {
+  template <class... BigEqClasses>
+  struct Impl {
+    // Validate that the value produced by `small_gen` is less than all of the
+    // values generated by those of the logically larger equivalence classes.
+    template <class SmallGenerator>
+    void operator()(SmallGenerator small_gen) const {
+      (ForEachTupleElement)(ExpectBiggerGeneratorThanEqClassesComparisons<
+                                T, Prof, SmallGenerator>{small_gen, errors},
+                            big_eq_classes);
+    }
+
+    std::tuple<BigEqClasses...> big_eq_classes;
+    ConformanceErrors* errors;
+  };
+
+  // When given no equivalence classes, no validation is necessary.
+  void operator()() const {}
+
+  template <class SmallEqClass, class... BigEqClasses>
+  void operator()(SmallEqClass small_eq_class,
+                  BigEqClasses... big_eq_classes) const {
+    // For each generator in the first equivalence class, make sure that it is
+    // less than each of those in the logically greater equivalence classes.
+    (ForEachTupleElement)(
+        Impl<BigEqClasses...>{std::make_tuple(absl::move(big_eq_classes)...),
+                              errors},
+        small_eq_class.generators);
+
+    // Recurse so that all equivalence class combinations are checked.
+    (*this)(absl::move(big_eq_classes)...);
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Validate that the non-comparison binary operations required by Prof are
+// correct for the result of each generator of big_eq_classes and a generator of
+// the logically smaller value returned by small_gen.
+template <class T, class Prof>
+struct ExpectOrderedEquivalenceClasses {
+  template <class... BigEqClasses>
+  struct Impl {
+    template <class SmallGenerator>
+    void operator()(SmallGenerator small_gen) const {
+      (ForEachTupleElement)(
+          ExpectBiggerGeneratorThanEqClasses<T, Prof, SmallGenerator>{small_gen,
+                                                                      errors},
+          big_eq_classes);
+    }
+
+    std::tuple<BigEqClasses...> big_eq_classes;
+    ConformanceErrors* errors;
+  };
+
+  // Check that small_eq_class is logically consistent and also is logically
+  // less than all values in big_eq_classes.
+  template <class SmallEqClass, class... BigEqClasses>
+  void operator()(SmallEqClass small_eq_class,
+                  BigEqClasses... big_eq_classes) const {
+    (ForEachTupleElement)(
+        Impl<BigEqClasses...>{std::make_tuple(absl::move(big_eq_classes)...),
+                              errors},
+        small_eq_class.generators);
+
+    (*this)(absl::move(big_eq_classes)...);
+  }
+
+  // Terminating case of operator().
+  void operator()() const {}
+
+  ConformanceErrors* errors;
+};
+
+// Validate that a type meets the syntactic requirements of std::hash if the
+// range of profiles requires it.
+template <class T, class MinProf, class MaxProf>
+struct ExpectHashable {
+  void operator()() const {
+    ExpectModelOfHashable<T, MinProf, MaxProf>(errors);
+  }
+
+  ConformanceErrors* errors;
+};
+
+// Validate that the type `T` meets all of the requirements associated with
+// `MinProf` and without going beyond the syntactic properties of `MaxProf`.
+template <class T, class MinProf, class MaxProf>
+struct ExpectModels {
+  void operator()(ConformanceErrors* errors) const {
+    ExpectModelOfDefaultConstructible<T, MinProf, MaxProf>(errors);
+    ExpectModelOfMoveConstructible<T, MinProf, MaxProf>(errors);
+    ExpectModelOfCopyConstructible<T, MinProf, MaxProf>(errors);
+    ExpectModelOfMoveAssignable<T, MinProf, MaxProf>(errors);
+    ExpectModelOfCopyAssignable<T, MinProf, MaxProf>(errors);
+    ExpectModelOfDestructible<T, MinProf, MaxProf>(errors);
+    ExpectModelOfEqualityComparable<T, MinProf, MaxProf>(errors);
+    ExpectModelOfInequalityComparable<T, MinProf, MaxProf>(errors);
+    ExpectModelOfLessThanComparable<T, MinProf, MaxProf>(errors);
+    ExpectModelOfLessEqualComparable<T, MinProf, MaxProf>(errors);
+    ExpectModelOfGreaterEqualComparable<T, MinProf, MaxProf>(errors);
+    ExpectModelOfGreaterThanComparable<T, MinProf, MaxProf>(errors);
+    ExpectModelOfSwappable<T, MinProf, MaxProf>(errors);
+
+    // Only check hashability on compilers that have a compliant default-hash.
+    If<!poisoned_hash_fails_instantiation()>::Invoke(
+        ExpectHashable<T, MinProf, MaxProf>{errors});
+  }
+};
+
+// A metafunction that yields a Profile matching the set of properties that are
+// safe to be checked (lack-of-hashability is only checked on standard library
+// implementations that are standards compliant in that they provide a std::hash
+// primary template that is SFINAE-friendly)
+template <class LogicalProf, class T>
+struct MinimalCheckableProfile {
+  using type =
+      MinimalProfiles<PropertiesOfT<LogicalProf>,
+                      PropertiesOfT<SyntacticConformanceProfileOf<
+                          T, !PropertiesOfT<LogicalProf>::is_hashable &&
+                                     poisoned_hash_fails_instantiation()
+                                 ? CheckHashability::no
+                                 : CheckHashability::yes>>>;
+};
+
+// An identity metafunction
+template <class T>
+struct Always {
+  using type = T;
+};
+
+// Validate the T meets all of the necessary requirements of LogicalProf, with
+// syntactic requirements defined by the profile range [MinProf, MaxProf].
+template <class T, class LogicalProf, class MinProf, class MaxProf,
+          class... EqClasses>
+ConformanceErrors ExpectRegularityImpl(
+    OrderedEquivalenceClasses<EqClasses...> vals) {
+  ConformanceErrors errors((NameOf<T>()));
+
+  If<!constexpr_instantiation_when_unevaluated()>::Invoke(
+      ExpectModels<T, MinProf, MaxProf>(), &errors);
+
+  using minimal_profile = typename absl::conditional_t<
+      constexpr_instantiation_when_unevaluated(), Always<LogicalProf>,
+      MinimalCheckableProfile<LogicalProf, T>>::type;
+
+  If<PropertiesOfT<minimal_profile>::is_default_constructible>::Invoke(
+      ExpectDefaultConstructWithDestruct<T>{&errors});
+
+  //////////////////////////////////////////////////////////////////////////////
+  // Perform all comparison checks first, since later checks depend on their
+  // correctness.
+  //
+  // Check all of the comparisons for all values in the same equivalence
+  // class (equal with respect to comparison operators and hash the same).
+  (ForEachTupleElement)(
+      ExpectEquivalenceClassComparisons<T, minimal_profile>{&errors},
+      vals.eq_classes);
+
+  // Check all of the comparisons for each combination of values that are in
+  // different equivalence classes (not equal with respect to comparison
+  // operators).
+  absl::apply(
+      ExpectOrderedEquivalenceClassesComparisons<T, minimal_profile>{&errors},
+      vals.eq_classes);
+  //
+  //////////////////////////////////////////////////////////////////////////////
+
+  // Perform remaining checks, relying on comparisons.
+  // TODO(calabrese) short circuit if any comparisons above failed.
+  (ForEachTupleElement)(ExpectEquivalenceClass<T, minimal_profile>{&errors},
+                        vals.eq_classes);
+
+  absl::apply(ExpectOrderedEquivalenceClasses<T, minimal_profile>{&errors},
+              vals.eq_classes);
+
+  return errors;
+}
+
+// A type that represents a range of profiles that are acceptable to be matched.
+//
+// `MinProf` is the minimum set of syntactic requirements that must be met.
+//
+// `MaxProf` is the maximum set of syntactic requirements that must be met.
+// This maximum is particularly useful for certain "strictness" checking. Some
+// examples for when this is useful:
+//
+// * Making sure that a type is move-only (rather than simply movable)
+//
+// * Making sure that a member function is *not* noexcept in cases where it
+//   cannot be noexcept, such as if a dependent datamember has certain
+//   operations that are not noexcept.
+//
+// * Making sure that a type tightly matches a spec, such as the standard.
+//
+// `LogicalProf` is the Profile for which run-time testing is to take place.
+//
+// Note: The reason for `LogicalProf` is because it is often the case, when
+// dealing with templates, that a declaration of a given operation is specified,
+// but whose body would fail to instantiate. Examples include the
+// copy-constructor of a standard container when the element-type is move-only,
+// or the comparison operators of a standard container when the element-type
+// does not have the necessary comparison operations defined. The `LogicalProf`
+// parameter allows us to capture the intent of what should be tested at
+// run-time, even in the cases where syntactically it might otherwise appear as
+// though the type undergoing testing supports more than it actually does.
+template <class LogicalProf, class MinProf = LogicalProf,
+          class MaxProf = MinProf>
+struct ProfileRange {
+  using logical_profile = LogicalProf;
+  using min_profile = MinProf;
+  using max_profile = MaxProf;
+};
+
+// Similar to ProfileRange except that it creates a profile range that is
+// coupled with a Domain and is used when testing that a type matches exactly
+// the "minimum" requirements of LogicalProf.
+template <class StrictnessDomain, class LogicalProf,
+          class MinProf = LogicalProf, class MaxProf = MinProf>
+struct StrictProfileRange {
+  // We do not yet support extension.
+  static_assert(
+      std::is_same<StrictnessDomain, RegularityDomain>::value,
+      "Currently, the only valid StrictnessDomain is RegularityDomain.");
+  using strictness_domain = StrictnessDomain;
+  using logical_profile = LogicalProf;
+  using min_profile = MinProf;
+  using max_profile = MaxProf;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction that creates a StrictProfileRange from a Domain and either a
+// Profile or ProfileRange.
+template <class StrictnessDomain, class ProfOrRange>
+struct MakeStrictProfileRange;
+
+template <class StrictnessDomain, class LogicalProf>
+struct MakeStrictProfileRange {
+  using type = StrictProfileRange<StrictnessDomain, LogicalProf>;
+};
+
+template <class StrictnessDomain, class LogicalProf, class MinProf,
+          class MaxProf>
+struct MakeStrictProfileRange<StrictnessDomain,
+                              ProfileRange<LogicalProf, MinProf, MaxProf>> {
+  using type =
+      StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>;
+};
+
+template <class StrictnessDomain, class ProfOrRange>
+using MakeStrictProfileRangeT =
+    typename MakeStrictProfileRange<StrictnessDomain, ProfOrRange>::type;
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// A profile in the RegularityDomain with the strongest possible requirements.
+using MostStrictProfile =
+    CombineProfiles<TriviallyCompleteProfile, NothrowComparableProfile>;
+
+// Forms a ProfileRange that treats the Profile as the bare minimum requirements
+// of a type.
+template <class LogicalProf, class MinProf = LogicalProf>
+using LooseProfileRange = StrictProfileRange<RegularityDomain, LogicalProf,
+                                             MinProf, MostStrictProfile>;
+
+template <class Prof>
+using MakeLooseProfileRangeT = Prof;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// The following classes implement the metafunction ProfileRangeOfT<T> that
+// takes either a Profile or ProfileRange and yields the ProfileRange to be
+// used during testing.
+//
+template <class T, class /*Enabler*/ = void>
+struct ProfileRangeOfImpl;
+
+template <class T>
+struct ProfileRangeOfImpl<T, absl::void_t<PropertiesOfT<T>>> {
+  using type = LooseProfileRange<T>;
+};
+
+template <class T>
+struct ProfileRangeOf : ProfileRangeOfImpl<T> {};
+
+template <class StrictnessDomain, class LogicalProf, class MinProf,
+          class MaxProf>
+struct ProfileRangeOf<
+    StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>> {
+  using type =
+      StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>;
+};
+
+template <class T>
+using ProfileRangeOfT = typename ProfileRangeOf<T>::type;
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Extract the logical profile of a range (what will be runtime tested).
+template <class T>
+using LogicalProfileOfT = typename ProfileRangeOfT<T>::logical_profile;
+
+// Extract the minimal syntactic profile of a range (error if not at least).
+template <class T>
+using MinProfileOfT = typename ProfileRangeOfT<T>::min_profile;
+
+// Extract the maximum syntactic profile of a range (error if more than).
+template <class T>
+using MaxProfileOfT = typename ProfileRangeOfT<T>::max_profile;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+template <class T>
+struct IsProfileOrProfileRange : IsProfile<T>::type {};
+
+template <class StrictnessDomain, class LogicalProf, class MinProf,
+          class MaxProf>
+struct IsProfileOrProfileRange<
+    StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>>
+    : std::true_type {};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// TODO(calabrese): Consider naming the functions in this class the same as
+// the macros (defined later on) so that auto-complete leads to the correct name
+// and so that a user cannot accidentally call a function rather than the macro
+// form.
+template <bool ExpectSuccess, class T, class... EqClasses>
+struct ExpectConformanceOf {
+  // Add a value to be tested. Subsequent calls to this function on the same
+  // object must specify logically "larger" values with respect to the
+  // comparison operators of the type, if any.
+  //
+  // NOTE: This function should not be called directly. A stateless lambda is
+  // implicitly formed and passed when using the INITIALIZER macro at the bottom
+  // of this file.
+  template <class Fun,
+            absl::enable_if_t<std::is_same<
+                ResultOfGeneratorT<GeneratorType<Fun>>, T>::value>** = nullptr>
+  ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...,
+                                           EquivalenceClassType<Fun>>
+  initializer(GeneratorType<Fun> fun) && {
+    return {
+        {std::tuple_cat(absl::move(ordered_vals.eq_classes),
+                        std::make_tuple((EquivalenceClass)(absl::move(fun))))},
+        std::move(expected_failed_tests)};
+  }
+
+  template <class... TestNames,
+            absl::enable_if_t<!ExpectSuccess && sizeof...(EqClasses) == 0 &&
+                              absl::conjunction<std::is_convertible<
+                                  TestNames, absl::string_view>...>::value>** =
+                nullptr>
+  ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...>
+  due_to(TestNames&&... test_names) && {
+    (InsertEach)(&expected_failed_tests,
+                 absl::AsciiStrToLower(absl::string_view(test_names))...);
+
+    return {absl::move(ordered_vals), std::move(expected_failed_tests)};
+  }
+
+  template <class... TestNames, int = 0,  // MSVC disambiguator
+            absl::enable_if_t<ExpectSuccess && sizeof...(EqClasses) == 0 &&
+                              absl::conjunction<std::is_convertible<
+                                  TestNames, absl::string_view>...>::value>** =
+                nullptr>
+  ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...>
+  due_to(TestNames&&... test_names) && {
+    // TODO(calabrese) Instead have DUE_TO only exist via a CRTP base.
+    // This would produce better errors messages than the static_assert.
+    static_assert(!ExpectSuccess,
+                  "DUE_TO cannot be called when conformance is expected -- did "
+                  "you mean to use ASSERT_NONCONFORMANCE_OF?");
+  }
+
+  // Add a value to be tested. Subsequent calls to this function on the same
+  // object must specify logically "larger" values with respect to the
+  // comparison operators of the type, if any.
+  //
+  // NOTE: This function should not be called directly. A stateful lambda is
+  // implicitly formed and passed when using the INITIALIZER macro at the bottom
+  // of this file.
+  template <class Fun,
+            absl::enable_if_t<std::is_same<
+                ResultOfGeneratorT<GeneratorType<Fun>>, T>::value>** = nullptr>
+  ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...,
+                                           EquivalenceClassType<Fun>>
+  dont_class_directly_stateful_initializer(GeneratorType<Fun> fun) && {
+    return {
+        {std::tuple_cat(absl::move(ordered_vals.eq_classes),
+                        std::make_tuple((EquivalenceClass)(absl::move(fun))))},
+        std::move(expected_failed_tests)};
+  }
+
+  // Add a set of value to be tested, where each value is equal with respect to
+  // the comparison operators and std::hash specialization, if defined.
+  template <
+      class... Funs,
+      absl::void_t<absl::enable_if_t<std::is_same<
+          ResultOfGeneratorT<GeneratorType<Funs>>, T>::value>...>** = nullptr>
+  ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...,
+                                           EquivalenceClassType<Funs...>>
+  equivalence_class(GeneratorType<Funs>... funs) && {
+    return {{std::tuple_cat(
+                absl::move(ordered_vals.eq_classes),
+                std::make_tuple((EquivalenceClass)(absl::move(funs)...)))},
+            std::move(expected_failed_tests)};
+  }
+
+  // Execute the tests for the captured set of values, strictly matching a range
+  // of expected profiles in a given domain.
+  template <
+      class ProfRange,
+      absl::enable_if_t<IsProfileOrProfileRange<ProfRange>::value>** = nullptr>
+  ABSL_MUST_USE_RESULT ::testing::AssertionResult with_strict_profile(
+      ProfRange /*profile*/) {
+    ConformanceErrors test_result =
+        (ExpectRegularityImpl<
+            T, LogicalProfileOfT<ProfRange>, MinProfileOfT<ProfRange>,
+            MaxProfileOfT<ProfRange>>)(absl::move(ordered_vals));
+
+    return ExpectSuccess ? test_result.assertionResult()
+                         : test_result.expectFailedTests(expected_failed_tests);
+  }
+
+  // Execute the tests for the captured set of values, loosely matching a range
+  // of expected profiles (loose in that an interface is allowed to be more
+  // refined that a profile suggests, such as a type having a noexcept copy
+  // constructor when all that is required is that the copy constructor exists).
+  template <class Prof, absl::enable_if_t<IsProfile<Prof>::value>** = nullptr>
+  ABSL_MUST_USE_RESULT ::testing::AssertionResult with_loose_profile(
+      Prof /*profile*/) {
+    ConformanceErrors test_result =
+        (ExpectRegularityImpl<
+            T, Prof, Prof,
+            CombineProfiles<TriviallyCompleteProfile,
+                            NothrowComparableProfile>>)(absl::
+                                                            move(ordered_vals));
+
+    return ExpectSuccess ? test_result.assertionResult()
+                         : test_result.expectFailedTests(expected_failed_tests);
+  }
+
+  OrderedEquivalenceClasses<EqClasses...> ordered_vals;
+  std::set<std::string> expected_failed_tests;
+};
+
+template <class T>
+using ExpectConformanceOfType = ExpectConformanceOf</*ExpectSuccess=*/true, T>;
+
+template <class T>
+using ExpectNonconformanceOfType =
+    ExpectConformanceOf</*ExpectSuccess=*/false, T>;
+
+struct EquivalenceClassMaker {
+  // TODO(calabrese) Constrain to callable
+  template <class Fun>
+  static GeneratorType<Fun> initializer(GeneratorType<Fun> fun) {
+    return fun;
+  }
+};
+
+// A top-level macro that begins the builder pattern.
+//
+// The argument here takes the datatype to be tested.
+#define ABSL_INTERNAL_ASSERT_CONFORMANCE_OF(...)                            \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                             \
+  if ABSL_INTERNAL_LPAREN                                                   \
+  const ::testing::AssertionResult gtest_ar =                               \
+      ABSL_INTERNAL_LPAREN ::absl::types_internal::ExpectConformanceOfType< \
+          __VA_ARGS__>()
+
+// Akin to ASSERT_CONFORMANCE_OF except that it expects failure and tries to
+// match text.
+#define ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(...)                            \
+  GTEST_AMBIGUOUS_ELSE_BLOCKER_                                                \
+  if ABSL_INTERNAL_LPAREN                                                      \
+  const ::testing::AssertionResult gtest_ar =                                  \
+      ABSL_INTERNAL_LPAREN ::absl::types_internal::ExpectNonconformanceOfType< \
+          __VA_ARGS__>()
+
+////////////////////////////////////////////////////////////////////////////////
+// NOTE: The following macros look like they are recursive, but are not (macros
+// cannot recurse). These actually refer to member functions of the same name.
+// This is done intentionally so that a user cannot accidentally invoke a
+// member function of the conformance-testing suite without going through the
+// macro.
+////////////////////////////////////////////////////////////////////////////////
+
+// Specify expected test failures as comma-separated strings.
+#define DUE_TO(...) due_to(__VA_ARGS__)
+
+// Specify a value to be tested.
+//
+// Note: Internally, this takes an expression and turns it into the return value
+// of lambda that captures no data. The expression is stringized during
+// preprocessing so that it can be used in error reports.
+#define INITIALIZER(...)                         \
+  initializer(::absl::types_internal::Generator( \
+      [] { return __VA_ARGS__; }, ABSL_INTERNAL_STRINGIZE(__VA_ARGS__)))
+
+// Specify a value to be tested.
+//
+// Note: Internally, this takes an expression and turns it into the return value
+// of lambda that captures data by reference. The expression is stringized
+// during preprocessing so that it can be used in error reports.
+#define STATEFUL_INITIALIZER(...)                         \
+  stateful_initializer(::absl::types_internal::Generator( \
+      [&] { return __VA_ARGS__; }, ABSL_INTERNAL_STRINGIZE(__VA_ARGS__)))
+
+// Used in the builder-pattern.
+//
+// Takes a series of INITIALIZER and/or STATEFUL_INITIALIZER invocations and
+// forwards them along to be tested, grouping them such that the testing suite
+// knows that they are supposed to represent the same logical value (the values
+// compare the same, hash the same, etc.).
+#define EQUIVALENCE_CLASS(...)                    \
+  equivalence_class(ABSL_INTERNAL_TRANSFORM_ARGS( \
+      ABSL_INTERNAL_PREPEND_EQ_MAKER, __VA_ARGS__))
+
+// An invocation of this or WITH_STRICT_PROFILE must end the builder-pattern.
+// It takes a Profile as its argument.
+//
+// This executes the tests and allows types that are "more referined" than the
+// profile specifies, but not less. For instance, if the Profile specifies
+// noexcept copy-constructiblity, the test will fail if the copy-constructor is
+// not noexcept, however, it will succeed if the copy constructor is trivial.
+//
+// This is useful for testing that a type meets some minimum set of
+// requirements.
+#define WITH_LOOSE_PROFILE(...)                                      \
+  with_loose_profile(                                                \
+      ::absl::types_internal::MakeLooseProfileRangeT<__VA_ARGS__>()) \
+      ABSL_INTERNAL_RPAREN ABSL_INTERNAL_RPAREN;                     \
+  else GTEST_FATAL_FAILURE_(gtest_ar.failure_message())  // NOLINT
+
+// An invocation of this or WITH_STRICT_PROFILE must end the builder-pattern.
+// It takes a Domain and a Profile as its arguments.
+//
+// This executes the tests and disallows types that differ at all from the
+// properties of the Profile. For instance, if the Profile specifies noexcept
+// copy-constructiblity, the test will fail if the copy constructor is trivial.
+//
+// This is useful for testing that a type does not do anything more than a
+// specification requires, such as to minimize things like Hyrum's Law, or more
+// commonly, to prevent a type from being "accidentally" copy-constructible in
+// a way that may produce incorrect results, simply because the user forget to
+// delete that operation.
+#define WITH_STRICT_PROFILE(...)                                      \
+  with_strict_profile(                                                \
+      ::absl::types_internal::MakeStrictProfileRangeT<__VA_ARGS__>()) \
+      ABSL_INTERNAL_RPAREN ABSL_INTERNAL_RPAREN;                      \
+  else GTEST_FATAL_FAILURE_(gtest_ar.failure_message())  // NOLINT
+
+// Internal macro that is used in the internals of the EDSL when forming
+// equivalence classes.
+#define ABSL_INTERNAL_PREPEND_EQ_MAKER(arg) \
+  ::absl::types_internal::EquivalenceClassMaker().arg
+
+}  // namespace types_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_
diff --git a/absl/types/internal/conformance_testing_helpers.h b/absl/types/internal/conformance_testing_helpers.h
new file mode 100644
index 0000000..00775f9
--- /dev/null
+++ b/absl/types/internal/conformance_testing_helpers.h
@@ -0,0 +1,391 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_
+#define ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_
+
+// Checks to determine whether or not we can use abi::__cxa_demangle
+#if (defined(__ANDROID__) || defined(ANDROID)) && !defined(OS_ANDROID)
+#define ABSL_INTERNAL_OS_ANDROID
+#endif
+
+// We support certain compilers only.  See demangle.h for details.
+#if defined(OS_ANDROID) && (defined(__i386__) || defined(__x86_64__))
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0
+#elif (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \
+    !defined(__mips__)
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1
+#elif defined(__clang__) && !defined(_MSC_VER)
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1
+#else
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0
+#endif
+
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+#include "absl/utility/utility.h"
+
+#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE
+#include <cxxabi.h>
+
+#include <cstdlib>
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace types_internal {
+
+// Return a readable name for type T.
+template <class T>
+absl::string_view NameOfImpl() {
+// TODO(calabrese) Investigate using debugging:internal_demangle as a fallback.
+#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE
+  int status = 0;
+  char* demangled_name = nullptr;
+
+  demangled_name =
+      abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
+
+  if (status == 0 && demangled_name != nullptr) {
+    return demangled_name;
+  } else {
+    return typeid(T).name();
+  }
+#else
+  return typeid(T).name();
+#endif
+  // NOTE: We intentionally leak demangled_name so that it remains valid
+  // throughout the remainder of the program.
+}
+
+// Given a type, returns as nice of a type name as we can produce (demangled).
+//
+// Note: This currently strips cv-qualifiers and references, but that is okay
+// because we only use this internally with unqualified object types.
+template <class T>
+std::string NameOf() {
+  static const absl::string_view result = NameOfImpl<T>();
+  return std::string(result);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Metafunction to check if a type is callable with no explicit arguments
+template <class Fun, class /*Enabler*/ = void>
+struct IsNullaryCallableImpl : std::false_type {};
+
+template <class Fun>
+struct IsNullaryCallableImpl<
+    Fun, absl::void_t<decltype(std::declval<const Fun&>()())>>
+    : std::true_type {
+  using result_type = decltype(std::declval<const Fun&>()());
+
+  template <class ValueType>
+  using for_type = std::is_same<ValueType, result_type>;
+
+  using void_if_true = void;
+};
+
+template <class Fun>
+struct IsNullaryCallable : IsNullaryCallableImpl<Fun> {};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// A type that contains a function object that returns an instance of a type
+// that is undergoing conformance testing. This function is required to always
+// return the same value upon invocation.
+template <class Fun>
+struct GeneratorType;
+
+// A type that contains a tuple of GeneratorType<Fun> where each Fun has the
+// same return type. The result of each of the different generators should all
+// be equal values, though the underlying object representation may differ (such
+// as if one returns 0.0 and another return -0.0, or if one returns an empty
+// vector and another returns an empty vector with a different capacity.
+template <class... Funs>
+struct EquivalenceClassType;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction to check if a type is a specialization of EquivalenceClassType
+template <class T>
+struct IsEquivalenceClass : std::false_type {};
+
+template <>
+struct IsEquivalenceClass<EquivalenceClassType<>> : std::true_type {
+  using self = IsEquivalenceClass;
+
+  // A metafunction to check if this EquivalenceClassType is a valid
+  // EquivalenceClassType for a type `ValueType` that is undergoing testing
+  template <class ValueType>
+  using for_type = std::true_type;
+};
+
+template <class Head, class... Tail>
+struct IsEquivalenceClass<EquivalenceClassType<Head, Tail...>>
+    : std::true_type {
+  using self = IsEquivalenceClass;
+
+  // The type undergoing conformance testing that this EquivalenceClass
+  // corresponds to
+  using result_type = typename IsNullaryCallable<Head>::result_type;
+
+  // A metafunction to check if this EquivalenceClassType is a valid
+  // EquivalenceClassType for a type `ValueType` that is undergoing testing
+  template <class ValueType>
+  using for_type = std::is_same<ValueType, result_type>;
+};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// A type that contains an ordered series of EquivalenceClassTypes, where the
+// the function object of each underlying GeneratorType has the same return type
+//
+// These equivalence classes are required to be in a logical ascending order
+// that is consistent with comparison operators that are defined for the return
+// type of each GeneratorType, if any.
+template <class... EqClasses>
+struct OrderedEquivalenceClasses;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction to determine the return type of the function object contained
+// in a GeneratorType specialization.
+template <class T>
+struct ResultOfGenerator {};
+
+template <class Fun>
+struct ResultOfGenerator<GeneratorType<Fun>> {
+  using type = decltype(std::declval<const Fun&>()());
+};
+
+template <class Fun>
+using ResultOfGeneratorT = typename ResultOfGenerator<GeneratorType<Fun>>::type;
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction that yields true iff each of Funs is a GeneratorType
+// specialization and they all contain functions with the same return type
+template <class /*Enabler*/, class... Funs>
+struct AreGeneratorsWithTheSameReturnTypeImpl : std::false_type {};
+
+template <>
+struct AreGeneratorsWithTheSameReturnTypeImpl<void> : std::true_type {};
+
+template <class Head, class... Tail>
+struct AreGeneratorsWithTheSameReturnTypeImpl<
+    typename std::enable_if<absl::conjunction<std::is_same<
+        ResultOfGeneratorT<Head>, ResultOfGeneratorT<Tail>>...>::value>::type,
+    Head, Tail...> : std::true_type {};
+
+template <class... Funs>
+struct AreGeneratorsWithTheSameReturnType
+    : AreGeneratorsWithTheSameReturnTypeImpl<void, Funs...>::type {};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction that yields true iff each of Funs is an EquivalenceClassType
+// specialization and they all contain GeneratorType specializations that have
+// the same return type
+template <class... EqClasses>
+struct AreEquivalenceClassesOfTheSameType {
+  static_assert(sizeof...(EqClasses) != sizeof...(EqClasses), "");
+};
+
+template <>
+struct AreEquivalenceClassesOfTheSameType<> : std::true_type {
+  using self = AreEquivalenceClassesOfTheSameType;
+
+  // Metafunction to check that a type is the same as all of the equivalence
+  // classes, if any.
+  // Note: In this specialization there are no equivalence classes, so the
+  // value type is always compatible.
+  template <class /*ValueType*/>
+  using for_type = std::true_type;
+};
+
+template <class... Funs>
+struct AreEquivalenceClassesOfTheSameType<EquivalenceClassType<Funs...>>
+    : std::true_type {
+  using self = AreEquivalenceClassesOfTheSameType;
+
+  // Metafunction to check that a type is the same as all of the equivalence
+  // classes, if any.
+  template <class ValueType>
+  using for_type = typename IsEquivalenceClass<
+      EquivalenceClassType<Funs...>>::template for_type<ValueType>;
+};
+
+template <class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+    EquivalenceClassType<>, EquivalenceClassType<>, TailEqClasses...>
+    : AreEquivalenceClassesOfTheSameType<TailEqClasses...>::self {};
+
+template <class HeadNextFun, class... TailNextFuns, class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+    EquivalenceClassType<>, EquivalenceClassType<HeadNextFun, TailNextFuns...>,
+    TailEqClasses...>
+    : AreEquivalenceClassesOfTheSameType<
+          EquivalenceClassType<HeadNextFun, TailNextFuns...>,
+          TailEqClasses...>::self {};
+
+template <class HeadHeadFun, class... TailHeadFuns, class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+    EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, EquivalenceClassType<>,
+    TailEqClasses...>
+    : AreEquivalenceClassesOfTheSameType<
+          EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
+          TailEqClasses...>::self {};
+
+template <class HeadHeadFun, class... TailHeadFuns, class HeadNextFun,
+          class... TailNextFuns, class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+    EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
+    EquivalenceClassType<HeadNextFun, TailNextFuns...>, TailEqClasses...>
+    : absl::conditional_t<
+          IsNullaryCallable<HeadNextFun>::template for_type<
+              typename IsNullaryCallable<HeadHeadFun>::result_type>::value,
+          AreEquivalenceClassesOfTheSameType<
+              EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
+              TailEqClasses...>,
+          std::false_type> {};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Execute a function for each passed-in parameter.
+template <class Fun, class... Cases>
+void ForEachParameter(const Fun& fun, const Cases&... cases) {
+  const std::initializer_list<bool> results = {
+      (static_cast<void>(fun(cases)), true)...};
+
+  (void)results;
+}
+
+// Execute a function on each passed-in parameter (using a bound function).
+template <class Fun>
+struct ForEachParameterFun {
+  template <class... T>
+  void operator()(const T&... cases) const {
+    (ForEachParameter)(fun, cases...);
+  }
+
+  Fun fun;
+};
+
+// Execute a function on each element of a tuple.
+template <class Fun, class Tup>
+void ForEachTupleElement(const Fun& fun, const Tup& tup) {
+  absl::apply(ForEachParameterFun<Fun>{fun}, tup);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Execute a function for each combination of two elements of a tuple, including
+// combinations of an element with itself.
+template <class Fun, class... T>
+struct ForEveryTwoImpl {
+  template <class Lhs>
+  struct WithBoundLhs {
+    template <class Rhs>
+    void operator()(const Rhs& rhs) const {
+      fun(lhs, rhs);
+    }
+
+    Fun fun;
+    Lhs lhs;
+  };
+
+  template <class Lhs>
+  void operator()(const Lhs& lhs) const {
+    (ForEachTupleElement)(WithBoundLhs<Lhs>{fun, lhs}, args);
+  }
+
+  Fun fun;
+  std::tuple<T...> args;
+};
+
+template <class Fun, class... T>
+void ForEveryTwo(const Fun& fun, std::tuple<T...> args) {
+  (ForEachTupleElement)(ForEveryTwoImpl<Fun, T...>{fun, args}, args);
+}
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Insert all values into an associative container
+template<class Container>
+void InsertEach(Container* cont) {
+}
+
+template<class Container, class H, class... T>
+void InsertEach(Container* cont, H&& head, T&&... tail) {
+  cont->insert(head);
+  (InsertEach)(cont, tail...);
+}
+//
+////////////////////////////////////////////////////////////////////////////////
+// A template with a nested "Invoke" static-member-function that executes a
+// passed-in Callable when `Condition` is true, otherwise it ignores the
+// Callable. This is useful for executing a function object with a condition
+// that corresponds to whether or not the Callable can be safely instantiated.
+// It has some overlapping uses with C++17 `if constexpr`.
+template <bool Condition>
+struct If;
+
+template <>
+struct If</*Condition =*/false> {
+  template <class Fun, class... P>
+  static void Invoke(const Fun& /*fun*/, P&&... /*args*/) {}
+};
+
+template <>
+struct If</*Condition =*/true> {
+  template <class Fun, class... P>
+  static void Invoke(const Fun& fun, P&&... args) {
+    // TODO(calabrese) Use std::invoke equivalent instead of function-call.
+    fun(absl::forward<P>(args)...);
+  }
+};
+
+//
+// ABSL_INTERNAL_STRINGIZE(...)
+//
+// This variadic macro transforms its arguments into a c-string literal after
+// expansion.
+//
+// Example:
+//
+//   ABSL_INTERNAL_STRINGIZE(std::array<int, 10>)
+//
+// Results in:
+//
+//   "std::array<int, 10>"
+#define ABSL_INTERNAL_STRINGIZE(...) ABSL_INTERNAL_STRINGIZE_IMPL((__VA_ARGS__))
+#define ABSL_INTERNAL_STRINGIZE_IMPL(arg) ABSL_INTERNAL_STRINGIZE_IMPL2 arg
+#define ABSL_INTERNAL_STRINGIZE_IMPL2(...) #__VA_ARGS__
+
+}  // namespace types_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_
diff --git a/absl/types/internal/conformance_testing_test.cc b/absl/types/internal/conformance_testing_test.cc
new file mode 100644
index 0000000..cf262fa
--- /dev/null
+++ b/absl/types/internal/conformance_testing_test.cc
@@ -0,0 +1,1556 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/types/internal/conformance_testing.h"
+
+#include <new>
+#include <type_traits>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+#include "absl/types/internal/conformance_aliases.h"
+#include "absl/types/internal/conformance_profile.h"
+
+namespace {
+
+namespace ti = absl::types_internal;
+
+template <class T>
+using DefaultConstructibleWithNewImpl = decltype(::new (std::nothrow) T);
+
+template <class T>
+using DefaultConstructibleWithNew =
+    absl::type_traits_internal::is_detected<DefaultConstructibleWithNewImpl, T>;
+
+template <class T>
+using MoveConstructibleWithNewImpl =
+    decltype(::new (std::nothrow) T(std::declval<T>()));
+
+template <class T>
+using MoveConstructibleWithNew =
+    absl::type_traits_internal::is_detected<MoveConstructibleWithNewImpl, T>;
+
+template <class T>
+using CopyConstructibleWithNewImpl =
+    decltype(::new (std::nothrow) T(std::declval<const T&>()));
+
+template <class T>
+using CopyConstructibleWithNew =
+    absl::type_traits_internal::is_detected<CopyConstructibleWithNewImpl, T>;
+
+template <class T,
+          class Result =
+              std::integral_constant<bool, noexcept(::new (std::nothrow) T)>>
+using NothrowDefaultConstructibleWithNewImpl =
+    typename std::enable_if<Result::value>::type;
+
+template <class T>
+using NothrowDefaultConstructibleWithNew =
+    absl::type_traits_internal::is_detected<
+        NothrowDefaultConstructibleWithNewImpl, T>;
+
+template <class T,
+          class Result = std::integral_constant<
+              bool, noexcept(::new (std::nothrow) T(std::declval<T>()))>>
+using NothrowMoveConstructibleWithNewImpl =
+    typename std::enable_if<Result::value>::type;
+
+template <class T>
+using NothrowMoveConstructibleWithNew =
+    absl::type_traits_internal::is_detected<NothrowMoveConstructibleWithNewImpl,
+                                            T>;
+
+template <class T,
+          class Result = std::integral_constant<
+              bool, noexcept(::new (std::nothrow) T(std::declval<const T&>()))>>
+using NothrowCopyConstructibleWithNewImpl =
+    typename std::enable_if<Result::value>::type;
+
+template <class T>
+using NothrowCopyConstructibleWithNew =
+    absl::type_traits_internal::is_detected<NothrowCopyConstructibleWithNewImpl,
+                                            T>;
+
+// NOTE: ?: is used to verify contextually-convertible to bool and not simply
+//       implicit or explicit convertibility.
+#define ABSL_INTERNAL_COMPARISON_OP_EXPR(op) \
+  ((std::declval<const T&>() op std::declval<const T&>()) ? true : true)
+
+#define ABSL_INTERNAL_COMPARISON_OP_TRAIT(name, op)                         \
+  template <class T>                                                        \
+  using name##Impl = decltype(ABSL_INTERNAL_COMPARISON_OP_EXPR(op));        \
+                                                                            \
+  template <class T>                                                        \
+  using name = absl::type_traits_internal::is_detected<name##Impl, T>;      \
+                                                                            \
+  template <class T,                                                        \
+            class Result = std::integral_constant<                          \
+                bool, noexcept(ABSL_INTERNAL_COMPARISON_OP_EXPR(op))>>      \
+  using Nothrow##name##Impl = typename std::enable_if<Result::value>::type; \
+                                                                            \
+  template <class T>                                                        \
+  using Nothrow##name =                                                     \
+      absl::type_traits_internal::is_detected<Nothrow##name##Impl, T>
+
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(EqualityComparable, ==);
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(InequalityComparable, !=);
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessThanComparable, <);
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessEqualComparable, <=);
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterEqualComparable, >=);
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterThanComparable, >);
+
+#undef ABSL_INTERNAL_COMPARISON_OP_TRAIT
+
+template <class T>
+class ProfileTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(ProfileTest);
+
+TYPED_TEST_P(ProfileTest, HasAppropriateConstructionProperties) {
+  using profile = typename TypeParam::profile;
+  using arch = typename TypeParam::arch;
+  using expected_profile = typename TypeParam::expected_profile;
+
+  using props = ti::PropertiesOfT<profile>;
+  using arch_props = ti::PropertiesOfArchetypeT<arch>;
+  using expected_props = ti::PropertiesOfT<expected_profile>;
+
+  // Make sure all of the properties are as expected.
+  // There are seemingly redundant tests here to make it easier to diagnose
+  // the specifics of the failure if something were to go wrong.
+  EXPECT_TRUE((std::is_same<props, arch_props>::value));
+  EXPECT_TRUE((std::is_same<props, expected_props>::value));
+  EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
+
+  EXPECT_EQ(props::default_constructible_support,
+            expected_props::default_constructible_support);
+
+  EXPECT_EQ(props::move_constructible_support,
+            expected_props::move_constructible_support);
+
+  EXPECT_EQ(props::copy_constructible_support,
+            expected_props::copy_constructible_support);
+
+  EXPECT_EQ(props::destructible_support, expected_props::destructible_support);
+
+  // Avoid additional error message noise when profile and archetype match with
+  // each other but were not what was expected.
+  if (!std::is_same<props, arch_props>::value) {
+    EXPECT_EQ(arch_props::default_constructible_support,
+              expected_props::default_constructible_support);
+
+    EXPECT_EQ(arch_props::move_constructible_support,
+              expected_props::move_constructible_support);
+
+    EXPECT_EQ(arch_props::copy_constructible_support,
+              expected_props::copy_constructible_support);
+
+    EXPECT_EQ(arch_props::destructible_support,
+              expected_props::destructible_support);
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                       Default constructor checks                         //
+  //////////////////////////////////////////////////////////////////////////////
+  EXPECT_EQ(props::default_constructible_support,
+            expected_props::default_constructible_support);
+
+  switch (expected_props::default_constructible_support) {
+    case ti::default_constructible::maybe:
+      EXPECT_FALSE(DefaultConstructibleWithNew<arch>::value);
+      EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_FALSE(std::is_default_constructible<arch>::value);
+        EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value);
+        EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value);
+      }
+      break;
+    case ti::default_constructible::yes:
+      EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value);
+      EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_TRUE(std::is_default_constructible<arch>::value);
+        EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value);
+        EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value);
+      }
+      break;
+    case ti::default_constructible::nothrow:
+      EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value);
+      EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_TRUE(std::is_default_constructible<arch>::value);
+        EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value);
+        EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value);
+
+        // Constructor traits also check the destructor.
+        if (std::is_nothrow_destructible<arch>::value) {
+          EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value);
+        }
+      }
+      break;
+    case ti::default_constructible::trivial:
+      EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value);
+      EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_TRUE(std::is_default_constructible<arch>::value);
+        EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value);
+
+        // Constructor triviality traits require trivially destructible types.
+        if (absl::is_trivially_destructible<arch>::value) {
+          EXPECT_TRUE(absl::is_trivially_default_constructible<arch>::value);
+        }
+      }
+      break;
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                         Move constructor checks                          //
+  //////////////////////////////////////////////////////////////////////////////
+  EXPECT_EQ(props::move_constructible_support,
+            expected_props::move_constructible_support);
+
+  switch (expected_props::move_constructible_support) {
+    case ti::move_constructible::maybe:
+      EXPECT_FALSE(MoveConstructibleWithNew<arch>::value);
+      EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_FALSE(std::is_move_constructible<arch>::value);
+        EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value);
+        EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value);
+      }
+      break;
+    case ti::move_constructible::yes:
+      EXPECT_TRUE(MoveConstructibleWithNew<arch>::value);
+      EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_TRUE(std::is_move_constructible<arch>::value);
+        EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value);
+        EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value);
+      }
+      break;
+    case ti::move_constructible::nothrow:
+      EXPECT_TRUE(MoveConstructibleWithNew<arch>::value);
+      EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_TRUE(std::is_move_constructible<arch>::value);
+        EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value);
+        EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value);
+
+        // Constructor traits also check the destructor.
+        if (std::is_nothrow_destructible<arch>::value) {
+          EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value);
+        }
+      }
+      break;
+    case ti::move_constructible::trivial:
+      EXPECT_TRUE(MoveConstructibleWithNew<arch>::value);
+      EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_TRUE(std::is_move_constructible<arch>::value);
+        EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value);
+
+        // Constructor triviality traits require trivially destructible types.
+        if (absl::is_trivially_destructible<arch>::value) {
+          EXPECT_TRUE(absl::is_trivially_move_constructible<arch>::value);
+        }
+      }
+      break;
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                         Copy constructor checks                          //
+  //////////////////////////////////////////////////////////////////////////////
+  EXPECT_EQ(props::copy_constructible_support,
+            expected_props::copy_constructible_support);
+
+  switch (expected_props::copy_constructible_support) {
+    case ti::copy_constructible::maybe:
+      EXPECT_FALSE(CopyConstructibleWithNew<arch>::value);
+      EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_FALSE(std::is_copy_constructible<arch>::value);
+        EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value);
+        EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value);
+      }
+      break;
+    case ti::copy_constructible::yes:
+      EXPECT_TRUE(CopyConstructibleWithNew<arch>::value);
+      EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_TRUE(std::is_copy_constructible<arch>::value);
+        EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value);
+        EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value);
+      }
+      break;
+    case ti::copy_constructible::nothrow:
+      EXPECT_TRUE(CopyConstructibleWithNew<arch>::value);
+      EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_TRUE(std::is_copy_constructible<arch>::value);
+        EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value);
+        EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value);
+
+        // Constructor traits also check the destructor.
+        if (std::is_nothrow_destructible<arch>::value) {
+          EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value);
+        }
+      }
+      break;
+    case ti::copy_constructible::trivial:
+      EXPECT_TRUE(CopyConstructibleWithNew<arch>::value);
+      EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value);
+
+      // Standard constructible traits depend on the destructor.
+      if (std::is_destructible<arch>::value) {
+        EXPECT_TRUE(std::is_copy_constructible<arch>::value);
+        EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value);
+
+        // Constructor triviality traits require trivially destructible types.
+        if (absl::is_trivially_destructible<arch>::value) {
+          EXPECT_TRUE(absl::is_trivially_copy_constructible<arch>::value);
+        }
+      }
+      break;
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                           Destructible checks                            //
+  //////////////////////////////////////////////////////////////////////////////
+  EXPECT_EQ(props::destructible_support, expected_props::destructible_support);
+
+  switch (expected_props::destructible_support) {
+    case ti::destructible::maybe:
+      EXPECT_FALSE(std::is_destructible<arch>::value);
+      EXPECT_FALSE(std::is_nothrow_destructible<arch>::value);
+      EXPECT_FALSE(absl::is_trivially_destructible<arch>::value);
+      break;
+    case ti::destructible::yes:
+      EXPECT_TRUE(std::is_destructible<arch>::value);
+      EXPECT_FALSE(std::is_nothrow_destructible<arch>::value);
+      EXPECT_FALSE(absl::is_trivially_destructible<arch>::value);
+      break;
+    case ti::destructible::nothrow:
+      EXPECT_TRUE(std::is_destructible<arch>::value);
+      EXPECT_TRUE(std::is_nothrow_destructible<arch>::value);
+      EXPECT_FALSE(absl::is_trivially_destructible<arch>::value);
+      break;
+    case ti::destructible::trivial:
+      EXPECT_TRUE(std::is_destructible<arch>::value);
+      EXPECT_TRUE(std::is_nothrow_destructible<arch>::value);
+      EXPECT_TRUE(absl::is_trivially_destructible<arch>::value);
+      break;
+  }
+}
+
+TYPED_TEST_P(ProfileTest, HasAppropriateAssignmentProperties) {
+  using profile = typename TypeParam::profile;
+  using arch = typename TypeParam::arch;
+  using expected_profile = typename TypeParam::expected_profile;
+
+  using props = ti::PropertiesOfT<profile>;
+  using arch_props = ti::PropertiesOfArchetypeT<arch>;
+  using expected_props = ti::PropertiesOfT<expected_profile>;
+
+  // Make sure all of the properties are as expected.
+  // There are seemingly redundant tests here to make it easier to diagnose
+  // the specifics of the failure if something were to go wrong.
+  EXPECT_TRUE((std::is_same<props, arch_props>::value));
+  EXPECT_TRUE((std::is_same<props, expected_props>::value));
+  EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
+
+  EXPECT_EQ(props::move_assignable_support,
+            expected_props::move_assignable_support);
+
+  EXPECT_EQ(props::copy_assignable_support,
+            expected_props::copy_assignable_support);
+
+  // Avoid additional error message noise when profile and archetype match with
+  // each other but were not what was expected.
+  if (!std::is_same<props, arch_props>::value) {
+    EXPECT_EQ(arch_props::move_assignable_support,
+              expected_props::move_assignable_support);
+
+    EXPECT_EQ(arch_props::copy_assignable_support,
+              expected_props::copy_assignable_support);
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                          Move assignment checks                          //
+  //////////////////////////////////////////////////////////////////////////////
+  EXPECT_EQ(props::move_assignable_support,
+            expected_props::move_assignable_support);
+
+  switch (expected_props::move_assignable_support) {
+    case ti::move_assignable::maybe:
+      EXPECT_FALSE(std::is_move_assignable<arch>::value);
+      EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value);
+      EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value);
+      break;
+    case ti::move_assignable::yes:
+      EXPECT_TRUE(std::is_move_assignable<arch>::value);
+      EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value);
+      EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value);
+      break;
+    case ti::move_assignable::nothrow:
+      EXPECT_TRUE(std::is_move_assignable<arch>::value);
+      EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value);
+      EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value);
+      break;
+    case ti::move_assignable::trivial:
+      EXPECT_TRUE(std::is_move_assignable<arch>::value);
+      EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value);
+      EXPECT_TRUE(absl::is_trivially_move_assignable<arch>::value);
+      break;
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                          Copy assignment checks                          //
+  //////////////////////////////////////////////////////////////////////////////
+  EXPECT_EQ(props::copy_assignable_support,
+            expected_props::copy_assignable_support);
+
+  switch (expected_props::copy_assignable_support) {
+    case ti::copy_assignable::maybe:
+      EXPECT_FALSE(std::is_copy_assignable<arch>::value);
+      EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value);
+      EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value);
+      break;
+    case ti::copy_assignable::yes:
+      EXPECT_TRUE(std::is_copy_assignable<arch>::value);
+      EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value);
+      EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value);
+      break;
+    case ti::copy_assignable::nothrow:
+      EXPECT_TRUE(std::is_copy_assignable<arch>::value);
+      EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value);
+      EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value);
+      break;
+    case ti::copy_assignable::trivial:
+      EXPECT_TRUE(std::is_copy_assignable<arch>::value);
+      EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value);
+      EXPECT_TRUE(absl::is_trivially_copy_assignable<arch>::value);
+      break;
+  }
+}
+
+TYPED_TEST_P(ProfileTest, HasAppropriateComparisonProperties) {
+  using profile = typename TypeParam::profile;
+  using arch = typename TypeParam::arch;
+  using expected_profile = typename TypeParam::expected_profile;
+
+  using props = ti::PropertiesOfT<profile>;
+  using arch_props = ti::PropertiesOfArchetypeT<arch>;
+  using expected_props = ti::PropertiesOfT<expected_profile>;
+
+  // Make sure all of the properties are as expected.
+  // There are seemingly redundant tests here to make it easier to diagnose
+  // the specifics of the failure if something were to go wrong.
+  EXPECT_TRUE((std::is_same<props, arch_props>::value));
+  EXPECT_TRUE((std::is_same<props, expected_props>::value));
+  EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
+
+  EXPECT_EQ(props::equality_comparable_support,
+            expected_props::equality_comparable_support);
+
+  EXPECT_EQ(props::inequality_comparable_support,
+            expected_props::inequality_comparable_support);
+
+  EXPECT_EQ(props::less_than_comparable_support,
+            expected_props::less_than_comparable_support);
+
+  EXPECT_EQ(props::less_equal_comparable_support,
+            expected_props::less_equal_comparable_support);
+
+  EXPECT_EQ(props::greater_equal_comparable_support,
+            expected_props::greater_equal_comparable_support);
+
+  EXPECT_EQ(props::greater_than_comparable_support,
+            expected_props::greater_than_comparable_support);
+
+  // Avoid additional error message noise when profile and archetype match with
+  // each other but were not what was expected.
+  if (!std::is_same<props, arch_props>::value) {
+    EXPECT_EQ(arch_props::equality_comparable_support,
+              expected_props::equality_comparable_support);
+
+    EXPECT_EQ(arch_props::inequality_comparable_support,
+              expected_props::inequality_comparable_support);
+
+    EXPECT_EQ(arch_props::less_than_comparable_support,
+              expected_props::less_than_comparable_support);
+
+    EXPECT_EQ(arch_props::less_equal_comparable_support,
+              expected_props::less_equal_comparable_support);
+
+    EXPECT_EQ(arch_props::greater_equal_comparable_support,
+              expected_props::greater_equal_comparable_support);
+
+    EXPECT_EQ(arch_props::greater_than_comparable_support,
+              expected_props::greater_than_comparable_support);
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                        Equality comparable checks                        //
+  //////////////////////////////////////////////////////////////////////////////
+  switch (expected_props::equality_comparable_support) {
+    case ti::equality_comparable::maybe:
+      EXPECT_FALSE(EqualityComparable<arch>::value);
+      EXPECT_FALSE(NothrowEqualityComparable<arch>::value);
+      break;
+    case ti::equality_comparable::yes:
+      EXPECT_TRUE(EqualityComparable<arch>::value);
+      EXPECT_FALSE(NothrowEqualityComparable<arch>::value);
+      break;
+    case ti::equality_comparable::nothrow:
+      EXPECT_TRUE(EqualityComparable<arch>::value);
+      EXPECT_TRUE(NothrowEqualityComparable<arch>::value);
+      break;
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                       Inequality comparable checks                       //
+  //////////////////////////////////////////////////////////////////////////////
+  switch (expected_props::inequality_comparable_support) {
+    case ti::inequality_comparable::maybe:
+      EXPECT_FALSE(InequalityComparable<arch>::value);
+      EXPECT_FALSE(NothrowInequalityComparable<arch>::value);
+      break;
+    case ti::inequality_comparable::yes:
+      EXPECT_TRUE(InequalityComparable<arch>::value);
+      EXPECT_FALSE(NothrowInequalityComparable<arch>::value);
+      break;
+    case ti::inequality_comparable::nothrow:
+      EXPECT_TRUE(InequalityComparable<arch>::value);
+      EXPECT_TRUE(NothrowInequalityComparable<arch>::value);
+      break;
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                       Less than comparable checks                        //
+  //////////////////////////////////////////////////////////////////////////////
+  switch (expected_props::less_than_comparable_support) {
+    case ti::less_than_comparable::maybe:
+      EXPECT_FALSE(LessThanComparable<arch>::value);
+      EXPECT_FALSE(NothrowLessThanComparable<arch>::value);
+      break;
+    case ti::less_than_comparable::yes:
+      EXPECT_TRUE(LessThanComparable<arch>::value);
+      EXPECT_FALSE(NothrowLessThanComparable<arch>::value);
+      break;
+    case ti::less_than_comparable::nothrow:
+      EXPECT_TRUE(LessThanComparable<arch>::value);
+      EXPECT_TRUE(NothrowLessThanComparable<arch>::value);
+      break;
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                      Less equal comparable checks                        //
+  //////////////////////////////////////////////////////////////////////////////
+  switch (expected_props::less_equal_comparable_support) {
+    case ti::less_equal_comparable::maybe:
+      EXPECT_FALSE(LessEqualComparable<arch>::value);
+      EXPECT_FALSE(NothrowLessEqualComparable<arch>::value);
+      break;
+    case ti::less_equal_comparable::yes:
+      EXPECT_TRUE(LessEqualComparable<arch>::value);
+      EXPECT_FALSE(NothrowLessEqualComparable<arch>::value);
+      break;
+    case ti::less_equal_comparable::nothrow:
+      EXPECT_TRUE(LessEqualComparable<arch>::value);
+      EXPECT_TRUE(NothrowLessEqualComparable<arch>::value);
+      break;
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                     Greater equal comparable checks                      //
+  //////////////////////////////////////////////////////////////////////////////
+  switch (expected_props::greater_equal_comparable_support) {
+    case ti::greater_equal_comparable::maybe:
+      EXPECT_FALSE(GreaterEqualComparable<arch>::value);
+      EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value);
+      break;
+    case ti::greater_equal_comparable::yes:
+      EXPECT_TRUE(GreaterEqualComparable<arch>::value);
+      EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value);
+      break;
+    case ti::greater_equal_comparable::nothrow:
+      EXPECT_TRUE(GreaterEqualComparable<arch>::value);
+      EXPECT_TRUE(NothrowGreaterEqualComparable<arch>::value);
+      break;
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                     Greater than comparable checks                       //
+  //////////////////////////////////////////////////////////////////////////////
+  switch (expected_props::greater_than_comparable_support) {
+    case ti::greater_than_comparable::maybe:
+      EXPECT_FALSE(GreaterThanComparable<arch>::value);
+      EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value);
+      break;
+    case ti::greater_than_comparable::yes:
+      EXPECT_TRUE(GreaterThanComparable<arch>::value);
+      EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value);
+      break;
+    case ti::greater_than_comparable::nothrow:
+      EXPECT_TRUE(GreaterThanComparable<arch>::value);
+      EXPECT_TRUE(NothrowGreaterThanComparable<arch>::value);
+      break;
+  }
+}
+
+TYPED_TEST_P(ProfileTest, HasAppropriateAuxilliaryProperties) {
+  using profile = typename TypeParam::profile;
+  using arch = typename TypeParam::arch;
+  using expected_profile = typename TypeParam::expected_profile;
+
+  using props = ti::PropertiesOfT<profile>;
+  using arch_props = ti::PropertiesOfArchetypeT<arch>;
+  using expected_props = ti::PropertiesOfT<expected_profile>;
+
+  // Make sure all of the properties are as expected.
+  // There are seemingly redundant tests here to make it easier to diagnose
+  // the specifics of the failure if something were to go wrong.
+  EXPECT_TRUE((std::is_same<props, arch_props>::value));
+  EXPECT_TRUE((std::is_same<props, expected_props>::value));
+  EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
+
+  EXPECT_EQ(props::swappable_support, expected_props::swappable_support);
+
+  EXPECT_EQ(props::hashable_support, expected_props::hashable_support);
+
+  // Avoid additional error message noise when profile and archetype match with
+  // each other but were not what was expected.
+  if (!std::is_same<props, arch_props>::value) {
+    EXPECT_EQ(arch_props::swappable_support, expected_props::swappable_support);
+
+    EXPECT_EQ(arch_props::hashable_support, expected_props::hashable_support);
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                            Swappable checks                              //
+  //////////////////////////////////////////////////////////////////////////////
+  switch (expected_props::swappable_support) {
+    case ti::swappable::maybe:
+      EXPECT_FALSE(absl::type_traits_internal::IsSwappable<arch>::value);
+      EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value);
+      break;
+    case ti::swappable::yes:
+      EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value);
+      EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value);
+      break;
+    case ti::swappable::nothrow:
+      EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value);
+      EXPECT_TRUE(absl::type_traits_internal::IsNothrowSwappable<arch>::value);
+      break;
+  }
+
+  //////////////////////////////////////////////////////////////////////////////
+  //                             Hashable checks                              //
+  //////////////////////////////////////////////////////////////////////////////
+  switch (expected_props::hashable_support) {
+    case ti::hashable::maybe:
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+      EXPECT_FALSE(absl::type_traits_internal::IsHashable<arch>::value);
+#endif  // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+      break;
+    case ti::hashable::yes:
+      EXPECT_TRUE(absl::type_traits_internal::IsHashable<arch>::value);
+      break;
+  }
+}
+
+REGISTER_TYPED_TEST_SUITE_P(ProfileTest, HasAppropriateConstructionProperties,
+                            HasAppropriateAssignmentProperties,
+                            HasAppropriateComparisonProperties,
+                            HasAppropriateAuxilliaryProperties);
+
+template <class Profile, class Arch, class ExpectedProfile>
+struct ProfileAndExpectation {
+  using profile = Profile;
+  using arch = Arch;
+  using expected_profile = ExpectedProfile;
+};
+
+using CoreProfilesToTest = ::testing::Types<
+    // The terminating case of combine (all properties are "maybe").
+    ProfileAndExpectation<ti::CombineProfiles<>,
+                          ti::Archetype<ti::CombineProfiles<>>,
+                          ti::ConformanceProfile<>>,
+
+    // Core default constructor profiles
+    ProfileAndExpectation<
+        ti::HasDefaultConstructorProfile, ti::HasDefaultConstructorArchetype,
+        ti::ConformanceProfile<ti::default_constructible::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowDefaultConstructorProfile,
+        ti::HasNothrowDefaultConstructorArchetype,
+        ti::ConformanceProfile<ti::default_constructible::nothrow>>,
+    ProfileAndExpectation<
+        ti::HasTrivialDefaultConstructorProfile,
+        ti::HasTrivialDefaultConstructorArchetype,
+        ti::ConformanceProfile<ti::default_constructible::trivial>>,
+
+    // Core move constructor profiles
+    ProfileAndExpectation<
+        ti::HasMoveConstructorProfile, ti::HasMoveConstructorArchetype,
+        ti::ConformanceProfile<ti::default_constructible::maybe,
+                               ti::move_constructible::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowMoveConstructorProfile,
+        ti::HasNothrowMoveConstructorArchetype,
+        ti::ConformanceProfile<ti::default_constructible::maybe,
+                               ti::move_constructible::nothrow>>,
+    ProfileAndExpectation<
+        ti::HasTrivialMoveConstructorProfile,
+        ti::HasTrivialMoveConstructorArchetype,
+        ti::ConformanceProfile<ti::default_constructible::maybe,
+                               ti::move_constructible::trivial>>,
+
+    // Core copy constructor profiles
+    ProfileAndExpectation<
+        ti::HasCopyConstructorProfile, ti::HasCopyConstructorArchetype,
+        ti::ConformanceProfile<ti::default_constructible::maybe,
+                               ti::move_constructible::maybe,
+                               ti::copy_constructible::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowCopyConstructorProfile,
+        ti::HasNothrowCopyConstructorArchetype,
+        ti::ConformanceProfile<ti::default_constructible::maybe,
+                               ti::move_constructible::maybe,
+                               ti::copy_constructible::nothrow>>,
+    ProfileAndExpectation<
+        ti::HasTrivialCopyConstructorProfile,
+        ti::HasTrivialCopyConstructorArchetype,
+        ti::ConformanceProfile<ti::default_constructible::maybe,
+                               ti::move_constructible::maybe,
+                               ti::copy_constructible::trivial>>,
+
+    // Core move assignment profiles
+    ProfileAndExpectation<
+        ti::HasMoveAssignProfile, ti::HasMoveAssignArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowMoveAssignProfile, ti::HasNothrowMoveAssignArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::nothrow>>,
+    ProfileAndExpectation<
+        ti::HasTrivialMoveAssignProfile, ti::HasTrivialMoveAssignArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::trivial>>,
+
+    // Core copy assignment profiles
+    ProfileAndExpectation<
+        ti::HasCopyAssignProfile, ti::HasCopyAssignArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowCopyAssignProfile, ti::HasNothrowCopyAssignArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::nothrow>>,
+    ProfileAndExpectation<
+        ti::HasTrivialCopyAssignProfile, ti::HasTrivialCopyAssignArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::trivial>>,
+
+    // Core destructor profiles
+    ProfileAndExpectation<
+        ti::HasDestructorProfile, ti::HasDestructorArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowDestructorProfile, ti::HasNothrowDestructorArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::nothrow>>,
+    ProfileAndExpectation<
+        ti::HasTrivialDestructorProfile, ti::HasTrivialDestructorArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::trivial>>,
+
+    // Core equality comparable profiles
+    ProfileAndExpectation<
+        ti::HasEqualityProfile, ti::HasEqualityArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowEqualityProfile, ti::HasNothrowEqualityArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::nothrow>>,
+
+    // Core inequality comparable profiles
+    ProfileAndExpectation<
+        ti::HasInequalityProfile, ti::HasInequalityArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowInequalityProfile, ti::HasNothrowInequalityArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe,
+            ti::inequality_comparable::nothrow>>,
+
+    // Core less than comparable profiles
+    ProfileAndExpectation<
+        ti::HasLessThanProfile, ti::HasLessThanArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowLessThanProfile, ti::HasNothrowLessThanArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::nothrow>>,
+
+    // Core less equal comparable profiles
+    ProfileAndExpectation<
+        ti::HasLessEqualProfile, ti::HasLessEqualArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowLessEqualProfile, ti::HasNothrowLessEqualArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe,
+            ti::less_equal_comparable::nothrow>>,
+
+    // Core greater equal comparable profiles
+    ProfileAndExpectation<
+        ti::HasGreaterEqualProfile, ti::HasGreaterEqualArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowGreaterEqualProfile, ti::HasNothrowGreaterEqualArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::nothrow>>,
+
+    // Core greater than comparable profiles
+    ProfileAndExpectation<
+        ti::HasGreaterThanProfile, ti::HasGreaterThanArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::maybe,
+            ti::greater_than_comparable::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowGreaterThanProfile, ti::HasNothrowGreaterThanArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::maybe,
+            ti::greater_than_comparable::nothrow>>,
+
+    // Core swappable profiles
+    ProfileAndExpectation<
+        ti::HasSwapProfile, ti::HasSwapArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::maybe,
+            ti::greater_than_comparable::maybe, ti::swappable::yes>>,
+    ProfileAndExpectation<
+        ti::HasNothrowSwapProfile, ti::HasNothrowSwapArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::maybe,
+            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
+
+    // Core hashable profiles
+    ProfileAndExpectation<
+        ti::HasStdHashSpecializationProfile,
+        ti::HasStdHashSpecializationArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::maybe,
+            ti::greater_than_comparable::maybe, ti::swappable::maybe,
+            ti::hashable::yes>>>;
+
+using CommonProfilesToTest = ::testing::Types<
+    // NothrowMoveConstructible
+    ProfileAndExpectation<
+        ti::NothrowMoveConstructibleProfile,
+        ti::NothrowMoveConstructibleArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::nothrow,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::nothrow>>,
+
+    // CopyConstructible
+    ProfileAndExpectation<
+        ti::CopyConstructibleProfile, ti::CopyConstructibleArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::nothrow,
+            ti::copy_constructible::yes, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::nothrow>>,
+
+    // NothrowMovable
+    ProfileAndExpectation<
+        ti::NothrowMovableProfile, ti::NothrowMovableArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::nothrow,
+            ti::copy_constructible::maybe, ti::move_assignable::nothrow,
+            ti::copy_assignable::maybe, ti::destructible::nothrow,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::maybe,
+            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
+
+    // Value
+    ProfileAndExpectation<
+        ti::ValueProfile, ti::ValueArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::nothrow,
+            ti::copy_constructible::yes, ti::move_assignable::nothrow,
+            ti::copy_assignable::yes, ti::destructible::nothrow,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::maybe,
+            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
+
+    ////////////////////////////////////////////////////////////////////////////
+    //                  Common but also DefaultConstructible                  //
+    ////////////////////////////////////////////////////////////////////////////
+
+    // DefaultConstructibleNothrowMoveConstructible
+    ProfileAndExpectation<
+        ti::DefaultConstructibleNothrowMoveConstructibleProfile,
+        ti::DefaultConstructibleNothrowMoveConstructibleArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::yes, ti::move_constructible::nothrow,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::nothrow>>,
+
+    // DefaultConstructibleCopyConstructible
+    ProfileAndExpectation<
+        ti::DefaultConstructibleCopyConstructibleProfile,
+        ti::DefaultConstructibleCopyConstructibleArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::yes, ti::move_constructible::nothrow,
+            ti::copy_constructible::yes, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::nothrow>>,
+
+    // DefaultConstructibleNothrowMovable
+    ProfileAndExpectation<
+        ti::DefaultConstructibleNothrowMovableProfile,
+        ti::DefaultConstructibleNothrowMovableArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::yes, ti::move_constructible::nothrow,
+            ti::copy_constructible::maybe, ti::move_assignable::nothrow,
+            ti::copy_assignable::maybe, ti::destructible::nothrow,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::maybe,
+            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
+
+    // DefaultConstructibleValue
+    ProfileAndExpectation<
+        ti::DefaultConstructibleValueProfile,
+        ti::DefaultConstructibleValueArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::yes, ti::move_constructible::nothrow,
+            ti::copy_constructible::yes, ti::move_assignable::nothrow,
+            ti::copy_assignable::yes, ti::destructible::nothrow,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::maybe,
+            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>>;
+
+using ComparableHelpersProfilesToTest = ::testing::Types<
+    // Equatable
+    ProfileAndExpectation<
+        ti::EquatableProfile, ti::EquatableArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::yes, ti::inequality_comparable::yes>>,
+
+    // Comparable
+    ProfileAndExpectation<
+        ti::ComparableProfile, ti::ComparableArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::yes, ti::inequality_comparable::yes,
+            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+            ti::greater_equal_comparable::yes,
+            ti::greater_than_comparable::yes>>,
+
+    // NothrowEquatable
+    ProfileAndExpectation<
+        ti::NothrowEquatableProfile, ti::NothrowEquatableArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::nothrow,
+            ti::inequality_comparable::nothrow>>,
+
+    // NothrowComparable
+    ProfileAndExpectation<
+        ti::NothrowComparableProfile, ti::NothrowComparableArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::maybe,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::maybe,
+            ti::equality_comparable::nothrow,
+            ti::inequality_comparable::nothrow,
+            ti::less_than_comparable::nothrow,
+            ti::less_equal_comparable::nothrow,
+            ti::greater_equal_comparable::nothrow,
+            ti::greater_than_comparable::nothrow>>>;
+
+using CommonComparableProfilesToTest = ::testing::Types<
+    // ComparableNothrowMoveConstructible
+    ProfileAndExpectation<
+        ti::ComparableNothrowMoveConstructibleProfile,
+        ti::ComparableNothrowMoveConstructibleArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::nothrow,
+            ti::copy_constructible::maybe, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::nothrow,
+            ti::equality_comparable::yes, ti::inequality_comparable::yes,
+            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+            ti::greater_equal_comparable::yes,
+            ti::greater_than_comparable::yes>>,
+
+    // ComparableCopyConstructible
+    ProfileAndExpectation<
+        ti::ComparableCopyConstructibleProfile,
+        ti::ComparableCopyConstructibleArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::nothrow,
+            ti::copy_constructible::yes, ti::move_assignable::maybe,
+            ti::copy_assignable::maybe, ti::destructible::nothrow,
+            ti::equality_comparable::yes, ti::inequality_comparable::yes,
+            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+            ti::greater_equal_comparable::yes,
+            ti::greater_than_comparable::yes>>,
+
+    // ComparableNothrowMovable
+    ProfileAndExpectation<
+        ti::ComparableNothrowMovableProfile,
+        ti::ComparableNothrowMovableArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::nothrow,
+            ti::copy_constructible::maybe, ti::move_assignable::nothrow,
+            ti::copy_assignable::maybe, ti::destructible::nothrow,
+            ti::equality_comparable::yes, ti::inequality_comparable::yes,
+            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+            ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes,
+            ti::swappable::nothrow>>,
+
+    // ComparableValue
+    ProfileAndExpectation<
+        ti::ComparableValueProfile, ti::ComparableValueArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::maybe, ti::move_constructible::nothrow,
+            ti::copy_constructible::yes, ti::move_assignable::nothrow,
+            ti::copy_assignable::yes, ti::destructible::nothrow,
+            ti::equality_comparable::yes, ti::inequality_comparable::yes,
+            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+            ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes,
+            ti::swappable::nothrow>>>;
+
+using TrivialProfilesToTest = ::testing::Types<
+    ProfileAndExpectation<
+        ti::TrivialSpecialMemberFunctionsProfile,
+        ti::TrivialSpecialMemberFunctionsArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::trivial, ti::move_constructible::trivial,
+            ti::copy_constructible::trivial, ti::move_assignable::trivial,
+            ti::copy_assignable::trivial, ti::destructible::trivial,
+            ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+            ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+            ti::greater_equal_comparable::maybe,
+            ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
+
+    ProfileAndExpectation<
+        ti::TriviallyCompleteProfile, ti::TriviallyCompleteArchetype,
+        ti::ConformanceProfile<
+            ti::default_constructible::trivial, ti::move_constructible::trivial,
+            ti::copy_constructible::trivial, ti::move_assignable::trivial,
+            ti::copy_assignable::trivial, ti::destructible::trivial,
+            ti::equality_comparable::yes, ti::inequality_comparable::yes,
+            ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+            ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes,
+            ti::swappable::nothrow, ti::hashable::yes>>>;
+
+INSTANTIATE_TYPED_TEST_SUITE_P(Core, ProfileTest, CoreProfilesToTest);
+INSTANTIATE_TYPED_TEST_SUITE_P(Common, ProfileTest, CommonProfilesToTest);
+INSTANTIATE_TYPED_TEST_SUITE_P(ComparableHelpers, ProfileTest,
+                               ComparableHelpersProfilesToTest);
+INSTANTIATE_TYPED_TEST_SUITE_P(CommonComparable, ProfileTest,
+                               CommonComparableProfilesToTest);
+INSTANTIATE_TYPED_TEST_SUITE_P(Trivial, ProfileTest, TrivialProfilesToTest);
+
+TEST(ConformanceTestingTest, Basic) {
+  using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile,
+                                      ti::NothrowComparableProfile>;
+
+  using lim = std::numeric_limits<float>;
+
+  ABSL_INTERNAL_ASSERT_CONFORMANCE_OF(float)
+      .INITIALIZER(-lim::infinity())
+      .INITIALIZER(lim::lowest())
+      .INITIALIZER(-1.f)
+      .INITIALIZER(-lim::min())
+      .EQUIVALENCE_CLASS(INITIALIZER(-0.f), INITIALIZER(0.f))
+      .INITIALIZER(lim::min())
+      .INITIALIZER(1.f)
+      .INITIALIZER(lim::max())
+      .INITIALIZER(lim::infinity())
+      .WITH_STRICT_PROFILE(absl::types_internal::RegularityDomain, profile);
+}
+
+struct BadMoveConstruct {
+  BadMoveConstruct() = default;
+  BadMoveConstruct(BadMoveConstruct&& other) noexcept
+      : value(other.value + 1) {}
+  BadMoveConstruct& operator=(BadMoveConstruct&& other) noexcept = default;
+  int value = 0;
+
+  friend bool operator==(BadMoveConstruct const& lhs,
+                         BadMoveConstruct const& rhs) {
+    return lhs.value == rhs.value;
+  }
+  friend bool operator!=(BadMoveConstruct const& lhs,
+                         BadMoveConstruct const& rhs) {
+    return lhs.value != rhs.value;
+  }
+};
+
+struct BadMoveAssign {
+  BadMoveAssign() = default;
+  BadMoveAssign(BadMoveAssign&& other) noexcept = default;
+  BadMoveAssign& operator=(BadMoveAssign&& other) noexcept {
+    int new_value = other.value + 1;
+    value = new_value;
+    return *this;
+  }
+  int value = 0;
+
+  friend bool operator==(BadMoveAssign const& lhs, BadMoveAssign const& rhs) {
+    return lhs.value == rhs.value;
+  }
+  friend bool operator!=(BadMoveAssign const& lhs, BadMoveAssign const& rhs) {
+    return lhs.value != rhs.value;
+  }
+};
+
+enum class WhichCompIsBad { eq, ne, lt, le, ge, gt };
+
+template <WhichCompIsBad Which>
+struct BadCompare {
+  int value;
+
+  friend bool operator==(BadCompare const& lhs, BadCompare const& rhs) {
+    return Which == WhichCompIsBad::eq ? lhs.value != rhs.value
+                                       : lhs.value == rhs.value;
+  }
+
+  friend bool operator!=(BadCompare const& lhs, BadCompare const& rhs) {
+    return Which == WhichCompIsBad::ne ? lhs.value == rhs.value
+                                       : lhs.value != rhs.value;
+  }
+
+  friend bool operator<(BadCompare const& lhs, BadCompare const& rhs) {
+    return Which == WhichCompIsBad::lt ? lhs.value >= rhs.value
+                                       : lhs.value < rhs.value;
+  }
+
+  friend bool operator<=(BadCompare const& lhs, BadCompare const& rhs) {
+    return Which == WhichCompIsBad::le ? lhs.value > rhs.value
+                                       : lhs.value <= rhs.value;
+  }
+
+  friend bool operator>=(BadCompare const& lhs, BadCompare const& rhs) {
+    return Which == WhichCompIsBad::ge ? lhs.value < rhs.value
+                                       : lhs.value >= rhs.value;
+  }
+
+  friend bool operator>(BadCompare const& lhs, BadCompare const& rhs) {
+    return Which == WhichCompIsBad::gt ? lhs.value <= rhs.value
+                                       : lhs.value > rhs.value;
+  }
+};
+
+TEST(ConformanceTestingDeathTest, Failures) {
+  {
+    using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile,
+                                        ti::NothrowComparableProfile>;
+
+    // Note: The initializers are intentionally in the wrong order.
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(float)
+        .INITIALIZER(1.f)
+        .INITIALIZER(0.f)
+        .WITH_LOOSE_PROFILE(profile);
+  }
+
+  {
+    using profile =
+        ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>;
+
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveConstruct)
+        .DUE_TO("Move construction")
+        .INITIALIZER(BadMoveConstruct())
+        .WITH_LOOSE_PROFILE(profile);
+  }
+
+  {
+    using profile =
+        ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>;
+
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveAssign)
+        .DUE_TO("Move assignment")
+        .INITIALIZER(BadMoveAssign())
+        .WITH_LOOSE_PROFILE(profile);
+  }
+}
+
+TEST(ConformanceTestingDeathTest, CompFailures) {
+  using profile = ti::ComparableProfile;
+
+  {
+    using BadComp = BadCompare<WhichCompIsBad::eq>;
+
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+        .DUE_TO("Comparison")
+        .INITIALIZER(BadComp{0})
+        .INITIALIZER(BadComp{1})
+        .WITH_LOOSE_PROFILE(profile);
+  }
+
+  {
+    using BadComp = BadCompare<WhichCompIsBad::ne>;
+
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+        .DUE_TO("Comparison")
+        .INITIALIZER(BadComp{0})
+        .INITIALIZER(BadComp{1})
+        .WITH_LOOSE_PROFILE(profile);
+  }
+
+  {
+    using BadComp = BadCompare<WhichCompIsBad::lt>;
+
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+        .DUE_TO("Comparison")
+        .INITIALIZER(BadComp{0})
+        .INITIALIZER(BadComp{1})
+        .WITH_LOOSE_PROFILE(profile);
+  }
+
+  {
+    using BadComp = BadCompare<WhichCompIsBad::le>;
+
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+        .DUE_TO("Comparison")
+        .INITIALIZER(BadComp{0})
+        .INITIALIZER(BadComp{1})
+        .WITH_LOOSE_PROFILE(profile);
+  }
+
+  {
+    using BadComp = BadCompare<WhichCompIsBad::ge>;
+
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+        .DUE_TO("Comparison")
+        .INITIALIZER(BadComp{0})
+        .INITIALIZER(BadComp{1})
+        .WITH_LOOSE_PROFILE(profile);
+  }
+
+  {
+    using BadComp = BadCompare<WhichCompIsBad::gt>;
+
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+        .DUE_TO("Comparison")
+        .INITIALIZER(BadComp{0})
+        .INITIALIZER(BadComp{1})
+        .WITH_LOOSE_PROFILE(profile);
+  }
+}
+
+struct BadSelfMove {
+  BadSelfMove() = default;
+  BadSelfMove(BadSelfMove&&) = default;
+  BadSelfMove& operator=(BadSelfMove&& other) noexcept {
+    if (this == &other) {
+      broken_state = true;
+    }
+    return *this;
+  }
+
+  friend bool operator==(const BadSelfMove& lhs, const BadSelfMove& rhs) {
+    return !(lhs.broken_state || rhs.broken_state);
+  }
+
+  friend bool operator!=(const BadSelfMove& lhs, const BadSelfMove& rhs) {
+    return lhs.broken_state || rhs.broken_state;
+  }
+
+  bool broken_state = false;
+};
+
+TEST(ConformanceTestingDeathTest, SelfMoveFailure) {
+  using profile = ti::EquatableNothrowMovableProfile;
+
+  {
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfMove)
+        .DUE_TO("Move assignment")
+        .INITIALIZER(BadSelfMove())
+        .WITH_LOOSE_PROFILE(profile);
+  }
+}
+
+struct BadSelfCopy {
+  BadSelfCopy() = default;
+  BadSelfCopy(BadSelfCopy&&) = default;
+  BadSelfCopy(const BadSelfCopy&) = default;
+  BadSelfCopy& operator=(BadSelfCopy&&) = default;
+  BadSelfCopy& operator=(BadSelfCopy const& other) {
+    if (this == &other) {
+      broken_state = true;
+    }
+    return *this;
+  }
+
+  friend bool operator==(const BadSelfCopy& lhs, const BadSelfCopy& rhs) {
+    return !(lhs.broken_state || rhs.broken_state);
+  }
+
+  friend bool operator!=(const BadSelfCopy& lhs, const BadSelfCopy& rhs) {
+    return lhs.broken_state || rhs.broken_state;
+  }
+
+  bool broken_state = false;
+};
+
+TEST(ConformanceTestingDeathTest, SelfCopyFailure) {
+  using profile = ti::EquatableValueProfile;
+
+  {
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfCopy)
+        .DUE_TO("Copy assignment")
+        .INITIALIZER(BadSelfCopy())
+        .WITH_LOOSE_PROFILE(profile);
+  }
+}
+
+struct BadSelfSwap {
+  friend void swap(BadSelfSwap& lhs, BadSelfSwap& rhs) noexcept {
+    if (&lhs == &rhs) lhs.broken_state = true;
+  }
+
+  friend bool operator==(const BadSelfSwap& lhs, const BadSelfSwap& rhs) {
+    return !(lhs.broken_state || rhs.broken_state);
+  }
+
+  friend bool operator!=(const BadSelfSwap& lhs, const BadSelfSwap& rhs) {
+    return lhs.broken_state || rhs.broken_state;
+  }
+
+  bool broken_state = false;
+};
+
+TEST(ConformanceTestingDeathTest, SelfSwapFailure) {
+  using profile = ti::EquatableNothrowMovableProfile;
+
+  {
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfSwap)
+        .DUE_TO("Swap")
+        .INITIALIZER(BadSelfSwap())
+        .WITH_LOOSE_PROFILE(profile);
+  }
+}
+
+struct BadDefaultInitializedMoveAssign {
+  BadDefaultInitializedMoveAssign() : default_initialized(true) {}
+  explicit BadDefaultInitializedMoveAssign(int v) : value(v) {}
+  BadDefaultInitializedMoveAssign(
+      BadDefaultInitializedMoveAssign&& other) noexcept
+      : value(other.value) {}
+  BadDefaultInitializedMoveAssign& operator=(
+      BadDefaultInitializedMoveAssign&& other) noexcept {
+    value = other.value;
+    if (default_initialized) ++value;  // Bad move if lhs is default initialized
+    return *this;
+  }
+
+  friend bool operator==(const BadDefaultInitializedMoveAssign& lhs,
+                         const BadDefaultInitializedMoveAssign& rhs) {
+    return lhs.value == rhs.value;
+  }
+
+  friend bool operator!=(const BadDefaultInitializedMoveAssign& lhs,
+                         const BadDefaultInitializedMoveAssign& rhs) {
+    return lhs.value != rhs.value;
+  }
+
+  bool default_initialized = false;
+  int value = 0;
+};
+
+TEST(ConformanceTestingDeathTest, DefaultInitializedMoveAssignFailure) {
+  using profile =
+      ti::CombineProfiles<ti::DefaultConstructibleNothrowMovableProfile,
+                          ti::EquatableProfile>;
+
+  {
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedMoveAssign)
+        .DUE_TO("move assignment")
+        .INITIALIZER(BadDefaultInitializedMoveAssign(0))
+        .WITH_LOOSE_PROFILE(profile);
+  }
+}
+
+struct BadDefaultInitializedCopyAssign {
+  BadDefaultInitializedCopyAssign() : default_initialized(true) {}
+  explicit BadDefaultInitializedCopyAssign(int v) : value(v) {}
+  BadDefaultInitializedCopyAssign(
+      BadDefaultInitializedCopyAssign&& other) noexcept
+      : value(other.value) {}
+  BadDefaultInitializedCopyAssign(const BadDefaultInitializedCopyAssign& other)
+      : value(other.value) {}
+
+  BadDefaultInitializedCopyAssign& operator=(
+      BadDefaultInitializedCopyAssign&& other) noexcept {
+    value = other.value;
+    return *this;
+  }
+
+  BadDefaultInitializedCopyAssign& operator=(
+      const BadDefaultInitializedCopyAssign& other) {
+    value = other.value;
+    if (default_initialized) ++value;  // Bad move if lhs is default initialized
+    return *this;
+  }
+
+  friend bool operator==(const BadDefaultInitializedCopyAssign& lhs,
+                         const BadDefaultInitializedCopyAssign& rhs) {
+    return lhs.value == rhs.value;
+  }
+
+  friend bool operator!=(const BadDefaultInitializedCopyAssign& lhs,
+                         const BadDefaultInitializedCopyAssign& rhs) {
+    return lhs.value != rhs.value;
+  }
+
+  bool default_initialized = false;
+  int value = 0;
+};
+
+TEST(ConformanceTestingDeathTest, DefaultInitializedAssignFailure) {
+  using profile = ti::CombineProfiles<ti::DefaultConstructibleValueProfile,
+                                      ti::EquatableProfile>;
+
+  {
+    ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedCopyAssign)
+        .DUE_TO("copy assignment")
+        .INITIALIZER(BadDefaultInitializedCopyAssign(0))
+        .WITH_LOOSE_PROFILE(profile);
+  }
+}
+
+}  // namespace
diff --git a/absl/types/internal/optional.h b/absl/types/internal/optional.h
index 8acbda2..92932b6 100644
--- a/absl/types/internal/optional.h
+++ b/absl/types/internal/optional.h
@@ -54,6 +54,7 @@
 #endif
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // Forward declaration
 template <typename T>
@@ -84,8 +85,8 @@
   bool engaged_;
   // Data storage
   union {
-    dummy_type dummy_;
     T data_;
+    dummy_type dummy_;
   };
 
   void destruct() noexcept {
@@ -119,8 +120,8 @@
   bool engaged_;
   // Data storage
   union {
-    dummy_type dummy_;
     T data_;
+    dummy_type dummy_;
   };
   void destruct() noexcept { engaged_ = false; }
 
@@ -387,6 +388,7 @@
 };
 
 }  // namespace optional_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
diff --git a/absl/types/internal/parentheses.h b/absl/types/internal/parentheses.h
new file mode 100644
index 0000000..5aebee8
--- /dev/null
+++ b/absl/types/internal/parentheses.h
@@ -0,0 +1,34 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// parentheses.h
+// -----------------------------------------------------------------------------
+//
+// This file contains macros that expand to a left parenthesis and a right
+// parenthesis. These are in their own file and are generated from macros
+// because otherwise clang-format gets confused and clang-format off directives
+// do not help.
+//
+// The parentheses macros are used when wanting to require a rescan before
+// expansion of parenthesized text appearing after a function-style macro name.
+
+#ifndef ABSL_TYPES_INTERNAL_PARENTHESES_H_
+#define ABSL_TYPES_INTERNAL_PARENTHESES_H_
+
+#define ABSL_INTERNAL_LPAREN (
+
+#define ABSL_INTERNAL_RPAREN )
+
+#endif  // ABSL_TYPES_INTERNAL_PARENTHESES_H_
diff --git a/absl/types/internal/span.h b/absl/types/internal/span.h
index d203aad..112612f 100644
--- a/absl/types/internal/span.h
+++ b/absl/types/internal/span.h
@@ -26,6 +26,7 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace span_internal {
 // A constexpr min function
@@ -121,6 +122,7 @@
 using EnableIfConvertibleTo =
     typename std::enable_if<IsConvertible<From, To>::value>::type;
 }  // namespace span_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TYPES_INTERNAL_SPAN_H_
diff --git a/absl/types/internal/transform_args.h b/absl/types/internal/transform_args.h
new file mode 100644
index 0000000..4a0ab42
--- /dev/null
+++ b/absl/types/internal/transform_args.h
@@ -0,0 +1,246 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// transform_args.h
+// -----------------------------------------------------------------------------
+//
+// This file contains a higher-order macro that "transforms" each element of a
+// a variadic argument by a provided secondary macro.
+
+#ifndef ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_
+#define ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_
+
+//
+// ABSL_INTERNAL_CAT(a, b)
+//
+// This macro takes two arguments and concatenates them together via ## after
+// expansion.
+//
+// Example:
+//
+//   ABSL_INTERNAL_CAT(foo_, bar)
+//
+// Results in:
+//
+//   foo_bar
+#define ABSL_INTERNAL_CAT(a, b) ABSL_INTERNAL_CAT_IMPL(a, b)
+#define ABSL_INTERNAL_CAT_IMPL(a, b) a##b
+
+//
+// ABSL_INTERNAL_TRANSFORM_ARGS(m, ...)
+//
+// This macro takes another macro as an argument followed by a trailing series
+// of additional parameters (up to 32 additional arguments). It invokes the
+// passed-in macro once for each of the additional arguments, with the
+// expansions separated by commas.
+//
+// Example:
+//
+//   ABSL_INTERNAL_TRANSFORM_ARGS(MY_MACRO, a, b, c)
+//
+// Results in:
+//
+//   MY_MACRO(a), MY_MACRO(b), MY_MACRO(c)
+//
+// TODO(calabrese) Handle no arguments as a special case.
+#define ABSL_INTERNAL_TRANSFORM_ARGS(m, ...)             \
+  ABSL_INTERNAL_CAT(ABSL_INTERNAL_TRANSFORM_ARGS,        \
+                    ABSL_INTERNAL_NUM_ARGS(__VA_ARGS__)) \
+  (m, __VA_ARGS__)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS1(m, a0) m(a0)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS2(m, a0, a1) m(a0), m(a1)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS3(m, a0, a1, a2) m(a0), m(a1), m(a2)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS4(m, a0, a1, a2, a3) \
+  m(a0), m(a1), m(a2), m(a3)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS5(m, a0, a1, a2, a3, a4) \
+  m(a0), m(a1), m(a2), m(a3), m(a4)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS6(m, a0, a1, a2, a3, a4, a5) \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS7(m, a0, a1, a2, a3, a4, a5, a6) \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS8(m, a0, a1, a2, a3, a4, a5, a6, a7) \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS9(m, a0, a1, a2, a3, a4, a5, a6, a7, a8) \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS10(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9)                                    \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS11(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10)                               \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), m(a10)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS12(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11)                          \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS13(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12)                     \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS14(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12, a13)                \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS15(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12, a13, a14)           \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS16(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12, a13, a14, a15)      \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS17(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12, a13, a14, a15, a16) \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS18(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12, a13, a14, a15, a16, \
+                                       a17)                                   \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS19(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12, a13, a14, a15, a16, \
+                                       a17, a18)                              \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS20(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12, a13, a14, a15, a16, \
+                                       a17, a18, a19)                         \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+      m(a19)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS21(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12, a13, a14, a15, a16, \
+                                       a17, a18, a19, a20)                    \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+      m(a19), m(a20)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS22(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12, a13, a14, a15, a16, \
+                                       a17, a18, a19, a20, a21)               \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+      m(a19), m(a20), m(a21)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS23(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12, a13, a14, a15, a16, \
+                                       a17, a18, a19, a20, a21, a22)          \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+      m(a19), m(a20), m(a21), m(a22)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS24(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+                                       a9, a10, a11, a12, a13, a14, a15, a16, \
+                                       a17, a18, a19, a20, a21, a22, a23)     \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+      m(a19), m(a20), m(a21), m(a22), m(a23)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS25(m, a0, a1, a2, a3, a4, a5, a6, a7, a8,  \
+                                       a9, a10, a11, a12, a13, a14, a15, a16,  \
+                                       a17, a18, a19, a20, a21, a22, a23, a24) \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),        \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18),  \
+      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS26(                                       \
+    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,  \
+    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25)                         \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS27(                                       \
+    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,  \
+    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26)                    \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS28(                                       \
+    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,  \
+    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27)               \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS29(                                       \
+    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,  \
+    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28)          \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \
+      m(a28)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS30(                                       \
+    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,  \
+    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29)     \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),       \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \
+      m(a28), m(a29)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS31(                                        \
+    m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15,   \
+    a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30) \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),        \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18),  \
+      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27),  \
+      m(a28), m(a29), m(a30)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS32(m, a0, a1, a2, a3, a4, a5, a6, a7, a8,  \
+                                       a9, a10, a11, a12, a13, a14, a15, a16,  \
+                                       a17, a18, a19, a20, a21, a22, a23, a24, \
+                                       a25, a26, a27, a28, a29, a30, a31)      \
+  m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9),        \
+      m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18),  \
+      m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27),  \
+      m(a28), m(a29), m(a30), m(a31)
+
+#define ABSL_INTERNAL_NUM_ARGS_IMPL(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9,    \
+                                    a10, a11, a12, a13, a14, a15, a16, a17,    \
+                                    a18, a19, a20, a21, a22, a23, a24, a25,    \
+                                    a26, a27, a28, a29, a30, a31, result, ...) \
+  result
+
+#define ABSL_INTERNAL_FORCE_EXPANSION(...) __VA_ARGS__
+
+#define ABSL_INTERNAL_NUM_ARGS(...)                                            \
+  ABSL_INTERNAL_FORCE_EXPANSION(ABSL_INTERNAL_NUM_ARGS_IMPL(                   \
+      __VA_ARGS__, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, \
+      17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, ))
+
+#endif  // ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_
diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h
index 19de2e1..772008c 100644
--- a/absl/types/internal/variant.h
+++ b/absl/types/internal/variant.h
@@ -37,14 +37,15 @@
 #include "absl/types/bad_variant_access.h"
 #include "absl/utility/utility.h"
 
-#if !defined(ABSL_HAVE_STD_VARIANT)
+#if !defined(ABSL_USES_STD_VARIANT)
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 template <class... Types>
 class variant;
 
-ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1);
+ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, static_cast<size_t>(-1));
 
 template <class T>
 struct variant_size;
@@ -291,7 +292,7 @@
 template <class Op, std::size_t I>
 struct ReachableSwitchCase {
   static VisitIndicesResultT<Op, std::size_t> Run(Op&& op) {
-    return absl::base_internal::Invoke(absl::forward<Op>(op), SizeT<I>());
+    return absl::base_internal::invoke(absl::forward<Op>(op), SizeT<I>());
   }
 };
 
@@ -423,7 +424,7 @@
         return PickCase<Op, 32, EndIndex>::Run(absl::forward<Op>(op));
       default:
         ABSL_ASSERT(i == variant_npos);
-        return absl::base_internal::Invoke(absl::forward<Op>(op), NPos());
+        return absl::base_internal::invoke(absl::forward<Op>(op), NPos());
     }
   }
 };
@@ -487,7 +488,7 @@
     template <std::size_t I>
     VisitIndicesResultT<Op, decltype(EndIndices)...> operator()(
         SizeT<I> /*index*/) && {
-      return base_internal::Invoke(
+      return base_internal::invoke(
           absl::forward<Op>(op),
           SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value -
                 std::size_t{1}>()...);
@@ -929,7 +930,7 @@
                      absl::result_of_t<Op(VariantAccessResult<
                                           Is, QualifiedVariants>...)>>::value,
         "All visitation overloads must have the same return type.");
-    return absl::base_internal::Invoke(
+    return absl::base_internal::invoke(
         absl::forward<Op>(op),
         VariantCoreAccess::Access<Is>(
             absl::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...);
@@ -1638,7 +1639,8 @@
 };
 
 }  // namespace variant_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // !defined(ABSL_HAVE_STD_VARIANT)
+#endif  // !defined(ABSL_USES_STD_VARIANT)
 #endif  // ABSL_TYPES_variant_internal_H_
diff --git a/absl/types/optional.h b/absl/types/optional.h
index ed8faf9..61540cf 100644
--- a/absl/types/optional.h
+++ b/absl/types/optional.h
@@ -38,19 +38,21 @@
 #include "absl/base/config.h"   // TODO(calabrese) IWYU removal?
 #include "absl/utility/utility.h"
 
-#ifdef ABSL_HAVE_STD_OPTIONAL
+#ifdef ABSL_USES_STD_OPTIONAL
 
 #include <optional>  // IWYU pragma: export
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 using std::bad_optional_access;
 using std::optional;
 using std::make_optional;
 using std::nullopt_t;
 using std::nullopt;
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#else  // ABSL_HAVE_STD_OPTIONAL
+#else  // ABSL_USES_STD_OPTIONAL
 
 #include <cassert>
 #include <functional>
@@ -65,6 +67,7 @@
 #include "absl/types/internal/optional.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // nullopt_t
 //
@@ -133,10 +136,10 @@
   constexpr optional(nullopt_t) noexcept {}  // NOLINT(runtime/explicit)
 
   // Copy constructor, standard semantics
-  optional(const optional& src) = default;
+  optional(const optional&) = default;
 
   // Move constructor, standard semantics
-  optional(optional&& src) = default;
+  optional(optional&&) = default;
 
   // Constructs a non-empty `optional` direct-initialized value of type `T` from
   // the arguments `std::forward<Args>(args)...`  within the `optional`.
@@ -409,11 +412,11 @@
   //
   // If you need myOpt->foo in constexpr, use (*myOpt).foo instead.
   const T* operator->() const {
-    assert(this->engaged_);
+    ABSL_HARDENING_ASSERT(this->engaged_);
     return std::addressof(this->data_);
   }
   T* operator->() {
-    assert(this->engaged_);
+    ABSL_HARDENING_ASSERT(this->engaged_);
     return std::addressof(this->data_);
   }
 
@@ -422,17 +425,17 @@
   // Accesses the underlying `T` value of an `optional`. If the `optional` is
   // empty, behavior is undefined.
   constexpr const T& operator*() const& {
-    return ABSL_ASSERT(this->engaged_), reference();
+    return ABSL_HARDENING_ASSERT(this->engaged_), reference();
   }
   T& operator*() & {
-    assert(this->engaged_);
+    ABSL_HARDENING_ASSERT(this->engaged_);
     return reference();
   }
   constexpr const T&& operator*() const && {
-    return absl::move(reference());
+    return ABSL_HARDENING_ASSERT(this->engaged_), absl::move(reference());
   }
   T&& operator*() && {
-    assert(this->engaged_);
+    ABSL_HARDENING_ASSERT(this->engaged_);
     return std::move(reference());
   }
 
@@ -441,7 +444,7 @@
   // Returns false if and only if the `optional` is empty.
   //
   //   if (opt) {
-  //     // do something with opt.value();
+  //     // do something with *opt or opt->;
   //   } else {
   //     // opt is empty.
   //   }
@@ -754,6 +757,7 @@
   return static_cast<bool>(x) ? static_cast<bool>(v >= *x) : true;
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 namespace std {
@@ -767,6 +771,6 @@
 
 #undef ABSL_MSVC_CONSTEXPR_BUG_IN_UNION_LIKE_CLASS
 
-#endif  // ABSL_HAVE_STD_OPTIONAL
+#endif  // ABSL_USES_STD_OPTIONAL
 
 #endif  // ABSL_TYPES_OPTIONAL_H_
diff --git a/absl/types/optional_exception_safety_test.cc b/absl/types/optional_exception_safety_test.cc
index f99e35c..8e5fe85 100644
--- a/absl/types/optional_exception_safety_test.cc
+++ b/absl/types/optional_exception_safety_test.cc
@@ -18,12 +18,13 @@
 
 // This test is a no-op when absl::optional is an alias for std::optional and
 // when exceptions are not enabled.
-#if !defined(ABSL_HAVE_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS)
+#if !defined(ABSL_USES_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS)
 
 #include "gtest/gtest.h"
 #include "absl/base/internal/exception_safety_testing.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 namespace {
 
@@ -285,6 +286,7 @@
 
 }  // namespace
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // #if !defined(ABSL_HAVE_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS)
+#endif  // #if !defined(ABSL_USES_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc
index e005aff..7ef142c 100644
--- a/absl/types/optional_test.cc
+++ b/absl/types/optional_test.cc
@@ -15,7 +15,7 @@
 #include "absl/types/optional.h"
 
 // This test is a no-op when absl::optional is an alias for std::optional.
-#if !defined(ABSL_HAVE_STD_OPTIONAL)
+#if !defined(ABSL_USES_STD_OPTIONAL)
 
 #include <string>
 #include <type_traits>
@@ -224,7 +224,7 @@
 
   EXPECT_FALSE(
       absl::is_trivially_copy_constructible<absl::optional<Copyable>>::value);
-#if defined(ABSL_HAVE_STD_OPTIONAL) && defined(__GLIBCXX__)
+#if defined(ABSL_USES_STD_OPTIONAL) && defined(__GLIBCXX__)
   // libstdc++ std::optional implementation (as of 7.2) has a bug: when T is
   // trivially copyable, optional<T> is not trivially copyable (due to one of
   // its base class is unconditionally nontrivial).
@@ -279,7 +279,7 @@
     // std::optional when T is volatile-qualified. So skipping this test.
     // Bug report:
     // https://connect.microsoft.com/VisualStudio/feedback/details/3142534
-#if defined(ABSL_HAVE_STD_OPTIONAL) && defined(_MSC_VER) && _MSC_VER >= 1911
+#if defined(ABSL_USES_STD_OPTIONAL) && defined(_MSC_VER) && _MSC_VER >= 1911
 #define ABSL_MSVC_OPTIONAL_VOLATILE_COPY_BUG 1
 #endif
 #ifndef ABSL_MSVC_OPTIONAL_VOLATILE_COPY_BUG
@@ -305,7 +305,7 @@
   EXPECT_FALSE(std::is_move_constructible<absl::optional<NonMovable>>::value);
   // test noexcept
   EXPECT_TRUE(std::is_nothrow_move_constructible<absl::optional<int>>::value);
-#ifndef ABSL_HAVE_STD_OPTIONAL
+#ifndef ABSL_USES_STD_OPTIONAL
   EXPECT_EQ(
       absl::default_allocator_is_nothrow::value,
       std::is_nothrow_move_constructible<absl::optional<MoveableThrow>>::value);
@@ -639,7 +639,7 @@
   EXPECT_FALSE(absl::is_trivially_copy_assignable<NonTrivial>::value);
 
   // std::optional doesn't support volatile nontrivial types.
-#ifndef ABSL_HAVE_STD_OPTIONAL
+#ifndef ABSL_USES_STD_OPTIONAL
   {
     StructorListener listener;
     Listenable::listener = &listener;
@@ -658,7 +658,7 @@
     EXPECT_EQ(1, listener.destruct);
     EXPECT_EQ(1, listener.volatile_copy_assign);
   }
-#endif  // ABSL_HAVE_STD_OPTIONAL
+#endif  // ABSL_USES_STD_OPTIONAL
 }
 
 TEST(optionalTest, MoveAssignment) {
@@ -682,7 +682,7 @@
     EXPECT_EQ(1, listener.move_assign);
   }
   // std::optional doesn't support volatile nontrivial types.
-#ifndef ABSL_HAVE_STD_OPTIONAL
+#ifndef ABSL_USES_STD_OPTIONAL
   {
     StructorListener listener;
     Listenable::listener = &listener;
@@ -702,7 +702,7 @@
     EXPECT_EQ(1, listener.destruct);
     EXPECT_EQ(1, listener.volatile_move_assign);
   }
-#endif  // ABSL_HAVE_STD_OPTIONAL
+#endif  // ABSL_USES_STD_OPTIONAL
   EXPECT_FALSE(absl::is_move_assignable<absl::optional<const int>>::value);
   EXPECT_TRUE(absl::is_move_assignable<absl::optional<Copyable>>::value);
   EXPECT_TRUE(absl::is_move_assignable<absl::optional<MoveableThrow>>::value);
@@ -944,7 +944,7 @@
 
 template <int v>
 struct DeletedOpAddr {
-  constexpr static const int value = v;
+  int value = v;
   constexpr DeletedOpAddr() = default;
   constexpr const DeletedOpAddr<v>* operator&() const = delete;  // NOLINT
   DeletedOpAddr<v>* operator&() = delete;                        // NOLINT
@@ -954,9 +954,9 @@
 // to document the fact that the current implementation of absl::optional<T>
 // expects such usecases to be malformed and not compile.
 TEST(optionalTest, OperatorAddr) {
-  constexpr const int v = -1;
+  constexpr int v = -1;
   {  // constexpr
-    constexpr const absl::optional<DeletedOpAddr<v>> opt(absl::in_place_t{});
+    constexpr absl::optional<DeletedOpAddr<v>> opt(absl::in_place_t{});
     static_assert(opt.has_value(), "");
     // static_assert(opt->value == v, "");
     static_assert((*opt).value == v, "");
@@ -1051,14 +1051,13 @@
 #ifdef ABSL_HAVE_EXCEPTIONS
   EXPECT_THROW((void)empty.value(), absl::bad_optional_access);
 #else
-  EXPECT_DEATH((void)empty.value(), "Bad optional access");
+  EXPECT_DEATH_IF_SUPPORTED((void)empty.value(), "Bad optional access");
 #endif
 
   // test constexpr value()
   constexpr absl::optional<int> o1(1);
   static_assert(1 == o1.value(), "");  // const &
-#if !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG) && \
-    !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
+#if !defined(_MSC_VER) && !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
   using COI = const absl::optional<int>;
   static_assert(2 == COI(2).value(), "");  // const &&
 #endif
@@ -1098,8 +1097,7 @@
 
   constexpr absl::optional<int> opt1(1);
   static_assert(*opt1 == 1, "");
-#if !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG) && \
-    !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
+#if !defined(_MSC_VER) && !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
   using COI = const absl::optional<int>;
   static_assert(*COI(2) == 2, "");
 #endif
@@ -1560,7 +1558,7 @@
   static_assert(
       std::is_nothrow_move_constructible<absl::optional<MoveMeNoThrow>>::value,
       "");
-#ifndef ABSL_HAVE_STD_OPTIONAL
+#ifndef ABSL_USES_STD_OPTIONAL
   static_assert(absl::default_allocator_is_nothrow::value ==
                     std::is_nothrow_move_constructible<
                         absl::optional<MoveMeThrow>>::value,
@@ -1658,4 +1656,4 @@
 
 }  // namespace
 
-#endif  // #if !defined(ABSL_HAVE_STD_OPTIONAL)
+#endif  // #if !defined(ABSL_USES_STD_OPTIONAL)
diff --git a/absl/types/span.h b/absl/types/span.h
index b007fc1..95fe792 100644
--- a/absl/types/span.h
+++ b/absl/types/span.h
@@ -17,32 +17,30 @@
 // span.h
 // -----------------------------------------------------------------------------
 //
-// This header file defines a `Span<T>` type for holding a view of an existing
-// array of data. The `Span` object, much like the `absl::string_view` object,
-// does not own such data itself. A span provides a lightweight way to pass
-// around view of such data.
+// This header file defines a `Span<T>` type for holding a reference to existing
+// array data. The `Span` object, much like the `absl::string_view` object,
+// does not own such data itself, and the data being referenced by the span must
+// outlive the span itself. Unlike `view` type references, a span can hold a
+// reference to mutable data (and can mutate it for underlying types of
+// non-const T.) A span provides a lightweight way to pass a reference to such
+// data.
 //
 // Additionally, this header file defines `MakeSpan()` and `MakeConstSpan()`
 // factory functions, for clearly creating spans of type `Span<T>` or read-only
 // `Span<const T>` when such types may be difficult to identify due to issues
 // with implicit conversion.
 //
-// The C++ standards committee currently has a proposal for a `std::span` type,
-// (http://wg21.link/p0122), which is not yet part of the standard (though may
-// become part of C++20). As of August 2017, the differences between
-// `absl::Span` and this proposal are:
-//    * `absl::Span` uses `size_t` for `size_type`
-//    * `absl::Span` has no `operator()`
-//    * `absl::Span` has no constructors for `std::unique_ptr` or
-//      `std::shared_ptr`
+// The C++20 draft standard includes a `std::span` type. As of June 2020, the
+// differences between `absl::Span` and `std::span` are:
+//    * `absl::Span` has `operator==` (which is likely a design bug,
+//       per https://abseil.io/blog/20180531-regular-types)
 //    * `absl::Span` has the factory functions `MakeSpan()` and
 //      `MakeConstSpan()`
-//    * `absl::Span` has `front()` and `back()` methods
 //    * bounds-checked access to `absl::Span` is accomplished with `at()`
 //    * `absl::Span` has compiler-provided move and copy constructors and
 //      assignment. This is due to them being specified as `constexpr`, but that
 //      implies const in C++11.
-//    * `absl::Span` has no `element_type` or `index_type` typedefs
+//    * `absl::Span` has no `element_type` typedef
 //    * A read-only `absl::Span<const T>` can be implicitly constructed from an
 //      initializer list.
 //    * `absl::Span` has no `bytes()`, `size_bytes()`, `as_bytes()`, or
@@ -71,14 +69,15 @@
 #include "absl/types/internal/span.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 //------------------------------------------------------------------------------
 // Span
 //------------------------------------------------------------------------------
 //
-// A `Span` is an "array view" type for holding a view of a contiguous data
-// array; the `Span` object does not and cannot own such data itself. A span
-// provides an easy way to provide overloads for anything operating on
+// A `Span` is an "array reference" type for holding a reference of contiguous
+// array data; the `Span` object does not and cannot own such data itself. A
+// span provides an easy way to provide overloads for anything operating on
 // contiguous sequences without needing to manage pointers and array lengths
 // manually.
 
@@ -96,7 +95,8 @@
 // constructors.
 //
 // A `Span<T>` is somewhat analogous to an `absl::string_view`, but for an array
-// of elements of type `T`. A user of `Span` must ensure that the data being
+// of elements of type `T`, and unlike an `absl::string_view`, a span can hold a
+// reference to mutable data. A user of `Span` must ensure that the data being
 // pointed to outlives the `Span` itself.
 //
 // You can construct a `Span<T>` in several ways:
@@ -126,7 +126,7 @@
 // Note that `Span` objects, in addition to requiring that the memory they
 // point to remains alive, must also ensure that such memory does not get
 // reallocated. Therefore, to avoid undefined behavior, containers with
-// associated span views should not invoke operations that may reallocate memory
+// associated spans should not invoke operations that may reallocate memory
 // (such as resizing) or invalidate iterators into the container.
 //
 // One common use for a `Span` is when passing arguments to a routine that can
@@ -275,7 +275,7 @@
   // Returns a reference to the i'th element of this span.
   constexpr reference operator[](size_type i) const noexcept {
     // MSVC 2015 accepts this as constexpr, but not ptr_[i]
-    return *(data() + i);
+    return ABSL_HARDENING_ASSERT(i < size()), *(data() + i);
   }
 
   // Span::at()
@@ -291,60 +291,74 @@
 
   // Span::front()
   //
-  // Returns a reference to the first element of this span.
+  // Returns a reference to the first element of this span. The span must not
+  // be empty.
   constexpr reference front() const noexcept {
-    return ABSL_ASSERT(size() > 0), *data();
+    return ABSL_HARDENING_ASSERT(size() > 0), *data();
   }
 
   // Span::back()
   //
-  // Returns a reference to the last element of this span.
+  // Returns a reference to the last element of this span. The span must not
+  // be empty.
   constexpr reference back() const noexcept {
-    return ABSL_ASSERT(size() > 0), *(data() + size() - 1);
+    return ABSL_HARDENING_ASSERT(size() > 0), *(data() + size() - 1);
   }
 
   // Span::begin()
   //
-  // Returns an iterator to the first element of this span.
+  // Returns an iterator pointing to the first element of this span, or `end()`
+  // if the span is empty.
   constexpr iterator begin() const noexcept { return data(); }
 
   // Span::cbegin()
   //
-  // Returns a const iterator to the first element of this span.
+  // Returns a const iterator pointing to the first element of this span, or
+  // `end()` if the span is empty.
   constexpr const_iterator cbegin() const noexcept { return begin(); }
 
   // Span::end()
   //
-  // Returns an iterator to the last element of this span.
+  // Returns an iterator pointing just beyond the last element at the
+  // end of this span. This iterator acts as a placeholder; attempting to
+  // access it results in undefined behavior.
   constexpr iterator end() const noexcept { return data() + size(); }
 
   // Span::cend()
   //
-  // Returns a const iterator to the last element of this span.
+  // Returns a const iterator pointing just beyond the last element at the
+  // end of this span. This iterator acts as a placeholder; attempting to
+  // access it results in undefined behavior.
   constexpr const_iterator cend() const noexcept { return end(); }
 
   // Span::rbegin()
   //
-  // Returns a reverse iterator starting at the last element of this span.
+  // Returns a reverse iterator pointing to the last element at the end of this
+  // span, or `rend()` if the span is empty.
   constexpr reverse_iterator rbegin() const noexcept {
     return reverse_iterator(end());
   }
 
   // Span::crbegin()
   //
-  // Returns a reverse const iterator starting at the last element of this span.
+  // Returns a const reverse iterator pointing to the last element at the end of
+  // this span, or `crend()` if the span is empty.
   constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
 
   // Span::rend()
   //
-  // Returns a reverse iterator starting at the first element of this span.
+  // Returns a reverse iterator pointing just before the first element
+  // at the beginning of this span. This pointer acts as a placeholder;
+  // attempting to access its element results in undefined behavior.
   constexpr reverse_iterator rend() const noexcept {
     return reverse_iterator(begin());
   }
 
   // Span::crend()
   //
-  // Returns a reverse iterator starting at the first element of this span.
+  // Returns a reverse const iterator pointing just before the first element
+  // at the beginning of this span. This pointer acts as a placeholder;
+  // attempting to access its element results in undefined behavior.
   constexpr const_reverse_iterator crend() const noexcept { return rend(); }
 
   // Span mutations
@@ -353,7 +367,7 @@
   //
   // Removes the first `n` elements from the span.
   void remove_prefix(size_type n) noexcept {
-    assert(size() >= n);
+    ABSL_HARDENING_ASSERT(size() >= n);
     ptr_ += n;
     len_ -= n;
   }
@@ -362,7 +376,7 @@
   //
   // Removes the last `n` elements from the span.
   void remove_suffix(size_type n) noexcept {
-    assert(size() >= n);
+    ABSL_HARDENING_ASSERT(size() >= n);
     len_ -= n;
   }
 
@@ -650,7 +664,7 @@
 
 template <int&... ExplicitArgumentBarrier, typename T>
 Span<T> MakeSpan(T* begin, T* end) noexcept {
-  return ABSL_ASSERT(begin <= end), Span<T>(begin, end - begin);
+  return ABSL_HARDENING_ASSERT(begin <= end), Span<T>(begin, end - begin);
 }
 
 template <int&... ExplicitArgumentBarrier, typename C>
@@ -695,7 +709,7 @@
 
 template <int&... ExplicitArgumentBarrier, typename T>
 Span<const T> MakeConstSpan(T* begin, T* end) noexcept {
-  return ABSL_ASSERT(begin <= end), Span<const T>(begin, end - begin);
+  return ABSL_HARDENING_ASSERT(begin <= end), Span<const T>(begin, end - begin);
 }
 
 template <int&... ExplicitArgumentBarrier, typename C>
@@ -707,5 +721,6 @@
 constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept {
   return Span<const T>(array, N);
 }
+ABSL_NAMESPACE_END
 }  // namespace absl
 #endif  // ABSL_TYPES_SPAN_H_
diff --git a/absl/types/span_test.cc b/absl/types/span_test.cc
index 22467a0..2584339 100644
--- a/absl/types/span_test.cc
+++ b/absl/types/span_test.cc
@@ -27,6 +27,7 @@
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/exception_testing.h"
+#include "absl/base/options.h"
 #include "absl/container/fixed_array.h"
 #include "absl/container/inlined_vector.h"
 #include "absl/hash/hash_testing.h"
@@ -232,6 +233,11 @@
 
   EXPECT_EQ(s.front(), s[0]);
   EXPECT_EQ(s.back(), s[9]);
+
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+  EXPECT_DEATH_IF_SUPPORTED(s[-1], "");
+  EXPECT_DEATH_IF_SUPPORTED(s[10], "");
+#endif
 }
 
 TEST(IntSpan, AtThrows) {
@@ -268,6 +274,13 @@
   EXPECT_EQ(s.size(), 0);
 
   EXPECT_EQ(v, MakeRamp(20, 1));
+
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+  absl::Span<int> prefix_death(v);
+  EXPECT_DEATH_IF_SUPPORTED(prefix_death.remove_prefix(21), "");
+  absl::Span<int> suffix_death(v);
+  EXPECT_DEATH_IF_SUPPORTED(suffix_death.remove_suffix(21), "");
+#endif
 }
 
 TEST(IntSpan, Subspan) {
diff --git a/absl/types/variant.h b/absl/types/variant.h
index ebd52d2..ac93464 100644
--- a/absl/types/variant.h
+++ b/absl/types/variant.h
@@ -24,7 +24,7 @@
 // should always hold a value of one of its alternative types (except in the
 // "valueless by exception state" -- see below). A default-constructed
 // `absl::variant` will hold the value of its first alternative type, provided
-// it is default-constructable.
+// it is default-constructible.
 //
 // In exceptional cases due to error, an `absl::variant` can hold no
 // value (known as a "valueless by exception" state), though this is not the
@@ -45,11 +45,12 @@
 #include "absl/base/config.h"
 #include "absl/utility/utility.h"
 
-#ifdef ABSL_HAVE_STD_VARIANT
+#ifdef ABSL_USES_STD_VARIANT
 
 #include <variant>  // IWYU pragma: export
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 using std::bad_variant_access;
 using std::get;
 using std::get_if;
@@ -62,9 +63,10 @@
 using std::variant_size;
 using std::variant_size_v;
 using std::visit;
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#else  // ABSL_HAVE_STD_VARIANT
+#else  // ABSL_USES_STD_VARIANT
 
 #include <functional>
 #include <new>
@@ -77,6 +79,7 @@
 #include "absl/types/internal/variant.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // -----------------------------------------------------------------------------
 // absl::variant
@@ -92,7 +95,7 @@
 //   // assign it to a std::string.
 //   absl::variant<int, std::string> v = std::string("abc");
 //
-//   // A default-contructed variant will hold a value-initialized value of
+//   // A default-constructed variant will hold a value-initialized value of
 //   // the first alternative type.
 //   auto a = absl::variant<int, std::string>();   // Holds an int of value '0'.
 //
@@ -601,7 +604,10 @@
 
   // emplace() Functions
 
-  // Constructs a value of the given alternative type T within the variant.
+  // Constructs a value of the given alternative type T within the variant. The
+  // existing value of the variant is destroyed first (provided that
+  // `absl::valueless_by_exception()` is false). Requires that T is unambiguous
+  // in the variant.
   //
   // Example:
   //
@@ -621,7 +627,9 @@
   }
 
   // Constructs a value of the given alternative type T within the variant using
-  // an initializer list.
+  // an initializer list. The existing value of the variant is destroyed first
+  // (provided that `absl::valueless_by_exception()` is false). Requires that T
+  // is unambiguous in the variant.
   //
   // Example:
   //
@@ -640,7 +648,7 @@
   }
 
   // Destroys the current value of the variant (provided that
-  // `absl::valueless_by_exception()` is false, and constructs a new value at
+  // `absl::valueless_by_exception()` is false) and constructs a new value at
   // the given index.
   //
   // Example:
@@ -659,7 +667,7 @@
   }
 
   // Destroys the current value of the variant (provided that
-  // `absl::valueless_by_exception()` is false, and constructs a new value at
+  // `absl::valueless_by_exception()` is false) and constructs a new value at
   // the given index using an initializer list and the provided arguments.
   //
   // Example:
@@ -795,6 +803,7 @@
                    a.index());
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 namespace std {
@@ -812,9 +821,10 @@
 
 }  // namespace std
 
-#endif  // ABSL_HAVE_STD_VARIANT
+#endif  // ABSL_USES_STD_VARIANT
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace variant_internal {
 
 // Helper visitor for converting a variant<Ts...>` into another type (mostly
@@ -850,6 +860,7 @@
                      std::forward<Variant>(variant));
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_TYPES_VARIANT_H_
diff --git a/absl/types/variant_benchmark.cc b/absl/types/variant_benchmark.cc
index a5f5216..350b175 100644
--- a/absl/types/variant_benchmark.cc
+++ b/absl/types/variant_benchmark.cc
@@ -28,6 +28,7 @@
 #include "absl/utility/utility.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 template <std::size_t I>
@@ -217,4 +218,5 @@
     ->DenseRange(0, integral_pow(4, 2) - 1);
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/types/variant_exception_safety_test.cc b/absl/types/variant_exception_safety_test.cc
index fd7e6c7..439c6e1 100644
--- a/absl/types/variant_exception_safety_test.cc
+++ b/absl/types/variant_exception_safety_test.cc
@@ -18,7 +18,7 @@
 
 // This test is a no-op when absl::variant is an alias for std::variant and when
 // exceptions are not enabled.
-#if !defined(ABSL_HAVE_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS)
+#if !defined(ABSL_USES_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS)
 
 #include <iostream>
 #include <memory>
@@ -34,6 +34,7 @@
 #if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 using ::testing::MakeExceptionSafetyTester;
@@ -237,7 +238,7 @@
   }
   // libstdc++ std::variant has bugs on copy assignment regarding exception
   // safety.
-#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
   // index() != j
   // if is_nothrow_copy_constructible_v<Tj> or
   // !is_nothrow_move_constructible<Tj> is true, equivalent to
@@ -268,7 +269,7 @@
                     .Test());
     EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
   }
-#endif  // !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#endif  // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
   {
     // is_nothrow_copy_constructible_v<Tj> == false &&
     // is_nothrow_move_constructible_v<Tj> == true
@@ -325,7 +326,7 @@
     // The fix is targeted for gcc-9.
     // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7
     // https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614
-#if !(defined(ABSL_HAVE_STD_VARIANT) && \
+#if !(defined(ABSL_USES_STD_VARIANT) && \
       defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
     // - otherwise (index() != j), equivalent to
     // emplace<j>(get<j>(std::move(rhs)))
@@ -342,7 +343,7 @@
                       auto copy = rhs;
                       *lhs = std::move(copy);
                     }));
-#endif  // !(defined(ABSL_HAVE_STD_VARIANT) &&
+#endif  // !(defined(ABSL_USES_STD_VARIANT) &&
         //   defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
   }
 }
@@ -445,7 +446,7 @@
   // and operator=(variant&&) invokes Tj's move ctor which doesn't throw.
   // libstdc++ std::variant has bugs on conversion assignment regarding
   // exception safety.
-#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
   {
     MoveNothrow rhs;
     EXPECT_TRUE(MakeExceptionSafetyTester()
@@ -453,7 +454,7 @@
                     .WithContracts(VariantInvariants, strong_guarantee)
                     .Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }));
   }
-#endif  // !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#endif  // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
 }
 
 TEST(VariantExceptionSafetyTest, Emplace) {
@@ -523,8 +524,9 @@
 }
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
 
-#endif  // #if !defined(ABSL_HAVE_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS)
+#endif  // #if !defined(ABSL_USES_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc
index b591274..cf23733 100644
--- a/absl/types/variant_test.cc
+++ b/absl/types/variant_test.cc
@@ -20,7 +20,7 @@
 #include "absl/types/variant.h"
 
 // This test is a no-op when absl::variant is an alias for std::variant.
-#if !defined(ABSL_HAVE_STD_VARIANT)
+#if !defined(ABSL_USES_STD_VARIANT)
 
 #include <algorithm>
 #include <cstddef>
@@ -50,7 +50,7 @@
 #else
 
 #define ABSL_VARIANT_TEST_EXPECT_FAIL(expr, exception_t, text) \
-  EXPECT_DEATH(expr, text)
+  EXPECT_DEATH_IF_SUPPORTED(expr, text)
 
 #endif  // ABSL_HAVE_EXCEPTIONS
 
@@ -70,6 +70,7 @@
 struct NonHashable {};
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace {
 
 using ::testing::DoubleEq;
@@ -678,7 +679,7 @@
   object.operator=(object);
   EXPECT_EQ(0, counter);
 
-  // A std::string long enough that it's likely to defeat any inline representation
+  // A string long enough that it's likely to defeat any inline representation
   // optimization.
   const std::string long_str(128, 'a');
 
@@ -842,7 +843,7 @@
   }
 
   // libstdc++ doesn't pass this test
-#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
   EXPECT_EQ(3, counter[0]);
   EXPECT_EQ(2, counter[1]);
   EXPECT_EQ(2, counter[2]);
@@ -1933,7 +1934,7 @@
 }
 
 // libstdc++ std::variant doesn't support the INVOKE semantics.
-#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
 TEST(VariantTest, VisitMemberFunction) {
   absl::variant<std::unique_ptr<Class>> p(absl::make_unique<Class>());
   absl::variant<std::unique_ptr<const Class>> cp(
@@ -1957,7 +1958,7 @@
 
   EXPECT_EQ(42, absl::visit(&Class::member, cp));
 }
-#endif  // !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#endif  // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
 
 /////////////////////////
 // [variant.monostate] //
@@ -2035,7 +2036,7 @@
   std::swap(a, b);
   EXPECT_THAT(a, VariantWith<SpecialSwap>(v2));
   EXPECT_THAT(b, VariantWith<SpecialSwap>(v1));
-#ifndef ABSL_HAVE_STD_VARIANT
+#ifndef ABSL_USES_STD_VARIANT
   EXPECT_FALSE(absl::get<SpecialSwap>(a).special_swap);
 #endif
 
@@ -2083,7 +2084,7 @@
 
 // MSVC std::hash<std::variant> does not use the index, thus produce the same
 // result on the same value as different alternative.
-#if !(defined(_MSC_VER) && defined(ABSL_HAVE_STD_VARIANT))
+#if !(defined(_MSC_VER) && defined(ABSL_USES_STD_VARIANT))
   {
     // same value as different alternative
     variant<int, int> v0(in_place_index<0>, 42);
@@ -2091,7 +2092,7 @@
     std::hash<variant<int, int>> hash;
     EXPECT_NE(hash(v0), hash(v1));
   }
-#endif  // !(defined(_MSC_VER) && defined(ABSL_HAVE_STD_VARIANT))
+#endif  // !(defined(_MSC_VER) && defined(ABSL_USES_STD_VARIANT))
 
   {
     std::hash<variant<int>> hash;
@@ -2118,7 +2119,7 @@
 ////////////////////////////////////////
 
 // Test that a set requiring a basic type conversion works correctly
-#if !defined(ABSL_HAVE_STD_VARIANT)
+#if !defined(ABSL_USES_STD_VARIANT)
 TEST(VariantTest, TestConvertingSet) {
   typedef variant<double> Variant;
   Variant v(1.0);
@@ -2128,7 +2129,7 @@
   ASSERT_TRUE(nullptr != absl::get_if<double>(&v));
   EXPECT_DOUBLE_EQ(2, absl::get<double>(v));
 }
-#endif  // ABSL_HAVE_STD_VARIANT
+#endif  // ABSL_USES_STD_VARIANT
 
 // Test that a vector of variants behaves reasonably.
 TEST(VariantTest, Container) {
@@ -2280,7 +2281,7 @@
 };
 
 TEST(VariantTest, TestRvalueConversion) {
-#if !defined(ABSL_HAVE_STD_VARIANT)
+#if !defined(ABSL_USES_STD_VARIANT)
   variant<double, std::string> var(
       ConvertVariantTo<variant<double, std::string>>(
           variant<std::string, int>(0)));
@@ -2310,10 +2311,11 @@
   ASSERT_TRUE(absl::holds_alternative<int32_t>(variant2));
   EXPECT_EQ(42, absl::get<int32_t>(variant2));
 
-  variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
+  variant2 =
+      ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
   ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2));
   EXPECT_EQ(42, absl::get<uint32_t>(variant2));
-#endif  // !ABSL_HAVE_STD_VARIANT
+#endif  // !ABSL_USES_STD_VARIANT
 
   variant<Convertible1, Convertible2> variant3(
       ConvertVariantTo<variant<Convertible1, Convertible2>>(
@@ -2326,7 +2328,7 @@
 }
 
 TEST(VariantTest, TestLvalueConversion) {
-#if !defined(ABSL_HAVE_STD_VARIANT)
+#if !defined(ABSL_USES_STD_VARIANT)
   variant<std::string, int> source1 = 0;
   variant<double, std::string> destination(
       ConvertVariantTo<variant<double, std::string>>(source1));
@@ -2428,7 +2430,7 @@
 }
 
 TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {
-#if !defined(ABSL_HAVE_STD_VARIANT)
+#if !defined(ABSL_USES_STD_VARIANT)
   variant<double, std::string> var(
       ConvertVariantTo<variant<double, std::string>>(
           variant<std::string, int>(3)));
@@ -2452,7 +2454,8 @@
       ConvertVariantTo<variant<int32_t, uint32_t>>(variant<int32_t>(42)));
   EXPECT_THAT(absl::get_if<int32_t>(&variant2), Pointee(42));
 
-  variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
+  variant2 =
+      ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
   EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42));
 #endif
 
@@ -2467,7 +2470,7 @@
 }
 
 TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {
-#if !defined(ABSL_HAVE_STD_VARIANT)
+#if !defined(ABSL_USES_STD_VARIANT)
   variant<std::string, int> source1 = 3;
   variant<double, std::string> destination(
       ConvertVariantTo<variant<double, std::string>>(source1));
@@ -2499,7 +2502,7 @@
   variant<uint32_t> source6(42);
   variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6);
   EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42));
-#endif  // !ABSL_HAVE_STD_VARIANT
+#endif  // !ABSL_USES_STD_VARIANT
 
   variant<Convertible2, Convertible1> source7((Convertible1()));
   variant<Convertible1, Convertible2> variant3(
@@ -2533,7 +2536,7 @@
 // standard and we know that libstdc++ variant doesn't have this feature.
 // For more details see the paper:
 // http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0602r0.html
-#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
 #define ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY 1
 #endif
 
@@ -2709,6 +2712,7 @@
 }
 
 }  // namespace
+ABSL_NAMESPACE_END
 }  // namespace absl
 
-#endif  // #if !defined(ABSL_HAVE_STD_VARIANT)
+#endif  // #if !defined(ABSL_USES_STD_VARIANT)
diff --git a/absl/utility/BUILD.bazel b/absl/utility/BUILD.bazel
index 6881f93..02b2c40 100644
--- a/absl/utility/BUILD.bazel
+++ b/absl/utility/BUILD.bazel
@@ -24,7 +24,7 @@
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "utility",
diff --git a/absl/utility/utility.h b/absl/utility/utility.h
index eef8fb4..bf92322 100644
--- a/absl/utility/utility.h
+++ b/absl/utility/utility.h
@@ -51,6 +51,7 @@
 #include "absl/meta/type_traits.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 
 // integer_sequence
 //
@@ -158,12 +159,12 @@
 
 // Tag types
 
-#ifdef ABSL_HAVE_STD_OPTIONAL
+#ifdef ABSL_USES_STD_OPTIONAL
 
 using std::in_place_t;
 using std::in_place;
 
-#else  // ABSL_HAVE_STD_OPTIONAL
+#else  // ABSL_USES_STD_OPTIONAL
 
 // in_place_t
 //
@@ -174,9 +175,9 @@
 
 ABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {});
 
-#endif  // ABSL_HAVE_STD_OPTIONAL
+#endif  // ABSL_USES_STD_OPTIONAL
 
-#if defined(ABSL_HAVE_STD_ANY) || defined(ABSL_HAVE_STD_VARIANT)
+#if defined(ABSL_USES_STD_ANY) || defined(ABSL_USES_STD_VARIANT)
 using std::in_place_type;
 using std::in_place_type_t;
 #else
@@ -191,9 +192,9 @@
 
 template <typename T>
 void in_place_type(utility_internal::InPlaceTypeTag<T>) {}
-#endif  // ABSL_HAVE_STD_ANY || ABSL_HAVE_STD_VARIANT
+#endif  // ABSL_USES_STD_ANY || ABSL_USES_STD_VARIANT
 
-#ifdef ABSL_HAVE_STD_VARIANT
+#ifdef ABSL_USES_STD_VARIANT
 using std::in_place_index;
 using std::in_place_index_t;
 #else
@@ -208,7 +209,7 @@
 
 template <size_t I>
 void in_place_index(utility_internal::InPlaceIndexTag<I>) {}
-#endif  // ABSL_HAVE_STD_VARIANT
+#endif  // ABSL_USES_STD_VARIANT
 
 // Constexpr move and forward
 
@@ -235,10 +236,10 @@
 // Helper method for expanding tuple into a called method.
 template <typename Functor, typename Tuple, std::size_t... Indexes>
 auto apply_helper(Functor&& functor, Tuple&& t, index_sequence<Indexes...>)
-    -> decltype(absl::base_internal::Invoke(
+    -> decltype(absl::base_internal::invoke(
         absl::forward<Functor>(functor),
         std::get<Indexes>(absl::forward<Tuple>(t))...)) {
-  return absl::base_internal::Invoke(
+  return absl::base_internal::invoke(
       absl::forward<Functor>(functor),
       std::get<Indexes>(absl::forward<Tuple>(t))...);
 }
@@ -343,6 +344,7 @@
           std::tuple_size<absl::decay_t<Tuple>>::value>{});
 }
 
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_UTILITY_UTILITY_H_
diff --git a/ci/absl_alternate_options.h b/ci/absl_alternate_options.h
new file mode 100644
index 0000000..29b020d
--- /dev/null
+++ b/ci/absl_alternate_options.h
@@ -0,0 +1,29 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Alternate options.h file, used in continuous integration testing to exercise
+// option settings not used by default.
+
+#ifndef ABSL_BASE_OPTIONS_H_
+#define ABSL_BASE_OPTIONS_H_
+
+#define ABSL_OPTION_USE_STD_ANY 0
+#define ABSL_OPTION_USE_STD_OPTIONAL 0
+#define ABSL_OPTION_USE_STD_STRING_VIEW 0
+#define ABSL_OPTION_USE_STD_VARIANT 0
+#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
+#define ABSL_OPTION_INLINE_NAMESPACE_NAME ns
+#define ABSL_OPTION_HARDENED 1
+
+#endif  // ABSL_BASE_OPTIONS_H_
diff --git a/ci/cmake_common.sh b/ci/cmake_common.sh
new file mode 100644
index 0000000..aec8a11
--- /dev/null
+++ b/ci/cmake_common.sh
@@ -0,0 +1,25 @@
+# Copyright 2020 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# The commit of GoogleTest to be used in the CMake tests in this directory.
+# Keep this in sync with the commit in the WORKSPACE file.
+readonly ABSL_GOOGLETEST_COMMIT="8567b09290fe402cf01923e2131c5635b8ed851b"
+
+# Avoid depending on GitHub by looking for a cached copy of the commit first.
+if [[ -r "${KOKORO_GFILE_DIR:-}/distdir/${ABSL_GOOGLETEST_COMMIT}.zip" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+  ABSL_GOOGLETEST_DOWNLOAD_URL="file:///distdir/${ABSL_GOOGLETEST_COMMIT}.zip"
+else
+  ABSL_GOOGLETEST_DOWNLOAD_URL="https://github.com/google/googletest/archive/${ABSL_GOOGLETEST_COMMIT}.zip"
+fi
diff --git a/ci/cmake_install_test.sh b/ci/cmake_install_test.sh
index 03eb043..5bf540c 100755
--- a/ci/cmake_install_test.sh
+++ b/ci/cmake_install_test.sh
@@ -16,18 +16,22 @@
 
 set -euox pipefail
 
-if [ -z ${ABSEIL_ROOT:-} ]; then
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
 fi
 
+source "${ABSEIL_ROOT}/ci/cmake_common.sh"
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}
+
 time docker run \
-    --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
+    --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
     --workdir=/abseil-cpp \
     --tmpfs=/buildfs:exec \
     --cap-add=SYS_PTRACE \
     --rm \
     -e CFLAGS="-Werror" \
     -e CXXFLAGS="-Werror" \
-    gcr.io/google.com/absl-177019/linux_gcc-latest:20190703 \
+    ${DOCKER_CONTAINER} \
     /bin/bash CMake/install_test_project/test.sh $@
-
diff --git a/ci/linux_clang-latest_libcxx_asan_bazel.sh b/ci/linux_clang-latest_libcxx_asan_bazel.sh
index cc8c695..ffbb832 100755
--- a/ci/linux_clang-latest_libcxx_asan_bazel.sh
+++ b/ci/linux_clang-latest_libcxx_asan_bazel.sh
@@ -20,28 +20,29 @@
 
 set -euox pipefail
 
-if [ -z ${ABSEIL_ROOT:-} ]; then
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
 fi
 
-if [ -z ${STD:-} ]; then
-  STD="c++11 c++14 c++17"
+if [[ -z ${STD:-} ]]; then
+  STD="c++11 c++14 c++17 c++20"
 fi
 
-if [ -z ${COMPILATION_MODE:-} ]; then
+if [[ -z ${COMPILATION_MODE:-} ]]; then
   COMPILATION_MODE="fastbuild opt"
 fi
 
-if [ -z ${EXCEPTIONS_MODE:-} ]; then
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
   EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
 fi
 
-readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813"
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
 
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
-if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then
-  DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
   # Bazel doesn't track changes to tools outside of the workspace
   # (e.g. /usr/bin/gcc), so by appending the docker container to the
   # remote_http_cache url, we make changes to the container part of
@@ -50,17 +51,24 @@
   BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
 for std in ${STD}; do
   for compilation_mode in ${COMPILATION_MODE}; do
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
-        --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
+        --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
         -e CC="/opt/llvm/clang/bin/clang" \
-        -e BAZEL_COMPILER="llvm" \
         -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \
         -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \
         -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx/include/c++/v1" \
@@ -69,13 +77,11 @@
         /usr/local/bin/bazel test ... \
           --compilation_mode="${compilation_mode}" \
           --copt="${exceptions_mode}" \
-          --copt="-DDYNAMIC_ANNOTATIONS_ENABLED=1" \
-          --copt="-DADDRESS_SANITIZER" \
-          --copt="-DUNDEFINED_BEHAVIOR_SANITIZER" \
           --copt="-fsanitize=address" \
           --copt="-fsanitize=float-divide-by-zero" \
           --copt="-fsanitize=nullability" \
           --copt="-fsanitize=undefined" \
+          --copt="-fno-sanitize-blacklist" \
           --copt=-Werror \
           --keep_going \
           --linkopt="-fsanitize=address" \
diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh
index 5849a84..f6a2221 100755
--- a/ci/linux_clang-latest_libcxx_bazel.sh
+++ b/ci/linux_clang-latest_libcxx_bazel.sh
@@ -20,28 +20,29 @@
 
 set -euox pipefail
 
-if [ -z ${ABSEIL_ROOT:-} ]; then
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
 fi
 
-if [ -z ${STD:-} ]; then
-  STD="c++11 c++14 c++17"
+if [[ -z ${STD:-} ]]; then
+  STD="c++11 c++14 c++17 c++20"
 fi
 
-if [ -z ${COMPILATION_MODE:-} ]; then
+if [[ -z ${COMPILATION_MODE:-} ]]; then
   COMPILATION_MODE="fastbuild opt"
 fi
 
-if [ -z ${EXCEPTIONS_MODE:-} ]; then
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
   EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
 fi
 
-readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813"
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
 
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
-if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then
-  DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
   # Bazel doesn't track changes to tools outside of the workspace
   # (e.g. /usr/bin/gcc), so by appending the docker container to the
   # remote_http_cache url, we make changes to the container part of
@@ -50,34 +51,47 @@
   BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
 for std in ${STD}; do
   for compilation_mode in ${COMPILATION_MODE}; do
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
-        --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
+        --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \
+        --tmpfs=/abseil-cpp \
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
         -e CC="/opt/llvm/clang/bin/clang" \
-        -e BAZEL_COMPILER="llvm" \
         -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \
         -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \
         -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx/include/c++/v1" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
-        /usr/local/bin/bazel test ... \
-          --compilation_mode="${compilation_mode}" \
-          --copt="${exceptions_mode}" \
-          --copt=-Werror \
-          --define="absl=1" \
-          --keep_going \
-          --show_timestamps \
-          --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \
-          --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
-          --test_output=errors \
-          --test_tag_filters=-benchmark \
-          ${BAZEL_EXTRA_ARGS:-}
+        /bin/sh -c "
+          cp -r /abseil-cpp-ro/* /abseil-cpp/
+          if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then
+            cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
+          fi
+          /usr/local/bin/bazel test ... \
+            --compilation_mode=\"${compilation_mode}\" \
+            --copt=\"${exceptions_mode}\" \
+            --copt=-Werror \
+            --define=\"absl=1\" \
+            --keep_going \
+            --show_timestamps \
+            --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \
+            --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \
+            --test_output=errors \
+            --test_tag_filters=-benchmark \
+            ${BAZEL_EXTRA_ARGS:-}"
     done
   done
 done
diff --git a/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/ci/linux_clang-latest_libcxx_tsan_bazel.sh
index 8721ada..e70e821 100755
--- a/ci/linux_clang-latest_libcxx_tsan_bazel.sh
+++ b/ci/linux_clang-latest_libcxx_tsan_bazel.sh
@@ -20,28 +20,29 @@
 
 set -euox pipefail
 
-if [ -z ${ABSEIL_ROOT:-} ]; then
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
 fi
 
-if [ -z ${STD:-} ]; then
-  STD="c++11 c++14 c++17"
+if [[ -z ${STD:-} ]]; then
+  STD="c++11 c++14 c++17 c++20"
 fi
 
-if [ -z ${COMPILATION_MODE:-} ]; then
+if [[ -z ${COMPILATION_MODE:-} ]]; then
   COMPILATION_MODE="fastbuild opt"
 fi
 
-if [ -z ${EXCEPTIONS_MODE:-} ]; then
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
   EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
 fi
 
-readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813"
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
 
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
-if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then
-  DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
   # Bazel doesn't track changes to tools outside of the workspace
   # (e.g. /usr/bin/gcc), so by appending the docker container to the
   # remote_http_cache url, we make changes to the container part of
@@ -50,17 +51,24 @@
   BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
 for std in ${STD}; do
   for compilation_mode in ${COMPILATION_MODE}; do
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
-        --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
+        --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
         -e CC="/opt/llvm/clang/bin/clang" \
-        -e BAZEL_COMPILER="llvm" \
         -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \
         -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx-tsan/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx-tsan/lib" \
         -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx-tsan/include/c++/v1" \
@@ -70,9 +78,8 @@
           --build_tag_filters="-notsan" \
           --compilation_mode="${compilation_mode}" \
           --copt="${exceptions_mode}" \
-          --copt="-DDYNAMIC_ANNOTATIONS_ENABLED=1" \
-          --copt="-DTHREAD_SANITIZER" \
           --copt="-fsanitize=thread" \
+          --copt="-fno-sanitize-blacklist" \
           --copt=-Werror \
           --keep_going \
           --linkopt="-fsanitize=thread" \
diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh
index 78ce0b3..0986ff4 100755
--- a/ci/linux_clang-latest_libstdcxx_bazel.sh
+++ b/ci/linux_clang-latest_libstdcxx_bazel.sh
@@ -20,28 +20,29 @@
 
 set -euox pipefail
 
-if [ -z ${ABSEIL_ROOT:-} ]; then
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
 fi
 
-if [ -z ${STD:-} ]; then
-  STD="c++11 c++14 c++17"
+if [[ -z ${STD:-} ]]; then
+  STD="c++11 c++14 c++17 c++20"
 fi
 
-if [ -z ${COMPILATION_MODE:-} ]; then
+if [[ -z ${COMPILATION_MODE:-} ]]; then
   COMPILATION_MODE="fastbuild opt"
 fi
 
-if [ -z ${EXCEPTIONS_MODE:-} ]; then
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
   EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
 fi
 
-readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20190813"
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
 
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
-if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then
-  DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
   # Bazel doesn't track changes to tools outside of the workspace
   # (e.g. /usr/bin/gcc), so by appending the docker container to the
   # remote_http_cache url, we make changes to the container part of
@@ -50,27 +51,35 @@
   BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
 for std in ${STD}; do
   for compilation_mode in ${COMPILATION_MODE}; do
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
-        --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
+        --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
         -e CC="/opt/llvm/clang/bin/clang" \
-        -e BAZEL_COMPILER="llvm" \
         -e BAZEL_CXXOPTS="-std=${std}" \
-        -e CPLUS_INCLUDE_PATH="/usr/include/c++/6" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
         /usr/local/bin/bazel test ... \
           --compilation_mode="${compilation_mode}" \
+          --copt="--gcc-toolchain=/usr/local" \
           --copt="${exceptions_mode}" \
           --copt=-Werror \
           --define="absl=1" \
           --keep_going \
+          --linkopt="--gcc-toolchain=/usr/local" \
           --show_timestamps \
           --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \
           --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
diff --git a/ci/linux_docker_containers.sh b/ci/linux_docker_containers.sh
new file mode 100644
index 0000000..1c29d9a
--- /dev/null
+++ b/ci/linux_docker_containers.sh
@@ -0,0 +1,21 @@
+# Copyright 2019 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# The file contains Docker container identifiers currently used by test scripts.
+# Test scripts should source this file to get the identifiers.
+
+readonly LINUX_ALPINE_CONTAINER="gcr.io/google.com/absl-177019/alpine:20201026"
+readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20201008"
+readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20201008"
+readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20201015"
diff --git a/ci/linux_gcc-4.9_libstdcxx_bazel.sh b/ci/linux_gcc-floor_libstdcxx_bazel.sh
similarity index 77%
rename from ci/linux_gcc-4.9_libstdcxx_bazel.sh
rename to ci/linux_gcc-floor_libstdcxx_bazel.sh
index c3b936b..224aef8 100755
--- a/ci/linux_gcc-4.9_libstdcxx_bazel.sh
+++ b/ci/linux_gcc-floor_libstdcxx_bazel.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 #
-# Copyright 2019 The Abseil Authors.
+# Copyright 2020 The Abseil Authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -20,27 +20,28 @@
 
 set -euox pipefail
 
-if [ -z ${ABSEIL_ROOT:-} ]; then
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
 fi
 
-if [ -z ${STD:-} ]; then
+if [[ -z ${STD:-} ]]; then
   STD="c++11 c++14"
 fi
 
-if [ -z ${COMPILATION_MODE:-} ]; then
+if [[ -z ${COMPILATION_MODE:-} ]]; then
   COMPILATION_MODE="fastbuild opt"
 fi
 
-if [ -z ${EXCEPTIONS_MODE:-} ]; then
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
   EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
 fi
 
-readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20190702"
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_GCC_FLOOR_CONTAINER}
 
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
-if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
   DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
   # Bazel doesn't track changes to tools outside of the workspace
   # (e.g. /usr/bin/gcc), so by appending the docker container to the
@@ -50,6 +51,14 @@
   BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+  DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
 for std in ${STD}; do
   for compilation_mode in ${COMPILATION_MODE}; do
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
@@ -59,7 +68,7 @@
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
-        -e CC="/usr/bin/gcc-4.9" \
+        -e CC="/usr/local/bin/gcc" \
         -e BAZEL_CXXOPTS="-std=${std}" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh
index 10f6be2..37d89d9 100755
--- a/ci/linux_gcc-latest_libstdcxx_bazel.sh
+++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh
@@ -20,28 +20,29 @@
 
 set -euox pipefail
 
-if [ -z ${ABSEIL_ROOT:-} ]; then
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
 fi
 
-if [ -z ${STD:-} ]; then
-  STD="c++11 c++14 c++17"
+if [[ -z ${STD:-} ]]; then
+  STD="c++11 c++14 c++17 c++20"
 fi
 
-if [ -z ${COMPILATION_MODE:-} ]; then
+if [[ -z ${COMPILATION_MODE:-} ]]; then
   COMPILATION_MODE="fastbuild opt"
 fi
 
-if [ -z ${EXCEPTIONS_MODE:-} ]; then
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
   EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
 fi
 
-readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20190703"
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}
 
 # USE_BAZEL_CACHE=1 only works on Kokoro.
 # Without access to the credentials this won't work.
-if [ ${USE_BAZEL_CACHE:-0} -ne 0 ]; then
-  DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
   # Bazel doesn't track changes to tools outside of the workspace
   # (e.g. /usr/bin/gcc), so by appending the docker container to the
   # remote_http_cache url, we make changes to the container part of
@@ -50,12 +51,21 @@
   BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
 fi
 
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+  DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+  BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
 for std in ${STD}; do
   for compilation_mode in ${COMPILATION_MODE}; do
     for exceptions_mode in ${EXCEPTIONS_MODE}; do
       echo "--------------------------------------------------------------------"
       time docker run \
-        --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
+        --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \
+        --tmpfs=/abseil-cpp \
         --workdir=/abseil-cpp \
         --cap-add=SYS_PTRACE \
         --rm \
@@ -63,18 +73,23 @@
         -e BAZEL_CXXOPTS="-std=${std}" \
         ${DOCKER_EXTRA_ARGS:-} \
         ${DOCKER_CONTAINER} \
-        /usr/local/bin/bazel test ... \
-          --compilation_mode="${compilation_mode}" \
-          --copt="${exceptions_mode}" \
-          --copt=-Werror \
-          --define="absl=1" \
-          --keep_going \
-          --show_timestamps \
-          --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \
-          --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
-          --test_output=errors \
-          --test_tag_filters=-benchmark \
-          ${BAZEL_EXTRA_ARGS:-}
+        /bin/sh -c "
+          cp -r /abseil-cpp-ro/* /abseil-cpp/
+          if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then
+            cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
+          fi
+          /usr/local/bin/bazel test ... \
+            --compilation_mode=\"${compilation_mode}\" \
+            --copt=\"${exceptions_mode}\" \
+            --copt=-Werror \
+            --define=\"absl=1\" \
+            --keep_going \
+            --show_timestamps \
+            --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \
+            --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \
+            --test_output=errors \
+            --test_tag_filters=-benchmark \
+            ${BAZEL_EXTRA_ARGS:-}"
     done
   done
 done
diff --git a/ci/linux_gcc-latest_libstdcxx_cmake.sh b/ci/linux_gcc-latest_libstdcxx_cmake.sh
index 3e831c1..ed9cfa3 100755
--- a/ci/linux_gcc-latest_libstdcxx_cmake.sh
+++ b/ci/linux_gcc-latest_libstdcxx_cmake.sh
@@ -14,48 +14,52 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# TODO(absl-team): This script isn't fully hermetic because
-# -DABSL_USE_GOOGLETEST_HEAD=ON means that this script isn't pinned to a fixed
-# version of GoogleTest. This means that an upstream change to GoogleTest could
-# break this test. Fix this by allowing this script to pin to a known-good
-# version of GoogleTest.
-
 set -euox pipefail
 
-if [ -z ${ABSEIL_ROOT:-} ]; then
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
 fi
 
-if [ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]; then
-  ABSL_CMAKE_CXX_STANDARDS="11 14 17"
+source "${ABSEIL_ROOT}/ci/cmake_common.sh"
+
+if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then
+  ABSL_CMAKE_CXX_STANDARDS="11 14 17 20"
 fi
 
-if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then
+if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
   ABSL_CMAKE_BUILD_TYPES="Debug Release"
 fi
 
+if [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then
+  ABSL_CMAKE_BUILD_SHARED="OFF ON"
+fi
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}
+
 for std in ${ABSL_CMAKE_CXX_STANDARDS}; do
   for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do
-    echo "--------------------------------------------------------------------"
-    echo "Testing with CMAKE_BUILD_TYPE=${compilation_mode} and -std=c++${std}"
-
-    time docker run \
-      --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
-      --workdir=/abseil-cpp \
-      --tmpfs=/buildfs:exec \
-      --cap-add=SYS_PTRACE \
-      --rm \
-      -e CFLAGS="-Werror" \
-      -e CXXFLAGS="-Werror" \
-      gcr.io/google.com/absl-177019/linux_gcc-latest:20190703 \
-      /bin/bash -c "
-        cd /buildfs && \
-        cmake /abseil-cpp \
-          -DABSL_USE_GOOGLETEST_HEAD=ON \
-          -DABSL_RUN_TESTS=ON \
-          -DCMAKE_BUILD_TYPE=${compilation_mode} \
-          -DCMAKE_CXX_STANDARD=${std} && \
-        make -j$(nproc) && \
-        ctest -j$(nproc) --output-on-failure"
+    for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do
+      time docker run \
+        --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
+        --tmpfs=/buildfs:exec \
+        --workdir=/buildfs \
+        --cap-add=SYS_PTRACE \
+        --rm \
+        -e CFLAGS="-Werror" \
+        -e CXXFLAGS="-Werror" \
+        ${DOCKER_EXTRA_ARGS:-} \
+        "${DOCKER_CONTAINER}" \
+        /bin/bash -c "
+          cmake /abseil-cpp \
+            -DABSL_GOOGLETEST_DOWNLOAD_URL=${ABSL_GOOGLETEST_DOWNLOAD_URL} \
+            -DABSL_RUN_TESTS=ON \
+            -DBUILD_SHARED_LIBS=${build_shared} \
+            -DCMAKE_BUILD_TYPE=${compilation_mode} \
+            -DCMAKE_CXX_STANDARD=${std} \
+            -DCMAKE_MODULE_LINKER_FLAGS=\"-Wl,--no-undefined\" && \
+          make -j$(nproc) && \
+          ctest -j$(nproc) --output-on-failure"
+    done
   done
 done
diff --git a/ci/linux_gcc_alpine_cmake.sh b/ci/linux_gcc_alpine_cmake.sh
new file mode 100755
index 0000000..31310ac
--- /dev/null
+++ b/ci/linux_gcc_alpine_cmake.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+#
+# Copyright 2019 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+  ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+source "${ABSEIL_ROOT}/ci/cmake_common.sh"
+
+if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then
+  ABSL_CMAKE_CXX_STANDARDS="11 14 17"
+fi
+
+if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
+  ABSL_CMAKE_BUILD_TYPES="Debug Release"
+fi
+
+if [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then
+  ABSL_CMAKE_BUILD_SHARED="OFF ON"
+fi
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_ALPINE_CONTAINER}
+
+for std in ${ABSL_CMAKE_CXX_STANDARDS}; do
+  for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do
+    for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do
+      time docker run \
+        --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
+        --tmpfs=/buildfs:exec \
+        --workdir=/buildfs \
+        --cap-add=SYS_PTRACE \
+        --rm \
+        -e CFLAGS="-Werror" \
+        -e CXXFLAGS="-Werror" \
+        ${DOCKER_EXTRA_ARGS:-} \
+        "${DOCKER_CONTAINER}" \
+        /bin/sh -c "
+          cmake /abseil-cpp \
+            -DABSL_GOOGLETEST_DOWNLOAD_URL=${ABSL_GOOGLETEST_DOWNLOAD_URL} \
+            -DABSL_RUN_TESTS=ON \
+            -DCMAKE_BUILD_TYPE=${compilation_mode} \
+            -DCMAKE_CXX_STANDARD=${std} \
+            -DCMAKE_MODULE_LINKER_FLAGS=\"-Wl,--no-undefined\" && \
+          make -j$(nproc) && \
+          ctest -j$(nproc) --output-on-failure"
+    done
+  done
+done
diff --git a/ci/macos_xcode_bazel.sh b/ci/macos_xcode_bazel.sh
index 3e13b15..738adf9 100755
--- a/ci/macos_xcode_bazel.sh
+++ b/ci/macos_xcode_bazel.sh
@@ -19,13 +19,13 @@
 
 set -euox pipefail
 
-if [ -z ${ABSEIL_ROOT:-} ]; then
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
 fi
 
 # If we are running on Kokoro, check for a versioned Bazel binary.
-KOKORO_GFILE_BAZEL_BIN="bazel-0.28.1-darwin-x86_64"
-if [ ${KOKORO_GFILE_DIR:-} ] && [ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]; then
+KOKORO_GFILE_BAZEL_BIN="bazel-2.0.0-darwin-x86_64"
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
   BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
   chmod +x ${BAZEL_BIN}
 else
@@ -41,6 +41,10 @@
 
 cd ${ABSEIL_ROOT}
 
+if [[ -n "${ALTERNATE_OPTIONS:-}" ]]; then
+  cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
+fi
+
 ${BAZEL_BIN} test ... \
   --copt=-Werror \
   --keep_going \
diff --git a/ci/macos_xcode_cmake.sh b/ci/macos_xcode_cmake.sh
index 75b0f2d..0847b3e 100755
--- a/ci/macos_xcode_cmake.sh
+++ b/ci/macos_xcode_cmake.sh
@@ -14,30 +14,43 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# This script is invoked on Kokoro to test Abseil on macOS.
-# It is not hermetic and may break when Kokoro is updated.
-
 set -euox pipefail
 
-if [ -z ${ABSEIL_ROOT:-} ]; then
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
   ABSEIL_ROOT="$(dirname ${0})/.."
 fi
 ABSEIL_ROOT=$(realpath ${ABSEIL_ROOT})
 
-if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then
+source "${ABSEIL_ROOT}/ci/cmake_common.sh"
+
+# The MacOS build doesn't run in a docker container, so we have to override ABSL_GOOGLETEST_DOWNLOAD_URL.
+if [[ -r "${KOKORO_GFILE_DIR}/distdir/${ABSL_GOOGLETEST_COMMIT}.zip" ]]; then
+  ABSL_GOOGLETEST_DOWNLOAD_URL="file://${KOKORO_GFILE_DIR}/distdir/${ABSL_GOOGLETEST_COMMIT}.zip"
+fi
+
+if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
   ABSL_CMAKE_BUILD_TYPES="Debug"
 fi
 
-for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do
-  BUILD_DIR=$(mktemp -d ${compilation_mode}.XXXXXXXX)
-  cd ${BUILD_DIR}
+if [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then
+  ABSL_CMAKE_BUILD_SHARED="OFF ON"
+fi
 
-  # TODO(absl-team): Enable -Werror once all warnings are fixed.
-  time cmake ${ABSEIL_ROOT} \
-    -GXcode \
-    -DCMAKE_BUILD_TYPE=${compilation_mode} \
-    -DABSL_USE_GOOGLETEST_HEAD=ON \
-    -DABSL_RUN_TESTS=ON
-  time cmake --build .
-  time ctest -C ${compilation_mode} --output-on-failure
+for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do
+  for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do
+    BUILD_DIR=$(mktemp -d ${compilation_mode}.XXXXXXXX)
+    cd ${BUILD_DIR}
+
+    # TODO(absl-team): Enable -Werror once all warnings are fixed.
+    time cmake ${ABSEIL_ROOT} \
+      -GXcode \
+      -DBUILD_SHARED_LIBS=${build_shared} \
+      -DCMAKE_BUILD_TYPE=${compilation_mode} \
+      -DCMAKE_CXX_STANDARD=11 \
+      -DCMAKE_MODULE_LINKER_FLAGS="-Wl,--no-undefined" \
+      -DABSL_GOOGLETEST_DOWNLOAD_URL="${ABSL_GOOGLETEST_DOWNLOAD_URL}" \
+      -DABSL_RUN_TESTS=ON
+    time cmake --build .
+    time ctest -C ${compilation_mode} --output-on-failure
+  done
 done
diff --git a/conanfile.py b/conanfile.py
old mode 100644
new mode 100755
index cd124aa..926ec5c
--- a/conanfile.py
+++ b/conanfile.py
@@ -30,7 +30,7 @@
             raise ConanInvalidConfiguration("Abseil does not support MSVC < 14")
 
     def build(self):
-        tools.replace_in_file("CMakeLists.txt", "project(absl)", "project(absl)\ninclude(conanbuildinfo.cmake)\nconan_basic_setup()")
+        tools.replace_in_file("CMakeLists.txt", "project(absl CXX)", "project(absl CXX)\ninclude(conanbuildinfo.cmake)\nconan_basic_setup()")
         cmake = CMake(self)
         cmake.definitions["BUILD_TESTING"] = False
         cmake.configure()