about summary refs log tree commit diff
path: root/third_party/abseil_cpp/absl/strings/internal
diff options
context:
space:
mode:
authorVincent Ambo <mail@tazj.in>2020-11-21T13·43+0100
committerVincent Ambo <mail@tazj.in>2020-11-21T14·48+0100
commit082c006c04343a78d87b6c6ab3608c25d6213c3f (patch)
tree16e6f04f8d1d1d2d67e8e917d5e7bb48c1b60375 /third_party/abseil_cpp/absl/strings/internal
parentcc27324d0226953943f408ce3c69ad7d648e005e (diff)
merge(3p/absl): subtree merge of Abseil up to e19260f r/1889
... notably, this includes Abseil's own StatusOr type, which
conflicted with our implementation (that was taken from TensorFlow).

Change-Id: Ie7d6764b64055caaeb8dc7b6b9d066291e6b538f
Diffstat (limited to 'third_party/abseil_cpp/absl/strings/internal')
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/charconv_bigint_test.cc55
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/charconv_parse.cc12
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/cord_internal.h186
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/arg.cc14
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/arg.h48
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/arg_test.cc16
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/bind.cc16
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/bind.h23
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/bind_test.cc14
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/checker.h14
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/checker_test.cc14
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/convert_test.cc483
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/extension.cc23
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/extension.h6
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/extension_test.cc15
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.cc303
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.h14
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/parser.cc14
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/parser.h14
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_format/parser_test.cc14
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/str_split_internal.h55
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/string_constant.h70
-rw-r--r--third_party/abseil_cpp/absl/strings/internal/string_constant_test.cc60
23 files changed, 1323 insertions, 160 deletions
diff --git a/third_party/abseil_cpp/absl/strings/internal/charconv_bigint_test.cc b/third_party/abseil_cpp/absl/strings/internal/charconv_bigint_test.cc
index 363bcb03d938..a8b9945829e8 100644
--- a/third_party/abseil_cpp/absl/strings/internal/charconv_bigint_test.cc
+++ b/third_party/abseil_cpp/absl/strings/internal/charconv_bigint_test.cc
@@ -69,6 +69,61 @@ TEST(BigUnsigned, ShiftLeft) {
     // 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) {
diff --git a/third_party/abseil_cpp/absl/strings/internal/charconv_parse.cc b/third_party/abseil_cpp/absl/strings/internal/charconv_parse.cc
index fd6d9480fc04..8b11868c887a 100644
--- a/third_party/abseil_cpp/absl/strings/internal/charconv_parse.cc
+++ b/third_party/abseil_cpp/absl/strings/internal/charconv_parse.cc
@@ -246,8 +246,8 @@ constexpr int DigitMagnitude<16>() {
 // 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) {
@@ -282,7 +282,7 @@ std::size_t ConsumeDigits(const char* begin, const char* end, int max_digits,
     *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
@@ -372,7 +372,7 @@ strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
 
   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;
@@ -398,14 +398,14 @@ strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
       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;
 
diff --git a/third_party/abseil_cpp/absl/strings/internal/cord_internal.h b/third_party/abseil_cpp/absl/strings/internal/cord_internal.h
index 830ceaf473bd..aa91a691b949 100644
--- a/third_party/abseil_cpp/absl/strings/internal/cord_internal.h
+++ b/third_party/abseil_cpp/absl/strings/internal/cord_internal.h
@@ -21,6 +21,8 @@
 #include <cstdint>
 #include <type_traits>
 
+#include "absl/base/internal/invoke.h"
+#include "absl/container/internal/compressed_tuple.h"
 #include "absl/meta/type_traits.h"
 #include "absl/strings/string_view.h"
 
@@ -31,14 +33,17 @@ namespace cord_internal {
 // Wraps std::atomic for reference counting.
 class Refcount {
  public:
-  Refcount() : count_{1} {}
-  ~Refcount() {}
+  constexpr Refcount() : count_{kRefIncrement} {}
+  struct Immortal {};
+  explicit constexpr Refcount(Immortal) : count_(kImmortalTag) {}
 
-  // Increments the reference count by 1. Imposes no memory ordering.
-  inline void Increment() { count_.fetch_add(1, std::memory_order_relaxed); }
+  // 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 by 1.
+  // 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
@@ -46,19 +51,24 @@ class Refcount {
   // false.
   inline bool Decrement() {
     int32_t refcount = count_.load(std::memory_order_acquire);
-    assert(refcount > 0);
-    return refcount != 1 && count_.fetch_sub(1, std::memory_order_acq_rel) != 1;
+    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(1, std::memory_order_acq_rel);
-    assert(refcount > 0);
-    return refcount != 1;
+    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); }
+  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
@@ -68,9 +78,27 @@ class Refcount {
   // 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) == 1; }
+  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_;
 };
 
@@ -83,7 +111,22 @@ struct CordRepConcat;
 struct CordRepSubstring;
 struct CordRepExternal;
 
+// Various representations that we allow
+enum CordRepKind {
+  CONCAT        = 0,
+  EXTERNAL      = 1,
+  SUBSTRING     = 2,
+
+  // We have different tags for different sized flat arrays,
+  // starting with FLAT
+  FLAT          = 3,
+};
+
 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;
@@ -114,35 +157,112 @@ struct CordRepSubstring : public CordRep {
   CordRep* child;
 };
 
-// TODO(strel): replace the following logic (and related functions in cord.cc)
-// with container_internal::Layout.
-
-// Alignment requirement for CordRepExternal so that the type erased releaser
-// will be stored at a suitably aligned address.
-constexpr size_t ExternalRepAlignment() {
-#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
-  return __STDCPP_DEFAULT_NEW_ALIGNMENT__;
-#else
-  return alignof(max_align_t);
-#endif
-}
-
-// Type for function pointer that will invoke and destroy the type-erased
-// releaser function object. Accepts a pointer to the releaser and the
-// `string_view` that were passed in to `NewExternalRep` below. The return value
-// is the size of the `Releaser` type.
-using ExternalReleaserInvoker = size_t (*)(void*, absl::string_view);
+// 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 alignas(ExternalRepAlignment()) CordRepExternal : public CordRep {
+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;
 };
 
-// TODO(strel): look into removing, it doesn't seem like anything relies on this
-static_assert(sizeof(CordRepConcat) == sizeof(CordRepSubstring), "");
+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);
+  }
+};
+
+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, "");
 
 }  // namespace cord_internal
 ABSL_NAMESPACE_END
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/arg.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/arg.cc
index 9feb22487932..e28a29b17169 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/arg.cc
+++ b/third_party/abseil_cpp/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
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/arg.h b/third_party/abseil_cpp/absl/strings/internal/str_format/arg.h
index d441e87fff33..7040c866778e 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/arg.h
+++ b/third_party/abseil_cpp/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_
 
@@ -25,10 +39,12 @@ class Cord;
 class FormatCountCapture;
 class FormatSink;
 
-namespace str_format_internal {
-
+template <absl::FormatConversionCharSet C>
+struct FormatConvertResult;
 class FormatConversionSpec;
 
+namespace str_format_internal {
+
 template <typename T, typename = void>
 struct HasUserDefinedConvert : std::false_type {};
 
@@ -39,6 +55,22 @@ struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
                                     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;
 
@@ -46,6 +78,13 @@ class StreamedWrapper;
 // 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;
@@ -62,6 +101,11 @@ struct ArgConvertResult {
 };
 
 template <FormatConversionCharSet C>
+constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
+  return C;
+}
+
+template <FormatConversionCharSet C>
 constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {
   return C;
 }
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/arg_test.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/arg_test.cc
index bf3d7e8e3777..1261937c3097 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/arg_test.cc
+++ b/third_party/abseil_cpp/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>
@@ -23,8 +29,17 @@ class FormatArgImplTest : public ::testing::Test {
   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));
@@ -59,6 +74,7 @@ TEST_F(FormatArgImplTest, ToInt) {
       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);
 }
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/bind.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/bind.cc
index 6980ed1d8f0e..4e68b90b5ce8 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/bind.cc
+++ b/third_party/abseil_cpp/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>
@@ -221,7 +235,7 @@ int FprintF(std::FILE* output, const UntypedFormatSpecImpl format,
     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;
   }
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/bind.h b/third_party/abseil_cpp/absl/strings/internal/str_format/bind.h
index 585246e77e56..267cc0ef6928 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/bind.h
+++ b/third_party/abseil_cpp/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_
 
@@ -119,10 +133,11 @@ class FormatSpecTemplate
 
 #endif  // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
 
-  template <FormatConversionCharSet... C,
-            typename = typename std::enable_if<
-                AllOf(sizeof...(C) == sizeof...(Args), Contains(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) {}
 };
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/bind_test.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/bind_test.cc
index 64790a85fd23..1eef9c4326e2 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/bind_test.cc
+++ b/third_party/abseil_cpp/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>
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/checker.h b/third_party/abseil_cpp/absl/strings/internal/str_format/checker.h
index 424c51f74f17..2a2601eccfd8 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/checker.h
+++ b/third_party/abseil_cpp/absl/strings/internal/str_format/checker.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_CHECKER_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
 
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/checker_test.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/checker_test.cc
index a76d70b0586c..7c70f47d682a 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/checker_test.cc
+++ b/third_party/abseil_cpp/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"
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/convert_test.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/convert_test.cc
index 0e8535c27b7a..375db0a0592c 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/convert_test.cc
+++ b/third_party/abseil_cpp/absl/strings/internal/str_format/convert_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 <errno.h>
 #include <stdarg.h>
 #include <stdio.h>
@@ -12,6 +26,7 @@
 #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 {
@@ -19,6 +34,13 @@ 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;
@@ -118,6 +140,63 @@ std::string StrPrint(const char *format, ...) {
   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>
@@ -474,6 +553,68 @@ TEST_F(FormatConvertTest, Uint128) {
   }
 }
 
+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
@@ -481,9 +622,62 @@ TEST_F(FormatConvertTest, Float) {
   return;
 #endif  // _MSC_VER
 
-  const char *const kFormats[] = {
-      "%",  "%.3", "%8.5", "%500",   "%.5000", "%.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,
@@ -554,52 +748,10 @@ TEST_F(FormatConvertTest, Float) {
   doubles.push_back(std::nan(""));
 #endif
 
-  // 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);
-
-  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') {
-        // This particular test takes way too long with snprintf.
-        // Disable for the case we are not implementing natively.
-        continue;
-      }
-
-      for (double d : doubles) {
-        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("%.1080f", d);
-        }
-      }
-    }
-  }
+  TestWithMultipleFormatsHelper(doubles);
 }
 
-TEST_F(FormatConvertTest, FloatRound) {
+TEST_F(FormatConvertTest, DoubleRound) {
   std::string s;
   const auto format = [&](const char *fmt, double d) -> std::string & {
     s.clear();
@@ -704,6 +856,193 @@ TEST_F(FormatConvertTest, FloatRound) {
             "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 {
@@ -735,6 +1074,7 @@ TEST_F(FormatConvertTest, LongDouble) {
   // 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"};
 
@@ -777,12 +1117,20 @@ TEST_F(FormatConvertTest, LongDouble) {
                    'e', 'E'}) {
       std::string fmt_str = std::string(fmt) + 'L' + f;
 
-      if (fmt == absl::string_view("%.5000") && f != 'f' && f != '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);
@@ -797,7 +1145,8 @@ TEST_F(FormatConvertTest, LongDouble) {
   }
 }
 
-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[] = {
@@ -813,14 +1162,17 @@ TEST_F(FormatConvertTest, IntAsFloat) {
       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);
@@ -865,6 +1217,25 @@ TEST_F(FormatConvertTest, ExpectedFailures) {
   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
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/extension.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/extension.cc
index 94f2b9c209aa..bb0d96cf3216 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/extension.cc
+++ b/third_party/abseil_cpp/absl/strings/internal/str_format/extension.cc
@@ -33,6 +33,29 @@ std::string Flags::ToString() const {
   return s;
 }
 
+#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;
+
+#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
+
+// 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;
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/extension.h b/third_party/abseil_cpp/absl/strings/internal/str_format/extension.h
index 6c60c6c3a379..a9b9e137deb2 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/extension.h
+++ b/third_party/abseil_cpp/absl/strings/internal/str_format/extension.h
@@ -31,11 +31,11 @@
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-namespace str_format_internal {
-
 enum class FormatConversionChar : uint8_t;
 enum class FormatConversionCharSet : uint64_t;
 
+namespace str_format_internal {
+
 class FormatRawSinkImpl {
  public:
   // Implicitly convert from any type that provides the hook function as
@@ -361,14 +361,12 @@ struct FormatConversionCharSetInternal {
   static constexpr FormatConversionCharSet kStar =
       FormatConversionCharToConvValue('*');
 
-  // Some predefined values (TODO(matthewbr), delete any that are unused).
   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 kString = s;
   static constexpr FormatConversionCharSet kPointer = p;
 };
 
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/extension_test.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/extension_test.cc
index 0a023f9c0333..1c93fdb1c75b 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/extension_test.cc
+++ b/third_party/abseil_cpp/absl/strings/internal/str_format/extension_test.cc
@@ -80,4 +80,19 @@ TEST(FormatExtensionTest, SinkAppendChars) {
     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/third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.cc
index 10e4695411b2..0ded0a66afa9 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.cc
+++ b/third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.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/float_conversion.h"
 
 #include <string.h>
@@ -15,6 +29,7 @@
 #include "absl/functional/function_ref.h"
 #include "absl/meta/type_traits.h"
 #include "absl/numeric/int128.h"
+#include "absl/strings/numbers.h"
 #include "absl/types/optional.h"
 #include "absl/types/span.h"
 
@@ -119,7 +134,7 @@ class BinaryToDecimal {
     assert(exp > 0);
     assert(exp <= std::numeric_limits<long double>::max_exponent);
     static_assert(
-        StackArray::kMaxCapacity >=
+        static_cast<int>(StackArray::kMaxCapacity) >=
             ChunksNeeded(std::numeric_limits<long double>::max_exponent),
         "");
 
@@ -204,7 +219,7 @@ class BinaryToDecimal {
   }
 
  private:
-  static constexpr size_t kDigitsPerChunk = 9;
+  static constexpr int kDigitsPerChunk = 9;
 
   int decimal_start_;
   int decimal_end_;
@@ -441,8 +456,10 @@ struct Padding {
 };
 
 Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
-  if (state.conv.width() < 0 || state.conv.width() <= total_size)
+  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};
@@ -453,26 +470,31 @@ Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
   }
 }
 
-void FinalPrint(absl::string_view data, int trailing_zeros,
-                const FormatState &state) {
+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() +
-                              static_cast<size_t>(trailing_zeros),
-                          state);
+  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);
+  state.sink->Append(data.substr(padding_offset));
   state.sink->Append(trailing_zeros, '0');
+  state.sink->Append(data_postfix);
   state.sink->Append(padding.right_spaces, ' ');
 }
 
@@ -525,10 +547,11 @@ void FormatFFast(Int v, int exp, const FormatState &state) {
   // 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(absl::string_view(integral_digits_start, size),
+  FinalPrint(state, absl::string_view(integral_digits_start, size),
+             /*padding_offset=*/0,
              static_cast<int>(state.precision - (fractional_digits_end -
                                                  fractional_digits_start)),
-             state);
+             /*data_postfix=*/"");
 }
 
 // Slow %f formatter for when the shifted value does not fit in a uint128, and
@@ -655,6 +678,255 @@ void FormatF(Int mantissa, int exp, const FormatState &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();
@@ -1103,7 +1375,10 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
     }
   } else if (c == FormatConversionCharInternal::a ||
              c == FormatConversionCharInternal::A) {
-    return FallbackToSnprintf(v, conv, sink);
+    bool uppercase = (c == FormatConversionCharInternal::A);
+    FormatA(HexFloatTypeParams(Float{}), decomposed.mantissa,
+            decomposed.exponent, uppercase, {sign_char, precision, conv, sink});
+    return true;
   } else {
     return false;
   }
@@ -1131,7 +1406,7 @@ bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &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 FormatConversionSpecImpl &conv,
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.h b/third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.h
index e78bc19106ff..71100e714257 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.h
+++ b/third_party/abseil_cpp/absl/strings/internal/str_format/float_conversion.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_FLOAT_CONVERSION_H_
 #define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
 
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/parser.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/parser.cc
index cc55dfa9c74e..f308d0235120 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/parser.cc
+++ b/third_party/abseil_cpp/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>
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/parser.h b/third_party/abseil_cpp/absl/strings/internal/str_format/parser.h
index fffed04fa072..6504dd3ddc20 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/parser.h
+++ b/third_party/abseil_cpp/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_
 
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_format/parser_test.cc b/third_party/abseil_cpp/absl/strings/internal/str_format/parser_test.cc
index 5aced987200d..a5fa1c79aaf4 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_format/parser_test.cc
+++ b/third_party/abseil_cpp/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>
diff --git a/third_party/abseil_cpp/absl/strings/internal/str_split_internal.h b/third_party/abseil_cpp/absl/strings/internal/str_split_internal.h
index 6f5bc095fbbe..a2f41c153131 100644
--- a/third_party/abseil_cpp/absl/strings/internal/str_split_internal.h
+++ b/third_party/abseil_cpp/absl/strings/internal/str_split_internal.h
@@ -51,9 +51,9 @@ 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)
@@ -65,41 +65,12 @@ class ConvertibleToStringView {
       : 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_;
 };
 
@@ -273,7 +244,11 @@ struct SplitterIsConvertibleTo
 // 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;
@@ -281,12 +256,12 @@ class Splitter {
   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_; }
 
@@ -336,7 +311,7 @@ class Splitter {
     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;
@@ -401,7 +376,7 @@ class Splitter {
       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 {
@@ -443,7 +418,7 @@ class Splitter {
     };
   };
 
-  ConvertibleToStringView text_;
+  StringType text_;
   Delimiter delimiter_;
   Predicate predicate_;
 };
diff --git a/third_party/abseil_cpp/absl/strings/internal/string_constant.h b/third_party/abseil_cpp/absl/strings/internal/string_constant.h
new file mode 100644
index 000000000000..b15f1d9bcfac
--- /dev/null
+++ b/third_party/abseil_cpp/absl/strings/internal/string_constant.h
@@ -0,0 +1,70 @@
+// 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 {
+ private:
+  // Returns true if `view` points to constant data.
+  // Otherwise, it can't be constant evaluated.
+  static constexpr bool ValidateConstant(absl::string_view view) {
+    return view.empty() || 2 * view[0] != 1;
+  }
+
+ public:
+  static constexpr absl::string_view value = T{}();
+  constexpr absl::string_view operator()() const { return value; }
+
+  static_assert(ValidateConstant(value),
+                "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/third_party/abseil_cpp/absl/strings/internal/string_constant_test.cc b/third_party/abseil_cpp/absl/strings/internal/string_constant_test.cc
new file mode 100644
index 000000000000..392833cf1592
--- /dev/null
+++ b/third_party/abseil_cpp/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