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

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

Change-Id: I59864a0053f6e03d88cc9d5e2a92757039a05484
git-subtree-dir: third_party/abseil
git-subtree-split: 384af0e9141283172e2bff3210dae79fb7130d9c
diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc
index 53e2b84..4482955 100644
--- a/absl/flags/internal/commandlineflag.cc
+++ b/absl/flags/internal/commandlineflag.cc
@@ -1,5 +1,5 @@
 //
-// Copyright 2019 The Abseil Authors.
+// Copyright 2020 The Abseil Authors.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -15,380 +15,12 @@
 
 #include "absl/flags/internal/commandlineflag.h"
 
-#include <cassert>
-
-#include "absl/base/internal/raw_logging.h"
-#include "absl/base/optimization.h"
-#include "absl/flags/config.h"
-#include "absl/flags/usage_config.h"
-#include "absl/strings/str_cat.h"
-#include "absl/synchronization/mutex.h"
-
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-// The help message indicating that the commandline flag has been
-// 'stripped'. It will not show up when doing "-help" and its
-// variants. The flag is stripped if ABSL_FLAGS_STRIP_HELP is set to 1
-// before including absl/flags/flag.h
-
-// This is used by this file, and also in commandlineflags_reporting.cc
-const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
-
-namespace {
-
-// Currently we only validate flag values for user-defined flag types.
-bool ShouldValidateFlagValue(const CommandLineFlag& flag) {
-#define DONT_VALIDATE(T) \
-  if (flag.IsOfType<T>()) return false;
-  ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(DONT_VALIDATE)
-  DONT_VALIDATE(std::string)
-  DONT_VALIDATE(std::vector<std::string>)
-#undef DONT_VALIDATE
-
-  return true;
-}
-
-}  // namespace
-
-absl::Mutex* InitFlag(CommandLineFlag* flag) {
-  ABSL_CONST_INIT static absl::Mutex init_lock(absl::kConstInit);
-  absl::Mutex* mu;
-
-  {
-    absl::MutexLock lock(&init_lock);
-
-    if (flag->locks_ == nullptr) {  // Must initialize Mutexes for this flag.
-      flag->locks_ = new flags_internal::CommandLineFlagLocks;
-    }
-
-    mu = &flag->locks_->primary_mu;
-  }
-
-  {
-    absl::MutexLock lock(mu);
-
-    if (!flag->IsRetired() && flag->def_ == nullptr) {
-      // Need to initialize def and cur fields.
-      flag->def_ = (*flag->make_init_value_)();
-      flag->cur_ = Clone(flag->op_, flag->def_);
-      UpdateCopy(flag);
-      flag->inited_.store(true, std::memory_order_release);
-      flag->InvokeCallback();
-    }
-  }
-
-  flag->inited_.store(true, std::memory_order_release);
-  return mu;
-}
-
-// Ensure that the lazily initialized fields of *flag have been initialized,
-// and return &flag->locks_->primary_mu.
-absl::Mutex* CommandLineFlag::InitFlagIfNecessary() const
-    ABSL_LOCK_RETURNED(locks_->primary_mu) {
-  if (!inited_.load(std::memory_order_acquire)) {
-    return InitFlag(const_cast<CommandLineFlag*>(this));
-  }
-
-  // All fields initialized; locks_ is therefore safe to read.
-  return &locks_->primary_mu;
-}
-
-bool CommandLineFlag::IsModified() const {
-  absl::MutexLock l(InitFlagIfNecessary());
-  return modified_;
-}
-
-void CommandLineFlag::SetModified(bool is_modified) {
-  absl::MutexLock l(InitFlagIfNecessary());
-  modified_ = is_modified;
-}
-
-bool CommandLineFlag::IsSpecifiedOnCommandLine() const {
-  absl::MutexLock l(InitFlagIfNecessary());
-  return on_command_line_;
-}
-
-absl::string_view CommandLineFlag::Typename() const {
-  // We do not store/report type in Abseil Flags, so that user do not rely on in
-  // at runtime
-  if (IsAbseilFlag() || IsRetired()) return "";
-
-#define HANDLE_V1_BUILTIN_TYPE(t) \
-  if (IsOfType<t>()) {            \
-    return #t;                    \
-  }
-
-  HANDLE_V1_BUILTIN_TYPE(bool);
-  HANDLE_V1_BUILTIN_TYPE(int32_t);
-  HANDLE_V1_BUILTIN_TYPE(int64_t);
-  HANDLE_V1_BUILTIN_TYPE(uint64_t);
-  HANDLE_V1_BUILTIN_TYPE(double);
-#undef HANDLE_V1_BUILTIN_TYPE
-
-  if (IsOfType<std::string>()) {
-    return "string";
-  }
-
-  return "";
-}
-
-std::string CommandLineFlag::Filename() const {
-  return flags_internal::GetUsageConfig().normalize_filename(filename_);
-}
-
-std::string CommandLineFlag::DefaultValue() const {
-  absl::MutexLock l(InitFlagIfNecessary());
-
-  return Unparse(marshalling_op_, def_);
-}
-
-std::string CommandLineFlag::CurrentValue() const {
-  absl::MutexLock l(InitFlagIfNecessary());
-
-  return Unparse(marshalling_op_, cur_);
-}
-
-// Attempts to parse supplied `value` string using parsing routine in the `flag`
-// argument. If parsing is successful, it will try to validate that the parsed
-// value is valid for the specified 'flag'. Finally this function stores the
-// parsed value in 'dst' assuming it is a pointer to the flag's value type. In
-// case if any error is encountered in either step, the error message is stored
-// in 'err'
-bool TryParseLocked(CommandLineFlag* flag, void* dst, absl::string_view value,
-                    std::string* err)
-    ABSL_EXCLUSIVE_LOCKS_REQUIRED(flag->locks_->primary_mu) {
-  void* tentative_value = Clone(flag->op_, flag->def_);
-  std::string parse_err;
-  if (!Parse(flag->marshalling_op_, value, tentative_value, &parse_err)) {
-    auto type_name = flag->Typename();
-    absl::string_view err_sep = parse_err.empty() ? "" : "; ";
-    absl::string_view typename_sep = type_name.empty() ? "" : " ";
-    *err = absl::StrCat("Illegal value '", value, "' specified for",
-                        typename_sep, type_name, " flag '", flag->Name(), "'",
-                        err_sep, parse_err);
-    Delete(flag->op_, tentative_value);
-    return false;
-  }
-
-  if (!flag->InvokeValidator(tentative_value)) {
-    *err = absl::StrCat("Failed validation of new value '",
-                        Unparse(flag->marshalling_op_, tentative_value),
-                        "' for flag '", flag->Name(), "'");
-    Delete(flag->op_, tentative_value);
-    return false;
-  }
-
-  flag->counter_++;
-  Copy(flag->op_, tentative_value, dst);
-  Delete(flag->op_, tentative_value);
-  return true;
-}
-
-// Sets the value of the flag based on specified string `value`. If the flag
-// was successfully set to new value, it returns true. Otherwise, sets `err`
-// to indicate the error, leaves the flag unchanged, and returns false. There
-// are three ways to set the flag's value:
-//  * Update the current flag value
-//  * Update the flag's default value
-//  * Update the current flag value if it was never set before
-// The mode is selected based on 'set_mode' parameter.
-bool CommandLineFlag::SetFromString(absl::string_view value,
-                                    FlagSettingMode set_mode,
-                                    ValueSource source, std::string* err) {
-  if (IsRetired()) return false;
-
-  absl::MutexLock l(InitFlagIfNecessary());
-
-  // Direct-access flags can be modified without going through the
-  // flag API. Detect such changes and update the flag->modified_ bit.
-  if (!IsAbseilFlag()) {
-    if (!modified_ && ChangedDirectly(this, cur_, def_)) {
-      modified_ = true;
-    }
-  }
-
-  switch (set_mode) {
-    case SET_FLAGS_VALUE: {
-      // set or modify the flag's value
-      if (!TryParseLocked(this, cur_, value, err)) return false;
-      modified_ = true;
-      UpdateCopy(this);
-      InvokeCallback();
-
-      if (source == kCommandLine) {
-        on_command_line_ = true;
-      }
-      break;
-    }
-    case SET_FLAG_IF_DEFAULT: {
-      // set the flag's value, but only if it hasn't been set by someone else
-      if (!modified_) {
-        if (!TryParseLocked(this, cur_, value, err)) return false;
-        modified_ = true;
-        UpdateCopy(this);
-        InvokeCallback();
-      } else {
-        // TODO(rogeeff): review and fix this semantic. Currently we do not fail
-        // in this case if flag is modified. This is misleading since the flag's
-        // value is not updated even though we return true.
-        // *err = absl::StrCat(Name(), " is already set to ",
-        //                     CurrentValue(), "\n");
-        // return false;
-        return true;
-      }
-      break;
-    }
-    case SET_FLAGS_DEFAULT: {
-      // modify the flag's default-value
-      if (!TryParseLocked(this, def_, value, err)) return false;
-
-      if (!modified_) {
-        // Need to set both defvalue *and* current, in this case
-        Copy(op_, def_, cur_);
-        UpdateCopy(this);
-        InvokeCallback();
-      }
-      break;
-    }
-    default: {
-      // unknown set_mode
-      assert(false);
-      return false;
-    }
-  }
-
-  return true;
-}
-
-void CommandLineFlag::CheckDefaultValueParsingRoundtrip() const {
-  std::string v = DefaultValue();
-
-  absl::MutexLock lock(InitFlagIfNecessary());
-
-  void* dst = Clone(op_, def_);
-  std::string error;
-  if (!flags_internal::Parse(marshalling_op_, v, dst, &error)) {
-    ABSL_INTERNAL_LOG(
-        FATAL,
-        absl::StrCat("Flag ", Name(), " (from ", Filename(),
-                     "): std::string form of default value '", v,
-                     "' could not be parsed; error=", error));
-  }
-
-  // We do not compare dst to def since parsing/unparsing may make
-  // small changes, e.g., precision loss for floating point types.
-  Delete(op_, dst);
-}
-
-bool CommandLineFlag::ValidateDefaultValue() const {
-  absl::MutexLock lock(InitFlagIfNecessary());
-  return InvokeValidator(def_);
-}
-
-bool CommandLineFlag::ValidateInputValue(absl::string_view value) const {
-  absl::MutexLock l(InitFlagIfNecessary());  // protect default value access
-
-  void* obj = Clone(op_, def_);
-  std::string ignored_error;
-  const bool result =
-      flags_internal::Parse(marshalling_op_, value, obj, &ignored_error) &&
-      InvokeValidator(obj);
-  Delete(op_, obj);
-  return result;
-}
-
-void CommandLineFlag::Read(void* dst,
-                           const flags_internal::FlagOpFn dst_op) const {
-  absl::ReaderMutexLock l(InitFlagIfNecessary());
-
-  // `dst_op` is the unmarshaling operation corresponding to the declaration
-  // visibile at the call site. `op` is the Flag's defined unmarshalling
-  // operation. They must match for this operation to be well-defined.
-  if (ABSL_PREDICT_FALSE(dst_op != op_)) {
-    ABSL_INTERNAL_LOG(
-        ERROR,
-        absl::StrCat("Flag '", Name(),
-                     "' is defined as one type and declared as another"));
-  }
-  CopyConstruct(op_, cur_, dst);
-}
-
-void CommandLineFlag::Write(const void* src,
-                            const flags_internal::FlagOpFn src_op) {
-  absl::MutexLock l(InitFlagIfNecessary());
-
-  // `src_op` is the marshalling operation corresponding to the declaration
-  // visible at the call site. `op` is the Flag's defined marshalling operation.
-  // They must match for this operation to be well-defined.
-  if (ABSL_PREDICT_FALSE(src_op != op_)) {
-    ABSL_INTERNAL_LOG(
-        ERROR,
-        absl::StrCat("Flag '", Name(),
-                     "' is defined as one type and declared as another"));
-  }
-
-  if (ShouldValidateFlagValue(*this)) {
-    void* obj = Clone(op_, src);
-    std::string ignored_error;
-    std::string src_as_str = Unparse(marshalling_op_, src);
-    if (!Parse(marshalling_op_, src_as_str, obj, &ignored_error) ||
-        !InvokeValidator(obj)) {
-      ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(),
-                                            "' to invalid value ", src_as_str));
-    }
-    Delete(op_, obj);
-  }
-
-  modified_ = true;
-  counter_++;
-  Copy(op_, src, cur_);
-
-  UpdateCopy(this);
-  InvokeCallback();
-}
-
-std::string HelpText::GetHelpText() const {
-  if (help_function_) return help_function_();
-  if (help_message_) return help_message_;
-
-  return {};
-}
-
-// Update any copy of the flag value that is stored in an atomic word.
-// In addition if flag has a mutation callback this function invokes it.
-void UpdateCopy(CommandLineFlag* flag) {
-#define STORE_ATOMIC(T)           \
-  else if (flag->IsOfType<T>()) { \
-    flag->StoreAtomic();          \
-  }
-
-  if (false) {
-  }
-  ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(STORE_ATOMIC)
-#undef STORE_ATOMIC
-}
-
-// Return true iff flag value was changed via direct-access.
-bool ChangedDirectly(CommandLineFlag* flag, const void* a, const void* b) {
-  if (!flag->IsAbseilFlag()) {
-// Need to compare values for direct-access flags.
-#define CHANGED_FOR_TYPE(T)                                                  \
-  if (flag->IsOfType<T>()) {                                                 \
-    return *reinterpret_cast<const T*>(a) != *reinterpret_cast<const T*>(b); \
-  }
-
-    CHANGED_FOR_TYPE(bool);
-    CHANGED_FOR_TYPE(int32_t);
-    CHANGED_FOR_TYPE(int64_t);
-    CHANGED_FOR_TYPE(uint64_t);
-    CHANGED_FOR_TYPE(double);
-    CHANGED_FOR_TYPE(std::string);
-#undef CHANGED_FOR_TYPE
-  }
-
-  return false;
-}
+FlagStateInterface::~FlagStateInterface() {}
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h
index 284286b..ebfe81b 100644
--- a/absl/flags/internal/commandlineflag.h
+++ b/absl/flags/internal/commandlineflag.h
@@ -16,29 +16,19 @@
 #ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
 #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
 
-#include <atomic>
-
-#include "absl/base/macros.h"
-#include "absl/flags/marshalling.h"
-#include "absl/synchronization/mutex.h"
-#include "absl/types/optional.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-// Type-specific operations, eg., parsing, copying, etc. are provided
-// by function specific to that type with a signature matching FlagOpFn.
-enum FlagOp {
-  kDelete,
-  kClone,
-  kCopy,
-  kCopyConstruct,
-  kSizeof,
-  kParse,
-  kUnparse
-};
-using FlagOpFn = void* (*)(FlagOp, const void*, void*);
-using FlagMarshallingOpFn = void* (*)(FlagOp, const void*, void*, void*);
+// An alias for flag fast type id. This value identifies the flag value type
+// similarly to typeid(T), without relying on RTTI being available. In most
+// cases this id is enough to uniquely identify the flag's value type. In a few
+// cases we'll have to resort to using actual RTTI implementation if it is
+// available.
+using FlagFastTypeId = absl::base_internal::FastTypeIdType;
 
 // Options that control SetCommandLineOptionWithMode.
 enum FlagSettingMode {
@@ -53,7 +43,7 @@
   SET_FLAGS_DEFAULT
 };
 
-// Options that control SetFromString: Source of a value.
+// Options that control ParseFrom: Source of a value.
 enum ValueSource {
   // Flag is being set by value specified on a command line.
   kCommandLine,
@@ -61,309 +51,18 @@
   kProgrammaticChange,
 };
 
-// Signature for the help generation function used as an argument for the
-// absl::Flag constructor.
-using HelpGenFunc = std::string (*)();
-
-// Signature for the function generating the initial flag value based (usually
-// based on default value supplied in flag's definition)
-using InitialValGenFunc = void* (*)();
-
-extern const char kStrippedFlagHelp[];
-
-// The per-type function
-template <typename T>
-void* FlagOps(FlagOp op, const void* v1, void* v2) {
-  switch (op) {
-    case kDelete:
-      delete static_cast<const T*>(v1);
-      return nullptr;
-    case kClone:
-      return new T(*static_cast<const T*>(v1));
-    case kCopy:
-      *static_cast<T*>(v2) = *static_cast<const T*>(v1);
-      return nullptr;
-    case kCopyConstruct:
-      new (v2) T(*static_cast<const T*>(v1));
-      return nullptr;
-    case kSizeof:
-      return reinterpret_cast<void*>(sizeof(T));
-    default:
-      return nullptr;
-  }
-}
-
-template <typename T>
-void* FlagMarshallingOps(FlagOp op, const void* v1, void* v2, void* v3) {
-  switch (op) {
-    case kParse: {
-      // initialize the temporary instance of type T based on current value in
-      // destination (which is going to be flag's default value).
-      T temp(*static_cast<T*>(v2));
-      if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp,
-                              static_cast<std::string*>(v3))) {
-        return nullptr;
-      }
-      *static_cast<T*>(v2) = std::move(temp);
-      return v2;
-    }
-    case kUnparse:
-      *static_cast<std::string*>(v2) =
-          absl::UnparseFlag<T>(*static_cast<const T*>(v1));
-      return nullptr;
-    default:
-      return nullptr;
-  }
-}
-
-// Functions that invoke flag-type-specific operations.
-inline void Delete(FlagOpFn op, const void* obj) {
-  op(flags_internal::kDelete, obj, nullptr);
-}
-
-inline void* Clone(FlagOpFn op, const void* obj) {
-  return op(flags_internal::kClone, obj, nullptr);
-}
-
-inline void Copy(FlagOpFn op, const void* src, void* dst) {
-  op(flags_internal::kCopy, src, dst);
-}
-
-inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
-  op(flags_internal::kCopyConstruct, src, dst);
-}
-
-inline bool Parse(FlagMarshallingOpFn op, absl::string_view text, void* dst,
-                  std::string* error) {
-  return op(flags_internal::kParse, &text, dst, error) != nullptr;
-}
-
-inline std::string Unparse(FlagMarshallingOpFn op, const void* val) {
-  std::string result;
-  op(flags_internal::kUnparse, val, &result, nullptr);
-  return result;
-}
-
-inline size_t Sizeof(FlagOpFn op) {
-  // This sequence of casts reverses the sequence from base::internal::FlagOps()
-  return static_cast<size_t>(reinterpret_cast<intptr_t>(
-      op(flags_internal::kSizeof, nullptr, nullptr)));
-}
-
-// The following struct contains the locks in a CommandLineFlag struct.
-// They are in a separate struct that is lazily allocated to avoid problems
-// with static initialization and to avoid multiple allocations.
-struct CommandLineFlagLocks {
-  absl::Mutex primary_mu;   // protects several fields in CommandLineFlag
-  absl::Mutex callback_mu;  // used to serialize callbacks
-};
-
-// Holds either a pointer to help text or a function which produces it.  This is
-// needed for supporting both static initialization of Flags while supporting
-// the legacy registration framework.  We can't use absl::variant<const char*,
-// const char*(*)()> since anybody passing 0 or nullptr in to a CommandLineFlag
-// would find an ambiguity.
-class HelpText {
+// Handle to FlagState objects. Specific flag state objects will restore state
+// of a flag produced this flag state from method CommandLineFlag::SaveState().
+class FlagStateInterface {
  public:
-  static constexpr HelpText FromFunctionPointer(const HelpGenFunc fn) {
-    return HelpText(fn, nullptr);
-  }
-  static constexpr HelpText FromStaticCString(const char* msg) {
-    return HelpText(nullptr, msg);
-  }
+  virtual ~FlagStateInterface();
 
-  std::string GetHelpText() const;
-
-  HelpText() = delete;
-  HelpText(const HelpText&) = default;
-  HelpText(HelpText&&) = default;
-
- private:
-  explicit constexpr HelpText(const HelpGenFunc fn, const char* msg)
-      : help_function_(fn), help_message_(msg) {}
-
-  HelpGenFunc help_function_;
-  const char* help_message_;
+  // Restores the flag originated this object to the saved state.
+  virtual void Restore() const = 0;
 };
 
-// Holds all information for a flag.
-class CommandLineFlag {
- public:
-  constexpr CommandLineFlag(
-      const char* name, HelpText help_text, const char* filename,
-      const flags_internal::FlagOpFn op,
-      const flags_internal::FlagMarshallingOpFn marshalling_op,
-      const flags_internal::InitialValGenFunc initial_value_gen, void* def,
-      void* cur)
-      : name_(name),
-        help_(help_text),
-        filename_(filename),
-        op_(op),
-        marshalling_op_(marshalling_op),
-        make_init_value_(initial_value_gen),
-        inited_(false),
-        modified_(false),
-        on_command_line_(false),
-        def_(def),
-        cur_(cur),
-        counter_(0),
-        locks_(nullptr) {}
-
-  // Virtual destructor
-  virtual void Destroy() const = 0;
-
-  // Not copyable/assignable.
-  CommandLineFlag(const CommandLineFlag&) = delete;
-  CommandLineFlag& operator=(const CommandLineFlag&) = delete;
-
-  // Access methods.
-
-  // Returns true iff this object corresponds to retired flag
-  virtual bool IsRetired() const { return false; }
-  // Returns true iff this is a handle to an Abseil Flag.
-  virtual bool IsAbseilFlag() const { return true; }
-
-  absl::string_view Name() const { return name_; }
-  std::string Help() const { return help_.GetHelpText(); }
-  bool IsModified() const;
-  void SetModified(bool is_modified);
-  bool IsSpecifiedOnCommandLine() const;
-
-  absl::string_view Typename() const;
-  std::string Filename() const;
-  std::string DefaultValue() const;
-  std::string CurrentValue() const;
-
-  // Interface to store the value in atomic if one used. This is short term
-  // interface. To be reworked once cur_ is moved.
-  virtual void StoreAtomic() {}
-
-  // Interfaces to operate on validators.
-  virtual bool HasValidatorFn() const { return false; }
-  virtual bool InvokeValidator(const void* /*value*/) const { return true; }
-  // Invoke the flag validators for old flags.
-  // TODO(rogeeff): implement proper validators for Abseil Flags
-  bool ValidateDefaultValue() const;
-  bool ValidateInputValue(absl::string_view value) const;
-
-  // Return true iff flag has type T.
-  template <typename T>
-  inline bool IsOfType() const {
-    return op_ == &flags_internal::FlagOps<T>;
-  }
-
-  // Attempts to retrieve the flag value. Returns value on success,
-  // absl::nullopt otherwise.
-  template <typename T>
-  absl::optional<T> Get() const {
-    if (IsRetired() || flags_internal::FlagOps<T> != op_) return absl::nullopt;
-
-    T res;
-    Read(&res, flags_internal::FlagOps<T>);
-
-    return res;
-  }
-
-  // Interfaces to overate on callbacks.
-  virtual void InvokeCallback() {}
-
-  // Sets the value of the flag based on specified std::string `value`. If the flag
-  // was successfully set to new value, it returns true. Otherwise, sets `error`
-  // to indicate the error, leaves the flag unchanged, and returns false. There
-  // are three ways to set the flag's value:
-  //  * Update the current flag value
-  //  * Update the flag's default value
-  //  * Update the current flag value if it was never set before
-  // The mode is selected based on `set_mode` parameter.
-  bool SetFromString(absl::string_view value,
-                     flags_internal::FlagSettingMode set_mode,
-                     flags_internal::ValueSource source, std::string* error);
-
-  void CheckDefaultValueParsingRoundtrip() const;
-
-  // Constant configuration for a particular flag.
- protected:
-  ~CommandLineFlag() = default;
-
-  const char* const name_;
-  const HelpText help_;
-  const char* const filename_;
-
-  const FlagOpFn op_;                         // Type-specific handler
-  const FlagMarshallingOpFn marshalling_op_;  // Marshalling ops handler
-  const InitialValGenFunc make_init_value_;  // Makes initial value for the flag
-  std::atomic<bool> inited_;  // fields have been lazily initialized
-
-  // Mutable state (guarded by locks_->primary_mu).
-  bool modified_;         // Has flag value been modified?
-  bool on_command_line_;  // Specified on command line.
-  void* def_;             // Lazily initialized pointer to default value
-  void* cur_;             // Lazily initialized pointer to current value
-  int64_t counter_;         // Mutation counter
-
-  // Lazily initialized mutexes for this flag value.  We cannot inline a
-  // SpinLock or Mutex here because those have non-constexpr constructors and
-  // so would prevent constant initialization of this type.
-  // TODO(rogeeff): fix it once Mutex has constexpr constructor
-  struct CommandLineFlagLocks* locks_;  // locks, laziliy allocated.
-
-  // Ensure that the lazily initialized fields of *flag have been initialized,
-  // and return the lock which should be locked when flag's state is mutated.
-  absl::Mutex* InitFlagIfNecessary() const ABSL_LOCK_RETURNED(locks_->primary_mu);
-
-  // copy construct new value of flag's type in a memory referenced by dst
-  // based on current flag's value
-  void Read(void* dst, const flags_internal::FlagOpFn dst_op) const;
-  // updates flag's value to *src (locked)
-  void Write(const void* src, const flags_internal::FlagOpFn src_op);
-
-  friend class FlagRegistry;
-  friend class FlagPtrMap;
-  friend class FlagSaverImpl;
-  friend bool TryParseLocked(CommandLineFlag* flag, void* dst,
-                             absl::string_view value, std::string* err);
-  friend absl::Mutex* InitFlag(CommandLineFlag* flag);
-
-  // This is a short term, until we completely rework persistent state
-  // storage API.
-  virtual void* GetValidator() const { return nullptr; }
-  virtual bool SetValidator(void*) { return false; }
-};
-
-// Update any copy of the flag value that is stored in an atomic word.
-// In addition if flag has a mutation callback this function invokes it. While
-// callback is being invoked the primary flag's mutex is unlocked and it is
-// re-locked back after call to callback is completed. Callback invocation is
-// guarded by flag's secondary mutex instead which prevents concurrent callback
-// invocation. Note that it is possible for other thread to grab the primary
-// lock and update flag's value at any time during the callback invocation.
-// This is by design. Callback can get a value of the flag if necessary, but it
-// might be different from the value initiated the callback and it also can be
-// different by the time the callback invocation is completed.
-// Requires that *primary_lock be held in exclusive mode; it may be released
-// and reacquired by the implementation.
-void UpdateCopy(CommandLineFlag* flag);
-// Return true iff flag value was changed via direct-access.
-bool ChangedDirectly(CommandLineFlag* flag, const void* a, const void* b);
-
-// This macro is the "source of truth" for the list of supported flag types we
-// expect to perform lock free operations on. Specifically it generates code,
-// a one argument macro operating on a type, supplied as a macro argument, for
-// each type in the list.
-#define ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(A) \
-  A(bool)                                         \
-  A(short)                                        \
-  A(unsigned short)                               \
-  A(int)                                          \
-  A(unsigned int)                                 \
-  A(long)                                         \
-  A(unsigned long)                                \
-  A(long long)                                    \
-  A(unsigned long long)                           \
-  A(double)                                       \
-  A(float)
-
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
diff --git a/absl/flags/internal/commandlineflag_test.cc b/absl/flags/internal/commandlineflag_test.cc
deleted file mode 100644
index 5a0c271..0000000
--- a/absl/flags/internal/commandlineflag_test.cc
+++ /dev/null
@@ -1,218 +0,0 @@
-//
-//  Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/flags/internal/commandlineflag.h"
-
-#include <algorithm>
-#include <string>
-
-#include "gtest/gtest.h"
-#include "absl/flags/flag.h"
-#include "absl/flags/internal/registry.h"
-#include "absl/flags/usage_config.h"
-#include "absl/memory/memory.h"
-#include "absl/strings/match.h"
-#include "absl/strings/str_cat.h"
-
-ABSL_FLAG(int, int_flag, 201, "int_flag help");
-ABSL_FLAG(std::string, string_flag, "dflt",
-          absl::StrCat("string_flag", " help"));
-ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
-
-namespace {
-
-namespace flags = absl::flags_internal;
-
-class CommandLineFlagTest : public testing::Test {
- protected:
-  static void SetUpTestSuite() {
-    // Install a function to normalize filenames before this test is run.
-    absl::FlagsUsageConfig default_config;
-    default_config.normalize_filename = &CommandLineFlagTest::NormalizeFileName;
-    absl::SetFlagsUsageConfig(default_config);
-  }
-
-  void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); }
-  void TearDown() override { flag_saver_.reset(); }
-
- private:
-  static std::string NormalizeFileName(absl::string_view fname) {
-#ifdef _WIN32
-    std::string normalized(fname);
-    std::replace(normalized.begin(), normalized.end(), '\\', '/');
-    fname = normalized;
-#endif
-    return std::string(fname);
-  }
-
-  std::unique_ptr<flags::FlagSaver> flag_saver_;
-};
-
-TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
-
-  ASSERT_TRUE(flag_01);
-  EXPECT_EQ(flag_01->Name(), "int_flag");
-  EXPECT_EQ(flag_01->Help(), "int_flag help");
-  EXPECT_EQ(flag_01->Typename(), "");
-  EXPECT_TRUE(!flag_01->IsRetired());
-  EXPECT_TRUE(flag_01->IsOfType<int>());
-  EXPECT_TRUE(
-      absl::EndsWith(flag_01->Filename(),
-                     "absl/flags/internal/commandlineflag_test.cc"))
-      << flag_01->Filename();
-
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
-
-  ASSERT_TRUE(flag_02);
-  EXPECT_EQ(flag_02->Name(), "string_flag");
-  EXPECT_EQ(flag_02->Help(), "string_flag help");
-  EXPECT_EQ(flag_02->Typename(), "");
-  EXPECT_TRUE(!flag_02->IsRetired());
-  EXPECT_TRUE(flag_02->IsOfType<std::string>());
-  EXPECT_TRUE(
-      absl::EndsWith(flag_02->Filename(),
-                     "absl/flags/internal/commandlineflag_test.cc"))
-      << flag_02->Filename();
-
-  auto* flag_03 = flags::FindRetiredFlag("bool_retired_flag");
-
-  ASSERT_TRUE(flag_03);
-  EXPECT_EQ(flag_03->Name(), "bool_retired_flag");
-  EXPECT_EQ(flag_03->Help(), "");
-  EXPECT_EQ(flag_03->Typename(), "");
-  EXPECT_TRUE(flag_03->IsRetired());
-  EXPECT_TRUE(flag_03->IsOfType<bool>());
-  EXPECT_EQ(flag_03->Filename(), "RETIRED");
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
-  absl::SetFlag(&FLAGS_int_flag, 301);
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
-
-  ASSERT_TRUE(flag_01);
-  EXPECT_EQ(flag_01->CurrentValue(), "301");
-  EXPECT_EQ(flag_01->DefaultValue(), "201");
-
-  absl::SetFlag(&FLAGS_string_flag, "new_str_value");
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
-
-  ASSERT_TRUE(flag_02);
-  EXPECT_EQ(flag_02->CurrentValue(), "new_str_value");
-  EXPECT_EQ(flag_02->DefaultValue(), "dflt");
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(CommandLineFlagTest, TestSetFromStringCurrentValue) {
-  std::string err;
-
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(flag_01->SetFromString("11", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(flag_01->SetFromString("-123", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(!flag_01->SetFromString("xyz", flags::SET_FLAGS_VALUE,
-                                      flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
-  EXPECT_EQ(err, "Illegal value 'xyz' specified for flag 'int_flag'");
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(!flag_01->SetFromString("A1", flags::SET_FLAGS_VALUE,
-                                      flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
-  EXPECT_EQ(err, "Illegal value 'A1' specified for flag 'int_flag'");
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(flag_01->SetFromString("0x10", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);
-  EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(flag_01->SetFromString("011", flags::SET_FLAGS_VALUE,
-                                     flags::kCommandLine, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
-  EXPECT_TRUE(flag_01->IsSpecifiedOnCommandLine());
-
-  EXPECT_TRUE(!flag_01->SetFromString("", flags::SET_FLAGS_VALUE,
-                                      flags::kProgrammaticChange, &err));
-  EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'");
-
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
-  EXPECT_TRUE(flag_02->SetFromString("xyz", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz");
-
-  EXPECT_TRUE(flag_02->SetFromString("", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(CommandLineFlagTest, TestSetFromStringDefaultValue) {
-  std::string err;
-
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
-
-  EXPECT_TRUE(flag_01->SetFromString("111", flags::SET_FLAGS_DEFAULT,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(flag_01->DefaultValue(), "111");
-
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
-
-  EXPECT_TRUE(flag_02->SetFromString("abc", flags::SET_FLAGS_DEFAULT,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(flag_02->DefaultValue(), "abc");
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(CommandLineFlagTest, TestSetFromStringIfDefault) {
-  std::string err;
-
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
-
-  EXPECT_TRUE(flag_01->SetFromString("22", flags::SET_FLAG_IF_DEFAULT,
-                                     flags::kProgrammaticChange, &err))
-      << err;
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
-
-  EXPECT_TRUE(flag_01->SetFromString("33", flags::SET_FLAG_IF_DEFAULT,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
-  // EXPECT_EQ(err, "ERROR: int_flag is already set to 22");
-
-  // Reset back to default value
-  EXPECT_TRUE(flag_01->SetFromString("201", flags::SET_FLAGS_VALUE,
-                                     flags::kProgrammaticChange, &err));
-
-  EXPECT_TRUE(flag_01->SetFromString("33", flags::SET_FLAG_IF_DEFAULT,
-                                     flags::kProgrammaticChange, &err));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201);
-  // EXPECT_EQ(err, "ERROR: int_flag is already set to 201");
-}
-
-}  // namespace
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc
index 0f40358..f83c1fe 100644
--- a/absl/flags/internal/flag.cc
+++ b/absl/flags/internal/flag.cc
@@ -15,37 +15,567 @@
 
 #include "absl/flags/internal/flag.h"
 
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <array>
+#include <atomic>
+#include <memory>
+#include <new>
+#include <string>
+#include <typeinfo>
+
+#include "absl/base/call_once.h"
+#include "absl/base/casts.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/flags/config.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/usage_config.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-// If the flag has a mutation callback this function invokes it. While the
-// callback is being invoked the primary flag's mutex is unlocked and it is
-// re-locked back after call to callback is completed. Callback invocation is
-// guarded by flag's secondary mutex instead which prevents concurrent
-// callback invocation. Note that it is possible for other thread to grab the
-// primary lock and update flag's value at any time during the callback
-// invocation. This is by design. Callback can get a value of the flag if
-// necessary, but it might be different from the value initiated the callback
-// and it also can be different by the time the callback invocation is
-// completed. Requires that *primary_lock be held in exclusive mode; it may be
-// released and reacquired by the implementation.
-void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu,
-                    FlagCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(primary_mu) {
-  if (!cb) return;
+// The help message indicating that the commandline flag has been
+// 'stripped'. It will not show up when doing "-help" and its
+// variants. The flag is stripped if ABSL_FLAGS_STRIP_HELP is set to 1
+// before including absl/flags/flag.h
+const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
 
-  // When executing the callback we need the primary flag's mutex to be
-  // unlocked so that callback can retrieve the flag's value.
-  primary_mu->Unlock();
+namespace {
 
-  {
-    absl::MutexLock lock(callback_mu);
-    cb();
+// Currently we only validate flag values for user-defined flag types.
+bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {
+#define DONT_VALIDATE(T, _) \
+  if (flag_type_id == base_internal::FastTypeId<T>()) return false;
+  ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(DONT_VALIDATE)
+#undef DONT_VALIDATE
+
+  return true;
+}
+
+// RAII helper used to temporarily unlock and relock `absl::Mutex`.
+// This is used when we need to ensure that locks are released while
+// invoking user supplied callbacks and then reacquired, since callbacks may
+// need to acquire these locks themselves.
+class MutexRelock {
+ public:
+  explicit MutexRelock(absl::Mutex& mu) : mu_(mu) { mu_.Unlock(); }
+  ~MutexRelock() { mu_.Lock(); }
+
+  MutexRelock(const MutexRelock&) = delete;
+  MutexRelock& operator=(const MutexRelock&) = delete;
+
+ private:
+  absl::Mutex& mu_;
+};
+
+}  // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// Persistent state of the flag data.
+
+class FlagImpl;
+
+class FlagState : public flags_internal::FlagStateInterface {
+ public:
+  template <typename V>
+  FlagState(FlagImpl& flag_impl, const V& v, bool modified,
+            bool on_command_line, int64_t counter)
+      : flag_impl_(flag_impl),
+        value_(v),
+        modified_(modified),
+        on_command_line_(on_command_line),
+        counter_(counter) {}
+
+  ~FlagState() override {
+    if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer &&
+        flag_impl_.ValueStorageKind() != FlagValueStorageKind::kSequenceLocked)
+      return;
+    flags_internal::Delete(flag_impl_.op_, value_.heap_allocated);
   }
 
-  primary_mu->Lock();
+ private:
+  friend class FlagImpl;
+
+  // Restores the flag to the saved state.
+  void Restore() const override {
+    if (!flag_impl_.RestoreState(*this)) return;
+
+    ABSL_INTERNAL_LOG(INFO,
+                      absl::StrCat("Restore saved value of ", flag_impl_.Name(),
+                                   " to: ", flag_impl_.CurrentValue()));
+  }
+
+  // Flag and saved flag data.
+  FlagImpl& flag_impl_;
+  union SavedValue {
+    explicit SavedValue(void* v) : heap_allocated(v) {}
+    explicit SavedValue(int64_t v) : one_word(v) {}
+
+    void* heap_allocated;
+    int64_t one_word;
+  } value_;
+  bool modified_;
+  bool on_command_line_;
+  int64_t counter_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag implementation, which does not depend on flag value type.
+
+DynValueDeleter::DynValueDeleter(FlagOpFn op_arg) : op(op_arg) {}
+
+void DynValueDeleter::operator()(void* ptr) const {
+  if (op == nullptr) return;
+
+  Delete(op, ptr);
+}
+
+void FlagImpl::Init() {
+  new (&data_guard_) absl::Mutex;
+
+  auto def_kind = static_cast<FlagDefaultKind>(def_kind_);
+
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer:
+      // For this storage kind the default_value_ always points to gen_func
+      // during initialization.
+      assert(def_kind == FlagDefaultKind::kGenFunc);
+      (*default_value_.gen_func)(AlignedBufferValue());
+      break;
+    case FlagValueStorageKind::kOneWordAtomic: {
+      alignas(int64_t) std::array<char, sizeof(int64_t)> buf{};
+      if (def_kind == FlagDefaultKind::kGenFunc) {
+        (*default_value_.gen_func)(buf.data());
+      } else {
+        assert(def_kind != FlagDefaultKind::kDynamicValue);
+        std::memcpy(buf.data(), &default_value_, Sizeof(op_));
+      }
+      OneWordValue().store(absl::bit_cast<int64_t>(buf),
+                           std::memory_order_release);
+      break;
+    }
+    case FlagValueStorageKind::kSequenceLocked: {
+      // For this storage kind the default_value_ always points to gen_func
+      // during initialization.
+      assert(def_kind == FlagDefaultKind::kGenFunc);
+      (*default_value_.gen_func)(AtomicBufferValue());
+      break;
+    }
+  }
+  seq_lock_.MarkInitialized();
+}
+
+absl::Mutex* FlagImpl::DataGuard() const {
+  absl::call_once(const_cast<FlagImpl*>(this)->init_control_, &FlagImpl::Init,
+                  const_cast<FlagImpl*>(this));
+
+  // data_guard_ is initialized inside Init.
+  return reinterpret_cast<absl::Mutex*>(&data_guard_);
+}
+
+void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id,
+                               const std::type_info* (*gen_rtti)()) const {
+  FlagFastTypeId lhs_type_id = flags_internal::FastTypeId(op_);
+
+  // `rhs_type_id` is the fast type id corresponding to the declaration
+  // visibile at the call site. `lhs_type_id` is the fast type id
+  // corresponding to the type specified in flag definition. They must match
+  //  for this operation to be well-defined.
+  if (ABSL_PREDICT_TRUE(lhs_type_id == rhs_type_id)) return;
+
+  const std::type_info* lhs_runtime_type_id =
+      flags_internal::RuntimeTypeId(op_);
+  const std::type_info* rhs_runtime_type_id = (*gen_rtti)();
+
+  if (lhs_runtime_type_id == rhs_runtime_type_id) return;
+
+#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI)
+  if (*lhs_runtime_type_id == *rhs_runtime_type_id) return;
+#endif
+
+  ABSL_INTERNAL_LOG(
+      FATAL, absl::StrCat("Flag '", Name(),
+                          "' is defined as one type and declared as another"));
+}
+
+std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const {
+  void* res = nullptr;
+  switch (DefaultKind()) {
+    case FlagDefaultKind::kDynamicValue:
+      res = flags_internal::Clone(op_, default_value_.dynamic_value);
+      break;
+    case FlagDefaultKind::kGenFunc:
+      res = flags_internal::Alloc(op_);
+      (*default_value_.gen_func)(res);
+      break;
+    default:
+      res = flags_internal::Clone(op_, &default_value_);
+      break;
+  }
+  return {res, DynValueDeleter{op_}};
+}
+
+void FlagImpl::StoreValue(const void* src) {
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer:
+      Copy(op_, src, AlignedBufferValue());
+      seq_lock_.IncrementModificationCount();
+      break;
+    case FlagValueStorageKind::kOneWordAtomic: {
+      int64_t one_word_val = 0;
+      std::memcpy(&one_word_val, src, Sizeof(op_));
+      OneWordValue().store(one_word_val, std::memory_order_release);
+      seq_lock_.IncrementModificationCount();
+      break;
+    }
+    case FlagValueStorageKind::kSequenceLocked: {
+      seq_lock_.Write(AtomicBufferValue(), src, Sizeof(op_));
+      break;
+    }
+  }
+  modified_ = true;
+  InvokeCallback();
+}
+
+absl::string_view FlagImpl::Name() const { return name_; }
+
+std::string FlagImpl::Filename() const {
+  return flags_internal::GetUsageConfig().normalize_filename(filename_);
+}
+
+std::string FlagImpl::Help() const {
+  return HelpSourceKind() == FlagHelpKind::kLiteral ? help_.literal
+                                                    : help_.gen_func();
+}
+
+FlagFastTypeId FlagImpl::TypeId() const {
+  return flags_internal::FastTypeId(op_);
+}
+
+int64_t FlagImpl::ModificationCount() const {
+  return seq_lock_.ModificationCount();
+}
+
+bool FlagImpl::IsSpecifiedOnCommandLine() const {
+  absl::MutexLock l(DataGuard());
+  return on_command_line_;
+}
+
+std::string FlagImpl::DefaultValue() const {
+  absl::MutexLock l(DataGuard());
+
+  auto obj = MakeInitValue();
+  return flags_internal::Unparse(op_, obj.get());
+}
+
+std::string FlagImpl::CurrentValue() const {
+  auto* guard = DataGuard();  // Make sure flag initialized
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer: {
+      absl::MutexLock l(guard);
+      return flags_internal::Unparse(op_, AlignedBufferValue());
+    }
+    case FlagValueStorageKind::kOneWordAtomic: {
+      const auto one_word_val =
+          absl::bit_cast<std::array<char, sizeof(int64_t)>>(
+              OneWordValue().load(std::memory_order_acquire));
+      return flags_internal::Unparse(op_, one_word_val.data());
+    }
+    case FlagValueStorageKind::kSequenceLocked: {
+      std::unique_ptr<void, DynValueDeleter> cloned(flags_internal::Alloc(op_),
+                                                    DynValueDeleter{op_});
+      ReadSequenceLockedData(cloned.get());
+      return flags_internal::Unparse(op_, cloned.get());
+    }
+  }
+
+  return "";
+}
+
+void FlagImpl::SetCallback(const FlagCallbackFunc mutation_callback) {
+  absl::MutexLock l(DataGuard());
+
+  if (callback_ == nullptr) {
+    callback_ = new FlagCallback;
+  }
+  callback_->func = mutation_callback;
+
+  InvokeCallback();
+}
+
+void FlagImpl::InvokeCallback() const {
+  if (!callback_) return;
+
+  // Make a copy of the C-style function pointer that we are about to invoke
+  // before we release the lock guarding it.
+  FlagCallbackFunc cb = callback_->func;
+
+  // If the flag has a mutation callback this function invokes it. While the
+  // callback is being invoked the primary flag's mutex is unlocked and it is
+  // re-locked back after call to callback is completed. Callback invocation is
+  // guarded by flag's secondary mutex instead which prevents concurrent
+  // callback invocation. Note that it is possible for other thread to grab the
+  // primary lock and update flag's value at any time during the callback
+  // invocation. This is by design. Callback can get a value of the flag if
+  // necessary, but it might be different from the value initiated the callback
+  // and it also can be different by the time the callback invocation is
+  // completed. Requires that *primary_lock be held in exclusive mode; it may be
+  // released and reacquired by the implementation.
+  MutexRelock relock(*DataGuard());
+  absl::MutexLock lock(&callback_->guard);
+  cb();
+}
+
+std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {
+  absl::MutexLock l(DataGuard());
+
+  bool modified = modified_;
+  bool on_command_line = on_command_line_;
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer: {
+      return absl::make_unique<FlagState>(
+          *this, flags_internal::Clone(op_, AlignedBufferValue()), modified,
+          on_command_line, ModificationCount());
+    }
+    case FlagValueStorageKind::kOneWordAtomic: {
+      return absl::make_unique<FlagState>(
+          *this, OneWordValue().load(std::memory_order_acquire), modified,
+          on_command_line, ModificationCount());
+    }
+    case FlagValueStorageKind::kSequenceLocked: {
+      void* cloned = flags_internal::Alloc(op_);
+      // Read is guaranteed to be successful because we hold the lock.
+      bool success =
+          seq_lock_.TryRead(cloned, AtomicBufferValue(), Sizeof(op_));
+      assert(success);
+      static_cast<void>(success);
+      return absl::make_unique<FlagState>(*this, cloned, modified,
+                                          on_command_line, ModificationCount());
+    }
+  }
+  return nullptr;
+}
+
+bool FlagImpl::RestoreState(const FlagState& flag_state) {
+  absl::MutexLock l(DataGuard());
+  if (flag_state.counter_ == ModificationCount()) {
+    return false;
+  }
+
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer:
+    case FlagValueStorageKind::kSequenceLocked:
+      StoreValue(flag_state.value_.heap_allocated);
+      break;
+    case FlagValueStorageKind::kOneWordAtomic:
+      StoreValue(&flag_state.value_.one_word);
+      break;
+  }
+
+  modified_ = flag_state.modified_;
+  on_command_line_ = flag_state.on_command_line_;
+
+  return true;
+}
+
+template <typename StorageT>
+StorageT* FlagImpl::OffsetValue() const {
+  char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this));
+  // The offset is deduced via Flag value type specific op_.
+  size_t offset = flags_internal::ValueOffset(op_);
+
+  return reinterpret_cast<StorageT*>(p + offset);
+}
+
+void* FlagImpl::AlignedBufferValue() const {
+  assert(ValueStorageKind() == FlagValueStorageKind::kAlignedBuffer);
+  return OffsetValue<void>();
+}
+
+std::atomic<uint64_t>* FlagImpl::AtomicBufferValue() const {
+  assert(ValueStorageKind() == FlagValueStorageKind::kSequenceLocked);
+  return OffsetValue<std::atomic<uint64_t>>();
+}
+
+std::atomic<int64_t>& FlagImpl::OneWordValue() const {
+  assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic);
+  return OffsetValue<FlagOneWordValue>()->value;
+}
+
+// Attempts to parse supplied `value` string using parsing routine in the `flag`
+// argument. If parsing successful, this function replaces the dst with newly
+// parsed value. In case if any error is encountered in either step, the error
+// message is stored in 'err'
+std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse(
+    absl::string_view value, std::string& err) const {
+  std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue();
+
+  std::string parse_err;
+  if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) {
+    absl::string_view err_sep = parse_err.empty() ? "" : "; ";
+    err = absl::StrCat("Illegal value '", value, "' specified for flag '",
+                       Name(), "'", err_sep, parse_err);
+    return nullptr;
+  }
+
+  return tentative_value;
+}
+
+void FlagImpl::Read(void* dst) const {
+  auto* guard = DataGuard();  // Make sure flag initialized
+  switch (ValueStorageKind()) {
+    case FlagValueStorageKind::kAlignedBuffer: {
+      absl::MutexLock l(guard);
+      flags_internal::CopyConstruct(op_, AlignedBufferValue(), dst);
+      break;
+    }
+    case FlagValueStorageKind::kOneWordAtomic: {
+      const int64_t one_word_val =
+          OneWordValue().load(std::memory_order_acquire);
+      std::memcpy(dst, &one_word_val, Sizeof(op_));
+      break;
+    }
+    case FlagValueStorageKind::kSequenceLocked: {
+      ReadSequenceLockedData(dst);
+      break;
+    }
+  }
+}
+
+void FlagImpl::ReadSequenceLockedData(void* dst) const {
+  int size = Sizeof(op_);
+  // Attempt to read using the sequence lock.
+  if (ABSL_PREDICT_TRUE(seq_lock_.TryRead(dst, AtomicBufferValue(), size))) {
+    return;
+  }
+  // We failed due to contention. Acquire the lock to prevent contention
+  // and try again.
+  absl::ReaderMutexLock l(DataGuard());
+  bool success = seq_lock_.TryRead(dst, AtomicBufferValue(), size);
+  assert(success);
+  static_cast<void>(success);
+}
+
+void FlagImpl::Write(const void* src) {
+  absl::MutexLock l(DataGuard());
+
+  if (ShouldValidateFlagValue(flags_internal::FastTypeId(op_))) {
+    std::unique_ptr<void, DynValueDeleter> obj{flags_internal::Clone(op_, src),
+                                               DynValueDeleter{op_}};
+    std::string ignored_error;
+    std::string src_as_str = flags_internal::Unparse(op_, src);
+    if (!flags_internal::Parse(op_, src_as_str, obj.get(), &ignored_error)) {
+      ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(),
+                                            "' to invalid value ", src_as_str));
+    }
+  }
+
+  StoreValue(src);
+}
+
+// Sets the value of the flag based on specified string `value`. If the flag
+// was successfully set to new value, it returns true. Otherwise, sets `err`
+// to indicate the error, leaves the flag unchanged, and returns false. There
+// are three ways to set the flag's value:
+//  * Update the current flag value
+//  * Update the flag's default value
+//  * Update the current flag value if it was never set before
+// The mode is selected based on 'set_mode' parameter.
+bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode,
+                         ValueSource source, std::string& err) {
+  absl::MutexLock l(DataGuard());
+
+  switch (set_mode) {
+    case SET_FLAGS_VALUE: {
+      // set or modify the flag's value
+      auto tentative_value = TryParse(value, err);
+      if (!tentative_value) return false;
+
+      StoreValue(tentative_value.get());
+
+      if (source == kCommandLine) {
+        on_command_line_ = true;
+      }
+      break;
+    }
+    case SET_FLAG_IF_DEFAULT: {
+      // set the flag's value, but only if it hasn't been set by someone else
+      if (modified_) {
+        // TODO(rogeeff): review and fix this semantic. Currently we do not fail
+        // in this case if flag is modified. This is misleading since the flag's
+        // value is not updated even though we return true.
+        // *err = absl::StrCat(Name(), " is already set to ",
+        //                     CurrentValue(), "\n");
+        // return false;
+        return true;
+      }
+      auto tentative_value = TryParse(value, err);
+      if (!tentative_value) return false;
+
+      StoreValue(tentative_value.get());
+      break;
+    }
+    case SET_FLAGS_DEFAULT: {
+      auto tentative_value = TryParse(value, err);
+      if (!tentative_value) return false;
+
+      if (DefaultKind() == FlagDefaultKind::kDynamicValue) {
+        void* old_value = default_value_.dynamic_value;
+        default_value_.dynamic_value = tentative_value.release();
+        tentative_value.reset(old_value);
+      } else {
+        default_value_.dynamic_value = tentative_value.release();
+        def_kind_ = static_cast<uint8_t>(FlagDefaultKind::kDynamicValue);
+      }
+
+      if (!modified_) {
+        // Need to set both default value *and* current, in this case.
+        StoreValue(default_value_.dynamic_value);
+        modified_ = false;
+      }
+      break;
+    }
+  }
+
+  return true;
+}
+
+void FlagImpl::CheckDefaultValueParsingRoundtrip() const {
+  std::string v = DefaultValue();
+
+  absl::MutexLock lock(DataGuard());
+
+  auto dst = MakeInitValue();
+  std::string error;
+  if (!flags_internal::Parse(op_, v, dst.get(), &error)) {
+    ABSL_INTERNAL_LOG(
+        FATAL,
+        absl::StrCat("Flag ", Name(), " (from ", Filename(),
+                     "): string form of default value '", v,
+                     "' could not be parsed; error=", error));
+  }
+
+  // We do not compare dst to def since parsing/unparsing may make
+  // small changes, e.g., precision loss for floating point types.
+}
+
+bool FlagImpl::ValidateInputValue(absl::string_view value) const {
+  absl::MutexLock l(DataGuard());
+
+  auto obj = MakeInitValue();
+  std::string ignored_error;
+  return flags_internal::Parse(op_, value, obj.get(), &ignored_error);
 }
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index 1633038..8354814 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -16,58 +16,597 @@
 #ifndef ABSL_FLAGS_INTERNAL_FLAG_H_
 #define ABSL_FLAGS_INTERNAL_FLAG_H_
 
-#include <cstring>
+#include <stddef.h>
+#include <stdint.h>
 
+#include <atomic>
+#include <cstring>
+#include <memory>
+#include <new>
+#include <string>
+#include <type_traits>
+#include <typeinfo>
+
+#include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/config.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/internal/registry.h"
+#include "absl/flags/internal/sequence_lock.h"
+#include "absl/flags/marshalling.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/utility/utility.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Forward declaration of absl::Flag<T> public API.
+namespace flags_internal {
+template <typename T>
+class Flag;
+}  // namespace flags_internal
+
+#if defined(_MSC_VER) && !defined(__clang__)
+template <typename T>
+class Flag;
+#else
+template <typename T>
+using Flag = flags_internal::Flag<T>;
+#endif
+
+template <typename T>
+ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag);
+
+template <typename T>
+void SetFlag(absl::Flag<T>* flag, const T& v);
+
+template <typename T, typename V>
+void SetFlag(absl::Flag<T>* flag, const V& v);
+
+template <typename U>
+const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<U>& f);
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag value type operations, eg., parsing, copying, etc. are provided
+// by function specific to that type with a signature matching FlagOpFn.
+
 namespace flags_internal {
 
-constexpr int64_t AtomicInit() { return 0xababababababababll; }
+enum class FlagOp {
+  kAlloc,
+  kDelete,
+  kCopy,
+  kCopyConstruct,
+  kSizeof,
+  kFastTypeId,
+  kRuntimeTypeId,
+  kParse,
+  kUnparse,
+  kValueOffset,
+};
+using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*);
+
+// Forward declaration for Flag value specific operations.
+template <typename T>
+void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3);
+
+// Allocate aligned memory for a flag value.
+inline void* Alloc(FlagOpFn op) {
+  return op(FlagOp::kAlloc, nullptr, nullptr, nullptr);
+}
+// Deletes memory interpreting obj as flag value type pointer.
+inline void Delete(FlagOpFn op, void* obj) {
+  op(FlagOp::kDelete, nullptr, obj, nullptr);
+}
+// Copies src to dst interpreting as flag value type pointers.
+inline void Copy(FlagOpFn op, const void* src, void* dst) {
+  op(FlagOp::kCopy, src, dst, nullptr);
+}
+// Construct a copy of flag value in a location pointed by dst
+// based on src - pointer to the flag's value.
+inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
+  op(FlagOp::kCopyConstruct, src, dst, nullptr);
+}
+// Makes a copy of flag value pointed by obj.
+inline void* Clone(FlagOpFn op, const void* obj) {
+  void* res = flags_internal::Alloc(op);
+  flags_internal::CopyConstruct(op, obj, res);
+  return res;
+}
+// Returns true if parsing of input text is successfull.
+inline bool Parse(FlagOpFn op, absl::string_view text, void* dst,
+                  std::string* error) {
+  return op(FlagOp::kParse, &text, dst, error) != nullptr;
+}
+// Returns string representing supplied value.
+inline std::string Unparse(FlagOpFn op, const void* val) {
+  std::string result;
+  op(FlagOp::kUnparse, val, &result, nullptr);
+  return result;
+}
+// Returns size of flag value type.
+inline size_t Sizeof(FlagOpFn op) {
+  // This sequence of casts reverses the sequence from
+  // `flags_internal::FlagOps()`
+  return static_cast<size_t>(reinterpret_cast<intptr_t>(
+      op(FlagOp::kSizeof, nullptr, nullptr, nullptr)));
+}
+// Returns fast type id coresponding to the value type.
+inline FlagFastTypeId FastTypeId(FlagOpFn op) {
+  return reinterpret_cast<FlagFastTypeId>(
+      op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr));
+}
+// Returns fast type id coresponding to the value type.
+inline const std::type_info* RuntimeTypeId(FlagOpFn op) {
+  return reinterpret_cast<const std::type_info*>(
+      op(FlagOp::kRuntimeTypeId, nullptr, nullptr, nullptr));
+}
+// Returns offset of the field value_ from the field impl_ inside of
+// absl::Flag<T> data. Given FlagImpl pointer p you can get the
+// location of the corresponding value as:
+//      reinterpret_cast<char*>(p) + ValueOffset().
+inline ptrdiff_t ValueOffset(FlagOpFn op) {
+  // This sequence of casts reverses the sequence from
+  // `flags_internal::FlagOps()`
+  return static_cast<ptrdiff_t>(reinterpret_cast<intptr_t>(
+      op(FlagOp::kValueOffset, nullptr, nullptr, nullptr)));
+}
+
+// Returns an address of RTTI's typeid(T).
+template <typename T>
+inline const std::type_info* GenRuntimeTypeId() {
+#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI)
+  return &typeid(T);
+#else
+  return nullptr;
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag help auxiliary structs.
+
+// This is help argument for absl::Flag encapsulating the string literal pointer
+// or pointer to function generating it as well as enum descriminating two
+// cases.
+using HelpGenFunc = std::string (*)();
+
+template <size_t N>
+struct FixedCharArray {
+  char value[N];
+
+  template <size_t... I>
+  static constexpr FixedCharArray<N> FromLiteralString(
+      absl::string_view str, absl::index_sequence<I...>) {
+    return (void)str, FixedCharArray<N>({{str[I]..., '\0'}});
+  }
+};
+
+template <typename Gen, size_t N = Gen::Value().size()>
+constexpr FixedCharArray<N + 1> HelpStringAsArray(int) {
+  return FixedCharArray<N + 1>::FromLiteralString(
+      Gen::Value(), absl::make_index_sequence<N>{});
+}
+
+template <typename Gen>
+constexpr std::false_type HelpStringAsArray(char) {
+  return std::false_type{};
+}
+
+union FlagHelpMsg {
+  constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {}
+  constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {}
+
+  const char* literal;
+  HelpGenFunc gen_func;
+};
+
+enum class FlagHelpKind : uint8_t { kLiteral = 0, kGenFunc = 1 };
+
+struct FlagHelpArg {
+  FlagHelpMsg source;
+  FlagHelpKind kind;
+};
+
+extern const char kStrippedFlagHelp[];
+
+// These two HelpArg overloads allows us to select at compile time one of two
+// way to pass Help argument to absl::Flag. We'll be passing
+// AbslFlagHelpGenFor##name as Gen and integer 0 as a single argument to prefer
+// first overload if possible. If help message is evaluatable on constexpr
+// context We'll be able to make FixedCharArray out of it and we'll choose first
+// overload. In this case the help message expression is immediately evaluated
+// and is used to construct the absl::Flag. No additionl code is generated by
+// ABSL_FLAG Otherwise SFINAE kicks in and first overload is dropped from the
+// consideration, in which case the second overload will be used. The second
+// overload does not attempt to evaluate the help message expression
+// immediately and instead delays the evaluation by returing the function
+// pointer (&T::NonConst) genering the help message when necessary. This is
+// evaluatable in constexpr context, but the cost is an extra function being
+// generated in the ABSL_FLAG code.
+template <typename Gen, size_t N>
+constexpr FlagHelpArg HelpArg(const FixedCharArray<N>& value) {
+  return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral};
+}
+
+template <typename Gen>
+constexpr FlagHelpArg HelpArg(std::false_type) {
+  return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc};
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag default value auxiliary structs.
+
+// Signature for the function generating the initial flag value (usually
+// based on default value supplied in flag's definition)
+using FlagDfltGenFunc = void (*)(void*);
+
+union FlagDefaultSrc {
+  constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg)
+      : gen_func(gen_func_arg) {}
+
+#define ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE(T, name) \
+  T name##_value;                                  \
+  constexpr explicit FlagDefaultSrc(T value) : name##_value(value) {}  // NOLINT
+  ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE)
+#undef ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE
+
+  void* dynamic_value;
+  FlagDfltGenFunc gen_func;
+};
+
+enum class FlagDefaultKind : uint8_t {
+  kDynamicValue = 0,
+  kGenFunc = 1,
+  kOneWord = 2  // for default values UP to one word in size
+};
+
+struct FlagDefaultArg {
+  FlagDefaultSrc source;
+  FlagDefaultKind kind;
+};
+
+// This struct and corresponding overload to InitDefaultValue are used to
+// facilitate usage of {} as default value in ABSL_FLAG macro.
+// TODO(rogeeff): Fix handling types with explicit constructors.
+struct EmptyBraces {};
+
+template <typename T>
+constexpr T InitDefaultValue(T t) {
+  return t;
+}
+
+template <typename T>
+constexpr T InitDefaultValue(EmptyBraces) {
+  return T{};
+}
+
+template <typename ValueT, typename GenT,
+          typename std::enable_if<std::is_integral<ValueT>::value, int>::type =
+              (GenT{}, 0)>
+constexpr FlagDefaultArg DefaultArg(int) {
+  return {FlagDefaultSrc(GenT{}.value), FlagDefaultKind::kOneWord};
+}
+
+template <typename ValueT, typename GenT>
+constexpr FlagDefaultArg DefaultArg(char) {
+  return {FlagDefaultSrc(&GenT::Gen), FlagDefaultKind::kGenFunc};
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag current value auxiliary structs.
+
+constexpr int64_t UninitializedFlagValue() { return 0xababababababababll; }
+
+template <typename T>
+using FlagUseOneWordStorage = std::integral_constant<
+    bool, absl::type_traits_internal::is_trivially_copyable<T>::value &&
+              (sizeof(T) <= 8)>;
+
+template <class T>
+using FlagShouldUseSequenceLock = std::integral_constant<
+    bool, absl::type_traits_internal::is_trivially_copyable<T>::value &&
+              (sizeof(T) > 8)>;
+
+enum class FlagValueStorageKind : uint8_t {
+  kAlignedBuffer = 0,
+  kOneWordAtomic = 1,
+  kSequenceLocked = 2,
+};
+
+template <typename T>
+static constexpr FlagValueStorageKind StorageKind() {
+  return FlagUseOneWordStorage<T>::value ? FlagValueStorageKind::kOneWordAtomic
+         : FlagShouldUseSequenceLock<T>::value
+             ? FlagValueStorageKind::kSequenceLocked
+             : FlagValueStorageKind::kAlignedBuffer;
+}
+
+struct FlagOneWordValue {
+  constexpr FlagOneWordValue() : value(UninitializedFlagValue()) {}
+
+  std::atomic<int64_t> value;
+};
+
+template <typename T,
+          FlagValueStorageKind Kind = flags_internal::StorageKind<T>()>
+struct FlagValue;
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> {
+  bool Get(const SequenceLock&, T&) const { return false; }
+
+  alignas(T) char value[sizeof(T)];
+};
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue {
+  bool Get(const SequenceLock&, T& dst) const {
+    int64_t one_word_val = value.load(std::memory_order_acquire);
+    if (ABSL_PREDICT_FALSE(one_word_val == UninitializedFlagValue())) {
+      return false;
+    }
+    std::memcpy(&dst, static_cast<const void*>(&one_word_val), sizeof(T));
+    return true;
+  }
+};
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kSequenceLocked> {
+  bool Get(const SequenceLock& lock, T& dst) const {
+    return lock.TryRead(&dst, value_words, sizeof(T));
+  }
+
+  static constexpr int kNumWords =
+      flags_internal::AlignUp(sizeof(T), sizeof(uint64_t)) / sizeof(uint64_t);
+
+  alignas(T) alignas(
+      std::atomic<uint64_t>) std::atomic<uint64_t> value_words[kNumWords];
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag callback auxiliary structs.
 
 // Signature for the mutation callback used by watched Flags
 // The callback is noexcept.
 // TODO(rogeeff): add noexcept after C++17 support is added.
-using FlagCallback = void (*)();
+using FlagCallbackFunc = void (*)();
 
-void InvokeCallback(absl::Mutex* primary_mu, absl::Mutex* callback_mu,
-                    FlagCallback cb) ABSL_EXCLUSIVE_LOCKS_REQUIRED(primary_mu);
+struct FlagCallback {
+  FlagCallbackFunc func;
+  absl::Mutex guard;  // Guard for concurrent callback invocations.
+};
 
-// This is "unspecified" implementation of absl::Flag<T> type.
-template <typename T>
-class Flag final : public flags_internal::CommandLineFlag {
+///////////////////////////////////////////////////////////////////////////////
+// Flag implementation, which does not depend on flag value type.
+// The class encapsulates the Flag's data and access to it.
+
+struct DynValueDeleter {
+  explicit DynValueDeleter(FlagOpFn op_arg = nullptr);
+  void operator()(void* ptr) const;
+
+  FlagOpFn op;
+};
+
+class FlagState;
+
+class FlagImpl final : public CommandLineFlag {
  public:
-  constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen,
-                 const char* filename,
-                 const flags_internal::FlagMarshallingOpFn marshalling_op,
-                 const flags_internal::InitialValGenFunc initial_value_gen)
-      : flags_internal::CommandLineFlag(
-            name, flags_internal::HelpText::FromFunctionPointer(help_gen),
-            filename, &flags_internal::FlagOps<T>, marshalling_op,
-            initial_value_gen,
-            /*def=*/nullptr,
-            /*cur=*/nullptr),
-        atomic_(flags_internal::AtomicInit()),
-        callback_(nullptr) {}
+  constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op,
+                     FlagHelpArg help, FlagValueStorageKind value_kind,
+                     FlagDefaultArg default_arg)
+      : name_(name),
+        filename_(filename),
+        op_(op),
+        help_(help.source),
+        help_source_kind_(static_cast<uint8_t>(help.kind)),
+        value_storage_kind_(static_cast<uint8_t>(value_kind)),
+        def_kind_(static_cast<uint8_t>(default_arg.kind)),
+        modified_(false),
+        on_command_line_(false),
+        callback_(nullptr),
+        default_value_(default_arg.source),
+        data_guard_{} {}
+
+  // Constant access methods
+  void Read(void* dst) const override ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  // Mutating access methods
+  void Write(const void* src) ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  // Interfaces to operate on callbacks.
+  void SetCallback(const FlagCallbackFunc mutation_callback)
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+  void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+  // Used in read/write operations to validate source/target has correct type.
+  // For example if flag is declared as absl::Flag<int> FLAGS_foo, a call to
+  // absl::GetFlag(FLAGS_foo) validates that the type of FLAGS_foo is indeed
+  // int. To do that we pass the "assumed" type id (which is deduced from type
+  // int) as an argument `type_id`, which is in turn is validated against the
+  // type id stored in flag object by flag definition statement.
+  void AssertValidType(FlagFastTypeId type_id,
+                       const std::type_info* (*gen_rtti)()) const;
+
+ private:
+  template <typename T>
+  friend class Flag;
+  friend class FlagState;
+
+  // Ensures that `data_guard_` is initialized and returns it.
+  absl::Mutex* DataGuard() const
+      ABSL_LOCK_RETURNED(reinterpret_cast<absl::Mutex*>(data_guard_));
+  // Returns heap allocated value of type T initialized with default value.
+  std::unique_ptr<void, DynValueDeleter> MakeInitValue() const
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+  // Flag initialization called via absl::call_once.
+  void Init();
+
+  // Offset value access methods. One per storage kind. These methods to not
+  // respect const correctness, so be very carefull using them.
+
+  // This is a shared helper routine which encapsulates most of the magic. Since
+  // it is only used inside the three routines below, which are defined in
+  // flag.cc, we can define it in that file as well.
+  template <typename StorageT>
+  StorageT* OffsetValue() const;
+  // This is an accessor for a value stored in an aligned buffer storage
+  // used for non-trivially-copyable data types.
+  // Returns a mutable pointer to the start of a buffer.
+  void* AlignedBufferValue() const;
+
+  // The same as above, but used for sequencelock-protected storage.
+  std::atomic<uint64_t>* AtomicBufferValue() const;
+
+  // This is an accessor for a value stored as one word atomic. Returns a
+  // mutable reference to an atomic value.
+  std::atomic<int64_t>& OneWordValue() const;
+
+  // Attempts to parse supplied `value` string. If parsing is successful,
+  // returns new value. Otherwise returns nullptr.
+  std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value,
+                                                  std::string& err) const
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+  // Stores the flag value based on the pointer to the source.
+  void StoreValue(const void* src) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+  // Copy the flag data, protected by `seq_lock_` into `dst`.
+  //
+  // REQUIRES: ValueStorageKind() == kSequenceLocked.
+  void ReadSequenceLockedData(void* dst) const
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  FlagHelpKind HelpSourceKind() const {
+    return static_cast<FlagHelpKind>(help_source_kind_);
+  }
+  FlagValueStorageKind ValueStorageKind() const {
+    return static_cast<FlagValueStorageKind>(value_storage_kind_);
+  }
+  FlagDefaultKind DefaultKind() const
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()) {
+    return static_cast<FlagDefaultKind>(def_kind_);
+  }
+
+  // CommandLineFlag interface implementation
+  absl::string_view Name() const override;
+  std::string Filename() const override;
+  std::string Help() const override;
+  FlagFastTypeId TypeId() const override;
+  bool IsSpecifiedOnCommandLine() const override
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+  std::string DefaultValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard());
+  std::string CurrentValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard());
+  bool ValidateInputValue(absl::string_view value) const override
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+  void CheckDefaultValueParsingRoundtrip() const override
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  int64_t ModificationCount() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+  // Interfaces to save and restore flags to/from persistent state.
+  // Returns current flag state or nullptr if flag does not support
+  // saving and restoring a state.
+  std::unique_ptr<FlagStateInterface> SaveState() override
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  // Restores the flag state to the supplied state object. If there is
+  // nothing to restore returns false. Otherwise returns true.
+  bool RestoreState(const FlagState& flag_state)
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  bool ParseFrom(absl::string_view value, FlagSettingMode set_mode,
+                 ValueSource source, std::string& error) override
+      ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+  // Immutable flag's state.
+
+  // Flags name passed to ABSL_FLAG as second arg.
+  const char* const name_;
+  // The file name where ABSL_FLAG resides.
+  const char* const filename_;
+  // Type-specific operations "vtable".
+  const FlagOpFn op_;
+  // Help message literal or function to generate it.
+  const FlagHelpMsg help_;
+  // Indicates if help message was supplied as literal or generator func.
+  const uint8_t help_source_kind_ : 1;
+  // Kind of storage this flag is using for the flag's value.
+  const uint8_t value_storage_kind_ : 2;
+
+  uint8_t : 0;  // The bytes containing the const bitfields must not be
+                // shared with bytes containing the mutable bitfields.
+
+  // Mutable flag's state (guarded by `data_guard_`).
+
+  // def_kind_ is not guard by DataGuard() since it is accessed in Init without
+  // locks.
+  uint8_t def_kind_ : 2;
+  // Has this flag's value been modified?
+  bool modified_ : 1 ABSL_GUARDED_BY(*DataGuard());
+  // Has this flag been specified on command line.
+  bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard());
+
+  // Unique tag for absl::call_once call to initialize this flag.
+  absl::once_flag init_control_;
+
+  // Sequence lock / mutation counter.
+  flags_internal::SequenceLock seq_lock_;
+
+  // Optional flag's callback and absl::Mutex to guard the invocations.
+  FlagCallback* callback_ ABSL_GUARDED_BY(*DataGuard());
+  // Either a pointer to the function generating the default value based on the
+  // value specified in ABSL_FLAG or pointer to the dynamically set default
+  // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish
+  // these two cases.
+  FlagDefaultSrc default_value_;
+
+  // This is reserved space for an absl::Mutex to guard flag data. It will be
+  // initialized in FlagImpl::Init via placement new.
+  // We can't use "absl::Mutex data_guard_", since this class is not literal.
+  // We do not want to use "absl::Mutex* data_guard_", since this would require
+  // heap allocation during initialization, which is both slows program startup
+  // and can fail. Using reserved space + placement new allows us to avoid both
+  // problems.
+  alignas(absl::Mutex) mutable char data_guard_[sizeof(absl::Mutex)];
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// The Flag object parameterized by the flag's value type. This class implements
+// flag reflection handle interface.
+
+template <typename T>
+class Flag {
+ public:
+  constexpr Flag(const char* name, const char* filename, FlagHelpArg help,
+                 const FlagDefaultArg default_arg)
+      : impl_(name, filename, &FlagOps<T>, help,
+              flags_internal::StorageKind<T>(), default_arg),
+        value_() {}
+
+  // CommandLineFlag interface
+  absl::string_view Name() const { return impl_.Name(); }
+  std::string Filename() const { return impl_.Filename(); }
+  std::string Help() const { return impl_.Help(); }
+  // Do not use. To be removed.
+  bool IsSpecifiedOnCommandLine() const {
+    return impl_.IsSpecifiedOnCommandLine();
+  }
+  std::string DefaultValue() const { return impl_.DefaultValue(); }
+  std::string CurrentValue() const { return impl_.CurrentValue(); }
+
+ private:
+  template <typename, bool>
+  friend class FlagRegistrar;
+  friend class FlagImplPeer;
 
   T Get() const {
-    // Implementation notes:
-    //
-    // We are wrapping a union around the value of `T` to serve three purposes:
-    //
-    //  1. `U.value` has correct size and alignment for a value of type `T`
-    //  2. The `U.value` constructor is not invoked since U's constructor does
-    //  not
-    //     do it explicitly.
-    //  3. The `U.value` destructor is invoked since U's destructor does it
-    //     explicitly. This makes `U` a kind of RAII wrapper around non default
-    //     constructible value of T, which is destructed when we leave the
-    //     scope. We do need to destroy U.value, which is constructed by
-    //     CommandLineFlag::Read even though we left it in a moved-from state
-    //     after std::move.
-    //
-    // All of this serves to avoid requiring `T` being default constructible.
+    // See implementation notes in CommandLineFlag::Get().
     union U {
       T value;
       U() {}
@@ -75,97 +614,133 @@
     };
     U u;
 
-    Read(&u.value, &flags_internal::FlagOps<T>);
+#if !defined(NDEBUG)
+    impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
+#endif
+
+    if (ABSL_PREDICT_FALSE(!value_.Get(impl_.seq_lock_, u.value))) {
+      impl_.Read(&u.value);
+    }
     return std::move(u.value);
   }
-
-  bool AtomicGet(T* v) const {
-    const int64_t r = atomic_.load(std::memory_order_acquire);
-    if (r != flags_internal::AtomicInit()) {
-      std::memcpy(v, &r, sizeof(T));
-      return true;
-    }
-
-    return false;
+  void Set(const T& v) {
+    impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
+    impl_.Write(&v);
   }
 
-  void Set(const T& v) { Write(&v, &flags_internal::FlagOps<T>); }
-
-  void SetCallback(const flags_internal::FlagCallback mutation_callback) {
-    absl::MutexLock l(InitFlagIfNecessary());
-
-    callback_ = mutation_callback;
-
-    InvokeCallback();
-  }
-  void InvokeCallback() override
-      ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) {
-    flags_internal::InvokeCallback(&locks_->primary_mu, &locks_->callback_mu,
-                                   callback_);
-  }
-
- private:
-  void Destroy() const override {
-    // Values are heap allocated Abseil Flags.
-    if (cur_) Delete(op_, cur_);
-    if (def_) Delete(op_, def_);
-
-    delete locks_;
-  }
-
-  void StoreAtomic() override {
-    if (sizeof(T) <= sizeof(int64_t)) {
-      int64_t t = 0;
-      std::memcpy(&t, cur_, (std::min)(sizeof(T), sizeof(int64_t)));
-      atomic_.store(t, std::memory_order_release);
-    }
-  }
+  // Access to the reflection.
+  const CommandLineFlag& Reflect() const { return impl_; }
 
   // Flag's data
-  // For some types, a copy of the current value is kept in an atomically
-  // accessible field.
-  std::atomic<int64_t> atomic_;
-  FlagCallback callback_;  // Mutation callback
+  // The implementation depends on value_ field to be placed exactly after the
+  // impl_ field, so that impl_ can figure out the offset to the value and
+  // access it.
+  FlagImpl impl_;
+  FlagValue<T> value_;
 };
 
+///////////////////////////////////////////////////////////////////////////////
+// Trampoline for friend access
+
+class FlagImplPeer {
+ public:
+  template <typename T, typename FlagType>
+  static T InvokeGet(const FlagType& flag) {
+    return flag.Get();
+  }
+  template <typename FlagType, typename T>
+  static void InvokeSet(FlagType& flag, const T& v) {
+    flag.Set(v);
+  }
+  template <typename FlagType>
+  static const CommandLineFlag& InvokeReflect(const FlagType& f) {
+    return f.Reflect();
+  }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation of Flag value specific operations routine.
+template <typename T>
+void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
+  switch (op) {
+    case FlagOp::kAlloc: {
+      std::allocator<T> alloc;
+      return std::allocator_traits<std::allocator<T>>::allocate(alloc, 1);
+    }
+    case FlagOp::kDelete: {
+      T* p = static_cast<T*>(v2);
+      p->~T();
+      std::allocator<T> alloc;
+      std::allocator_traits<std::allocator<T>>::deallocate(alloc, p, 1);
+      return nullptr;
+    }
+    case FlagOp::kCopy:
+      *static_cast<T*>(v2) = *static_cast<const T*>(v1);
+      return nullptr;
+    case FlagOp::kCopyConstruct:
+      new (v2) T(*static_cast<const T*>(v1));
+      return nullptr;
+    case FlagOp::kSizeof:
+      return reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(T)));
+    case FlagOp::kFastTypeId:
+      return const_cast<void*>(base_internal::FastTypeId<T>());
+    case FlagOp::kRuntimeTypeId:
+      return const_cast<std::type_info*>(GenRuntimeTypeId<T>());
+    case FlagOp::kParse: {
+      // Initialize the temporary instance of type T based on current value in
+      // destination (which is going to be flag's default value).
+      T temp(*static_cast<T*>(v2));
+      if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp,
+                              static_cast<std::string*>(v3))) {
+        return nullptr;
+      }
+      *static_cast<T*>(v2) = std::move(temp);
+      return v2;
+    }
+    case FlagOp::kUnparse:
+      *static_cast<std::string*>(v2) =
+          absl::UnparseFlag<T>(*static_cast<const T*>(v1));
+      return nullptr;
+    case FlagOp::kValueOffset: {
+      // Round sizeof(FlagImp) to a multiple of alignof(FlagValue<T>) to get the
+      // offset of the data.
+      ptrdiff_t round_to = alignof(FlagValue<T>);
+      ptrdiff_t offset =
+          (sizeof(FlagImpl) + round_to - 1) / round_to * round_to;
+      return reinterpret_cast<void*>(offset);
+    }
+  }
+  return nullptr;
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // This class facilitates Flag object registration and tail expression-based
 // flag definition, for example:
 // ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher);
+struct FlagRegistrarEmpty {};
 template <typename T, bool do_register>
 class FlagRegistrar {
  public:
-  explicit FlagRegistrar(Flag<T>* flag) : flag_(flag) {
-    if (do_register) flags_internal::RegisterCommandLineFlag(flag_);
+  explicit FlagRegistrar(Flag<T>& flag) : flag_(flag) {
+    if (do_register) flags_internal::RegisterCommandLineFlag(flag_.impl_);
   }
 
-  FlagRegistrar& OnUpdate(flags_internal::FlagCallback cb) && {
-    flag_->SetCallback(cb);
+  FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
+    flag_.impl_.SetCallback(cb);
     return *this;
   }
 
-  // Make the registrar "die" gracefully as a bool on a line where registration
-  // happens. Registrar objects are intended to live only as temporary.
-  operator bool() const { return true; }  // NOLINT
+  // Make the registrar "die" gracefully as an empty struct on a line where
+  // registration happens. Registrar objects are intended to live only as
+  // temporary.
+  operator FlagRegistrarEmpty() const { return {}; }  // NOLINT
 
  private:
-  Flag<T>* flag_;  // Flag being registered (not owned).
+  Flag<T>& flag_;  // Flag being registered (not owned).
 };
 
-// This struct and corresponding overload to MakeDefaultValue are used to
-// facilitate usage of {} as default value in ABSL_FLAG macro.
-struct EmptyBraces {};
-
-template <typename T>
-T* MakeFromDefaultValue(T t) {
-  return new T(std::move(t));
-}
-
-template <typename T>
-T* MakeFromDefaultValue(EmptyBraces) {
-  return new T;
-}
-
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_FLAG_H_
diff --git a/absl/flags/internal/parse.h b/absl/flags/internal/parse.h
index fd3aca6..de706c8 100644
--- a/absl/flags/internal/parse.h
+++ b/absl/flags/internal/parse.h
@@ -19,7 +19,9 @@
 #include <string>
 #include <vector>
 
+#include "absl/base/config.h"
 #include "absl/flags/declare.h"
+#include "absl/strings/string_view.h"
 
 ABSL_DECLARE_FLAG(std::vector<std::string>, flagfile);
 ABSL_DECLARE_FLAG(std::vector<std::string>, fromenv);
@@ -27,6 +29,7 @@
 ABSL_DECLARE_FLAG(std::vector<std::string>, undefok);
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 enum class ArgvListAction { kRemoveParsedArgs, kKeepParsedArgs };
@@ -42,7 +45,15 @@
                                         UsageFlagsAction usage_flag_act,
                                         OnUndefinedFlag on_undef_flag);
 
+// --------------------------------------------------------------------
+// Inspect original command line
+
+// Returns true if flag with specified name was either present on the original
+// command line or specified in flag file present on the original command line.
+bool WasPresentOnCommandLine(absl::string_view flag_name);
+
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_PARSE_H_
diff --git a/absl/flags/internal/path_util.h b/absl/flags/internal/path_util.h
index 5615c0e..a6594d3 100644
--- a/absl/flags/internal/path_util.h
+++ b/absl/flags/internal/path_util.h
@@ -16,10 +16,11 @@
 #ifndef ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
 #define ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
 
-#include "absl/strings/match.h"
+#include "absl/base/config.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 // A portable interface that returns the basename of the filename passed as an
@@ -55,6 +56,7 @@
 }
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
diff --git a/absl/flags/internal/private_handle_accessor.cc b/absl/flags/internal/private_handle_accessor.cc
new file mode 100644
index 0000000..a7eb58b
--- /dev/null
+++ b/absl/flags/internal/private_handle_accessor.cc
@@ -0,0 +1,65 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/internal/private_handle_accessor.h"
+
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+FlagFastTypeId PrivateHandleAccessor::TypeId(const CommandLineFlag& flag) {
+  return flag.TypeId();
+}
+
+std::unique_ptr<FlagStateInterface> PrivateHandleAccessor::SaveState(
+    CommandLineFlag& flag) {
+  return flag.SaveState();
+}
+
+bool PrivateHandleAccessor::IsSpecifiedOnCommandLine(
+    const CommandLineFlag& flag) {
+  return flag.IsSpecifiedOnCommandLine();
+}
+
+bool PrivateHandleAccessor::ValidateInputValue(const CommandLineFlag& flag,
+                                               absl::string_view value) {
+  return flag.ValidateInputValue(value);
+}
+
+void PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
+    const CommandLineFlag& flag) {
+  flag.CheckDefaultValueParsingRoundtrip();
+}
+
+bool PrivateHandleAccessor::ParseFrom(CommandLineFlag& flag,
+                                      absl::string_view value,
+                                      flags_internal::FlagSettingMode set_mode,
+                                      flags_internal::ValueSource source,
+                                      std::string& error) {
+  return flag.ParseFrom(value, set_mode, source, error);
+}
+
+}  // namespace flags_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
diff --git a/absl/flags/internal/private_handle_accessor.h b/absl/flags/internal/private_handle_accessor.h
new file mode 100644
index 0000000..c64435c
--- /dev/null
+++ b/absl/flags/internal/private_handle_accessor.h
@@ -0,0 +1,61 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
+#define ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
+
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// This class serves as a trampoline to access private methods of
+// CommandLineFlag. This class is intended for use exclusively internally inside
+// of the Abseil Flags implementation.
+class PrivateHandleAccessor {
+ public:
+  // Access to CommandLineFlag::TypeId.
+  static FlagFastTypeId TypeId(const CommandLineFlag& flag);
+
+  // Access to CommandLineFlag::SaveState.
+  static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag& flag);
+
+  // Access to CommandLineFlag::IsSpecifiedOnCommandLine.
+  static bool IsSpecifiedOnCommandLine(const CommandLineFlag& flag);
+
+  // Access to CommandLineFlag::ValidateInputValue.
+  static bool ValidateInputValue(const CommandLineFlag& flag,
+                                 absl::string_view value);
+
+  // Access to CommandLineFlag::CheckDefaultValueParsingRoundtrip.
+  static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag);
+
+  static bool ParseFrom(CommandLineFlag& flag, absl::string_view value,
+                        flags_internal::FlagSettingMode set_mode,
+                        flags_internal::ValueSource source, std::string& error);
+};
+
+}  // namespace flags_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
diff --git a/absl/flags/internal/program_name.cc b/absl/flags/internal/program_name.cc
index f0811f1..51d698d 100644
--- a/absl/flags/internal/program_name.cc
+++ b/absl/flags/internal/program_name.cc
@@ -17,10 +17,16 @@
 
 #include <string>
 
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/const_init.h"
+#include "absl/base/thread_annotations.h"
 #include "absl/flags/internal/path_util.h"
+#include "absl/strings/string_view.h"
 #include "absl/synchronization/mutex.h"
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 ABSL_CONST_INIT static absl::Mutex program_name_guard(absl::kConstInit);
@@ -50,4 +56,5 @@
 }
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/program_name.h b/absl/flags/internal/program_name.h
index 326f24b..b99b94f 100644
--- a/absl/flags/internal/program_name.h
+++ b/absl/flags/internal/program_name.h
@@ -18,12 +18,14 @@
 
 #include <string>
 
+#include "absl/base/config.h"
 #include "absl/strings/string_view.h"
 
 // --------------------------------------------------------------------
 // Program name
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 // Returns program invocation name or "UNKNOWN" if `SetProgramInvocationName()`
@@ -42,6 +44,7 @@
 void SetProgramInvocationName(absl::string_view prog_name_str);
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_
diff --git a/absl/flags/internal/program_name_test.cc b/absl/flags/internal/program_name_test.cc
index ed69218..aff9f63 100644
--- a/absl/flags/internal/program_name_test.cc
+++ b/absl/flags/internal/program_name_test.cc
@@ -15,14 +15,17 @@
 
 #include "absl/flags/internal/program_name.h"
 
+#include <string>
+
 #include "gtest/gtest.h"
 #include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
 
 namespace {
 
 namespace flags = absl::flags_internal;
 
-TEST(FlagsPathUtilTest, TestInitialProgamName) {
+TEST(FlagsPathUtilTest, TestProgamNameInterfaces) {
   flags::SetProgramInvocationName("absl/flags/program_name_test");
   std::string program_name = flags::ProgramInvocationName();
   for (char& c : program_name)
@@ -40,9 +43,7 @@
 
   EXPECT_TRUE(absl::EndsWith(program_name, expect_name)) << program_name;
   EXPECT_EQ(flags::ShortProgramInvocationName(), expect_basename);
-}
 
-TEST(FlagsPathUtilTest, TestProgamNameInterfaces) {
   flags::SetProgramInvocationName("a/my_test");
 
   EXPECT_EQ(flags::ProgramInvocationName(), "a/my_test");
diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc
deleted file mode 100644
index 4bea313..0000000
--- a/absl/flags/internal/registry.cc
+++ /dev/null
@@ -1,404 +0,0 @@
-//
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/flags/internal/registry.h"
-
-#include "absl/base/dynamic_annotations.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/flags/config.h"
-#include "absl/flags/usage_config.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
-#include "absl/synchronization/mutex.h"
-
-// --------------------------------------------------------------------
-// FlagRegistry implementation
-//    A FlagRegistry holds all flag objects indexed
-//    by their names so that if you know a flag's name you can access or
-//    set it.
-
-namespace absl {
-namespace flags_internal {
-
-// --------------------------------------------------------------------
-// FlagRegistry
-//    A FlagRegistry singleton object holds all flag objects indexed
-//    by their names so that if you know a flag's name (as a C
-//    string), you can access or set it.  If the function is named
-//    FooLocked(), you must own the registry lock before calling
-//    the function; otherwise, you should *not* hold the lock, and
-//    the function will acquire it itself if needed.
-// --------------------------------------------------------------------
-
-class FlagRegistry {
- public:
-  FlagRegistry() = default;
-  ~FlagRegistry() {
-    for (auto& p : flags_) {
-      p.second->Destroy();
-    }
-  }
-
-  // Store a flag in this registry.  Takes ownership of *flag.
-  void RegisterFlag(CommandLineFlag* flag);
-
-  void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); }
-  void Unlock() ABSL_UNLOCK_FUNCTION(lock_) { lock_.Unlock(); }
-
-  // Returns the flag object for the specified name, or nullptr if not found.
-  // Will emit a warning if a 'retired' flag is specified.
-  CommandLineFlag* FindFlagLocked(absl::string_view name);
-
-  // Returns the retired flag object for the specified name, or nullptr if not
-  // found or not retired.  Does not emit a warning.
-  CommandLineFlag* FindRetiredFlagLocked(absl::string_view name);
-
-  static FlagRegistry* GlobalRegistry();  // returns a singleton registry
-
- private:
-  friend class FlagSaverImpl;  // reads all the flags in order to copy them
-  friend void ForEachFlagUnlocked(
-      std::function<void(CommandLineFlag*)> visitor);
-
-  // The map from name to flag, for FindFlagLocked().
-  using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
-  using FlagIterator = FlagMap::iterator;
-  using FlagConstIterator = FlagMap::const_iterator;
-  FlagMap flags_;
-
-  absl::Mutex lock_;
-
-  // Disallow
-  FlagRegistry(const FlagRegistry&);
-  FlagRegistry& operator=(const FlagRegistry&);
-};
-
-FlagRegistry* FlagRegistry::GlobalRegistry() {
-  static FlagRegistry* global_registry = new FlagRegistry;
-  return global_registry;
-}
-
-namespace {
-
-class FlagRegistryLock {
- public:
-  explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
-  ~FlagRegistryLock() { fr_->Unlock(); }
-
- private:
-  FlagRegistry* const fr_;
-};
-
-}  // namespace
-
-void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
-  FlagRegistryLock registry_lock(this);
-  std::pair<FlagIterator, bool> ins =
-      flags_.insert(FlagMap::value_type(flag->Name(), flag));
-  if (ins.second == false) {  // means the name was already in the map
-    CommandLineFlag* old_flag = ins.first->second;
-    if (flag->IsRetired() != old_flag->IsRetired()) {
-      // All registrations must agree on the 'retired' flag.
-      flags_internal::ReportUsageError(
-          absl::StrCat(
-              "Retired flag '", flag->Name(),
-              "' was defined normally in file '",
-              (flag->IsRetired() ? old_flag->Filename() : flag->Filename()),
-              "'."),
-          true);
-    } else if (flag->op_ != old_flag->op_) {
-      flags_internal::ReportUsageError(
-          absl::StrCat("Flag '", flag->Name(),
-                       "' was defined more than once but with "
-                       "differing types. Defined in files '",
-                       old_flag->Filename(), "' and '", flag->Filename(),
-                       "' with types '", old_flag->Typename(), "' and '",
-                       flag->Typename(), "', respectively."),
-          true);
-    } else if (old_flag->IsRetired()) {
-      // Retired definitions are idempotent. Just keep the old one.
-      flag->Destroy();
-      return;
-    } else if (old_flag->Filename() != flag->Filename()) {
-      flags_internal::ReportUsageError(
-          absl::StrCat("Flag '", flag->Name(),
-                       "' was defined more than once (in files '",
-                       old_flag->Filename(), "' and '", flag->Filename(),
-                       "')."),
-          true);
-    } else {
-      flags_internal::ReportUsageError(
-          absl::StrCat(
-              "Something wrong with flag '", flag->Name(), "' in file '",
-              flag->Filename(), "'. One possibility: file '", flag->Filename(),
-              "' is being linked both statically and dynamically into this "
-              "executable. e.g. some files listed as srcs to a test and also "
-              "listed as srcs of some shared lib deps of the same test."),
-          true);
-    }
-    // All cases above are fatal, except for the retired flags.
-    std::exit(1);
-  }
-}
-
-CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) {
-  FlagConstIterator i = flags_.find(name);
-  if (i == flags_.end()) {
-    return nullptr;
-  }
-
-  if (i->second->IsRetired()) {
-    flags_internal::ReportUsageError(
-        absl::StrCat("Accessing retired flag '", name, "'"), false);
-  }
-
-  return i->second;
-}
-
-CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) {
-  FlagConstIterator i = flags_.find(name);
-  if (i == flags_.end() || !i->second->IsRetired()) {
-    return nullptr;
-  }
-
-  return i->second;
-}
-
-// --------------------------------------------------------------------
-// FlagSaver
-// FlagSaverImpl
-//    This class stores the states of all flags at construct time,
-//    and restores all flags to that state at destruct time.
-//    Its major implementation challenge is that it never modifies
-//    pointers in the 'main' registry, so global FLAG_* vars always
-//    point to the right place.
-// --------------------------------------------------------------------
-
-class FlagSaverImpl {
- public:
-  // Constructs an empty FlagSaverImpl object.
-  FlagSaverImpl() {}
-  ~FlagSaverImpl() {
-    // reclaim memory from each of our CommandLineFlags
-    for (const SavedFlag& src : backup_registry_) {
-      Delete(src.op, src.current);
-      Delete(src.op, src.default_value);
-    }
-  }
-
-  // Saves the flag states from the flag registry into this object.
-  // It's an error to call this more than once.
-  // Must be called when the registry mutex is not held.
-  void SaveFromRegistry() {
-    assert(backup_registry_.empty());  // call only once!
-    SavedFlag saved;
-    flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) {
-      if (flag->IsRetired()) return;
-
-      saved.name = flag->Name();
-      saved.op = flag->op_;
-      saved.marshalling_op = flag->marshalling_op_;
-      {
-        absl::MutexLock l(flag->InitFlagIfNecessary());
-        saved.validator = flag->GetValidator();
-        saved.modified = flag->modified_;
-        saved.on_command_line = flag->on_command_line_;
-        saved.current = Clone(saved.op, flag->cur_);
-        saved.default_value = Clone(saved.op, flag->def_);
-        saved.counter = flag->counter_;
-      }
-      backup_registry_.push_back(saved);
-    });
-  }
-
-  // Restores the saved flag states into the flag registry.  We
-  // assume no flags were added or deleted from the registry since
-  // the SaveFromRegistry; if they were, that's trouble!  Must be
-  // called when the registry mutex is not held.
-  void RestoreToRegistry() {
-    FlagRegistry* const global_registry = FlagRegistry::GlobalRegistry();
-    FlagRegistryLock frl(global_registry);
-    for (const SavedFlag& src : backup_registry_) {
-      CommandLineFlag* flag = global_registry->FindFlagLocked(src.name);
-      // If null, flag got deleted from registry.
-      if (!flag) continue;
-
-      bool restored = false;
-      {
-        // This function encapsulate the lock.
-        flag->SetValidator(src.validator);
-
-        absl::MutexLock l(flag->InitFlagIfNecessary());
-        flag->modified_ = src.modified;
-        flag->on_command_line_ = src.on_command_line;
-        if (flag->counter_ != src.counter ||
-            ChangedDirectly(flag, src.default_value, flag->def_)) {
-          restored = true;
-          Copy(src.op, src.default_value, flag->def_);
-        }
-        if (flag->counter_ != src.counter ||
-            ChangedDirectly(flag, src.current, flag->cur_)) {
-          restored = true;
-          Copy(src.op, src.current, flag->cur_);
-          UpdateCopy(flag);
-          flag->InvokeCallback();
-        }
-      }
-
-      if (restored) {
-        flag->counter_++;
-
-        // Revalidate the flag because the validator might store state based
-        // on the flag's value, which just changed due to the restore.
-        // Failing validation is ignored because it's assumed that the flag
-        // was valid previously and there's little that can be done about it
-        // here, anyway.
-        flag->ValidateInputValue(flag->CurrentValue());
-
-        ABSL_INTERNAL_LOG(
-            INFO, absl::StrCat("Restore saved value of ", flag->Name(), ": ",
-                               Unparse(src.marshalling_op, src.current)));
-      }
-    }
-  }
-
- private:
-  struct SavedFlag {
-    absl::string_view name;
-    FlagOpFn op;
-    FlagMarshallingOpFn marshalling_op;
-    int64_t counter;
-    void* validator;
-    bool modified;
-    bool on_command_line;
-    const void* current;        // nullptr after restore
-    const void* default_value;  // nullptr after restore
-  };
-
-  std::vector<SavedFlag> backup_registry_;
-
-  FlagSaverImpl(const FlagSaverImpl&);  // no copying!
-  void operator=(const FlagSaverImpl&);
-};
-
-FlagSaver::FlagSaver() : impl_(new FlagSaverImpl()) {
-  impl_->SaveFromRegistry();
-}
-
-void FlagSaver::Ignore() {
-  delete impl_;
-  impl_ = nullptr;
-}
-
-FlagSaver::~FlagSaver() {
-  if (!impl_) return;
-
-  impl_->RestoreToRegistry();
-  delete impl_;
-}
-
-// --------------------------------------------------------------------
-
-CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
-  if (name.empty()) return nullptr;
-  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
-  FlagRegistryLock frl(registry);
-
-  return registry->FindFlagLocked(name);
-}
-
-CommandLineFlag* FindRetiredFlag(absl::string_view name) {
-  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
-  FlagRegistryLock frl(registry);
-
-  return registry->FindRetiredFlagLocked(name);
-}
-
-// --------------------------------------------------------------------
-
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor) {
-  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
-  for (FlagRegistry::FlagConstIterator i = registry->flags_.begin();
-       i != registry->flags_.end(); ++i) {
-    visitor(i->second);
-  }
-}
-
-void ForEachFlag(std::function<void(CommandLineFlag*)> visitor) {
-  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
-  FlagRegistryLock frl(registry);
-  ForEachFlagUnlocked(visitor);
-}
-
-// --------------------------------------------------------------------
-
-bool RegisterCommandLineFlag(CommandLineFlag* flag) {
-  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
-  return true;
-}
-
-// --------------------------------------------------------------------
-
-namespace {
-
-class RetiredFlagObj final : public flags_internal::CommandLineFlag {
- public:
-  constexpr RetiredFlagObj(const char* name, FlagOpFn ops,
-                           FlagMarshallingOpFn marshalling_ops)
-      : flags_internal::CommandLineFlag(
-            name, flags_internal::HelpText::FromStaticCString(nullptr),
-            /*filename=*/"RETIRED", ops, marshalling_ops,
-            /*initial_value_gen=*/nullptr,
-            /*def=*/nullptr,
-            /*cur=*/nullptr) {}
-
- private:
-  bool IsRetired() const override { return true; }
-
-  void Destroy() const override {
-    // Values are heap allocated for Retired Flags.
-    if (cur_) Delete(op_, cur_);
-    if (def_) Delete(op_, def_);
-
-    if (locks_) delete locks_;
-
-    delete this;
-  }
-};
-
-}  // namespace
-
-bool Retire(const char* name, FlagOpFn ops,
-            FlagMarshallingOpFn marshalling_ops) {
-  auto* flag = new flags_internal::RetiredFlagObj(name, ops, marshalling_ops);
-  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
-  return true;
-}
-
-// --------------------------------------------------------------------
-
-bool IsRetiredFlag(absl::string_view name, bool* type_is_bool) {
-  assert(!name.empty());
-  CommandLineFlag* flag = flags_internal::FindRetiredFlag(name);
-  if (flag == nullptr) {
-    return false;
-  }
-  assert(type_is_bool);
-  *type_is_bool = flag->IsOfType<bool>();
-  return true;
-}
-
-}  // namespace flags_internal
-}  // namespace absl
diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h
index eb134a9..a8d9eb9 100644
--- a/absl/flags/internal/registry.h
+++ b/absl/flags/internal/registry.h
@@ -17,31 +17,28 @@
 #define ABSL_FLAGS_INTERNAL_REGISTRY_H_
 
 #include <functional>
-#include <map>
-#include <string>
 
-#include "absl/base/macros.h"
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
 #include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
 
 // --------------------------------------------------------------------
 // Global flags registry API.
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
-CommandLineFlag* FindCommandLineFlag(absl::string_view name);
-CommandLineFlag* FindRetiredFlag(absl::string_view name);
-
-// Executes specified visitor for each non-retired flag in the registry.
-// Requires the caller hold the registry lock.
-void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor);
 // Executes specified visitor for each non-retired flag in the registry. While
 // callback are executed, the registry is locked and can't be changed.
-void ForEachFlag(std::function<void(CommandLineFlag*)> visitor);
+void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
 
 //-----------------------------------------------------------------------------
 
-bool RegisterCommandLineFlag(CommandLineFlag*);
+bool RegisterCommandLineFlag(CommandLineFlag&);
+
+void FinalizeRegistry();
 
 //-----------------------------------------------------------------------------
 // Retired registrations:
@@ -76,47 +73,25 @@
 //
 
 // Retire flag with name "name" and type indicated by ops.
-bool Retire(const char* name, FlagOpFn ops,
-            FlagMarshallingOpFn marshalling_ops);
+void Retire(const char* name, FlagFastTypeId type_id, char* buf);
+
+constexpr size_t kRetiredFlagObjSize = 3 * sizeof(void*);
+constexpr size_t kRetiredFlagObjAlignment = alignof(void*);
 
 // Registered a retired flag with name 'flag_name' and type 'T'.
 template <typename T>
-inline bool RetiredFlag(const char* flag_name) {
-  return flags_internal::Retire(flag_name, flags_internal::FlagOps<T>,
-                                flags_internal::FlagMarshallingOps<T>);
-}
-
-// If the flag is retired, returns true and indicates in |*type_is_bool|
-// whether the type of the retired flag is a bool.
-// Only to be called by code that needs to explicitly ignore retired flags.
-bool IsRetiredFlag(absl::string_view name, bool* type_is_bool);
-
-//-----------------------------------------------------------------------------
-// Saves the states (value, default value, whether the user has set
-// the flag, registered validators, etc) of all flags, and restores
-// them when the FlagSaver is destroyed.
-//
-// This class is thread-safe.  However, its destructor writes to
-// exactly the set of flags that have changed value during its
-// lifetime, so concurrent _direct_ access to those flags
-// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe.
-
-class FlagSaver {
+class RetiredFlag {
  public:
-  FlagSaver();
-  ~FlagSaver();
-
-  FlagSaver(const FlagSaver&) = delete;
-  void operator=(const FlagSaver&) = delete;
-
-  // Prevents saver from restoring the saved state of flags.
-  void Ignore();
+  void Retire(const char* flag_name) {
+    flags_internal::Retire(flag_name, base_internal::FastTypeId<T>(), buf_);
+  }
 
  private:
-  class FlagSaverImpl* impl_;  // we use pimpl here to keep API steady
+  alignas(kRetiredFlagObjAlignment) char buf_[kRetiredFlagObjSize];
 };
 
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_REGISTRY_H_
diff --git a/absl/flags/internal/sequence_lock.h b/absl/flags/internal/sequence_lock.h
new file mode 100644
index 0000000..807b2a7
--- /dev/null
+++ b/absl/flags/internal/sequence_lock.h
@@ -0,0 +1,187 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
+#define ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+#include <cassert>
+#include <cstring>
+
+#include "absl/base/optimization.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// Align 'x' up to the nearest 'align' bytes.
+inline constexpr size_t AlignUp(size_t x, size_t align) {
+  return align * ((x + align - 1) / align);
+}
+
+// A SequenceLock implements lock-free reads. A sequence counter is incremented
+// before and after each write, and readers access the counter before and after
+// accessing the protected data. If the counter is verified to not change during
+// the access, and the sequence counter value was even, then the reader knows
+// that the read was race-free and valid. Otherwise, the reader must fall back
+// to a Mutex-based code path.
+//
+// This particular SequenceLock starts in an "uninitialized" state in which
+// TryRead() returns false. It must be enabled by calling MarkInitialized().
+// This serves as a marker that the associated flag value has not yet been
+// initialized and a slow path needs to be taken.
+//
+// The memory reads and writes protected by this lock must use the provided
+// `TryRead()` and `Write()` functions. These functions behave similarly to
+// `memcpy()`, with one oddity: the protected data must be an array of
+// `std::atomic<int64>`. This is to comply with the C++ standard, which
+// considers data races on non-atomic objects to be undefined behavior. See "Can
+// Seqlocks Get Along With Programming Language Memory Models?"[1] by Hans J.
+// Boehm for more details.
+//
+// [1] https://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf
+class SequenceLock {
+ public:
+  constexpr SequenceLock() : lock_(kUninitialized) {}
+
+  // Mark that this lock is ready for use.
+  void MarkInitialized() {
+    assert(lock_.load(std::memory_order_relaxed) == kUninitialized);
+    lock_.store(0, std::memory_order_release);
+  }
+
+  // Copy "size" bytes of data from "src" to "dst", protected as a read-side
+  // critical section of the sequence lock.
+  //
+  // Unlike traditional sequence lock implementations which loop until getting a
+  // clean read, this implementation returns false in the case of concurrent
+  // calls to `Write`. In such a case, the caller should fall back to a
+  // locking-based slow path.
+  //
+  // Returns false if the sequence lock was not yet marked as initialized.
+  //
+  // NOTE: If this returns false, "dst" may be overwritten with undefined
+  // (potentially uninitialized) data.
+  bool TryRead(void* dst, const std::atomic<uint64_t>* src, size_t size) const {
+    // Acquire barrier ensures that no loads done by f() are reordered
+    // above the first load of the sequence counter.
+    int64_t seq_before = lock_.load(std::memory_order_acquire);
+    if (ABSL_PREDICT_FALSE(seq_before & 1) == 1) return false;
+    RelaxedCopyFromAtomic(dst, src, size);
+    // Another acquire fence ensures that the load of 'lock_' below is
+    // strictly ordered after the RelaxedCopyToAtomic call above.
+    std::atomic_thread_fence(std::memory_order_acquire);
+    int64_t seq_after = lock_.load(std::memory_order_relaxed);
+    return ABSL_PREDICT_TRUE(seq_before == seq_after);
+  }
+
+  // Copy "size" bytes from "src" to "dst" as a write-side critical section
+  // of the sequence lock. Any concurrent readers will be forced to retry
+  // until they get a read that does not conflict with this write.
+  //
+  // This call must be externally synchronized against other calls to Write,
+  // but may proceed concurrently with reads.
+  void Write(std::atomic<uint64_t>* dst, const void* src, size_t size) {
+    // We can use relaxed instructions to increment the counter since we
+    // are extenally synchronized. The std::atomic_thread_fence below
+    // ensures that the counter updates don't get interleaved with the
+    // copy to the data.
+    int64_t orig_seq = lock_.load(std::memory_order_relaxed);
+    assert((orig_seq & 1) == 0);  // Must be initially unlocked.
+    lock_.store(orig_seq + 1, std::memory_order_relaxed);
+
+    // We put a release fence between update to lock_ and writes to shared data.
+    // Thus all stores to shared data are effectively release operations and
+    // update to lock_ above cannot be re-ordered past any of them. Note that
+    // this barrier is not for the fetch_add above.  A release barrier for the
+    // fetch_add would be before it, not after.
+    std::atomic_thread_fence(std::memory_order_release);
+    RelaxedCopyToAtomic(dst, src, size);
+    // "Release" semantics ensure that none of the writes done by
+    // RelaxedCopyToAtomic() can be reordered after the following modification.
+    lock_.store(orig_seq + 2, std::memory_order_release);
+  }
+
+  // Return the number of times that Write() has been called.
+  //
+  // REQUIRES: This must be externally synchronized against concurrent calls to
+  // `Write()` or `IncrementModificationCount()`.
+  // REQUIRES: `MarkInitialized()` must have been previously called.
+  int64_t ModificationCount() const {
+    int64_t val = lock_.load(std::memory_order_relaxed);
+    assert(val != kUninitialized && (val & 1) == 0);
+    return val / 2;
+  }
+
+  // REQUIRES: This must be externally synchronized against concurrent calls to
+  // `Write()` or `ModificationCount()`.
+  // REQUIRES: `MarkInitialized()` must have been previously called.
+  void IncrementModificationCount() {
+    int64_t val = lock_.load(std::memory_order_relaxed);
+    assert(val != kUninitialized);
+    lock_.store(val + 2, std::memory_order_relaxed);
+  }
+
+ private:
+  // Perform the equivalent of "memcpy(dst, src, size)", but using relaxed
+  // atomics.
+  static void RelaxedCopyFromAtomic(void* dst, const std::atomic<uint64_t>* src,
+                                    size_t size) {
+    char* dst_byte = static_cast<char*>(dst);
+    while (size >= sizeof(uint64_t)) {
+      uint64_t word = src->load(std::memory_order_relaxed);
+      std::memcpy(dst_byte, &word, sizeof(word));
+      dst_byte += sizeof(word);
+      src++;
+      size -= sizeof(word);
+    }
+    if (size > 0) {
+      uint64_t word = src->load(std::memory_order_relaxed);
+      std::memcpy(dst_byte, &word, size);
+    }
+  }
+
+  // Perform the equivalent of "memcpy(dst, src, size)", but using relaxed
+  // atomics.
+  static void RelaxedCopyToAtomic(std::atomic<uint64_t>* dst, const void* src,
+                                  size_t size) {
+    const char* src_byte = static_cast<const char*>(src);
+    while (size >= sizeof(uint64_t)) {
+      uint64_t word;
+      std::memcpy(&word, src_byte, sizeof(word));
+      dst->store(word, std::memory_order_relaxed);
+      src_byte += sizeof(word);
+      dst++;
+      size -= sizeof(word);
+    }
+    if (size > 0) {
+      uint64_t word = 0;
+      std::memcpy(&word, src_byte, size);
+      dst->store(word, std::memory_order_relaxed);
+    }
+  }
+
+  static constexpr int64_t kUninitialized = -1;
+  std::atomic<int64_t> lock_;
+};
+
+}  // namespace flags_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
diff --git a/absl/flags/internal/sequence_lock_test.cc b/absl/flags/internal/sequence_lock_test.cc
new file mode 100644
index 0000000..9aff1ed
--- /dev/null
+++ b/absl/flags/internal/sequence_lock_test.cc
@@ -0,0 +1,146 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "absl/flags/internal/sequence_lock.h"
+
+#include <atomic>
+#include <thread>  // NOLINT(build/c++11)
+#include <tuple>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/sysinfo.h"
+#include "absl/container/fixed_array.h"
+#include "absl/time/clock.h"
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+class ConcurrentSequenceLockTest
+    : public testing::TestWithParam<std::tuple<int, int>> {
+ public:
+  ConcurrentSequenceLockTest()
+      : buf_bytes_(std::get<0>(GetParam())),
+        num_threads_(std::get<1>(GetParam())) {}
+
+ protected:
+  const int buf_bytes_;
+  const int num_threads_;
+};
+
+TEST_P(ConcurrentSequenceLockTest, ReadAndWrite) {
+  const int buf_words =
+      flags::AlignUp(buf_bytes_, sizeof(uint64_t)) / sizeof(uint64_t);
+
+  // The buffer that will be protected by the SequenceLock.
+  absl::FixedArray<std::atomic<uint64_t>> protected_buf(buf_words);
+  for (auto& v : protected_buf) v = -1;
+
+  flags::SequenceLock seq_lock;
+  std::atomic<bool> stop{false};
+  std::atomic<int64_t> bad_reads{0};
+  std::atomic<int64_t> good_reads{0};
+  std::atomic<int64_t> unsuccessful_reads{0};
+
+  // Start a bunch of threads which read 'protected_buf' under the sequence
+  // lock. The main thread will concurrently update 'protected_buf'. The updates
+  // always consist of an array of identical integers. The reader ensures that
+  // any data it reads matches that pattern (i.e. the reads are not "torn").
+  std::vector<std::thread> threads;
+  for (int i = 0; i < num_threads_; i++) {
+    threads.emplace_back([&]() {
+      absl::FixedArray<char> local_buf(buf_bytes_);
+      while (!stop.load(std::memory_order_relaxed)) {
+        if (seq_lock.TryRead(local_buf.data(), protected_buf.data(),
+                             buf_bytes_)) {
+          bool good = true;
+          for (const auto& v : local_buf) {
+            if (v != local_buf[0]) good = false;
+          }
+          if (good) {
+            good_reads.fetch_add(1, std::memory_order_relaxed);
+          } else {
+            bad_reads.fetch_add(1, std::memory_order_relaxed);
+          }
+        } else {
+          unsuccessful_reads.fetch_add(1, std::memory_order_relaxed);
+        }
+      }
+    });
+  }
+  while (unsuccessful_reads.load(std::memory_order_relaxed) < num_threads_) {
+    absl::SleepFor(absl::Milliseconds(1));
+  }
+  seq_lock.MarkInitialized();
+
+  // Run a maximum of 5 seconds. On Windows, the scheduler behavior seems
+  // somewhat unfair and without an explicit timeout for this loop, the tests
+  // can run a long time.
+  absl::Time deadline = absl::Now() + absl::Seconds(5);
+  for (int i = 0; i < 100 && absl::Now() < deadline; i++) {
+    absl::FixedArray<char> writer_buf(buf_bytes_);
+    for (auto& v : writer_buf) v = i;
+    seq_lock.Write(protected_buf.data(), writer_buf.data(), buf_bytes_);
+    absl::SleepFor(absl::Microseconds(10));
+  }
+  stop.store(true, std::memory_order_relaxed);
+  for (auto& t : threads) t.join();
+  ASSERT_GE(good_reads, 0);
+  ASSERT_EQ(bad_reads, 0);
+}
+
+// Simple helper for generating a range of thread counts.
+// Generates [low, low*scale, low*scale^2, ...high)
+// (even if high is between low*scale^k and low*scale^(k+1)).
+std::vector<int> MultiplicativeRange(int low, int high, int scale) {
+  std::vector<int> result;
+  for (int current = low; current < high; current *= scale) {
+    result.push_back(current);
+  }
+  result.push_back(high);
+  return result;
+}
+
+INSTANTIATE_TEST_SUITE_P(TestManyByteSizes, ConcurrentSequenceLockTest,
+                         testing::Combine(
+                             // Buffer size (bytes).
+                             testing::Range(1, 128),
+                             // Number of reader threads.
+                             testing::ValuesIn(MultiplicativeRange(
+                                 1, absl::base_internal::NumCPUs(), 2))));
+
+// Simple single-threaded test, parameterized by the size of the buffer to be
+// protected.
+class SequenceLockTest : public testing::TestWithParam<int> {};
+
+TEST_P(SequenceLockTest, SingleThreaded) {
+  const int size = GetParam();
+  absl::FixedArray<std::atomic<uint64_t>> protected_buf(
+      flags::AlignUp(size, sizeof(uint64_t)) / sizeof(uint64_t));
+
+  flags::SequenceLock seq_lock;
+  seq_lock.MarkInitialized();
+
+  std::vector<char> src_buf(size, 'x');
+  seq_lock.Write(protected_buf.data(), src_buf.data(), size);
+
+  std::vector<char> dst_buf(size, '0');
+  ASSERT_TRUE(seq_lock.TryRead(dst_buf.data(), protected_buf.data(), size));
+  ASSERT_EQ(src_buf, dst_buf);
+}
+INSTANTIATE_TEST_SUITE_P(TestManyByteSizes, SequenceLockTest,
+                         // Buffer size (bytes).
+                         testing::Range(1, 128));
+
+}  // namespace
diff --git a/absl/flags/internal/type_erased.cc b/absl/flags/internal/type_erased.cc
deleted file mode 100644
index a1650fc..0000000
--- a/absl/flags/internal/type_erased.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/flags/internal/type_erased.h"
-
-#include "absl/base/internal/raw_logging.h"
-#include "absl/flags/config.h"
-#include "absl/flags/usage_config.h"
-#include "absl/strings/str_cat.h"
-
-namespace absl {
-namespace flags_internal {
-
-bool GetCommandLineOption(absl::string_view name, std::string* value) {
-  if (name.empty()) return false;
-  assert(value);
-
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-  if (flag == nullptr || flag->IsRetired()) {
-    return false;
-  }
-
-  *value = flag->CurrentValue();
-  return true;
-}
-
-bool SetCommandLineOption(absl::string_view name, absl::string_view value) {
-  return SetCommandLineOptionWithMode(name, value,
-                                      flags_internal::SET_FLAGS_VALUE);
-}
-
-bool SetCommandLineOptionWithMode(absl::string_view name,
-                                  absl::string_view value,
-                                  FlagSettingMode set_mode) {
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-
-  if (!flag || flag->IsRetired()) return false;
-
-  std::string error;
-  if (!flag->SetFromString(value, set_mode, kProgrammaticChange, &error)) {
-    // Errors here are all of the form: the provided name was a recognized
-    // flag, but the value was invalid (bad type, or validation failed).
-    flags_internal::ReportUsageError(error, false);
-    return false;
-  }
-
-  return true;
-}
-
-// --------------------------------------------------------------------
-
-bool IsValidFlagValue(absl::string_view name, absl::string_view value) {
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-
-  return flag != nullptr &&
-         (flag->IsRetired() || flag->ValidateInputValue(value));
-}
-
-// --------------------------------------------------------------------
-
-bool SpecifiedOnCommandLine(absl::string_view name) {
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-  if (flag != nullptr && !flag->IsRetired()) {
-    return flag->IsSpecifiedOnCommandLine();
-  }
-  return false;
-}
-
-}  // namespace flags_internal
-}  // namespace absl
diff --git a/absl/flags/internal/type_erased.h b/absl/flags/internal/type_erased.h
deleted file mode 100644
index a955116..0000000
--- a/absl/flags/internal/type_erased.h
+++ /dev/null
@@ -1,86 +0,0 @@
-//
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
-#define ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
-
-#include <string>
-
-#include "absl/flags/internal/commandlineflag.h"
-#include "absl/flags/internal/registry.h"
-
-// --------------------------------------------------------------------
-// Registry interfaces operating on type erased handles.
-
-namespace absl {
-namespace flags_internal {
-
-// If a flag named "name" exists, store its current value in *OUTPUT
-// and return true.  Else return false without changing *OUTPUT.
-// Thread-safe.
-bool GetCommandLineOption(absl::string_view name, std::string* value);
-
-// Set the value of the flag named "name" to value.  If successful,
-// returns true.  If not successful (e.g., the flag was not found or
-// the value is not a valid value), returns false.
-// Thread-safe.
-bool SetCommandLineOption(absl::string_view name, absl::string_view value);
-
-bool SetCommandLineOptionWithMode(absl::string_view name,
-                                  absl::string_view value,
-                                  FlagSettingMode set_mode);
-
-//-----------------------------------------------------------------------------
-
-// Returns true iff all of the following conditions are true:
-// (a) "name" names a registered flag
-// (b) "value" can be parsed succesfully according to the type of the flag
-// (c) parsed value passes any validator associated with the flag
-bool IsValidFlagValue(absl::string_view name, absl::string_view value);
-
-//-----------------------------------------------------------------------------
-
-// Returns true iff a flag named "name" was specified on the command line
-// (either directly, or via one of --flagfile or --fromenv or --tryfromenv).
-//
-// Any non-command-line modification of the flag does not affect the
-// result of this function.  So for example, if a flag was passed on
-// the command line but then reset via SET_FLAGS_DEFAULT, this
-// function will still return true.
-bool SpecifiedOnCommandLine(absl::string_view name);
-
-//-----------------------------------------------------------------------------
-
-// If a flag with specified "name" exists and has type T, store
-// its current value in *dst and return true.  Else return false
-// without touching *dst.  T must obey all of the requirements for
-// types passed to DEFINE_FLAG.
-template <typename T>
-inline bool GetByName(absl::string_view name, T* dst) {
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-  if (!flag) return false;
-
-  if (auto val = flag->Get<T>()) {
-    *dst = *val;
-    return true;
-  }
-
-  return false;
-}
-
-}  // namespace flags_internal
-}  // namespace absl
-
-#endif  // ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
diff --git a/absl/flags/internal/type_erased_test.cc b/absl/flags/internal/type_erased_test.cc
deleted file mode 100644
index ac749a6..0000000
--- a/absl/flags/internal/type_erased_test.cc
+++ /dev/null
@@ -1,147 +0,0 @@
-//
-//  Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/flags/internal/type_erased.h"
-
-#include <cmath>
-
-#include "gtest/gtest.h"
-#include "absl/flags/flag.h"
-#include "absl/memory/memory.h"
-#include "absl/strings/str_cat.h"
-
-ABSL_FLAG(int, int_flag, 1, "int_flag help");
-ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
-ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
-
-namespace {
-
-namespace flags = absl::flags_internal;
-
-class TypeErasedTest : public testing::Test {
- protected:
-  void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); }
-  void TearDown() override { flag_saver_.reset(); }
-
- private:
-  std::unique_ptr<flags::FlagSaver> flag_saver_;
-};
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestGetCommandLineOption) {
-  std::string value;
-  EXPECT_TRUE(flags::GetCommandLineOption("int_flag", &value));
-  EXPECT_EQ(value, "1");
-
-  EXPECT_TRUE(flags::GetCommandLineOption("string_flag", &value));
-  EXPECT_EQ(value, "dflt");
-
-  EXPECT_FALSE(flags::GetCommandLineOption("bool_retired_flag", &value));
-
-  EXPECT_FALSE(flags::GetCommandLineOption("unknown_flag", &value));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOption) {
-  EXPECT_TRUE(flags::SetCommandLineOption("int_flag", "101"));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
-  EXPECT_TRUE(flags::SetCommandLineOption("string_flag", "asdfgh"));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
-  EXPECT_FALSE(flags::SetCommandLineOption("bool_retired_flag", "true"));
-
-  EXPECT_FALSE(flags::SetCommandLineOption("unknown_flag", "true"));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_VALUE) {
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
-                                                  flags::SET_FLAGS_VALUE));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
-                                                  flags::SET_FLAGS_VALUE));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
-                                                   flags::SET_FLAGS_VALUE));
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
-                                                   flags::SET_FLAGS_VALUE));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAG_IF_DEFAULT) {
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
-                                                  flags::SET_FLAG_IF_DEFAULT));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
-  // This semantic is broken. We return true instead of false. Value is not
-  // updated.
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202",
-                                                  flags::SET_FLAG_IF_DEFAULT));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
-                                                  flags::SET_FLAG_IF_DEFAULT));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
-                                                   flags::SET_FLAG_IF_DEFAULT));
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
-                                                   flags::SET_FLAG_IF_DEFAULT));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_DEFAULT) {
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
-                                                  flags::SET_FLAGS_DEFAULT));
-
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
-                                                  flags::SET_FLAGS_DEFAULT));
-  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
-                                                   flags::SET_FLAGS_DEFAULT));
-
-  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
-                                                   flags::SET_FLAGS_DEFAULT));
-
-  // This should be successfull, since flag is still is not set
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202",
-                                                  flags::SET_FLAG_IF_DEFAULT));
-  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 202);
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestIsValidFlagValue) {
-  EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "57"));
-  EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "-101"));
-  EXPECT_FALSE(flags::IsValidFlagValue("int_flag", "1.1"));
-
-  EXPECT_TRUE(flags::IsValidFlagValue("string_flag", "#%^#%^$%DGHDG$W%adsf"));
-
-  EXPECT_TRUE(flags::IsValidFlagValue("bool_retired_flag", "true"));
-}
-
-}  // namespace
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
index 0304851..a588c7f 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -15,38 +15,48 @@
 
 #include "absl/flags/internal/usage.h"
 
-#include <map>
-#include <string>
+#include <stdint.h>
 
+#include <functional>
+#include <map>
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
 #include "absl/flags/flag.h"
+#include "absl/flags/internal/flag.h"
 #include "absl/flags/internal/path_util.h"
+#include "absl/flags/internal/private_handle_accessor.h"
 #include "absl/flags/internal/program_name.h"
+#include "absl/flags/internal/registry.h"
 #include "absl/flags/usage_config.h"
-#include "absl/strings/ascii.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/str_split.h"
 #include "absl/strings/string_view.h"
-#include "absl/synchronization/mutex.h"
 
-ABSL_FLAG(bool, help, false,
-          "show help on important flags for this binary [tip: all flags can "
-          "have two dashes]");
-ABSL_FLAG(bool, helpfull, false, "show help on all flags");
-ABSL_FLAG(bool, helpshort, false,
-          "show help on only the main module for this program");
-ABSL_FLAG(bool, helppackage, false,
-          "show help on all modules in the main package");
-ABSL_FLAG(bool, version, false, "show version and build info and exit");
-ABSL_FLAG(bool, only_check_args, false, "exit after checking all flags");
-ABSL_FLAG(std::string, helpon, "",
-          "show help on the modules named by this flag value");
-ABSL_FLAG(std::string, helpmatch, "",
-          "show help on modules whose name contains the specified substr");
+// Dummy global variables to prevent anyone else defining these.
+bool FLAGS_help = false;
+bool FLAGS_helpfull = false;
+bool FLAGS_helpshort = false;
+bool FLAGS_helppackage = false;
+bool FLAGS_version = false;
+bool FLAGS_only_check_args = false;
+bool FLAGS_helpon = false;
+bool FLAGS_helpmatch = false;
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 namespace {
 
+using PerFlagFilter = std::function<bool(const absl::CommandLineFlag&)>;
+
+// Maximum length size in a human readable format.
+constexpr size_t kHrfMaxLineLength = 80;
+
 // This class is used to emit an XML element with `tag` and `text`.
 // It adds opening and closing tags and escapes special characters in the text.
 // For example:
@@ -99,21 +109,24 @@
  public:
   // Pretty printer holds on to the std::ostream& reference to direct an output
   // to that stream.
-  FlagHelpPrettyPrinter(int max_line_len, std::ostream* out)
-      : out_(*out),
+  FlagHelpPrettyPrinter(size_t max_line_len, size_t min_line_len,
+                        size_t wrapped_line_indent, std::ostream& out)
+      : out_(out),
         max_line_len_(max_line_len),
+        min_line_len_(min_line_len),
+        wrapped_line_indent_(wrapped_line_indent),
         line_len_(0),
         first_line_(true) {}
 
   void Write(absl::string_view str, bool wrap_line = false) {
-    // Empty std::string - do nothing.
+    // Empty string - do nothing.
     if (str.empty()) return;
 
     std::vector<absl::string_view> tokens;
     if (wrap_line) {
       for (auto line : absl::StrSplit(str, absl::ByAnyChar("\n\r"))) {
         if (!tokens.empty()) {
-          // Keep line separators in the input std::string.
+          // Keep line separators in the input string.
           tokens.push_back("\n");
         }
         for (auto token :
@@ -128,14 +141,15 @@
     for (auto token : tokens) {
       bool new_line = (line_len_ == 0);
 
-      // Respect line separators in the input std::string.
+      // Respect line separators in the input string.
       if (token == "\n") {
         EndLine();
         continue;
       }
 
-      // Write the token, ending the std::string first if necessary/possible.
-      if (!new_line && (line_len_ + token.size() >= max_line_len_)) {
+      // Write the token, ending the string first if necessary/possible.
+      if (!new_line &&
+          (line_len_ + static_cast<int>(token.size()) >= max_line_len_)) {
         EndLine();
         new_line = true;
       }
@@ -154,13 +168,12 @@
 
   void StartLine() {
     if (first_line_) {
-      out_ << "    ";
-      line_len_ = 4;
+      line_len_ = min_line_len_;
       first_line_ = false;
     } else {
-      out_ << "      ";
-      line_len_ = 6;
+      line_len_ = min_line_len_ + wrapped_line_indent_;
     }
+    out_ << std::string(line_len_, ' ');
   }
   void EndLine() {
     out_ << '\n';
@@ -169,38 +182,36 @@
 
  private:
   std::ostream& out_;
-  const int max_line_len_;
-  int line_len_;
+  const size_t max_line_len_;
+  const size_t min_line_len_;
+  const size_t wrapped_line_indent_;
+  size_t line_len_;
   bool first_line_;
 };
 
-void FlagHelpHumanReadable(const flags_internal::CommandLineFlag& flag,
-                           std::ostream* out) {
-  FlagHelpPrettyPrinter printer(80, out);  // Max line length is 80.
+void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
+  FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 4, 2, out);
 
   // Flag name.
-  printer.Write(absl::StrCat("-", flag.Name()));
+  printer.Write(absl::StrCat("--", flag.Name()));
 
   // Flag help.
   printer.Write(absl::StrCat("(", flag.Help(), ");"), /*wrap_line=*/true);
 
-  // Flag data type (for V1 flags only).
-  if (!flag.IsAbseilFlag() && !flag.IsRetired()) {
-    printer.Write(absl::StrCat("type: ", flag.Typename(), ";"));
-  }
-
   // The listed default value will be the actual default from the flag
   // definition in the originating source file, unless the value has
   // subsequently been modified using SetCommandLineOption() with mode
   // SET_FLAGS_DEFAULT.
   std::string dflt_val = flag.DefaultValue();
+  std::string curr_val = flag.CurrentValue();
+  bool is_modified = curr_val != dflt_val;
+
   if (flag.IsOfType<std::string>()) {
     dflt_val = absl::StrCat("\"", dflt_val, "\"");
   }
   printer.Write(absl::StrCat("default: ", dflt_val, ";"));
 
-  if (flag.IsModified()) {
-    std::string curr_val = flag.CurrentValue();
+  if (is_modified) {
     if (flag.IsOfType<std::string>()) {
       curr_val = absl::StrCat("\"", curr_val, "\"");
     }
@@ -215,7 +226,7 @@
 // If a flag's help message has been stripped (e.g. by adding '#define
 // STRIP_FLAG_HELP 1' then this flag will not be displayed by '--help'
 // and its variants.
-void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
+void FlagsHelpImpl(std::ostream& out, PerFlagFilter filter_cb,
                    HelpFormat format, absl::string_view program_usage_message) {
   if (format == HelpFormat::kHumanReadable) {
     out << flags_internal::ShortProgramInvocationName() << ": "
@@ -223,6 +234,9 @@
   } else {
     // XML schema is not a part of our public API for now.
     out << "<?xml version=\"1.0\"?>\n"
+        << "<!-- This output should be used with care. We do not report type "
+           "names for flags with user defined types -->\n"
+        << "<!-- Prefer flag only_check_args for validating flag inputs -->\n"
         // The document.
         << "<AllFlags>\n"
         // The program name and usage.
@@ -237,30 +251,28 @@
   // This map is used to output matching flags grouped by package and file
   // name.
   std::map<std::string,
-           std::map<std::string,
-                    std::vector<const flags_internal::CommandLineFlag*>>>
+           std::map<std::string, std::vector<const absl::CommandLineFlag*>>>
       matching_flags;
 
-  flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) {
-    std::string flag_filename = flag->Filename();
-
+  flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) {
     // Ignore retired flags.
-    if (flag->IsRetired()) return;
+    if (flag.IsRetired()) return;
 
     // If the flag has been stripped, pretend that it doesn't exist.
-    if (flag->Help() == flags_internal::kStrippedFlagHelp) return;
+    if (flag.Help() == flags_internal::kStrippedFlagHelp) return;
 
     // Make sure flag satisfies the filter
-    if (!filter_cb || !filter_cb(flag_filename)) return;
+    if (!filter_cb(flag)) return;
+
+    std::string flag_filename = flag.Filename();
 
     matching_flags[std::string(flags_internal::Package(flag_filename))]
                   [flag_filename]
-                      .push_back(flag);
+                      .push_back(&flag);
   });
 
-  absl::string_view
-      package_separator;             // controls blank lines between packages.
-  absl::string_view file_separator;  // controls blank lines between files.
+  absl::string_view package_separator;  // controls blank lines between packages
+  absl::string_view file_separator;     // controls blank lines between files
   for (const auto& package : matching_flags) {
     if (format == HelpFormat::kHumanReadable) {
       out << package_separator;
@@ -282,27 +294,46 @@
   }
 
   if (format == HelpFormat::kHumanReadable) {
+    FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 0, 0, out);
+
     if (filter_cb && matching_flags.empty()) {
-      out << "  No modules matched: use -helpfull\n";
+      printer.Write("No flags matched.\n", true);
     }
+    printer.EndLine();
+    printer.Write(
+        "Try --helpfull to get a list of all flags or --help=substring "
+        "shows help for flags which include specified substring in either "
+        "in the name, or description or path.\n",
+        true);
   } else {
     // The end of the document.
     out << "</AllFlags>\n";
   }
 }
 
+void FlagsHelpImpl(std::ostream& out,
+                   flags_internal::FlagKindFilter filename_filter_cb,
+                   HelpFormat format, absl::string_view program_usage_message) {
+  FlagsHelpImpl(
+      out,
+      [&](const absl::CommandLineFlag& flag) {
+        return filename_filter_cb && filename_filter_cb(flag.Filename());
+      },
+      format, program_usage_message);
+}
+
 }  // namespace
 
 // --------------------------------------------------------------------
 // Produces the help message describing specific flag.
-void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag,
+void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
               HelpFormat format) {
   if (format == HelpFormat::kHumanReadable)
-    flags_internal::FlagHelpHumanReadable(flag, &out);
+    flags_internal::FlagHelpHumanReadable(flag, out);
 }
 
 // --------------------------------------------------------------------
-// Produces the help messages for all flags matching the filter.
+// Produces the help messages for all flags matching the filename filter.
 // If filter is empty produces help messages for all flags.
 void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,
                absl::string_view program_usage_message) {
@@ -317,67 +348,171 @@
 // If so, handles them appropriately.
 int HandleUsageFlags(std::ostream& out,
                      absl::string_view program_usage_message) {
-  if (absl::GetFlag(FLAGS_helpshort)) {
-    flags_internal::FlagsHelpImpl(
-        out, flags_internal::GetUsageConfig().contains_helpshort_flags,
-        HelpFormat::kHumanReadable, program_usage_message);
-    return 1;
-  }
+  switch (GetFlagsHelpMode()) {
+    case HelpMode::kNone:
+      break;
+    case HelpMode::kImportant:
+      flags_internal::FlagsHelpImpl(
+          out, flags_internal::GetUsageConfig().contains_help_flags,
+          GetFlagsHelpFormat(), program_usage_message);
+      return 1;
 
-  if (absl::GetFlag(FLAGS_helpfull)) {
-    // show all options
-    flags_internal::FlagsHelp(out, "", HelpFormat::kHumanReadable,
-                              program_usage_message);
-    return 1;
-  }
+    case HelpMode::kShort:
+      flags_internal::FlagsHelpImpl(
+          out, flags_internal::GetUsageConfig().contains_helpshort_flags,
+          GetFlagsHelpFormat(), program_usage_message);
+      return 1;
 
-  if (!absl::GetFlag(FLAGS_helpon).empty()) {
-    flags_internal::FlagsHelp(
-        out, absl::StrCat("/", absl::GetFlag(FLAGS_helpon), "."),
-        HelpFormat::kHumanReadable, program_usage_message);
-    return 1;
-  }
+    case HelpMode::kFull:
+      flags_internal::FlagsHelp(out, "", GetFlagsHelpFormat(),
+                                program_usage_message);
+      return 1;
 
-  if (!absl::GetFlag(FLAGS_helpmatch).empty()) {
-    flags_internal::FlagsHelp(out, absl::GetFlag(FLAGS_helpmatch),
-                              HelpFormat::kHumanReadable,
-                              program_usage_message);
-    return 1;
-  }
+    case HelpMode::kPackage:
+      flags_internal::FlagsHelpImpl(
+          out, flags_internal::GetUsageConfig().contains_helppackage_flags,
+          GetFlagsHelpFormat(), program_usage_message);
 
-  if (absl::GetFlag(FLAGS_help)) {
-    flags_internal::FlagsHelpImpl(
-        out, flags_internal::GetUsageConfig().contains_help_flags,
-        HelpFormat::kHumanReadable, program_usage_message);
+      return 1;
 
-    out << "\nTry --helpfull to get a list of all flags.\n";
+    case HelpMode::kMatch: {
+      std::string substr = GetFlagsHelpMatchSubstr();
+      if (substr.empty()) {
+        // show all options
+        flags_internal::FlagsHelp(out, substr, GetFlagsHelpFormat(),
+                                  program_usage_message);
+      } else {
+        auto filter_cb = [&substr](const absl::CommandLineFlag& flag) {
+          if (absl::StrContains(flag.Name(), substr)) return true;
+          if (absl::StrContains(flag.Filename(), substr)) return true;
+          if (absl::StrContains(flag.Help(), substr)) return true;
 
-    return 1;
-  }
+          return false;
+        };
+        flags_internal::FlagsHelpImpl(
+            out, filter_cb, HelpFormat::kHumanReadable, program_usage_message);
+      }
 
-  if (absl::GetFlag(FLAGS_helppackage)) {
-    flags_internal::FlagsHelpImpl(
-        out, flags_internal::GetUsageConfig().contains_helppackage_flags,
-        HelpFormat::kHumanReadable, program_usage_message);
+      return 1;
+    }
+    case HelpMode::kVersion:
+      if (flags_internal::GetUsageConfig().version_string)
+        out << flags_internal::GetUsageConfig().version_string();
+      // Unlike help, we may be asking for version in a script, so return 0
+      return 0;
 
-    out << "\nTry --helpfull to get a list of all flags.\n";
-
-    return 1;
-  }
-
-  if (absl::GetFlag(FLAGS_version)) {
-    if (flags_internal::GetUsageConfig().version_string)
-      out << flags_internal::GetUsageConfig().version_string();
-    // Unlike help, we may be asking for version in a script, so return 0
-    return 0;
-  }
-
-  if (absl::GetFlag(FLAGS_only_check_args)) {
-    return 0;
+    case HelpMode::kOnlyCheckArgs:
+      return 0;
   }
 
   return -1;
 }
 
+// --------------------------------------------------------------------
+// Globals representing usage reporting flags
+
+namespace {
+
+ABSL_CONST_INIT absl::Mutex help_attributes_guard(absl::kConstInit);
+ABSL_CONST_INIT std::string* match_substr
+    ABSL_GUARDED_BY(help_attributes_guard) = nullptr;
+ABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(help_attributes_guard) =
+    HelpMode::kNone;
+ABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(help_attributes_guard) =
+    HelpFormat::kHumanReadable;
+
+}  // namespace
+
+std::string GetFlagsHelpMatchSubstr() {
+  absl::MutexLock l(&help_attributes_guard);
+  if (match_substr == nullptr) return "";
+  return *match_substr;
+}
+
+void SetFlagsHelpMatchSubstr(absl::string_view substr) {
+  absl::MutexLock l(&help_attributes_guard);
+  if (match_substr == nullptr) match_substr = new std::string;
+  match_substr->assign(substr.data(), substr.size());
+}
+
+HelpMode GetFlagsHelpMode() {
+  absl::MutexLock l(&help_attributes_guard);
+  return help_mode;
+}
+
+void SetFlagsHelpMode(HelpMode mode) {
+  absl::MutexLock l(&help_attributes_guard);
+  help_mode = mode;
+}
+
+HelpFormat GetFlagsHelpFormat() {
+  absl::MutexLock l(&help_attributes_guard);
+  return help_format;
+}
+
+void SetFlagsHelpFormat(HelpFormat format) {
+  absl::MutexLock l(&help_attributes_guard);
+  help_format = format;
+}
+
+// Deduces usage flags from the input argument in a form --name=value or
+// --name. argument is already split into name and value before we call this
+// function.
+bool DeduceUsageFlags(absl::string_view name, absl::string_view value) {
+  if (absl::ConsumePrefix(&name, "help")) {
+    if (name == "") {
+      if (value.empty()) {
+        SetFlagsHelpMode(HelpMode::kImportant);
+      } else {
+        SetFlagsHelpMode(HelpMode::kMatch);
+        SetFlagsHelpMatchSubstr(value);
+      }
+      return true;
+    }
+
+    if (name == "match") {
+      SetFlagsHelpMode(HelpMode::kMatch);
+      SetFlagsHelpMatchSubstr(value);
+      return true;
+    }
+
+    if (name == "on") {
+      SetFlagsHelpMode(HelpMode::kMatch);
+      SetFlagsHelpMatchSubstr(absl::StrCat("/", value, "."));
+      return true;
+    }
+
+    if (name == "full") {
+      SetFlagsHelpMode(HelpMode::kFull);
+      return true;
+    }
+
+    if (name == "short") {
+      SetFlagsHelpMode(HelpMode::kShort);
+      return true;
+    }
+
+    if (name == "package") {
+      SetFlagsHelpMode(HelpMode::kPackage);
+      return true;
+    }
+
+    return false;
+  }
+
+  if (name == "version") {
+    SetFlagsHelpMode(HelpMode::kVersion);
+    return true;
+  }
+
+  if (name == "only_check_args") {
+    SetFlagsHelpMode(HelpMode::kOnlyCheckArgs);
+    return true;
+  }
+
+  return false;
+}
+
 }  // namespace flags_internal
+ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/usage.h b/absl/flags/internal/usage.h
index 76075b0..c0bcac5 100644
--- a/absl/flags/internal/usage.h
+++ b/absl/flags/internal/usage.h
@@ -19,14 +19,16 @@
 #include <iosfwd>
 #include <string>
 
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
 #include "absl/flags/declare.h"
-#include "absl/flags/internal/commandlineflag.h"
 #include "absl/strings/string_view.h"
 
 // --------------------------------------------------------------------
 // Usage reporting interfaces
 
 namespace absl {
+ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 // The format to report the help messages in.
@@ -34,8 +36,9 @@
   kHumanReadable,
 };
 
-// Outputs the help message describing specific flag.
-void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag,
+// Streams the help message describing `flag` to `out`.
+// The default value for `flag` is included in the output.
+void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
               HelpFormat format = HelpFormat::kHumanReadable);
 
 // Produces the help messages for all flags matching the filter. A flag matches
@@ -63,16 +66,39 @@
 int HandleUsageFlags(std::ostream& out,
                      absl::string_view program_usage_message);
 
-}  // namespace flags_internal
-}  // namespace absl
+// --------------------------------------------------------------------
+// Globals representing usage reporting flags
 
-ABSL_DECLARE_FLAG(bool, help);
-ABSL_DECLARE_FLAG(bool, helpfull);
-ABSL_DECLARE_FLAG(bool, helpshort);
-ABSL_DECLARE_FLAG(bool, helppackage);
-ABSL_DECLARE_FLAG(bool, version);
-ABSL_DECLARE_FLAG(bool, only_check_args);
-ABSL_DECLARE_FLAG(std::string, helpon);
-ABSL_DECLARE_FLAG(std::string, helpmatch);
+enum class HelpMode {
+  kNone,
+  kImportant,
+  kShort,
+  kFull,
+  kPackage,
+  kMatch,
+  kVersion,
+  kOnlyCheckArgs
+};
+
+// Returns substring to filter help output (--help=substr argument)
+std::string GetFlagsHelpMatchSubstr();
+// Returns the requested help mode.
+HelpMode GetFlagsHelpMode();
+// Returns the requested help format.
+HelpFormat GetFlagsHelpFormat();
+
+// These are corresponding setters to the attributes above.
+void SetFlagsHelpMatchSubstr(absl::string_view);
+void SetFlagsHelpMode(HelpMode);
+void SetFlagsHelpFormat(HelpFormat);
+
+// Deduces usage flags from the input argument in a form --name=value or
+// --name. argument is already split into name and value before we call this
+// function.
+bool DeduceUsageFlags(absl::string_view name, absl::string_view value);
+
+}  // namespace flags_internal
+ABSL_NAMESPACE_END
+}  // namespace absl
 
 #endif  // ABSL_FLAGS_INTERNAL_USAGE_H_
diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc
index d15e448..b5c2487 100644
--- a/absl/flags/internal/usage_test.cc
+++ b/absl/flags/internal/usage_test.cc
@@ -15,17 +15,21 @@
 
 #include "absl/flags/internal/usage.h"
 
+#include <stdint.h>
+
 #include <sstream>
+#include <string>
 
 #include "gtest/gtest.h"
 #include "absl/flags/flag.h"
+#include "absl/flags/internal/parse.h"
 #include "absl/flags/internal/path_util.h"
 #include "absl/flags/internal/program_name.h"
-#include "absl/flags/parse.h"
+#include "absl/flags/reflection.h"
 #include "absl/flags/usage.h"
 #include "absl/flags/usage_config.h"
-#include "absl/memory/memory.h"
 #include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
 
 ABSL_FLAG(int, usage_reporting_test_flag_01, 101,
           "usage_reporting_test_flag_01 help message");
@@ -83,9 +87,14 @@
     default_config.normalize_filename = &NormalizeFileName;
     absl::SetFlagsUsageConfig(default_config);
   }
+  ~UsageReportingTest() override {
+    flags::SetFlagsHelpMode(flags::HelpMode::kNone);
+    flags::SetFlagsHelpMatchSubstr("");
+    flags::SetFlagsHelpFormat(flags::HelpFormat::kHumanReadable);
+  }
 
  private:
-  flags::FlagSaver flag_saver_;
+  absl::FlagSaver flag_saver_;
 };
 
 // --------------------------------------------------------------------
@@ -97,69 +106,70 @@
 
 #ifndef _WIN32
   // TODO(rogeeff): figure out why this does not work on Windows.
-  EXPECT_DEATH(absl::SetProgramUsageMessage("custom usage message"),
-               ".*SetProgramUsageMessage\\(\\) called twice.*");
+  EXPECT_DEATH_IF_SUPPORTED(
+      absl::SetProgramUsageMessage("custom usage message"),
+      ".*SetProgramUsageMessage\\(\\) called twice.*");
 #endif
 }
 
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {
-  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_01");
+  const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_01");
   std::stringstream test_buf;
 
   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
   EXPECT_EQ(
       test_buf.str(),
-      R"(    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+      R"(    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
 )");
 }
 
 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
-  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_02");
+  const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_02");
   std::stringstream test_buf;
 
   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
   EXPECT_EQ(
       test_buf.str(),
-      R"(    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+      R"(    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
 )");
 }
 
 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {
-  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_03");
+  const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_03");
   std::stringstream test_buf;
 
   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
   EXPECT_EQ(
       test_buf.str(),
-      R"(    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+      R"(    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
 )");
 }
 
 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
-  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_04");
+  const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_04");
   std::stringstream test_buf;
 
   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
   EXPECT_EQ(
       test_buf.str(),
-      R"(    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+      R"(    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
 )");
 }
 
 TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) {
-  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_05");
+  const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_05");
   std::stringstream test_buf;
 
   flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
   EXPECT_EQ(
       test_buf.str(),
-      R"(    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+      R"(    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
 )");
 }
@@ -171,21 +181,25 @@
       R"(usage_test: Custom usage message
 
   Flags from absl/flags/internal/usage_test.cc:
-    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
-    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
-    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
-    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
-    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
-    -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
 
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )";
 
   std::stringstream test_buf_01;
@@ -209,7 +223,11 @@
   EXPECT_EQ(test_buf_04.str(),
             R"(usage_test: Custom usage message
 
-  No modules matched: use -helpfull
+No flags matched.
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 
   std::stringstream test_buf_05;
@@ -221,12 +239,8 @@
       absl::StartsWith(test_out_str, "usage_test: Custom usage message"));
   EXPECT_TRUE(absl::StrContains(
       test_out_str, "Flags from absl/flags/internal/usage_test.cc:"));
-  EXPECT_TRUE(absl::StrContains(test_out_str,
-                                "Flags from absl/flags/internal/usage.cc:"));
   EXPECT_TRUE(
       absl::StrContains(test_out_str, "-usage_reporting_test_flag_01 "));
-  EXPECT_TRUE(absl::StrContains(test_out_str, "-help (show help"))
-      << test_out_str;
 }
 
 // --------------------------------------------------------------------
@@ -239,7 +253,7 @@
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_helpshort) {
-  absl::SetFlag(&FLAGS_helpshort, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kShort);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -247,28 +261,32 @@
             R"(usage_test: Custom usage message
 
   Flags from absl/flags/internal/usage_test.cc:
-    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
-    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
-    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
-    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
-    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
-    -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
 
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }
 
 // --------------------------------------------------------------------
 
-TEST_F(UsageReportingTest, TestUsageFlag_help) {
-  absl::SetFlag(&FLAGS_help, true);
+TEST_F(UsageReportingTest, TestUsageFlag_help_simple) {
+  flags::SetFlagsHelpMode(flags::HelpMode::kImportant);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -276,30 +294,90 @@
             R"(usage_test: Custom usage message
 
   Flags from absl/flags/internal/usage_test.cc:
-    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
-    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
-    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
-    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
-    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
-    -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
 
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
 
-Try --helpfull to get a list of all flags.
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_help_one_flag) {
+  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+  flags::SetFlagsHelpMatchSubstr("usage_reporting_test_flag_06");
+
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+  EXPECT_EQ(test_buf.str(),
+            R"(usage_test: Custom usage message
+
+  Flags from absl/flags/internal/usage_test.cc:
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+      Some more help.
+      Even more long long long long long long long long long long long long help
+      message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) {
+  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+  flags::SetFlagsHelpMatchSubstr("test_flag");
+
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+  EXPECT_EQ(test_buf.str(),
+            R"(usage_test: Custom usage message
+
+  Flags from absl/flags/internal/usage_test.cc:
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+      default: 101;
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+      default: false;
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+      default: 1.03;
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+      default: 1000000000000004;
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+      default: UDT{};
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+      Some more help.
+      Even more long long long long long long long long long long long long help
+      message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }
 
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
-  absl::SetFlag(&FLAGS_helppackage, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kPackage);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -307,30 +385,32 @@
             R"(usage_test: Custom usage message
 
   Flags from absl/flags/internal/usage_test.cc:
-    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
-    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
-    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
-    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
-    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
-    -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
 
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
 
-Try --helpfull to get a list of all flags.
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }
 
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_version) {
-  absl::SetFlag(&FLAGS_version, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kVersion);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
@@ -344,7 +424,7 @@
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
-  absl::SetFlag(&FLAGS_only_check_args, true);
+  flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs);
 
   std::stringstream test_buf;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
@@ -354,17 +434,22 @@
 // --------------------------------------------------------------------
 
 TEST_F(UsageReportingTest, TestUsageFlag_helpon) {
-  absl::SetFlag(&FLAGS_helpon, "bla-bla");
+  flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+  flags::SetFlagsHelpMatchSubstr("/bla-bla.");
 
   std::stringstream test_buf_01;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), 1);
   EXPECT_EQ(test_buf_01.str(),
             R"(usage_test: Custom usage message
 
-  No modules matched: use -helpfull
+No flags matched.
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 
-  absl::SetFlag(&FLAGS_helpon, "usage_test");
+  flags::SetFlagsHelpMatchSubstr("/usage_test.");
 
   std::stringstream test_buf_02;
   EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1);
@@ -372,21 +457,25 @@
             R"(usage_test: Custom usage message
 
   Flags from absl/flags/internal/usage_test.cc:
-    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+    --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
       default: 101;
-    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+    --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
       default: false;
-    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+    --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
       default: 1.03;
-    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+    --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
       default: 1000000000000004;
-    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+    --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
       default: UDT{};
-    -usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+    --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
 
       Some more help.
       Even more long long long long long long long long long long long long help
       message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
 )");
 }