about summary refs log tree commit diff
path: root/third_party/abseil_cpp/absl/flags
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/abseil_cpp/absl/flags')
-rw-r--r--third_party/abseil_cpp/absl/flags/BUILD.bazel12
-rw-r--r--third_party/abseil_cpp/absl/flags/CMakeLists.txt8
-rw-r--r--third_party/abseil_cpp/absl/flags/commandlineflag.cc4
-rw-r--r--third_party/abseil_cpp/absl/flags/commandlineflag.h4
-rw-r--r--third_party/abseil_cpp/absl/flags/flag.h33
-rw-r--r--third_party/abseil_cpp/absl/flags/flag_benchmark.cc33
-rw-r--r--third_party/abseil_cpp/absl/flags/flag_test.cc11
-rw-r--r--third_party/abseil_cpp/absl/flags/flag_test_defs.cc4
-rw-r--r--third_party/abseil_cpp/absl/flags/internal/commandlineflag.cc26
-rw-r--r--third_party/abseil_cpp/absl/flags/internal/flag.h41
-rw-r--r--third_party/abseil_cpp/absl/flags/internal/registry.h22
-rw-r--r--third_party/abseil_cpp/absl/flags/internal/usage.cc277
-rw-r--r--third_party/abseil_cpp/absl/flags/internal/usage.h43
-rw-r--r--third_party/abseil_cpp/absl/flags/internal/usage_test.cc116
-rw-r--r--third_party/abseil_cpp/absl/flags/parse.cc17
-rw-r--r--third_party/abseil_cpp/absl/flags/parse_test.cc33
-rw-r--r--third_party/abseil_cpp/absl/flags/reflection.cc153
-rw-r--r--third_party/abseil_cpp/absl/flags/reflection.h9
-rw-r--r--third_party/abseil_cpp/absl/flags/reflection_test.cc207
19 files changed, 840 insertions, 213 deletions
diff --git a/third_party/abseil_cpp/absl/flags/BUILD.bazel b/third_party/abseil_cpp/absl/flags/BUILD.bazel
index 006911fd8e71..78d6da74d819 100644
--- a/third_party/abseil_cpp/absl/flags/BUILD.bazel
+++ b/third_party/abseil_cpp/absl/flags/BUILD.bazel
@@ -24,7 +24,7 @@ load(
 
 package(default_visibility = ["//visibility:public"])
 
-licenses(["notice"])  # Apache 2.0
+licenses(["notice"])
 
 cc_library(
     name = "path_util",
@@ -106,12 +106,14 @@ cc_library(
 
 cc_library(
     name = "commandlineflag_internal",
+    srcs = [
+        "internal/commandlineflag.cc",
+    ],
     hdrs = [
         "internal/commandlineflag.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = ["//visibility:private"],
     deps = [
         "//absl/base:config",
         "//absl/base:fast_type_id",
@@ -176,6 +178,7 @@ cc_library(
         ":private_handle_accessor",
         "//absl/base:config",
         "//absl/base:core_headers",
+        "//absl/container:flat_hash_map",
         "//absl/strings",
         "//absl/synchronization",
     ],
@@ -378,6 +381,8 @@ cc_binary(
     deps = [
         ":flag",
         ":marshalling",
+        ":parse",
+        ":reflection",
         "//absl/strings",
         "//absl/time",
         "//absl/types:optional",
@@ -411,6 +416,7 @@ cc_test(
         ":flag",
         ":parse",
         ":reflection",
+        ":usage_internal",
         "//absl/base:raw_logging_internal",
         "//absl/base:scoped_set_env",
         "//absl/strings",
@@ -461,7 +467,9 @@ cc_test(
         ":flag",
         ":marshalling",
         ":reflection",
+        ":usage_internal",
         "//absl/memory",
+        "//absl/strings",
         "@com_google_googletest//:gtest_main",
     ],
 )
diff --git a/third_party/abseil_cpp/absl/flags/CMakeLists.txt b/third_party/abseil_cpp/absl/flags/CMakeLists.txt
index ef75db8e9c5f..e5083d7b9a87 100644
--- a/third_party/abseil_cpp/absl/flags/CMakeLists.txt
+++ b/third_party/abseil_cpp/absl/flags/CMakeLists.txt
@@ -95,6 +95,8 @@ absl_cc_library(
 absl_cc_library(
   NAME
     flags_commandlineflag_internal
+  SRCS
+    "internal/commandlineflag.cc"
   HDRS
     "internal/commandlineflag.h"
   COPTS
@@ -163,6 +165,7 @@ absl_cc_library(
     absl::flags_config
     absl::strings
     absl::synchronization
+    absl::flat_hash_map
 )
 
 # Internal-only target, do not depend on directly.
@@ -180,6 +183,7 @@ absl_cc_library(
   DEPS
     absl::base
     absl::config
+    absl::flags_commandlineflag
     absl::flags_commandlineflag_internal
     absl::flags_config
     absl::flags_marshalling
@@ -362,6 +366,7 @@ absl_cc_test(
     absl::flags
     absl::flags_parse
     absl::flags_reflection
+    absl::flags_usage_internal
     absl::raw_logging_internal
     absl::scoped_set_env
     absl::span
@@ -405,9 +410,10 @@ absl_cc_test(
     absl::flags_commandlineflag_internal
     absl::flags
     absl::flags_reflection
+    absl::flags_usage
     absl::memory
     absl::strings
-    gtest_main
+    gmock_main
 )
 
 absl_cc_test(
diff --git a/third_party/abseil_cpp/absl/flags/commandlineflag.cc b/third_party/abseil_cpp/absl/flags/commandlineflag.cc
index 217b2d870079..9f3b4a5a28ef 100644
--- a/third_party/abseil_cpp/absl/flags/commandlineflag.cc
+++ b/third_party/abseil_cpp/absl/flags/commandlineflag.cc
@@ -30,9 +30,5 @@ bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) {
                    flags_internal::kProgrammaticChange, *error);
 }
 
-namespace flags_internal {
-FlagStateInterface::~FlagStateInterface() {}
-}  // namespace flags_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
-
diff --git a/third_party/abseil_cpp/absl/flags/commandlineflag.h b/third_party/abseil_cpp/absl/flags/commandlineflag.h
index 7e21d05d8a53..f2fa08977fd4 100644
--- a/third_party/abseil_cpp/absl/flags/commandlineflag.h
+++ b/third_party/abseil_cpp/absl/flags/commandlineflag.h
@@ -108,6 +108,10 @@ class CommandLineFlag {
     U u;
 
     Read(&u.value);
+    // allow retired flags to be "read", so we can report invalid access.
+    if (IsRetired()) {
+      return absl::nullopt;
+    }
     return std::move(u.value);
   }
 
diff --git a/third_party/abseil_cpp/absl/flags/flag.h b/third_party/abseil_cpp/absl/flags/flag.h
index 90dc2894df54..a9cb2b7994d1 100644
--- a/third_party/abseil_cpp/absl/flags/flag.h
+++ b/third_party/abseil_cpp/absl/flags/flag.h
@@ -144,11 +144,17 @@ class Flag {
   inline bool IsOfType() const {
     return GetImpl().template IsOfType<U>();
   }
-  T Get() const { return GetImpl().Get(); }
-  void Set(const T& v) { GetImpl().Set(v); }
+  T Get() const {
+    return flags_internal::FlagImplPeer::InvokeGet<T>(GetImpl());
+  }
+  void Set(const T& v) {
+    flags_internal::FlagImplPeer::InvokeSet(GetImpl(), v);
+  }
   void InvokeCallback() { GetImpl().InvokeCallback(); }
 
-  const CommandLineFlag& Reflect() const { return GetImpl().Reflect(); }
+  const CommandLineFlag& Reflect() const {
+    return flags_internal::FlagImplPeer::InvokeReflect(GetImpl());
+  }
 
   // The data members are logically private, but they need to be public for
   // this to be an aggregate type.
@@ -180,7 +186,7 @@ class Flag {
 //   std::string first_name = absl::GetFlag(FLAGS_firstname);
 template <typename T>
 ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
-  return flag.Get();
+  return flags_internal::FlagImplPeer::InvokeGet<T>(flag);
 }
 
 // SetFlag()
@@ -192,7 +198,7 @@ ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
 // but especially within performance-critical code.
 template <typename T>
 void SetFlag(absl::Flag<T>* flag, const T& v) {
-  flag->Set(v);
+  flags_internal::FlagImplPeer::InvokeSet(*flag, v);
 }
 
 // Overload of `SetFlag()` to allow callers to pass in a value that is
@@ -201,7 +207,7 @@ void SetFlag(absl::Flag<T>* flag, const T& v) {
 template <typename T, typename V>
 void SetFlag(absl::Flag<T>* flag, const V& v) {
   T value(v);
-  flag->Set(value);
+  flags_internal::FlagImplPeer::InvokeSet(*flag, value);
 }
 
 // GetFlagReflectionHandle()
@@ -216,7 +222,7 @@ void SetFlag(absl::Flag<T>* flag, const V& v) {
 
 template <typename T>
 const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
-  return f.Reflect();
+  return flags_internal::FlagImplPeer::InvokeReflect(f);
 }
 
 ABSL_NAMESPACE_END
@@ -379,11 +385,12 @@ ABSL_NAMESPACE_END
 //
 // `default_value` is only used as a double check on the type. `explanation` is
 // unused.
-// TODO(rogeeff): Return an anonymous struct instead of bool, and place it into
-// the unnamed namespace.
-#define ABSL_RETIRED_FLAG(type, flagname, default_value, explanation) \
-  ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname =        \
-      ([] { return type(default_value); },                            \
-       absl::flags_internal::RetiredFlag<type>(#flagname))
+// TODO(rogeeff): replace RETIRED_FLAGS with FLAGS once forward declarations of
+// retired flags are cleaned up.
+#define ABSL_RETIRED_FLAG(type, name, default_value, explanation)      \
+  static absl::flags_internal::RetiredFlag<type> RETIRED_FLAGS_##name; \
+  ABSL_ATTRIBUTE_UNUSED static const auto RETIRED_FLAGS_REG_##name =   \
+      (RETIRED_FLAGS_##name.Retire(#name),                             \
+       ::absl::flags_internal::FlagRegistrarEmpty{})
 
 #endif  // ABSL_FLAGS_FLAG_H_
diff --git a/third_party/abseil_cpp/absl/flags/flag_benchmark.cc b/third_party/abseil_cpp/absl/flags/flag_benchmark.cc
index 7b52c9bc9f1c..9982b604b3b5 100644
--- a/third_party/abseil_cpp/absl/flags/flag_benchmark.cc
+++ b/third_party/abseil_cpp/absl/flags/flag_benchmark.cc
@@ -20,6 +20,8 @@
 
 #include "absl/flags/flag.h"
 #include "absl/flags/marshalling.h"
+#include "absl/flags/parse.h"
+#include "absl/flags/reflection.h"
 #include "absl/strings/string_view.h"
 #include "absl/time/time.h"
 #include "absl/types/optional.h"
@@ -103,6 +105,23 @@ std::string AbslUnparseFlag(const UDT&) { return ""; }
 
 BENCHMARKED_TYPES(FLAG_DEF)
 
+// Register thousands of flags to bloat up the size of the registry.
+// This mimics real life production binaries.
+#define DEFINE_FLAG_0(name) ABSL_FLAG(int, name, 0, "");
+#define DEFINE_FLAG_1(name) DEFINE_FLAG_0(name##0) DEFINE_FLAG_0(name##1)
+#define DEFINE_FLAG_2(name) DEFINE_FLAG_1(name##0) DEFINE_FLAG_1(name##1)
+#define DEFINE_FLAG_3(name) DEFINE_FLAG_2(name##0) DEFINE_FLAG_2(name##1)
+#define DEFINE_FLAG_4(name) DEFINE_FLAG_3(name##0) DEFINE_FLAG_3(name##1)
+#define DEFINE_FLAG_5(name) DEFINE_FLAG_4(name##0) DEFINE_FLAG_4(name##1)
+#define DEFINE_FLAG_6(name) DEFINE_FLAG_5(name##0) DEFINE_FLAG_5(name##1)
+#define DEFINE_FLAG_7(name) DEFINE_FLAG_6(name##0) DEFINE_FLAG_6(name##1)
+#define DEFINE_FLAG_8(name) DEFINE_FLAG_7(name##0) DEFINE_FLAG_7(name##1)
+#define DEFINE_FLAG_9(name) DEFINE_FLAG_8(name##0) DEFINE_FLAG_8(name##1)
+#define DEFINE_FLAG_10(name) DEFINE_FLAG_9(name##0) DEFINE_FLAG_9(name##1)
+#define DEFINE_FLAG_11(name) DEFINE_FLAG_10(name##0) DEFINE_FLAG_10(name##1)
+#define DEFINE_FLAG_12(name) DEFINE_FLAG_11(name##0) DEFINE_FLAG_11(name##1)
+DEFINE_FLAG_12(bloat_flag_);
+
 namespace {
 
 #define BM_GetFlag(T)                                            \
@@ -115,6 +134,20 @@ namespace {
 
 BENCHMARKED_TYPES(BM_GetFlag)
 
+void BM_ThreadedFindCommandLineFlag(benchmark::State& state) {
+  char dummy[] = "dummy";
+  char* argv[] = {dummy};
+  // We need to ensure that flags have been parsed. That is where the registry
+  // is finalized.
+  absl::ParseCommandLine(1, argv);
+
+  for (auto s : state) {
+    benchmark::DoNotOptimize(
+        absl::FindCommandLineFlag("bloat_flag_010101010101"));
+  }
+}
+BENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16);
+
 }  // namespace
 
 #define InvokeGetFlag(T)                                               \
diff --git a/third_party/abseil_cpp/absl/flags/flag_test.cc b/third_party/abseil_cpp/absl/flags/flag_test.cc
index 2eb2ba71d37c..654c8122215c 100644
--- a/third_party/abseil_cpp/absl/flags/flag_test.cc
+++ b/third_party/abseil_cpp/absl/flags/flag_test.cc
@@ -812,6 +812,17 @@ ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
 ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
 ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
 
+bool initializaion_order_fiasco_test = [] {
+  // Iterate over all the flags during static initialization.
+  // This should not trigger ASan's initialization-order-fiasco.
+  auto* handle1 = absl::FindCommandLineFlag("flag_on_separate_file");
+  auto* handle2 = absl::FindCommandLineFlag("retired_flag_on_separate_file");
+  if (handle1 != nullptr && handle2 != nullptr) {
+    return handle1->Name() == handle2->Name();
+  }
+  return true;
+}();
+
 namespace {
 
 TEST_F(FlagTest, TestRetiredFlagRegistration) {
diff --git a/third_party/abseil_cpp/absl/flags/flag_test_defs.cc b/third_party/abseil_cpp/absl/flags/flag_test_defs.cc
index 49f91dee3922..4e1693cdb9c4 100644
--- a/third_party/abseil_cpp/absl/flags/flag_test_defs.cc
+++ b/third_party/abseil_cpp/absl/flags/flag_test_defs.cc
@@ -20,5 +20,5 @@
 
 ABSL_FLAG(int, mistyped_int_flag, 0, "");
 ABSL_FLAG(std::string, mistyped_string_flag, "", "");
-ABSL_RETIRED_FLAG(bool, old_bool_flag, true,
-                  "repetition of retired flag definition");
+ABSL_FLAG(bool, flag_on_separate_file, false, "");
+ABSL_RETIRED_FLAG(bool, retired_flag_on_separate_file, false, "");
diff --git a/third_party/abseil_cpp/absl/flags/internal/commandlineflag.cc b/third_party/abseil_cpp/absl/flags/internal/commandlineflag.cc
new file mode 100644
index 000000000000..4482955c4cb6
--- /dev/null
+++ b/third_party/abseil_cpp/absl/flags/internal/commandlineflag.cc
@@ -0,0 +1,26 @@
+//
+// 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/commandlineflag.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+FlagStateInterface::~FlagStateInterface() {}
+
+}  // namespace flags_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
diff --git a/third_party/abseil_cpp/absl/flags/internal/flag.h b/third_party/abseil_cpp/absl/flags/internal/flag.h
index 2cc44e00f762..370d8a02ef04 100644
--- a/third_party/abseil_cpp/absl/flags/internal/flag.h
+++ b/third_party/abseil_cpp/absl/flags/internal/flag.h
@@ -482,7 +482,8 @@ class FlagImpl final : public CommandLineFlag {
   friend class FlagState;
 
   // Ensures that `data_guard_` is initialized and returns it.
-  absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED((absl::Mutex*)&data_guard_);
+  absl::Mutex* DataGuard() const
+      ABSL_LOCK_RETURNED(reinterpret_cast<absl::Mutex*>(data_guard_));
   // Returns heap allocated value of type T initialized with default value.
   std::unique_ptr<void, DynValueDeleter> MakeInitValue() const
       ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
@@ -631,20 +632,9 @@ class Flag {
   std::string CurrentValue() const { return impl_.CurrentValue(); }
 
  private:
-  template <typename U, bool do_register>
+  template <typename, bool>
   friend class FlagRegistrar;
-
-#if !defined(_MSC_VER) || defined(__clang__)
-  template <typename U>
-  friend U absl::GetFlag(const flags_internal::Flag<U>& flag);
-  template <typename U>
-  friend void absl::SetFlag(flags_internal::Flag<U>* flag, const U& v);
-  template <typename U, typename V>
-  friend void absl::SetFlag(flags_internal::Flag<U>* flag, const V& v);
-#else
-  template <typename U>
-  friend class absl::Flag;
-#endif
+  friend class FlagImplPeer;
 
   T Get() const {
     // See implementation notes in CommandLineFlag::Get().
@@ -667,10 +657,6 @@ class Flag {
     impl_.Write(&v);
   }
 
-  template <typename U>
-  friend const CommandLineFlag& absl::GetFlagReflectionHandle(
-      const absl::Flag<U>& f);
-
   // Access to the reflection.
   const CommandLineFlag& Reflect() const { return impl_; }
 
@@ -683,6 +669,25 @@ class Flag {
 };
 
 ///////////////////////////////////////////////////////////////////////////////
+// Trampoline for friend access
+
+class FlagImplPeer {
+ public:
+  template <typename T, typename FlagType>
+  static T InvokeGet(const FlagType& flag) {
+    return flag.Get();
+  }
+  template <typename FlagType, typename T>
+  static void InvokeSet(FlagType& flag, const T& v) {
+    flag.Set(v);
+  }
+  template <typename FlagType>
+  static const CommandLineFlag& InvokeReflect(const FlagType& f) {
+    return f.Reflect();
+  }
+};
+
+///////////////////////////////////////////////////////////////////////////////
 // Implementation of Flag value specific operations routine.
 template <typename T>
 void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
diff --git a/third_party/abseil_cpp/absl/flags/internal/registry.h b/third_party/abseil_cpp/absl/flags/internal/registry.h
index 6f5006a016fd..a8d9eb9cb0bb 100644
--- a/third_party/abseil_cpp/absl/flags/internal/registry.h
+++ b/third_party/abseil_cpp/absl/flags/internal/registry.h
@@ -30,9 +30,6 @@ namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-// Executes specified visitor for each non-retired flag in the registry.
-// Requires the caller hold the registry lock.
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor);
 // Executes specified visitor for each non-retired flag in the registry. While
 // callback are executed, the registry is locked and can't be changed.
 void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
@@ -41,6 +38,8 @@ void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
 
 bool RegisterCommandLineFlag(CommandLineFlag&);
 
+void FinalizeRegistry();
+
 //-----------------------------------------------------------------------------
 // Retired registrations:
 //
@@ -74,13 +73,22 @@ bool RegisterCommandLineFlag(CommandLineFlag&);
 //
 
 // Retire flag with name "name" and type indicated by ops.
-bool Retire(const char* name, FlagFastTypeId type_id);
+void Retire(const char* name, FlagFastTypeId type_id, char* buf);
+
+constexpr size_t kRetiredFlagObjSize = 3 * sizeof(void*);
+constexpr size_t kRetiredFlagObjAlignment = alignof(void*);
 
 // Registered a retired flag with name 'flag_name' and type 'T'.
 template <typename T>
-inline bool RetiredFlag(const char* flag_name) {
-  return flags_internal::Retire(flag_name, base_internal::FastTypeId<T>());
-}
+class RetiredFlag {
+ public:
+  void Retire(const char* flag_name) {
+    flags_internal::Retire(flag_name, base_internal::FastTypeId<T>(), buf_);
+  }
+
+ private:
+  alignas(kRetiredFlagObjAlignment) char buf_[kRetiredFlagObjSize];
+};
 
 }  // namespace flags_internal
 ABSL_NAMESPACE_END
diff --git a/third_party/abseil_cpp/absl/flags/internal/usage.cc b/third_party/abseil_cpp/absl/flags/internal/usage.cc
index 35b6427b6c83..f29d7c9b48f0 100644
--- a/third_party/abseil_cpp/absl/flags/internal/usage.cc
+++ b/third_party/abseil_cpp/absl/flags/internal/usage.cc
@@ -37,26 +37,26 @@
 #include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
 
-ABSL_FLAG(bool, help, false,
-          "show help on important flags for this binary [tip: all flags can "
-          "have two dashes]");
-ABSL_FLAG(bool, helpfull, false, "show help on all flags");
-ABSL_FLAG(bool, helpshort, false,
-          "show help on only the main module for this program");
-ABSL_FLAG(bool, helppackage, false,
-          "show help on all modules in the main package");
-ABSL_FLAG(bool, version, false, "show version and build info and exit");
-ABSL_FLAG(bool, only_check_args, false, "exit after checking all flags");
-ABSL_FLAG(std::string, helpon, "",
-          "show help on the modules named by this flag value");
-ABSL_FLAG(std::string, helpmatch, "",
-          "show help on modules whose name contains the specified substr");
+// Dummy global variables to prevent anyone else defining these.
+bool FLAGS_help = false;
+bool FLAGS_helpfull = false;
+bool FLAGS_helpshort = false;
+bool FLAGS_helppackage = false;
+bool FLAGS_version = false;
+bool FLAGS_only_check_args = false;
+bool FLAGS_helpon = false;
+bool FLAGS_helpmatch = false;
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 namespace {
 
+using PerFlagFilter = std::function<bool(const absl::CommandLineFlag&)>;
+
+// Maximum length size in a human readable format.
+constexpr size_t kHrfMaxLineLength = 80;
+
 // This class is used to emit an XML element with `tag` and `text`.
 // It adds opening and closing tags and escapes special characters in the text.
 // For example:
@@ -109,9 +109,12 @@ class FlagHelpPrettyPrinter {
  public:
   // Pretty printer holds on to the std::ostream& reference to direct an output
   // to that stream.
-  FlagHelpPrettyPrinter(int max_line_len, std::ostream& out)
+  FlagHelpPrettyPrinter(size_t max_line_len, size_t min_line_len,
+                        size_t wrapped_line_indent, std::ostream& out)
       : out_(out),
         max_line_len_(max_line_len),
+        min_line_len_(min_line_len),
+        wrapped_line_indent_(wrapped_line_indent),
         line_len_(0),
         first_line_(true) {}
 
@@ -145,7 +148,8 @@ class FlagHelpPrettyPrinter {
       }
 
       // Write the token, ending the string first if necessary/possible.
-      if (!new_line && (line_len_ + token.size() >= max_line_len_)) {
+      if (!new_line &&
+          (line_len_ + static_cast<int>(token.size()) >= max_line_len_)) {
         EndLine();
         new_line = true;
       }
@@ -164,13 +168,12 @@ class FlagHelpPrettyPrinter {
 
   void StartLine() {
     if (first_line_) {
-      out_ << "    ";
-      line_len_ = 4;
+      line_len_ = min_line_len_;
       first_line_ = false;
     } else {
-      out_ << "      ";
-      line_len_ = 6;
+      line_len_ = min_line_len_ + wrapped_line_indent_;
     }
+    out_ << std::string(line_len_, ' ');
   }
   void EndLine() {
     out_ << '\n';
@@ -179,13 +182,15 @@ class FlagHelpPrettyPrinter {
 
  private:
   std::ostream& out_;
-  const int max_line_len_;
-  int line_len_;
+  const size_t max_line_len_;
+  const size_t min_line_len_;
+  const size_t wrapped_line_indent_;
+  size_t line_len_;
   bool first_line_;
 };
 
 void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
-  FlagHelpPrettyPrinter printer(80, out);  // Max line length is 80.
+  FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 4, 2, out);
 
   // Flag name.
   printer.Write(absl::StrCat("--", flag.Name()));
@@ -221,7 +226,7 @@ void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
 // If a flag's help message has been stripped (e.g. by adding '#define
 // STRIP_FLAG_HELP 1' then this flag will not be displayed by '--help'
 // and its variants.
-void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
+void FlagsHelpImpl(std::ostream& out, PerFlagFilter filter_cb,
                    HelpFormat format, absl::string_view program_usage_message) {
   if (format == HelpFormat::kHumanReadable) {
     out << flags_internal::ShortProgramInvocationName() << ": "
@@ -250,8 +255,6 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
       matching_flags;
 
   flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) {
-    std::string flag_filename = flag.Filename();
-
     // Ignore retired flags.
     if (flag.IsRetired()) return;
 
@@ -259,7 +262,9 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
     if (flag.Help() == flags_internal::kStrippedFlagHelp) return;
 
     // Make sure flag satisfies the filter
-    if (!filter_cb || !filter_cb(flag_filename)) return;
+    if (!filter_cb(flag)) return;
+
+    std::string flag_filename = flag.Filename();
 
     matching_flags[std::string(flags_internal::Package(flag_filename))]
                   [flag_filename]
@@ -289,15 +294,34 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
   }
 
   if (format == HelpFormat::kHumanReadable) {
+    FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 0, 0, out);
+
     if (filter_cb && matching_flags.empty()) {
-      out << "  No modules matched: use -helpfull\n";
+      printer.Write("No flags matched.\n", true);
     }
+    printer.EndLine();
+    printer.Write(
+        "Try --helpfull to get a list of all flags or --help=substring "
+        "shows help for flags which include specified substring in either "
+        "in the name, or description or path.\n",
+        true);
   } else {
     // The end of the document.
     out << "</AllFlags>\n";
   }
 }
 
+void FlagsHelpImpl(std::ostream& out,
+                   flags_internal::FlagKindFilter filename_filter_cb,
+                   HelpFormat format, absl::string_view program_usage_message) {
+  FlagsHelpImpl(
+      out,
+      [&](const absl::CommandLineFlag& flag) {
+        return filename_filter_cb && filename_filter_cb(flag.Filename());
+      },
+      format, program_usage_message);
+}
+
 }  // namespace
 
 // --------------------------------------------------------------------
@@ -309,7 +333,7 @@ void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
 }
 
 // --------------------------------------------------------------------
-// Produces the help messages for all flags matching the filter.
+// Produces the help messages for all flags matching the filename filter.
 // If filter is empty produces help messages for all flags.
 void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,
                absl::string_view program_usage_message) {
@@ -324,66 +348,175 @@ void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,
 // If so, handles them appropriately.
 int HandleUsageFlags(std::ostream& out,
                      absl::string_view program_usage_message) {
-  if (absl::GetFlag(FLAGS_helpshort)) {
-    flags_internal::FlagsHelpImpl(
-        out, flags_internal::GetUsageConfig().contains_helpshort_flags,
-        HelpFormat::kHumanReadable, program_usage_message);
-    return 1;
-  }
+  switch (GetFlagsHelpMode()) {
+    case HelpMode::kNone:
+      break;
+    case HelpMode::kImportant:
+      flags_internal::FlagsHelpImpl(
+          out, flags_internal::GetUsageConfig().contains_help_flags,
+          GetFlagsHelpFormat(), program_usage_message);
+      return 1;
+
+    case HelpMode::kShort:
+      flags_internal::FlagsHelpImpl(
+          out, flags_internal::GetUsageConfig().contains_helpshort_flags,
+          GetFlagsHelpFormat(), program_usage_message);
+      return 1;
+
+    case HelpMode::kFull:
+      flags_internal::FlagsHelp(out, "", GetFlagsHelpFormat(),
+                                program_usage_message);
+      return 1;
+
+    case HelpMode::kPackage:
+      flags_internal::FlagsHelpImpl(
+          out, flags_internal::GetUsageConfig().contains_helppackage_flags,
+          GetFlagsHelpFormat(), program_usage_message);
+
+      return 1;
+
+    case HelpMode::kMatch: {
+      std::string substr = GetFlagsHelpMatchSubstr();
+      if (substr.empty()) {
+        // show all options
+        flags_internal::FlagsHelp(out, substr, GetFlagsHelpFormat(),
+                                  program_usage_message);
+      } else {
+        auto filter_cb = [&substr](const absl::CommandLineFlag& flag) {
+          if (absl::StrContains(flag.Name(), substr)) return true;
+          if (absl::StrContains(flag.Filename(), substr)) return true;
+          if (absl::StrContains(flag.Help(), substr)) return true;
+
+          return false;
+        };
+        flags_internal::FlagsHelpImpl(
+            out, filter_cb, HelpFormat::kHumanReadable, program_usage_message);
+      }
 
-  if (absl::GetFlag(FLAGS_helpfull)) {
-    // show all options
-    flags_internal::FlagsHelp(out, "", HelpFormat::kHumanReadable,
-                              program_usage_message);
-    return 1;
+      return 1;
+    }
+    case HelpMode::kVersion:
+      if (flags_internal::GetUsageConfig().version_string)
+        out << flags_internal::GetUsageConfig().version_string();
+      // Unlike help, we may be asking for version in a script, so return 0
+      return 0;
+
+    case HelpMode::kOnlyCheckArgs:
+      return 0;
   }
 
-  if (!absl::GetFlag(FLAGS_helpon).empty()) {
-    flags_internal::FlagsHelp(
-        out, absl::StrCat("/", absl::GetFlag(FLAGS_helpon), "."),
-        HelpFormat::kHumanReadable, program_usage_message);
-    return 1;
-  }
+  return -1;
+}
 
-  if (!absl::GetFlag(FLAGS_helpmatch).empty()) {
-    flags_internal::FlagsHelp(out, absl::GetFlag(FLAGS_helpmatch),
-                              HelpFormat::kHumanReadable,
-                              program_usage_message);
-    return 1;
-  }
+// --------------------------------------------------------------------
+// Globals representing usage reporting flags
+
+namespace {
+
+ABSL_CONST_INIT absl::Mutex help_attributes_guard(absl::kConstInit);
+ABSL_CONST_INIT std::string* match_substr
+    ABSL_GUARDED_BY(help_attributes_guard) = nullptr;
+ABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(help_attributes_guard) =
+    HelpMode::kNone;
+ABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(help_attributes_guard) =
+    HelpFormat::kHumanReadable;
+
+}  // namespace
 
-  if (absl::GetFlag(FLAGS_help)) {
-    flags_internal::FlagsHelpImpl(
-        out, flags_internal::GetUsageConfig().contains_help_flags,
-        HelpFormat::kHumanReadable, program_usage_message);
+std::string GetFlagsHelpMatchSubstr() {
+  absl::MutexLock l(&help_attributes_guard);
+  if (match_substr == nullptr) return "";
+  return *match_substr;
+}
 
-    out << "\nTry --helpfull to get a list of all flags.\n";
+void SetFlagsHelpMatchSubstr(absl::string_view substr) {
+  absl::MutexLock l(&help_attributes_guard);
+  if (match_substr == nullptr) match_substr = new std::string;
+  match_substr->assign(substr.data(), substr.size());
+}
 
-    return 1;
+HelpMode GetFlagsHelpMode() {
+  absl::MutexLock l(&help_attributes_guard);
+  // Refer to dummy variales to prevent linker dropping them
+  if (FLAGS_help || FLAGS_helpfull || FLAGS_helpshort || FLAGS_helppackage ||
+      FLAGS_version || FLAGS_only_check_args || FLAGS_helpon ||
+      FLAGS_helpmatch) {
+    help_mode = HelpMode::kNone;
   }
+  return help_mode;
+}
+
+void SetFlagsHelpMode(HelpMode mode) {
+  absl::MutexLock l(&help_attributes_guard);
+  help_mode = mode;
+}
 
-  if (absl::GetFlag(FLAGS_helppackage)) {
-    flags_internal::FlagsHelpImpl(
-        out, flags_internal::GetUsageConfig().contains_helppackage_flags,
-        HelpFormat::kHumanReadable, program_usage_message);
+HelpFormat GetFlagsHelpFormat() {
+  absl::MutexLock l(&help_attributes_guard);
+  return help_format;
+}
+
+void SetFlagsHelpFormat(HelpFormat format) {
+  absl::MutexLock l(&help_attributes_guard);
+  help_format = format;
+}
 
-    out << "\nTry --helpfull to get a list of all flags.\n";
+// Deduces usage flags from the input argument in a form --name=value or
+// --name. argument is already split into name and value before we call this
+// function.
+bool DeduceUsageFlags(absl::string_view name, absl::string_view value) {
+  if (absl::ConsumePrefix(&name, "help")) {
+    if (name == "") {
+      if (value.empty()) {
+        SetFlagsHelpMode(HelpMode::kImportant);
+      } else {
+        SetFlagsHelpMode(HelpMode::kMatch);
+        SetFlagsHelpMatchSubstr(value);
+      }
+      return true;
+    }
 
-    return 1;
+    if (name == "match") {
+      SetFlagsHelpMode(HelpMode::kMatch);
+      SetFlagsHelpMatchSubstr(value);
+      return true;
+    }
+
+    if (name == "on") {
+      SetFlagsHelpMode(HelpMode::kMatch);
+      SetFlagsHelpMatchSubstr(absl::StrCat("/", value, "."));
+      return true;
+    }
+
+    if (name == "full") {
+      SetFlagsHelpMode(HelpMode::kFull);
+      return true;
+    }
+
+    if (name == "short") {
+      SetFlagsHelpMode(HelpMode::kShort);
+      return true;
+    }
+
+    if (name == "package") {
+      SetFlagsHelpMode(HelpMode::kPackage);
+      return true;
+    }
+
+    return false;
   }
 
-  if (absl::GetFlag(FLAGS_version)) {
-    if (flags_internal::GetUsageConfig().version_string)
-      out << flags_internal::GetUsageConfig().version_string();
-    // Unlike help, we may be asking for version in a script, so return 0
-    return 0;
+  if (name == "version") {
+    SetFlagsHelpMode(HelpMode::kVersion);
+    return true;
   }
 
-  if (absl::GetFlag(FLAGS_only_check_args)) {
-    return 0;
+  if (name == "only_check_args") {
+    SetFlagsHelpMode(HelpMode::kOnlyCheckArgs);
+    return true;
   }
 
-  return -1;
+  return false;
 }
 
 }  // namespace flags_internal
diff --git a/third_party/abseil_cpp/absl/flags/internal/usage.h b/third_party/abseil_cpp/absl/flags/internal/usage.h
index 0c62dc4b2ac6..c0bcac57628a 100644
--- a/third_party/abseil_cpp/absl/flags/internal/usage.h
+++ b/third_party/abseil_cpp/absl/flags/internal/usage.h
@@ -36,7 +36,8 @@ enum class HelpFormat {
   kHumanReadable,
 };
 
-// Outputs the help message describing specific flag.
+// Streams the help message describing `flag` to `out`.
+// The default value for `flag` is included in the output.
 void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
               HelpFormat format = HelpFormat::kHumanReadable);
 
@@ -65,17 +66,39 @@ void FlagsHelp(std::ostream& out, absl::string_view filter,
 int HandleUsageFlags(std::ostream& out,
                      absl::string_view program_usage_message);
 
+// --------------------------------------------------------------------
+// Globals representing usage reporting flags
+
+enum class HelpMode {
+  kNone,
+  kImportant,
+  kShort,
+  kFull,
+  kPackage,
+  kMatch,
+  kVersion,
+  kOnlyCheckArgs
+};
+
+// Returns substring to filter help output (--help=substr argument)
+std::string GetFlagsHelpMatchSubstr();
+// Returns the requested help mode.
+HelpMode GetFlagsHelpMode();
+// Returns the requested help format.
+HelpFormat GetFlagsHelpFormat();
+
+// These are corresponding setters to the attributes above.
+void SetFlagsHelpMatchSubstr(absl::string_view);
+void SetFlagsHelpMode(HelpMode);
+void SetFlagsHelpFormat(HelpFormat);
+
+// Deduces usage flags from the input argument in a form --name=value or
+// --name. argument is already split into name and value before we call this
+// function.
+bool DeduceUsageFlags(absl::string_view name, absl::string_view value);
+
 }  // namespace flags_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
 
-ABSL_DECLARE_FLAG(bool, help);
-ABSL_DECLARE_FLAG(bool, helpfull);
-ABSL_DECLARE_FLAG(bool, helpshort);
-ABSL_DECLARE_FLAG(bool, helppackage);
-ABSL_DECLARE_FLAG(bool, version);
-ABSL_DECLARE_FLAG(bool, only_check_args);
-ABSL_DECLARE_FLAG(std::string, helpon);
-ABSL_DECLARE_FLAG(std::string, helpmatch);
-
 #endif  // ABSL_FLAGS_INTERNAL_USAGE_H_
diff --git a/third_party/abseil_cpp/absl/flags/internal/usage_test.cc b/third_party/abseil_cpp/absl/flags/internal/usage_test.cc
index 6e583fbe4b0e..b5c2487da577 100644
--- a/third_party/abseil_cpp/absl/flags/internal/usage_test.cc
+++ b/third_party/abseil_cpp/absl/flags/internal/usage_test.cc
@@ -87,6 +87,11 @@ class UsageReportingTest : public testing::Test {
     default_config.normalize_filename = &NormalizeFileName;
     absl::SetFlagsUsageConfig(default_config);
   }
+  ~UsageReportingTest() override {
+    flags::SetFlagsHelpMode(flags::HelpMode::kNone);
+    flags::SetFlagsHelpMatchSubstr("");
+    flags::SetFlagsHelpFormat(flags::HelpFormat::kHumanReadable);
+  }
 
  private:
   absl::FlagSaver flag_saver_;
@@ -191,6 +196,10 @@ TEST_F(UsageReportingTest, TestFlagsHelpHRF) {
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )";
 
   std::stringstream test_buf_01;
@@ -214,7 +223,11 @@ TEST_F(UsageReportingTest, TestFlagsHelpHRF) {
   EXPECT_EQ(test_buf_04.str(),
             R"(usage_test: Custom usage message
 
-  No modules matched: use -helpfull
+No flags matched.
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 
   std::stringstream test_buf_05;
@@ -226,12 +239,8 @@ TEST_F(UsageReportingTest, TestFlagsHelpHRF) {
       absl::StartsWith(test_out_str, "usage_test: Custom usage message"));
   EXPECT_TRUE(absl::StrContains(
       test_out_str, "Flags from absl/flags/internal/usage_test.cc:"));
-  EXPECT_TRUE(absl::StrContains(test_out_str,
-                                "Flags from absl/flags/internal/usage.cc:"));
   EXPECT_TRUE(
       absl::StrContains(test_out_str, "-usage_reporting_test_flag_01 "));
-  EXPECT_TRUE(absl::StrContains(test_out_str, "-help (show help"))
-      << test_out_str;
 }
 
 // --------------------------------------------------------------------
@@ -244,7 +253,40 @@ TEST_F(UsageReportingTest, TestNoUsageFlags) {
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_helpshort) {
-  absl::SetFlag(&FLAGS_helpshort, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kShort);
+
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+  EXPECT_EQ(test_buf.str(),
+            R"(usage_test: Custom usage message
+
+  Flags from absl/flags/internal/usage_test.cc:
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+      default: 101;
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+      default: false;
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+      default: 1.03;
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+      default: 1000000000000004;
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+      default: UDT{};
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+      Some more help.
+      Even more long long long long long long long long long long long long help
+      message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_help_simple) {
+  flags::SetFlagsHelpMode(flags::HelpMode::kImportant);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -267,13 +309,42 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpshort) {
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_help_one_flag) {
+  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+  flags::SetFlagsHelpMatchSubstr("usage_reporting_test_flag_06");
+
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+  EXPECT_EQ(test_buf.str(),
+            R"(usage_test: Custom usage message
+
+  Flags from absl/flags/internal/usage_test.cc:
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+      Some more help.
+      Even more long long long long long long long long long long long long help
+      message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }
 
 // --------------------------------------------------------------------
 
-TEST_F(UsageReportingTest, TestUsageFlag_help) {
-  absl::SetFlag(&FLAGS_help, true);
+TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) {
+  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+  flags::SetFlagsHelpMatchSubstr("test_flag");
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -297,14 +368,16 @@ TEST_F(UsageReportingTest, TestUsageFlag_help) {
       Even more long long long long long long long long long long long long help
       message.); default: "";
 
-Try --helpfull to get a list of all flags.
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }
 
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
-  absl::SetFlag(&FLAGS_helppackage, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kPackage);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -328,14 +401,16 @@ TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
       Even more long long long long long long long long long long long long help
       message.); default: "";
 
-Try --helpfull to get a list of all flags.
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }
 
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_version) {
-  absl::SetFlag(&FLAGS_version, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kVersion);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
@@ -349,7 +424,7 @@ TEST_F(UsageReportingTest, TestUsageFlag_version) {
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
-  absl::SetFlag(&FLAGS_only_check_args, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
@@ -359,17 +434,22 @@ TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_helpon) {
-  absl::SetFlag(&FLAGS_helpon, "bla-bla");
+  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+  flags::SetFlagsHelpMatchSubstr("/bla-bla.");
 
   std::stringstream test_buf_01;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), 1);
   EXPECT_EQ(test_buf_01.str(),
             R"(usage_test: Custom usage message
 
-  No modules matched: use -helpfull
+No flags matched.
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 
-  absl::SetFlag(&FLAGS_helpon, "usage_test");
+  flags::SetFlagsHelpMatchSubstr("/usage_test.");
 
   std::stringstream test_buf_02;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1);
@@ -392,6 +472,10 @@ TEST_F(UsageReportingTest, TestUsageFlag_helpon) {
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }
 
diff --git a/third_party/abseil_cpp/absl/flags/parse.cc b/third_party/abseil_cpp/absl/flags/parse.cc
index e2c88ff863ce..dd1a6796cabd 100644
--- a/third_party/abseil_cpp/absl/flags/parse.cc
+++ b/third_party/abseil_cpp/absl/flags/parse.cc
@@ -611,6 +611,11 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
                                         OnUndefinedFlag on_undef_flag) {
   ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
 
+  // Once parsing has started we will not have more flag registrations.
+  // If we did, they would be missing during parsing, which is a problem on
+  // itself.
+  flags_internal::FinalizeRegistry();
+
   // This routine does not return anything since we abort on failure.
   CheckDefaultValuesParsingRoundtrip();
 
@@ -708,6 +713,11 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
     std::tie(flag, is_negative) = LocateFlag(flag_name);
 
     if (flag == nullptr) {
+      // Usage flags are not modeled as Abseil flags. Locate them separately.
+      if (flags_internal::DeduceUsageFlags(flag_name, value)) {
+        continue;
+      }
+
       if (on_undef_flag != OnUndefinedFlag::kIgnoreUndefined) {
         undefined_flag_names.emplace_back(arg_from_argv,
                                           std::string(flag_name));
@@ -729,12 +739,13 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
     }
 
     // 100. Set the located flag to a new new value, unless it is retired.
-    // Setting retired flag fails, but we ignoring it here.
-    if (flag->IsRetired()) continue;
-
+    // Setting retired flag fails, but we ignoring it here while also reporting
+    // access to retired flag.
     std::string error;
     if (!flags_internal::PrivateHandleAccessor::ParseFrom(
             *flag, value, SET_FLAGS_VALUE, kCommandLine, error)) {
+      if (flag->IsRetired()) continue;
+
       flags_internal::ReportUsageError(error, true);
       success = false;
     } else {
diff --git a/third_party/abseil_cpp/absl/flags/parse_test.cc b/third_party/abseil_cpp/absl/flags/parse_test.cc
index d35a6e471abd..41bc0bc6b3a4 100644
--- a/third_party/abseil_cpp/absl/flags/parse_test.cc
+++ b/third_party/abseil_cpp/absl/flags/parse_test.cc
@@ -28,6 +28,7 @@
 #include "absl/flags/declare.h"
 #include "absl/flags/flag.h"
 #include "absl/flags/internal/parse.h"
+#include "absl/flags/internal/usage.h"
 #include "absl/flags/reflection.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
@@ -207,6 +208,9 @@ namespace flags = absl::flags_internal;
 using testing::ElementsAreArray;
 
 class ParseTest : public testing::Test {
+ public:
+  ~ParseTest() override { flags::SetFlagsHelpMode(flags::HelpMode::kNone); }
+
  private:
   absl::FlagSaver flag_saver_;
 };
@@ -851,7 +855,7 @@ TEST_F(ParseTest, TestIgnoreUndefinedFlags) {
 
 // --------------------------------------------------------------------
 
-TEST_F(ParseDeathTest, TestHelpFlagHandling) {
+TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {
   const char* in_args1[] = {
       "testbin",
       "--help",
@@ -870,11 +874,38 @@ TEST_F(ParseDeathTest, TestHelpFlagHandling) {
       flags::UsageFlagsAction::kIgnoreUsage,
       flags::OnUndefinedFlag::kAbortIfUndefined);
 
+  EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
 }
 
 // --------------------------------------------------------------------
 
+TEST_F(ParseDeathTest, TestSubstringHelpFlagHandling) {
+  const char* in_args1[] = {
+      "testbin",
+      "--help=abcd",
+  };
+
+  auto out_args1 = flags::ParseCommandLineImpl(
+      2, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs,
+      flags::UsageFlagsAction::kIgnoreUsage,
+      flags::OnUndefinedFlag::kAbortIfUndefined);
+
+  EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kMatch);
+  EXPECT_EQ(flags::GetFlagsHelpMatchSubstr(), "abcd");
+
+  const char* in_args2[] = {"testbin", "--help", "some_positional_arg"};
+
+  auto out_args2 = flags::ParseCommandLineImpl(
+      3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs,
+      flags::UsageFlagsAction::kIgnoreUsage,
+      flags::OnUndefinedFlag::kAbortIfUndefined);
+
+  EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
+}
+
+// --------------------------------------------------------------------
+
 TEST_F(ParseTest, WasPresentOnCommandLine) {
   const char* in_args1[] = {
       "testbin",        "arg1", "--bool_flag",
diff --git a/third_party/abseil_cpp/absl/flags/reflection.cc b/third_party/abseil_cpp/absl/flags/reflection.cc
index 5fc945f23767..c976d4679601 100644
--- a/third_party/abseil_cpp/absl/flags/reflection.cc
+++ b/third_party/abseil_cpp/absl/flags/reflection.cc
@@ -17,6 +17,7 @@
 
 #include <assert.h>
 
+#include <atomic>
 #include <map>
 #include <string>
 
@@ -56,25 +57,23 @@ class FlagRegistry {
 
   // Returns the flag object for the specified name, or nullptr if not found.
   // Will emit a warning if a 'retired' flag is specified.
-  CommandLineFlag* FindFlagLocked(absl::string_view name);
-
-  // Returns the retired flag object for the specified name, or nullptr if not
-  // found or not retired.  Does not emit a warning.
-  CommandLineFlag* FindRetiredFlagLocked(absl::string_view name);
+  CommandLineFlag* FindFlag(absl::string_view name);
 
   static FlagRegistry& GlobalRegistry();  // returns a singleton registry
 
  private:
   friend class flags_internal::FlagSaverImpl;  // reads all the flags in order
                                                // to copy them
-  friend void ForEachFlagUnlocked(
-      std::function<void(CommandLineFlag&)> visitor);
+  friend void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
+  friend void FinalizeRegistry();
 
-  // The map from name to flag, for FindFlagLocked().
+  // The map from name to flag, for FindFlag().
   using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
   using FlagIterator = FlagMap::iterator;
   using FlagConstIterator = FlagMap::const_iterator;
   FlagMap flags_;
+  std::vector<CommandLineFlag*> flat_flags_;
+  std::atomic<bool> finalized_flags_{false};
 
   absl::Mutex lock_;
 
@@ -83,29 +82,6 @@ class FlagRegistry {
   FlagRegistry& operator=(const FlagRegistry&);
 };
 
-CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) {
-  FlagConstIterator i = flags_.find(name);
-  if (i == flags_.end()) {
-    return nullptr;
-  }
-
-  if (i->second->IsRetired()) {
-    flags_internal::ReportUsageError(
-        absl::StrCat("Accessing retired flag '", name, "'"), false);
-  }
-
-  return i->second;
-}
-
-CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) {
-  FlagConstIterator i = flags_.find(name);
-  if (i == flags_.end() || !i->second->IsRetired()) {
-    return nullptr;
-  }
-
-  return i->second;
-}
-
 namespace {
 
 class FlagRegistryLock {
@@ -117,12 +93,26 @@ class FlagRegistryLock {
   FlagRegistry& fr_;
 };
 
-void DestroyRetiredFlag(CommandLineFlag& flag);
-
 }  // namespace
 
+CommandLineFlag* FlagRegistry::FindFlag(absl::string_view name) {
+  if (finalized_flags_.load(std::memory_order_acquire)) {
+    // We could save some gcus here if we make `Name()` be non-virtual.
+    // We could move the `const char*` name to the base class.
+    auto it = std::partition_point(
+        flat_flags_.begin(), flat_flags_.end(),
+        [=](CommandLineFlag* f) { return f->Name() < name; });
+    if (it != flat_flags_.end() && (*it)->Name() == name) return *it;
+  }
+
+  FlagRegistryLock frl(*this);
+  auto it = flags_.find(name);
+  return it != flags_.end() ? it->second : nullptr;
+}
+
 void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
   FlagRegistryLock registry_lock(*this);
+
   std::pair<FlagIterator, bool> ins =
       flags_.insert(FlagMap::value_type(flag.Name(), &flag));
   if (ins.second == false) {  // means the name was already in the map
@@ -143,8 +133,6 @@ void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
                        old_flag.Filename(), "' and '", flag.Filename(), "'."),
           true);
     } else if (old_flag.IsRetired()) {
-      // Retired flag can just be deleted.
-      DestroyRetiredFlag(flag);
       return;
     } else if (old_flag.Filename() != flag.Filename()) {
       flags_internal::ReportUsageError(
@@ -155,7 +143,7 @@ void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
     } else {
       flags_internal::ReportUsageError(
           absl::StrCat(
-              "Something wrong with flag '", flag.Name(), "' in file '",
+              "Something is wrong with flag '", flag.Name(), "' in file '",
               flag.Filename(), "'. One possibility: file '", flag.Filename(),
               "' is being linked both statically and dynamically into this "
               "executable. e.g. some files listed as srcs to a test and also "
@@ -174,18 +162,15 @@ FlagRegistry& FlagRegistry::GlobalRegistry() {
 
 // --------------------------------------------------------------------
 
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor) {
+void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {
   FlagRegistry& registry = FlagRegistry::GlobalRegistry();
-  for (FlagRegistry::FlagConstIterator i = registry.flags_.begin();
-       i != registry.flags_.end(); ++i) {
-    visitor(*i->second);
+
+  if (registry.finalized_flags_.load(std::memory_order_acquire)) {
+    for (const auto& i : registry.flat_flags_) visitor(*i);
   }
-}
 
-void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {
-  FlagRegistry& registry = FlagRegistry::GlobalRegistry();
   FlagRegistryLock frl(registry);
-  ForEachFlagUnlocked(visitor);
+  for (const auto& i : registry.flags_) visitor(*i.second);
 }
 
 // --------------------------------------------------------------------
@@ -195,6 +180,21 @@ bool RegisterCommandLineFlag(CommandLineFlag& flag) {
   return true;
 }
 
+void FinalizeRegistry() {
+  auto& registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  if (registry.finalized_flags_.load(std::memory_order_relaxed)) {
+    // Was already finalized. Ignore the second time.
+    return;
+  }
+  registry.flat_flags_.reserve(registry.flags_.size());
+  for (const auto& f : registry.flags_) {
+    registry.flat_flags_.push_back(f.second);
+  }
+  registry.flags_.clear();
+  registry.finalized_flags_.store(true, std::memory_order_release);
+}
+
 // --------------------------------------------------------------------
 
 namespace {
@@ -206,16 +206,34 @@ class RetiredFlagObj final : public CommandLineFlag {
 
  private:
   absl::string_view Name() const override { return name_; }
-  std::string Filename() const override { return "RETIRED"; }
+  std::string Filename() const override {
+    OnAccess();
+    return "RETIRED";
+  }
   FlagFastTypeId TypeId() const override { return type_id_; }
-  std::string Help() const override { return ""; }
+  std::string Help() const override {
+    OnAccess();
+    return "";
+  }
   bool IsRetired() const override { return true; }
-  bool IsSpecifiedOnCommandLine() const override { return false; }
-  std::string DefaultValue() const override { return ""; }
-  std::string CurrentValue() const override { return ""; }
+  bool IsSpecifiedOnCommandLine() const override {
+    OnAccess();
+    return false;
+  }
+  std::string DefaultValue() const override {
+    OnAccess();
+    return "";
+  }
+  std::string CurrentValue() const override {
+    OnAccess();
+    return "";
+  }
 
   // Any input is valid
-  bool ValidateInputValue(absl::string_view) const override { return true; }
+  bool ValidateInputValue(absl::string_view) const override {
+    OnAccess();
+    return true;
+  }
 
   std::unique_ptr<flags_internal::FlagStateInterface> SaveState() override {
     return nullptr;
@@ -223,29 +241,32 @@ class RetiredFlagObj final : public CommandLineFlag {
 
   bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode,
                  flags_internal::ValueSource, std::string&) override {
+    OnAccess();
     return false;
   }
 
-  void CheckDefaultValueParsingRoundtrip() const override {}
+  void CheckDefaultValueParsingRoundtrip() const override { OnAccess(); }
+
+  void Read(void*) const override { OnAccess(); }
 
-  void Read(void*) const override {}
+  void OnAccess() const {
+    flags_internal::ReportUsageError(
+        absl::StrCat("Accessing retired flag '", name_, "'"), false);
+  }
 
   // Data members
   const char* const name_;
   const FlagFastTypeId type_id_;
 };
 
-void DestroyRetiredFlag(CommandLineFlag& flag) {
-  assert(flag.IsRetired());
-  delete static_cast<RetiredFlagObj*>(&flag);
-}
-
 }  // namespace
 
-bool Retire(const char* name, FlagFastTypeId type_id) {
-  auto* flag = new flags_internal::RetiredFlagObj(name, type_id);
+void Retire(const char* name, FlagFastTypeId type_id, char* buf) {
+  static_assert(sizeof(RetiredFlagObj) == kRetiredFlagObjSize, "");
+  static_assert(alignof(RetiredFlagObj) == kRetiredFlagObjAlignment, "");
+  auto* flag = ::new (static_cast<void*>(buf))
+      flags_internal::RetiredFlagObj(name, type_id);
   FlagRegistry::GlobalRegistry().RegisterFlag(*flag);
-  return true;
 }
 
 // --------------------------------------------------------------------
@@ -299,9 +320,17 @@ CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
   if (name.empty()) return nullptr;
   flags_internal::FlagRegistry& registry =
       flags_internal::FlagRegistry::GlobalRegistry();
-  flags_internal::FlagRegistryLock frl(registry);
+  return registry.FindFlag(name);
+}
+
+// --------------------------------------------------------------------
 
-  return registry.FindFlagLocked(name);
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags() {
+  absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> res;
+  flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+    if (!flag.IsRetired()) res.insert({flag.Name(), &flag});
+  });
+  return res;
 }
 
 ABSL_NAMESPACE_END
diff --git a/third_party/abseil_cpp/absl/flags/reflection.h b/third_party/abseil_cpp/absl/flags/reflection.h
index 045f9784e269..e6baf5de4b0c 100644
--- a/third_party/abseil_cpp/absl/flags/reflection.h
+++ b/third_party/abseil_cpp/absl/flags/reflection.h
@@ -26,6 +26,7 @@
 #include <string>
 
 #include "absl/base/config.h"
+#include "absl/container/flat_hash_map.h"
 #include "absl/flags/commandlineflag.h"
 #include "absl/flags/internal/commandlineflag.h"
 
@@ -40,7 +41,11 @@ class FlagSaverImpl;
 // Returns the reflection handle of an Abseil flag of the specified name, or
 // `nullptr` if not found. This function will emit a warning if the name of a
 // 'retired' flag is specified.
-CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+absl::CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+
+// Returns current state of the Flags registry in a form of mapping from flag
+// name to a flag reflection handle.
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags();
 
 //------------------------------------------------------------------------------
 // FlagSaver
@@ -59,7 +64,7 @@ CommandLineFlag* FindCommandLineFlag(absl::string_view name);
 //   void MyFunc() {
 //    absl::FlagSaver fs;
 //    ...
-//    absl::SetFlag(FLAGS_myFlag, otherValue);
+//    absl::SetFlag(&FLAGS_myFlag, otherValue);
 //    ...
 //  } // scope of FlagSaver left, flags return to previous state
 //
diff --git a/third_party/abseil_cpp/absl/flags/reflection_test.cc b/third_party/abseil_cpp/absl/flags/reflection_test.cc
index 9781e597dbd9..4c80900956a9 100644
--- a/third_party/abseil_cpp/absl/flags/reflection_test.cc
+++ b/third_party/abseil_cpp/absl/flags/reflection_test.cc
@@ -18,11 +18,15 @@
 #include <memory>
 #include <string>
 
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include "absl/flags/declare.h"
 #include "absl/flags/flag.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/marshalling.h"
 #include "absl/memory/memory.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
 
 ABSL_FLAG(int, int_flag, 1, "int_flag help");
 ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
@@ -57,4 +61,207 @@ TEST_F(ReflectionTest, TestFindCommandLineFlag) {
   EXPECT_NE(handle, nullptr);
 }
 
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestGetAllFlags) {
+  auto all_flags = absl::GetAllFlags();
+  EXPECT_NE(all_flags.find("int_flag"), all_flags.end());
+  EXPECT_EQ(all_flags.find("bool_retired_flag"), all_flags.end());
+  EXPECT_EQ(all_flags.find("some_undefined_flag"), all_flags.end());
+
+  std::vector<absl::string_view> flag_names_first_attempt;
+  auto all_flags_1 = absl::GetAllFlags();
+  for (auto f : all_flags_1) {
+    flag_names_first_attempt.push_back(f.first);
+  }
+
+  std::vector<absl::string_view> flag_names_second_attempt;
+  auto all_flags_2 = absl::GetAllFlags();
+  for (auto f : all_flags_2) {
+    flag_names_second_attempt.push_back(f.first);
+  }
+
+  EXPECT_THAT(flag_names_first_attempt,
+              ::testing::UnorderedElementsAreArray(flag_names_second_attempt));
+}
+
+// --------------------------------------------------------------------
+
+struct CustomUDT {
+  CustomUDT() : a(1), b(1) {}
+  CustomUDT(int a_, int b_) : a(a_), b(b_) {}
+
+  friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
+    return f1.a == f2.a && f1.b == f2.b;
+  }
+
+  int a;
+  int b;
+};
+bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
+  std::vector<absl::string_view> parts =
+      absl::StrSplit(in, ':', absl::SkipWhitespace());
+
+  if (parts.size() != 2) return false;
+
+  if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
+
+  if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
+
+  return true;
+}
+std::string AbslUnparseFlag(const CustomUDT& f) {
+  return absl::StrCat(f.a, ":", f.b);
+}
+
+}  // namespace
+
+// --------------------------------------------------------------------
+
+ABSL_FLAG(bool, test_flag_01, true, "");
+ABSL_FLAG(int, test_flag_02, 1234, "");
+ABSL_FLAG(int16_t, test_flag_03, -34, "");
+ABSL_FLAG(uint16_t, test_flag_04, 189, "");
+ABSL_FLAG(int32_t, test_flag_05, 10765, "");
+ABSL_FLAG(uint32_t, test_flag_06, 40000, "");
+ABSL_FLAG(int64_t, test_flag_07, -1234567, "");
+ABSL_FLAG(uint64_t, test_flag_08, 9876543, "");
+ABSL_FLAG(double, test_flag_09, -9.876e-50, "");
+ABSL_FLAG(float, test_flag_10, 1.234e12f, "");
+ABSL_FLAG(std::string, test_flag_11, "", "");
+ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "");
+static int counter = 0;
+ABSL_FLAG(int, test_flag_13, 200, "").OnUpdate([]() { counter++; });
+ABSL_FLAG(CustomUDT, test_flag_14, {}, "");
+
+namespace {
+
+TEST_F(ReflectionTest, TestFlagSaverInScope) {
+  {
+    absl::FlagSaver s;
+    counter = 0;
+    absl::SetFlag(&FLAGS_test_flag_01, false);
+    absl::SetFlag(&FLAGS_test_flag_02, -1021);
+    absl::SetFlag(&FLAGS_test_flag_03, 6009);
+    absl::SetFlag(&FLAGS_test_flag_04, 44);
+    absl::SetFlag(&FLAGS_test_flag_05, +800);
+    absl::SetFlag(&FLAGS_test_flag_06, -40978756);
+    absl::SetFlag(&FLAGS_test_flag_07, 23405);
+    absl::SetFlag(&FLAGS_test_flag_08, 975310);
+    absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
+    absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
+    absl::SetFlag(&FLAGS_test_flag_11, "asdf");
+    absl::SetFlag(&FLAGS_test_flag_12, absl::Hours(20));
+    absl::SetFlag(&FLAGS_test_flag_13, 4);
+    absl::SetFlag(&FLAGS_test_flag_14, CustomUDT{-1, -2});
+  }
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});
+  EXPECT_EQ(counter, 2);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestFlagSaverVsUpdateViaReflection) {
+  {
+    absl::FlagSaver s;
+    counter = 0;
+    std::string error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_01")->ParseFrom("false", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_02")->ParseFrom("-4536", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_03")->ParseFrom("111", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_04")->ParseFrom("909", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_05")->ParseFrom("-2004", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_06")->ParseFrom("1000023", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_07")->ParseFrom("69305", &error))
+        << error;
+    EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_08")
+                    ->ParseFrom("1000000001", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_09")->ParseFrom("2.09021", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_10")->ParseFrom("-33.1", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_11")->ParseFrom("ADD_FOO", &error))
+        << error;
+    EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_12")
+                    ->ParseFrom("3h11m16s", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_13")->ParseFrom("0", &error))
+        << error;
+    EXPECT_TRUE(
+        absl::FindCommandLineFlag("test_flag_14")->ParseFrom("10:1", &error))
+        << error;
+  }
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});
+  EXPECT_EQ(counter, 2);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestMultipleFlagSaversInEnclosedScopes) {
+  {
+    absl::FlagSaver s;
+    absl::SetFlag(&FLAGS_test_flag_08, 10);
+    EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);
+    {
+      absl::FlagSaver s;
+      absl::SetFlag(&FLAGS_test_flag_08, 20);
+      EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);
+      {
+        absl::FlagSaver s;
+        absl::SetFlag(&FLAGS_test_flag_08, -200);
+        EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), -200);
+      }
+      EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);
+    }
+    EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);
+  }
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
+}
+
 }  // namespace