about summary refs log tree commit diff
path: root/absl/flags
diff options
context:
space:
mode:
Diffstat (limited to 'absl/flags')
-rw-r--r--absl/flags/BUILD.bazel171
-rw-r--r--absl/flags/CMakeLists.txt140
-rw-r--r--absl/flags/commandlineflag.cc (renamed from absl/flags/internal/commandlineflag.cc)14
-rw-r--r--absl/flags/commandlineflag.h196
-rw-r--r--absl/flags/commandlineflag_test.cc (renamed from absl/flags/internal/commandlineflag_test.cc)108
-rw-r--r--absl/flags/declare.h1
-rw-r--r--absl/flags/flag.cc2
-rw-r--r--absl/flags/flag.h142
-rw-r--r--absl/flags/flag_benchmark.cc7
-rw-r--r--absl/flags/flag_test.cc402
-rw-r--r--absl/flags/internal/commandlineflag.h119
-rw-r--r--absl/flags/internal/flag.cc48
-rw-r--r--absl/flags/internal/flag.h105
-rw-r--r--absl/flags/internal/parse.h1
-rw-r--r--absl/flags/internal/path_util.h1
-rw-r--r--absl/flags/internal/private_handle_accessor.cc18
-rw-r--r--absl/flags/internal/private_handle_accessor.h12
-rw-r--r--absl/flags/internal/program_name_test.cc4
-rw-r--r--absl/flags/internal/registry.h43
-rw-r--r--absl/flags/internal/type_erased.cc86
-rw-r--r--absl/flags/internal/type_erased.h79
-rw-r--r--absl/flags/internal/type_erased_test.cc157
-rw-r--r--absl/flags/internal/usage.cc33
-rw-r--r--absl/flags/internal/usage.h4
-rw-r--r--absl/flags/internal/usage_test.cc16
-rw-r--r--absl/flags/marshalling.cc21
-rw-r--r--absl/flags/parse.cc45
-rw-r--r--absl/flags/parse.h1
-rw-r--r--absl/flags/parse_test.cc34
-rw-r--r--absl/flags/reflection.cc (renamed from absl/flags/internal/registry.cc)296
-rw-r--r--absl/flags/reflection.h85
-rw-r--r--absl/flags/reflection_test.cc60
-rw-r--r--absl/flags/usage_config.cc1
33 files changed, 1236 insertions, 1216 deletions
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index 368108252741..006911fd8e71 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -27,28 +27,18 @@ package(default_visibility = ["//visibility:public"])
 licenses(["notice"])  # Apache 2.0
 
 cc_library(
-    name = "flag_internal",
-    srcs = [
-        "internal/flag.cc",
-    ],
+    name = "path_util",
     hdrs = [
-        "internal/flag.h",
+        "internal/path_util.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = ["//absl/base:__subpackages__"],
+    visibility = [
+        "//absl/flags:__pkg__",
+    ],
     deps = [
-        ":config",
-        ":handle",
-        ":marshalling",
-        ":registry",
-        "//absl/base",
         "//absl/base:config",
-        "//absl/base:core_headers",
-        "//absl/memory",
-        "//absl/meta:type_traits",
         "//absl/strings",
-        "//absl/synchronization",
     ],
 )
 
@@ -75,22 +65,6 @@ cc_library(
 )
 
 cc_library(
-    name = "path_util",
-    hdrs = [
-        "internal/path_util.h",
-    ],
-    copts = ABSL_DEFAULT_COPTS,
-    linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl/flags:__pkg__",
-    ],
-    deps = [
-        "//absl/base:config",
-        "//absl/strings",
-    ],
-)
-
-cc_library(
     name = "config",
     srcs = [
         "usage_config.cc",
@@ -131,21 +105,32 @@ cc_library(
 )
 
 cc_library(
-    name = "handle",
-    srcs = [
-        "internal/commandlineflag.cc",
-    ],
+    name = "commandlineflag_internal",
     hdrs = [
         "internal/commandlineflag.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl/flags:__pkg__",
+    visibility = ["//visibility:private"],
+    deps = [
+        "//absl/base:config",
+        "//absl/base:fast_type_id",
     ],
+)
+
+cc_library(
+    name = "commandlineflag",
+    srcs = [
+        "commandlineflag.cc",
+    ],
+    hdrs = [
+        "commandlineflag.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":commandlineflag_internal",
         "//absl/base:config",
-        "//absl/base:core_headers",
         "//absl/base:fast_type_id",
         "//absl/strings",
         "//absl/types:optional",
@@ -165,37 +150,66 @@ cc_library(
     visibility = [
         "//absl/flags:__pkg__",
     ],
-    deps = [":handle"],
+    deps = [
+        ":commandlineflag",
+        ":commandlineflag_internal",
+        "//absl/base:config",
+        "//absl/strings",
+    ],
 )
 
 cc_library(
-    name = "registry",
+    name = "reflection",
     srcs = [
-        "internal/registry.cc",
-        "internal/type_erased.cc",
+        "reflection.cc",
     ],
     hdrs = [
         "internal/registry.h",
-        "internal/type_erased.h",
+        "reflection.h",
     ],
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
-    visibility = [
-        "//absl/flags:__pkg__",
-    ],
     deps = [
+        ":commandlineflag",
+        ":commandlineflag_internal",
         ":config",
-        ":handle",
         ":private_handle_accessor",
         "//absl/base:config",
         "//absl/base:core_headers",
-        "//absl/base:raw_logging_internal",
         "//absl/strings",
         "//absl/synchronization",
     ],
 )
 
 cc_library(
+    name = "flag_internal",
+    srcs = [
+        "internal/flag.cc",
+    ],
+    hdrs = [
+        "internal/flag.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = ["//absl/base:__subpackages__"],
+    deps = [
+        ":commandlineflag",
+        ":commandlineflag_internal",
+        ":config",
+        ":marshalling",
+        ":reflection",
+        "//absl/base",
+        "//absl/base:config",
+        "//absl/base:core_headers",
+        "//absl/memory",
+        "//absl/meta:type_traits",
+        "//absl/strings",
+        "//absl/synchronization",
+        "//absl/utility",
+    ],
+)
+
+cc_library(
     name = "flag",
     srcs = [
         "flag.cc",
@@ -209,9 +223,7 @@ cc_library(
     deps = [
         ":config",
         ":flag_internal",
-        ":handle",
-        ":marshalling",
-        ":registry",
+        ":reflection",
         "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
@@ -233,14 +245,14 @@ cc_library(
         "//absl/flags:__pkg__",
     ],
     deps = [
+        ":commandlineflag",
         ":config",
         ":flag",
         ":flag_internal",
-        ":handle",
         ":path_util",
         ":private_handle_accessor",
         ":program_name",
-        ":registry",
+        ":reflection",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/strings",
@@ -276,13 +288,14 @@ cc_library(
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":commandlineflag",
+        ":commandlineflag_internal",
         ":config",
         ":flag",
         ":flag_internal",
-        ":handle",
         ":private_handle_accessor",
         ":program_name",
-        ":registry",
+        ":reflection",
         ":usage",
         ":usage_internal",
         "//absl/base:config",
@@ -299,16 +312,17 @@ cc_test(
     name = "commandlineflag_test",
     size = "small",
     srcs = [
-        "internal/commandlineflag_test.cc",
+        "commandlineflag_test.cc",
     ],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":commandlineflag",
+        ":commandlineflag_internal",
         ":config",
         ":flag",
-        ":handle",
         ":private_handle_accessor",
-        ":registry",
+        ":reflection",
         "//absl/memory",
         "//absl/strings",
         "@com_google_googletest//:gtest_main",
@@ -342,8 +356,8 @@ cc_test(
         ":config",
         ":flag",
         ":flag_internal",
-        ":handle",
-        ":registry",
+        ":marshalling",
+        ":reflection",
         "//absl/base:core_headers",
         "//absl/base:malloc_internal",
         "//absl/strings",
@@ -363,6 +377,8 @@ cc_binary(
     visibility = ["//visibility:private"],
     deps = [
         ":flag",
+        ":marshalling",
+        "//absl/strings",
         "//absl/time",
         "//absl/types:optional",
         "@com_github_google_benchmark//:benchmark_main",
@@ -384,35 +400,35 @@ cc_test(
 )
 
 cc_test(
-    name = "path_util_test",
+    name = "parse_test",
     size = "small",
     srcs = [
-        "internal/path_util_test.cc",
+        "parse_test.cc",
     ],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        ":path_util",
+        ":flag",
+        ":parse",
+        ":reflection",
+        "//absl/base:raw_logging_internal",
+        "//absl/base:scoped_set_env",
+        "//absl/strings",
+        "//absl/types:span",
         "@com_google_googletest//:gtest_main",
     ],
 )
 
 cc_test(
-    name = "parse_test",
+    name = "path_util_test",
     size = "small",
     srcs = [
-        "parse_test.cc",
+        "internal/path_util_test.cc",
     ],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
-        ":flag",
-        ":parse",
-        ":registry",
-        "//absl/base:raw_logging_internal",
-        "//absl/base:scoped_set_env",
-        "//absl/strings",
-        "//absl/types:span",
+        ":path_util",
         "@com_google_googletest//:gtest_main",
     ],
 )
@@ -433,18 +449,18 @@ cc_test(
 )
 
 cc_test(
-    name = "type_erased_test",
+    name = "reflection_test",
     size = "small",
     srcs = [
-        "internal/type_erased_test.cc",
+        "reflection_test.cc",
     ],
     copts = ABSL_TEST_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":commandlineflag_internal",
         ":flag",
-        ":handle",
         ":marshalling",
-        ":registry",
+        ":reflection",
         "//absl/memory",
         "@com_google_googletest//:gtest_main",
     ],
@@ -481,10 +497,9 @@ cc_test(
         ":parse",
         ":path_util",
         ":program_name",
-        ":registry",
+        ":reflection",
         ":usage",
         ":usage_internal",
-        "//absl/memory",
         "//absl/strings",
         "@com_google_googletest//:gtest",
     ],
diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt
index e6b17c9b048c..ef75db8e9c5f 100644
--- a/absl/flags/CMakeLists.txt
+++ b/absl/flags/CMakeLists.txt
@@ -17,24 +17,16 @@
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
-    flags_internal
-  SRCS
-    "internal/flag.cc"
+    flags_path_util
   HDRS
-    "internal/flag.h"
+    "internal/path_util.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
-    absl::base
     absl::config
-    absl::flags_config
-    absl::flags_handle
-    absl::flags_marshalling
-    absl::flags_registry
-    absl::synchronization
-    absl::meta
+    absl::strings
   PUBLIC
 )
 
@@ -59,22 +51,6 @@ absl_cc_library(
   PUBLIC
 )
 
-# Internal-only target, do not depend on directly.
-absl_cc_library(
-  NAME
-    flags_path_util
-  HDRS
-    "internal/path_util.h"
-  COPTS
-    ${ABSL_DEFAULT_COPTS}
-  LINKOPTS
-    ${ABSL_DEFAULT_LINKOPTS}
-  DEPS
-    absl::config
-    absl::strings
-  PUBLIC
-)
-
 absl_cc_library(
   NAME
     flags_config
@@ -118,9 +94,7 @@ absl_cc_library(
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
-    flags_handle
-  SRCS
-    "internal/commandlineflag.cc"
+    flags_commandlineflag_internal
   HDRS
     "internal/commandlineflag.h"
   COPTS
@@ -130,11 +104,25 @@ absl_cc_library(
   DEPS
     absl::config
     absl::fast_type_id
-    absl::core_headers
+)
+
+absl_cc_library(
+  NAME
+    flags_commandlineflag
+  SRCS
+    "commandlineflag.cc"
+  HDRS
+    "commandlineflag.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::fast_type_id
+    absl::flags_commandlineflag_internal
     absl::optional
-    absl::raw_logging_internal
     absl::strings
-    absl::synchronization
 )
 
 # Internal-only target, do not depend on directly.
@@ -150,34 +138,57 @@ absl_cc_library(
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
-    absl::flags_handle
+    absl::config
+    absl::flags_commandlineflag
+    absl::flags_commandlineflag_internal
+    absl::strings
 )
 
-# Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
-    flags_registry
+    flags_reflection
   SRCS
-    "internal/registry.cc"
-    "internal/type_erased.cc"
+    "reflection.cc"
   HDRS
+    "reflection.h"
     "internal/registry.h"
-    "internal/type_erased.h"
   COPTS
     ${ABSL_DEFAULT_COPTS}
   LINKOPTS
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::config
-    absl::flags_config
-    absl::flags_handle
+    absl::flags_commandlineflag
     absl::flags_private_handle_accessor
-    absl::core_headers
-    absl::raw_logging_internal
+    absl::flags_config
     absl::strings
     absl::synchronization
 )
 
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    flags_internal
+  SRCS
+    "internal/flag.cc"
+  HDRS
+    "internal/flag.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::base
+    absl::config
+    absl::flags_commandlineflag_internal
+    absl::flags_config
+    absl::flags_marshalling
+    absl::synchronization
+    absl::meta
+    absl::utility
+  PUBLIC
+)
+
 absl_cc_library(
   NAME
     flags
@@ -192,11 +203,10 @@ absl_cc_library(
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::config
+    absl::flags_commandlineflag
     absl::flags_config
-    absl::flags_handle
     absl::flags_internal
-    absl::flags_marshalling
-    absl::flags_registry
+    absl::flags_reflection
     absl::base
     absl::core_headers
     absl::strings
@@ -218,12 +228,12 @@ absl_cc_library(
     absl::config
     absl::flags_config
     absl::flags
-    absl::flags_handle
-    absl::flags_private_handle_accessor
+    absl::flags_commandlineflag
     absl::flags_internal
     absl::flags_path_util
+    absl::flags_private_handle_accessor
     absl::flags_program_name
-    absl::flags_registry
+    absl::flags_reflection
     absl::strings
     absl::synchronization
 )
@@ -264,11 +274,12 @@ absl_cc_library(
     absl::core_headers
     absl::flags_config
     absl::flags
-    absl::flags_handle
-    absl::flags_private_handle_accessor
+    absl::flags_commandlineflag
+    absl::flags_commandlineflag_internal
     absl::flags_internal
+    absl::flags_private_handle_accessor
     absl::flags_program_name
-    absl::flags_registry
+    absl::flags_reflection
     absl::flags_usage
     absl::strings
     absl::synchronization
@@ -281,15 +292,16 @@ absl_cc_test(
   NAME
     flags_commandlineflag_test
   SRCS
-    "internal/commandlineflag_test.cc"
+    "commandlineflag_test.cc"
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
     absl::flags
+    absl::flags_commandlineflag
+    absl::flags_commandlineflag_internal
     absl::flags_config
-    absl::flags_handle
     absl::flags_private_handle_accessor
-    absl::flags_registry
+    absl::flags_reflection
     absl::memory
     absl::strings
     gtest_main
@@ -319,9 +331,9 @@ absl_cc_test(
     absl::core_headers
     absl::flags
     absl::flags_config
-    absl::flags_handle
     absl::flags_internal
-    absl::flags_registry
+    absl::flags_marshalling
+    absl::flags_reflection
     absl::strings
     absl::time
     gtest_main
@@ -349,7 +361,7 @@ absl_cc_test(
   DEPS
     absl::flags
     absl::flags_parse
-    absl::flags_registry
+    absl::flags_reflection
     absl::raw_logging_internal
     absl::scoped_set_env
     absl::span
@@ -384,16 +396,15 @@ absl_cc_test(
 
 absl_cc_test(
   NAME
-    flags_type_erased_test
+    flags_reflection_test
   SRCS
-    "internal/type_erased_test.cc"
+    "reflection_test.cc"
   COPTS
     ${ABSL_TEST_COPTS}
   DEPS
+    absl::flags_commandlineflag_internal
     absl::flags
-    absl::flags_handle
-    absl::flags_marshalling
-    absl::flags_registry
+    absl::flags_reflection
     absl::memory
     absl::strings
     gtest_main
@@ -427,9 +438,8 @@ absl_cc_test(
     absl::flags_path_util
     absl::flags_program_name
     absl::flags_parse
-    absl::flags_registry
+    absl::flags_reflection
     absl::flags_usage
-    absl::memory
     absl::strings
     gtest
 )
diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/commandlineflag.cc
index 84112437d9cf..217b2d870079 100644
--- a/absl/flags/internal/commandlineflag.cc
+++ b/absl/flags/commandlineflag.cc
@@ -13,21 +13,25 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "absl/flags/commandlineflag.h"
+
+#include <string>
+
+#include "absl/base/config.h"
 #include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
-namespace flags_internal {
-
-FlagStateInterface::~FlagStateInterface() {}
 
 bool CommandLineFlag::IsRetired() const { return false; }
-
 bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) {
   return ParseFrom(value, flags_internal::SET_FLAGS_VALUE,
-                   flags_internal::kProgrammaticChange, error);
+                   flags_internal::kProgrammaticChange, *error);
 }
 
+namespace flags_internal {
+FlagStateInterface::~FlagStateInterface() {}
 }  // namespace flags_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/commandlineflag.h b/absl/flags/commandlineflag.h
new file mode 100644
index 000000000000..7e21d05d8a53
--- /dev/null
+++ b/absl/flags/commandlineflag.h
@@ -0,0 +1,196 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: commandlineflag.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `CommandLineFlag`, which acts as a type-erased
+// handle for accessing metadata about the Abseil Flag in question.
+//
+// Because an actual Abseil flag is of an unspecified type, you should not
+// manipulate or interact directly with objects of that type. Instead, use the
+// CommandLineFlag type as an intermediary.
+#ifndef ABSL_FLAGS_COMMANDLINEFLAG_H_
+#define ABSL_FLAGS_COMMANDLINEFLAG_H_
+
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+class PrivateHandleAccessor;
+}  // namespace flags_internal
+
+// CommandLineFlag
+//
+// This type acts as a type-erased handle for an instance of an Abseil Flag and
+// holds reflection information pertaining to that flag. Use CommandLineFlag to
+// access a flag's name, location, help string etc.
+//
+// To obtain an absl::CommandLineFlag, invoke `absl::FindCommandLineFlag()`
+// passing it the flag name string.
+//
+// Example:
+//
+//   // Obtain reflection handle for a flag named "flagname".
+//   const absl::CommandLineFlag* my_flag_data =
+//        absl::FindCommandLineFlag("flagname");
+//
+//   // Now you can get flag info from that reflection handle.
+//   std::string flag_location = my_flag_data->Filename();
+//   ...
+class CommandLineFlag {
+ public:
+  constexpr CommandLineFlag() = default;
+
+  // Not copyable/assignable.
+  CommandLineFlag(const CommandLineFlag&) = delete;
+  CommandLineFlag& operator=(const CommandLineFlag&) = delete;
+
+  // absl::CommandLineFlag::IsOfType()
+  //
+  // Return true iff flag has type T.
+  template <typename T>
+  inline bool IsOfType() const {
+    return TypeId() == base_internal::FastTypeId<T>();
+  }
+
+  // absl::CommandLineFlag::TryGet()
+  //
+  // Attempts to retrieve the flag value. Returns value on success,
+  // absl::nullopt otherwise.
+  template <typename T>
+  absl::optional<T> TryGet() const {
+    if (IsRetired() || !IsOfType<T>()) {
+      return absl::nullopt;
+    }
+
+    // Implementation notes:
+    //
+    // We are wrapping a union around the value of `T` to serve three purposes:
+    //
+    //  1. `U.value` has correct size and alignment for a value of type `T`
+    //  2. The `U.value` constructor is not invoked since U's constructor does
+    //     not do it explicitly.
+    //  3. The `U.value` destructor is invoked since U's destructor does it
+    //     explicitly. This makes `U` a kind of RAII wrapper around non default
+    //     constructible value of T, which is destructed when we leave the
+    //     scope. We do need to destroy U.value, which is constructed by
+    //     CommandLineFlag::Read even though we left it in a moved-from state
+    //     after std::move.
+    //
+    // All of this serves to avoid requiring `T` being default constructible.
+    union U {
+      T value;
+      U() {}
+      ~U() { value.~T(); }
+    };
+    U u;
+
+    Read(&u.value);
+    return std::move(u.value);
+  }
+
+  // absl::CommandLineFlag::Name()
+  //
+  // Returns name of this flag.
+  virtual absl::string_view Name() const = 0;
+
+  // absl::CommandLineFlag::Filename()
+  //
+  // Returns name of the file where this flag is defined.
+  virtual std::string Filename() const = 0;
+
+  // absl::CommandLineFlag::Help()
+  //
+  // Returns help message associated with this flag.
+  virtual std::string Help() const = 0;
+
+  // absl::CommandLineFlag::IsRetired()
+  //
+  // Returns true iff this object corresponds to retired flag.
+  virtual bool IsRetired() const;
+
+  // absl::CommandLineFlag::DefaultValue()
+  //
+  // Returns the default value for this flag.
+  virtual std::string DefaultValue() const = 0;
+
+  // absl::CommandLineFlag::CurrentValue()
+  //
+  // Returns the current value for this flag.
+  virtual std::string CurrentValue() const = 0;
+
+  // absl::CommandLineFlag::ParseFrom()
+  //
+  // Sets the value of the flag based on specified string `value`. If the flag
+  // was successfully set to new value, it returns true. Otherwise, sets `error`
+  // to indicate the error, leaves the flag unchanged, and returns false.
+  bool ParseFrom(absl::string_view value, std::string* error);
+
+ protected:
+  ~CommandLineFlag() = default;
+
+ private:
+  friend class flags_internal::PrivateHandleAccessor;
+
+  // Sets the value of the flag based on specified string `value`. If the flag
+  // was successfully set to new value, it returns true. Otherwise, sets `error`
+  // to indicate the error, leaves the flag unchanged, and returns false. There
+  // are three ways to set the flag's value:
+  //  * Update the current flag value
+  //  * Update the flag's default value
+  //  * Update the current flag value if it was never set before
+  // The mode is selected based on `set_mode` parameter.
+  virtual bool ParseFrom(absl::string_view value,
+                         flags_internal::FlagSettingMode set_mode,
+                         flags_internal::ValueSource source,
+                         std::string& error) = 0;
+
+  // Returns id of the flag's value type.
+  virtual flags_internal::FlagFastTypeId TypeId() const = 0;
+
+  // Interface to save flag to some persistent state. Returns current flag state
+  // or nullptr if flag does not support saving and restoring a state.
+  virtual std::unique_ptr<flags_internal::FlagStateInterface> SaveState() = 0;
+
+  // Copy-construct a new value of the flag's type in a memory referenced by
+  // the dst based on the current flag's value.
+  virtual void Read(void* dst) const = 0;
+
+  // To be deleted. Used to return true if flag's current value originated from
+  // command line.
+  virtual bool IsSpecifiedOnCommandLine() const = 0;
+
+  // Validates supplied value usign validator or parseflag routine
+  virtual bool ValidateInputValue(absl::string_view value) const = 0;
+
+  // Checks that flags default value can be converted to string and back to the
+  // flag's value type.
+  virtual void CheckDefaultValueParsingRoundtrip() const = 0;
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_COMMANDLINEFLAG_H_
diff --git a/absl/flags/internal/commandlineflag_test.cc b/absl/flags/commandlineflag_test.cc
index 0b5aea379219..585db4ba78a0 100644
--- a/absl/flags/internal/commandlineflag_test.cc
+++ b/absl/flags/commandlineflag_test.cc
@@ -13,15 +13,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/commandlineflag.h"
 
 #include <memory>
 #include <string>
 
 #include "gtest/gtest.h"
 #include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/internal/private_handle_accessor.h"
-#include "absl/flags/internal/registry.h"
+#include "absl/flags/reflection.h"
 #include "absl/flags/usage_config.h"
 #include "absl/memory/memory.h"
 #include "absl/strings/match.h"
@@ -33,6 +34,10 @@ ABSL_FLAG(std::string, string_flag, "dflt",
           absl::StrCat("string_flag", " help"));
 ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
 
+// These are only used to test default values.
+ABSL_FLAG(int, int_flag2, 201, "");
+ABSL_FLAG(std::string, string_flag2, "dflt", "");
+
 namespace {
 
 namespace flags = absl::flags_internal;
@@ -46,7 +51,7 @@ class CommandLineFlagTest : public testing::Test {
     absl::SetFlagsUsageConfig(default_config);
   }
 
-  void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); }
+  void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
   void TearDown() override { flag_saver_.reset(); }
 
  private:
@@ -59,56 +64,49 @@ class CommandLineFlagTest : public testing::Test {
     return std::string(fname);
   }
 
-  std::unique_ptr<flags::FlagSaver> flag_saver_;
+  std::unique_ptr<absl::FlagSaver> flag_saver_;
 };
 
 TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+  auto* flag_01 = absl::FindCommandLineFlag("int_flag");
 
   ASSERT_TRUE(flag_01);
   EXPECT_EQ(flag_01->Name(), "int_flag");
   EXPECT_EQ(flag_01->Help(), "int_flag help");
   EXPECT_TRUE(!flag_01->IsRetired());
   EXPECT_TRUE(flag_01->IsOfType<int>());
-  EXPECT_TRUE(
-      absl::EndsWith(flag_01->Filename(),
-                     "absl/flags/internal/commandlineflag_test.cc"))
+  EXPECT_TRUE(!flag_01->IsOfType<bool>());
+  EXPECT_TRUE(!flag_01->IsOfType<std::string>());
+  EXPECT_TRUE(absl::EndsWith(flag_01->Filename(),
+                             "absl/flags/commandlineflag_test.cc"))
       << flag_01->Filename();
 
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+  auto* flag_02 = absl::FindCommandLineFlag("string_flag");
 
   ASSERT_TRUE(flag_02);
   EXPECT_EQ(flag_02->Name(), "string_flag");
   EXPECT_EQ(flag_02->Help(), "string_flag help");
   EXPECT_TRUE(!flag_02->IsRetired());
   EXPECT_TRUE(flag_02->IsOfType<std::string>());
-  EXPECT_TRUE(
-      absl::EndsWith(flag_02->Filename(),
-                     "absl/flags/internal/commandlineflag_test.cc"))
+  EXPECT_TRUE(!flag_02->IsOfType<bool>());
+  EXPECT_TRUE(!flag_02->IsOfType<int>());
+  EXPECT_TRUE(absl::EndsWith(flag_02->Filename(),
+                             "absl/flags/commandlineflag_test.cc"))
       << flag_02->Filename();
-
-  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_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");
+  absl::SetFlag(&FLAGS_int_flag2, 301);
+  auto* flag_01 = absl::FindCommandLineFlag("int_flag2");
 
   ASSERT_TRUE(flag_01);
   EXPECT_EQ(flag_01->CurrentValue(), "301");
   EXPECT_EQ(flag_01->DefaultValue(), "201");
 
-  absl::SetFlag(&FLAGS_string_flag, "new_str_value");
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+  absl::SetFlag(&FLAGS_string_flag2, "new_str_value");
+  auto* flag_02 = absl::FindCommandLineFlag("string_flag2");
 
   ASSERT_TRUE(flag_02);
   EXPECT_EQ(flag_02->CurrentValue(), "new_str_value");
@@ -120,62 +118,62 @@ TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
 TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
   std::string err;
 
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+  auto* flag_01 = absl::FindCommandLineFlag("int_flag");
   EXPECT_FALSE(
       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
 
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "11", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));
+      *flag_01, "11", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
   EXPECT_FALSE(
       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
 
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "-123", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
-      &err));
+      *flag_01, "-123", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+      err));
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
   EXPECT_FALSE(
       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
 
   EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
-      &err));
+      *flag_01, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+      err));
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
   EXPECT_EQ(err, "Illegal value 'xyz' specified for flag 'int_flag'");
   EXPECT_FALSE(
       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
 
   EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "A1", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));
+      *flag_01, "A1", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
   EXPECT_EQ(err, "Illegal value 'A1' specified for flag 'int_flag'");
   EXPECT_FALSE(
       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
 
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "0x10", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
-      &err));
+      *flag_01, "0x10", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+      err));
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);
   EXPECT_FALSE(
       flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
 
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "011", flags::SET_FLAGS_VALUE, flags::kCommandLine, &err));
+      *flag_01, "011", flags::SET_FLAGS_VALUE, flags::kCommandLine, err));
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
   EXPECT_TRUE(flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
 
   EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));
+      *flag_01, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
   EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'");
 
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+  auto* flag_02 = absl::FindCommandLineFlag("string_flag");
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_02, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
-      &err));
+      *flag_02, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+      err));
   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz");
 
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_02, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err));
+      *flag_02, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
   EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
 }
 
@@ -184,18 +182,18 @@ TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
 TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {
   std::string err;
 
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+  auto* flag_01 = absl::FindCommandLineFlag("int_flag");
 
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
-      &err));
+      *flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
+      err));
   EXPECT_EQ(flag_01->DefaultValue(), "111");
 
-  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+  auto* flag_02 = absl::FindCommandLineFlag("string_flag");
 
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
-      &err));
+      *flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
+      err));
   EXPECT_EQ(flag_02->DefaultValue(), "abc");
 }
 
@@ -204,28 +202,28 @@ TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {
 TEST_F(CommandLineFlagTest, TestParseFromIfDefault) {
   std::string err;
 
-  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+  auto* flag_01 = absl::FindCommandLineFlag("int_flag");
 
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "22", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
-      &err))
+      *flag_01, "22", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+      err))
       << err;
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
 
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
-      &err));
+      *flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+      err));
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
   // EXPECT_EQ(err, "ERROR: int_flag is already set to 22");
 
   // Reset back to default value
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "201", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
-      &err));
+      *flag_01, "201", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+      err));
 
   EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
-      flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
-      &err));
+      *flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+      err));
   EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201);
   // EXPECT_EQ(err, "ERROR: int_flag is already set to 201");
 }
diff --git a/absl/flags/declare.h b/absl/flags/declare.h
index 0f8cc6a59972..b9794d8b85ac 100644
--- a/absl/flags/declare.h
+++ b/absl/flags/declare.h
@@ -26,7 +26,6 @@
 #define ABSL_FLAGS_DECLARE_H_
 
 #include "absl/base/config.h"
-#include "absl/strings/string_view.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/flags/flag.cc b/absl/flags/flag.cc
index f7a457bf0ce2..531df1287a17 100644
--- a/absl/flags/flag.cc
+++ b/absl/flags/flag.cc
@@ -16,8 +16,6 @@
 #include "absl/flags/flag.h"
 
 #include "absl/base/config.h"
-#include "absl/flags/internal/commandlineflag.h"
-#include "absl/flags/internal/flag.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index ca7d581fce71..90dc2894df54 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -33,14 +33,11 @@
 #include <type_traits>
 
 #include "absl/base/attributes.h"
-#include "absl/base/casts.h"
 #include "absl/base/config.h"
+#include "absl/base/optimization.h"
 #include "absl/flags/config.h"
-#include "absl/flags/declare.h"
-#include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/internal/flag.h"
 #include "absl/flags/internal/registry.h"
-#include "absl/flags/marshalling.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
@@ -111,12 +108,12 @@ class Flag {
         impl_(nullptr) {}
 #endif
 
-  flags_internal::Flag<T>* GetImpl() const {
+  flags_internal::Flag<T>& GetImpl() const {
     if (!inited_.load(std::memory_order_acquire)) {
       absl::MutexLock l(flags_internal::GetGlobalConstructionGuard());
 
       if (inited_.load(std::memory_order_acquire)) {
-        return impl_;
+        return *impl_;
       }
 
       impl_ = new flags_internal::Flag<T>(
@@ -128,28 +125,30 @@ class Flag {
       inited_.store(true, std::memory_order_release);
     }
 
-    return impl_;
+    return *impl_;
   }
 
   // Public methods of `absl::Flag<T>` are NOT part of the Abseil Flags API.
   // See https://abseil.io/docs/cpp/guides/flags
-  bool IsRetired() const { return GetImpl()->IsRetired(); }
-  absl::string_view Name() const { return GetImpl()->Name(); }
-  std::string Help() const { return GetImpl()->Help(); }
-  bool IsModified() const { return GetImpl()->IsModified(); }
+  bool IsRetired() const { return GetImpl().IsRetired(); }
+  absl::string_view Name() const { return GetImpl().Name(); }
+  std::string Help() const { return GetImpl().Help(); }
+  bool IsModified() const { return GetImpl().IsModified(); }
   bool IsSpecifiedOnCommandLine() const {
-    return GetImpl()->IsSpecifiedOnCommandLine();
+    return GetImpl().IsSpecifiedOnCommandLine();
   }
-  std::string Filename() const { return GetImpl()->Filename(); }
-  std::string DefaultValue() const { return GetImpl()->DefaultValue(); }
-  std::string CurrentValue() const { return GetImpl()->CurrentValue(); }
+  std::string Filename() const { return GetImpl().Filename(); }
+  std::string DefaultValue() const { return GetImpl().DefaultValue(); }
+  std::string CurrentValue() const { return GetImpl().CurrentValue(); }
   template <typename U>
   inline bool IsOfType() const {
-    return GetImpl()->template IsOfType<U>();
+    return GetImpl().template IsOfType<U>();
   }
-  T Get() const { return GetImpl()->Get(); }
-  void Set(const T& v) { GetImpl()->Set(v); }
-  void InvokeCallback() { GetImpl()->InvokeCallback(); }
+  T Get() const { return GetImpl().Get(); }
+  void Set(const T& v) { GetImpl().Set(v); }
+  void InvokeCallback() { GetImpl().InvokeCallback(); }
+
+  const CommandLineFlag& Reflect() const { return GetImpl().Reflect(); }
 
   // The data members are logically private, but they need to be public for
   // this to be an aggregate type.
@@ -205,6 +204,21 @@ void SetFlag(absl::Flag<T>* flag, const V& v) {
   flag->Set(value);
 }
 
+// GetFlagReflectionHandle()
+//
+// Returns the reflection handle corresponding to specified Abseil Flag
+// instance. Use this handle to access flag's reflection information, like name,
+// location, default value etc.
+//
+// Example:
+//
+//   std::string = absl::GetFlagReflectionHandle(FLAGS_count).DefaultValue();
+
+template <typename T>
+const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
+  return f.Reflect();
+}
+
 ABSL_NAMESPACE_END
 }  // namespace absl
 
@@ -265,27 +279,29 @@ ABSL_NAMESPACE_END
 // -----------------------------------------------------------------------------
 
 // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES
+#if !defined(_MSC_VER) || defined(__clang__)
+#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag
+#define ABSL_FLAG_IMPL_HELP_ARG(name)                      \
+  absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \
+      FLAGS_help_storage_##name)
+#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) \
+  absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)
+#else
+#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag.GetImpl()
+#define ABSL_FLAG_IMPL_HELP_ARG(name) &AbslFlagHelpGenFor##name::NonConst
+#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) &AbslFlagDefaultGenFor##name::Gen
+#endif
 
 #if ABSL_FLAGS_STRIP_NAMES
 #define ABSL_FLAG_IMPL_FLAGNAME(txt) ""
 #define ABSL_FLAG_IMPL_FILENAME() ""
-#if !defined(_MSC_VER) || defined(__clang__)
 #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, false>(&flag)
-#else
-#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, false>(flag.GetImpl())
-#endif
+  absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
 #else
 #define ABSL_FLAG_IMPL_FLAGNAME(txt) txt
 #define ABSL_FLAG_IMPL_FILENAME() __FILE__
-#if !defined(_MSC_VER) || defined(__clang__)
 #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, true>(&flag)
-#else
-#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, true>(flag.GetImpl())
-#endif
+  absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
 #endif
 
 // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
@@ -301,15 +317,24 @@ ABSL_NAMESPACE_END
 // between the two via the call to HelpArg in absl::Flag instantiation below.
 // If help message expression is constexpr evaluable compiler will optimize
 // away this whole struct.
-#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt)                     \
-  struct AbslFlagHelpGenFor##name {                                        \
-    template <typename T = void>                                           \
-    static constexpr const char* Const() {                                 \
-      return absl::flags_internal::HelpConstexprWrap(                      \
-          ABSL_FLAG_IMPL_FLAGHELP(txt));                                   \
-    }                                                                      \
-    static std::string NonConst() { return ABSL_FLAG_IMPL_FLAGHELP(txt); } \
-  }
+// TODO(rogeeff): place these generated structs into local namespace and apply
+// ABSL_INTERNAL_UNIQUE_SHORT_NAME.
+// TODO(rogeeff): Apply __attribute__((nodebug)) to FLAGS_help_storage_##name
+#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt)                       \
+  struct AbslFlagHelpGenFor##name {                                          \
+    /* The expression is run in the caller as part of the   */               \
+    /* default value argument. That keeps temporaries alive */               \
+    /* long enough for NonConst to work correctly.          */               \
+    static constexpr absl::string_view Value(                                \
+        absl::string_view v = ABSL_FLAG_IMPL_FLAGHELP(txt)) {                \
+      return v;                                                              \
+    }                                                                        \
+    static std::string NonConst() { return std::string(Value()); }           \
+  };                                                                         \
+  constexpr auto FLAGS_help_storage_##name ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
+      ABSL_ATTRIBUTE_SECTION_VARIABLE(flags_help_cold) =                     \
+          absl::flags_internal::HelpStringAsArray<AbslFlagHelpGenFor##name>( \
+              0);
 
 #define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)     \
   struct AbslFlagDefaultGenFor##name {                                        \
@@ -317,40 +342,23 @@ ABSL_NAMESPACE_END
     static void Gen(void* p) {                                                \
       new (p) Type(AbslFlagDefaultGenFor##name{}.value);                      \
     }                                                                         \
-  }
+  };
 
 // ABSL_FLAG_IMPL
 //
 // Note: Name of registrar object is not arbitrary. It is used to "grab"
 // global name for FLAGS_no<flag_name> symbol, thus preventing the possibility
 // of defining two flags with names foo and nofoo.
-#if !defined(_MSC_VER) || defined(__clang__)
-
-#define ABSL_FLAG_IMPL(Type, name, default_value, help)                        \
-  namespace absl /* block flags in namespaces */ {}                            \
-  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value);           \
-  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help);                             \
-  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                               \
-      ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(),               \
-      absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>(0),              \
-      absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)}; \
-  extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;              \
-  absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =                    \
+#define ABSL_FLAG_IMPL(Type, name, default_value, help)                       \
+  namespace absl /* block flags in namespaces */ {}                           \
+  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)           \
+  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help)                             \
+  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                              \
+      ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(),              \
+      ABSL_FLAG_IMPL_HELP_ARG(name), ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \
+  extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;             \
+  absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =                   \
       ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
-#else
-// MSVC version uses aggregate initialization. We also do not try to
-// optimize away help wrapper.
-#define ABSL_FLAG_IMPL(Type, name, default_value, help)                        \
-  namespace absl /* block flags in namespaces */ {}                            \
-  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value);           \
-  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help);                             \
-  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                               \
-      ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(),               \
-      &AbslFlagHelpGenFor##name::NonConst, &AbslFlagDefaultGenFor##name::Gen}; \
-  extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;              \
-  absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =                    \
-      ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
-#endif
 
 // ABSL_RETIRED_FLAG
 //
diff --git a/absl/flags/flag_benchmark.cc b/absl/flags/flag_benchmark.cc
index ff95bb5d7bfc..7b52c9bc9f1c 100644
--- a/absl/flags/flag_benchmark.cc
+++ b/absl/flags/flag_benchmark.cc
@@ -13,7 +13,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
 #include "absl/flags/flag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/strings/string_view.h"
 #include "absl/time/time.h"
 #include "absl/types/optional.h"
 #include "benchmark/benchmark.h"
diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc
index 416a31e5232a..2eb2ba71d37c 100644
--- a/absl/flags/flag_test.cc
+++ b/absl/flags/flag_test.cc
@@ -15,9 +15,11 @@
 
 #include "absl/flags/flag.h"
 
+#include <stddef.h>
 #include <stdint.h>
 
 #include <cmath>
+#include <new>
 #include <string>
 #include <thread>  // NOLINT
 #include <vector>
@@ -26,9 +28,9 @@
 #include "absl/base/attributes.h"
 #include "absl/flags/config.h"
 #include "absl/flags/declare.h"
-#include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/internal/flag.h"
-#include "absl/flags/internal/registry.h"
+#include "absl/flags/marshalling.h"
+#include "absl/flags/reflection.h"
 #include "absl/flags/usage_config.h"
 #include "absl/strings/match.h"
 #include "absl/strings/numbers.h"
@@ -45,6 +47,9 @@ namespace {
 namespace flags = absl::flags_internal;
 
 std::string TestHelpMsg() { return "dynamic help"; }
+#if defined(_MSC_VER) && !defined(__clang__)
+std::string TestLiteralHelpMsg() { return "literal help"; }
+#endif
 template <typename T>
 void TestMakeDflt(void* dst) {
   new (dst) T{};
@@ -76,7 +81,7 @@ class FlagTest : public testing::Test {
 #endif
     return std::string(fname);
   }
-  flags::FlagSaver flag_saver_;
+  absl::FlagSaver flag_saver_;
 };
 
 struct S1 {
@@ -128,15 +133,29 @@ constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"),
 
 using String = std::string;
 
-#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind)                      \
-  constexpr flags::FlagDefaultArg f1default##T{                          \
-      flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind};   \
-  constexpr flags::Flag<T> f1##T("f1", "file", help_arg, f1default##T);  \
-  ABSL_CONST_INIT flags::Flag<T> f2##T(                                  \
-      "f2", "file",                                                      \
-      {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
-      flags::FlagDefaultArg{flags::FlagDefaultSrc(&TestMakeDflt<T>),     \
-                            flags::FlagDefaultKind::kGenFunc})
+#if !defined(_MSC_VER) || defined(__clang__)
+#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind)                        \
+  constexpr flags::FlagDefaultArg f1default##T{                            \
+      flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind};     \
+  constexpr absl::Flag<T> f1##T{"f1", "file", help_arg, f1default##T};     \
+  ABSL_CONST_INIT absl::Flag<T> f2##T {                                    \
+    "f2", "file",                                                          \
+        {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
+        flags::FlagDefaultArg {                                            \
+      flags::FlagDefaultSrc(&TestMakeDflt<T>),                             \
+          flags::FlagDefaultKind::kGenFunc                                 \
+    }                                                                      \
+  }
+#else
+#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind)                    \
+  constexpr flags::FlagDefaultArg f1default##T{                        \
+      flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
+  constexpr absl::Flag<T> f1##T{"f1", "file", &TestLiteralHelpMsg,     \
+                                &TestMakeDflt<T>};                     \
+  ABSL_CONST_INIT absl::Flag<T> f2##T {                                \
+    "f2", "file", &TestHelpMsg, &TestMakeDflt<T>                       \
+  }
+#endif
 
 DEFINE_CONSTRUCTED_FLAG(bool, true, kOneWord);
 DEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord);
@@ -151,21 +170,22 @@ DEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc);
 DEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc);
 
 template <typename T>
-bool TestConstructionFor(const flags::Flag<T>& f1, flags::Flag<T>* f2) {
-  EXPECT_EQ(f1.Name(), "f1");
-  EXPECT_EQ(f1.Help(), "literal help");
-  EXPECT_EQ(f1.Filename(), "file");
+bool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Name(), "f1");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), "literal help");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), "file");
 
-  flags::FlagRegistrar<T, false>(f2).OnUpdate(TestCallback);
+  flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2))
+      .OnUpdate(TestCallback);
 
-  EXPECT_EQ(f2->Name(), "f2");
-  EXPECT_EQ(f2->Help(), "dynamic help");
-  EXPECT_EQ(f2->Filename(), "file");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), "dynamic help");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), "file");
 
   return true;
 }
 
-#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, &f2##T);
+#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);
 
 TEST_F(FlagTest, TestConstruction) {
   TEST_CONSTRUCTED_FLAG(bool);
@@ -204,18 +224,30 @@ namespace {
 
 TEST_F(FlagTest, TestFlagDeclaration) {
   // test that we can access flag objects.
-  EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");
-  EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");
-  EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");
-  EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");
-  EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");
-  EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");
-  EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");
-  EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");
-  EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");
-  EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");
-  EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11");
-  EXPECT_EQ(FLAGS_test_flag_12.Name(), "test_flag_12");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
+            "test_flag_01");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
+            "test_flag_02");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
+            "test_flag_03");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
+            "test_flag_04");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
+            "test_flag_05");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
+            "test_flag_06");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
+            "test_flag_07");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
+            "test_flag_08");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
+            "test_flag_09");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
+            "test_flag_10");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
+            "test_flag_11");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
+            "test_flag_12");
 }
 #endif  // !ABSL_FLAGS_STRIP_NAMES
 
@@ -242,96 +274,168 @@ namespace {
 TEST_F(FlagTest, TestFlagDefinition) {
   absl::string_view expected_file_name = "absl/flags/flag_test.cc";
 
-  EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");
-  EXPECT_EQ(FLAGS_test_flag_01.Help(), "test flag 01");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_01.Filename(), expected_file_name))
-      << FLAGS_test_flag_01.Filename();
-
-  EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");
-  EXPECT_EQ(FLAGS_test_flag_02.Help(), "test flag 02");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_02.Filename(), expected_file_name))
-      << FLAGS_test_flag_02.Filename();
-
-  EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");
-  EXPECT_EQ(FLAGS_test_flag_03.Help(), "test flag 03");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_03.Filename(), expected_file_name))
-      << FLAGS_test_flag_03.Filename();
-
-  EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");
-  EXPECT_EQ(FLAGS_test_flag_04.Help(), "test flag 04");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_04.Filename(), expected_file_name))
-      << FLAGS_test_flag_04.Filename();
-
-  EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");
-  EXPECT_EQ(FLAGS_test_flag_05.Help(), "test flag 05");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_05.Filename(), expected_file_name))
-      << FLAGS_test_flag_05.Filename();
-
-  EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");
-  EXPECT_EQ(FLAGS_test_flag_06.Help(), "test flag 06");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_06.Filename(), expected_file_name))
-      << FLAGS_test_flag_06.Filename();
-
-  EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");
-  EXPECT_EQ(FLAGS_test_flag_07.Help(), "test flag 07");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_07.Filename(), expected_file_name))
-      << FLAGS_test_flag_07.Filename();
-
-  EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");
-  EXPECT_EQ(FLAGS_test_flag_08.Help(), "test flag 08");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_08.Filename(), expected_file_name))
-      << FLAGS_test_flag_08.Filename();
-
-  EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");
-  EXPECT_EQ(FLAGS_test_flag_09.Help(), "test flag 09");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_09.Filename(), expected_file_name))
-      << FLAGS_test_flag_09.Filename();
-
-  EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");
-  EXPECT_EQ(FLAGS_test_flag_10.Help(), "test flag 10");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_10.Filename(), expected_file_name))
-      << FLAGS_test_flag_10.Filename();
-
-  EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11");
-  EXPECT_EQ(FLAGS_test_flag_11.Help(), "test flag 11");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_11.Filename(), expected_file_name))
-      << FLAGS_test_flag_11.Filename();
-
-  EXPECT_EQ(FLAGS_test_flag_12.Name(), "test_flag_12");
-  EXPECT_EQ(FLAGS_test_flag_12.Help(), "test flag 12");
-  EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_12.Filename(), expected_file_name))
-      << FLAGS_test_flag_12.Filename();
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
+            "test_flag_01");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(),
+            "test flag 01");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
+            "test_flag_02");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(),
+            "test flag 02");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
+            "test_flag_03");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(),
+            "test flag 03");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
+            "test_flag_04");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(),
+            "test flag 04");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
+            "test_flag_05");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(),
+            "test flag 05");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
+            "test_flag_06");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(),
+            "test flag 06");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
+            "test_flag_07");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(),
+            "test flag 07");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
+            "test_flag_08");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(),
+            "test flag 08");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
+            "test_flag_09");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(),
+            "test flag 09");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
+            "test_flag_10");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(),
+            "test flag 10");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
+            "test_flag_11");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(),
+            "test flag 11");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename();
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
+            "test_flag_12");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(),
+            "test flag 12");
+  EXPECT_TRUE(absl::EndsWith(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(),
+      expected_file_name))
+      << absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename();
 }
 #endif  // !ABSL_FLAGS_STRIP_NAMES
 
 // --------------------------------------------------------------------
 
 TEST_F(FlagTest, TestDefault) {
-  EXPECT_EQ(FLAGS_test_flag_01.DefaultValue(), "true");
-  EXPECT_EQ(FLAGS_test_flag_02.DefaultValue(), "1234");
-  EXPECT_EQ(FLAGS_test_flag_03.DefaultValue(), "-34");
-  EXPECT_EQ(FLAGS_test_flag_04.DefaultValue(), "189");
-  EXPECT_EQ(FLAGS_test_flag_05.DefaultValue(), "10765");
-  EXPECT_EQ(FLAGS_test_flag_06.DefaultValue(), "40000");
-  EXPECT_EQ(FLAGS_test_flag_07.DefaultValue(), "-1234567");
-  EXPECT_EQ(FLAGS_test_flag_08.DefaultValue(), "9876543");
-  EXPECT_EQ(FLAGS_test_flag_09.DefaultValue(), "-9.876e-50");
-  EXPECT_EQ(FLAGS_test_flag_10.DefaultValue(), "1.234e+12");
-  EXPECT_EQ(FLAGS_test_flag_11.DefaultValue(), "");
-  EXPECT_EQ(FLAGS_test_flag_12.DefaultValue(), "10m");
-
-  EXPECT_EQ(FLAGS_test_flag_01.CurrentValue(), "true");
-  EXPECT_EQ(FLAGS_test_flag_02.CurrentValue(), "1234");
-  EXPECT_EQ(FLAGS_test_flag_03.CurrentValue(), "-34");
-  EXPECT_EQ(FLAGS_test_flag_04.CurrentValue(), "189");
-  EXPECT_EQ(FLAGS_test_flag_05.CurrentValue(), "10765");
-  EXPECT_EQ(FLAGS_test_flag_06.CurrentValue(), "40000");
-  EXPECT_EQ(FLAGS_test_flag_07.CurrentValue(), "-1234567");
-  EXPECT_EQ(FLAGS_test_flag_08.CurrentValue(), "9876543");
-  EXPECT_EQ(FLAGS_test_flag_09.CurrentValue(), "-9.876e-50");
-  EXPECT_EQ(FLAGS_test_flag_10.CurrentValue(), "1.234e+12");
-  EXPECT_EQ(FLAGS_test_flag_11.CurrentValue(), "");
-  EXPECT_EQ(FLAGS_test_flag_12.CurrentValue(), "10m");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(),
+            "true");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(),
+            "1234");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(),
+            "-34");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(),
+            "189");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(),
+            "10765");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(),
+            "40000");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(),
+            "-1234567");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(),
+            "9876543");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(),
+            "-9.876e-50");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(),
+            "1.234e+12");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(),
+            "");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).DefaultValue(),
+            "10m");
+
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(),
+            "true");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(),
+            "1234");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(),
+            "-34");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(),
+            "189");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(),
+            "10765");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(),
+            "40000");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(),
+            "-1234567");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(),
+            "9876543");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(),
+            "-9.876e-50");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(),
+            "1.234e+12");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(),
+            "");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(),
+            "10m");
 
   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
@@ -386,12 +490,18 @@ ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, "");
 namespace {
 
 TEST_F(FlagTest, TestEmptyBracesDefault) {
-  EXPECT_EQ(FLAGS_test_flag_eb_01.DefaultValue(), "false");
-  EXPECT_EQ(FLAGS_test_flag_eb_02.DefaultValue(), "0");
-  EXPECT_EQ(FLAGS_test_flag_eb_03.DefaultValue(), "0");
-  EXPECT_EQ(FLAGS_test_flag_eb_04.DefaultValue(), "0");
-  EXPECT_EQ(FLAGS_test_flag_eb_05.DefaultValue(), "");
-  EXPECT_EQ(FLAGS_test_flag_eb_06.DefaultValue(), "0");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(),
+            "false");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(),
+            "0");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(),
+            "0");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(),
+            "0");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(),
+            "");
+  EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_06).DefaultValue(),
+            "0");
 
   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false);
   EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0);
@@ -445,29 +555,29 @@ TEST_F(FlagTest, TestGetSet) {
 // --------------------------------------------------------------------
 
 TEST_F(FlagTest, TestGetViaReflection) {
-  auto* handle = flags::FindCommandLineFlag("test_flag_01");
+  auto* handle = absl::FindCommandLineFlag("test_flag_01");
   EXPECT_EQ(*handle->TryGet<bool>(), true);
-  handle = flags::FindCommandLineFlag("test_flag_02");
+  handle = absl::FindCommandLineFlag("test_flag_02");
   EXPECT_EQ(*handle->TryGet<int>(), 1234);
-  handle = flags::FindCommandLineFlag("test_flag_03");
+  handle = absl::FindCommandLineFlag("test_flag_03");
   EXPECT_EQ(*handle->TryGet<int16_t>(), -34);
-  handle = flags::FindCommandLineFlag("test_flag_04");
+  handle = absl::FindCommandLineFlag("test_flag_04");
   EXPECT_EQ(*handle->TryGet<uint16_t>(), 189);
-  handle = flags::FindCommandLineFlag("test_flag_05");
+  handle = absl::FindCommandLineFlag("test_flag_05");
   EXPECT_EQ(*handle->TryGet<int32_t>(), 10765);
-  handle = flags::FindCommandLineFlag("test_flag_06");
+  handle = absl::FindCommandLineFlag("test_flag_06");
   EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000);
-  handle = flags::FindCommandLineFlag("test_flag_07");
+  handle = absl::FindCommandLineFlag("test_flag_07");
   EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567);
-  handle = flags::FindCommandLineFlag("test_flag_08");
+  handle = absl::FindCommandLineFlag("test_flag_08");
   EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543);
-  handle = flags::FindCommandLineFlag("test_flag_09");
+  handle = absl::FindCommandLineFlag("test_flag_09");
   EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55);
-  handle = flags::FindCommandLineFlag("test_flag_10");
+  handle = absl::FindCommandLineFlag("test_flag_10");
   EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f);
-  handle = flags::FindCommandLineFlag("test_flag_11");
+  handle = absl::FindCommandLineFlag("test_flag_11");
   EXPECT_EQ(*handle->TryGet<std::string>(), "");
-  handle = flags::FindCommandLineFlag("test_flag_12");
+  handle = absl::FindCommandLineFlag("test_flag_12");
   EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10));
 }
 
@@ -501,8 +611,9 @@ namespace {
 
 #if !ABSL_FLAGS_STRIP_HELP
 TEST_F(FlagTest, TestNonConstexprHelp) {
-  EXPECT_EQ(FLAGS_test_flag_with_non_const_help.Help(),
-            "test flag non const help");
+  EXPECT_EQ(
+      absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(),
+      "test flag non const help");
 }
 #endif  //! ABSL_FLAGS_STRIP_HELP
 
@@ -704,14 +815,15 @@ ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
 namespace {
 
 TEST_F(FlagTest, TestRetiredFlagRegistration) {
-  bool is_bool = false;
-  EXPECT_TRUE(flags::IsRetiredFlag("old_bool_flag", &is_bool));
-  EXPECT_TRUE(is_bool);
-  EXPECT_TRUE(flags::IsRetiredFlag("old_int_flag", &is_bool));
-  EXPECT_FALSE(is_bool);
-  EXPECT_TRUE(flags::IsRetiredFlag("old_str_flag", &is_bool));
-  EXPECT_FALSE(is_bool);
-  EXPECT_FALSE(flags::IsRetiredFlag("some_other_flag", &is_bool));
+  auto* handle = absl::FindCommandLineFlag("old_bool_flag");
+  EXPECT_TRUE(handle->IsOfType<bool>());
+  EXPECT_TRUE(handle->IsRetired());
+  handle = absl::FindCommandLineFlag("old_int_flag");
+  EXPECT_TRUE(handle->IsOfType<int>());
+  EXPECT_TRUE(handle->IsRetired());
+  handle = absl::FindCommandLineFlag("old_str_flag");
+  EXPECT_TRUE(handle->IsOfType<std::string>());
+  EXPECT_TRUE(handle->IsRetired());
 }
 
 }  // namespace
diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h
index fa050209b0d7..cb46fe2e979d 100644
--- a/absl/flags/internal/commandlineflag.h
+++ b/absl/flags/internal/commandlineflag.h
@@ -16,14 +16,8 @@
 #ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
 #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
 
-#include <memory>
-#include <string>
-
 #include "absl/base/config.h"
 #include "absl/base/internal/fast_type_id.h"
-#include "absl/base/macros.h"
-#include "absl/strings/string_view.h"
-#include "absl/types/optional.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -34,7 +28,7 @@ namespace flags_internal {
 // 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 = base_internal::FastTypeIdType;
+using FlagFastTypeId = absl::base_internal::FastTypeIdType;
 
 // Options that control SetCommandLineOptionWithMode.
 enum FlagSettingMode {
@@ -67,117 +61,6 @@ class FlagStateInterface {
   virtual void Restore() const = 0;
 };
 
-// Holds all information for a flag.
-class CommandLineFlag {
- public:
-  constexpr CommandLineFlag() = default;
-
-  // Not copyable/assignable.
-  CommandLineFlag(const CommandLineFlag&) = delete;
-  CommandLineFlag& operator=(const CommandLineFlag&) = delete;
-
-  // Non-polymorphic access methods.
-
-  // Return true iff flag has type T.
-  template <typename T>
-  inline bool IsOfType() const {
-    return TypeId() == base_internal::FastTypeId<T>();
-  }
-
-  // Attempts to retrieve the flag value. Returns value on success,
-  // absl::nullopt otherwise.
-  template <typename T>
-  absl::optional<T> TryGet() const {
-    if (IsRetired() || !IsOfType<T>()) {
-      return absl::nullopt;
-    }
-
-    // Implementation notes:
-    //
-    // We are wrapping a union around the value of `T` to serve three purposes:
-    //
-    //  1. `U.value` has correct size and alignment for a value of type `T`
-    //  2. The `U.value` constructor is not invoked since U's constructor does
-    //     not do it explicitly.
-    //  3. The `U.value` destructor is invoked since U's destructor does it
-    //     explicitly. This makes `U` a kind of RAII wrapper around non default
-    //     constructible value of T, which is destructed when we leave the
-    //     scope. We do need to destroy U.value, which is constructed by
-    //     CommandLineFlag::Read even though we left it in a moved-from state
-    //     after std::move.
-    //
-    // All of this serves to avoid requiring `T` being default constructible.
-    union U {
-      T value;
-      U() {}
-      ~U() { value.~T(); }
-    };
-    U u;
-
-    Read(&u.value);
-    return std::move(u.value);
-  }
-
-  // Polymorphic access methods
-
-  // Returns name of this flag.
-  virtual absl::string_view Name() const = 0;
-  // Returns name of the file where this flag is defined.
-  virtual std::string Filename() const = 0;
-  // Returns help message associated with this flag.
-  virtual std::string Help() const = 0;
-  // Returns true iff this object corresponds to retired flag.
-  virtual bool IsRetired() const;
-  virtual std::string DefaultValue() const = 0;
-  virtual std::string CurrentValue() const = 0;
-
-  // Sets the value of the flag based on specified string `value`. If the flag
-  // was successfully set to new value, it returns true. Otherwise, sets `error`
-  // to indicate the error, leaves the flag unchanged, and returns false.
-  bool ParseFrom(absl::string_view value, std::string* error);
-
- protected:
-  ~CommandLineFlag() = default;
-
- private:
-  friend class PrivateHandleAccessor;
-
-  // Sets the value of the flag based on specified string `value`. If the flag
-  // was successfully set to new value, it returns true. Otherwise, sets `error`
-  // to indicate the error, leaves the flag unchanged, and returns false. There
-  // are three ways to set the flag's value:
-  //  * Update the current flag value
-  //  * Update the flag's default value
-  //  * Update the current flag value if it was never set before
-  // The mode is selected based on `set_mode` parameter.
-  virtual bool ParseFrom(absl::string_view value,
-                         flags_internal::FlagSettingMode set_mode,
-                         flags_internal::ValueSource source,
-                         std::string* error) = 0;
-
-  // Returns id of the flag's value type.
-  virtual FlagFastTypeId TypeId() const = 0;
-
-  // Interface to save flag to some persistent state. Returns current flag state
-  // or nullptr if flag does not support saving and restoring a state.
-  virtual std::unique_ptr<FlagStateInterface> SaveState() = 0;
-
-  // Copy-construct a new value of the flag's type in a memory referenced by
-  // the dst based on the current flag's value.
-  virtual void Read(void* dst) const = 0;
-
-  // To be deleted. Used to return true if flag's current value originated from
-  // command line.
-  virtual bool IsSpecifiedOnCommandLine() const = 0;
-
-  // Validates supplied value usign validator or parseflag routine
-  virtual bool ValidateInputValue(absl::string_view value) const = 0;
-
-  // Checks that flags default value can be converted to string and back to the
-  // flag's value type.
-  virtual void CheckDefaultValueParsingRoundtrip() const = 0;
-};
-
 }  // namespace flags_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc
index 96c026dcb5d2..1502e7f11d36 100644
--- a/absl/flags/internal/flag.cc
+++ b/absl/flags/internal/flag.cc
@@ -15,22 +15,26 @@
 
 #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 <vector>
+#include <typeinfo>
 
-#include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
 #include "absl/base/casts.h"
 #include "absl/base/config.h"
-#include "absl/base/const_init.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"
@@ -63,14 +67,14 @@ bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {
 // need to acquire these locks themselves.
 class MutexRelock {
  public:
-  explicit MutexRelock(absl::Mutex* mu) : mu_(mu) { mu_->Unlock(); }
-  ~MutexRelock() { mu_->Lock(); }
+  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_;
+  absl::Mutex& mu_;
 };
 
 }  // namespace
@@ -83,7 +87,7 @@ class FlagImpl;
 class FlagState : public flags_internal::FlagStateInterface {
  public:
   template <typename V>
-  FlagState(FlagImpl* flag_impl, const V& v, bool modified,
+  FlagState(FlagImpl& flag_impl, const V& v, bool modified,
             bool on_command_line, int64_t counter)
       : flag_impl_(flag_impl),
         value_(v),
@@ -92,9 +96,9 @@ class FlagState : public flags_internal::FlagStateInterface {
         counter_(counter) {}
 
   ~FlagState() override {
-    if (flag_impl_->ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer)
+    if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer)
       return;
-    flags_internal::Delete(flag_impl_->op_, value_.heap_allocated);
+    flags_internal::Delete(flag_impl_.op_, value_.heap_allocated);
   }
 
  private:
@@ -102,15 +106,15 @@ class FlagState : public flags_internal::FlagStateInterface {
 
   // Restores the flag to the saved state.
   void Restore() const override {
-    if (!flag_impl_->RestoreState(*this)) return;
+    if (!flag_impl_.RestoreState(*this)) return;
 
-    ABSL_INTERNAL_LOG(
-        INFO, absl::StrCat("Restore saved value of ", flag_impl_->Name(),
-                           " to: ", flag_impl_->CurrentValue()));
+    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_;
+  FlagImpl& flag_impl_;
   union SavedValue {
     explicit SavedValue(void* v) : heap_allocated(v) {}
     explicit SavedValue(int64_t v) : one_word(v) {}
@@ -327,7 +331,7 @@ void FlagImpl::InvokeCallback() const {
   // 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());
+  MutexRelock relock(*DataGuard());
   absl::MutexLock lock(&callback_->guard);
   cb();
 }
@@ -340,17 +344,17 @@ std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {
   switch (ValueStorageKind()) {
     case FlagValueStorageKind::kAlignedBuffer: {
       return absl::make_unique<FlagState>(
-          this, flags_internal::Clone(op_, AlignedBufferValue()), modified,
+          *this, flags_internal::Clone(op_, AlignedBufferValue()), modified,
           on_command_line, counter_);
     }
     case FlagValueStorageKind::kOneWordAtomic: {
       return absl::make_unique<FlagState>(
-          this, OneWordValue().load(std::memory_order_acquire), modified,
+          *this, OneWordValue().load(std::memory_order_acquire), modified,
           on_command_line, counter_);
     }
     case FlagValueStorageKind::kTwoWordsAtomic: {
       return absl::make_unique<FlagState>(
-          this, TwoWordsValue().load(std::memory_order_acquire), modified,
+          *this, TwoWordsValue().load(std::memory_order_acquire), modified,
           on_command_line, counter_);
     }
   }
@@ -411,14 +415,14 @@ std::atomic<AlignedTwoWords>& FlagImpl::TwoWordsValue() const {
 // 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 {
+    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);
+    err = absl::StrCat("Illegal value '", value, "' specified for flag '",
+                       Name(), "'", err_sep, parse_err);
     return nullptr;
   }
 
@@ -474,7 +478,7 @@ void FlagImpl::Write(const void* src) {
 //  * 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) {
+                         ValueSource source, std::string& err) {
   absl::MutexLock l(DataGuard());
 
   switch (set_mode) {
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
index e374ecde3d95..2cc44e00f762 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -16,31 +16,36 @@
 #ifndef ABSL_FLAGS_INTERNAL_FLAG_H_
 #define ABSL_FLAGS_INTERNAL_FLAG_H_
 
+#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/marshalling.h"
-#include "absl/memory/memory.h"
 #include "absl/meta/type_traits.h"
-#include "absl/strings/str_cat.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>
@@ -64,12 +69,15 @@ void SetFlag(absl::Flag<T>* flag, const T& v);
 template <typename T, typename V>
 void SetFlag(absl::Flag<T>* flag, const V& v);
 
-namespace flags_internal {
+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 {
+
 enum class FlagOp {
   kAlloc,
   kDelete,
@@ -168,6 +176,28 @@ inline const std::type_info* GenRuntimeTypeId() {
 // 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) {}
@@ -185,40 +215,28 @@ struct FlagHelpArg {
 
 extern const char kStrippedFlagHelp[];
 
-// HelpConstexprWrap is used by struct AbslFlagHelpGenFor##name generated by
-// ABSL_FLAG macro. It is only used to silence the compiler in the case where
-// help message expression is not constexpr and does not have type const char*.
-// If help message expression is indeed constexpr const char* HelpConstexprWrap
-// is just a trivial identity function.
-template <typename T>
-const char* HelpConstexprWrap(const T&) {
-  return nullptr;
-}
-constexpr const char* HelpConstexprWrap(const char* p) { return p; }
-constexpr const char* HelpConstexprWrap(char* p) { return p; }
-
 // 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 T and integer 0 as a single argument to prefer
-// first overload if possible. If T::Const is evaluatable on constexpr
-// context (see non template int parameter below) 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
+// 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 T, int = (T::Const(), 1)>
-constexpr FlagHelpArg HelpArg(int) {
-  return {FlagHelpMsg(T::Const()), FlagHelpKind::kLiteral};
+template <typename Gen, size_t N>
+constexpr FlagHelpArg HelpArg(const FixedCharArray<N>& value) {
+  return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral};
 }
 
-template <typename T>
-constexpr FlagHelpArg HelpArg(char) {
-  return {FlagHelpMsg(&T::NonConst), FlagHelpKind::kGenFunc};
+template <typename Gen>
+constexpr FlagHelpArg HelpArg(std::false_type) {
+  return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc};
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -364,31 +382,31 @@ struct FlagValue;
 
 template <typename T>
 struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> {
-  bool Get(T*) const { return false; }
+  bool Get(T&) const { return false; }
 
   alignas(T) char value[sizeof(T)];
 };
 
 template <typename T>
 struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue {
-  bool Get(T* dst) const {
+  bool Get(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));
+    std::memcpy(&dst, static_cast<const void*>(&one_word_val), sizeof(T));
     return true;
   }
 };
 
 template <typename T>
 struct FlagValue<T, FlagValueStorageKind::kTwoWordsAtomic> : FlagTwoWordsValue {
-  bool Get(T* dst) const {
+  bool Get(T& dst) const {
     AlignedTwoWords two_words_val = value.load(std::memory_order_acquire);
     if (ABSL_PREDICT_FALSE(!two_words_val.IsInitialized())) {
       return false;
     }
-    std::memcpy(dst, static_cast<const void*>(&two_words_val), sizeof(T));
+    std::memcpy(&dst, static_cast<const void*>(&two_words_val), sizeof(T));
     return true;
   }
 };
@@ -419,7 +437,7 @@ struct DynValueDeleter {
 
 class FlagState;
 
-class FlagImpl final : public flags_internal::CommandLineFlag {
+class FlagImpl final : public CommandLineFlag {
  public:
   constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op,
                      FlagHelpArg help, FlagValueStorageKind value_kind,
@@ -492,7 +510,7 @@ class FlagImpl final : public flags_internal::CommandLineFlag {
   // 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
+                                                  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());
@@ -534,7 +552,7 @@ class FlagImpl final : public flags_internal::CommandLineFlag {
       ABSL_LOCKS_EXCLUDED(*DataGuard());
 
   bool ParseFrom(absl::string_view value, FlagSettingMode set_mode,
-                 ValueSource source, std::string* error) override
+                 ValueSource source, std::string& error) override
       ABSL_LOCKS_EXCLUDED(*DataGuard());
 
   // Immutable flag's state.
@@ -641,7 +659,7 @@ class Flag {
     impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
 #endif
 
-    if (!value_.Get(&u.value)) impl_.Read(&u.value);
+    if (!value_.Get(u.value)) impl_.Read(&u.value);
     return std::move(u.value);
   }
   void Set(const T& v) {
@@ -649,6 +667,13 @@ class Flag {
     impl_.Write(&v);
   }
 
+  template <typename U>
+  friend const CommandLineFlag& absl::GetFlagReflectionHandle(
+      const absl::Flag<U>& f);
+
+  // Access to the reflection.
+  const CommandLineFlag& Reflect() const { return impl_; }
+
   // Flag's data
   // 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
@@ -720,12 +745,12 @@ 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_->impl_);
+  explicit FlagRegistrar(Flag<T>& flag) : flag_(flag) {
+    if (do_register) flags_internal::RegisterCommandLineFlag(flag_.impl_);
   }
 
   FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
-    flag_->impl_.SetCallback(cb);
+    flag_.impl_.SetCallback(cb);
     return *this;
   }
 
@@ -735,7 +760,7 @@ class FlagRegistrar {
   operator FlagRegistrarEmpty() const { return {}; }  // NOLINT
 
  private:
-  Flag<T>* flag_;  // Flag being registered (not owned).
+  Flag<T>& flag_;  // Flag being registered (not owned).
 };
 
 }  // namespace flags_internal
diff --git a/absl/flags/internal/parse.h b/absl/flags/internal/parse.h
index d259be733ce2..de706c898470 100644
--- a/absl/flags/internal/parse.h
+++ b/absl/flags/internal/parse.h
@@ -21,6 +21,7 @@
 
 #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);
diff --git a/absl/flags/internal/path_util.h b/absl/flags/internal/path_util.h
index 365c83052266..a6594d3347e1 100644
--- a/absl/flags/internal/path_util.h
+++ b/absl/flags/internal/path_util.h
@@ -17,7 +17,6 @@
 #define ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
 
 #include "absl/base/config.h"
-#include "absl/strings/match.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
diff --git a/absl/flags/internal/private_handle_accessor.cc b/absl/flags/internal/private_handle_accessor.cc
index 64fe31663a0a..a7eb58b6d45f 100644
--- a/absl/flags/internal/private_handle_accessor.cc
+++ b/absl/flags/internal/private_handle_accessor.cc
@@ -15,6 +15,14 @@
 
 #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 {
@@ -24,8 +32,8 @@ FlagFastTypeId PrivateHandleAccessor::TypeId(const CommandLineFlag& flag) {
 }
 
 std::unique_ptr<FlagStateInterface> PrivateHandleAccessor::SaveState(
-    CommandLineFlag* flag) {
-  return flag->SaveState();
+    CommandLineFlag& flag) {
+  return flag.SaveState();
 }
 
 bool PrivateHandleAccessor::IsSpecifiedOnCommandLine(
@@ -43,12 +51,12 @@ void PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
   flag.CheckDefaultValueParsingRoundtrip();
 }
 
-bool PrivateHandleAccessor::ParseFrom(CommandLineFlag* flag,
+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);
+                                      std::string& error) {
+  return flag.ParseFrom(value, set_mode, source, error);
 }
 
 }  // namespace flags_internal
diff --git a/absl/flags/internal/private_handle_accessor.h b/absl/flags/internal/private_handle_accessor.h
index 40591de447dd..c64435cd6199 100644
--- a/absl/flags/internal/private_handle_accessor.h
+++ b/absl/flags/internal/private_handle_accessor.h
@@ -16,7 +16,13 @@
 #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
@@ -31,7 +37,7 @@ class PrivateHandleAccessor {
   static FlagFastTypeId TypeId(const CommandLineFlag& flag);
 
   // Access to CommandLineFlag::SaveState.
-  static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag* flag);
+  static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag& flag);
 
   // Access to CommandLineFlag::IsSpecifiedOnCommandLine.
   static bool IsSpecifiedOnCommandLine(const CommandLineFlag& flag);
@@ -43,9 +49,9 @@ class PrivateHandleAccessor {
   // Access to CommandLineFlag::CheckDefaultValueParsingRoundtrip.
   static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag);
 
-  static bool ParseFrom(CommandLineFlag* flag, absl::string_view value,
+  static bool ParseFrom(CommandLineFlag& flag, absl::string_view value,
                         flags_internal::FlagSettingMode set_mode,
-                        flags_internal::ValueSource source, std::string* error);
+                        flags_internal::ValueSource source, std::string& error);
 };
 
 }  // namespace flags_internal
diff --git a/absl/flags/internal/program_name_test.cc b/absl/flags/internal/program_name_test.cc
index 269142f2255f..aff9f6315e4e 100644
--- a/absl/flags/internal/program_name_test.cc
+++ b/absl/flags/internal/program_name_test.cc
@@ -25,7 +25,7 @@ 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)
@@ -43,9 +43,7 @@ TEST(FlagsPathUtilTest, TestInitialProgamName) {
 
   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.h b/absl/flags/internal/registry.h
index af8ed6b99b78..6f5006a016fd 100644
--- a/absl/flags/internal/registry.h
+++ b/absl/flags/internal/registry.h
@@ -17,11 +17,9 @@
 #define ABSL_FLAGS_INTERNAL_REGISTRY_H_
 
 #include <functional>
-#include <map>
-#include <string>
 
 #include "absl/base/config.h"
-#include "absl/base/macros.h"
+#include "absl/flags/commandlineflag.h"
 #include "absl/flags/internal/commandlineflag.h"
 #include "absl/strings/string_view.h"
 
@@ -32,19 +30,16 @@ 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);
+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&);
 
 //-----------------------------------------------------------------------------
 // Retired registrations:
@@ -87,36 +82,6 @@ inline bool RetiredFlag(const char* flag_name) {
   return flags_internal::Retire(flag_name, base_internal::FastTypeId<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 {
- public:
-  FlagSaver();
-  ~FlagSaver();
-
-  FlagSaver(const FlagSaver&) = delete;
-  void operator=(const FlagSaver&) = delete;
-
-  // Prevents saver from restoring the saved state of flags.
-  void Ignore();
-
- private:
-  class FlagSaverImpl* impl_;  // we use pimpl here to keep API steady
-};
-
 }  // namespace flags_internal
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/internal/type_erased.cc b/absl/flags/internal/type_erased.cc
deleted file mode 100644
index c13fb9b0d453..000000000000
--- a/absl/flags/internal/type_erased.cc
+++ /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.
-
-#include "absl/flags/internal/type_erased.h"
-
-#include <assert.h>
-
-#include <string>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/flags/internal/commandlineflag.h"
-#include "absl/flags/internal/private_handle_accessor.h"
-#include "absl/flags/internal/registry.h"
-#include "absl/flags/usage_config.h"
-#include "absl/strings/string_view.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-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 (!flags_internal::PrivateHandleAccessor::ParseFrom(
-          flag, value, set_mode, kProgrammaticChange, &error)) {
-    // Errors here are all of the form: the provided name was a recognized
-    // flag, but the value was invalid (bad type, or validation failed).
-    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() ||
-          flags_internal::PrivateHandleAccessor::ValidateInputValue(*flag,
-                                                                    value));
-}
-
-// --------------------------------------------------------------------
-
-}  // namespace flags_internal
-ABSL_NAMESPACE_END
-}  // namespace absl
diff --git a/absl/flags/internal/type_erased.h b/absl/flags/internal/type_erased.h
deleted file mode 100644
index b43a0ff7be66..000000000000
--- a/absl/flags/internal/type_erased.h
+++ /dev/null
@@ -1,79 +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/base/config.h"
-#include "absl/flags/internal/commandlineflag.h"
-#include "absl/flags/internal/registry.h"
-#include "absl/strings/string_view.h"
-
-// --------------------------------------------------------------------
-// Registry interfaces operating on type erased handles.
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-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);
-
-//-----------------------------------------------------------------------------
-
-// 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->TryGet<T>()) {
-    *dst = *val;
-    return true;
-  }
-
-  return false;
-}
-
-}  // namespace flags_internal
-ABSL_NAMESPACE_END
-}  // 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 4ce5981047b6..000000000000
--- a/absl/flags/internal/type_erased_test.cc
+++ /dev/null
@@ -1,157 +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 <memory>
-#include <string>
-
-#include "gtest/gtest.h"
-#include "absl/flags/flag.h"
-#include "absl/flags/internal/commandlineflag.h"
-#include "absl/flags/internal/registry.h"
-#include "absl/flags/marshalling.h"
-#include "absl/memory/memory.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));
-
-  // Set it again to ensure that resetting logic is covered.
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "102",
-                                                  flags::SET_FLAGS_DEFAULT));
-
-  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "103",
-                                                  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 10accc46f32a..35b6427b6c83 100644
--- a/absl/flags/internal/usage.cc
+++ b/absl/flags/internal/usage.cc
@@ -15,6 +15,8 @@
 
 #include "absl/flags/internal/usage.h"
 
+#include <stdint.h>
+
 #include <functional>
 #include <map>
 #include <ostream>
@@ -23,8 +25,8 @@
 #include <vector>
 
 #include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
 #include "absl/flags/flag.h"
-#include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/internal/flag.h"
 #include "absl/flags/internal/path_util.h"
 #include "absl/flags/internal/private_handle_accessor.h"
@@ -107,8 +109,8 @@ class FlagHelpPrettyPrinter {
  public:
   // Pretty printer holds on to the std::ostream& reference to direct an output
   // to that stream.
-  FlagHelpPrettyPrinter(int max_line_len, std::ostream* out)
-      : out_(*out),
+  FlagHelpPrettyPrinter(int max_line_len, std::ostream& out)
+      : out_(out),
         max_line_len_(max_line_len),
         line_len_(0),
         first_line_(true) {}
@@ -182,8 +184,7 @@ class FlagHelpPrettyPrinter {
   bool first_line_;
 };
 
-void FlagHelpHumanReadable(const flags_internal::CommandLineFlag& flag,
-                           std::ostream* out) {
+void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
   FlagHelpPrettyPrinter printer(80, out);  // Max line length is 80.
 
   // Flag name.
@@ -245,30 +246,28 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
   // 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) {
+    std::string flag_filename = flag.Filename();
 
     // 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;
 
     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;
@@ -303,10 +302,10 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
 
 // --------------------------------------------------------------------
 // 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);
 }
 
 // --------------------------------------------------------------------
diff --git a/absl/flags/internal/usage.h b/absl/flags/internal/usage.h
index 6b080fd1eeec..0c62dc4b2ac6 100644
--- a/absl/flags/internal/usage.h
+++ b/absl/flags/internal/usage.h
@@ -20,8 +20,8 @@
 #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"
 
 // --------------------------------------------------------------------
@@ -37,7 +37,7 @@ enum class HelpFormat {
 };
 
 // Outputs 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 = HelpFormat::kHumanReadable);
 
 // Produces the help messages for all flags matching the filter. A flag matches
diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc
index 8dd3532e6d40..6e583fbe4b0e 100644
--- a/absl/flags/internal/usage_test.cc
+++ b/absl/flags/internal/usage_test.cc
@@ -21,15 +21,13 @@
 #include <string>
 
 #include "gtest/gtest.h"
-#include "absl/flags/declare.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/internal/registry.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"
 
@@ -91,7 +89,7 @@ class UsageReportingTest : public testing::Test {
   }
 
  private:
-  flags::FlagSaver flag_saver_;
+  absl::FlagSaver flag_saver_;
 };
 
 // --------------------------------------------------------------------
@@ -112,7 +110,7 @@ TEST_F(UsageReportingDeathTest, TestSetProgramUsageMessage) {
 // --------------------------------------------------------------------
 
 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);
@@ -124,7 +122,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {
 }
 
 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);
@@ -136,7 +134,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
 }
 
 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);
@@ -148,7 +146,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_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);
@@ -160,7 +158,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
 }
 
 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);
diff --git a/absl/flags/marshalling.cc b/absl/flags/marshalling.cc
index 09baae88cd58..81f9cebd6f41 100644
--- a/absl/flags/marshalling.cc
+++ b/absl/flags/marshalling.cc
@@ -74,15 +74,16 @@ static int NumericBase(absl::string_view text) {
 }
 
 template <typename IntType>
-inline bool ParseFlagImpl(absl::string_view text, IntType* dst) {
+inline bool ParseFlagImpl(absl::string_view text, IntType& dst) {
   text = absl::StripAsciiWhitespace(text);
 
-  return absl::numbers_internal::safe_strtoi_base(text, dst, NumericBase(text));
+  return absl::numbers_internal::safe_strtoi_base(text, &dst,
+                                                  NumericBase(text));
 }
 
 bool AbslParseFlag(absl::string_view text, short* dst, std::string*) {
   int val;
-  if (!ParseFlagImpl(text, &val)) return false;
+  if (!ParseFlagImpl(text, val)) return false;
   if (static_cast<short>(val) != val)  // worked, but number out of range
     return false;
   *dst = static_cast<short>(val);
@@ -91,7 +92,7 @@ bool AbslParseFlag(absl::string_view text, short* dst, std::string*) {
 
 bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
   unsigned int val;
-  if (!ParseFlagImpl(text, &val)) return false;
+  if (!ParseFlagImpl(text, val)) return false;
   if (static_cast<unsigned short>(val) !=
       val)  // worked, but number out of range
     return false;
@@ -100,28 +101,28 @@ bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
 }
 
 bool AbslParseFlag(absl::string_view text, int* dst, std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 bool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 bool AbslParseFlag(absl::string_view text, long* dst, std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 bool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 bool AbslParseFlag(absl::string_view text, long long* dst, std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 bool AbslParseFlag(absl::string_view text, unsigned long long* dst,
                    std::string*) {
-  return ParseFlagImpl(text, dst);
+  return ParseFlagImpl(text, *dst);
 }
 
 // --------------------------------------------------------------------
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
index fbf4267512b6..e2c88ff863ce 100644
--- a/absl/flags/parse.cc
+++ b/absl/flags/parse.cc
@@ -34,6 +34,7 @@
 #include "absl/base/config.h"
 #include "absl/base/const_init.h"
 #include "absl/base/thread_annotations.h"
+#include "absl/flags/commandlineflag.h"
 #include "absl/flags/config.h"
 #include "absl/flags/flag.h"
 #include "absl/flags/internal/commandlineflag.h"
@@ -41,8 +42,8 @@
 #include "absl/flags/internal/parse.h"
 #include "absl/flags/internal/private_handle_accessor.h"
 #include "absl/flags/internal/program_name.h"
-#include "absl/flags/internal/registry.h"
 #include "absl/flags/internal/usage.h"
+#include "absl/flags/reflection.h"
 #include "absl/flags/usage.h"
 #include "absl/flags/usage_config.h"
 #include "absl/strings/ascii.h"
@@ -222,7 +223,7 @@ bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {
 // Reads the environment variable with name `name` and stores results in
 // `value`. If variable is not present in environment returns false, otherwise
 // returns true.
-bool GetEnvVar(const char* var_name, std::string* var_value) {
+bool GetEnvVar(const char* var_name, std::string& var_value) {
 #ifdef _WIN32
   char buf[1024];
   auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
@@ -234,14 +235,14 @@ bool GetEnvVar(const char* var_name, std::string* var_value) {
     return false;
   }
 
-  *var_value = std::string(buf, get_res);
+  var_value = std::string(buf, get_res);
 #else
   const char* val = ::getenv(var_name);
   if (val == nullptr) {
     return false;
   }
 
-  *var_value = val;
+  var_value = val;
 #endif
 
   return true;
@@ -289,11 +290,11 @@ std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue(
 //  found flag or nullptr
 //  is negative in case of --nofoo
 std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
-  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(flag_name);
+  CommandLineFlag* flag = absl::FindCommandLineFlag(flag_name);
   bool is_negative = false;
 
   if (!flag && absl::ConsumePrefix(&flag_name, "no")) {
-    flag = flags_internal::FindCommandLineFlag(flag_name);
+    flag = absl::FindCommandLineFlag(flag_name);
     is_negative = true;
   }
 
@@ -306,17 +307,17 @@ std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
 // back.
 void CheckDefaultValuesParsingRoundtrip() {
 #ifndef NDEBUG
-  flags_internal::ForEachFlag([&](CommandLineFlag* flag) {
-    if (flag->IsRetired()) return;
+  flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+    if (flag.IsRetired()) return;
 
 #define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \
-  if (flag->IsOfType<T>()) return;
+  if (flag.IsOfType<T>()) return;
 
     ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(ABSL_FLAGS_INTERNAL_IGNORE_TYPE)
 #undef ABSL_FLAGS_INTERNAL_IGNORE_TYPE
 
     flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
-        *flag);
+        flag);
   });
 #endif
 }
@@ -329,13 +330,13 @@ void CheckDefaultValuesParsingRoundtrip() {
 // the first flagfile in the input list are processed before the second flagfile
 // etc.
 bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
-                   std::vector<ArgsList>* input_args) {
+                   std::vector<ArgsList>& input_args) {
   bool success = true;
   for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) {
     ArgsList al;
 
     if (al.ReadFromFlagfile(*it)) {
-      input_args->push_back(al);
+      input_args.push_back(al);
     } else {
       success = false;
     }
@@ -350,7 +351,7 @@ bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
 // `flag_name` is a string from the input flag_names list. If successful we
 // append a single ArgList at the end of the input_args.
 bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
-                      std::vector<ArgsList>* input_args,
+                      std::vector<ArgsList>& input_args,
                       bool fail_on_absent_in_env) {
   bool success = true;
   std::vector<std::string> args;
@@ -371,7 +372,7 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
 
     const std::string envname = absl::StrCat("FLAGS_", flag_name);
     std::string envval;
-    if (!GetEnvVar(envname.c_str(), &envval)) {
+    if (!GetEnvVar(envname.c_str(), envval)) {
       if (fail_on_absent_in_env) {
         flags_internal::ReportUsageError(
             absl::StrCat(envname, " not found in environment"), true);
@@ -386,7 +387,7 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
   }
 
   if (success) {
-    input_args->emplace_back(args);
+    input_args.emplace_back(args);
   }
 
   return success;
@@ -396,8 +397,8 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
 
 // Returns success status, which is true if were able to handle all generator
 // flags (flagfile, fromenv, tryfromemv) successfully.
-bool HandleGeneratorFlags(std::vector<ArgsList>* input_args,
-                          std::vector<std::string>* flagfile_value) {
+bool HandleGeneratorFlags(std::vector<ArgsList>& input_args,
+                          std::vector<std::string>& flagfile_value) {
   bool success = true;
 
   absl::MutexLock l(&flags_internal::processing_checks_guard);
@@ -422,9 +423,9 @@ bool HandleGeneratorFlags(std::vector<ArgsList>* input_args,
   if (flags_internal::flagfile_needs_processing) {
     auto flagfiles = absl::GetFlag(FLAGS_flagfile);
 
-    if (input_args->size() == 1) {
-      flagfile_value->insert(flagfile_value->end(), flagfiles.begin(),
-                             flagfiles.end());
+    if (input_args.size() == 1) {
+      flagfile_value.insert(flagfile_value.end(), flagfiles.begin(),
+                            flagfiles.end());
     }
 
     success &= ReadFlagfiles(flagfiles, input_args);
@@ -647,7 +648,7 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
   bool success = true;
   while (!input_args.empty()) {
     // 10. First we process the built-in generator flags.
-    success &= HandleGeneratorFlags(&input_args, &flagfile_value);
+    success &= HandleGeneratorFlags(input_args, flagfile_value);
 
     // 30. Select top-most (most recent) arguments list. If it is empty drop it
     // and re-try.
@@ -733,7 +734,7 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
 
     std::string error;
     if (!flags_internal::PrivateHandleAccessor::ParseFrom(
-            flag, value, SET_FLAGS_VALUE, kCommandLine, &error)) {
+            *flag, value, SET_FLAGS_VALUE, kCommandLine, error)) {
       flags_internal::ReportUsageError(error, true);
       success = false;
     } else {
diff --git a/absl/flags/parse.h b/absl/flags/parse.h
index f37b0602e662..929de2cb40de 100644
--- a/absl/flags/parse.h
+++ b/absl/flags/parse.h
@@ -23,7 +23,6 @@
 #ifndef ABSL_FLAGS_PARSE_H_
 #define ABSL_FLAGS_PARSE_H_
 
-#include <string>
 #include <vector>
 
 #include "absl/base/config.h"
diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc
index e6a53ae6cb43..d35a6e471abd 100644
--- a/absl/flags/parse_test.cc
+++ b/absl/flags/parse_test.cc
@@ -28,7 +28,7 @@
 #include "absl/flags/declare.h"
 #include "absl/flags/flag.h"
 #include "absl/flags/internal/parse.h"
-#include "absl/flags/internal/registry.h"
+#include "absl/flags/reflection.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include "absl/strings/substitute.h"
@@ -171,8 +171,8 @@ constexpr const char* const ff2_data[] = {
 // temporary directory location. This way we can test inclusion of one flagfile
 // from another flagfile.
 const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
-                            std::string* flagfile_flag) {
-  *flagfile_flag = "--flagfile=";
+                            std::string& flagfile_flag) {
+  flagfile_flag = "--flagfile=";
   absl::string_view separator;
   for (const auto& flagfile_data : ffd) {
     std::string flagfile_name =
@@ -183,11 +183,11 @@ const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
       flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n";
     }
 
-    absl::StrAppend(flagfile_flag, separator, flagfile_name);
+    absl::StrAppend(&flagfile_flag, separator, flagfile_name);
     separator = ",";
   }
 
-  return flagfile_flag->c_str();
+  return flagfile_flag.c_str();
 }
 
 }  // namespace
@@ -208,7 +208,7 @@ using testing::ElementsAreArray;
 
 class ParseTest : public testing::Test {
  private:
-  flags::FlagSaver flag_saver_;
+  absl::FlagSaver flag_saver_;
 };
 
 // --------------------------------------------------------------------
@@ -588,14 +588,14 @@ TEST_F(ParseTest, TestSimpleValidFlagfile) {
   const char* in_args1[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
   TestParse(in_args1, -1, 0.1, "q2w2  ", true);
 
   const char* in_args2[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
   TestParse(in_args2, 100, 0.1, "q2w2  ", false);
 }
@@ -609,7 +609,7 @@ TEST_F(ParseTest, TestValidMultiFlagfile) {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
                        {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
   TestParse(in_args1, -1, 0.1, "q2w2  ", true);
 }
@@ -622,7 +622,7 @@ TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) {
   const char* in_args1[] = {
       "testbin", "--int_flag=3",
       GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
       "-double_flag=0.2"};
   TestParse(in_args1, -1, 0.2, "q2w2  ", true);
 }
@@ -637,10 +637,14 @@ TEST_F(ParseTest, TestFlagfileInFlagfile) {
       "--flagfile=$0/parse_test.ff2",
   };
 
+  GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
+                   {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
+                      flagfile_flag);
+
   const char* in_args1[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
   TestParse(in_args1, 100, 0.1, "q2w2  ", false);
 }
@@ -657,7 +661,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
   const char* in_args1[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff4",
-                        absl::MakeConstSpan(ff4_data)}}, &flagfile_flag),
+                        absl::MakeConstSpan(ff4_data)}}, flagfile_flag),
   };
   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
                "Unknown command line flag 'unknown_flag'");
@@ -669,7 +673,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
   const char* in_args2[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff5",
-                        absl::MakeConstSpan(ff5_data)}}, &flagfile_flag),
+                        absl::MakeConstSpan(ff5_data)}}, flagfile_flag),
   };
   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
                "Unknown command line flag 'int_flag 10'");
@@ -681,7 +685,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
   const char* in_args3[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
                "Flagfile can't contain position arguments or --");
@@ -702,7 +706,7 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
   const char* in_args5[] = {
       "testbin",
       GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}},
-                      &flagfile_flag),
+                      flagfile_flag),
   };
   EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5),
                "Unexpected line in the flagfile .*: \\*bin\\*");
diff --git a/absl/flags/internal/registry.cc b/absl/flags/reflection.cc
index 3b941f04c21d..5fc945f23767 100644
--- a/absl/flags/internal/registry.cc
+++ b/absl/flags/reflection.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.
@@ -13,46 +13,34 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "absl/flags/internal/registry.h"
+#include "absl/flags/reflection.h"
 
 #include <assert.h>
-#include <stdlib.h>
 
-#include <functional>
 #include <map>
-#include <memory>
 #include <string>
-#include <utility>
-#include <vector>
 
 #include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
 #include "absl/base/thread_annotations.h"
-#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/commandlineflag.h"
 #include "absl/flags/internal/private_handle_accessor.h"
+#include "absl/flags/internal/registry.h"
 #include "absl/flags/usage_config.h"
 #include "absl/strings/str_cat.h"
 #include "absl/strings/string_view.h"
 #include "absl/synchronization/mutex.h"
 
-// --------------------------------------------------------------------
-// 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 {
 ABSL_NAMESPACE_BEGIN
 namespace flags_internal {
 
 // --------------------------------------------------------------------
 // FlagRegistry
-//    A FlagRegistry singleton object holds all flag objects indexed
-//    by their names so that if you know a flag's name (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.
+//    A FlagRegistry singleton object holds all flag objects indexed by their
+//    names so that if you know a flag's name, you can access or set it. If the
+//    function is named FooLocked(), you must own the registry lock before
+//    calling the function; otherwise, you should *not* hold the lock, and the
+//    function will acquire it itself if needed.
 // --------------------------------------------------------------------
 
 class FlagRegistry {
@@ -60,8 +48,8 @@ class FlagRegistry {
   FlagRegistry() = default;
   ~FlagRegistry() = default;
 
-  // Store a flag in this registry.  Takes ownership of *flag.
-  void RegisterFlag(CommandLineFlag* flag);
+  // 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(); }
@@ -74,12 +62,13 @@ class FlagRegistry {
   // found or not retired.  Does not emit a warning.
   CommandLineFlag* FindRetiredFlagLocked(absl::string_view name);
 
-  static FlagRegistry* GlobalRegistry();  // returns a singleton registry
+  static FlagRegistry& GlobalRegistry();  // returns a singleton registry
 
  private:
-  friend class FlagSaverImpl;  // reads all the flags in order to copy them
+  friend class flags_internal::FlagSaverImpl;  // reads all the flags in order
+                                               // to copy them
   friend void ForEachFlagUnlocked(
-      std::function<void(CommandLineFlag*)> visitor);
+      std::function<void(CommandLineFlag&)> visitor);
 
   // The map from name to flag, for FindFlagLocked().
   using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
@@ -94,64 +83,80 @@ class FlagRegistry {
   FlagRegistry& operator=(const FlagRegistry&);
 };
 
-FlagRegistry* FlagRegistry::GlobalRegistry() {
-  static FlagRegistry* global_registry = new FlagRegistry;
-  return global_registry;
+CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) {
+  FlagConstIterator i = flags_.find(name);
+  if (i == flags_.end()) {
+    return nullptr;
+  }
+
+  if (i->second->IsRetired()) {
+    flags_internal::ReportUsageError(
+        absl::StrCat("Accessing retired flag '", name, "'"), false);
+  }
+
+  return i->second;
+}
+
+CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) {
+  FlagConstIterator i = flags_.find(name);
+  if (i == flags_.end() || !i->second->IsRetired()) {
+    return nullptr;
+  }
+
+  return i->second;
 }
 
 namespace {
 
 class FlagRegistryLock {
  public:
-  explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
-  ~FlagRegistryLock() { fr_->Unlock(); }
+  explicit FlagRegistryLock(FlagRegistry& fr) : fr_(fr) { fr_.Lock(); }
+  ~FlagRegistryLock() { fr_.Unlock(); }
 
  private:
-  FlagRegistry* const fr_;
+  FlagRegistry& fr_;
 };
 
-void DestroyRetiredFlag(CommandLineFlag* flag);
+void DestroyRetiredFlag(CommandLineFlag& flag);
+
 }  // namespace
 
-void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
-  FlagRegistryLock registry_lock(this);
+void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
+  FlagRegistryLock registry_lock(*this);
   std::pair<FlagIterator, bool> ins =
-      flags_.insert(FlagMap::value_type(flag->Name(), flag));
+      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()) {
+    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()),
-              "'."),
+              "Retired flag '", flag.Name(), "' was defined normally in file '",
+              (flag.IsRetired() ? old_flag.Filename() : flag.Filename()), "'."),
           true);
-    } else if (flags_internal::PrivateHandleAccessor::TypeId(*flag) !=
-               flags_internal::PrivateHandleAccessor::TypeId(*old_flag)) {
+    } else if (flags_internal::PrivateHandleAccessor::TypeId(flag) !=
+               flags_internal::PrivateHandleAccessor::TypeId(old_flag)) {
       flags_internal::ReportUsageError(
-          absl::StrCat("Flag '", flag->Name(),
+          absl::StrCat("Flag '", flag.Name(),
                        "' was defined more than once but with "
                        "differing types. Defined in files '",
-                       old_flag->Filename(), "' and '", flag->Filename(), "'."),
+                       old_flag.Filename(), "' and '", flag.Filename(), "'."),
           true);
-    } else if (old_flag->IsRetired()) {
+    } else if (old_flag.IsRetired()) {
       // Retired flag can just be deleted.
       DestroyRetiredFlag(flag);
       return;
-    } else if (old_flag->Filename() != flag->Filename()) {
+    } else if (old_flag.Filename() != flag.Filename()) {
       flags_internal::ReportUsageError(
-          absl::StrCat("Flag '", flag->Name(),
+          absl::StrCat("Flag '", flag.Name(),
                        "' was defined more than once (in files '",
-                       old_flag->Filename(), "' and '", flag->Filename(),
-                       "')."),
+                       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(),
+              "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."),
@@ -162,120 +167,31 @@ void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
   }
 }
 
-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:
-  FlagSaverImpl() = default;
-  FlagSaverImpl(const FlagSaverImpl&) = delete;
-  void operator=(const FlagSaverImpl&) = delete;
-
-  // Saves the flag states from the flag registry into this object.
-  // It's an error to call this more than once.
-  void SaveFromRegistry() {
-    assert(backup_registry_.empty());  // call only once!
-    flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) {
-      if (auto flag_state =
-              flags_internal::PrivateHandleAccessor::SaveState(flag)) {
-        backup_registry_.emplace_back(std::move(flag_state));
-      }
-    });
-  }
-
-  // Restores the saved flag states into the flag registry.
-  void RestoreToRegistry() {
-    for (const auto& flag_state : backup_registry_) {
-      flag_state->Restore();
-    }
-  }
-
- private:
-  std::vector<std::unique_ptr<flags_internal::FlagStateInterface>>
-      backup_registry_;
-};
-
-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);
+FlagRegistry& FlagRegistry::GlobalRegistry() {
+  static FlagRegistry* global_registry = new FlagRegistry;
+  return *global_registry;
 }
 
 // --------------------------------------------------------------------
 
-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 ForEachFlagUnlocked(std::function<void(CommandLineFlag&)> visitor) {
+  FlagRegistry& 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();
+void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {
+  FlagRegistry& registry = FlagRegistry::GlobalRegistry();
   FlagRegistryLock frl(registry);
   ForEachFlagUnlocked(visitor);
 }
 
 // --------------------------------------------------------------------
 
-bool RegisterCommandLineFlag(CommandLineFlag* flag) {
-  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
+bool RegisterCommandLineFlag(CommandLineFlag& flag) {
+  FlagRegistry::GlobalRegistry().RegisterFlag(flag);
   return true;
 }
 
@@ -283,7 +199,7 @@ bool RegisterCommandLineFlag(CommandLineFlag* flag) {
 
 namespace {
 
-class RetiredFlagObj final : public flags_internal::CommandLineFlag {
+class RetiredFlagObj final : public CommandLineFlag {
  public:
   constexpr RetiredFlagObj(const char* name, FlagFastTypeId type_id)
       : name_(name), type_id_(type_id) {}
@@ -306,7 +222,7 @@ class RetiredFlagObj final : public flags_internal::CommandLineFlag {
   }
 
   bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode,
-                 flags_internal::ValueSource, std::string*) override {
+                 flags_internal::ValueSource, std::string&) override {
     return false;
   }
 
@@ -319,32 +235,74 @@ class RetiredFlagObj final : public flags_internal::CommandLineFlag {
   const FlagFastTypeId type_id_;
 };
 
-void DestroyRetiredFlag(flags_internal::CommandLineFlag* flag) {
-  assert(flag->IsRetired());
-  delete static_cast<RetiredFlagObj*>(flag);
+void DestroyRetiredFlag(CommandLineFlag& flag) {
+  assert(flag.IsRetired());
+  delete static_cast<RetiredFlagObj*>(&flag);
 }
 
 }  // namespace
 
 bool Retire(const char* name, FlagFastTypeId type_id) {
   auto* flag = new flags_internal::RetiredFlagObj(name, type_id);
-  FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
+  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;
+class FlagSaverImpl {
+ public:
+  FlagSaverImpl() = default;
+  FlagSaverImpl(const FlagSaverImpl&) = delete;
+  void operator=(const FlagSaverImpl&) = delete;
+
+  // Saves the flag states from the flag registry into this object.
+  // It's an error to call this more than once.
+  void SaveFromRegistry() {
+    assert(backup_registry_.empty());  // call only once!
+    flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+      if (auto flag_state =
+              flags_internal::PrivateHandleAccessor::SaveState(flag)) {
+        backup_registry_.emplace_back(std::move(flag_state));
+      }
+    });
   }
-  assert(type_is_bool);
-  *type_is_bool = flag->IsOfType<bool>();
-  return true;
-}
+
+  // Restores the saved flag states into the flag registry.
+  void RestoreToRegistry() {
+    for (const auto& flag_state : backup_registry_) {
+      flag_state->Restore();
+    }
+  }
+
+ private:
+  std::vector<std::unique_ptr<flags_internal::FlagStateInterface>>
+      backup_registry_;
+};
 
 }  // namespace flags_internal
+
+FlagSaver::FlagSaver() : impl_(new flags_internal::FlagSaverImpl) {
+  impl_->SaveFromRegistry();
+}
+
+FlagSaver::~FlagSaver() {
+  if (!impl_) return;
+
+  impl_->RestoreToRegistry();
+  delete impl_;
+}
+
+// --------------------------------------------------------------------
+
+CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
+  if (name.empty()) return nullptr;
+  flags_internal::FlagRegistry& registry =
+      flags_internal::FlagRegistry::GlobalRegistry();
+  flags_internal::FlagRegistryLock frl(registry);
+
+  return registry.FindFlagLocked(name);
+}
+
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/flags/reflection.h b/absl/flags/reflection.h
new file mode 100644
index 000000000000..045f9784e269
--- /dev/null
+++ b/absl/flags/reflection.h
@@ -0,0 +1,85 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: reflection.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the routines to access and operate on an Abseil Flag's
+// reflection handle.
+
+#ifndef ABSL_FLAGS_REFLECTION_H_
+#define ABSL_FLAGS_REFLECTION_H_
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+class FlagSaverImpl;
+}  // namespace flags_internal
+
+// FindCommandLineFlag()
+//
+// Returns the reflection handle of an Abseil flag of the specified name, or
+// `nullptr` if not found. This function will emit a warning if the name of a
+// 'retired' flag is specified.
+CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+
+//------------------------------------------------------------------------------
+// FlagSaver
+//------------------------------------------------------------------------------
+//
+// A FlagSaver object stores the state of flags in the scope where the FlagSaver
+// is defined, allowing modification of those flags within that scope and
+// automatic restoration of the flags to their previous state upon leaving the
+// scope.
+//
+// A FlagSaver can be used within tests to temporarily change the test
+// environment and restore the test case to its previous state.
+//
+// Example:
+//
+//   void MyFunc() {
+//    absl::FlagSaver fs;
+//    ...
+//    absl::SetFlag(FLAGS_myFlag, otherValue);
+//    ...
+//  } // scope of FlagSaver left, flags return to previous state
+//
+// This class is thread-safe.
+
+class FlagSaver {
+ public:
+  FlagSaver();
+  ~FlagSaver();
+
+  FlagSaver(const FlagSaver&) = delete;
+  void operator=(const FlagSaver&) = delete;
+
+ private:
+  flags_internal::FlagSaverImpl* impl_;
+};
+
+//-----------------------------------------------------------------------------
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_REFLECTION_H_
diff --git a/absl/flags/reflection_test.cc b/absl/flags/reflection_test.cc
new file mode 100644
index 000000000000..9781e597dbd9
--- /dev/null
+++ b/absl/flags/reflection_test.cc
@@ -0,0 +1,60 @@
+//
+//  Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/reflection.h"
+
+#include <memory>
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/memory/memory.h"
+
+ABSL_FLAG(int, int_flag, 1, "int_flag help");
+ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
+ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+class ReflectionTest : public testing::Test {
+ protected:
+  void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
+  void TearDown() override { flag_saver_.reset(); }
+
+ private:
+  std::unique_ptr<absl::FlagSaver> flag_saver_;
+};
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestFindCommandLineFlag) {
+  auto* handle = absl::FindCommandLineFlag("some_flag");
+  EXPECT_EQ(handle, nullptr);
+
+  handle = absl::FindCommandLineFlag("int_flag");
+  EXPECT_NE(handle, nullptr);
+
+  handle = absl::FindCommandLineFlag("string_flag");
+  EXPECT_NE(handle, nullptr);
+
+  handle = absl::FindCommandLineFlag("bool_retired_flag");
+  EXPECT_NE(handle, nullptr);
+}
+
+}  // namespace
diff --git a/absl/flags/usage_config.cc b/absl/flags/usage_config.cc
index 0d21bce6a9ad..ae2f548a570b 100644
--- a/absl/flags/usage_config.cc
+++ b/absl/flags/usage_config.cc
@@ -15,6 +15,7 @@
 
 #include "absl/flags/usage_config.h"
 
+#include <functional>
 #include <iostream>
 #include <string>