about summary refs log tree commit diff
path: root/absl
diff options
context:
space:
mode:
authorAbseil Team <absl-team@google.com>2020-05-07T17·42-0700
committervslashg <gfalcon@google.com>2020-05-07T19·26-0400
commita35ef8a62ce7cded2f131ccbd2b5c4a81d622507 (patch)
tree2b4a4451d714d8ebee30db71f7a0ee8430e9789e /absl
parentbd317cae3bc2630d1b12c5f1d77036e937d1d725 (diff)
Export of internal Abseil changes
--
034c30a00c64d93b9fcbc9d99a0a33801544d741 by Gennadiy Rozental <rogeeff@google.com>:

Split private handle interfaces accessor into a separate target with private visibility.

PiperOrigin-RevId: 310391488

--
6f6ca869309b17900b90849e08488ce7f7b0193a by Derek Mauro <dmauro@google.com>:

Remove __CLANG_SUPPORT_DYN_ANNOTATION__, which is a symbol defined by us
to be true in all builds

PiperOrigin-RevId: 310385325

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

Add tests to exercise extreme width and precision, and fix the overflows from
it.

PiperOrigin-RevId: 310224957
GitOrigin-RevId: 034c30a00c64d93b9fcbc9d99a0a33801544d741
Change-Id: I6c89a3c89ae92fa617c696044148ce9a79bcdda8
Diffstat (limited to 'absl')
-rw-r--r--absl/base/BUILD.bazel1
-rw-r--r--absl/base/CMakeLists.txt2
-rw-r--r--absl/base/dynamic_annotations.h5
-rw-r--r--absl/flags/BUILD.bazel23
-rw-r--r--absl/flags/CMakeLists.txt23
-rw-r--r--absl/flags/internal/commandlineflag.cc27
-rw-r--r--absl/flags/internal/commandlineflag.h31
-rw-r--r--absl/flags/internal/commandlineflag_test.cc31
-rw-r--r--absl/flags/internal/flag.h1
-rw-r--r--absl/flags/internal/private_handle_accessor.cc52
-rw-r--r--absl/flags/internal/private_handle_accessor.h52
-rw-r--r--absl/flags/internal/registry.cc7
-rw-r--r--absl/flags/internal/type_erased.cc7
-rw-r--r--absl/flags/internal/usage.cc1
-rw-r--r--absl/flags/parse.cc5
-rw-r--r--absl/strings/internal/str_format/convert_test.cc25
-rw-r--r--absl/strings/internal/str_format/float_conversion.cc20
17 files changed, 214 insertions, 99 deletions
diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel
index 1664a35124..816e592b53 100644
--- a/absl/base/BUILD.bazel
+++ b/absl/base/BUILD.bazel
@@ -118,7 +118,6 @@ cc_library(
     srcs = ["dynamic_annotations.cc"],
     hdrs = ["dynamic_annotations.h"],
     copts = ABSL_DEFAULT_COPTS,
-    defines = ["__CLANG_SUPPORT_DYN_ANNOTATION__"],
     linkopts = ABSL_DEFAULT_LINKOPTS,
 )
 
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
index 2df2e9713a..292998b3bf 100644
--- a/absl/base/CMakeLists.txt
+++ b/absl/base/CMakeLists.txt
@@ -108,8 +108,6 @@ absl_cc_library(
     "dynamic_annotations.cc"
   COPTS
     ${ABSL_DEFAULT_COPTS}
-  DEFINES
-    "__CLANG_SUPPORT_DYN_ANNOTATION__"
   PUBLIC
 )
 
diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h
index 65a54b447f..2d98526075 100644
--- a/absl/base/dynamic_annotations.h
+++ b/absl/base/dynamic_annotations.h
@@ -140,10 +140,7 @@
   #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 defined(__clang__) && !defined(SWIG)
 
   #if DYNAMIC_ANNOTATIONS_ENABLED == 0
     #define ANNOTALYSIS_ENABLED
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index 685e395419..3681082527 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -40,6 +40,7 @@ cc_library(
     deps = [
         ":config",
         ":handle",
+        ":marshalling",
         ":registry",
         "//absl/base",
         "//absl/base:config",
@@ -143,8 +144,6 @@ cc_library(
         "//absl/flags:__pkg__",
     ],
     deps = [
-        ":config",
-        ":marshalling",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:fast_type_id",
@@ -154,6 +153,22 @@ cc_library(
 )
 
 cc_library(
+    name = "private_handle_accessor",
+    srcs = [
+        "internal/private_handle_accessor.cc",
+    ],
+    hdrs = [
+        "internal/private_handle_accessor.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl/flags:__pkg__",
+    ],
+    deps = [":handle"],
+)
+
+cc_library(
     name = "registry",
     srcs = [
         "internal/registry.cc",
@@ -171,6 +186,7 @@ cc_library(
     deps = [
         ":config",
         ":handle",
+        ":private_handle_accessor",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:raw_logging_internal",
@@ -222,6 +238,7 @@ cc_library(
         ":flag_internal",
         ":handle",
         ":path_util",
+        ":private_handle_accessor",
         ":program_name",
         ":registry",
         "//absl/base:config",
@@ -263,6 +280,7 @@ cc_library(
         ":flag",
         ":flag_internal",
         ":handle",
+        ":private_handle_accessor",
         ":program_name",
         ":registry",
         ":usage",
@@ -289,6 +307,7 @@ cc_test(
         ":config",
         ":flag",
         ":handle",
+        ":private_handle_accessor",
         ":registry",
         "//absl/memory",
         "//absl/strings",
diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt
index ec82ee1e36..e6b17c9b04 100644
--- a/absl/flags/CMakeLists.txt
+++ b/absl/flags/CMakeLists.txt
@@ -31,6 +31,7 @@ absl_cc_library(
     absl::config
     absl::flags_config
     absl::flags_handle
+    absl::flags_marshalling
     absl::flags_registry
     absl::synchronization
     absl::meta
@@ -129,8 +130,6 @@ absl_cc_library(
   DEPS
     absl::config
     absl::fast_type_id
-    absl::flags_config
-    absl::flags_marshalling
     absl::core_headers
     absl::optional
     absl::raw_logging_internal
@@ -141,6 +140,22 @@ absl_cc_library(
 # 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::flags_handle
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
     flags_registry
   SRCS
     "internal/registry.cc"
@@ -156,6 +171,7 @@ absl_cc_library(
     absl::config
     absl::flags_config
     absl::flags_handle
+    absl::flags_private_handle_accessor
     absl::core_headers
     absl::raw_logging_internal
     absl::strings
@@ -203,6 +219,7 @@ absl_cc_library(
     absl::flags_config
     absl::flags
     absl::flags_handle
+    absl::flags_private_handle_accessor
     absl::flags_internal
     absl::flags_path_util
     absl::flags_program_name
@@ -248,6 +265,7 @@ absl_cc_library(
     absl::flags_config
     absl::flags
     absl::flags_handle
+    absl::flags_private_handle_accessor
     absl::flags_internal
     absl::flags_program_name
     absl::flags_registry
@@ -270,6 +288,7 @@ absl_cc_test(
     absl::flags
     absl::flags_config
     absl::flags_handle
+    absl::flags_private_handle_accessor
     absl::flags_registry
     absl::memory
     absl::strings
diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc
index c919fa1be8..84112437d9 100644
--- a/absl/flags/internal/commandlineflag.cc
+++ b/absl/flags/internal/commandlineflag.cc
@@ -28,33 +28,6 @@ bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) {
                    flags_internal::kProgrammaticChange, error);
 }
 
-FlagFastTypeId PrivateHandleInterface::TypeId(const CommandLineFlag& flag) {
-  return flag.TypeId();
-}
-
-std::unique_ptr<FlagStateInterface> PrivateHandleInterface::SaveState(
-    CommandLineFlag* flag) {
-  return flag->SaveState();
-}
-
-bool PrivateHandleInterface::ValidateInputValue(const CommandLineFlag& flag,
-                                                absl::string_view value) {
-  return flag.ValidateInputValue(value);
-}
-
-void PrivateHandleInterface::CheckDefaultValueParsingRoundtrip(
-    const CommandLineFlag& flag) {
-  flag.CheckDefaultValueParsingRoundtrip();
-}
-
-bool PrivateHandleInterface::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/commandlineflag.h b/absl/flags/internal/commandlineflag.h
index af5e05d599..2d3b794dbd 100644
--- a/absl/flags/internal/commandlineflag.h
+++ b/absl/flags/internal/commandlineflag.h
@@ -16,18 +16,12 @@
 #ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
 #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
 
-#include <stddef.h>
-#include <stdint.h>
-
 #include <memory>
 #include <string>
-#include <typeinfo>
 
 #include "absl/base/config.h"
 #include "absl/base/internal/fast_type_id.h"
 #include "absl/base/macros.h"
-#include "absl/flags/config.h"
-#include "absl/flags/marshalling.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
 
@@ -147,7 +141,7 @@ class CommandLineFlag {
   ~CommandLineFlag() = default;
 
  private:
-  friend class PrivateHandleInterface;
+  friend class 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`
@@ -181,29 +175,6 @@ class CommandLineFlag {
   virtual void CheckDefaultValueParsingRoundtrip() const = 0;
 };
 
-// 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 PrivateHandleInterface {
- 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::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);
-};
-
 // This macro is the "source of truth" for the list of supported flag built-in
 // types.
 #define ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \
diff --git a/absl/flags/internal/commandlineflag_test.cc b/absl/flags/internal/commandlineflag_test.cc
index 4aeb3bf4dd..54d50fff35 100644
--- a/absl/flags/internal/commandlineflag_test.cc
+++ b/absl/flags/internal/commandlineflag_test.cc
@@ -20,6 +20,7 @@
 
 #include "gtest/gtest.h"
 #include "absl/flags/flag.h"
+#include "absl/flags/internal/private_handle_accessor.h"
 #include "absl/flags/internal/registry.h"
 #include "absl/flags/usage_config.h"
 #include "absl/memory/memory.h"
@@ -122,52 +123,52 @@ TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
   auto* flag_01 = flags::FindCommandLineFlag("int_flag");
   EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
 
-  EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom(
+  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(flag_01->IsSpecifiedOnCommandLine());
 
-  EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom(
+  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(flag_01->IsSpecifiedOnCommandLine());
 
-  EXPECT_TRUE(!flags::PrivateHandleInterface::ParseFrom(
+  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(flag_01->IsSpecifiedOnCommandLine());
 
-  EXPECT_TRUE(!flags::PrivateHandleInterface::ParseFrom(
+  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(flag_01->IsSpecifiedOnCommandLine());
 
-  EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom(
+  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(flag_01->IsSpecifiedOnCommandLine());
 
-  EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom(
+  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(flag_01->IsSpecifiedOnCommandLine());
 
-  EXPECT_TRUE(!flags::PrivateHandleInterface::ParseFrom(
+  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 = flags::FindCommandLineFlag("string_flag");
-  EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom(
+  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::PrivateHandleInterface::ParseFrom(
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
       flag_02, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));
   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
 }
@@ -179,14 +180,14 @@ TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {
 
   auto* flag_01 = flags::FindCommandLineFlag("int_flag");
 
-  EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom(
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
       flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
       &err));
   EXPECT_EQ(flag_01->DefaultValue(), "111");
 
   auto* flag_02 = flags::FindCommandLineFlag("string_flag");
 
-  EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom(
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
       flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
       &err));
   EXPECT_EQ(flag_02->DefaultValue(), "abc");
@@ -199,24 +200,24 @@ TEST_F(CommandLineFlagTest, TestParseFromIfDefault) {
 
   auto* flag_01 = flags::FindCommandLineFlag("int_flag");
 
-  EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom(
+  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::PrivateHandleInterface::ParseFrom(
+  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::PrivateHandleInterface::ParseFrom(
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
       flag_01, "201", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
       &err));
 
-  EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom(
+  EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
       flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
       &err));
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201);
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index b220882450..f53f484f8f 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -31,6 +31,7 @@
 #include "absl/flags/config.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/internal/registry.h"
+#include "absl/flags/marshalling.h"
 #include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
 #include "absl/strings/str_cat.h"
diff --git a/absl/flags/internal/private_handle_accessor.cc b/absl/flags/internal/private_handle_accessor.cc
new file mode 100644
index 0000000000..ec5776bb06
--- /dev/null
+++ b/absl/flags/internal/private_handle_accessor.cc
@@ -0,0 +1,52 @@
+//
+// 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"
+
+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::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 0000000000..fbb4409cdb
--- /dev/null
+++ b/absl/flags/internal/private_handle_accessor.h
@@ -0,0 +1,52 @@
+//
+// 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 "absl/flags/internal/commandlineflag.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::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/registry.cc b/absl/flags/internal/registry.cc
index 62b5b40d88..3b941f04c2 100644
--- a/absl/flags/internal/registry.cc
+++ b/absl/flags/internal/registry.cc
@@ -29,6 +29,7 @@
 #include "absl/base/internal/raw_logging.h"
 #include "absl/base/thread_annotations.h"
 #include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/private_handle_accessor.h"
 #include "absl/flags/usage_config.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
@@ -127,8 +128,8 @@ void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
               (flag->IsRetired() ? old_flag->Filename() : flag->Filename()),
               "'."),
           true);
-    } else if (flags_internal::PrivateHandleInterface::TypeId(*flag) !=
-               flags_internal::PrivateHandleInterface::TypeId(*old_flag)) {
+    } 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 "
@@ -206,7 +207,7 @@ class FlagSaverImpl {
     assert(backup_registry_.empty());  // call only once!
     flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) {
       if (auto flag_state =
-              flags_internal::PrivateHandleInterface::SaveState(flag)) {
+              flags_internal::PrivateHandleAccessor::SaveState(flag)) {
         backup_registry_.emplace_back(std::move(flag_state));
       }
     });
diff --git a/absl/flags/internal/type_erased.cc b/absl/flags/internal/type_erased.cc
index adeb7a1541..3cfc9b2dfb 100644
--- a/absl/flags/internal/type_erased.cc
+++ b/absl/flags/internal/type_erased.cc
@@ -22,6 +22,7 @@
 #include "absl/base/config.h"
 #include "absl/base/internal/raw_logging.h"
 #include "absl/flags/internal/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/string_view.h"
@@ -56,7 +57,7 @@ bool SetCommandLineOptionWithMode(absl::string_view name,
   if (!flag || flag->IsRetired()) return false;
 
   std::string error;
-  if (!flags_internal::PrivateHandleInterface::ParseFrom(
+  if (!flags_internal::PrivateHandleAccessor::ParseFrom(
           flag, 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).
@@ -74,8 +75,8 @@ bool IsValidFlagValue(absl::string_view name, absl::string_view value) {
 
   return flag != nullptr &&
          (flag->IsRetired() ||
-          flags_internal::PrivateHandleInterface::ValidateInputValue(*flag,
-                                                                     value));
+          flags_internal::PrivateHandleAccessor::ValidateInputValue(*flag,
+                                                                    value));
 }
 
 // --------------------------------------------------------------------
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
index 9d856c87a6..10accc46f3 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -27,6 +27,7 @@
 #include "absl/flags/internal/commandlineflag.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"
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
index cc13490987..66a28a93c7 100644
--- a/absl/flags/parse.cc
+++ b/absl/flags/parse.cc
@@ -39,6 +39,7 @@
 #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"
@@ -298,7 +299,7 @@ void CheckDefaultValuesParsingRoundtrip() {
     ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(IGNORE_TYPE)
 #undef IGNORE_TYPE
 
-    flags_internal::PrivateHandleInterface::CheckDefaultValueParsingRoundtrip(
+    flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
         *flag);
   });
 #endif
@@ -697,7 +698,7 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
     if (flag->IsRetired()) continue;
 
     std::string error;
-    if (!flags_internal::PrivateHandleInterface::ParseFrom(
+    if (!flags_internal::PrivateHandleAccessor::ParseFrom(
             flag, value, SET_FLAGS_VALUE, kCommandLine, &error)) {
       flags_internal::ReportUsageError(error, true);
       success = false;
diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc
index dd167f76e6..20c6229fcb 100644
--- a/absl/strings/internal/str_format/convert_test.cc
+++ b/absl/strings/internal/str_format/convert_test.cc
@@ -704,6 +704,31 @@ TEST_F(FormatConvertTest, FloatRound) {
             "1837869002408041296803276054561138153076171875");
 }
 
+// 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) {
 #ifdef _MSC_VER
   // MSVC has a different rounding policy than us so we can't test our
diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc
index cdccc86f55..a761a5a5f9 100644
--- a/absl/strings/internal/str_format/float_conversion.cc
+++ b/absl/strings/internal/str_format/float_conversion.cc
@@ -440,8 +440,10 @@ struct Padding {
   int right_spaces;
 };
 
-Padding ExtraWidthToPadding(int total_size, const FormatState &state) {
-  int missing_chars = std::max(state.conv.width() - total_size, 0);
+Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
+  if (state.conv.width() < 0 || 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()) {
@@ -462,8 +464,8 @@ void FinalPrint(absl::string_view data, int trailing_zeros,
   }
 
   auto padding =
-      ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) +
-                              static_cast<int>(data.size()) + trailing_zeros,
+      ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + data.size() +
+                              static_cast<size_t>(trailing_zeros),
                           state);
 
   state.sink->Append(padding.left_spaces, ' ');
@@ -536,8 +538,9 @@ void FormatFFast(Int v, int exp, const FormatState &state) {
 // worry about anything after the `.`.
 void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) {
   BinaryToDecimal::RunConversion(v, exp, [&](BinaryToDecimal btd) {
-    const int total_digits =
-        btd.TotalDigits() + (state.ShouldPrintDot() ? state.precision + 1 : 0);
+    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);
@@ -562,8 +565,9 @@ void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &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 int total_digits =
-      /* 0 */ 1 + (state.ShouldPrintDot() ? state.precision + 1 : 0);
+  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;