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.bazel351
-rw-r--r--absl/flags/CMakeLists.txt317
-rw-r--r--absl/flags/config.h54
-rw-r--r--absl/flags/declare.h58
-rw-r--r--absl/flags/flag.cc52
-rw-r--r--absl/flags/flag.h281
-rw-r--r--absl/flags/flag_test.cc482
-rw-r--r--absl/flags/flag_test_defs.cc22
-rw-r--r--absl/flags/internal/commandlineflag.cc383
-rw-r--r--absl/flags/internal/commandlineflag.h365
-rw-r--r--absl/flags/internal/commandlineflag_test.cc196
-rw-r--r--absl/flags/internal/flag.h103
-rw-r--r--absl/flags/internal/parse.h48
-rw-r--r--absl/flags/internal/path_util.h60
-rw-r--r--absl/flags/internal/path_util_test.cc46
-rw-r--r--absl/flags/internal/program_name.cc53
-rw-r--r--absl/flags/internal/program_name.h47
-rw-r--r--absl/flags/internal/program_name_test.cc60
-rw-r--r--absl/flags/internal/registry.cc529
-rw-r--r--absl/flags/internal/registry.h168
-rw-r--r--absl/flags/internal/type_erased.cc121
-rw-r--r--absl/flags/internal/type_erased.h97
-rw-r--r--absl/flags/internal/type_erased_test.cc147
-rw-r--r--absl/flags/internal/usage.cc392
-rw-r--r--absl/flags/internal/usage.h91
-rw-r--r--absl/flags/internal/usage_test.cc367
-rw-r--r--absl/flags/marshalling.cc189
-rw-r--r--absl/flags/marshalling.h260
-rw-r--r--absl/flags/marshalling_test.cc899
-rw-r--r--absl/flags/parse.cc762
-rw-r--r--absl/flags/parse.h58
-rw-r--r--absl/flags/parse_test.cc858
-rw-r--r--absl/flags/usage_config.cc152
-rw-r--r--absl/flags/usage_config.h131
-rw-r--r--absl/flags/usage_config_test.cc198
35 files changed, 8397 insertions, 0 deletions
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
new file mode 100644
index 000000000000..2d868b0ab8bb
--- /dev/null
+++ b/absl/flags/BUILD.bazel
@@ -0,0 +1,351 @@
+#
+#  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.
+#
+
+load(
+    "//absl:copts/configure_copts.bzl",
+    "ABSL_DEFAULT_COPTS",
+    "ABSL_DEFAULT_LINKOPTS",
+    "ABSL_TEST_COPTS",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])  # Apache 2.0
+
+cc_library(
+    name = "internal",
+    srcs = [
+        "internal/program_name.cc",
+    ],
+    hdrs = [
+        "internal/path_util.h",
+        "internal/program_name.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl/flags:__pkg__",
+    ],
+    deps = [
+        "//absl/strings",
+        "//absl/synchronization",
+    ],
+)
+
+cc_library(
+    name = "config",
+    srcs = [
+        "usage_config.cc",
+    ],
+    hdrs = [
+        "config.h",
+        "usage_config.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":internal",
+        "//absl/base:core_headers",
+        "//absl/strings",
+        "//absl/synchronization",
+    ],
+)
+
+cc_library(
+    name = "marshalling",
+    srcs = [
+        "marshalling.cc",
+    ],
+    hdrs = [
+        "marshalling.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        "//absl/base:core_headers",
+        "//absl/strings",
+        "//absl/strings:str_format",
+    ],
+)
+
+cc_library(
+    name = "handle",
+    srcs = [
+        "internal/commandlineflag.cc",
+    ],
+    hdrs = [
+        "internal/commandlineflag.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl/flags:__pkg__",
+    ],
+    deps = [
+        ":config",
+        ":marshalling",
+        "//absl/base",
+        "//absl/base:core_headers",
+        "//absl/strings",
+        "//absl/synchronization",
+        "//absl/types:optional",
+    ],
+)
+
+cc_library(
+    name = "registry",
+    srcs = [
+        "internal/registry.cc",
+        "internal/type_erased.cc",
+    ],
+    hdrs = [
+        "internal/registry.h",
+        "internal/type_erased.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl/flags:__pkg__",
+    ],
+    deps = [
+        ":config",
+        ":handle",
+        "//absl/base",
+        "//absl/base:core_headers",
+        "//absl/base:dynamic_annotations",
+        "//absl/strings",
+        "//absl/synchronization",
+    ],
+)
+
+cc_library(
+    name = "flag",
+    srcs = [
+        "flag.cc",
+    ],
+    hdrs = [
+        "declare.h",
+        "flag.h",
+        "internal/flag.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        ":handle",
+        ":marshalling",
+        ":registry",
+        "//absl/base",
+        "//absl/base:core_headers",
+        "//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "usage",
+    srcs = [
+        "internal/usage.cc",
+    ],
+    hdrs = [
+        "internal/usage.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    visibility = [
+        "//absl/flags:__pkg__",
+    ],
+    deps = [
+        ":config",
+        ":flag",
+        ":handle",
+        ":internal",
+        "//absl/strings",
+        "//absl/synchronization",
+    ],
+)
+
+cc_library(
+    name = "parse",
+    srcs = ["parse.cc"],
+    hdrs = [
+        "internal/parse.h",
+        "parse.h",
+    ],
+    copts = ABSL_DEFAULT_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        ":flag",
+        ":handle",
+        ":internal",
+        ":registry",
+        ":usage",
+        "//absl/strings",
+        "//absl/synchronization",
+    ],
+)
+
+############################################################################
+# Unit tests in alpahabetical order.
+
+cc_test(
+    name = "commandlineflag_test",
+    size = "small",
+    srcs = [
+        "internal/commandlineflag_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":flag",
+        ":handle",
+        ":registry",
+        "//absl/memory",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "flag_test",
+    size = "small",
+    srcs = [
+        "flag_test.cc",
+        "flag_test_defs.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":flag",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "marshalling_test",
+    size = "small",
+    srcs = [
+        "marshalling_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":marshalling",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "path_util_test",
+    size = "small",
+    srcs = [
+        "internal/path_util_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":internal",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "parse_test",
+    size = "small",
+    srcs = [
+        "parse_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":flag",
+        ":parse",
+        "//absl/base",
+        "//absl/base:scoped_set_env",
+        "//absl/strings",
+        "//absl/types:span",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "program_name_test",
+    size = "small",
+    srcs = [
+        "internal/program_name_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":internal",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "type_erased_test",
+    size = "small",
+    srcs = [
+        "internal/type_erased_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":flag",
+        ":registry",
+        "//absl/memory",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "usage_config_test",
+    size = "small",
+    srcs = [
+        "usage_config_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        ":internal",
+        "//absl/strings",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "usage_test",
+    size = "small",
+    srcs = [
+        "internal/usage_test.cc",
+    ],
+    copts = ABSL_TEST_COPTS,
+    linkopts = ABSL_DEFAULT_LINKOPTS,
+    deps = [
+        ":config",
+        ":flag",
+        ":internal",
+        ":parse",
+        ":usage",
+        "//absl/memory",
+        "//absl/strings",
+        "@com_google_googletest//:gtest",
+    ],
+)
diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt
new file mode 100644
index 000000000000..284d6279b19a
--- /dev/null
+++ b/absl/flags/CMakeLists.txt
@@ -0,0 +1,317 @@
+#
+# 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.
+#
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    flags_internal
+  SRCS
+    "internal/program_name.cc"
+  HDRS
+    "internal/path_util.h"
+    "internal/program_name.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::strings
+    absl::synchronization
+  PUBLIC
+)
+
+absl_cc_library(
+  NAME
+    flags_config
+  SRCS
+    "usage_config.cc"
+  HDRS
+    "config.h"
+    "usage_config.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::flags_internal
+    absl::core_headers
+    absl::strings
+    absl::synchronization
+)
+
+absl_cc_library(
+  NAME
+    flags_marshalling
+  SRCS
+    "marshalling.cc"
+  HDRS
+    "marshalling.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::core_headers
+    absl::strings
+    absl::str_format
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    flags_handle
+  SRCS
+    "internal/commandlineflag.cc"
+  HDRS
+    "internal/commandlineflag.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::flags_config
+    absl::flags_marshalling
+    absl::base
+    absl::core_headers
+    absl::strings
+    absl::synchronization
+    absl::optional
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    flags_registry
+  SRCS
+    "internal/registry.cc"
+    "internal/type_erased.cc"
+  HDRS
+    "internal/registry.h"
+    "internal/type_erased.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::flags_config
+    absl::flags_handle
+    absl::base
+    absl::core_headers
+    absl::dynamic_annotations
+    absl::strings
+    absl::synchronization
+)
+
+absl_cc_library(
+  NAME
+    flags
+  SRCS
+    "flag.cc"
+  HDRS
+    "declare.h"
+    "flag.h"
+    "internal/flag.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::flags_config
+    absl::flags_handle
+    absl::flags_marshalling
+    absl::flags_registry
+    absl::base
+    absl::core_headers
+    absl::strings
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+  NAME
+    flags_usage
+  SRCS
+    "internal/usage.cc"
+  HDRS
+    "internal/usage.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::flags_config
+    absl::flags
+    absl::flags_handle
+    absl::flags_internal
+    absl::strings
+    absl::synchronization
+)
+
+absl_cc_library(
+  NAME
+    flags_parse
+  SRCS
+    "parse.cc"
+  HDRS
+    "internal/parse.h"
+    "parse.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::flags_config
+    absl::flags
+    absl::flags_handle
+    absl::flags_internal
+    absl::flags_registry
+    absl::flags_usage
+    absl::strings
+    absl::synchronization
+)
+
+############################################################################
+# Unit tests in alpahabetical order.
+
+absl_cc_test(
+  NAME
+    flags_commandlineflag_test
+  SRCS
+    "internal/commandlineflag_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::flags
+    absl::flags_handle
+    absl::flags_registry
+    absl::memory
+    absl::strings
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    flags_flag_test
+  SRCS
+    "flag_test.cc"
+    "flag_test_defs.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::flags
+    absl::strings
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    flags_marshalling_test
+  SRCS
+    "marshalling_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::flags_marshalling
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    flags_parse_test
+  SRCS
+    "parse_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::flags
+    absl::base
+    absl::flags_parse
+    absl::scoped_set_env
+    absl::span
+    absl::strings
+    gmock_main
+)
+
+absl_cc_test(
+  NAME
+    flags_path_util_test
+  SRCS
+    "internal/path_util_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::flags_internal
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    flags_program_name_test
+  SRCS
+    "internal/program_name_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::flags_internal
+    absl::strings
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    flags_type_erased_test
+  SRCS
+    "internal/type_erased_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::flags
+    absl::flags_registry
+    absl::memory
+    absl::strings
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    flags_usage_config_test
+  SRCS
+    "usage_config_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::flags_config
+    absl::flags_internal
+    absl::strings
+    gtest_main
+)
+
+absl_cc_test(
+  NAME
+    flags_usage_test
+  SRCS
+    "internal/usage_test.cc"
+  COPTS
+    ${ABSL_TEST_COPTS}
+  DEPS
+    absl::flags_config
+    absl::flags
+    absl::flags_internal
+    absl::flags_parse
+    absl::flags_usage
+    absl::memory
+    absl::strings
+    gtest
+)
diff --git a/absl/flags/config.h b/absl/flags/config.h
new file mode 100644
index 000000000000..a734af4688de
--- /dev/null
+++ b/absl/flags/config.h
@@ -0,0 +1,54 @@
+//
+//  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_CONFIG_H_
+#define ABSL_FLAGS_CONFIG_H_
+
+// Determine if we should strip string literals from the Flag objects.
+#if !defined(ABSL_FLAGS_STRIP_NAMES)
+
+// Non-mobile linux platforms don't strip string literals.
+#if (defined(__linux__) || defined(__Fuchsia__)) && !defined(__ANDROID__)
+#define ABSL_FLAGS_STRIP_NAMES 0
+
+// So do Macs (not iOS or embedded Apple platforms).
+#elif defined(__APPLE__)
+#include <TargetConditionals.h>
+#if !TARGET_OS_IPHONE && !TARGET_OS_EMBEDDED
+#define ABSL_FLAGS_STRIP_NAMES 0
+#endif
+
+// And Windows.
+#elif defined(_WIN32)
+#define ABSL_FLAGS_STRIP_NAMES 0
+
+// And Myriad.
+#elif defined(__myriad2__)
+#define ABSL_FLAGS_STRIP_NAMES 0
+
+#endif
+#endif  // !defined(ABSL_FLAGS_STRIP_NAMES)
+
+#if ABSL_FLAGS_STRIP_NAMES
+#if !defined(ABSL_FLAGS_STRIP_HELP)
+#define ABSL_FLAGS_STRIP_HELP 1
+#endif
+#else
+#if !defined(ABSL_FLAGS_STRIP_HELP)
+#define ABSL_FLAGS_STRIP_HELP 0
+#endif
+#endif
+
+#endif  // ABSL_FLAGS_CONFIG_H_
diff --git a/absl/flags/declare.h b/absl/flags/declare.h
new file mode 100644
index 000000000000..556ec5e9aef9
--- /dev/null
+++ b/absl/flags/declare.h
@@ -0,0 +1,58 @@
+//
+//  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.
+//
+// -----------------------------------------------------------------------------
+// File: declare.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the ABSL_DECLARE_FLAG macro, allowing you to declare an
+// `absl::Flag` for use within a translation unit. You should place this
+// declaration within the header file associated with the .cc file that defines
+// and owns the `Flag`.
+
+#ifndef ABSL_FLAGS_DECLARE_H_
+#define ABSL_FLAGS_DECLARE_H_
+
+#include "absl/strings/string_view.h"
+
+namespace absl {
+namespace flags_internal {
+
+// absl::Flag<T> represents a flag of type 'T' created by ABSL_FLAG.
+template <typename T>
+class Flag;
+
+}  // namespace flags_internal
+
+// Flag
+//
+// Forward declaration of the `absl::Flag` type for use in defining the macro.
+template <typename T>
+using Flag = flags_internal::Flag<T>;
+
+}  // namespace absl
+
+// ABSL_DECLARE_FLAG()
+//
+// This macro is a convenience for declaring use of an `absl::Flag` within a
+// translation unit. This macro should be used within a header file to
+// declare usage of the flag within any .cc file including that header file.
+//
+// The ABSL_DECLARE_FLAG(type, name) macro expands to:
+//
+//   extern absl::Flag<type> FLAGS_name;
+#define ABSL_DECLARE_FLAG(type, name) extern ::absl::Flag<type> FLAGS_##name
+
+#endif  // ABSL_FLAGS_DECLARE_H_
diff --git a/absl/flags/flag.cc b/absl/flags/flag.cc
new file mode 100644
index 000000000000..ba002edd24f1
--- /dev/null
+++ b/absl/flags/flag.cc
@@ -0,0 +1,52 @@
+//
+//  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/flag.h"
+
+#include <cstring>
+
+namespace absl {
+
+// We want to validate the type mismatch between type definition and
+// declaration. The lock-free implementation does not allow us to do it,
+// so in debug builds we always use the slower implementation, which always
+// validates the type.
+#ifndef NDEBUG
+#define ABSL_FLAGS_ATOMIC_GET(T)                              \
+  T GetFlag(const absl::Flag<T>& flag) {                      \
+    T result;                                                 \
+    flag.internal.Read(&result, &flags_internal::FlagOps<T>); \
+    return result;                                            \
+  }
+#else
+#define ABSL_FLAGS_ATOMIC_GET(T)                                            \
+  T GetFlag(const absl::Flag<T>& flag) {                                    \
+    const int64_t r = flag.internal.atomic.load(std::memory_order_acquire); \
+    if (r != flags_internal::CommandLineFlag::kAtomicInit) {                \
+      T t;                                                                  \
+      memcpy(&t, &r, sizeof(T));                                            \
+      return t;                                                             \
+    }                                                                       \
+    T result;                                                               \
+    flag.internal.Read(&result, &flags_internal::FlagOps<T>);               \
+    return result;                                                          \
+  }
+#endif
+
+ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(ABSL_FLAGS_ATOMIC_GET)
+
+#undef ABSL_FLAGS_ATOMIC_GET
+
+}  // namespace absl
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
new file mode 100644
index 000000000000..2cbbb45ceacb
--- /dev/null
+++ b/absl/flags/flag.h
@@ -0,0 +1,281 @@
+//
+//  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.
+//
+// -----------------------------------------------------------------------------
+// File: flag.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `absl::Flag<T>` type for holding command-line
+// flag data, and abstractions to create, get and set such flag data.
+//
+// It is important to note that this type is **unspecified** (an implementation
+// detail) and you do not construct or manipulate actual `absl::Flag<T>`
+// instances. Instead, you define and declare flags using the
+// `ABSL_FLAG()` and `ABSL_DECLARE_FLAG()` macros, and get and set flag values
+// using the `absl::GetFlag()` and `absl::SetFlag()` functions.
+
+#ifndef ABSL_FLAGS_FLAG_H_
+#define ABSL_FLAGS_FLAG_H_
+
+#include "absl/base/attributes.h"
+#include "absl/base/casts.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/marshalling.h"
+
+namespace absl {
+
+// Flag
+//
+// An `absl::Flag` holds a command-line flag value, providing a runtime
+// parameter to a binary. Such flags should be defined in the global namespace
+// and (preferably) in the module containing the binary's `main()` function.
+//
+// You should not construct and cannot use the `absl::Flag` type directly;
+// instead, you should declare flags using the `ABSL_DECLARE_FLAG()` macro
+// within a header file, and define your flag using `ABSL_FLAG()` within your
+// header's associated `.cc` file. Such flags will be named `FLAGS_name`.
+//
+// Example:
+//
+//    .h file
+//
+//      // Declares usage of a flag named "FLAGS_count"
+//      ABSL_DECLARE_FLAG(int, count);
+//
+//    .cc file
+//
+//      // Defines a flag named "FLAGS_count" with a default `int` value of 0.
+//      ABSL_FLAG(int, count, 0, "Count of items to process");
+//
+// No public methods of `absl::Flag<T>` are part of the Abseil Flags API.
+template <typename T>
+using Flag = flags_internal::Flag<T>;
+
+// GetFlag()
+//
+// Returns the value (of type `T`) of an `absl::Flag<T>` instance, by value. Do
+// not construct an `absl::Flag<T>` directly and call `absl::GetFlag()`;
+// instead, refer to flag's constructed variable name (e.g. `FLAGS_name`).
+// Because this function returns by value and not by reference, it is
+// thread-safe, but note that the operation may be expensive; as a result, avoid
+// `absl::GetFlag()` within any tight loops.
+//
+// Example:
+//
+//   // FLAGS_count is a Flag of type `int`
+//   int my_count = absl::GetFlag(FLAGS_count);
+//
+//   // FLAGS_firstname is a Flag of type `std::string`
+//   std::string first_name = absl::GetFlag(FLAGS_firstname);
+template <typename T>
+T GetFlag(const absl::Flag<T>& flag) {
+#define ABSL_FLAGS_INTERNAL_LOCK_FREE_VALIDATE(BIT) \
+  static_assert(                                    \
+      !std::is_same<T, BIT>::value,                 \
+      "Do not specify explicit template parameters to absl::GetFlag");
+  ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(ABSL_FLAGS_INTERNAL_LOCK_FREE_VALIDATE)
+#undef ABSL_FLAGS_INTERNAL_LOCK_FREE_VALIDATE
+
+  // 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;
+
+  flag.internal.Read(&u.value, &flags_internal::FlagOps<T>);
+  return std::move(u.value);
+}
+
+// Overload for `GetFlag()` for types that support lock-free reads.
+#define ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT(T) \
+  extern T GetFlag(const absl::Flag<T>& flag);
+ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT)
+#undef ABSL_FLAGS_INTERNAL_LOCK_FREE_EXPORT
+
+// SetFlag()
+//
+// Sets the value of an `absl::Flag` to the value `v`. Do not construct an
+// `absl::Flag<T>` directly and call `absl::SetFlag()`; instead, use the
+// flag's variable name (e.g. `FLAGS_name`). This function is
+// thread-safe, but is potentially expensive. Avoid setting flags in general,
+// but especially within performance-critical code.
+template <typename T>
+void SetFlag(absl::Flag<T>* flag, const T& v) {
+  flag->internal.Write(&v, &flags_internal::FlagOps<T>);
+}
+
+// Overload of `SetFlag()` to allow callers to pass in a value that is
+// convertible to `T`. E.g., use this overload to pass a "const char*" when `T`
+// is `std::string`.
+template <typename T, typename V>
+void SetFlag(absl::Flag<T>* flag, const V& v) {
+  T value(v);
+  SetFlag<T>(flag, value);
+}
+
+}  // namespace absl
+
+
+// ABSL_FLAG()
+//
+// This macro defines an `absl::Flag<T>` instance of a specified type `T`:
+//
+//   ABSL_FLAG(T, name, default_value, help);
+//
+// where:
+//
+//   * `T` is a supported flag type (See below),
+//   * `name` designates the name of the flag (as a global variable
+//     `FLAGS_name`),
+//   * `default_value` is an expression holding the default value for this flag
+//     (which must be implicitly convertible to `T`),
+//   * `help` is the help text, which can also be an expression.
+//
+// This macro expands to a flag named 'FLAGS_name' of type 'T':
+//
+//   absl::Flag<T> FLAGS_name = ...;
+//
+// Note that all such instances are created as global variables.
+//
+// For `ABSL_FLAG()` values that you wish to expose to other translation units,
+// it is recommended to define those flags within the `.cc` file associated with
+// the header where the flag is declared.
+//
+// Note: do not construct objects of type `absl::Flag<T>` directly. Only use the
+// `ABSL_FLAG()` macro for such construction.
+#define ABSL_FLAG(Type, name, default_value, help) \
+  ABSL_FLAG_IMPL(Type, name, default_value, help)
+
+// ABSL_FLAG().OnUpdate()
+//
+// Defines a flag of type `T` with a callback attached:
+//
+//   ABSL_FLAG(T, name, default_value, help).OnUpdate(callback);
+//
+// After any setting of the flag value, the callback will be called at least
+// once. A rapid sequence of changes may be merged together into the same
+// callback. No concurrent calls to the callback will be made for the same
+// flag. Callbacks are allowed to read the current value of the flag but must
+// not mutate that flag.
+//
+// The update mechanism guarantees "eventual consistency"; if the callback
+// derives an auxiliary data structure from the flag value, it is guaranteed
+// that eventually the flag value and the derived data structure will be
+// consistent.
+//
+// Note: ABSL_FLAG.OnUpdate() does not have a public definition. Hence, this
+// comment serves as its API documentation.
+
+
+// -----------------------------------------------------------------------------
+// Implementation details below this section
+// -----------------------------------------------------------------------------
+
+// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES
+
+#if ABSL_FLAGS_STRIP_NAMES
+#define ABSL_FLAG_IMPL_FLAGNAME(txt) ""
+#define ABSL_FLAG_IMPL_FILENAME() ""
+#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
+  absl::flags_internal::FlagRegistrar<T, false>(&flag)
+#else
+#define ABSL_FLAG_IMPL_FLAGNAME(txt) txt
+#define ABSL_FLAG_IMPL_FILENAME() __FILE__
+#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
+  absl::flags_internal::FlagRegistrar<T, true>(&flag)
+#endif
+
+// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
+
+#if ABSL_FLAGS_STRIP_HELP
+#define ABSL_FLAG_IMPL_FLAGHELP(txt) absl::flags_internal::kStrippedFlagHelp
+#else
+#define ABSL_FLAG_IMPL_FLAGHELP(txt) txt
+#endif
+
+#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt) \
+  static std::string AbslFlagsWrapHelp##name() {       \
+    return ABSL_FLAG_IMPL_FLAGHELP(txt);               \
+  }
+
+#define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)   \
+  static void* AbslFlagsInitFlag##name() {                                  \
+    return absl::flags_internal::MakeFromDefaultValue<Type>(default_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.
+#define ABSL_FLAG_IMPL(Type, name, default_value, help)                   \
+  namespace absl {}                                                       \
+  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)       \
+  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help)                         \
+  absl::Flag<Type> FLAGS_##name(                                          \
+      ABSL_FLAG_IMPL_FLAGNAME(#name),                                     \
+      &AbslFlagsWrapHelp##name,                                           \
+      ABSL_FLAG_IMPL_FILENAME(),                                          \
+      &absl::flags_internal::FlagMarshallingOps<Type>,                    \
+      &AbslFlagsInitFlag##name);                                          \
+  extern bool FLAGS_no##name;                                             \
+  bool FLAGS_no##name = ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
+
+// ABSL_RETIRED_FLAG
+//
+// Designates the flag (which is usually pre-existing) as "retired." A retired
+// flag is a flag that is now unused by the program, but may still be passed on
+// the command line, usually by production scripts. A retired flag is ignored
+// and code can't access it at runtime.
+//
+// This macro registers a retired flag with given name and type, with a name
+// identical to the name of the original flag you are retiring. The retired
+// flag's type can change over time, so that you can retire code to support a
+// custom flag type.
+//
+// This macro has the same signature as `ABSL_FLAG`. To retire a flag, simply
+// replace an `ABSL_FLAG` definition with `ABSL_RETIRED_FLAG`, leaving the
+// arguments unchanged (unless of course you actually want to retire the flag
+// type at this time as well).
+//
+// `default_value` is only used as a double check on the type. `explanation` is
+// unused.
+// TODO(rogeeff): Return an anonymous struct instead of bool, and place it into
+// the unnamed namespace.
+#define ABSL_RETIRED_FLAG(type, flagname, default_value, explanation) \
+  ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname =        \
+      ([] { return type(default_value); },                            \
+       absl::flags_internal::RetiredFlag<type>(#flagname))
+
+#endif  // ABSL_FLAGS_FLAG_H_
diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc
new file mode 100644
index 000000000000..1bcd7e96868e
--- /dev/null
+++ b/absl/flags/flag_test.cc
@@ -0,0 +1,482 @@
+//
+//  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/flag.h"
+
+#include "gtest/gtest.h"
+#include "absl/strings/match.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+
+ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag);
+ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag);
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+std::string TestHelpMsg() { return "help"; }
+template <typename T>
+void* TestMakeDflt() {
+  return new T{};
+}
+void TestCallback() {}
+
+template <typename T>
+bool TestConstructionFor() {
+  constexpr flags::Flag<T> f1("f1", &TestHelpMsg, "file",
+                              &absl::flags_internal::FlagMarshallingOps<T>,
+                              &TestMakeDflt<T>);
+  EXPECT_EQ(f1.Name(), "f1");
+  EXPECT_EQ(f1.Help(), "help");
+  EXPECT_EQ(f1.Filename(), "file");
+
+  ABSL_CONST_INIT static flags::Flag<T> f2(
+      "f2", &TestHelpMsg, "file", &absl::flags_internal::FlagMarshallingOps<T>,
+      &TestMakeDflt<T>);
+  flags::FlagRegistrar<T, false>(&f2).OnUpdate(TestCallback);
+
+  EXPECT_EQ(f2.Name(), "f2");
+  EXPECT_EQ(f2.Help(), "help");
+  EXPECT_EQ(f2.Filename(), "file");
+
+  return true;
+}
+
+struct UDT {
+  UDT() = default;
+  UDT(const UDT&) = default;
+};
+bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
+std::string AbslUnparseFlag(const UDT&) { return ""; }
+
+TEST(FlagTest, TestConstruction) {
+  TestConstructionFor<bool>();
+  TestConstructionFor<int16_t>();
+  TestConstructionFor<uint16_t>();
+  TestConstructionFor<int32_t>();
+  TestConstructionFor<uint32_t>();
+  TestConstructionFor<int64_t>();
+  TestConstructionFor<uint64_t>();
+  TestConstructionFor<double>();
+  TestConstructionFor<float>();
+  TestConstructionFor<std::string>();
+
+  TestConstructionFor<UDT>();
+}
+
+// --------------------------------------------------------------------
+
+}  // namespace
+
+ABSL_DECLARE_FLAG(bool, test_flag_01);
+ABSL_DECLARE_FLAG(int, test_flag_02);
+ABSL_DECLARE_FLAG(int16_t, test_flag_03);
+ABSL_DECLARE_FLAG(uint16_t, test_flag_04);
+ABSL_DECLARE_FLAG(int32_t, test_flag_05);
+ABSL_DECLARE_FLAG(uint32_t, test_flag_06);
+ABSL_DECLARE_FLAG(int64_t, test_flag_07);
+ABSL_DECLARE_FLAG(uint64_t, test_flag_08);
+ABSL_DECLARE_FLAG(double, test_flag_09);
+ABSL_DECLARE_FLAG(float, test_flag_10);
+ABSL_DECLARE_FLAG(std::string, test_flag_11);
+
+namespace {
+
+#if !ABSL_FLAGS_STRIP_NAMES
+
+TEST(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");
+}
+#endif  // !ABSL_FLAGS_STRIP_NAMES
+
+// --------------------------------------------------------------------
+
+}  // namespace
+
+ABSL_FLAG(bool, test_flag_01, true, "test flag 01");
+ABSL_FLAG(int, test_flag_02, 1234, "test flag 02");
+ABSL_FLAG(int16_t, test_flag_03, -34, "test flag 03");
+ABSL_FLAG(uint16_t, test_flag_04, 189, "test flag 04");
+ABSL_FLAG(int32_t, test_flag_05, 10765, "test flag 05");
+ABSL_FLAG(uint32_t, test_flag_06, 40000, "test flag 06");
+ABSL_FLAG(int64_t, test_flag_07, -1234567, "test flag 07");
+ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08");
+ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09");
+ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10");
+ABSL_FLAG(std::string, test_flag_11, "", "test flag 11");
+
+namespace {
+
+#if !ABSL_FLAGS_STRIP_NAMES
+TEST(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));
+
+  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));
+
+  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));
+
+  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));
+
+  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));
+
+  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));
+
+  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));
+
+  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));
+
+  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));
+
+  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));
+
+  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));
+}
+#endif  // !ABSL_FLAGS_STRIP_NAMES
+
+// --------------------------------------------------------------------
+
+TEST(FlagTest, TestDefault) {
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
+}
+
+// --------------------------------------------------------------------
+
+TEST(FlagTest, TestGetSet) {
+  absl::SetFlag(&FLAGS_test_flag_01, false);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), false);
+
+  absl::SetFlag(&FLAGS_test_flag_02, 321);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 321);
+
+  absl::SetFlag(&FLAGS_test_flag_03, 67);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), 67);
+
+  absl::SetFlag(&FLAGS_test_flag_04, 1);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 1);
+
+  absl::SetFlag(&FLAGS_test_flag_05, -908);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), -908);
+
+  absl::SetFlag(&FLAGS_test_flag_06, 4001);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 4001);
+
+  absl::SetFlag(&FLAGS_test_flag_07, -23456);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -23456);
+
+  absl::SetFlag(&FLAGS_test_flag_08, 975310);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 975310);
+
+  absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), 1.00001, 1e-10);
+
+  absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), -3.54f, 1e-6f);
+
+  absl::SetFlag(&FLAGS_test_flag_11, "asdf");
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf");
+}
+
+// --------------------------------------------------------------------
+
+int GetDflt1() { return 1; }
+
+}  // namespace
+
+ABSL_FLAG(int, test_flag_12, GetDflt1(), "test flag 12");
+ABSL_FLAG(std::string, test_flag_13, absl::StrCat("AAA", "BBB"),
+          "test flag 13");
+
+namespace {
+
+TEST(FlagTest, TestNonConstexprDefault) {
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), 1);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), "AAABBB");
+}
+
+// --------------------------------------------------------------------
+
+}  // namespace
+
+ABSL_FLAG(bool, test_flag_14, true, absl::StrCat("test ", "flag ", "14"));
+
+namespace {
+
+#if !ABSL_FLAGS_STRIP_HELP
+TEST(FlagTest, TestNonConstexprHelp) {
+  EXPECT_EQ(FLAGS_test_flag_14.Help(), "test flag 14");
+}
+#endif  //! ABSL_FLAGS_STRIP_HELP
+
+// --------------------------------------------------------------------
+
+int cb_test_value = -1;
+void TestFlagCB();
+
+}  // namespace
+
+ABSL_FLAG(int, test_flag_with_cb, 100, "").OnUpdate(TestFlagCB);
+
+ABSL_FLAG(int, test_flag_with_lambda_cb, 200, "").OnUpdate([]() {
+  cb_test_value = absl::GetFlag(FLAGS_test_flag_with_lambda_cb) +
+                  absl::GetFlag(FLAGS_test_flag_with_cb);
+});
+
+namespace {
+
+void TestFlagCB() { cb_test_value = absl::GetFlag(FLAGS_test_flag_with_cb); }
+
+// Tests side-effects of callback invocation.
+TEST(FlagTest, CallbackInvocation) {
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_cb), 100);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_lambda_cb), 200);
+  EXPECT_EQ(cb_test_value, 300);
+
+  absl::SetFlag(&FLAGS_test_flag_with_cb, 1);
+  EXPECT_EQ(cb_test_value, 1);
+
+  absl::SetFlag(&FLAGS_test_flag_with_lambda_cb, 3);
+  EXPECT_EQ(cb_test_value, 4);
+}
+
+// --------------------------------------------------------------------
+
+struct CustomUDT {
+  CustomUDT() : a(1), b(1) {}
+  CustomUDT(int a_, int b_) : a(a_), b(b_) {}
+
+  friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
+    return f1.a == f2.a && f1.b == f2.b;
+  }
+
+  int a;
+  int b;
+};
+bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
+  std::vector<absl::string_view> parts =
+      absl::StrSplit(in, ':', absl::SkipWhitespace());
+
+  if (parts.size() != 2) return false;
+
+  if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
+
+  if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
+
+  return true;
+}
+std::string AbslUnparseFlag(const CustomUDT& f) {
+  return absl::StrCat(f.a, ":", f.b);
+}
+
+}  // namespace
+
+ABSL_FLAG(CustomUDT, test_flag_15, CustomUDT(), "test flag 15");
+
+namespace {
+
+TEST(FlagTest, TestCustomUDT) {
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(1, 1));
+  absl::SetFlag(&FLAGS_test_flag_15, CustomUDT(2, 3));
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(2, 3));
+}
+
+// MSVC produces link error on the type mismatch.
+// Linux does not have build errors and validations work as expected.
+#if 0  // !defined(_WIN32) && GTEST_HAS_DEATH_TEST
+
+TEST(Flagtest, TestTypeMismatchValidations) {
+  // For builtin types, GetFlag() only does validation in debug mode.
+  EXPECT_DEBUG_DEATH(
+      absl::GetFlag(FLAGS_mistyped_int_flag),
+      "Flag 'mistyped_int_flag' is defined as one type and declared "
+      "as another");
+  EXPECT_DEATH(absl::SetFlag(&FLAGS_mistyped_int_flag, 0),
+               "Flag 'mistyped_int_flag' is defined as one type and declared "
+               "as another");
+
+  EXPECT_DEATH(absl::GetFlag(FLAGS_mistyped_string_flag),
+               "Flag 'mistyped_string_flag' is defined as one type and "
+               "declared as another");
+  EXPECT_DEATH(
+      absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),
+      "Flag 'mistyped_string_flag' is defined as one type and declared as "
+      "another");
+}
+
+#endif
+
+// --------------------------------------------------------------------
+
+// A contrived type that offers implicit and explicit conversion from specific
+// source types.
+struct ConversionTestVal {
+  ConversionTestVal() = default;
+  explicit ConversionTestVal(int a_in) : a(a_in) {}
+
+  enum class ViaImplicitConv { kTen = 10, kEleven };
+  // NOLINTNEXTLINE
+  ConversionTestVal(ViaImplicitConv from) : a(static_cast<int>(from)) {}
+
+  int a;
+};
+
+bool AbslParseFlag(absl::string_view in, ConversionTestVal* val_out,
+                   std::string*) {
+  if (!absl::SimpleAtoi(in, &val_out->a)) {
+    return false;
+  }
+  return true;
+}
+std::string AbslUnparseFlag(const ConversionTestVal& val) {
+  return absl::StrCat(val.a);
+}
+
+}  // namespace
+
+// Flag default values can be specified with a value that converts to the flag
+// value type implicitly.
+ABSL_FLAG(ConversionTestVal, test_flag_16,
+          ConversionTestVal::ViaImplicitConv::kTen, "test flag 16");
+
+namespace {
+
+TEST(FlagTest, CanSetViaImplicitConversion) {
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 10);
+  absl::SetFlag(&FLAGS_test_flag_16,
+                ConversionTestVal::ViaImplicitConv::kEleven);
+  EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 11);
+}
+
+// --------------------------------------------------------------------
+
+struct NonDfltConstructible {
+ public:
+  // This constructor tests that we can initialize the flag with int value
+  NonDfltConstructible(int i) : value(i) {}  // NOLINT
+
+  // This constructor tests that we can't initialize the flag with char value
+  // but can with explicitly constructed NonDfltConstructible.
+  explicit NonDfltConstructible(char c) : value(100 + static_cast<int>(c)) {}
+
+  int value;
+};
+
+bool AbslParseFlag(absl::string_view in, NonDfltConstructible* ndc_out,
+                   std::string*) {
+  return absl::SimpleAtoi(in, &ndc_out->value);
+}
+std::string AbslUnparseFlag(const NonDfltConstructible& ndc) {
+  return absl::StrCat(ndc.value);
+}
+
+}  // namespace
+
+ABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible('1'),
+          "Flag with non default constructible type");
+ABSL_FLAG(NonDfltConstructible, ndc_flag2, 0,
+          "Flag with non default constructible type");
+
+namespace {
+
+TEST(FlagTest, TestNonDefaultConstructibleType) {
+  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, '1' + 100);
+  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 0);
+
+  absl::SetFlag(&FLAGS_ndc_flag1, NonDfltConstructible('A'));
+  absl::SetFlag(&FLAGS_ndc_flag2, 25);
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, 'A' + 100);
+  EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25);
+}
+
+// --------------------------------------------------------------------
+
+}  // namespace
+
+ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
+ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
+ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
+
+namespace {
+
+TEST(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));
+}
+
+}  // namespace
diff --git a/absl/flags/flag_test_defs.cc b/absl/flags/flag_test_defs.cc
new file mode 100644
index 000000000000..3366c5803279
--- /dev/null
+++ b/absl/flags/flag_test_defs.cc
@@ -0,0 +1,22 @@
+//
+//  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.
+
+// This file is used to test the mismatch of the flag type between definition
+// and declaration. These are definitions. flag_test.cc contains declarations.
+#include <string>
+#include "absl/flags/flag.h"
+
+ABSL_FLAG(int, mistyped_int_flag, 0, "");
+ABSL_FLAG(std::string, mistyped_string_flag, "", "");
diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc
new file mode 100644
index 000000000000..744447219c71
--- /dev/null
+++ b/absl/flags/internal/commandlineflag.cc
@@ -0,0 +1,383 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/internal/commandlineflag.h"
+
+#include <cassert>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/optimization.h"
+#include "absl/flags/config.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/str_cat.h"
+#include "absl/synchronization/mutex.h"
+
+namespace absl {
+namespace flags_internal {
+
+// The help message indicating that the commandline flag has been
+// 'stripped'. It will not show up when doing "-help" and its
+// variants. The flag is stripped if ABSL_FLAGS_STRIP_HELP is set to 1
+// before including absl/flags/flag.h
+
+// This is used by this file, and also in commandlineflags_reporting.cc
+const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
+
+namespace {
+
+void StoreAtomic(CommandLineFlag* flag, const void* data, size_t size) {
+  int64_t t = 0;
+  assert(size <= sizeof(int64_t));
+  memcpy(&t, data, size);
+  flag->atomic.store(t, std::memory_order_release);
+}
+
+// If the flag has a mutation callback this function invokes it. While the
+// callback is being invoked the primary flag's mutex is unlocked and it is
+// re-locked back after call to callback is completed. Callback invocation is
+// guarded by flag's secondary mutex instead which prevents concurrent callback
+// invocation. Note that it is possible for other thread to grab the primary
+// lock and update flag's value at any time during the callback invocation.
+// This is by design. Callback can get a value of the flag if necessary, but it
+// might be different from the value initiated the callback and it also can be
+// different by the time the callback invocation is completed.
+// Requires that *primary_lock be held in exclusive mode; it may be released
+// and reacquired by the implementation.
+void InvokeCallback(CommandLineFlag* flag, absl::Mutex* primary_lock)
+    EXCLUSIVE_LOCKS_REQUIRED(primary_lock) {
+  if (!flag->callback) return;
+
+  // The callback lock is guaranteed initialized, because *primary_lock exists.
+  absl::Mutex* callback_mu = &flag->locks->callback_mu;
+
+  // When executing the callback we need the primary flag's mutex to be unlocked
+  // so that callback can retrieve the flag's value.
+  primary_lock->Unlock();
+
+  {
+    absl::MutexLock lock(callback_mu);
+
+    flag->callback();
+  }
+
+  primary_lock->Lock();
+}
+
+// Currently we only validate flag values for user-defined flag types.
+bool ShouldValidateFlagValue(const CommandLineFlag& flag) {
+#define DONT_VALIDATE(T) \
+  if (flag.IsOfType<T>()) return false;
+  ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(DONT_VALIDATE)
+  DONT_VALIDATE(std::string)
+  DONT_VALIDATE(std::vector<std::string>)
+#undef DONT_VALIDATE
+
+  return true;
+}
+
+}  // namespace
+
+// Update any copy of the flag value that is stored in an atomic word.
+// In addition if flag has a mutation callback this function invokes it.
+void UpdateCopy(CommandLineFlag* flag, absl::Mutex* primary_lock)
+    EXCLUSIVE_LOCKS_REQUIRED(primary_lock) {
+#define STORE_ATOMIC(T)                      \
+  else if (flag->IsOfType<T>()) {            \
+    StoreAtomic(flag, flag->cur, sizeof(T)); \
+  }
+
+  if (false) {
+  }
+  ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(STORE_ATOMIC)
+#undef STORE_ATOMIC
+
+  InvokeCallback(flag, primary_lock);
+}
+
+// Ensure that the lazily initialized fields of *flag have been initialized,
+// and return &flag->locks->primary_mu.
+absl::Mutex* InitFlagIfNecessary(CommandLineFlag* flag)
+    LOCK_RETURNED(flag->locks->primary_mu) {
+  absl::Mutex* mu;
+  if (!flag->inited.load(std::memory_order_acquire)) {
+    // Need to initialize lazily initialized fields.
+    ABSL_CONST_INIT static absl::Mutex init_lock(absl::kConstInit);
+    init_lock.Lock();
+    if (flag->locks == nullptr) {  // Must initialize Mutexes for this flag.
+      flag->locks = new flags_internal::CommandLineFlagLocks;
+    }
+    mu = &flag->locks->primary_mu;
+    init_lock.Unlock();
+    mu->Lock();
+    if (!flag->retired &&
+        flag->def == nullptr) {  // Need to initialize def and cur fields.
+      flag->def = (*flag->make_init_value)();
+      flag->cur = Clone(flag->op, flag->def);
+      UpdateCopy(flag, mu);
+    }
+    mu->Unlock();
+    flag->inited.store(true, std::memory_order_release);
+  } else {  // All fields initialized; flag->locks is therefore safe to read.
+    mu = &flag->locks->primary_mu;
+  }
+  return mu;
+}
+
+// Return true iff flag value was changed via direct-access.
+bool ChangedDirectly(CommandLineFlag* flag, const void* a, const void* b) {
+  if (!flag->IsAbseilFlag()) {
+    // Need to compare values for direct-access flags.
+#define CHANGED_FOR_TYPE(T)                                                  \
+  if (flag->IsOfType<T>()) {                                                 \
+    return *reinterpret_cast<const T*>(a) != *reinterpret_cast<const T*>(b); \
+  }
+
+    CHANGED_FOR_TYPE(bool);
+    CHANGED_FOR_TYPE(int32_t);
+    CHANGED_FOR_TYPE(int64_t);
+    CHANGED_FOR_TYPE(uint64_t);
+    CHANGED_FOR_TYPE(double);
+    CHANGED_FOR_TYPE(std::string);
+#undef CHANGED_FOR_TYPE
+  }
+  return false;
+}
+
+// Direct-access flags can be modified without going through the
+// flag API. Detect such changes and updated the modified bit.
+void UpdateModifiedBit(CommandLineFlag* flag) {
+  if (!flag->IsAbseilFlag()) {
+    absl::MutexLock l(InitFlagIfNecessary(flag));
+    if (!flag->modified && ChangedDirectly(flag, flag->cur, flag->def)) {
+      flag->modified = true;
+    }
+  }
+}
+
+bool Validate(CommandLineFlag*, const void*) {
+  return true;
+}
+
+std::string HelpText::GetHelpText() const {
+  if (help_function_) return help_function_();
+  if (help_message_) return help_message_;
+
+  return {};
+}
+
+const int64_t CommandLineFlag::kAtomicInit;
+
+void CommandLineFlag::Read(void* dst,
+                           const flags_internal::FlagOpFn dst_op) const {
+  absl::ReaderMutexLock l(
+      InitFlagIfNecessary(const_cast<CommandLineFlag*>(this)));
+
+  // `dst_op` is the unmarshaling operation corresponding to the declaration
+  // visibile at the call site. `op` is the Flag's defined unmarshalling
+  // operation. They must match for this operation to be well-defined.
+  if (ABSL_PREDICT_FALSE(dst_op != op)) {
+    ABSL_INTERNAL_LOG(
+        ERROR,
+        absl::StrCat("Flag '", name,
+                     "' is defined as one type and declared as another"));
+  }
+  CopyConstruct(op, cur, dst);
+}
+
+void CommandLineFlag::Write(const void* src,
+                            const flags_internal::FlagOpFn src_op) {
+  absl::Mutex* mu = InitFlagIfNecessary(this);
+  absl::MutexLock l(mu);
+
+  // `src_op` is the marshalling operation corresponding to the declaration
+  // visible at the call site. `op` is the Flag's defined marshalling operation.
+  // They must match for this operation to be well-defined.
+  if (ABSL_PREDICT_FALSE(src_op != op)) {
+    ABSL_INTERNAL_LOG(
+        ERROR,
+        absl::StrCat("Flag '", name,
+                     "' is defined as one type and declared as another"));
+  }
+
+  if (ShouldValidateFlagValue(*this)) {
+    void* obj = Clone(op, src);
+    std::string ignored_error;
+    std::string src_as_str = Unparse(marshalling_op, src);
+    if (!Parse(marshalling_op, src_as_str, obj, &ignored_error) ||
+        !Validate(this, obj)) {
+      ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", name,
+                                            "' to invalid value ", src_as_str));
+    }
+    Delete(op, obj);
+  }
+
+  modified = true;
+  counter++;
+  Copy(op, src, cur);
+
+  UpdateCopy(this, mu);
+}
+
+absl::string_view CommandLineFlag::Typename() const {
+  // We do not store/report type in Abseil Flags, so that user do not rely on in
+  // at runtime
+  if (IsAbseilFlag() || IsRetired()) return "";
+
+#define HANDLE_V1_BUILTIN_TYPE(t) \
+  if (IsOfType<t>()) {            \
+    return #t;                    \
+  }
+
+  HANDLE_V1_BUILTIN_TYPE(bool);
+  HANDLE_V1_BUILTIN_TYPE(int32_t);
+  HANDLE_V1_BUILTIN_TYPE(int64_t);
+  HANDLE_V1_BUILTIN_TYPE(uint64_t);
+  HANDLE_V1_BUILTIN_TYPE(double);
+#undef HANDLE_V1_BUILTIN_TYPE
+
+  if (IsOfType<std::string>()) {
+    return "string";
+  }
+
+  return "";
+}
+
+std::string CommandLineFlag::Filename() const {
+  return flags_internal::GetUsageConfig().normalize_filename(this->filename);
+}
+
+std::string CommandLineFlag::DefaultValue() const {
+  return Unparse(this->marshalling_op, this->def);
+}
+
+std::string CommandLineFlag::CurrentValue() const {
+  return Unparse(this->marshalling_op, this->cur);
+}
+
+void CommandLineFlag::SetCallback(
+    const flags_internal::FlagCallback mutation_callback) {
+  absl::Mutex* mu = InitFlagIfNecessary(this);
+  absl::MutexLock l(mu);
+
+  callback = mutation_callback;
+
+  InvokeCallback(this, mu);
+}
+
+// Attempts to parse supplied `value` string using parsing routine in the `flag`
+// argument. If parsing is successful, it will try to validate that the parsed
+// value is valid for the specified 'flag'. Finally this function stores the
+// parsed value in 'dst' assuming it is a pointer to the flag's value type. In
+// case if any error is encountered in either step, the error message is stored
+// in 'err'
+static bool TryParseLocked(CommandLineFlag* flag, void* dst,
+                           absl::string_view value, std::string* err) {
+  void* tentative_value = Clone(flag->op, flag->def);
+  std::string parse_err;
+  if (!Parse(flag->marshalling_op, value, tentative_value, &parse_err)) {
+    auto type_name = flag->Typename();
+    absl::string_view err_sep = parse_err.empty() ? "" : "; ";
+    absl::string_view typename_sep = type_name.empty() ? "" : " ";
+    *err = absl::StrCat("Illegal value '", value, "' specified for",
+                        typename_sep, type_name, " flag '", flag->Name(), "'",
+                        err_sep, parse_err);
+    Delete(flag->op, tentative_value);
+    return false;
+  }
+
+  if (!Validate(flag, tentative_value)) {
+    *err = absl::StrCat("Failed validation of new value '",
+                        Unparse(flag->marshalling_op, tentative_value),
+                        "' for flag '", flag->Name(), "'");
+    Delete(flag->op, tentative_value);
+    return false;
+  }
+
+  flag->counter++;
+  Copy(flag->op, tentative_value, dst);
+  Delete(flag->op, tentative_value);
+  return true;
+}
+
+// Sets the value of the flag based on specified string `value`. If the flag
+// was successfully set to new value, it returns true. Otherwise, sets `err`
+// to indicate the error, leaves the flag unchanged, and returns false. There
+// are three ways to set the flag's value:
+//  * Update the current flag value
+//  * Update the flag's default value
+//  * Update the current flag value if it was never set before
+// The mode is selected based on 'set_mode' parameter.
+bool CommandLineFlag::SetFromString(absl::string_view value,
+                                    FlagSettingMode set_mode,
+                                    ValueSource source, std::string* err) {
+  if (IsRetired()) return false;
+
+  UpdateModifiedBit(this);
+
+  absl::Mutex* mu = InitFlagIfNecessary(this);
+  absl::MutexLock l(mu);
+
+  switch (set_mode) {
+    case SET_FLAGS_VALUE: {
+      // set or modify the flag's value
+      if (!TryParseLocked(this, this->cur, value, err)) return false;
+      this->modified = true;
+      UpdateCopy(this, mu);
+
+      if (source == kCommandLine) {
+        this->on_command_line = true;
+      }
+      break;
+    }
+    case SET_FLAG_IF_DEFAULT: {
+      // set the flag's value, but only if it hasn't been set by someone else
+      if (!this->modified) {
+        if (!TryParseLocked(this, this->cur, value, err)) return false;
+        this->modified = true;
+        UpdateCopy(this, mu);
+      } else {
+        // TODO(rogeeff): review and fix this semantic. Currently we do not fail
+        // in this case if flag is modified. This is misleading since the flag's
+        // value is not updated even though we return true.
+        // *err = absl::StrCat(this->Name(), " is already set to ",
+        //                     CurrentValue(), "\n");
+        // return false;
+        return true;
+      }
+      break;
+    }
+    case SET_FLAGS_DEFAULT: {
+      // modify the flag's default-value
+      if (!TryParseLocked(this, this->def, value, err)) return false;
+
+      if (!this->modified) {
+        // Need to set both defvalue *and* current, in this case
+        Copy(this->op, this->def, this->cur);
+        UpdateCopy(this, mu);
+      }
+      break;
+    }
+    default: {
+      // unknown set_mode
+      assert(false);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+}  // namespace flags_internal
+}  // namespace absl
diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h
new file mode 100644
index 000000000000..4815cdc7c9a2
--- /dev/null
+++ b/absl/flags/internal/commandlineflag.h
@@ -0,0 +1,365 @@
+//
+// 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_COMMANDLINEFLAG_H_
+#define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
+
+#include <atomic>
+
+#include "absl/base/macros.h"
+#include "absl/flags/marshalling.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+namespace flags_internal {
+
+// Type-specific operations, eg., parsing, copying, etc. are provided
+// by function specific to that type with a signature matching FlagOpFn.
+enum FlagOp {
+  kDelete,
+  kClone,
+  kCopy,
+  kCopyConstruct,
+  kSizeof,
+  kParse,
+  kUnparse
+};
+using FlagOpFn = void* (*)(FlagOp, const void*, void*);
+using FlagMarshallingOpFn = void* (*)(FlagOp, const void*, void*, void*);
+
+// Options that control SetCommandLineOptionWithMode.
+enum FlagSettingMode {
+  // update the flag's value unconditionally (can call this multiple times).
+  SET_FLAGS_VALUE,
+  // update the flag's value, but *only if* it has not yet been updated
+  // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
+  SET_FLAG_IF_DEFAULT,
+  // set the flag's default value to this.  If the flag has not been updated
+  // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
+  // change the flag's current value to the new default value as well.
+  SET_FLAGS_DEFAULT
+};
+
+// Options that control SetFromString: Source of a value.
+enum ValueSource {
+  // Flag is being set by value specified on a command line.
+  kCommandLine,
+  // Flag is being set by value specified in the code.
+  kProgrammaticChange,
+};
+
+// Signature for the help generation function used as an argument for the
+// absl::Flag constructor.
+using HelpGenFunc = std::string (*)();
+
+// Signature for the function generating the initial flag value based (usually
+// based on default value supplied in flag's definition)
+using InitialValGenFunc = void* (*)();
+
+// Signature for the mutation callback used by watched Flags
+// The callback is noexcept.
+// TODO(rogeeff): add noexcept after C++17 support is added.
+using FlagCallback = void (*)();
+
+extern const char kStrippedFlagHelp[];
+
+// The per-type function
+template <typename T>
+void* FlagOps(FlagOp op, const void* v1, void* v2) {
+  switch (op) {
+    case kDelete:
+      delete static_cast<const T*>(v1);
+      return nullptr;
+    case kClone:
+      return new T(*static_cast<const T*>(v1));
+    case kCopy:
+      *static_cast<T*>(v2) = *static_cast<const T*>(v1);
+      return nullptr;
+    case kCopyConstruct:
+      new (v2) T(*static_cast<const T*>(v1));
+      return nullptr;
+    case kSizeof:
+      return reinterpret_cast<void*>(sizeof(T));
+    default:
+      return nullptr;
+  }
+}
+
+template <typename T>
+void* FlagMarshallingOps(FlagOp op, const void* v1, void* v2, void* v3) {
+  switch (op) {
+    case kParse: {
+      // initialize the temporary instance of type T based on current value in
+      // destination (which is going to be flag's default value).
+      T temp(*static_cast<T*>(v2));
+      if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp,
+                              static_cast<std::string*>(v3))) {
+        return nullptr;
+      }
+      *static_cast<T*>(v2) = std::move(temp);
+      return v2;
+    }
+    case kUnparse:
+      *static_cast<std::string*>(v2) =
+          absl::UnparseFlag<T>(*static_cast<const T*>(v1));
+      return nullptr;
+    default:
+      return nullptr;
+  }
+}
+
+// Functions that invoke flag-type-specific operations.
+inline void Delete(FlagOpFn op, const void* obj) {
+  op(flags_internal::kDelete, obj, nullptr);
+}
+
+inline void* Clone(FlagOpFn op, const void* obj) {
+  return op(flags_internal::kClone, obj, nullptr);
+}
+
+inline void Copy(FlagOpFn op, const void* src, void* dst) {
+  op(flags_internal::kCopy, src, dst);
+}
+
+inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
+  op(flags_internal::kCopyConstruct, src, dst);
+}
+
+inline bool Parse(FlagMarshallingOpFn op, absl::string_view text, void* dst,
+                  std::string* error) {
+  return op(flags_internal::kParse, &text, dst, error) != nullptr;
+}
+
+inline std::string Unparse(FlagMarshallingOpFn op, const void* val) {
+  std::string result;
+  op(flags_internal::kUnparse, val, &result, nullptr);
+  return result;
+}
+
+inline size_t Sizeof(FlagOpFn op) {
+  // This sequence of casts reverses the sequence from base::internal::FlagOps()
+  return static_cast<size_t>(reinterpret_cast<intptr_t>(
+      op(flags_internal::kSizeof, nullptr, nullptr)));
+}
+
+// The following struct contains the locks in a CommandLineFlag struct.
+// They are in a separate struct that is lazily allocated to avoid problems
+// with static initialization and to avoid multiple allocations.
+struct CommandLineFlagLocks {
+  absl::Mutex primary_mu;   // protects several fields in CommandLineFlag
+  absl::Mutex callback_mu;  // used to serialize callbacks
+};
+
+// Holds either a pointer to help text or a function which produces it.  This is
+// needed for supporting both static initialization of Flags while supporting
+// the legacy registration framework.  We can't use absl::variant<const char*,
+// const char*(*)()> since anybody passing 0 or nullptr in to a CommandLineFlag
+// would find an ambiguity.
+class HelpText {
+ public:
+  static constexpr HelpText FromFunctionPointer(const HelpGenFunc fn) {
+    return HelpText(fn, nullptr);
+  }
+  static constexpr HelpText FromStaticCString(const char* msg) {
+    return HelpText(nullptr, msg);
+  }
+
+  std::string GetHelpText() const;
+
+  HelpText() = delete;
+  HelpText(const HelpText&) = default;
+  HelpText(HelpText&&) = default;
+
+ private:
+  explicit constexpr HelpText(const HelpGenFunc fn, const char* msg)
+      : help_function_(fn), help_message_(msg) {}
+
+  HelpGenFunc help_function_;
+  const char* help_message_;
+};
+
+// Holds all information for a flag.
+struct CommandLineFlag {
+  constexpr CommandLineFlag(
+      const char* name_arg, HelpText help_text, const char* filename_arg,
+      const flags_internal::FlagOpFn op_arg,
+      const flags_internal::FlagMarshallingOpFn marshalling_op_arg,
+      const flags_internal::InitialValGenFunc initial_value_gen,
+      const bool retired_arg, void* def_arg, void* cur_arg)
+      : name(name_arg),
+        help(help_text),
+        filename(filename_arg),
+        op(op_arg),
+        marshalling_op(marshalling_op_arg),
+        make_init_value(initial_value_gen),
+        retired(retired_arg),
+        inited(false),
+        modified(false),
+        on_command_line(false),
+        validator(nullptr),
+        callback(nullptr),
+        def(def_arg),
+        cur(cur_arg),
+        counter(0),
+        atomic(kAtomicInit),
+        locks(nullptr) {}
+
+  // Not copyable/assignable.
+  CommandLineFlag(const CommandLineFlag&) = delete;
+  CommandLineFlag& operator=(const CommandLineFlag&) = delete;
+
+  absl::string_view Name() const { return name; }
+  std::string Help() const { return help.GetHelpText(); }
+  bool IsRetired() const { return this->retired; }
+  bool IsSpecifiedOnCommandLine() const { return on_command_line; }
+  // Returns true iff this is a handle to an Abseil Flag.
+  bool IsAbseilFlag() const {
+    // Set to null for V1 flags
+    return this->make_init_value != nullptr;
+  }
+
+  absl::string_view Typename() const;
+  std::string Filename() const;
+  std::string DefaultValue() const;
+  std::string CurrentValue() const;
+
+  // Return true iff flag has type T.
+  template <typename T>
+  inline bool IsOfType() const {
+    return this->op == &flags_internal::FlagOps<T>;
+  }
+
+  // Attempts to retrieve the flag value. Returns value on success,
+  // absl::nullopt otherwise.
+  template <typename T>
+  absl::optional<T> Get() {
+    if (IsRetired() || flags_internal::FlagOps<T> != this->op)
+      return absl::nullopt;
+
+    T res;
+    Read(&res, flags_internal::FlagOps<T>);
+
+    return res;
+  }
+
+  void SetCallback(const flags_internal::FlagCallback mutation_callback);
+
+  // Sets the value of the flag based on specified std::string `value`. If the flag
+  // was successfully set to new value, it returns true. Otherwise, sets `error`
+  // to indicate the error, leaves the flag unchanged, and returns false. There
+  // are three ways to set the flag's value:
+  //  * Update the current flag value
+  //  * Update the flag's default value
+  //  * Update the current flag value if it was never set before
+  // The mode is selected based on `set_mode` parameter.
+  bool SetFromString(absl::string_view value,
+                     flags_internal::FlagSettingMode set_mode,
+                     flags_internal::ValueSource source, std::string* error);
+
+  // Constant configuration for a particular flag.
+ private:
+  const char* const name;
+  const HelpText help;
+  const char* const filename;
+
+ public:
+  const FlagOpFn op;                  // Type-specific handler
+  const FlagMarshallingOpFn marshalling_op;  // Marshalling ops handler
+  const InitialValGenFunc make_init_value;   // Makes initial value for the flag
+  const bool retired;                 // Is the flag retired?
+  std::atomic<bool> inited;           // fields have been lazily initialized
+
+  // Mutable state (guarded by locks->primary_mu).
+  bool modified;          // Has flag value been modified?
+  bool on_command_line;   // Specified on command line.
+  bool (*validator)();    // Validator function, or nullptr
+  FlagCallback callback;  // Mutation callback, or nullptr
+  void* def;              // Lazily initialized pointer to default value
+  void* cur;              // Lazily initialized pointer to current value
+  int64_t counter;          // Mutation counter
+
+  // For some types, a copy of the current value is kept in an atomically
+  // accessible field.
+  static const int64_t kAtomicInit = 0xababababababababll;
+  std::atomic<int64_t> atomic;
+
+  // Lazily initialized mutexes for this flag value.  We cannot inline a
+  // SpinLock or Mutex here because those have non-constexpr constructors and
+  // so would prevent constant initialization of this type.
+  // TODO(rogeeff): fix it once Mutex has constexpr constructor
+  struct CommandLineFlagLocks* locks;  // locks, laziliy allocated.
+
+  // copy construct new value of flag's type in a memory referenced by dst
+  // based on current flag's value
+  void Read(void* dst, const flags_internal::FlagOpFn dst_op) const;
+  // updates flag's value to *src (locked)
+  void Write(const void* src, const flags_internal::FlagOpFn src_op);
+
+  ABSL_DEPRECATED(
+      "temporary until FlagName call sites are migrated and validator API is "
+      "changed")
+  const char* NameAsCString() const { return name; }
+
+ private:
+  friend class FlagRegistry;
+};
+
+// Ensure that the lazily initialized fields of *flag have been initialized,
+// and return &flag->locks->primary_mu.
+absl::Mutex* InitFlagIfNecessary(CommandLineFlag* flag);
+// Update any copy of the flag value that is stored in an atomic word.
+// In addition if flag has a mutation callback this function invokes it. While
+// callback is being invoked the primary flag's mutex is unlocked and it is
+// re-locked back after call to callback is completed. Callback invocation is
+// guarded by flag's secondary mutex instead which prevents concurrent callback
+// invocation. Note that it is possible for other thread to grab the primary
+// lock and update flag's value at any time during the callback invocation.
+// This is by design. Callback can get a value of the flag if necessary, but it
+// might be different from the value initiated the callback and it also can be
+// different by the time the callback invocation is completed.
+// Requires that *primary_lock be held in exclusive mode; it may be released
+// and reacquired by the implementation.
+void UpdateCopy(CommandLineFlag* flag, absl::Mutex* primary_lock);
+// Return true iff flag value was changed via direct-access.
+bool ChangedDirectly(CommandLineFlag* flag, const void* a, const void* b);
+// Direct-access flags can be modified without going through the
+// flag API.  Detect such changes and updated the modified bit.
+void UpdateModifiedBit(CommandLineFlag* flag);
+// Invoke the flag validators for old flags.
+// TODO(rogeeff): implement proper validators for Abseil Flags
+bool Validate(CommandLineFlag* flag, const void* value);
+
+// This macro is the "source of truth" for the list of supported flag types we
+// expect to perform lock free operations on. Specifically it generates code,
+// a one argument macro operating on a type, supplied as a macro argument, for
+// each type in the list.
+#define ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(A) \
+  A(bool)                                         \
+  A(short)                                        \
+  A(unsigned short)                               \
+  A(int)                                          \
+  A(unsigned int)                                 \
+  A(long)                                         \
+  A(unsigned long)                                \
+  A(long long)                                    \
+  A(unsigned long long)                           \
+  A(double)                                       \
+  A(float)
+
+}  // namespace flags_internal
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
diff --git a/absl/flags/internal/commandlineflag_test.cc b/absl/flags/internal/commandlineflag_test.cc
new file mode 100644
index 000000000000..705f301ce7a0
--- /dev/null
+++ b/absl/flags/internal/commandlineflag_test.cc
@@ -0,0 +1,196 @@
+//
+//  Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/internal/commandlineflag.h"
+
+#include "gtest/gtest.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/registry.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
+
+ABSL_FLAG(int, int_flag, 201, "int_flag help");
+ABSL_FLAG(std::string, string_flag, "dflt",
+          absl::StrCat("string_flag", " help"));
+ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+class CommandLineFlagTest : public testing::Test {
+ protected:
+  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(CommandLineFlagTest, TestAttributesAccessMethods) {
+  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+
+  ASSERT_TRUE(flag_01);
+  EXPECT_EQ(flag_01->Name(), "int_flag");
+  EXPECT_EQ(flag_01->Help(), "int_flag help");
+  EXPECT_EQ(flag_01->Typename(), "");
+  EXPECT_TRUE(!flag_01->IsRetired());
+  EXPECT_TRUE(flag_01->IsOfType<int>());
+  EXPECT_TRUE(absl::EndsWith(
+      flag_01->Filename(),
+      "absl/flags/internal/commandlineflag_test.cc"));
+
+  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+
+  ASSERT_TRUE(flag_02);
+  EXPECT_EQ(flag_02->Name(), "string_flag");
+  EXPECT_EQ(flag_02->Help(), "string_flag help");
+  EXPECT_EQ(flag_02->Typename(), "");
+  EXPECT_TRUE(!flag_02->IsRetired());
+  EXPECT_TRUE(flag_02->IsOfType<std::string>());
+  EXPECT_TRUE(absl::EndsWith(
+      flag_02->Filename(),
+      "absl/flags/internal/commandlineflag_test.cc"));
+
+  auto* flag_03 = flags::FindRetiredFlag("bool_retired_flag");
+
+  ASSERT_TRUE(flag_03);
+  EXPECT_EQ(flag_03->Name(), "bool_retired_flag");
+  EXPECT_EQ(flag_03->Help(), "");
+  EXPECT_EQ(flag_03->Typename(), "");
+  EXPECT_TRUE(flag_03->IsRetired());
+  EXPECT_TRUE(flag_03->IsOfType<bool>());
+  EXPECT_EQ(flag_03->Filename(), "RETIRED");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
+  absl::SetFlag(&FLAGS_int_flag, 301);
+  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+
+  ASSERT_TRUE(flag_01);
+  EXPECT_EQ(flag_01->CurrentValue(), "301");
+  EXPECT_EQ(flag_01->DefaultValue(), "201");
+
+  absl::SetFlag(&FLAGS_string_flag, "new_str_value");
+  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+
+  ASSERT_TRUE(flag_02);
+  EXPECT_EQ(flag_02->CurrentValue(), "new_str_value");
+  EXPECT_EQ(flag_02->DefaultValue(), "dflt");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestSetFromStringCurrentValue) {
+  std::string err;
+
+  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+  EXPECT_FALSE(flag_01->on_command_line);
+
+  EXPECT_TRUE(flag_01->SetFromString("11", flags::SET_FLAGS_VALUE,
+                                     flags::kProgrammaticChange, &err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
+  EXPECT_FALSE(flag_01->on_command_line);
+
+  EXPECT_TRUE(flag_01->SetFromString("-123", flags::SET_FLAGS_VALUE,
+                                     flags::kProgrammaticChange, &err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
+  EXPECT_FALSE(flag_01->on_command_line);
+
+  EXPECT_TRUE(!flag_01->SetFromString("xyz", flags::SET_FLAGS_VALUE,
+                                      flags::kProgrammaticChange, &err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
+  EXPECT_EQ(err, "Illegal value 'xyz' specified for flag 'int_flag'");
+  EXPECT_FALSE(flag_01->on_command_line);
+
+  EXPECT_TRUE(!flag_01->SetFromString("A1", flags::SET_FLAGS_VALUE,
+                                      flags::kProgrammaticChange, &err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
+  EXPECT_EQ(err, "Illegal value 'A1' specified for flag 'int_flag'");
+  EXPECT_FALSE(flag_01->on_command_line);
+
+  EXPECT_TRUE(flag_01->SetFromString("0x10", flags::SET_FLAGS_VALUE,
+                                     flags::kProgrammaticChange, &err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);
+  EXPECT_FALSE(flag_01->on_command_line);
+
+  EXPECT_TRUE(flag_01->SetFromString("011", flags::SET_FLAGS_VALUE,
+                                     flags::kCommandLine, &err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
+  EXPECT_TRUE(flag_01->on_command_line);
+
+  EXPECT_TRUE(!flag_01->SetFromString("", flags::SET_FLAGS_VALUE,
+                                      flags::kProgrammaticChange, &err));
+  EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'");
+
+  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+  EXPECT_TRUE(flag_02->SetFromString("xyz", flags::SET_FLAGS_VALUE,
+                                     flags::kProgrammaticChange, &err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz");
+
+  EXPECT_TRUE(flag_02->SetFromString("", flags::SET_FLAGS_VALUE,
+                                     flags::kProgrammaticChange, &err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestSetFromStringDefaultValue) {
+  std::string err;
+
+  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+
+  EXPECT_TRUE(flag_01->SetFromString("111", flags::SET_FLAGS_DEFAULT,
+                                     flags::kProgrammaticChange, &err));
+  EXPECT_EQ(flag_01->DefaultValue(), "111");
+
+  auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+
+  EXPECT_TRUE(flag_02->SetFromString("abc", flags::SET_FLAGS_DEFAULT,
+                                     flags::kProgrammaticChange, &err));
+  EXPECT_EQ(flag_02->DefaultValue(), "abc");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestSetFromStringIfDefault) {
+  std::string err;
+
+  auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+
+  EXPECT_TRUE(flag_01->SetFromString("22", flags::SET_FLAG_IF_DEFAULT,
+                                     flags::kProgrammaticChange, &err))
+      << err;
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
+
+  EXPECT_TRUE(flag_01->SetFromString("33", flags::SET_FLAG_IF_DEFAULT,
+                                     flags::kProgrammaticChange, &err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
+  // EXPECT_EQ(err, "ERROR: int_flag is already set to 22");
+
+  // Reset back to default value
+  EXPECT_TRUE(flag_01->SetFromString("201", flags::SET_FLAGS_VALUE,
+                                     flags::kProgrammaticChange, &err));
+
+  EXPECT_TRUE(flag_01->SetFromString("33", flags::SET_FLAG_IF_DEFAULT,
+                                     flags::kProgrammaticChange, &err));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201);
+  // EXPECT_EQ(err, "ERROR: int_flag is already set to 201");
+}
+
+}  // namespace
diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h
new file mode 100644
index 000000000000..6402866f2249
--- /dev/null
+++ b/absl/flags/internal/flag.h
@@ -0,0 +1,103 @@
+//
+// 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_FLAG_H_
+#define ABSL_FLAGS_INTERNAL_FLAG_H_
+
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/registry.h"
+
+namespace absl {
+namespace flags_internal {
+
+// This is "unspecified" implementation of absl::Flag<T> type.
+template <typename T>
+class Flag {
+ public:
+  constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen,
+                 const char* filename,
+                 const flags_internal::FlagMarshallingOpFn marshalling_op,
+                 const flags_internal::InitialValGenFunc initial_value_gen)
+      : internal(name, flags_internal::HelpText::FromFunctionPointer(help_gen),
+                 filename, &flags_internal::FlagOps<T>, marshalling_op,
+                 initial_value_gen,
+                 /*retired_arg=*/false, /*def_arg=*/nullptr,
+                 /*cur_arg=*/nullptr) {}
+
+  // Not copyable/assignable.
+  Flag(const Flag<T>&) = delete;
+  Flag<T>& operator=(const Flag<T>&) = delete;
+
+  absl::string_view Name() const { return internal.Name(); }
+  std::string Help() const { return internal.Help(); }
+  std::string Filename() const { return internal.Filename(); }
+
+  absl::flags_internal::CommandLineFlag internal;
+
+  void SetCallback(const flags_internal::FlagCallback mutation_callback) {
+    internal.SetCallback(mutation_callback);
+  }
+
+ private:
+  // TODO(rogeeff): add these validations once UnparseFlag invocation is fixed
+  // for built-in types and when we cleanup existing code from operating on
+  // forward declared types.
+  //  auto IsCopyConstructible(const T& v) -> decltype(T(v));
+  //  auto HasAbslParseFlag(absl::string_view in, T* dst, std::string* err)
+  //      -> decltype(AbslParseFlag(in, dst, GlobalStringADLGuard(err)));
+  //  auto HasAbslUnparseFlag(const T& v) -> decltype(AbslUnparseFlag(v));
+};
+
+// This class facilitates Flag object registration and tail expression-based
+// flag definition, for example:
+// ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher);
+template <typename T, bool do_register>
+class FlagRegistrar {
+ public:
+  explicit FlagRegistrar(Flag<T>* flag) : flag_(flag) {
+    if (do_register) flags_internal::RegisterCommandLineFlag(&flag_->internal);
+  }
+
+  FlagRegistrar& OnUpdate(flags_internal::FlagCallback cb) && {
+    flag_->SetCallback(cb);
+    return *this;
+  }
+
+  // Make the registrar "die" gracefully as a bool on a line where registration
+  // happens. Registrar objects are intended to live only as temporary.
+  operator bool() const { return true; }  // NOLINT
+
+ private:
+  Flag<T>* flag_;  // Flag being registered (not owned).
+};
+
+// This struct and corresponding overload to MakeDefaultValue are used to
+// facilitate usage of {} as default value in ABSL_FLAG macro.
+struct EmptyBraces {};
+
+template <typename T>
+T* MakeFromDefaultValue(T t) {
+  return new T(std::move(t));
+}
+
+template <typename T>
+T* MakeFromDefaultValue(EmptyBraces) {
+  return new T;
+}
+
+}  // namespace flags_internal
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_INTERNAL_FLAG_H_
diff --git a/absl/flags/internal/parse.h b/absl/flags/internal/parse.h
new file mode 100644
index 000000000000..fd3aca61f408
--- /dev/null
+++ b/absl/flags/internal/parse.h
@@ -0,0 +1,48 @@
+//
+// 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_PARSE_H_
+#define ABSL_FLAGS_INTERNAL_PARSE_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/flags/declare.h"
+
+ABSL_DECLARE_FLAG(std::vector<std::string>, flagfile);
+ABSL_DECLARE_FLAG(std::vector<std::string>, fromenv);
+ABSL_DECLARE_FLAG(std::vector<std::string>, tryfromenv);
+ABSL_DECLARE_FLAG(std::vector<std::string>, undefok);
+
+namespace absl {
+namespace flags_internal {
+
+enum class ArgvListAction { kRemoveParsedArgs, kKeepParsedArgs };
+enum class UsageFlagsAction { kHandleUsage, kIgnoreUsage };
+enum class OnUndefinedFlag {
+  kIgnoreUndefined,
+  kReportUndefined,
+  kAbortIfUndefined
+};
+
+std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
+                                        ArgvListAction arg_list_act,
+                                        UsageFlagsAction usage_flag_act,
+                                        OnUndefinedFlag on_undef_flag);
+
+}  // namespace flags_internal
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_INTERNAL_PARSE_H_
diff --git a/absl/flags/internal/path_util.h b/absl/flags/internal/path_util.h
new file mode 100644
index 000000000000..5615c0e6c590
--- /dev/null
+++ b/absl/flags/internal/path_util.h
@@ -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.
+
+#ifndef ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
+#define ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
+
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+namespace flags_internal {
+
+// A portable interface that returns the basename of the filename passed as an
+// argument. It is similar to basename(3)
+// <https://linux.die.net/man/3/basename>.
+// For example:
+//     flags_internal::Basename("a/b/prog/file.cc")
+// returns "file.cc"
+//     flags_internal::Basename("file.cc")
+// returns "file.cc"
+inline absl::string_view Basename(absl::string_view filename) {
+  auto last_slash_pos = filename.find_last_of("/\\");
+
+  return last_slash_pos == absl::string_view::npos
+             ? filename
+             : filename.substr(last_slash_pos + 1);
+}
+
+// A portable interface that returns the directory name of the filename
+// passed as an argument, including the trailing slash.
+// Returns the empty string if a slash is not found in the input file name.
+// For example:
+//      flags_internal::Package("a/b/prog/file.cc")
+// returns "a/b/prog/"
+//      flags_internal::Package("file.cc")
+// returns ""
+inline absl::string_view Package(absl::string_view filename) {
+  auto last_slash_pos = filename.find_last_of("/\\");
+
+  return last_slash_pos == absl::string_view::npos
+             ? absl::string_view()
+             : filename.substr(0, last_slash_pos + 1);
+}
+
+}  // namespace flags_internal
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
diff --git a/absl/flags/internal/path_util_test.cc b/absl/flags/internal/path_util_test.cc
new file mode 100644
index 000000000000..2091373c88ea
--- /dev/null
+++ b/absl/flags/internal/path_util_test.cc
@@ -0,0 +1,46 @@
+//
+//  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/path_util.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+TEST(FlagsPathUtilTest, TestBasename) {
+  EXPECT_EQ(flags::Basename(""), "");
+  EXPECT_EQ(flags::Basename("a.cc"), "a.cc");
+  EXPECT_EQ(flags::Basename("dir/a.cc"), "a.cc");
+  EXPECT_EQ(flags::Basename("dir1/dir2/a.cc"), "a.cc");
+  EXPECT_EQ(flags::Basename("../dir1/dir2/a.cc"), "a.cc");
+  EXPECT_EQ(flags::Basename("/dir1/dir2/a.cc"), "a.cc");
+  EXPECT_EQ(flags::Basename("/dir1/dir2/../dir3/a.cc"), "a.cc");
+}
+
+// --------------------------------------------------------------------
+
+TEST(FlagsPathUtilTest, TestPackage) {
+  EXPECT_EQ(flags::Package(""), "");
+  EXPECT_EQ(flags::Package("a.cc"), "");
+  EXPECT_EQ(flags::Package("dir/a.cc"), "dir/");
+  EXPECT_EQ(flags::Package("dir1/dir2/a.cc"), "dir1/dir2/");
+  EXPECT_EQ(flags::Package("../dir1/dir2/a.cc"), "../dir1/dir2/");
+  EXPECT_EQ(flags::Package("/dir1/dir2/a.cc"), "/dir1/dir2/");
+  EXPECT_EQ(flags::Package("/dir1/dir2/../dir3/a.cc"), "/dir1/dir2/../dir3/");
+}
+
+}  // namespace
diff --git a/absl/flags/internal/program_name.cc b/absl/flags/internal/program_name.cc
new file mode 100644
index 000000000000..62be645a96ca
--- /dev/null
+++ b/absl/flags/internal/program_name.cc
@@ -0,0 +1,53 @@
+//
+//  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/program_name.h"
+
+#include <string>
+
+#include "absl/flags/internal/path_util.h"
+#include "absl/synchronization/mutex.h"
+
+namespace absl {
+namespace flags_internal {
+
+ABSL_CONST_INIT static absl::Mutex program_name_guard(absl::kConstInit);
+ABSL_CONST_INIT static std::string* program_name
+    GUARDED_BY(program_name_guard) = nullptr;
+
+std::string ProgramInvocationName() {
+  absl::MutexLock l(&program_name_guard);
+
+  return program_name ? *program_name : "UNKNOWN";
+}
+
+std::string ShortProgramInvocationName() {
+  absl::MutexLock l(&program_name_guard);
+
+  return program_name ? std::string(flags_internal::Basename(*program_name))
+                      : "UNKNOWN";
+}
+
+void SetProgramInvocationName(absl::string_view prog_name_str) {
+  absl::MutexLock l(&program_name_guard);
+
+  if (!program_name)
+    program_name = new std::string(prog_name_str);
+  else
+    program_name->assign(prog_name_str.data(), prog_name_str.size());
+}
+
+}  // namespace flags_internal
+}  // namespace absl
diff --git a/absl/flags/internal/program_name.h b/absl/flags/internal/program_name.h
new file mode 100644
index 000000000000..326f24bb6533
--- /dev/null
+++ b/absl/flags/internal/program_name.h
@@ -0,0 +1,47 @@
+//
+//  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_PROGRAM_NAME_H_
+#define ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_
+
+#include <string>
+
+#include "absl/strings/string_view.h"
+
+// --------------------------------------------------------------------
+// Program name
+
+namespace absl {
+namespace flags_internal {
+
+// Returns program invocation name or "UNKNOWN" if `SetProgramInvocationName()`
+// is never called. At the moment this is always set to argv[0] as part of
+// library initialization.
+std::string ProgramInvocationName();
+
+// Returns base name for program invocation name. For example, if
+//   ProgramInvocationName() == "a/b/mybinary"
+// then
+//   ShortProgramInvocationName() == "mybinary"
+std::string ShortProgramInvocationName();
+
+// Sets program invocation name to a new value. Should only be called once
+// during program initialization, before any threads are spawned.
+void SetProgramInvocationName(absl::string_view prog_name_str);
+
+}  // namespace flags_internal
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_
diff --git a/absl/flags/internal/program_name_test.cc b/absl/flags/internal/program_name_test.cc
new file mode 100644
index 000000000000..ed69218b8395
--- /dev/null
+++ b/absl/flags/internal/program_name_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/internal/program_name.h"
+
+#include "gtest/gtest.h"
+#include "absl/strings/match.h"
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+TEST(FlagsPathUtilTest, TestInitialProgamName) {
+  flags::SetProgramInvocationName("absl/flags/program_name_test");
+  std::string program_name = flags::ProgramInvocationName();
+  for (char& c : program_name)
+    if (c == '\\') c = '/';
+
+#if !defined(__wasm__) && !defined(__asmjs__)
+  const std::string expect_name = "absl/flags/program_name_test";
+  const std::string expect_basename = "program_name_test";
+#else
+  // For targets that generate javascript or webassembly the invocation name
+  // has the special value below.
+  const std::string expect_name = "this.program";
+  const std::string expect_basename = "this.program";
+#endif
+
+  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");
+  EXPECT_EQ(flags::ShortProgramInvocationName(), "my_test");
+
+  absl::string_view not_null_terminated("absl/aaa/bbb");
+  not_null_terminated = not_null_terminated.substr(1, 10);
+
+  flags::SetProgramInvocationName(not_null_terminated);
+
+  EXPECT_EQ(flags::ProgramInvocationName(), "bsl/aaa/bb");
+  EXPECT_EQ(flags::ShortProgramInvocationName(), "bb");
+}
+
+}  // namespace
diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc
new file mode 100644
index 000000000000..435c5b0be330
--- /dev/null
+++ b/absl/flags/internal/registry.cc
@@ -0,0 +1,529 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/internal/registry.h"
+
+#include "absl/base/call_once.h"
+#include "absl/base/dynamic_annotations.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/flags/config.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+
+// --------------------------------------------------------------------
+// FlagRegistry implementation
+//    A FlagRegistry holds all flag objects indexed
+//    by their names so that if you know a flag's name you can access or
+//    set it.
+
+namespace absl {
+namespace flags_internal {
+namespace {
+
+void DestroyFlag(CommandLineFlag* flag) NO_THREAD_SAFETY_ANALYSIS {
+  // Values are heap allocated for retired and Abseil Flags.
+  if (flag->IsRetired() || flag->IsAbseilFlag()) {
+    if (flag->cur) Delete(flag->op, flag->cur);
+    if (flag->def) Delete(flag->op, flag->def);
+  }
+
+  delete flag->locks;
+
+  // CommandLineFlag handle object is heap allocated for non Abseil Flags.
+  if (!flag->IsAbseilFlag()) {
+    delete flag;
+  }
+}
+
+// --------------------------------------------------------------------
+// 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 map from flag pointer to CommandLineFlag*. Used when registering
+// validators.
+class FlagPtrMap {
+ public:
+  void Register(CommandLineFlag* flag) {
+    auto& vec = buckets_[BucketForFlag(flag->cur)];
+    if (vec.size() == vec.capacity()) {
+      // Bypass default 2x growth factor with 1.25 so we have fuller vectors.
+      // This saves 4% memory compared to default growth.
+      vec.reserve(vec.size() * 1.25 + 0.5);
+    }
+    vec.push_back(flag);
+  }
+
+  CommandLineFlag* FindByPtr(const void* flag_ptr) {
+    const auto& flag_vector = buckets_[BucketForFlag(flag_ptr)];
+    for (CommandLineFlag* entry : flag_vector) {
+      if (entry->cur == flag_ptr) {
+        return entry;
+      }
+    }
+    return nullptr;
+  }
+
+ private:
+  // Instead of std::map, we use a custom hash table where each bucket stores
+  // flags in a vector. This reduces memory usage 40% of the memory that would
+  // have been used by std::map.
+  //
+  // kNumBuckets was picked as a large enough prime. As of writing this code, a
+  // typical large binary has ~8k (old-style) flags, and this would gives
+  // buckets with roughly 50 elements each.
+  //
+  // Note that reads to this hash table are rare: exactly as many as we have
+  // flags with validators. As of writing, a typical binary only registers 52
+  // validated flags.
+  static constexpr size_t kNumBuckets = 163;
+  std::vector<CommandLineFlag*> buckets_[kNumBuckets];
+
+  static int BucketForFlag(const void* ptr) {
+    // Modulo a prime is good enough here. On a real program, bucket size stddev
+    // after registering 8k flags is ~5 (mean size at 51).
+    return reinterpret_cast<uintptr_t>(ptr) % kNumBuckets;
+  }
+};
+constexpr size_t FlagPtrMap::kNumBuckets;
+
+}  // namespace
+
+class FlagRegistry {
+ public:
+  FlagRegistry() = default;
+  ~FlagRegistry() {
+    for (auto& p : flags_) {
+      DestroyFlag(p.second);
+    }
+  }
+
+  // Store a flag in this registry.  Takes ownership of *flag.
+  // If ptr is non-null, the flag can later be found by calling
+  // FindFlagViaPtrLocked(ptr).
+  void RegisterFlag(CommandLineFlag* flag, const void* ptr);
+
+  void Lock() EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); }
+  void Unlock() UNLOCK_FUNCTION(lock_) { lock_.Unlock(); }
+
+  // Returns the flag object for the specified name, or nullptr if not found.
+  // Will emit a warning if a 'retired' flag is specified.
+  CommandLineFlag* FindFlagLocked(absl::string_view name);
+
+  // Returns the retired flag object for the specified name, or nullptr if not
+  // found or not retired.  Does not emit a warning.
+  CommandLineFlag* FindRetiredFlagLocked(absl::string_view name);
+
+  // Returns the flag object whose current-value is stored at flag_ptr.
+  CommandLineFlag* FindFlagViaPtrLocked(const void* flag_ptr);
+
+  static FlagRegistry* GlobalRegistry();  // returns a singleton registry
+
+ private:
+  friend class FlagSaverImpl;  // reads all the flags in order to copy them
+  friend void ForEachFlagUnlocked(
+      std::function<void(CommandLineFlag*)> visitor);
+
+  // The map from name to flag, for FindFlagLocked().
+  using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
+  using FlagIterator = FlagMap::iterator;
+  using FlagConstIterator = FlagMap::const_iterator;
+  FlagMap flags_;
+
+  FlagPtrMap flag_ptr_map_;
+
+  static FlagRegistry* global_registry_;  // a singleton registry
+
+  static absl::once_flag global_registry_once_;
+
+  static void InitGlobalRegistry();
+
+  absl::Mutex lock_;
+
+  // Disallow
+  FlagRegistry(const FlagRegistry&);
+  FlagRegistry& operator=(const FlagRegistry&);
+};
+
+// Get the singleton FlagRegistry object
+FlagRegistry* FlagRegistry::global_registry_ = nullptr;
+absl::once_flag FlagRegistry::global_registry_once_;
+
+void FlagRegistry::InitGlobalRegistry() { global_registry_ = new FlagRegistry; }
+
+FlagRegistry* FlagRegistry::GlobalRegistry() {
+  absl::call_once(global_registry_once_, &InitGlobalRegistry);
+
+  return global_registry_;
+}
+
+namespace {
+
+class FlagRegistryLock {
+ public:
+  explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
+  ~FlagRegistryLock() { fr_->Unlock(); }
+
+ private:
+  FlagRegistry* const fr_;
+};
+
+}  // namespace
+
+void FlagRegistry::RegisterFlag(CommandLineFlag* flag, const void* ptr) {
+  FlagRegistryLock registry_lock(this);
+  std::pair<FlagIterator, bool> ins =
+      flags_.insert(FlagMap::value_type(flag->Name(), flag));
+  if (ins.second == false) {  // means the name was already in the map
+    CommandLineFlag* old_flag = ins.first->second;
+    if (flag->IsRetired() != old_flag->IsRetired()) {
+      // All registrations must agree on the 'retired' flag.
+      flags_internal::ReportUsageError(
+          absl::StrCat(
+              "Retired flag '", flag->Name(),
+              "' was defined normally in file '",
+              (flag->IsRetired() ? old_flag->Filename() : flag->Filename()),
+              "'."),
+          true);
+    } else if (flag->op != old_flag->op) {
+      flags_internal::ReportUsageError(
+          absl::StrCat("Flag '", flag->Name(),
+                       "' was defined more than once but with "
+                       "differing types. Defined in files '",
+                       old_flag->Filename(), "' and '", flag->Filename(),
+                       "' with types '", old_flag->Typename(), "' and '",
+                       flag->Typename(), "', respectively."),
+          true);
+    } else if (old_flag->IsRetired()) {
+      // Retired definitions are idempotent. Just keep the old one.
+      DestroyFlag(flag);
+      return;
+    } else if (old_flag->Filename() != flag->Filename()) {
+      flags_internal::ReportUsageError(
+          absl::StrCat("Flag '", flag->Name(),
+                       "' was defined more than once (in files '",
+                       old_flag->Filename(), "' and '", flag->Filename(),
+                       "')."),
+          true);
+    } else {
+      flags_internal::ReportUsageError(
+          absl::StrCat(
+              "Something wrong with flag '", flag->Name(), "' in file '",
+              flag->Filename(), "'. One possibility: file '", flag->Filename(),
+              "' is being linked both statically and dynamically into this "
+              "executable. e.g. some files listed as srcs to a test and also "
+              "listed as srcs of some shared lib deps of the same test."),
+          true);
+    }
+    // All cases above are fatal, except for the retired flags.
+    std::exit(1);
+  }
+
+  if (ptr != nullptr) {
+    // This must be the first time we're seeing this flag.
+    flag_ptr_map_.Register(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;
+}
+
+CommandLineFlag* FlagRegistry::FindFlagViaPtrLocked(const void* flag_ptr) {
+  return flag_ptr_map_.FindByPtr(flag_ptr);
+}
+
+// --------------------------------------------------------------------
+// FlagSaver
+// FlagSaverImpl
+//    This class stores the states of all flags at construct time,
+//    and restores all flags to that state at destruct time.
+//    Its major implementation challenge is that it never modifies
+//    pointers in the 'main' registry, so global FLAG_* vars always
+//    point to the right place.
+// --------------------------------------------------------------------
+
+class FlagSaverImpl {
+ public:
+  // Constructs an empty FlagSaverImpl object.
+  FlagSaverImpl() {}
+  ~FlagSaverImpl() {
+    // reclaim memory from each of our CommandLineFlags
+    for (const SavedFlag& src : backup_registry_) {
+      Delete(src.op, src.current);
+      Delete(src.op, src.default_value);
+    }
+  }
+
+  // Saves the flag states from the flag registry into this object.
+  // It's an error to call this more than once.
+  // Must be called when the registry mutex is not held.
+  void SaveFromRegistry() {
+    assert(backup_registry_.empty());  // call only once!
+    SavedFlag saved;
+    flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) {
+      if (flag->IsRetired()) return;
+
+      saved.name = flag->Name();
+      saved.op = flag->op;
+      saved.marshalling_op = flag->marshalling_op;
+      {
+        absl::MutexLock l(InitFlagIfNecessary(flag));
+        saved.validator = flag->validator;
+        saved.modified = flag->modified;
+        saved.on_command_line = flag->IsSpecifiedOnCommandLine();
+        saved.current = Clone(saved.op, flag->cur);
+        saved.default_value = Clone(saved.op, flag->def);
+        saved.counter = flag->counter;
+      }
+      backup_registry_.push_back(saved);
+    });
+  }
+
+  // Restores the saved flag states into the flag registry.  We
+  // assume no flags were added or deleted from the registry since
+  // the SaveFromRegistry; if they were, that's trouble!  Must be
+  // called when the registry mutex is not held.
+  void RestoreToRegistry() {
+    FlagRegistry* const global_registry = FlagRegistry::GlobalRegistry();
+    FlagRegistryLock frl(global_registry);
+    for (const SavedFlag& src : backup_registry_) {
+      CommandLineFlag* flag = global_registry->FindFlagLocked(src.name);
+      // If null, flag got deleted from registry.
+      if (!flag) continue;
+
+      bool restored = false;
+      {
+        absl::Mutex* mu = InitFlagIfNecessary(flag);
+        absl::MutexLock l(mu);
+        flag->validator = src.validator;
+        flag->modified = src.modified;
+        flag->on_command_line = src.on_command_line;
+        if (flag->counter != src.counter ||
+            ChangedDirectly(flag, src.default_value, flag->def)) {
+          flag->counter++;
+          Copy(src.op, src.default_value, flag->def);
+        }
+        if (flag->counter != src.counter ||
+            ChangedDirectly(flag, src.current, flag->cur)) {
+          restored = true;
+          flag->counter++;
+          Copy(src.op, src.current, flag->cur);
+          UpdateCopy(flag, mu);
+
+          // Revalidate the flag because the validator might store state based
+          // on the flag's value, which just changed due to the restore.
+          // Failing validation is ignored because it's assumed that the flag
+          // was valid previously and there's little that can be done about it
+          // here, anyway.
+          Validate(flag, flag->cur);
+        }
+      }
+
+      // Log statements must be done when no flag lock is held.
+      if (restored) {
+        ABSL_INTERNAL_LOG(
+            INFO, absl::StrCat("Restore saved value of ", flag->Name(), ": ",
+                               Unparse(src.marshalling_op, src.current)));
+      }
+    }
+  }
+
+ private:
+  struct SavedFlag {
+    absl::string_view name;
+    FlagOpFn op;
+    FlagMarshallingOpFn marshalling_op;
+    int64_t counter;
+    bool modified;
+    bool on_command_line;
+    bool (*validator)();
+    const void* current;        // nullptr after restore
+    const void* default_value;  // nullptr after restore
+  };
+
+  std::vector<SavedFlag> backup_registry_;
+
+  FlagSaverImpl(const FlagSaverImpl&);  // no copying!
+  void operator=(const FlagSaverImpl&);
+};
+
+FlagSaver::FlagSaver() : impl_(new FlagSaverImpl()) {
+  impl_->SaveFromRegistry();
+}
+
+void FlagSaver::Ignore() {
+  delete impl_;
+  impl_ = nullptr;
+}
+
+FlagSaver::~FlagSaver() {
+  if (!impl_) return;
+
+  impl_->RestoreToRegistry();
+  delete impl_;
+}
+
+// --------------------------------------------------------------------
+// GetAllFlags()
+//    The main way the FlagRegistry class exposes its data.  This
+//    returns, as strings, all the info about all the flags in
+//    the main registry, sorted first by filename they are defined
+//    in, and then by flagname.
+// --------------------------------------------------------------------
+
+struct FilenameFlagnameLess {
+  bool operator()(const CommandLineFlagInfo& a,
+                  const CommandLineFlagInfo& b) const {
+    int cmp = absl::string_view(a.filename).compare(b.filename);
+    if (cmp != 0) return cmp < 0;
+    return a.name < b.name;
+  }
+};
+
+void FillCommandLineFlagInfo(CommandLineFlag* flag,
+                             CommandLineFlagInfo* result) {
+  result->name = std::string(flag->Name());
+  result->type = std::string(flag->Typename());
+  result->description = flag->Help();
+  result->filename = flag->Filename();
+
+  UpdateModifiedBit(flag);
+
+  absl::MutexLock l(InitFlagIfNecessary(flag));
+  result->current_value = flag->CurrentValue();
+  result->default_value = flag->DefaultValue();
+  result->is_default = !flag->modified;
+  result->has_validator_fn = (flag->validator != nullptr);
+  result->flag_ptr = flag->IsAbseilFlag() ? nullptr : flag->cur;
+}
+
+// --------------------------------------------------------------------
+
+CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
+  if (name.empty()) return nullptr;
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+
+  return registry->FindFlagLocked(name);
+}
+
+CommandLineFlag* FindCommandLineV1Flag(const void* flag_ptr) {
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+
+  return registry->FindFlagViaPtrLocked(flag_ptr);
+}
+
+CommandLineFlag* FindRetiredFlag(absl::string_view name) {
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+
+  return registry->FindRetiredFlagLocked(name);
+}
+
+// --------------------------------------------------------------------
+
+void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor) {
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  for (FlagRegistry::FlagConstIterator i = registry->flags_.begin();
+       i != registry->flags_.end(); ++i) {
+    visitor(i->second);
+  }
+}
+
+void ForEachFlag(std::function<void(CommandLineFlag*)> visitor) {
+  FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+  FlagRegistryLock frl(registry);
+  ForEachFlagUnlocked(visitor);
+}
+
+// --------------------------------------------------------------------
+
+void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT) {
+  flags_internal::ForEachFlag([&](CommandLineFlag* flag) {
+    if (flag->IsRetired()) return;
+
+    CommandLineFlagInfo fi;
+    FillCommandLineFlagInfo(flag, &fi);
+    OUTPUT->push_back(fi);
+  });
+
+  // Now sort the flags, first by filename they occur in, then alphabetically
+  std::sort(OUTPUT->begin(), OUTPUT->end(), FilenameFlagnameLess());
+}
+
+// --------------------------------------------------------------------
+
+bool RegisterCommandLineFlag(CommandLineFlag* flag, const void* ptr) {
+  FlagRegistry::GlobalRegistry()->RegisterFlag(flag, ptr);
+  return true;
+}
+
+// --------------------------------------------------------------------
+
+bool Retire(FlagOpFn ops, FlagMarshallingOpFn marshalling_ops,
+            const char* name) {
+  auto* flag = new CommandLineFlag(
+      name,
+      /*help_text=*/absl::flags_internal::HelpText::FromStaticCString(nullptr),
+      /*filename_arg=*/"RETIRED", ops, marshalling_ops,
+      /*initial_value_gen=*/nullptr,
+      /*retired_arg=*/true, nullptr, nullptr);
+  FlagRegistry::GlobalRegistry()->RegisterFlag(flag, nullptr);
+  return true;
+}
+
+// --------------------------------------------------------------------
+
+bool IsRetiredFlag(absl::string_view name, bool* type_is_bool) {
+  assert(!name.empty());
+  CommandLineFlag* flag = flags_internal::FindRetiredFlag(name);
+  if (flag == nullptr) {
+    return false;
+  }
+  assert(type_is_bool);
+  *type_is_bool = flag->IsOfType<bool>();
+  return true;
+}
+
+}  // namespace flags_internal
+}  // namespace absl
diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h
new file mode 100644
index 000000000000..bd141e1e23d2
--- /dev/null
+++ b/absl/flags/internal/registry.h
@@ -0,0 +1,168 @@
+//
+// 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_REGISTRY_H_
+#define ABSL_FLAGS_INTERNAL_REGISTRY_H_
+
+#include <functional>
+#include <map>
+#include <string>
+
+#include "absl/base/macros.h"
+#include "absl/flags/internal/commandlineflag.h"
+
+// --------------------------------------------------------------------
+// Global flags registry API.
+
+namespace absl {
+namespace flags_internal {
+
+// CommandLineFlagInfo holds all information for a flag.
+struct CommandLineFlagInfo {
+  std::string name;           // the name of the flag
+  std::string type;           // DO NOT use. Use flag->IsOfType<T>() instead.
+  std::string description;    // the "help text" associated with the flag
+  std::string current_value;  // the current value, as a std::string
+  std::string default_value;  // the default value, as a std::string
+  std::string filename;       // 'cleaned' version of filename holding the flag
+  bool has_validator_fn;  // true if RegisterFlagValidator called on this flag
+
+  bool is_default;  // true if the flag has the default value and
+                    // has not been set explicitly from the cmdline
+                    // or via SetCommandLineOption.
+
+  // nullptr for ABSL_FLAG.  A pointer to the flag's current value
+  // otherwise.  E.g., for DEFINE_int32(foo, ...), flag_ptr will be
+  // &FLAGS_foo.
+  const void* flag_ptr;
+};
+
+//-----------------------------------------------------------------------------
+
+void FillCommandLineFlagInfo(CommandLineFlag* flag,
+                             CommandLineFlagInfo* result);
+
+//-----------------------------------------------------------------------------
+
+CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+CommandLineFlag* FindCommandLineV1Flag(const void* flag_ptr);
+CommandLineFlag* FindRetiredFlag(absl::string_view name);
+
+// Executes specified visitor for each non-retired flag in the registry.
+// Requires the caller hold the registry lock.
+void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor);
+// Executes specified visitor for each non-retired flag in the registry. While
+// callback are executed, the registry is locked and can't be changed.
+void ForEachFlag(std::function<void(CommandLineFlag*)> visitor);
+
+//-----------------------------------------------------------------------------
+
+// Store the list of all flags in *OUTPUT, sorted by file.
+void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
+
+//-----------------------------------------------------------------------------
+
+bool RegisterCommandLineFlag(CommandLineFlag*, const void* ptr = nullptr);
+
+//-----------------------------------------------------------------------------
+// Retired registrations:
+//
+// Retired flag registrations are treated specially. A 'retired' flag is
+// provided only for compatibility with automated invocations that still
+// name it.  A 'retired' flag:
+//   - is not bound to a C++ FLAGS_ reference.
+//   - has a type and a value, but that value is intentionally inaccessible.
+//   - does not appear in --help messages.
+//   - is fully supported by _all_ flag parsing routines.
+//   - consumes args normally, and complains about type mismatches in its
+//     argument.
+//   - emits a complaint but does not die (e.g. LOG(ERROR)) if it is
+//     accessed by name through the flags API for parsing or otherwise.
+//
+// The registrations for a flag happen in an unspecified order as the
+// initializers for the namespace-scope objects of a program are run.
+// Any number of weak registrations for a flag can weakly define the flag.
+// One non-weak registration will upgrade the flag from weak to non-weak.
+// Further weak registrations of a non-weak flag are ignored.
+//
+// This mechanism is designed to support moving dead flags into a
+// 'graveyard' library.  An example migration:
+//
+//   0: Remove references to this FLAGS_flagname in the C++ codebase.
+//   1: Register as 'retired' in old_lib.
+//   2: Make old_lib depend on graveyard.
+//   3: Add a redundant 'retired' registration to graveyard.
+//   4: Remove the old_lib 'retired' registration.
+//   5: Eventually delete the graveyard registration entirely.
+//
+// Returns bool to enable use in namespace-scope initializers.
+// For example:
+//
+//   static const bool dummy = base::RetiredFlag<int32_t>("myflag");
+//
+// Or to declare several at once:
+//
+//   static bool dummies[] = {
+//       base::RetiredFlag<std::string>("some_string_flag"),
+//       base::RetiredFlag<double>("some_double_flag"),
+//       base::RetiredFlag<int32_t>("some_int32_flag")
+//   };
+
+// Retire flag with name "name" and type indicated by ops.
+bool Retire(FlagOpFn ops, FlagMarshallingOpFn marshalling_ops,
+            const char* name);
+
+// Registered a retired flag with name 'flag_name' and type 'T'.
+template <typename T>
+inline bool RetiredFlag(const char* flag_name) {
+  return flags_internal::Retire(flags_internal::FlagOps<T>,
+                                flags_internal::FlagMarshallingOps<T>,
+                                flag_name);
+}
+
+// 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
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_INTERNAL_REGISTRY_H_
diff --git a/absl/flags/internal/type_erased.cc b/absl/flags/internal/type_erased.cc
new file mode 100644
index 000000000000..cc103983672b
--- /dev/null
+++ b/absl/flags/internal/type_erased.cc
@@ -0,0 +1,121 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/internal/type_erased.h"
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/flags/config.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+namespace flags_internal {
+
+bool GetCommandLineOption(absl::string_view name, std::string* value) {
+  if (name.empty()) return false;
+  assert(value);
+
+  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
+  if (flag == nullptr || flag->IsRetired()) {
+    return false;
+  }
+
+  absl::MutexLock l(InitFlagIfNecessary(flag));
+  *value = flag->CurrentValue();
+  return true;
+}
+
+bool GetCommandLineFlagInfo(absl::string_view name,
+                            CommandLineFlagInfo* OUTPUT) {
+  if (name.empty()) return false;
+
+  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
+  if (flag == nullptr || flag->IsRetired()) {
+    return false;
+  }
+
+  assert(OUTPUT);
+  FillCommandLineFlagInfo(flag, OUTPUT);
+  return true;
+}
+
+CommandLineFlagInfo GetCommandLineFlagInfoOrDie(absl::string_view name) {
+  CommandLineFlagInfo info;
+  if (!GetCommandLineFlagInfo(name, &info)) {
+    ABSL_INTERNAL_LOG(FATAL, absl::StrCat("Flag '", name, "' does not exist"));
+  }
+  return info;
+}
+
+// --------------------------------------------------------------------
+
+bool SetCommandLineOption(absl::string_view name, absl::string_view value) {
+  return SetCommandLineOptionWithMode(name, value,
+                                      flags_internal::SET_FLAGS_VALUE);
+}
+
+bool SetCommandLineOptionWithMode(absl::string_view name,
+                                  absl::string_view value,
+                                  FlagSettingMode set_mode) {
+  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
+
+  if (!flag || flag->IsRetired()) return false;
+
+  std::string error;
+  if (!flag->SetFromString(value, set_mode, kProgrammaticChange, &error)) {
+    // Errors here are all of the form: the provided name was a recognized
+    // flag, but the value was invalid (bad type, or validation failed).
+    flags_internal::ReportUsageError(error, false);
+    return false;
+  }
+
+  return true;
+}
+
+// --------------------------------------------------------------------
+
+bool IsValidFlagValue(absl::string_view name, absl::string_view value) {
+  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
+  if (flag == nullptr) {
+    return false;
+  }
+
+  if (flag->IsRetired()) {
+    return true;
+  }
+
+  // No need to lock the flag since we are not mutating it.
+  void* obj = Clone(flag->op, flag->def);
+  std::string ignored_error;
+  const bool result =
+      flags_internal::Parse(flag->marshalling_op, value, obj, &ignored_error) &&
+      Validate(flag, obj);
+  Delete(flag->op, obj);
+  return result;
+}
+
+// --------------------------------------------------------------------
+
+bool SpecifiedOnCommandLine(absl::string_view name) {
+  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
+  if (flag != nullptr && !flag->IsRetired()) {
+    absl::MutexLock l(InitFlagIfNecessary(flag));
+    return flag->IsSpecifiedOnCommandLine();
+  }
+  return false;
+}
+
+}  // namespace flags_internal
+}  // namespace absl
diff --git a/absl/flags/internal/type_erased.h b/absl/flags/internal/type_erased.h
new file mode 100644
index 000000000000..249d36b9f33f
--- /dev/null
+++ b/absl/flags/internal/type_erased.h
@@ -0,0 +1,97 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
+#define ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
+
+#include <string>
+
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/registry.h"
+
+// --------------------------------------------------------------------
+// Registry interfaces operating on type erased handles.
+
+namespace absl {
+namespace flags_internal {
+
+// If a flag named "name" exists, store its current value in *OUTPUT
+// and return true.  Else return false without changing *OUTPUT.
+// Thread-safe.
+bool GetCommandLineOption(absl::string_view name, std::string* value);
+
+// If a flag named "name" exists, store its information in *OUTPUT
+// and return true.  Else return false without changing *OUTPUT.
+// Thread-safe.
+bool GetCommandLineFlagInfo(absl::string_view name,
+                            CommandLineFlagInfo* OUTPUT);
+
+// Returns the CommandLineFlagInfo of the flagname.  exit() with an
+// error code if name not found.
+// Thread-safe.
+CommandLineFlagInfo GetCommandLineFlagInfoOrDie(absl::string_view name);
+
+// Set the value of the flag named "name" to value.  If successful,
+// returns true.  If not successful (e.g., the flag was not found or
+// the value is not a valid value), returns false.
+// Thread-safe.
+bool SetCommandLineOption(absl::string_view name, absl::string_view value);
+
+bool SetCommandLineOptionWithMode(absl::string_view name,
+                                  absl::string_view value,
+                                  FlagSettingMode set_mode);
+
+//-----------------------------------------------------------------------------
+
+// Returns true iff all of the following conditions are true:
+// (a) "name" names a registered flag
+// (b) "value" can be parsed succesfully according to the type of the flag
+// (c) parsed value passes any validator associated with the flag
+bool IsValidFlagValue(absl::string_view name, absl::string_view value);
+
+//-----------------------------------------------------------------------------
+
+// Returns true iff a flag named "name" was specified on the command line
+// (either directly, or via one of --flagfile or --fromenv or --tryfromenv).
+//
+// Any non-command-line modification of the flag does not affect the
+// result of this function.  So for example, if a flag was passed on
+// the command line but then reset via SET_FLAGS_DEFAULT, this
+// function will still return true.
+bool SpecifiedOnCommandLine(absl::string_view name);
+
+//-----------------------------------------------------------------------------
+
+// If a flag with specified "name" exists and has type T, store
+// its current value in *dst and return true.  Else return false
+// without touching *dst.  T must obey all of the requirements for
+// types passed to DEFINE_FLAG.
+template <typename T>
+inline bool GetByName(absl::string_view name, T* dst) {
+  CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
+  if (!flag) return false;
+
+  if (auto val = flag->Get<T>()) {
+    *dst = *val;
+    return true;
+  }
+
+  return false;
+}
+
+}  // namespace flags_internal
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
diff --git a/absl/flags/internal/type_erased_test.cc b/absl/flags/internal/type_erased_test.cc
new file mode 100644
index 000000000000..ac749a607548
--- /dev/null
+++ b/absl/flags/internal/type_erased_test.cc
@@ -0,0 +1,147 @@
+//
+//  Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/internal/type_erased.h"
+
+#include <cmath>
+
+#include "gtest/gtest.h"
+#include "absl/flags/flag.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/str_cat.h"
+
+ABSL_FLAG(int, int_flag, 1, "int_flag help");
+ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
+ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+class TypeErasedTest : public testing::Test {
+ protected:
+  void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); }
+  void TearDown() override { flag_saver_.reset(); }
+
+ private:
+  std::unique_ptr<flags::FlagSaver> flag_saver_;
+};
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestGetCommandLineOption) {
+  std::string value;
+  EXPECT_TRUE(flags::GetCommandLineOption("int_flag", &value));
+  EXPECT_EQ(value, "1");
+
+  EXPECT_TRUE(flags::GetCommandLineOption("string_flag", &value));
+  EXPECT_EQ(value, "dflt");
+
+  EXPECT_FALSE(flags::GetCommandLineOption("bool_retired_flag", &value));
+
+  EXPECT_FALSE(flags::GetCommandLineOption("unknown_flag", &value));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestSetCommandLineOption) {
+  EXPECT_TRUE(flags::SetCommandLineOption("int_flag", "101"));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
+
+  EXPECT_TRUE(flags::SetCommandLineOption("string_flag", "asdfgh"));
+  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
+
+  EXPECT_FALSE(flags::SetCommandLineOption("bool_retired_flag", "true"));
+
+  EXPECT_FALSE(flags::SetCommandLineOption("unknown_flag", "true"));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_VALUE) {
+  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
+                                                  flags::SET_FLAGS_VALUE));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
+
+  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
+                                                  flags::SET_FLAGS_VALUE));
+  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
+
+  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
+                                                   flags::SET_FLAGS_VALUE));
+
+  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
+                                                   flags::SET_FLAGS_VALUE));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAG_IF_DEFAULT) {
+  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
+                                                  flags::SET_FLAG_IF_DEFAULT));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
+
+  // This semantic is broken. We return true instead of false. Value is not
+  // updated.
+  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202",
+                                                  flags::SET_FLAG_IF_DEFAULT));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
+
+  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
+                                                  flags::SET_FLAG_IF_DEFAULT));
+  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
+
+  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
+                                                   flags::SET_FLAG_IF_DEFAULT));
+
+  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
+                                                   flags::SET_FLAG_IF_DEFAULT));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_DEFAULT) {
+  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
+                                                  flags::SET_FLAGS_DEFAULT));
+
+  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
+                                                  flags::SET_FLAGS_DEFAULT));
+  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
+
+  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
+                                                   flags::SET_FLAGS_DEFAULT));
+
+  EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
+                                                   flags::SET_FLAGS_DEFAULT));
+
+  // This should be successfull, since flag is still is not set
+  EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202",
+                                                  flags::SET_FLAG_IF_DEFAULT));
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 202);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestIsValidFlagValue) {
+  EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "57"));
+  EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "-101"));
+  EXPECT_FALSE(flags::IsValidFlagValue("int_flag", "1.1"));
+
+  EXPECT_TRUE(flags::IsValidFlagValue("string_flag", "#%^#%^$%DGHDG$W%adsf"));
+
+  EXPECT_TRUE(flags::IsValidFlagValue("bool_retired_flag", "true"));
+}
+
+}  // namespace
diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc
new file mode 100644
index 000000000000..f17cc6c5787d
--- /dev/null
+++ b/absl/flags/internal/usage.cc
@@ -0,0 +1,392 @@
+//
+// 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/usage.h"
+
+#include <map>
+#include <string>
+
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/path_util.h"
+#include "absl/flags/internal/program_name.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+#include "absl/synchronization/mutex.h"
+
+ABSL_FLAG(bool, help, false,
+          "show help on important flags for this binary [tip: all flags can "
+          "have two dashes]");
+ABSL_FLAG(bool, helpfull, false, "show help on all flags");
+ABSL_FLAG(bool, helpshort, false,
+          "show help on only the main module for this program");
+ABSL_FLAG(bool, helppackage, false,
+          "show help on all modules in the main package");
+ABSL_FLAG(bool, version, false, "show version and build info and exit");
+ABSL_FLAG(bool, only_check_args, false, "exit after checking all flags");
+ABSL_FLAG(std::string, helpon, "",
+          "show help on the modules named by this flag value");
+ABSL_FLAG(std::string, helpmatch, "",
+          "show help on modules whose name contains the specified substr");
+
+namespace absl {
+namespace flags_internal {
+namespace {
+
+// This class is used to emit an XML element with `tag` and `text`.
+// It adds opening and closing tags and escapes special characters in the text.
+// For example:
+// std::cout << XMLElement("title", "Milk & Cookies");
+// prints "<title>Milk &amp; Cookies</title>"
+class XMLElement {
+ public:
+  XMLElement(absl::string_view tag, absl::string_view txt)
+      : tag_(tag), txt_(txt) {}
+
+  friend std::ostream& operator<<(std::ostream& out,
+                                  const XMLElement& xml_elem) {
+    out << "<" << xml_elem.tag_ << ">";
+
+    for (auto c : xml_elem.txt_) {
+      switch (c) {
+        case '"':
+          out << "&quot;";
+          break;
+        case '\'':
+          out << "&apos;";
+          break;
+        case '&':
+          out << "&amp;";
+          break;
+        case '<':
+          out << "&lt;";
+          break;
+        case '>':
+          out << "&gt;";
+          break;
+        default:
+          out << c;
+          break;
+      }
+    }
+
+    return out << "</" << xml_elem.tag_ << ">";
+  }
+
+ private:
+  absl::string_view tag_;
+  absl::string_view txt_;
+};
+
+// --------------------------------------------------------------------
+// Helper class to pretty-print info about a flag.
+
+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),
+        max_line_len_(max_line_len),
+        line_len_(0),
+        first_line_(true) {}
+
+  void Write(absl::string_view str, bool wrap_line = false) {
+    // Empty std::string - do nothing.
+    if (str.empty()) return;
+
+    std::vector<absl::string_view> tokens;
+    if (wrap_line) {
+      tokens = absl::StrSplit(str, absl::ByAnyChar(" \f\n\r\t\v"),
+                              absl::SkipEmpty());
+    } else {
+      tokens.push_back(str);
+    }
+
+    for (auto token : tokens) {
+      bool new_line = (line_len_ == 0);
+
+      // Write the token, ending the std::string first if necessary/possible.
+      if (!new_line && (line_len_ + token.size() >= max_line_len_)) {
+        EndLine();
+        new_line = true;
+      }
+
+      if (new_line) {
+        StartLine();
+      } else {
+        out_ << ' ';
+        ++line_len_;
+      }
+
+      out_ << token;
+      line_len_ += token.size();
+    }
+  }
+
+  void StartLine() {
+    if (first_line_) {
+      out_ << "    ";
+      line_len_ = 4;
+      first_line_ = false;
+    } else {
+      out_ << "      ";
+      line_len_ = 6;
+    }
+  }
+  void EndLine() {
+    out_ << '\n';
+    line_len_ = 0;
+  }
+
+ private:
+  std::ostream& out_;
+  const int max_line_len_;
+  int line_len_;
+  bool first_line_;
+};
+
+void FlagHelpHumanReadable(const flags_internal::CommandLineFlag& flag,
+                           std::ostream* out) {
+  FlagHelpPrettyPrinter printer(80, out);  // Max line length is 80.
+
+  // Flag name.
+  printer.Write(absl::StrCat("-", flag.Name()));
+
+  // Flag help.
+  printer.Write(absl::StrCat("(", flag.Help(), ");"), /*wrap_line=*/true);
+
+  // Flag data type (for V1 flags only).
+  if (!flag.IsAbseilFlag() && !flag.IsRetired()) {
+    printer.Write(absl::StrCat("type: ", flag.Typename(), ";"));
+  }
+
+  // The listed default value will be the actual default from the flag
+  // definition in the originating source file, unless the value has
+  // subsequently been modified using SetCommandLineOption() with mode
+  // SET_FLAGS_DEFAULT.
+  std::string dflt_val = flag.DefaultValue();
+  if (flag.IsOfType<std::string>()) {
+    dflt_val = absl::StrCat("\"", dflt_val, "\"");
+  }
+  printer.Write(absl::StrCat("default: ", dflt_val, ";"));
+
+  if (flag.modified) {
+    std::string curr_val = flag.CurrentValue();
+    if (flag.IsOfType<std::string>()) {
+      curr_val = absl::StrCat("\"", curr_val, "\"");
+    }
+    printer.Write(absl::StrCat("currently: ", curr_val, ";"));
+  }
+
+  printer.EndLine();
+}
+
+// Shows help for every filename which matches any of the filters
+// If filters are empty, shows help for every file.
+// If a flag's help message has been stripped (e.g. by adding '#define
+// STRIP_FLAG_HELP 1' then this flag will not be displayed by '--help'
+// and its variants.
+void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
+                   HelpFormat format = HelpFormat::kHumanReadable) {
+  if (format == HelpFormat::kHumanReadable) {
+    out << flags_internal::ShortProgramInvocationName() << ": "
+        << flags_internal::ProgramUsageMessage() << "\n\n";
+  } else {
+    // XML schema is not a part of our public API for now.
+    out << "<?xml version=\"1.0\"?>\n"
+        // The document.
+        << "<AllFlags>\n"
+        // The program name and usage.
+        << XMLElement("program", flags_internal::ShortProgramInvocationName())
+        << '\n'
+        << XMLElement("usage", flags_internal::ProgramUsageMessage()) << '\n';
+  }
+
+  // Map of package name to
+  //   map of file name to
+  //     vector of flags in the file.
+  // 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*>>>
+      matching_flags;
+
+  flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) {
+    absl::MutexLock l(InitFlagIfNecessary(flag));
+
+    std::string flag_filename = flag->Filename();
+
+    // Ignore retired flags.
+    if (flag->IsRetired()) return;
+
+    // If the flag has been stripped, pretend that it doesn't exist.
+    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);
+  });
+
+  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;
+      package_separator = "\n\n";
+    }
+
+    file_separator = "";
+    for (const auto& flags_in_file : package.second) {
+      if (format == HelpFormat::kHumanReadable) {
+        out << file_separator << "  Flags from " << flags_in_file.first
+            << ":\n";
+        file_separator = "\n";
+      }
+
+      for (const auto* flag : flags_in_file.second) {
+        flags_internal::FlagHelp(out, *flag, format);
+      }
+    }
+  }
+
+  if (format == HelpFormat::kHumanReadable) {
+    if (filter_cb && matching_flags.empty()) {
+      out << "  No modules matched: use -helpfull\n";
+    }
+  } else {
+    // The end of the document.
+    out << "</AllFlags>\n";
+  }
+}
+
+ABSL_CONST_INIT absl::Mutex usage_message_guard(absl::kConstInit);
+ABSL_CONST_INIT std::string* program_usage_message
+    GUARDED_BY(usage_message_guard) = nullptr;
+
+}  // namespace
+
+// --------------------------------------------------------------------
+// Sets the "usage" message to be used by help reporting routines.
+
+void SetProgramUsageMessage(absl::string_view new_usage_message) {
+  absl::MutexLock l(&usage_message_guard);
+
+  if (flags_internal::program_usage_message != nullptr) {
+    ABSL_INTERNAL_LOG(FATAL, "SetProgramUsageMessage() called twice.");
+    std::exit(1);
+  }
+
+  program_usage_message = new std::string(new_usage_message);
+}
+
+// --------------------------------------------------------------------
+// Returns the usage message set by SetProgramUsageMessage().
+// Note: We able to return string_view here only because calling
+// SetProgramUsageMessage twice is prohibited.
+absl::string_view ProgramUsageMessage() {
+  absl::MutexLock l(&usage_message_guard);
+
+  return program_usage_message != nullptr
+             ? absl::string_view(*program_usage_message)
+             : "Warning: SetProgramUsageMessage() never called";
+}
+
+// --------------------------------------------------------------------
+// Produces the help message describing specific flag.
+void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag,
+              HelpFormat format) {
+  if (format == HelpFormat::kHumanReadable)
+    flags_internal::FlagHelpHumanReadable(flag, &out);
+}
+
+// --------------------------------------------------------------------
+// Produces the help messages for all flags matching the filter.
+// If filter is empty produces help messages for all flags.
+void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format) {
+  flags_internal::FlagKindFilter filter_cb = [&](absl::string_view filename) {
+    return filter.empty() || filename.find(filter) != absl::string_view::npos;
+  };
+  flags_internal::FlagsHelpImpl(out, filter_cb, format);
+}
+
+// --------------------------------------------------------------------
+// Checks all the 'usage' command line flags to see if any have been set.
+// If so, handles them appropriately.
+int HandleUsageFlags(std::ostream& out) {
+  if (absl::GetFlag(FLAGS_helpshort)) {
+    flags_internal::FlagsHelpImpl(
+        out, flags_internal::GetUsageConfig().contains_helpshort_flags,
+        HelpFormat::kHumanReadable);
+    return 1;
+  }
+
+  if (absl::GetFlag(FLAGS_helpfull)) {
+    // show all options
+    flags_internal::FlagsHelp(out);
+    return 1;
+  }
+
+  if (!absl::GetFlag(FLAGS_helpon).empty()) {
+    flags_internal::FlagsHelp(
+        out, absl::StrCat("/", absl::GetFlag(FLAGS_helpon), "."));
+    return 1;
+  }
+
+  if (!absl::GetFlag(FLAGS_helpmatch).empty()) {
+    flags_internal::FlagsHelp(out, absl::GetFlag(FLAGS_helpmatch));
+    return 1;
+  }
+
+  if (absl::GetFlag(FLAGS_help)) {
+    flags_internal::FlagsHelpImpl(
+        out, flags_internal::GetUsageConfig().contains_help_flags);
+
+    out << "\nTry --helpfull to get a list of all flags.\n";
+
+    return 1;
+  }
+
+  if (absl::GetFlag(FLAGS_helppackage)) {
+    flags_internal::FlagsHelpImpl(
+        out, flags_internal::GetUsageConfig().contains_helppackage_flags);
+
+    out << "\nTry --helpfull to get a list of all flags.\n";
+
+    return 1;
+  }
+
+  if (absl::GetFlag(FLAGS_version)) {
+    if (flags_internal::GetUsageConfig().version_string)
+      out << flags_internal::GetUsageConfig().version_string();
+    // Unlike help, we may be asking for version in a script, so return 0
+    return 0;
+  }
+
+  if (absl::GetFlag(FLAGS_only_check_args)) {
+    return 0;
+  }
+
+  return -1;
+}
+
+}  // namespace flags_internal
+}  // namespace absl
diff --git a/absl/flags/internal/usage.h b/absl/flags/internal/usage.h
new file mode 100644
index 000000000000..2d0ea7a72a4d
--- /dev/null
+++ b/absl/flags/internal/usage.h
@@ -0,0 +1,91 @@
+//
+//  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_USAGE_H_
+#define ABSL_FLAGS_INTERNAL_USAGE_H_
+
+#include <iosfwd>
+#include <string>
+
+#include "absl/flags/declare.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
+// --------------------------------------------------------------------
+// Usage reporting interfaces
+
+namespace absl {
+namespace flags_internal {
+
+// Sets the "usage" message to be used by help reporting routines.
+// For example:
+//  absl::SetProgramUsageMessage(
+//      absl::StrCat("This program does nothing.  Sample usage:\n", argv[0],
+//                   " <uselessarg1> <uselessarg2>"));
+// Do not include commandline flags in the usage: we do that for you!
+// Note: Calling SetProgramUsageMessage twice will trigger a call to std::exit.
+void SetProgramUsageMessage(absl::string_view new_usage_message);
+
+// Returns the usage message set by SetProgramUsageMessage().
+absl::string_view ProgramUsageMessage();
+
+// --------------------------------------------------------------------
+
+// The format to report the help messages in.
+enum class HelpFormat {
+  kHumanReadable,
+};
+
+// Outputs the help message describing specific flag.
+void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag,
+              HelpFormat format = HelpFormat::kHumanReadable);
+
+// Produces the help messages for all flags matching the filter. A flag matches
+// the filter if it is defined in a file with a filename which includes
+// filter string as a substring. You can use '/' and '.' to restrict the
+// matching to a specific file names. For example:
+//   FlagsHelp(out, "/path/to/file.");
+// restricts help to only flags which resides in files named like:
+//  .../path/to/file.<ext>
+// for any extension 'ext'. If the filter is empty this function produces help
+// messages for all flags.
+void FlagsHelp(std::ostream& out, absl::string_view filter = {},
+               HelpFormat format = HelpFormat::kHumanReadable);
+
+// --------------------------------------------------------------------
+
+// If any of the 'usage' related command line flags (listed on the bottom of
+// this file) has been set this routine produces corresponding help message in
+// the specified output stream and returns:
+//  0 - if "version" or "only_check_flags" flags were set and handled.
+//  1 - if some other 'usage' related flag was set and handled.
+// -1 - if no usage flags were set on a commmand line.
+// Non negative return values are expected to be used as an exit code for a
+// binary.
+int HandleUsageFlags(std::ostream& out);
+
+}  // namespace flags_internal
+}  // namespace absl
+
+ABSL_DECLARE_FLAG(bool, help);
+ABSL_DECLARE_FLAG(bool, helpfull);
+ABSL_DECLARE_FLAG(bool, helpshort);
+ABSL_DECLARE_FLAG(bool, helppackage);
+ABSL_DECLARE_FLAG(bool, version);
+ABSL_DECLARE_FLAG(bool, only_check_args);
+ABSL_DECLARE_FLAG(std::string, helpon);
+ABSL_DECLARE_FLAG(std::string, helpmatch);
+
+#endif  // ABSL_FLAGS_INTERNAL_USAGE_H_
diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc
new file mode 100644
index 000000000000..cb40aa42378d
--- /dev/null
+++ b/absl/flags/internal/usage_test.cc
@@ -0,0 +1,367 @@
+//
+//  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 <sstream>
+
+#include "gtest/gtest.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/parse.h"
+#include "absl/flags/internal/path_util.h"
+#include "absl/flags/internal/program_name.h"
+#include "absl/flags/internal/usage.h"
+#include "absl/flags/usage_config.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/match.h"
+
+ABSL_FLAG(int, usage_reporting_test_flag_01, 101,
+          "usage_reporting_test_flag_01 help message");
+ABSL_FLAG(bool, usage_reporting_test_flag_02, false,
+          "usage_reporting_test_flag_02 help message");
+ABSL_FLAG(double, usage_reporting_test_flag_03, 1.03,
+          "usage_reporting_test_flag_03 help message");
+ABSL_FLAG(int64_t, usage_reporting_test_flag_04, 1000000000000004L,
+          "usage_reporting_test_flag_04 help message");
+
+struct UDT {
+  UDT() = default;
+  UDT(const UDT&) = default;
+};
+bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
+std::string AbslUnparseFlag(const UDT&) { return "UDT{}"; }
+
+ABSL_FLAG(UDT, usage_reporting_test_flag_05, {},
+          "usage_reporting_test_flag_05 help message");
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+static std::string NormalizeFileName(absl::string_view fname) {
+#ifdef _WIN32
+  std::string normalized(fname);
+  std::replace(normalized.begin(), normalized.end(), '\\', '/');
+  fname = normalized;
+#endif
+
+  auto absl_pos = fname.find("/absl/");
+  if (absl_pos != absl::string_view::npos) {
+    fname = fname.substr(absl_pos + 1);
+  }
+  return std::string(fname);
+}
+
+class UsageReportingTest : public testing::Test {
+ protected:
+  UsageReportingTest() {
+    // Install default config for the use on this unit test.
+    // Binary may install a custom config before tests are run.
+    absl::FlagsUsageConfig default_config;
+    default_config.normalize_filename = &NormalizeFileName;
+    absl::SetFlagsUsageConfig(default_config);
+  }
+
+ private:
+  flags::FlagSaver flag_saver_;
+};
+
+// --------------------------------------------------------------------
+
+using UsageReportingDeathTest = UsageReportingTest;
+
+TEST_F(UsageReportingDeathTest, TestSetProgramUsageMessage) {
+  EXPECT_EQ(flags::ProgramUsageMessage(), "Custom usage message");
+
+#ifndef _WIN32
+  // TODO(rogeeff): figure out why this does not work on Windows.
+  EXPECT_DEATH(flags::SetProgramUsageMessage("custom usage message"),
+               ".*SetProgramUsageMessage\\(\\) called twice.*");
+#endif
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {
+  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_01");
+  std::stringstream test_buf;
+
+  flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
+  EXPECT_EQ(
+      test_buf.str(),
+      R"(    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+      default: 101;
+)");
+}
+
+TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
+  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_02");
+  std::stringstream test_buf;
+
+  flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
+  EXPECT_EQ(
+      test_buf.str(),
+      R"(    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+      default: false;
+)");
+}
+
+TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {
+  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_03");
+  std::stringstream test_buf;
+
+  flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
+  EXPECT_EQ(
+      test_buf.str(),
+      R"(    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+      default: 1.03;
+)");
+}
+
+TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
+  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_04");
+  std::stringstream test_buf;
+
+  flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
+  EXPECT_EQ(
+      test_buf.str(),
+      R"(    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+      default: 1000000000000004;
+)");
+}
+
+TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) {
+  const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_05");
+  std::stringstream test_buf;
+
+  flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
+  EXPECT_EQ(
+      test_buf.str(),
+      R"(    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+      default: UDT{};
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestFlagsHelpHRF) {
+  std::string usage_test_flags_out =
+      R"(usage_test: Custom usage message
+
+  Flags from absl/flags/internal/usage_test.cc:
+    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+      default: 101;
+    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+      default: false;
+    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+      default: 1.03;
+    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+      default: 1000000000000004;
+    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+      default: UDT{};
+)";
+
+  std::stringstream test_buf_01;
+  flags::FlagsHelp(test_buf_01, "usage_test.cc",
+                   flags::HelpFormat::kHumanReadable);
+  EXPECT_EQ(test_buf_01.str(), usage_test_flags_out);
+
+  std::stringstream test_buf_02;
+  flags::FlagsHelp(test_buf_02, "flags/internal/usage_test.cc",
+                   flags::HelpFormat::kHumanReadable);
+  EXPECT_EQ(test_buf_02.str(), usage_test_flags_out);
+
+  std::stringstream test_buf_03;
+  flags::FlagsHelp(test_buf_03, "usage_test",
+                   flags::HelpFormat::kHumanReadable);
+  EXPECT_EQ(test_buf_03.str(), usage_test_flags_out);
+
+  std::stringstream test_buf_04;
+  flags::FlagsHelp(test_buf_04, "flags/invalid_file_name.cc",
+                   flags::HelpFormat::kHumanReadable);
+  EXPECT_EQ(test_buf_04.str(),
+            R"(usage_test: Custom usage message
+
+  No modules matched: use -helpfull
+)");
+
+  std::stringstream test_buf_05;
+  flags::FlagsHelp(test_buf_05, "", flags::HelpFormat::kHumanReadable);
+  std::string test_out = test_buf_05.str();
+  absl::string_view test_out_str(test_out);
+  EXPECT_TRUE(
+      absl::StartsWith(test_out_str, "usage_test: Custom usage message"));
+  EXPECT_TRUE(absl::StrContains(
+      test_out_str, "Flags from absl/flags/internal/usage_test.cc:"));
+  EXPECT_TRUE(absl::StrContains(test_out_str,
+                                "Flags from absl/flags/internal/usage.cc:"));
+  EXPECT_TRUE(
+      absl::StrContains(test_out_str, "-usage_reporting_test_flag_01 "));
+  EXPECT_TRUE(absl::StrContains(test_out_str, "-help (show help"))
+      << test_out_str;
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestNoUsageFlags) {
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf), -1);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_helpshort) {
+  absl::SetFlag(&FLAGS_helpshort, true);
+
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf), 1);
+  EXPECT_EQ(test_buf.str(),
+            R"(usage_test: Custom usage message
+
+  Flags from absl/flags/internal/usage_test.cc:
+    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+      default: 101;
+    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+      default: false;
+    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+      default: 1.03;
+    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+      default: 1000000000000004;
+    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+      default: UDT{};
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_help) {
+  absl::SetFlag(&FLAGS_help, true);
+
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf), 1);
+  EXPECT_EQ(test_buf.str(),
+            R"(usage_test: Custom usage message
+
+  Flags from absl/flags/internal/usage_test.cc:
+    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+      default: 101;
+    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+      default: false;
+    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+      default: 1.03;
+    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+      default: 1000000000000004;
+    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+      default: UDT{};
+
+Try --helpfull to get a list of all flags.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
+  absl::SetFlag(&FLAGS_helppackage, true);
+
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf), 1);
+  EXPECT_EQ(test_buf.str(),
+            R"(usage_test: Custom usage message
+
+  Flags from absl/flags/internal/usage_test.cc:
+    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+      default: 101;
+    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+      default: false;
+    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+      default: 1.03;
+    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+      default: 1000000000000004;
+    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+      default: UDT{};
+
+Try --helpfull to get a list of all flags.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_version) {
+  absl::SetFlag(&FLAGS_version, true);
+
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf), 0);
+#ifndef NDEBUG
+  EXPECT_EQ(test_buf.str(),
+            "usage_test\nDebug build (NDEBUG not #defined)\n");
+#else
+  EXPECT_EQ(test_buf.str(), "usage_test\n");
+#endif
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
+  absl::SetFlag(&FLAGS_only_check_args, true);
+
+  std::stringstream test_buf;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf), 0);
+  EXPECT_EQ(test_buf.str(), "");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_helpon) {
+  absl::SetFlag(&FLAGS_helpon, "bla-bla");
+
+  std::stringstream test_buf_01;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf_01), 1);
+  EXPECT_EQ(test_buf_01.str(),
+            R"(usage_test: Custom usage message
+
+  No modules matched: use -helpfull
+)");
+
+  absl::SetFlag(&FLAGS_helpon, "usage_test");
+
+  std::stringstream test_buf_02;
+  EXPECT_EQ(flags::HandleUsageFlags(test_buf_02), 1);
+  EXPECT_EQ(test_buf_02.str(),
+            R"(usage_test: Custom usage message
+
+  Flags from absl/flags/internal/usage_test.cc:
+    -usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+      default: 101;
+    -usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+      default: false;
+    -usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+      default: 1.03;
+    -usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+      default: 1000000000000004;
+    -usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+      default: UDT{};
+)");
+}
+
+// --------------------------------------------------------------------
+
+}  // namespace
+
+int main(int argc, char* argv[]) {
+  absl::GetFlag(FLAGS_undefok);  // Force linking of parse.cc
+  flags::SetProgramInvocationName("usage_test");
+  flags::SetProgramUsageMessage("Custom usage message");
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
diff --git a/absl/flags/marshalling.cc b/absl/flags/marshalling.cc
new file mode 100644
index 000000000000..f025ae7e86c4
--- /dev/null
+++ b/absl/flags/marshalling.cc
@@ -0,0 +1,189 @@
+//
+//  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/marshalling.h"
+
+#include <limits>
+
+#include "absl/base/macros.h"
+#include "absl/strings/match.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/str_split.h"
+
+namespace absl {
+namespace flags_internal {
+
+// --------------------------------------------------------------------
+// AbslParseFlag specializations for boolean type.
+
+bool AbslParseFlag(absl::string_view text, bool* dst, std::string*) {
+  const char* kTrue[] = {"1", "t", "true", "y", "yes"};
+  const char* kFalse[] = {"0", "f", "false", "n", "no"};
+  static_assert(sizeof(kTrue) == sizeof(kFalse), "true_false_equal");
+
+  text = absl::StripAsciiWhitespace(text);
+
+  for (size_t i = 0; i < ABSL_ARRAYSIZE(kTrue); ++i) {
+    if (absl::EqualsIgnoreCase(text, kTrue[i])) {
+      *dst = true;
+      return true;
+    } else if (absl::EqualsIgnoreCase(text, kFalse[i])) {
+      *dst = false;
+      return true;
+    }
+  }
+  return false;  // didn't match a legal input
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for integral types.
+
+// Return the base to use for parsing text as an integer.  Leading 0x
+// puts us in base 16.  But leading 0 does not put us in base 8. It
+// caused too many bugs when we had that behavior.
+static int NumericBase(absl::string_view text) {
+  const bool hex = (text.size() >= 2 && text[0] == '0' &&
+                    (text[1] == 'x' || text[1] == 'X'));
+  return hex ? 16 : 10;
+}
+
+template <typename IntType>
+inline bool ParseFlagImpl(absl::string_view text, IntType* dst) {
+  text = absl::StripAsciiWhitespace(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 (static_cast<short>(val) != val)  // worked, but number out of range
+    return false;
+  *dst = static_cast<short>(val);
+  return true;
+}
+
+bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
+  unsigned int val;
+  if (!ParseFlagImpl(text, &val)) return false;
+  if (static_cast<unsigned short>(val) !=
+      val)  // worked, but number out of range
+    return false;
+  *dst = static_cast<unsigned short>(val);
+  return true;
+}
+
+bool AbslParseFlag(absl::string_view text, int* dst, std::string*) {
+  return ParseFlagImpl(text, dst);
+}
+
+bool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) {
+  return ParseFlagImpl(text, dst);
+}
+
+bool AbslParseFlag(absl::string_view text, long* dst, std::string*) {
+  return ParseFlagImpl(text, dst);
+}
+
+bool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) {
+  return ParseFlagImpl(text, dst);
+}
+
+bool AbslParseFlag(absl::string_view text, long long* dst, std::string*) {
+  return ParseFlagImpl(text, dst);
+}
+
+bool AbslParseFlag(absl::string_view text, unsigned long long* dst,
+                   std::string*) {
+  return ParseFlagImpl(text, dst);
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for floating point types.
+
+bool AbslParseFlag(absl::string_view text, float* dst, std::string*) {
+  return absl::SimpleAtof(text, dst);
+}
+
+bool AbslParseFlag(absl::string_view text, double* dst, std::string*) {
+  return absl::SimpleAtod(text, dst);
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for strings.
+
+bool AbslParseFlag(absl::string_view text, std::string* dst, std::string*) {
+  dst->assign(text.data(), text.size());
+  return true;
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for vector of strings.
+
+bool AbslParseFlag(absl::string_view text, std::vector<std::string>* dst,
+                   std::string*) {
+  // An empty flag value corresponds to an empty vector, not a vector
+  // with a single, empty std::string.
+  if (text.empty()) {
+    dst->clear();
+    return true;
+  }
+  *dst = absl::StrSplit(text, ',', absl::AllowEmpty());
+  return true;
+}
+
+// --------------------------------------------------------------------
+// AbslUnparseFlag specializations for various builtin flag types.
+
+std::string Unparse(bool v) { return v ? "true" : "false"; }
+std::string Unparse(short v) { return absl::StrCat(v); }
+std::string Unparse(unsigned short v) { return absl::StrCat(v); }
+std::string Unparse(int v) { return absl::StrCat(v); }
+std::string Unparse(unsigned int v) { return absl::StrCat(v); }
+std::string Unparse(long v) { return absl::StrCat(v); }
+std::string Unparse(unsigned long v) { return absl::StrCat(v); }
+std::string Unparse(long long v) { return absl::StrCat(v); }
+std::string Unparse(unsigned long long v) { return absl::StrCat(v); }
+template <typename T>
+std::string UnparseFloatingPointVal(T v) {
+  // digits10 is guaranteed to roundtrip correctly in std::string -> value -> std::string
+  // conversions, but may not be enough to represent all the values correctly.
+  std::string digit10_str =
+      absl::StrFormat("%.*g", std::numeric_limits<T>::digits10, v);
+  if (std::isnan(v) || std::isinf(v)) return digit10_str;
+
+  T roundtrip_val = 0;
+  std::string err;
+  if (absl::ParseFlag(digit10_str, &roundtrip_val, &err) &&
+      roundtrip_val == v) {
+    return digit10_str;
+  }
+
+  // max_digits10 is the number of base-10 digits that are necessary to uniquely
+  // represent all distinct values.
+  return absl::StrFormat("%.*g", std::numeric_limits<T>::max_digits10, v);
+}
+std::string Unparse(float v) { return UnparseFloatingPointVal(v); }
+std::string Unparse(double v) { return UnparseFloatingPointVal(v); }
+std::string AbslUnparseFlag(absl::string_view v) { return std::string(v); }
+std::string AbslUnparseFlag(const std::vector<std::string>& v) {
+  return absl::StrJoin(v, ",");
+}
+
+}  // namespace flags_internal
+}  // namespace absl
diff --git a/absl/flags/marshalling.h b/absl/flags/marshalling.h
new file mode 100644
index 000000000000..669cf452c4b0
--- /dev/null
+++ b/absl/flags/marshalling.h
@@ -0,0 +1,260 @@
+//
+//  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.
+//
+// -----------------------------------------------------------------------------
+// File: marshalling.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the API for extending Abseil flag support to
+// custom types, and defines the set of overloads for fundamental types.
+//
+// Out of the box, the Abseil flags library supports the following types:
+//
+// * `bool`
+// * `int16_t`
+// * `uint16_t`
+// * `int32_t`
+// * `uint32_t`
+// * `int64_t`
+// * `uint64_t`
+// * `float`
+// * `double`
+// * `std::string`
+// * `std::vector<std::string>`
+//
+// Note that support for integral types is implemented using overloads for
+// variable-width fundamental types (`short`, `int`, `long`, etc.). However,
+// you should prefer the fixed-width integral types (`int32_t`, `uint64_t`,
+// etc.) we've noted above within flag definitions.
+
+//
+// In addition, several Abseil libraries provide their own custom support for
+// Abseil flags.
+//
+// The Abseil time library provides the following support for civil time values:
+//
+// * `absl::CivilSecond`
+// * `absl::CivilMinute`
+// * `absl::CivilHour`
+// * `absl::CivilDay`
+// * `absl::CivilMonth`
+// * `absl::CivilYear`
+//
+// and also provides support for the following absolute time values:
+//
+// * `absl::Duration`
+// * `absl::Time`
+//
+// Additional support for Abseil types will be noted here as it is added.
+//
+// You can also provide your own custom flags by adding overloads for
+// `AbslParseFlag()` and `AbslUnparseFlag()` to your type definitions. (See
+// below.)
+//
+// -----------------------------------------------------------------------------
+// Adding Type Support for Abseil Flags
+// -----------------------------------------------------------------------------
+//
+// To add support for your user-defined type, add overloads of `AbslParseFlag()`
+// and `AbslUnparseFlag()` as free (non-member) functions to your type. If `T`
+// is a class type, these functions can be friend function definitions. These
+// overloads must be added to the same namespace where the type is defined, so
+// that they can be discovered by Argument-Dependent Lookup (ADL).
+//
+// Example:
+//
+//   namespace foo {
+//
+//   enum OutputMode { kPlainText, kHtml };
+//
+//   // AbslParseFlag converts from a string to OutputMode.
+//   // Must be in same namespace as OutputMode.
+//
+//   // Parses an OutputMode from the command line flag value `text. Returns
+//   // `true` and sets `*mode` on success; returns `false` and sets `*error`
+//   // on failure.
+//   bool AbslParseFlag(absl::string_view text,
+//                      OutputMode* mode,
+//                      std::string* error) {
+//     if (text == "plaintext") {
+//       *mode = kPlainText;
+//       return true;
+//     }
+//     if (text == "html") {
+//       *mode = kHtml;
+//      return true;
+//     }
+//     *error = "unknown value for enumeration";
+//     return false;
+//  }
+//
+//  // AbslUnparseFlag converts from an OutputMode to a string.
+//  // Must be in same namespace as OutputMode.
+//
+//  // Returns a textual flag value corresponding to the OutputMode `mode`.
+//  std::string AbslUnparseFlag(OutputMode mode) {
+//    switch (mode) {
+//     case kPlainText: return "plaintext";
+//     case kHtml: return "html";
+//     default: return SimpleItoa(mode);
+//    }
+//  }
+//
+// Notice that neither `AbslParseFlag()` nor `AbslUnparseFlag()` are class
+// members, but free functions. `AbslParseFlag/AbslUnparseFlag()` overloads
+// for a type should only be declared in the same file and namespace as said
+// type. The proper `AbslParseFlag/AbslUnparseFlag()` implementations for a
+// given type will be discovered via Argument-Dependent Lookup (ADL).
+//
+// `AbslParseFlag()` may need, in turn, to parse simpler constituent types
+// using `absl::ParseFlag()`. For example, a custom struct `MyFlagType`
+// consisting of a `std::pair<int, std::string>` would add an `AbslParseFlag()`
+// overload for its `MyFlagType` like so:
+//
+// Example:
+//
+//   namespace my_flag_type {
+//
+//   struct MyFlagType {
+//     std::pair<int, std::string> my_flag_data;
+//   };
+//
+//   bool AbslParseFlag(absl::string_view text, MyFlagType* flag,
+//                      std::string* err);
+//
+//   std::string AbslUnparseFlag(const MyFlagType&);
+//
+//   // Within the implementation, `AbslParseFlag()` will, in turn invoke
+//   // `absl::ParseFlag()` on its constituent `int` and `std::string` types
+//   // (which have built-in Abseil flag support.
+//
+//   bool AbslParseFlag(absl::string_view text, MyFlagType* flag,
+//                      std::string* err) {
+//     std::pair<absl::string_view, absl::string_view> tokens =
+//         absl::StrSplit(text, ',');
+//     if (!absl::ParseFlag(tokens.first, &flag->my_flag_data.first, err))
+//         return false;
+//     if (!absl::ParseFlag(tokens.second, &flag->my_flag_data.second, err))
+//         return false;
+//     return true;
+//   }
+//
+//   // Similarly, for unparsing, we can simply invoke `absl::UnparseFlag()` on
+//   // the constituent types.
+//   std::string AbslUnparseFlag(const MyFlagType& flag) {
+//     return absl::StrCat(absl::UnparseFlag(flag.my_flag_data.first),
+//                         ",",
+//                         absl::UnparseFlag(flag.my_flag_data.second));
+//   }
+#ifndef ABSL_FLAGS_MARSHALLING_H_
+#define ABSL_FLAGS_MARSHALLING_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+
+namespace absl {
+namespace flags_internal {
+
+// Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types.
+bool AbslParseFlag(absl::string_view, bool*, std::string*);
+bool AbslParseFlag(absl::string_view, short*, std::string*);           // NOLINT
+bool AbslParseFlag(absl::string_view, unsigned short*, std::string*);  // NOLINT
+bool AbslParseFlag(absl::string_view, int*, std::string*);             // NOLINT
+bool AbslParseFlag(absl::string_view, unsigned int*, std::string*);    // NOLINT
+bool AbslParseFlag(absl::string_view, long*, std::string*);            // NOLINT
+bool AbslParseFlag(absl::string_view, unsigned long*, std::string*);   // NOLINT
+bool AbslParseFlag(absl::string_view, long long*, std::string*);       // NOLINT
+bool AbslParseFlag(absl::string_view, unsigned long long*,
+                   std::string*);  // NOLINT
+bool AbslParseFlag(absl::string_view, float*, std::string*);
+bool AbslParseFlag(absl::string_view, double*, std::string*);
+bool AbslParseFlag(absl::string_view, std::string*, std::string*);
+bool AbslParseFlag(absl::string_view, std::vector<std::string>*, std::string*);
+
+struct GlobalStringADLGuard {
+  explicit GlobalStringADLGuard(std::string* p) : ptr(p) {}
+  operator std::string*() { return ptr; }  // NOLINT
+  std::string* ptr;
+};
+
+template <typename T>
+bool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) {
+  // Comment on next line provides a good compiler error message if T
+  // does not have AbslParseFlag(absl::string_view, T*, std::string*).
+  return AbslParseFlag(  // Is T missing AbslParseFlag?
+      input, dst, GlobalStringADLGuard(err));
+}
+
+// Strings and std:: containers do not have the same overload resolution
+// considerations as fundamental types. Naming these 'AbslUnparseFlag' means we
+// can avoid the need for additional specializations of Unparse (below).
+std::string AbslUnparseFlag(absl::string_view v);
+std::string AbslUnparseFlag(const std::vector<std::string>&);
+
+template <typename T>
+std::string Unparse(const T& v) {
+  // Comment on next line provides a good compiler error message if T does not
+  // have UnparseFlag.
+  return AbslUnparseFlag(v);  // Is T missing AbslUnparseFlag?
+}
+
+// Overloads for builtin types.
+std::string Unparse(bool v);
+std::string Unparse(short v);               // NOLINT
+std::string Unparse(unsigned short v);      // NOLINT
+std::string Unparse(int v);                 // NOLINT
+std::string Unparse(unsigned int v);        // NOLINT
+std::string Unparse(long v);                // NOLINT
+std::string Unparse(unsigned long v);       // NOLINT
+std::string Unparse(long long v);           // NOLINT
+std::string Unparse(unsigned long long v);  // NOLINT
+std::string Unparse(float v);
+std::string Unparse(double v);
+
+}  // namespace flags_internal
+
+// ParseFlag()
+//
+// Parses a string value into a flag value of type `T`. Do not add overloads of
+// this function for your type directly; instead, add an `AbslParseFlag()`
+// free function as documented above.
+//
+// Some implementations of `AbslParseFlag()` for types which consist of other,
+// constituent types which already have Abseil flag support, may need to call
+// `absl::ParseFlag()` on those consituent string values. (See above.)
+template <typename T>
+inline bool ParseFlag(absl::string_view input, T* dst, std::string* error) {
+  return flags_internal::InvokeParseFlag(input, dst, error);
+}
+
+// UnparseFlag()
+//
+// Unparses a flag value of type `T` into a string value. Do not add overloads
+// of this function for your type directly; instead, add an `AbslUnparseFlag()`
+// free function as documented above.
+//
+// Some implementations of `AbslUnparseFlag()` for types which consist of other,
+// constituent types which already have Abseil flag support, may want to call
+// `absl::UnparseFlag()` on those constituent types. (See above.)
+template <typename T>
+inline std::string UnparseFlag(const T& v) {
+  return flags_internal::Unparse(v);
+}
+
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_MARSHALLING_H_
diff --git a/absl/flags/marshalling_test.cc b/absl/flags/marshalling_test.cc
new file mode 100644
index 000000000000..37cd1940e34d
--- /dev/null
+++ b/absl/flags/marshalling_test.cc
@@ -0,0 +1,899 @@
+//
+//  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/marshalling.h"
+
+#include <cmath>
+
+#include "gtest/gtest.h"
+
+namespace {
+
+TEST(MarshallingTest, TestBoolParsing) {
+  std::string err;
+  bool value;
+
+  // True values.
+  EXPECT_TRUE(absl::ParseFlag("True", &value, &err));
+  EXPECT_TRUE(value);
+  EXPECT_TRUE(absl::ParseFlag("true", &value, &err));
+  EXPECT_TRUE(value);
+  EXPECT_TRUE(absl::ParseFlag("TRUE", &value, &err));
+  EXPECT_TRUE(value);
+
+  EXPECT_TRUE(absl::ParseFlag("Yes", &value, &err));
+  EXPECT_TRUE(value);
+  EXPECT_TRUE(absl::ParseFlag("yes", &value, &err));
+  EXPECT_TRUE(value);
+  EXPECT_TRUE(absl::ParseFlag("YES", &value, &err));
+  EXPECT_TRUE(value);
+
+  EXPECT_TRUE(absl::ParseFlag("t", &value, &err));
+  EXPECT_TRUE(value);
+  EXPECT_TRUE(absl::ParseFlag("T", &value, &err));
+  EXPECT_TRUE(value);
+
+  EXPECT_TRUE(absl::ParseFlag("y", &value, &err));
+  EXPECT_TRUE(value);
+  EXPECT_TRUE(absl::ParseFlag("Y", &value, &err));
+  EXPECT_TRUE(value);
+
+  EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+  EXPECT_TRUE(value);
+
+  // False values.
+  EXPECT_TRUE(absl::ParseFlag("False", &value, &err));
+  EXPECT_FALSE(value);
+  EXPECT_TRUE(absl::ParseFlag("false", &value, &err));
+  EXPECT_FALSE(value);
+  EXPECT_TRUE(absl::ParseFlag("FALSE", &value, &err));
+  EXPECT_FALSE(value);
+
+  EXPECT_TRUE(absl::ParseFlag("No", &value, &err));
+  EXPECT_FALSE(value);
+  EXPECT_TRUE(absl::ParseFlag("no", &value, &err));
+  EXPECT_FALSE(value);
+  EXPECT_TRUE(absl::ParseFlag("NO", &value, &err));
+  EXPECT_FALSE(value);
+
+  EXPECT_TRUE(absl::ParseFlag("f", &value, &err));
+  EXPECT_FALSE(value);
+  EXPECT_TRUE(absl::ParseFlag("F", &value, &err));
+  EXPECT_FALSE(value);
+
+  EXPECT_TRUE(absl::ParseFlag("n", &value, &err));
+  EXPECT_FALSE(value);
+  EXPECT_TRUE(absl::ParseFlag("N", &value, &err));
+  EXPECT_FALSE(value);
+
+  EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+  EXPECT_FALSE(value);
+
+  // Whitespace handling.
+  EXPECT_TRUE(absl::ParseFlag("  true", &value, &err));
+  EXPECT_TRUE(value);
+  EXPECT_TRUE(absl::ParseFlag("true  ", &value, &err));
+  EXPECT_TRUE(value);
+  EXPECT_TRUE(absl::ParseFlag("  true   ", &value, &err));
+  EXPECT_TRUE(value);
+
+  // Invalid input.
+  EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("  ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("2", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("11", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("tt", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt16Parsing) {
+  std::string err;
+  int16_t value;
+
+  // Decimal values.
+  EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+  EXPECT_EQ(value, 0);
+  EXPECT_TRUE(absl::ParseFlag("-1", &value, &err));
+  EXPECT_EQ(value, -1);
+  EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+  EXPECT_EQ(value, 123);
+  EXPECT_TRUE(absl::ParseFlag("-18765", &value, &err));
+  EXPECT_EQ(value, -18765);
+  EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+  EXPECT_EQ(value, 3);
+
+  // Leading zero values.
+  EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("-001", &value, &err));
+  EXPECT_EQ(value, -1);
+  EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+  EXPECT_EQ(value, 100);
+
+  // Hex values.
+  EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+  EXPECT_EQ(value, 16);
+  EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err));
+  EXPECT_EQ(value, 564);
+  // TODO(rogeeff): fix below validations
+  EXPECT_FALSE(absl::ParseFlag("-0x7FFD", &value, &err));
+  EXPECT_NE(value, -3);
+  EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+  EXPECT_NE(value, 49);
+
+  // Whitespace handling
+  EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err));
+  EXPECT_EQ(value, 10);
+  EXPECT_TRUE(absl::ParseFlag("  11", &value, &err));
+  EXPECT_EQ(value, 11);
+  EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err));
+  EXPECT_EQ(value, 12);
+  EXPECT_TRUE(absl::ParseFlag(" 0x22    ", &value, &err));
+  EXPECT_EQ(value, 34);
+
+  // Invalid values.
+  EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("  ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("40000", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUint16Parsing) {
+  std::string err;
+  uint16_t value;
+
+  // Decimal values.
+  EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+  EXPECT_EQ(value, 0);
+  EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+  EXPECT_EQ(value, 123);
+  EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+  EXPECT_EQ(value, 3);
+
+  // Leading zero values.
+  EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("001", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+  EXPECT_EQ(value, 100);
+
+  // Hex values.
+  EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+  EXPECT_EQ(value, 16);
+  EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err));
+  EXPECT_EQ(value, 564);
+  // TODO(rogeeff): fix below validations
+  EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+  EXPECT_NE(value, 49);
+
+  // Whitespace handling
+  EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err));
+  EXPECT_EQ(value, 10);
+  EXPECT_TRUE(absl::ParseFlag("  11", &value, &err));
+  EXPECT_EQ(value, 11);
+  EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err));
+  EXPECT_EQ(value, 12);
+  EXPECT_TRUE(absl::ParseFlag(" 0x22    ", &value, &err));
+  EXPECT_EQ(value, 34);
+
+  // Invalid values.
+  EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("  ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("70000", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("-1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt32Parsing) {
+  std::string err;
+  int32_t value;
+
+  // Decimal values.
+  EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+  EXPECT_EQ(value, 0);
+  EXPECT_TRUE(absl::ParseFlag("-1", &value, &err));
+  EXPECT_EQ(value, -1);
+  EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+  EXPECT_EQ(value, 123);
+  EXPECT_TRUE(absl::ParseFlag("-98765", &value, &err));
+  EXPECT_EQ(value, -98765);
+  EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+  EXPECT_EQ(value, 3);
+
+  // Leading zero values.
+  EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("-001", &value, &err));
+  EXPECT_EQ(value, -1);
+  EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+  EXPECT_EQ(value, 100);
+
+  // Hex values.
+  EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+  EXPECT_EQ(value, 16);
+  EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err));
+  EXPECT_EQ(value, 564);
+  // TODO(rogeeff): fix below validations
+  EXPECT_FALSE(absl::ParseFlag("-0x7FFFFFFD", &value, &err));
+  EXPECT_NE(value, -3);
+  EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+  EXPECT_NE(value, 49);
+
+  // Whitespace handling
+  EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err));
+  EXPECT_EQ(value, 10);
+  EXPECT_TRUE(absl::ParseFlag("  11", &value, &err));
+  EXPECT_EQ(value, 11);
+  EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err));
+  EXPECT_EQ(value, 12);
+  EXPECT_TRUE(absl::ParseFlag(" 0x22    ", &value, &err));
+  EXPECT_EQ(value, 34);
+
+  // Invalid values.
+  EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("  ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("70000000000", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUint32Parsing) {
+  std::string err;
+  uint32_t value;
+
+  // Decimal values.
+  EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+  EXPECT_EQ(value, 0);
+  EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+  EXPECT_EQ(value, 123);
+  EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+  EXPECT_EQ(value, 3);
+
+  // Leading zero values.
+  EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+  EXPECT_EQ(value, 100);
+
+  // Hex values.
+  EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+  EXPECT_EQ(value, 16);
+  EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err));
+  EXPECT_EQ(value, 564);
+  EXPECT_TRUE(absl::ParseFlag("0xFFFFFFFD", &value, &err));
+  EXPECT_EQ(value, 4294967293);
+  // TODO(rogeeff): fix below validations
+  EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+  EXPECT_NE(value, 49);
+
+  // Whitespace handling
+  EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err));
+  EXPECT_EQ(value, 10);
+  EXPECT_TRUE(absl::ParseFlag("  11", &value, &err));
+  EXPECT_EQ(value, 11);
+  EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err));
+  EXPECT_EQ(value, 12);
+  EXPECT_TRUE(absl::ParseFlag(" 0x22    ", &value, &err));
+  EXPECT_EQ(value, 34);
+
+  // Invalid values.
+  EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("  ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("140000000000", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("-1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt64Parsing) {
+  std::string err;
+  int64_t value;
+
+  // Decimal values.
+  EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+  EXPECT_EQ(value, 0);
+  EXPECT_TRUE(absl::ParseFlag("-1", &value, &err));
+  EXPECT_EQ(value, -1);
+  EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+  EXPECT_EQ(value, 123);
+  EXPECT_TRUE(absl::ParseFlag("-98765", &value, &err));
+  EXPECT_EQ(value, -98765);
+  EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+  EXPECT_EQ(value, 3);
+
+  // Leading zero values.
+  EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("001", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+  EXPECT_EQ(value, 100);
+
+  // Hex values.
+  EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+  EXPECT_EQ(value, 16);
+  EXPECT_TRUE(absl::ParseFlag("0XFFFAAABBBCCCDDD", &value, &err));
+  EXPECT_EQ(value, 1152827684197027293);
+  // TODO(rogeeff): fix below validation
+  EXPECT_FALSE(absl::ParseFlag("-0x7FFFFFFFFFFFFFFE", &value, &err));
+  EXPECT_NE(value, -2);
+  EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+  EXPECT_NE(value, 49);
+
+  // Whitespace handling
+  EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err));
+  EXPECT_EQ(value, 10);
+  EXPECT_TRUE(absl::ParseFlag("  11", &value, &err));
+  EXPECT_EQ(value, 11);
+  EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err));
+  EXPECT_EQ(value, 12);
+  EXPECT_TRUE(absl::ParseFlag(" 0x7F    ", &value, &err));
+  EXPECT_EQ(value, 127);
+
+  // Invalid values.
+  EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("  ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("0xFFFFFFFFFFFFFFFFFF", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUInt64Parsing) {
+  std::string err;
+  uint64_t value;
+
+  // Decimal values.
+  EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+  EXPECT_EQ(value, 0);
+  EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+  EXPECT_EQ(value, 123);
+  EXPECT_TRUE(absl::ParseFlag("+13", &value, &err));
+  EXPECT_EQ(value, 13);
+
+  // Leading zero values.
+  EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("001", &value, &err));
+  EXPECT_EQ(value, 1);
+  EXPECT_TRUE(absl::ParseFlag("0000300", &value, &err));
+  EXPECT_EQ(value, 300);
+
+  // Hex values.
+  EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+  EXPECT_EQ(value, 16);
+  EXPECT_TRUE(absl::ParseFlag("0XFFFF", &value, &err));
+  EXPECT_EQ(value, 65535);
+  // TODO(rogeeff): fix below validation
+  EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+  EXPECT_NE(value, 49);
+
+  // Whitespace handling
+  EXPECT_TRUE(absl::ParseFlag("10  ", &value, &err));
+  EXPECT_EQ(value, 10);
+  EXPECT_TRUE(absl::ParseFlag("  11", &value, &err));
+  EXPECT_EQ(value, 11);
+  EXPECT_TRUE(absl::ParseFlag("  012  ", &value, &err));
+  EXPECT_EQ(value, 12);
+
+  // Invalid values.
+  EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("  ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("0xFFFFFFFFFFFFFFFFFF", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("-1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestFloatParsing) {
+  std::string err;
+  float value;
+
+  // Ordinary values.
+  EXPECT_TRUE(absl::ParseFlag("1.3", &value, &err));
+  EXPECT_FLOAT_EQ(value, 1.3f);
+  EXPECT_TRUE(absl::ParseFlag("-0.1", &value, &err));
+  EXPECT_DOUBLE_EQ(value, -0.1f);
+  EXPECT_TRUE(absl::ParseFlag("+0.01", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 0.01f);
+
+  // Scientific values.
+  EXPECT_TRUE(absl::ParseFlag("1.2e3", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 1.2e3f);
+  EXPECT_TRUE(absl::ParseFlag("9.8765402e-37", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 9.8765402e-37f);
+  EXPECT_TRUE(absl::ParseFlag("0.11e+3", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 0.11e+3f);
+  EXPECT_TRUE(absl::ParseFlag("1.e-2300", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 0.f);
+  EXPECT_TRUE(absl::ParseFlag("1.e+2300", &value, &err));
+  EXPECT_TRUE(std::isinf(value));
+
+  // Leading zero values.
+  EXPECT_TRUE(absl::ParseFlag("01.6", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 1.6f);
+  EXPECT_TRUE(absl::ParseFlag("000.0001", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 0.0001f);
+
+  // Trailing zero values.
+  EXPECT_TRUE(absl::ParseFlag("-5.1000", &value, &err));
+  EXPECT_DOUBLE_EQ(value, -5.1f);
+
+  // Exceptional values.
+  EXPECT_TRUE(absl::ParseFlag("NaN", &value, &err));
+  EXPECT_TRUE(std::isnan(value));
+  EXPECT_TRUE(absl::ParseFlag("Inf", &value, &err));
+  EXPECT_TRUE(std::isinf(value));
+
+  // Hex values
+  EXPECT_TRUE(absl::ParseFlag("0x10.23p12", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 66096.f);
+  EXPECT_TRUE(absl::ParseFlag("-0xF1.A3p-2", &value, &err));
+  EXPECT_NEAR(value, -60.4092f, 5e-5f);
+  EXPECT_TRUE(absl::ParseFlag("+0x0.0AAp-12", &value, &err));
+  EXPECT_NEAR(value, 1.01328e-05f, 5e-11f);
+  EXPECT_TRUE(absl::ParseFlag("0x.01p1", &value, &err));
+  EXPECT_NEAR(value, 0.0078125f, 5e-8f);
+
+  // Whitespace handling
+  EXPECT_TRUE(absl::ParseFlag("10.1  ", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 10.1f);
+  EXPECT_TRUE(absl::ParseFlag("  2.34", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 2.34f);
+  EXPECT_TRUE(absl::ParseFlag("  5.7  ", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 5.7f);
+  EXPECT_TRUE(absl::ParseFlag("  -0xE0.F3p01  ", &value, &err));
+  EXPECT_NEAR(value, -449.8984375f, 5e-8f);
+
+  // Invalid values.
+  EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("  ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("2.3xxx", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("0x0.1pAA", &value, &err));
+  // TODO(rogeeff): below assertion should fail
+  EXPECT_TRUE(absl::ParseFlag("0x0.1", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestDoubleParsing) {
+  std::string err;
+  double value;
+
+  // Ordinary values.
+  EXPECT_TRUE(absl::ParseFlag("1.3", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 1.3);
+  EXPECT_TRUE(absl::ParseFlag("-0.1", &value, &err));
+  EXPECT_DOUBLE_EQ(value, -0.1);
+  EXPECT_TRUE(absl::ParseFlag("+0.01", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 0.01);
+
+  // Scientific values.
+  EXPECT_TRUE(absl::ParseFlag("1.2e3", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 1.2e3);
+  EXPECT_TRUE(absl::ParseFlag("9.00000002e-123", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 9.00000002e-123);
+  EXPECT_TRUE(absl::ParseFlag("0.11e+3", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 0.11e+3);
+  EXPECT_TRUE(absl::ParseFlag("1.e-2300", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 0);
+  EXPECT_TRUE(absl::ParseFlag("1.e+2300", &value, &err));
+  EXPECT_TRUE(std::isinf(value));
+
+  // Leading zero values.
+  EXPECT_TRUE(absl::ParseFlag("01.6", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 1.6);
+  EXPECT_TRUE(absl::ParseFlag("000.0001", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 0.0001);
+
+  // Trailing zero values.
+  EXPECT_TRUE(absl::ParseFlag("-5.1000", &value, &err));
+  EXPECT_DOUBLE_EQ(value, -5.1);
+
+  // Exceptional values.
+  EXPECT_TRUE(absl::ParseFlag("NaN", &value, &err));
+  EXPECT_TRUE(std::isnan(value));
+  EXPECT_TRUE(absl::ParseFlag("nan", &value, &err));
+  EXPECT_TRUE(std::isnan(value));
+  EXPECT_TRUE(absl::ParseFlag("Inf", &value, &err));
+  EXPECT_TRUE(std::isinf(value));
+  EXPECT_TRUE(absl::ParseFlag("inf", &value, &err));
+  EXPECT_TRUE(std::isinf(value));
+
+  // Hex values
+  EXPECT_TRUE(absl::ParseFlag("0x10.23p12", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 66096);
+  EXPECT_TRUE(absl::ParseFlag("-0xF1.A3p-2", &value, &err));
+  EXPECT_NEAR(value, -60.4092, 5e-5);
+  EXPECT_TRUE(absl::ParseFlag("+0x0.0AAp-12", &value, &err));
+  EXPECT_NEAR(value, 1.01328e-05, 5e-11);
+  EXPECT_TRUE(absl::ParseFlag("0x.01p1", &value, &err));
+  EXPECT_NEAR(value, 0.0078125, 5e-8);
+
+  // Whitespace handling
+  EXPECT_TRUE(absl::ParseFlag("10.1  ", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 10.1);
+  EXPECT_TRUE(absl::ParseFlag("  2.34", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 2.34);
+  EXPECT_TRUE(absl::ParseFlag("  5.7  ", &value, &err));
+  EXPECT_DOUBLE_EQ(value, 5.7);
+  EXPECT_TRUE(absl::ParseFlag("  -0xE0.F3p01  ", &value, &err));
+  EXPECT_NEAR(value, -449.8984375, 5e-8);
+
+  // Invalid values.
+  EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("  ", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("2.3xxx", &value, &err));
+  EXPECT_FALSE(absl::ParseFlag("0x0.1pAA", &value, &err));
+  // TODO(rogeeff): below assertion should fail
+  EXPECT_TRUE(absl::ParseFlag("0x0.1", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestStringParsing) {
+  std::string err;
+  std::string value;
+
+  EXPECT_TRUE(absl::ParseFlag("", &value, &err));
+  EXPECT_EQ(value, "");
+  EXPECT_TRUE(absl::ParseFlag(" ", &value, &err));
+  EXPECT_EQ(value, " ");
+  EXPECT_TRUE(absl::ParseFlag("   ", &value, &err));
+  EXPECT_EQ(value, "   ");
+  EXPECT_TRUE(absl::ParseFlag("\n", &value, &err));
+  EXPECT_EQ(value, "\n");
+  EXPECT_TRUE(absl::ParseFlag("\t", &value, &err));
+  EXPECT_EQ(value, "\t");
+  EXPECT_TRUE(absl::ParseFlag("asdfg", &value, &err));
+  EXPECT_EQ(value, "asdfg");
+  EXPECT_TRUE(absl::ParseFlag("asdf ghjk", &value, &err));
+  EXPECT_EQ(value, "asdf ghjk");
+  EXPECT_TRUE(absl::ParseFlag("a\nb\nc", &value, &err));
+  EXPECT_EQ(value, "a\nb\nc");
+  EXPECT_TRUE(absl::ParseFlag("asd\0fgh", &value, &err));
+  EXPECT_EQ(value, "asd");
+  EXPECT_TRUE(absl::ParseFlag("\\\\", &value, &err));
+  EXPECT_EQ(value, "\\\\");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestVectorOfStringParsing) {
+  std::string err;
+  std::vector<std::string> value;
+
+  EXPECT_TRUE(absl::ParseFlag("", &value, &err));
+  EXPECT_EQ(value, std::vector<std::string>{});
+  EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+  EXPECT_EQ(value, std::vector<std::string>({"1"}));
+  EXPECT_TRUE(absl::ParseFlag("a,b", &value, &err));
+  EXPECT_EQ(value, std::vector<std::string>({"a", "b"}));
+  EXPECT_TRUE(absl::ParseFlag("a,b,c,", &value, &err));
+  EXPECT_EQ(value, std::vector<std::string>({"a", "b", "c", ""}));
+  EXPECT_TRUE(absl::ParseFlag("a,,", &value, &err));
+  EXPECT_EQ(value, std::vector<std::string>({"a", "", ""}));
+  EXPECT_TRUE(absl::ParseFlag(",", &value, &err));
+  EXPECT_EQ(value, std::vector<std::string>({"", ""}));
+  EXPECT_TRUE(absl::ParseFlag("a, b,c ", &value, &err));
+  EXPECT_EQ(value, std::vector<std::string>({"a", " b", "c "}));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestBoolUnparsing) {
+  EXPECT_EQ(absl::UnparseFlag(true), "true");
+  EXPECT_EQ(absl::UnparseFlag(false), "false");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt16Unparsing) {
+  int16_t value;
+
+  value = 1;
+  EXPECT_EQ(absl::UnparseFlag(value), "1");
+  value = 0;
+  EXPECT_EQ(absl::UnparseFlag(value), "0");
+  value = -1;
+  EXPECT_EQ(absl::UnparseFlag(value), "-1");
+  value = 9876;
+  EXPECT_EQ(absl::UnparseFlag(value), "9876");
+  value = -987;
+  EXPECT_EQ(absl::UnparseFlag(value), "-987");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUint16Unparsing) {
+  uint16_t value;
+
+  value = 1;
+  EXPECT_EQ(absl::UnparseFlag(value), "1");
+  value = 0;
+  EXPECT_EQ(absl::UnparseFlag(value), "0");
+  value = 19876;
+  EXPECT_EQ(absl::UnparseFlag(value), "19876");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt32Unparsing) {
+  int32_t value;
+
+  value = 1;
+  EXPECT_EQ(absl::UnparseFlag(value), "1");
+  value = 0;
+  EXPECT_EQ(absl::UnparseFlag(value), "0");
+  value = -1;
+  EXPECT_EQ(absl::UnparseFlag(value), "-1");
+  value = 12345;
+  EXPECT_EQ(absl::UnparseFlag(value), "12345");
+  value = -987;
+  EXPECT_EQ(absl::UnparseFlag(value), "-987");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUint32Unparsing) {
+  uint32_t value;
+
+  value = 1;
+  EXPECT_EQ(absl::UnparseFlag(value), "1");
+  value = 0;
+  EXPECT_EQ(absl::UnparseFlag(value), "0");
+  value = 1234500;
+  EXPECT_EQ(absl::UnparseFlag(value), "1234500");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt64Unparsing) {
+  int64_t value;
+
+  value = 1;
+  EXPECT_EQ(absl::UnparseFlag(value), "1");
+  value = 0;
+  EXPECT_EQ(absl::UnparseFlag(value), "0");
+  value = -1;
+  EXPECT_EQ(absl::UnparseFlag(value), "-1");
+  value = 123456789L;
+  EXPECT_EQ(absl::UnparseFlag(value), "123456789");
+  value = -987654321L;
+  EXPECT_EQ(absl::UnparseFlag(value), "-987654321");
+  value = 0x7FFFFFFFFFFFFFFF;
+  EXPECT_EQ(absl::UnparseFlag(value), "9223372036854775807");
+  value = 0xFFFFFFFFFFFFFFFF;
+  EXPECT_EQ(absl::UnparseFlag(value), "-1");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUint64Unparsing) {
+  uint64_t value;
+
+  value = 1;
+  EXPECT_EQ(absl::UnparseFlag(value), "1");
+  value = 0;
+  EXPECT_EQ(absl::UnparseFlag(value), "0");
+  value = 123456789L;
+  EXPECT_EQ(absl::UnparseFlag(value), "123456789");
+  value = 0xFFFFFFFFFFFFFFFF;
+  EXPECT_EQ(absl::UnparseFlag(value), "18446744073709551615");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestFloatUnparsing) {
+  float value;
+
+  value = 1.1f;
+  EXPECT_EQ(absl::UnparseFlag(value), "1.1");
+  value = 0.01f;
+  EXPECT_EQ(absl::UnparseFlag(value), "0.01");
+  value = 1.23e-2f;
+  EXPECT_EQ(absl::UnparseFlag(value), "0.0123");
+  value = -0.71f;
+  EXPECT_EQ(absl::UnparseFlag(value), "-0.71");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestDoubleUnparsing) {
+  double value;
+
+  value = 1.1;
+  EXPECT_EQ(absl::UnparseFlag(value), "1.1");
+  value = 0.01;
+  EXPECT_EQ(absl::UnparseFlag(value), "0.01");
+  value = 1.23e-2;
+  EXPECT_EQ(absl::UnparseFlag(value), "0.0123");
+  value = -0.71;
+  EXPECT_EQ(absl::UnparseFlag(value), "-0.71");
+  value = -0;
+  EXPECT_EQ(absl::UnparseFlag(value), "0");
+  value = std::nan("");
+  EXPECT_EQ(absl::UnparseFlag(value), "nan");
+  value = std::numeric_limits<double>::infinity();
+  EXPECT_EQ(absl::UnparseFlag(value), "inf");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestStringUnparsing) {
+  EXPECT_EQ(absl::UnparseFlag(""), "");
+  EXPECT_EQ(absl::UnparseFlag(" "), " ");
+  EXPECT_EQ(absl::UnparseFlag("qwerty"), "qwerty");
+  EXPECT_EQ(absl::UnparseFlag("ASDFGH"), "ASDFGH");
+  EXPECT_EQ(absl::UnparseFlag("\n\t  "), "\n\t  ");
+}
+
+// --------------------------------------------------------------------
+
+template <typename T>
+void TestRoundtrip(T v) {
+  T new_v;
+  std::string err;
+  EXPECT_TRUE(absl::ParseFlag(absl::UnparseFlag(v), &new_v, &err));
+  EXPECT_EQ(new_v, v);
+}
+
+TEST(MarshallingTest, TestFloatRoundTrip) {
+  TestRoundtrip(0.1f);
+  TestRoundtrip(0.12f);
+  TestRoundtrip(0.123f);
+  TestRoundtrip(0.1234f);
+  TestRoundtrip(0.12345f);
+  TestRoundtrip(0.123456f);
+  TestRoundtrip(0.1234567f);
+  TestRoundtrip(0.12345678f);
+
+  TestRoundtrip(0.1e20f);
+  TestRoundtrip(0.12e20f);
+  TestRoundtrip(0.123e20f);
+  TestRoundtrip(0.1234e20f);
+  TestRoundtrip(0.12345e20f);
+  TestRoundtrip(0.123456e20f);
+  TestRoundtrip(0.1234567e20f);
+  TestRoundtrip(0.12345678e20f);
+
+  TestRoundtrip(0.1e-20f);
+  TestRoundtrip(0.12e-20f);
+  TestRoundtrip(0.123e-20f);
+  TestRoundtrip(0.1234e-20f);
+  TestRoundtrip(0.12345e-20f);
+  TestRoundtrip(0.123456e-20f);
+  TestRoundtrip(0.1234567e-20f);
+  TestRoundtrip(0.12345678e-20f);
+}
+
+TEST(MarshallingTest, TestDoubleRoundTrip) {
+  TestRoundtrip(0.1);
+  TestRoundtrip(0.12);
+  TestRoundtrip(0.123);
+  TestRoundtrip(0.1234);
+  TestRoundtrip(0.12345);
+  TestRoundtrip(0.123456);
+  TestRoundtrip(0.1234567);
+  TestRoundtrip(0.12345678);
+  TestRoundtrip(0.123456789);
+  TestRoundtrip(0.1234567891);
+  TestRoundtrip(0.12345678912);
+  TestRoundtrip(0.123456789123);
+  TestRoundtrip(0.1234567891234);
+  TestRoundtrip(0.12345678912345);
+  TestRoundtrip(0.123456789123456);
+  TestRoundtrip(0.1234567891234567);
+  TestRoundtrip(0.12345678912345678);
+
+  TestRoundtrip(0.1e50);
+  TestRoundtrip(0.12e50);
+  TestRoundtrip(0.123e50);
+  TestRoundtrip(0.1234e50);
+  TestRoundtrip(0.12345e50);
+  TestRoundtrip(0.123456e50);
+  TestRoundtrip(0.1234567e50);
+  TestRoundtrip(0.12345678e50);
+  TestRoundtrip(0.123456789e50);
+  TestRoundtrip(0.1234567891e50);
+  TestRoundtrip(0.12345678912e50);
+  TestRoundtrip(0.123456789123e50);
+  TestRoundtrip(0.1234567891234e50);
+  TestRoundtrip(0.12345678912345e50);
+  TestRoundtrip(0.123456789123456e50);
+  TestRoundtrip(0.1234567891234567e50);
+  TestRoundtrip(0.12345678912345678e50);
+
+  TestRoundtrip(0.1e-50);
+  TestRoundtrip(0.12e-50);
+  TestRoundtrip(0.123e-50);
+  TestRoundtrip(0.1234e-50);
+  TestRoundtrip(0.12345e-50);
+  TestRoundtrip(0.123456e-50);
+  TestRoundtrip(0.1234567e-50);
+  TestRoundtrip(0.12345678e-50);
+  TestRoundtrip(0.123456789e-50);
+  TestRoundtrip(0.1234567891e-50);
+  TestRoundtrip(0.12345678912e-50);
+  TestRoundtrip(0.123456789123e-50);
+  TestRoundtrip(0.1234567891234e-50);
+  TestRoundtrip(0.12345678912345e-50);
+  TestRoundtrip(0.123456789123456e-50);
+  TestRoundtrip(0.1234567891234567e-50);
+  TestRoundtrip(0.12345678912345678e-50);
+}
+
+}  // namespace
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
new file mode 100644
index 000000000000..b19619602433
--- /dev/null
+++ b/absl/flags/parse.cc
@@ -0,0 +1,762 @@
+//
+// 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/parse.h"
+
+#include <stdlib.h>
+#include <fstream>
+#include <iostream>
+#include <tuple>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/program_name.h"
+#include "absl/flags/internal/registry.h"
+#include "absl/flags/internal/usage.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/strip.h"
+#include "absl/synchronization/mutex.h"
+
+// --------------------------------------------------------------------
+
+namespace absl {
+namespace flags_internal {
+namespace {
+
+ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit);
+
+ABSL_CONST_INIT bool flagfile_needs_processing
+    GUARDED_BY(processing_checks_guard) = false;
+ABSL_CONST_INIT bool fromenv_needs_processing
+    GUARDED_BY(processing_checks_guard) = false;
+ABSL_CONST_INIT bool tryfromenv_needs_processing
+    GUARDED_BY(processing_checks_guard) = false;
+
+}  // namespace
+}  // namespace flags_internal
+}  // namespace absl
+
+ABSL_FLAG(std::vector<std::string>, flagfile, {},
+          "comma-separated list of files to load flags from")
+    .OnUpdate([]() {
+      if (absl::GetFlag(FLAGS_flagfile).empty()) return;
+
+      absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
+
+      // Setting this flag twice before it is handled most likely an internal
+      // error and should be reviewed by developers.
+      if (absl::flags_internal::flagfile_needs_processing) {
+        ABSL_INTERNAL_LOG(WARNING, "flagfile set twice before it is handled");
+      }
+
+      absl::flags_internal::flagfile_needs_processing = true;
+    });
+ABSL_FLAG(std::vector<std::string>, fromenv, {},
+          "comma-separated list of flags to set from the environment"
+          " [use 'export FLAGS_flag1=value']")
+    .OnUpdate([]() {
+      if (absl::GetFlag(FLAGS_fromenv).empty()) return;
+
+      absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
+
+      // Setting this flag twice before it is handled most likely an internal
+      // error and should be reviewed by developers.
+      if (absl::flags_internal::fromenv_needs_processing) {
+        ABSL_INTERNAL_LOG(WARNING, "fromenv set twice before it is handled.");
+      }
+
+      absl::flags_internal::fromenv_needs_processing = true;
+    });
+ABSL_FLAG(std::vector<std::string>, tryfromenv, {},
+          "comma-separated list of flags to try to set from the environment if "
+          "present")
+    .OnUpdate([]() {
+      if (absl::GetFlag(FLAGS_tryfromenv).empty()) return;
+
+      absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
+
+      // Setting this flag twice before it is handled most likely an internal
+      // error and should be reviewed by developers.
+      if (absl::flags_internal::tryfromenv_needs_processing) {
+        ABSL_INTERNAL_LOG(WARNING,
+                          "tryfromenv set twice before it is handled.");
+      }
+
+      absl::flags_internal::tryfromenv_needs_processing = true;
+    });
+
+ABSL_FLAG(std::vector<std::string>, undefok, {},
+          "comma-separated list of flag names that it is okay to specify "
+          "on the command line even if the program does not define a flag "
+          "with that name");
+
+namespace absl {
+namespace flags_internal {
+
+namespace {
+
+class ArgsList {
+ public:
+  ArgsList() : next_arg_(0) {}
+  ArgsList(int argc, char* argv[]) : args_(argv, argv + argc), next_arg_(0) {}
+  explicit ArgsList(const std::vector<std::string>& args)
+      : args_(args), next_arg_(0) {}
+
+  // Returns success status: true if parsing successful, false otherwise.
+  bool ReadFromFlagfile(const std::string& flag_file_name);
+
+  int Size() const { return args_.size() - next_arg_; }
+  int FrontIndex() const { return next_arg_; }
+  absl::string_view Front() const { return args_[next_arg_]; }
+  void PopFront() { next_arg_++; }
+
+ private:
+  std::vector<std::string> args_;
+  int next_arg_;
+};
+
+bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {
+  std::ifstream flag_file(flag_file_name);
+
+  if (!flag_file) {
+    flags_internal::ReportUsageError(
+        absl::StrCat("Can't open flagfile ", flag_file_name), true);
+
+    return false;
+  }
+
+  // This argument represents fake argv[0], which should be present in all arg
+  // lists.
+  args_.push_back("");
+
+  std::string line;
+  bool success = true;
+
+  while (std::getline(flag_file, line)) {
+    absl::string_view stripped = absl::StripLeadingAsciiWhitespace(line);
+
+    if (stripped.empty() || stripped[0] == '#') {
+      // Comment or empty line; just ignore.
+      continue;
+    }
+
+    if (stripped[0] == '-') {
+      if (stripped == "--") {
+        flags_internal::ReportUsageError(
+            "Flagfile can't contain position arguments or --", true);
+
+        success = false;
+        break;
+      }
+
+      args_.push_back(std::string(stripped));
+      continue;
+    }
+
+    flags_internal::ReportUsageError(
+        absl::StrCat("Unexpected line in the flagfile ", flag_file_name, ": ",
+                     line),
+        true);
+
+    success = false;
+  }
+
+  return success;
+}
+
+// --------------------------------------------------------------------
+
+// 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) {
+#ifdef _WIN32
+  char buf[1024];
+  auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
+  if (get_res >= sizeof(buf)) {
+    return "";
+  }
+
+  if (get_res == 0) {
+    return false;
+  }
+
+  *var_value = std::string(buf, get_res);
+#else
+  const char* val = ::getenv(var_name);
+  if (val == nullptr) {
+    return false;
+  }
+
+  *var_value = val;
+#endif
+
+  return true;
+}
+
+// --------------------------------------------------------------------
+
+// Returns:
+//  Flag name or empty if arg= --
+//  Flag value after = in --flag=value (empty if --foo)
+//  "Is empty value" status. True if arg= --foo=, false otherwise. This is
+//  required to separate --foo from --foo=.
+// For example:
+//      arg           return values
+//   "--foo=bar" -> {"foo", "bar", false}.
+//   "--foo"     -> {"foo", "", false}.
+//   "--foo="    -> {"foo", "", true}.
+std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue(
+    absl::string_view arg) {
+  // Allow -foo and --foo
+  absl::ConsumePrefix(&arg, "-");
+
+  if (arg.empty()) {
+    return std::make_tuple("", "", false);
+  }
+
+  auto equal_sign_pos = arg.find("=");
+
+  absl::string_view flag_name = arg.substr(0, equal_sign_pos);
+
+  absl::string_view value;
+  bool is_empty_value = false;
+
+  if (equal_sign_pos != absl::string_view::npos) {
+    value = arg.substr(equal_sign_pos + 1);
+    is_empty_value = value.empty();
+  }
+
+  return std::make_tuple(flag_name, value, is_empty_value);
+}
+
+// --------------------------------------------------------------------
+
+// Returns:
+//  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);
+  bool is_negative = false;
+
+  if (!flag && absl::ConsumePrefix(&flag_name, "no")) {
+    flag = flags_internal::FindCommandLineFlag(flag_name);
+    is_negative = true;
+  }
+
+  return std::make_tuple(flag, is_negative);
+}
+
+// --------------------------------------------------------------------
+
+// Verify that default values of typed flags must be convertible to string and
+// back.
+void CheckDefaultValuesParsingRoundtrip() {
+#ifndef NDEBUG
+  flags_internal::ForEachFlag([&](CommandLineFlag* flag) {
+    if (flag->IsRetired()) return;
+
+#define IGNORE_TYPE(T) \
+  if (flag->IsOfType<T>()) return;
+
+    ABSL_FLAGS_INTERNAL_FOR_EACH_LOCK_FREE(IGNORE_TYPE)
+    IGNORE_TYPE(std::string)
+    IGNORE_TYPE(std::vector<std::string>)
+#undef IGNORE_TYPE
+
+    absl::MutexLock lock(InitFlagIfNecessary(flag));
+
+    std::string v = flag->DefaultValue();
+    void* dst = Clone(flag->op, flag->def);
+    std::string error;
+    if (!flags_internal::Parse(flag->marshalling_op, v, dst, &error)) {
+      ABSL_INTERNAL_LOG(
+          FATAL,
+          absl::StrCat("Flag ", flag->Name(), " (from ", flag->Filename(),
+                       "): std::string form of default value '", v,
+                       "' could not be parsed; error=", error));
+    }
+
+    // We do not compare dst to def since parsing/unparsing may make
+    // small changes, e.g., precision loss for floating point types.
+    Delete(flag->op, dst);
+  });
+#endif
+}
+
+// --------------------------------------------------------------------
+
+// Returns success status, which is true if we successfully read all flag files,
+// in which case new ArgLists are appended to the input_args in a reverse order
+// of file names in the input flagfiles list. This order ensures that flags from
+// 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) {
+  bool success = true;
+  for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) {
+    ArgsList al;
+
+    if (al.ReadFromFlagfile(*it)) {
+      input_args->push_back(al);
+    } else {
+      success = false;
+    }
+  }
+
+  return success;
+}
+
+// Returns success status, which is true if were able to locate all environment
+// variables correctly or if fail_on_absent_in_env is false. The environment
+// variable names are expected to be of the form `FLAGS_<flag_name>`, where
+// `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,
+                      bool fail_on_absent_in_env) {
+  bool success = true;
+  std::vector<std::string> args;
+
+  // This argument represents fake argv[0], which should be present in all arg
+  // lists.
+  args.push_back("");
+
+  for (const auto& flag_name : flag_names) {
+    // Avoid infinite recursion.
+    if (flag_name == "fromenv" || flag_name == "tryfromenv") {
+      flags_internal::ReportUsageError(
+          absl::StrCat("Infinite recursion on flag ", flag_name), true);
+
+      success = false;
+      continue;
+    }
+
+    const std::string envname = absl::StrCat("FLAGS_", flag_name);
+    std::string envval;
+    if (!GetEnvVar(envname.c_str(), &envval)) {
+      if (fail_on_absent_in_env) {
+        flags_internal::ReportUsageError(
+            absl::StrCat(envname, " not found in environment"), true);
+
+        success = false;
+      }
+
+      continue;
+    }
+
+    args.push_back(absl::StrCat("--", flag_name, "=", envval));
+  }
+
+  if (success) {
+    input_args->emplace_back(args);
+  }
+
+  return success;
+}
+
+// --------------------------------------------------------------------
+
+// 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 success = true;
+
+  absl::MutexLock l(&flags_internal::processing_checks_guard);
+
+  // flagfile could have been set either on a command line or
+  // programmatically before invoking ParseCommandLine. Note that we do not
+  // actually process arguments specified in the flagfile, but instead
+  // create a secondary arguments list to be processed along with the rest
+  // of the comamnd line arguments. Since we always the process most recently
+  // created list of arguments first, this will result in flagfile argument
+  // being processed before any other argument in the command line. If
+  // FLAGS_flagfile contains more than one file name we create multiple new
+  // levels of arguments in a reverse order of file names. Thus we always
+  // process arguments from first file before arguments containing in a
+  // second file, etc. If flagfile contains another
+  // --flagfile inside of it, it will produce new level of arguments and
+  // processed before the rest of the flagfile. We are also collecting all
+  // flagfiles set on original command line. Unlike the rest of the flags,
+  // this flag can be set multiple times and is expected to be handled
+  // multiple times. We are collecting them all into a single list and set
+  // the value of FLAGS_flagfile to that value at the end of the parsing.
+  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());
+    }
+
+    success &= ReadFlagfiles(flagfiles, input_args);
+
+    flags_internal::flagfile_needs_processing = false;
+  }
+
+  // Similar to flagfile fromenv/tryfromemv can be set both
+  // programmatically and at runtime on a command line. Unlike flagfile these
+  // can't be recursive.
+  if (flags_internal::fromenv_needs_processing) {
+    auto flags_list = absl::GetFlag(FLAGS_fromenv);
+
+    success &= ReadFlagsFromEnv(flags_list, input_args, true);
+
+    flags_internal::fromenv_needs_processing = false;
+  }
+
+  if (flags_internal::tryfromenv_needs_processing) {
+    auto flags_list = absl::GetFlag(FLAGS_tryfromenv);
+
+    success &= ReadFlagsFromEnv(flags_list, input_args, false);
+
+    flags_internal::tryfromenv_needs_processing = false;
+  }
+
+  return success;
+}
+
+// --------------------------------------------------------------------
+
+void ResetGeneratorFlags(const std::vector<std::string>& flagfile_value) {
+  // Setting flagfile to the value which collates all the values set on a
+  // command line and programmatically. So if command line looked like
+  // --flagfile=f1 --flagfile=f2 the final value of the FLAGS_flagfile flag is
+  // going to be {"f1", "f2"}
+  if (!flagfile_value.empty()) {
+    absl::SetFlag(&FLAGS_flagfile, flagfile_value);
+    absl::MutexLock l(&flags_internal::processing_checks_guard);
+    flags_internal::flagfile_needs_processing = false;
+  }
+
+  // fromenv/tryfromenv are set to <undefined> value.
+  if (!absl::GetFlag(FLAGS_fromenv).empty()) {
+    absl::SetFlag(&FLAGS_fromenv, {});
+  }
+  if (!absl::GetFlag(FLAGS_tryfromenv).empty()) {
+    absl::SetFlag(&FLAGS_tryfromenv, {});
+  }
+
+  absl::MutexLock l(&flags_internal::processing_checks_guard);
+  flags_internal::fromenv_needs_processing = false;
+  flags_internal::tryfromenv_needs_processing = false;
+}
+
+// --------------------------------------------------------------------
+
+// Returns:
+//  success status
+//  deduced value
+// We are also mutating curr_list in case if we need to get a hold of next
+// argument in the input.
+std::tuple<bool, absl::string_view> DeduceFlagValue(const CommandLineFlag& flag,
+                                                    absl::string_view value,
+                                                    bool is_negative,
+                                                    bool is_empty_value,
+                                                    ArgsList* curr_list) {
+  // Value is either an argument suffix after `=` in "--foo=<value>"
+  // or separate argument in case of "--foo" "<value>".
+
+  // boolean flags have these forms:
+  //   --foo
+  //   --nofoo
+  //   --foo=true
+  //   --foo=false
+  //   --nofoo=<value> is not supported
+  //   --foo <value> is not supported
+
+  // non boolean flags have these forms:
+  // --foo=<value>
+  // --foo <value>
+  // --nofoo is not supported
+
+  if (flag.IsOfType<bool>()) {
+    if (value.empty()) {
+      if (is_empty_value) {
+        // "--bool_flag=" case
+        flags_internal::ReportUsageError(
+            absl::StrCat(
+                "Missing the value after assignment for the boolean flag '",
+                flag.Name(), "'"),
+            true);
+        return std::make_tuple(false, "");
+      }
+
+      // "--bool_flag" case
+      value = is_negative ? "0" : "1";
+    } else if (is_negative) {
+      // "--nobool_flag=Y" case
+      flags_internal::ReportUsageError(
+          absl::StrCat("Negative form with assignment is not valid for the "
+                       "boolean flag '",
+                       flag.Name(), "'"),
+          true);
+      return std::make_tuple(false, "");
+    }
+  } else if (is_negative) {
+    // "--noint_flag=1" case
+    flags_internal::ReportUsageError(
+        absl::StrCat("Negative form is not valid for the flag '", flag.Name(),
+                     "'"),
+        true);
+    return std::make_tuple(false, "");
+  } else if (value.empty() && (!is_empty_value)) {
+    if (curr_list->Size() == 1) {
+      // "--int_flag" case
+      flags_internal::ReportUsageError(
+          absl::StrCat("Missing the value for the flag '", flag.Name(), "'"),
+          true);
+      return std::make_tuple(false, "");
+    }
+
+    // "--int_flag" "10" case
+    curr_list->PopFront();
+    value = curr_list->Front();
+
+    // Heuristic to detect the case where someone treats a std::string arg
+    // like a bool or just forgets to pass a value:
+    // --my_string_var --foo=bar
+    // We look for a flag of std::string type, whose value begins with a
+    // dash and corresponds to known flag or standalone --.
+    if (value[0] == '-' && flag.IsOfType<std::string>()) {
+      auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1)));
+
+      if (maybe_flag_name.empty() ||
+          std::get<0>(LocateFlag(maybe_flag_name)) != nullptr) {
+        // "--string_flag" "--known_flag" case
+        ABSL_INTERNAL_LOG(
+            WARNING,
+            absl::StrCat("Did you really mean to set flag '", flag.Name(),
+                         "' to the value '", value, "'?"));
+      }
+    }
+  }
+
+  return std::make_tuple(true, value);
+}
+
+// --------------------------------------------------------------------
+
+bool CanIgnoreUndefinedFlag(absl::string_view flag_name) {
+  auto undefok = absl::GetFlag(FLAGS_undefok);
+  if (std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
+    return true;
+  }
+
+  if (absl::ConsumePrefix(&flag_name, "no") &&
+      std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
+    return true;
+  }
+
+  return false;
+}
+
+}  // namespace
+
+// --------------------------------------------------------------------
+
+std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
+                                        ArgvListAction arg_list_act,
+                                        UsageFlagsAction usage_flag_act,
+                                        OnUndefinedFlag on_undef_flag) {
+  ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
+
+  // This routine does not return anything since we abort on failure.
+  CheckDefaultValuesParsingRoundtrip();
+
+  std::vector<std::string> flagfile_value;
+
+  std::vector<ArgsList> input_args;
+  input_args.push_back(ArgsList(argc, argv));
+
+  std::vector<char*> output_args;
+  std::vector<char*> positional_args;
+  output_args.reserve(argc);
+
+  // This is the list of undefined flags. The element of the list is the pair
+  // consisting of boolean indicating if flag came from command line (vs from
+  // some flag file we've read) and flag name.
+  // TODO(rogeeff): Eliminate the first element in the pair after cleanup.
+  std::vector<std::pair<bool, std::string>> undefined_flag_names;
+
+  // Set program invocation name if it is not set before.
+  if (ProgramInvocationName() == "UNKNOWN") {
+    flags_internal::SetProgramInvocationName(argv[0]);
+  }
+  output_args.push_back(argv[0]);
+
+  // Iterate through the list of the input arguments. First level are arguments
+  // originated from argc/argv. Following levels are arguments originated from
+  // recursive parsing of flagfile(s).
+  bool success = true;
+  while (!input_args.empty()) {
+    // 10. First we process the built-in generator flags.
+    success &= HandleGeneratorFlags(&input_args, &flagfile_value);
+
+    // 30. Select top-most (most recent) arguments list. If it is empty drop it
+    // and re-try.
+    ArgsList& curr_list = input_args.back();
+
+    curr_list.PopFront();
+
+    if (curr_list.Size() == 0) {
+      input_args.pop_back();
+      continue;
+    }
+
+    // 40. Pick up the front remaining argument in the current list. If current
+    // stack of argument lists contains only one element - we are processing an
+    // argument from the original argv.
+    absl::string_view arg(curr_list.Front());
+    bool arg_from_argv = input_args.size() == 1;
+
+    // 50. If argument does not start with - or is just "-" - this is
+    // positional argument.
+    if (!absl::ConsumePrefix(&arg, "-") || arg.empty()) {
+      ABSL_INTERNAL_CHECK(arg_from_argv,
+                          "Flagfile cannot contain positional argument");
+
+      positional_args.push_back(argv[curr_list.FrontIndex()]);
+      continue;
+    }
+
+    if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs)) {
+      output_args.push_back(argv[curr_list.FrontIndex()]);
+    }
+
+    // 60. Split the current argument on '=' to figure out the argument
+    // name and value. If flag name is empty it means we've got "--". value
+    // can be empty either if there were no '=' in argument std::string at all or
+    // an argument looked like "--foo=". In a latter case is_empty_value is
+    // true.
+    absl::string_view flag_name;
+    absl::string_view value;
+    bool is_empty_value = false;
+
+    std::tie(flag_name, value, is_empty_value) = SplitNameAndValue(arg);
+
+    // 70. "--" alone means what it does for GNU: stop flags parsing. We do
+    // not support positional arguments in flagfiles, so we just drop them.
+    if (flag_name.empty()) {
+      ABSL_INTERNAL_CHECK(arg_from_argv,
+                          "Flagfile cannot contain positional argument");
+
+      curr_list.PopFront();
+      break;
+    }
+
+    // 80. Locate the flag based on flag name. Handle both --foo and --nofoo
+    CommandLineFlag* flag = nullptr;
+    bool is_negative = false;
+    std::tie(flag, is_negative) = LocateFlag(flag_name);
+
+    if (flag == nullptr) {
+      if (on_undef_flag != OnUndefinedFlag::kIgnoreUndefined) {
+        undefined_flag_names.emplace_back(arg_from_argv,
+                                          std::string(flag_name));
+      }
+      continue;
+    }
+
+    // 90. Deduce flag's value (from this or next argument)
+    auto curr_index = curr_list.FrontIndex();
+    bool value_success = true;
+    std::tie(value_success, value) =
+        DeduceFlagValue(*flag, value, is_negative, is_empty_value, &curr_list);
+    success &= value_success;
+
+    // If above call consumed an argument, it was a standalone value
+    if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs) &&
+        (curr_index != curr_list.FrontIndex())) {
+      output_args.push_back(argv[curr_list.FrontIndex()]);
+    }
+
+    // 100. Set the located flag to a new new value, unless it is retired.
+    // Setting retired flag fails, but we ignoring it here.
+    if (flag->IsRetired()) continue;
+
+    std::string error;
+    if (!flag->SetFromString(value, SET_FLAGS_VALUE, kCommandLine, &error)) {
+      flags_internal::ReportUsageError(error, true);
+      success = false;
+    }
+  }
+
+  for (const auto& flag_name : undefined_flag_names) {
+    if (CanIgnoreUndefinedFlag(flag_name.second)) continue;
+
+    flags_internal::ReportUsageError(
+        absl::StrCat("Unknown command line flag '", flag_name.second, "'"),
+        true);
+
+    success = false;
+  }
+
+#if ABSL_FLAGS_STRIP_NAMES
+  if (!success) {
+    flags_internal::ReportUsageError(
+        "NOTE: command line flags are disabled in this build", true);
+  }
+#endif
+
+  if (!success) {
+    flags_internal::HandleUsageFlags(std::cout);
+    std::exit(1);
+  }
+
+  if (usage_flag_act == UsageFlagsAction::kHandleUsage) {
+    int exit_code = flags_internal::HandleUsageFlags(std::cout);
+
+    if (exit_code != -1) {
+      std::exit(exit_code);
+    }
+  }
+
+  ResetGeneratorFlags(flagfile_value);
+
+  // Reinstate positional args which were intermixed with flags in the arguments
+  // list.
+  for (auto arg : positional_args) {
+    output_args.push_back(arg);
+  }
+
+  // All the remaining arguments are positional.
+  if (!input_args.empty()) {
+    for (int arg_index = input_args.back().FrontIndex(); arg_index < argc;
+         ++arg_index) {
+      output_args.push_back(argv[arg_index]);
+    }
+  }
+
+  return output_args;
+}
+
+}  // namespace flags_internal
+
+// --------------------------------------------------------------------
+
+std::vector<char*> ParseCommandLine(int argc, char* argv[]) {
+  return flags_internal::ParseCommandLineImpl(
+      argc, argv, flags_internal::ArgvListAction::kRemoveParsedArgs,
+      flags_internal::UsageFlagsAction::kHandleUsage,
+      flags_internal::OnUndefinedFlag::kAbortIfUndefined);
+}
+
+}  // namespace absl
diff --git a/absl/flags/parse.h b/absl/flags/parse.h
new file mode 100644
index 000000000000..dbb751015686
--- /dev/null
+++ b/absl/flags/parse.h
@@ -0,0 +1,58 @@
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: parse.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the main parsing function for Abseil flags:
+// `absl::ParseCommandLine()`.
+
+#ifndef ABSL_FLAGS_PARSE_H_
+#define ABSL_FLAGS_PARSE_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/flags/internal/parse.h"
+
+namespace absl {
+
+// ParseCommandLine()
+//
+// Parses the set of command-line arguments passed in the `argc` (argument
+// count) and `argv[]` (argument vector) parameters from `main()`, assigning
+// values to any defined Abseil flags. (Any arguments passed after the
+// flag-terminating delimiter (`--`) are treated as positional arguments and
+// ignored.)
+//
+// Any command-line flags (and arguments to those flags) are parsed into Abseil
+// Flag values, if those flags are defined. Any undefined flags will either
+// return an error, or be ignored if that flag is designated using `undefok` to
+// indicate "undefined is OK."
+//
+// Any command-line positional arguments not part of any command-line flag (or
+// arguments to a flag) are returned in a vector, with the program invocation
+// name at position 0 of that vector. (Note that this includes positional
+// arguments after the flag-terminating delimiter `--`.)
+//
+// After all flags and flag arguments are parsed, this function looks for any
+// built-in usage flags (e.g. `--help`), and if any were specified, it reports
+// help messages and then exits the program.
+std::vector<char*> ParseCommandLine(int argc, char* argv[]);
+
+}  // namespace absl
+
+#endif  // ABSL_FLAGS_PARSE_H_
diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc
new file mode 100644
index 000000000000..447a3bc7bdcb
--- /dev/null
+++ b/absl/flags/parse_test.cc
@@ -0,0 +1,858 @@
+//
+// 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/parse.h"
+
+#include <fstream>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/scoped_set_env.h"
+#include "absl/flags/flag.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/substitute.h"
+#include "absl/types/span.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+namespace {
+
+using absl::base_internal::ScopedSetEnv;
+
+struct UDT {
+  UDT() = default;
+  UDT(const UDT&) = default;
+  UDT(int v) : value(v) {}  // NOLINT
+
+  int value;
+};
+
+bool AbslParseFlag(absl::string_view in, UDT* udt, std::string* err) {
+  if (in == "A") {
+    udt->value = 1;
+    return true;
+  }
+  if (in == "AAA") {
+    udt->value = 10;
+    return true;
+  }
+
+  *err = "Use values A, AAA instead";
+  return false;
+}
+std::string AbslUnparseFlag(const UDT& udt) {
+  return udt.value == 1 ? "A" : "AAA";
+}
+
+std::string GetTestTmpDirEnvVar(const char* const env_var_name) {
+#ifdef _WIN32
+  char buf[MAX_PATH];
+  auto get_res = GetEnvironmentVariableA(env_var_name, buf, sizeof(buf));
+  if (get_res >= sizeof(buf) || get_res == 0) {
+    return "";
+  }
+
+  return std::string(buf, get_res);
+#else
+  const char* val = ::getenv(env_var_name);
+  if (val == nullptr) {
+    return "";
+  }
+
+  return val;
+#endif
+}
+
+const std::string& GetTestTempDir() {
+  static std::string* temp_dir_name = []() -> std::string* {
+    std::string* res = new std::string(GetTestTmpDirEnvVar("TEST_TMPDIR"));
+
+    if (res->empty()) {
+      *res = GetTestTmpDirEnvVar("TMPDIR");
+    }
+
+    if (res->empty()) {
+#ifdef _WIN32
+      char temp_path_buffer[MAX_PATH];
+
+      auto len = GetTempPathA(MAX_PATH, temp_path_buffer);
+      if (len < MAX_PATH && len != 0) {
+        std::string temp_dir_name = absl::StrCat(
+            temp_path_buffer, "\\parse_test.", GetCurrentProcessId());
+        if (CreateDirectoryA(temp_dir_name.c_str(), nullptr)) {
+          *res = temp_dir_name;
+        }
+      }
+#else
+      char temp_dir_template[] = "/tmp/parse_test.XXXXXX";
+      if (auto* unique_name = ::mkdtemp(temp_dir_template)) {
+        *res = unique_name;
+      }
+#endif
+
+      if (res->empty()) {
+        ABSL_INTERNAL_LOG(FATAL,
+                          "Failed to make temporary directory for data files");
+      }
+    }
+
+#ifdef _WIN32
+    *res += "\\";
+#else
+    *res += "/";
+#endif
+
+    return res;
+  }();
+
+  return *temp_dir_name;
+}
+
+struct FlagfileData {
+  const absl::string_view file_name;
+  const absl::Span<const char* const> file_lines;
+};
+
+// clang-format off
+constexpr const char* const ff1_data[] = {
+    "# comment    ",
+    "  # comment  ",
+    "",
+    "     ",
+    "--int_flag=-1",
+    "  --string_flag=q2w2  ",
+    "  ##   ",
+    "  --double_flag=0.1",
+    "--bool_flag=Y  "
+};
+
+constexpr const char* const ff2_data[] = {
+    "# Setting legacy flag",
+    "--legacy_int=1111",
+    "--legacy_bool",
+    "--nobool_flag",
+    "--legacy_str=aqsw",
+    "--int_flag=100",
+    "   ## ============="
+};
+// clang-format on
+
+// Builds flagfile flag in the flagfile_flag buffer and returns it. This
+// function also creates a temporary flagfile based on FlagfileData input.
+// We create a flagfile in a temporary directory with the name specified in
+// FlagfileData and populate it with lines specifed in FlagfileData. If $0 is
+// referenced in any of the lines in FlagfileData they are replaced with
+// 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=";
+  absl::string_view separator;
+  for (const auto& flagfile_data : ffd) {
+    std::string flagfile_name =
+        absl::StrCat(GetTestTempDir(), flagfile_data.file_name);
+
+    std::ofstream flagfile_out(flagfile_name);
+    for (auto line : flagfile_data.file_lines) {
+      flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n";
+    }
+
+    absl::StrAppend(flagfile_flag, separator, flagfile_name);
+    separator = ",";
+  }
+
+  return flagfile_flag->c_str();
+}
+
+}  // namespace
+
+ABSL_FLAG(int, int_flag, 1, "");
+ABSL_FLAG(double, double_flag, 1.1, "");
+ABSL_FLAG(std::string, string_flag, "a", "");
+ABSL_FLAG(bool, bool_flag, false, "");
+ABSL_FLAG(UDT, udt_flag, -1, "");
+ABSL_RETIRED_FLAG(int, legacy_int, 1, "");
+ABSL_RETIRED_FLAG(bool, legacy_bool, false, "");
+ABSL_RETIRED_FLAG(std::string, legacy_str, "l", "");
+
+namespace {
+
+namespace flags = absl::flags_internal;
+using testing::ElementsAreArray;
+
+class ParseTest : public testing::Test {
+ private:
+  flags::FlagSaver flag_saver_;
+};
+
+// --------------------------------------------------------------------
+
+template <int N>
+std::vector<char*> InvokeParse(const char* (&in_argv)[N]) {
+  return absl::ParseCommandLine(N, const_cast<char**>(in_argv));
+}
+
+// --------------------------------------------------------------------
+
+template <int N>
+void TestParse(const char* (&in_argv)[N], int int_flag_value,
+               double double_flag_val, absl::string_view string_flag_val,
+               bool bool_flag_val, int exp_position_args = 0) {
+  auto out_args = InvokeParse(in_argv);
+
+  EXPECT_EQ(out_args.size(), 1 + exp_position_args);
+  EXPECT_STREQ(out_args[0], "testbin");
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), int_flag_value);
+  EXPECT_NEAR(absl::GetFlag(FLAGS_double_flag), double_flag_val, 0.0001);
+  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), string_flag_val);
+  EXPECT_EQ(absl::GetFlag(FLAGS_bool_flag), bool_flag_val);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestEmptyArgv) {
+  const char* in_argv[] = {"testbin"};
+
+  auto out_args = InvokeParse(in_argv);
+
+  EXPECT_EQ(out_args.size(), 1);
+  EXPECT_STREQ(out_args[0], "testbin");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidIntArg) {
+  const char* in_args1[] = {
+      "testbin",
+      "--int_flag=10",
+  };
+  TestParse(in_args1, 10, 1.1, "a", false);
+
+  const char* in_args2[] = {
+      "testbin",
+      "-int_flag=020",
+  };
+  TestParse(in_args2, 20, 1.1, "a", false);
+
+  const char* in_args3[] = {
+      "testbin",
+      "--int_flag",
+      "-30",
+  };
+  TestParse(in_args3, -30, 1.1, "a", false);
+
+  const char* in_args4[] = {
+      "testbin",
+      "-int_flag",
+      "0x21",
+  };
+  TestParse(in_args4, 33, 1.1, "a", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidDoubleArg) {
+  const char* in_args1[] = {
+      "testbin",
+      "--double_flag=2.3",
+  };
+  TestParse(in_args1, 1, 2.3, "a", false);
+
+  const char* in_args2[] = {
+      "testbin",
+      "--double_flag=0x1.2",
+  };
+  TestParse(in_args2, 1, 1.125, "a", false);
+
+  const char* in_args3[] = {
+      "testbin",
+      "--double_flag",
+      "99.7",
+  };
+  TestParse(in_args3, 1, 99.7, "a", false);
+
+  const char* in_args4[] = {
+      "testbin",
+      "--double_flag",
+      "0x20.1",
+  };
+  TestParse(in_args4, 1, 32.0625, "a", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidStringArg) {
+  const char* in_args1[] = {
+      "testbin",
+      "--string_flag=aqswde",
+  };
+  TestParse(in_args1, 1, 1.1, "aqswde", false);
+
+  const char* in_args2[] = {
+      "testbin",
+      "-string_flag=a=b=c",
+  };
+  TestParse(in_args2, 1, 1.1, "a=b=c", false);
+
+  const char* in_args3[] = {
+      "testbin",
+      "--string_flag",
+      "zaxscd",
+  };
+  TestParse(in_args3, 1, 1.1, "zaxscd", false);
+
+  const char* in_args4[] = {
+      "testbin",
+      "-string_flag",
+      "--int_flag",
+  };
+  TestParse(in_args4, 1, 1.1, "--int_flag", false);
+
+  const char* in_args5[] = {
+      "testbin",
+      "--string_flag",
+      "--no_a_flag=11",
+  };
+  TestParse(in_args5, 1, 1.1, "--no_a_flag=11", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidBoolArg) {
+  const char* in_args1[] = {
+      "testbin",
+      "--bool_flag",
+  };
+  TestParse(in_args1, 1, 1.1, "a", true);
+
+  const char* in_args2[] = {
+      "testbin",
+      "--nobool_flag",
+  };
+  TestParse(in_args2, 1, 1.1, "a", false);
+
+  const char* in_args3[] = {
+      "testbin",
+      "--bool_flag=true",
+  };
+  TestParse(in_args3, 1, 1.1, "a", true);
+
+  const char* in_args4[] = {
+      "testbin",
+      "-bool_flag=false",
+  };
+  TestParse(in_args4, 1, 1.1, "a", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidUDTArg) {
+  const char* in_args1[] = {
+      "testbin",
+      "--udt_flag=A",
+  };
+  InvokeParse(in_args1);
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 1);
+
+  const char* in_args2[] = {"testbin", "--udt_flag", "AAA"};
+  InvokeParse(in_args2);
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 10);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidMultipleArg) {
+  const char* in_args1[] = {
+      "testbin",           "--bool_flag",       "--int_flag=2",
+      "--double_flag=0.1", "--string_flag=asd",
+  };
+  TestParse(in_args1, 2, 0.1, "asd", true);
+
+  const char* in_args2[] = {
+      "testbin", "--string_flag=", "--nobool_flag", "--int_flag",
+      "-011",    "--double_flag",  "-1e-2",
+  };
+  TestParse(in_args2, -11, -0.01, "", false);
+
+  const char* in_args3[] = {
+      "testbin",          "--int_flag",         "-0", "--string_flag", "\"\"",
+      "--bool_flag=true", "--double_flag=1e18",
+  };
+  TestParse(in_args3, 0, 1e18, "\"\"", true);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestPositionalArgs) {
+  const char* in_args1[] = {
+      "testbin",
+      "p1",
+      "p2",
+  };
+  TestParse(in_args1, 1, 1.1, "a", false, 2);
+
+  auto out_args1 = InvokeParse(in_args1);
+
+  EXPECT_STREQ(out_args1[1], "p1");
+  EXPECT_STREQ(out_args1[2], "p2");
+
+  const char* in_args2[] = {
+      "testbin",
+      "--int_flag=2",
+      "p1",
+  };
+  TestParse(in_args2, 2, 1.1, "a", false, 1);
+
+  auto out_args2 = InvokeParse(in_args2);
+
+  EXPECT_STREQ(out_args2[1], "p1");
+
+  const char* in_args3[] = {"testbin", "p1",          "--int_flag=3",
+                            "p2",      "--bool_flag", "true"};
+  TestParse(in_args3, 3, 1.1, "a", true, 3);
+
+  auto out_args3 = InvokeParse(in_args3);
+
+  EXPECT_STREQ(out_args3[1], "p1");
+  EXPECT_STREQ(out_args3[2], "p2");
+  EXPECT_STREQ(out_args3[3], "true");
+
+  const char* in_args4[] = {
+      "testbin",
+      "--",
+      "p1",
+      "p2",
+  };
+  TestParse(in_args4, 3, 1.1, "a", true, 2);
+
+  auto out_args4 = InvokeParse(in_args4);
+
+  EXPECT_STREQ(out_args4[1], "p1");
+  EXPECT_STREQ(out_args4[2], "p2");
+
+  const char* in_args5[] = {
+      "testbin", "p1", "--int_flag=4", "--", "--bool_flag", "false", "p2",
+  };
+  TestParse(in_args5, 4, 1.1, "a", true, 4);
+
+  auto out_args5 = InvokeParse(in_args5);
+
+  EXPECT_STREQ(out_args5[1], "p1");
+  EXPECT_STREQ(out_args5[2], "--bool_flag");
+  EXPECT_STREQ(out_args5[3], "false");
+  EXPECT_STREQ(out_args5[4], "p2");
+}
+
+// --------------------------------------------------------------------
+
+using ParseDeathTest = ParseTest;
+
+TEST_F(ParseDeathTest, TestUndefinedArg) {
+  const char* in_args1[] = {
+      "testbin",
+      "--undefined_flag",
+  };
+  EXPECT_DEATH(InvokeParse(in_args1),
+               "Unknown command line flag 'undefined_flag'");
+
+  const char* in_args2[] = {
+      "testbin",
+      "--noprefixed_flag",
+  };
+  EXPECT_DEATH(InvokeParse(in_args2),
+               "Unknown command line flag 'noprefixed_flag'");
+
+  const char* in_args3[] = {
+      "testbin",
+      "--Int_flag=1",
+  };
+  EXPECT_DEATH(InvokeParse(in_args3), "Unknown command line flag 'Int_flag'");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestInvalidBoolFlagFormat) {
+  const char* in_args1[] = {
+      "testbin",
+      "--bool_flag=",
+  };
+  EXPECT_DEATH(
+      InvokeParse(in_args1),
+      "Missing the value after assignment for the boolean flag 'bool_flag'");
+
+  const char* in_args2[] = {
+      "testbin",
+      "--nobool_flag=true",
+  };
+  EXPECT_DEATH(InvokeParse(in_args2),
+               "Negative form with assignment is not valid for the boolean "
+               "flag 'bool_flag'");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestInvalidNonBoolFlagFormat) {
+  const char* in_args1[] = {
+      "testbin",
+      "--nostring_flag",
+  };
+  EXPECT_DEATH(InvokeParse(in_args1),
+               "Negative form is not valid for the flag 'string_flag'");
+
+  const char* in_args2[] = {
+      "testbin",
+      "--int_flag",
+  };
+  EXPECT_DEATH(InvokeParse(in_args2),
+               "Missing the value for the flag 'int_flag'");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestInvalidUDTFlagFormat) {
+  const char* in_args1[] = {
+      "testbin",
+      "--udt_flag=1",
+  };
+  EXPECT_DEATH(InvokeParse(in_args1),
+               "Illegal value '1' specified for flag 'udt_flag'; Use values A, "
+               "AAA instead");
+
+  const char* in_args2[] = {
+      "testbin",
+      "--udt_flag",
+      "AA",
+  };
+  EXPECT_DEATH(InvokeParse(in_args2),
+               "Illegal value 'AA' specified for flag 'udt_flag'; Use values "
+               "A, AAA instead");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestLegacyFlags) {
+  const char* in_args1[] = {
+      "testbin",
+      "--legacy_int=11",
+  };
+  TestParse(in_args1, 1, 1.1, "a", false);
+
+  const char* in_args2[] = {
+      "testbin",
+      "--legacy_bool",
+  };
+  TestParse(in_args2, 1, 1.1, "a", false);
+
+  const char* in_args3[] = {
+      "testbin",       "--legacy_int", "22",           "--int_flag=2",
+      "--legacy_bool", "true",         "--legacy_str", "--string_flag=qwe",
+  };
+  TestParse(in_args3, 2, 1.1, "a", false, 1);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestSimpleValidFlagfile) {
+  std::string flagfile_flag;
+
+  const char* in_args1[] = {
+      "testbin",
+      GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
+                      &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),
+  };
+  TestParse(in_args2, 100, 0.1, "q2w2  ", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidMultiFlagfile) {
+  std::string flagfile_flag;
+
+  const char* in_args1[] = {
+      "testbin",
+      GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
+                       {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
+                      &flagfile_flag),
+  };
+  TestParse(in_args1, -1, 0.1, "q2w2  ", true);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) {
+  std::string flagfile_flag;
+
+  const char* in_args1[] = {
+      "testbin", "--int_flag=3",
+      GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
+                      &flagfile_flag),
+      "-double_flag=0.2"};
+  TestParse(in_args1, -1, 0.2, "q2w2  ", true);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestFlagfileInFlagfile) {
+  std::string flagfile_flag;
+
+  constexpr const char* const ff3_data[] = {
+      "--flagfile=$0/parse_test.ff1",
+      "--flagfile=$0/parse_test.ff2",
+  };
+
+  const char* in_args1[] = {
+      "testbin",
+      GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}},
+                      &flagfile_flag),
+  };
+  TestParse(in_args1, 100, 0.1, "q2w2  ", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
+  std::string flagfile_flag;
+
+  constexpr const char* const ff4_data[] = {
+    "--unknown_flag=10"
+  };
+
+  const char* in_args1[] = {
+      "testbin",
+      GetFlagfileFlag({{"parse_test.ff4",
+                        absl::MakeConstSpan(ff4_data)}}, &flagfile_flag),
+  };
+  EXPECT_DEATH(InvokeParse(in_args1),
+               "Unknown command line flag 'unknown_flag'");
+
+  constexpr const char* const ff5_data[] = {
+    "--int_flag 10",
+  };
+
+  const char* in_args2[] = {
+      "testbin",
+      GetFlagfileFlag({{"parse_test.ff5",
+                        absl::MakeConstSpan(ff5_data)}}, &flagfile_flag),
+  };
+  EXPECT_DEATH(InvokeParse(in_args2),
+               "Unknown command line flag 'int_flag 10'");
+
+  constexpr const char* const ff6_data[] = {
+      "--int_flag=10", "--", "arg1", "arg2", "arg3",
+  };
+
+  const char* in_args3[] = {
+      "testbin",
+      GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}},
+                      &flagfile_flag),
+  };
+  EXPECT_DEATH(InvokeParse(in_args3),
+               "Flagfile can't contain position arguments or --");
+
+  const char* in_args4[] = {
+      "testbin",
+      "--flagfile=invalid_flag_file",
+  };
+  EXPECT_DEATH(InvokeParse(in_args4), "Can't open flagfile invalid_flag_file");
+
+  constexpr const char* const ff7_data[] = {
+      "--int_flag=10",
+      "*bin*",
+      "--str_flag=aqsw",
+  };
+
+  const char* in_args5[] = {
+      "testbin",
+      GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}},
+                      &flagfile_flag),
+  };
+  EXPECT_DEATH(InvokeParse(in_args5),
+               "Unexpected line in the flagfile .*: \\*bin\\*");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestReadingRequiredFlagsFromEnv) {
+  const char* in_args1[] = {"testbin",
+                            "--fromenv=int_flag,bool_flag,string_flag"};
+
+  ScopedSetEnv set_int_flag("FLAGS_int_flag", "33");
+  ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "True");
+  ScopedSetEnv set_string_flag("FLAGS_string_flag", "AQ12");
+
+  TestParse(in_args1, 33, 1.1, "AQ12", true);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestReadingUnsetRequiredFlagsFromEnv) {
+  const char* in_args1[] = {"testbin", "--fromenv=int_flag"};
+
+  EXPECT_DEATH(InvokeParse(in_args1),
+               "FLAGS_int_flag not found in environment");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestRecursiveFlagsFromEnv) {
+  const char* in_args1[] = {"testbin", "--fromenv=tryfromenv"};
+
+  ScopedSetEnv set_tryfromenv("FLAGS_tryfromenv", "int_flag");
+
+  EXPECT_DEATH(InvokeParse(in_args1), "Infinite recursion on flag tryfromenv");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestReadingOptionalFlagsFromEnv) {
+  const char* in_args1[] = {
+      "testbin", "--tryfromenv=int_flag,bool_flag,string_flag,other_flag"};
+
+  ScopedSetEnv set_int_flag("FLAGS_int_flag", "17");
+  ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "Y");
+
+  TestParse(in_args1, 17, 1.1, "a", true);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestReadingFlagsFromEnvMoxedWithRegularFlags) {
+  const char* in_args1[] = {
+      "testbin",
+      "--bool_flag=T",
+      "--tryfromenv=int_flag,bool_flag",
+      "--int_flag=-21",
+  };
+
+  ScopedSetEnv set_int_flag("FLAGS_int_flag", "-15");
+  ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "F");
+
+  TestParse(in_args1, -21, 1.1, "a", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestKeepParsedArgs) {
+  const char* in_args1[] = {
+      "testbin",        "arg1", "--bool_flag",
+      "--int_flag=211", "arg2", "--double_flag=1.1",
+      "--string_flag",  "asd",  "--",
+      "arg3",           "arg4",
+  };
+
+  auto out_args1 = InvokeParse(in_args1);
+
+  EXPECT_THAT(
+      out_args1,
+      ElementsAreArray({absl::string_view("testbin"), absl::string_view("arg1"),
+                        absl::string_view("arg2"), absl::string_view("arg3"),
+                        absl::string_view("arg4")}));
+
+  auto out_args2 = flags::ParseCommandLineImpl(
+      11, const_cast<char**>(in_args1), flags::ArgvListAction::kKeepParsedArgs,
+      flags::UsageFlagsAction::kHandleUsage,
+      flags::OnUndefinedFlag::kAbortIfUndefined);
+
+  EXPECT_THAT(
+      out_args2,
+      ElementsAreArray({absl::string_view("testbin"),
+                        absl::string_view("--bool_flag"),
+                        absl::string_view("--int_flag=211"),
+                        absl::string_view("--double_flag=1.1"),
+                        absl::string_view("--string_flag"),
+                        absl::string_view("asd"), absl::string_view("--"),
+                        absl::string_view("arg1"), absl::string_view("arg2"),
+                        absl::string_view("arg3"), absl::string_view("arg4")}));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestIgnoreUndefinedFlags) {
+  const char* in_args1[] = {
+      "testbin",
+      "arg1",
+      "--undef_flag=aa",
+      "--int_flag=21",
+  };
+
+  auto out_args1 = flags::ParseCommandLineImpl(
+      4, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs,
+      flags::UsageFlagsAction::kHandleUsage,
+      flags::OnUndefinedFlag::kIgnoreUndefined);
+
+  EXPECT_THAT(out_args1, ElementsAreArray({absl::string_view("testbin"),
+                                           absl::string_view("arg1")}));
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 21);
+
+  const char* in_args2[] = {
+      "testbin",
+      "arg1",
+      "--undef_flag=aa",
+      "--string_flag=AA",
+  };
+
+  auto out_args2 = flags::ParseCommandLineImpl(
+      4, const_cast<char**>(in_args2), flags::ArgvListAction::kKeepParsedArgs,
+      flags::UsageFlagsAction::kHandleUsage,
+      flags::OnUndefinedFlag::kIgnoreUndefined);
+
+  EXPECT_THAT(
+      out_args2,
+      ElementsAreArray(
+          {absl::string_view("testbin"), absl::string_view("--undef_flag=aa"),
+           absl::string_view("--string_flag=AA"), absl::string_view("arg1")}));
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "AA");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestHelpFlagHandling) {
+  const char* in_args1[] = {
+      "testbin",
+      "--help",
+  };
+
+  EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(1), "");
+
+  const char* in_args2[] = {
+      "testbin",
+      "--help",
+      "--int_flag=3",
+  };
+
+  auto out_args2 = flags::ParseCommandLineImpl(
+      3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs,
+      flags::UsageFlagsAction::kIgnoreUsage,
+      flags::OnUndefinedFlag::kAbortIfUndefined);
+
+  EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
+}
+
+}  // namespace
diff --git a/absl/flags/usage_config.cc b/absl/flags/usage_config.cc
new file mode 100644
index 000000000000..d34ecfc82c7b
--- /dev/null
+++ b/absl/flags/usage_config.cc
@@ -0,0 +1,152 @@
+//
+//  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/usage_config.h"
+
+#include <iostream>
+#include <memory>
+
+#include "absl/base/attributes.h"
+#include "absl/flags/internal/path_util.h"
+#include "absl/flags/internal/program_name.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/strip.h"
+#include "absl/synchronization/mutex.h"
+
+extern "C" {
+
+// Additional report of fatal usage error message before we std::exit. Error is
+// fatal if is_fatal argument to ReportUsageError is true.
+ABSL_ATTRIBUTE_WEAK void AbslInternalReportFatalUsageError(absl::string_view) {}
+
+}  // extern "C"
+
+namespace absl {
+namespace flags_internal {
+
+namespace {
+
+// --------------------------------------------------------------------
+// Returns true if flags defined in the filename should be reported with
+// -helpshort flag.
+
+bool ContainsHelpshortFlags(absl::string_view filename) {
+  // By default we only want flags in binary's main. We expect the main
+  // routine to reside in <program>.cc or <program>-main.cc or
+  // <program>_main.cc, where the <program> is the name of the binary.
+  auto suffix = flags_internal::Basename(filename);
+  if (!absl::ConsumePrefix(&suffix,
+                           flags_internal::ShortProgramInvocationName()))
+    return false;
+  return absl::StartsWith(suffix, ".") || absl::StartsWith(suffix, "-main.") ||
+         absl::StartsWith(suffix, "_main.");
+}
+
+// --------------------------------------------------------------------
+// Returns true if flags defined in the filename should be reported with
+// -helppackage flag.
+
+bool ContainsHelppackageFlags(absl::string_view filename) {
+  // TODO(rogeeff): implement properly when registry is available.
+  return ContainsHelpshortFlags(filename);
+}
+
+// --------------------------------------------------------------------
+// Generates program version information into supplied output.
+
+std::string VersionString() {
+  std::string version_str(flags_internal::ShortProgramInvocationName());
+
+  version_str += "\n";
+
+#if !defined(NDEBUG)
+  version_str += "Debug build (NDEBUG not #defined)\n";
+#endif
+
+  return version_str;
+}
+
+// --------------------------------------------------------------------
+// Normalizes the filename specific to the build system/filesystem used.
+
+std::string NormalizeFilename(absl::string_view filename) {
+  // Skip any leading slashes
+  auto pos = filename.find_first_not_of("\\/");
+  if (pos == absl::string_view::npos) return "";
+
+  filename.remove_prefix(pos);
+  return std::string(filename);
+}
+
+// --------------------------------------------------------------------
+
+ABSL_CONST_INIT absl::Mutex custom_usage_config_guard(absl::kConstInit);
+ABSL_CONST_INIT FlagsUsageConfig* custom_usage_config
+    GUARDED_BY(custom_usage_config_guard) = nullptr;
+
+}  // namespace
+
+FlagsUsageConfig GetUsageConfig() {
+  absl::MutexLock l(&custom_usage_config_guard);
+
+  if (custom_usage_config) return *custom_usage_config;
+
+  FlagsUsageConfig default_config;
+  default_config.contains_helpshort_flags = &ContainsHelpshortFlags;
+  default_config.contains_help_flags = &ContainsHelppackageFlags;
+  default_config.contains_helppackage_flags = &ContainsHelppackageFlags;
+  default_config.version_string = &VersionString;
+  default_config.normalize_filename = &NormalizeFilename;
+
+  return default_config;
+}
+
+void ReportUsageError(absl::string_view msg, bool is_fatal) {
+  std::cerr << "ERROR: " << msg << std::endl;
+
+  if (is_fatal) {
+    AbslInternalReportFatalUsageError(msg);
+  }
+}
+
+}  // namespace flags_internal
+
+void SetFlagsUsageConfig(FlagsUsageConfig usage_config) {
+  absl::MutexLock l(&flags_internal::custom_usage_config_guard);
+
+  if (!usage_config.contains_helpshort_flags)
+    usage_config.contains_helpshort_flags =
+        flags_internal::ContainsHelpshortFlags;
+
+  if (!usage_config.contains_help_flags)
+    usage_config.contains_help_flags = flags_internal::ContainsHelppackageFlags;
+
+  if (!usage_config.contains_helppackage_flags)
+    usage_config.contains_helppackage_flags =
+        flags_internal::ContainsHelppackageFlags;
+
+  if (!usage_config.version_string)
+    usage_config.version_string = flags_internal::VersionString;
+
+  if (!usage_config.normalize_filename)
+    usage_config.normalize_filename = flags_internal::NormalizeFilename;
+
+  if (flags_internal::custom_usage_config)
+    *flags_internal::custom_usage_config = usage_config;
+  else
+    flags_internal::custom_usage_config = new FlagsUsageConfig(usage_config);
+}
+
+}  // namespace absl
diff --git a/absl/flags/usage_config.h b/absl/flags/usage_config.h
new file mode 100644
index 000000000000..ee5016a9ee30
--- /dev/null
+++ b/absl/flags/usage_config.h
@@ -0,0 +1,131 @@
+//
+//  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.
+//
+// -----------------------------------------------------------------------------
+// File: usage_config.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the main usage reporting configuration interfaces and
+// documents Abseil's supported built-in usage flags. If these flags are found
+// when parsing a command-line, Abseil will exit the program and display
+// appropriate help messages.
+#ifndef ABSL_FLAGS_USAGE_CONFIG_H_
+#define ABSL_FLAGS_USAGE_CONFIG_H_
+
+#include <functional>
+#include <string>
+
+#include "absl/strings/string_view.h"
+
+// -----------------------------------------------------------------------------
+// Built-in Usage Flags
+// -----------------------------------------------------------------------------
+//
+// Abseil supports the following built-in usage flags. When passed, these flags
+// exit the program and :
+//
+// * --help
+//     Shows help on important flags for this binary
+// * --helpfull
+//     Shows help on all flags
+// * --helpshort
+//     Shows help on only the main module for this program
+// * --helppackage
+//     Shows help on all modules in the main package
+// * --version
+//     Shows the version and build info for this binary and exits
+// * --only_check_args
+//     Exits after checking all flags
+// * --helpon
+//     Shows help on the modules named by this flag value
+// * --helpmatch
+//     Shows help on modules whose name contains the specified substring
+
+namespace absl {
+
+namespace flags_internal {
+using FlagKindFilter = std::function<bool (absl::string_view)>;
+}  // namespace flags_internal
+
+// FlagsUsageConfig
+//
+// This structure contains the collection of callbacks for changing the behavior
+// of the usage reporting routines in Abseil Flags.
+struct FlagsUsageConfig {
+  // Returns true if flags defined in the given source code file should be
+  // reported with --helpshort flag. For example, if the file
+  // "path/to/my/code.cc" defines the flag "--my_flag", and
+  // contains_helpshort_flags("path/to/my/code.cc") returns true, invoking the
+  // program with --helpshort will include information about --my_flag in the
+  // program output.
+  flags_internal::FlagKindFilter contains_helpshort_flags;
+
+  // Returns true if flags defined in the filename should be reported with
+  // --help flag. For example, if the file
+  // "path/to/my/code.cc" defines the flag "--my_flag", and
+  // contains_help_flags("path/to/my/code.cc") returns true, invoking the
+  // program with --help will include information about --my_flag in the
+  // program output.
+  flags_internal::FlagKindFilter contains_help_flags;
+
+  // Returns true if flags defined in the filename should be reported with
+  // --helppackage flag. For example, if the file
+  // "path/to/my/code.cc" defines the flag "--my_flag", and
+  // contains_helppackage_flags("path/to/my/code.cc") returns true, invoking the
+  // program with --helppackage will include information about --my_flag in the
+  // program output.
+  flags_internal::FlagKindFilter contains_helppackage_flags;
+
+  // Generates std::string containing program version. This is the std::string reported
+  // when user specifies --version in a command line.
+  std::function<std::string()> version_string;
+
+  // Normalizes the filename specific to the build system/filesystem used. This
+  // routine is used when we report the information about the flag definition
+  // location. For instance, if your build resides at some location you do not
+  // want to expose in the usage output, you can trim it to show only relevant
+  // part.
+  // For example:
+  //   normalize_filename("/my_company/some_long_path/src/project/file.cc")
+  // might produce
+  //   "project/file.cc".
+  std::function<std::string (absl::string_view)> normalize_filename;
+};
+
+// SetFlagsUsageConfig()
+//
+// Sets the usage reporting configuration callbacks. If any of the callbacks are
+// not set in usage_config instance, then the default value of the callback is
+// used.
+void SetFlagsUsageConfig(FlagsUsageConfig usage_config);
+
+namespace flags_internal {
+
+FlagsUsageConfig GetUsageConfig();
+
+void ReportUsageError(absl::string_view msg, bool is_fatal);
+
+}  // namespace flags_internal
+}  // namespace absl
+
+extern "C" {
+
+// Additional report of fatal usage error message before we std::exit. Error is
+// fatal if is_fatal argument to ReportUsageError is true.
+void AbslInternalReportFatalUsageError(absl::string_view);
+
+}  // extern "C"
+
+#endif  // ABSL_FLAGS_USAGE_CONFIG_H_
diff --git a/absl/flags/usage_config_test.cc b/absl/flags/usage_config_test.cc
new file mode 100644
index 000000000000..3bde13af8f84
--- /dev/null
+++ b/absl/flags/usage_config_test.cc
@@ -0,0 +1,198 @@
+//
+//  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/usage_config.h"
+
+#include "gtest/gtest.h"
+#include "absl/flags/internal/path_util.h"
+#include "absl/flags/internal/program_name.h"
+#include "absl/strings/match.h"
+
+namespace {
+
+class FlagsUsageConfigTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    // Install Default config for the use on this unit test.
+    // Binary may install a custom config before tests are run.
+    absl::FlagsUsageConfig default_config;
+    absl::SetFlagsUsageConfig(default_config);
+  }
+};
+
+namespace flags = absl::flags_internal;
+
+bool TstContainsHelpshortFlags(absl::string_view f) {
+  return absl::StartsWith(flags::Basename(f), "progname.");
+}
+
+bool TstContainsHelppackageFlags(absl::string_view f) {
+  return absl::EndsWith(flags::Package(f), "aaa/");
+}
+
+bool TstContainsHelpFlags(absl::string_view f) {
+  return absl::EndsWith(flags::Package(f), "zzz/");
+}
+
+std::string TstVersionString() { return "program 1.0.0"; }
+
+std::string TstNormalizeFilename(absl::string_view filename) {
+  return std::string(filename.substr(2));
+}
+
+void TstReportUsageMessage(absl::string_view msg) {}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestGetSetFlagsUsageConfig) {
+  EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags);
+  EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags);
+  EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags);
+  EXPECT_TRUE(flags::GetUsageConfig().version_string);
+  EXPECT_TRUE(flags::GetUsageConfig().normalize_filename);
+
+  absl::FlagsUsageConfig empty_config;
+  empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags;
+  empty_config.contains_help_flags = &TstContainsHelpFlags;
+  empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags;
+  empty_config.version_string = &TstVersionString;
+  empty_config.normalize_filename = &TstNormalizeFilename;
+  absl::SetFlagsUsageConfig(empty_config);
+
+  EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags);
+  EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags);
+  EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags);
+  EXPECT_TRUE(flags::GetUsageConfig().version_string);
+  EXPECT_TRUE(flags::GetUsageConfig().normalize_filename);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestContainsHelpshortFlags) {
+  flags::SetProgramInvocationName("usage_config_test");
+
+  auto config = flags::GetUsageConfig();
+  EXPECT_TRUE(config.contains_helpshort_flags("adir/cd/usage_config_test.cc"));
+  EXPECT_TRUE(
+      config.contains_helpshort_flags("aaaa/usage_config_test-main.cc"));
+  EXPECT_TRUE(config.contains_helpshort_flags("abc/usage_config_test_main.cc"));
+  EXPECT_FALSE(config.contains_helpshort_flags("usage_config_main.cc"));
+
+  absl::FlagsUsageConfig empty_config;
+  empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags;
+  absl::SetFlagsUsageConfig(empty_config);
+
+  EXPECT_TRUE(
+      flags::GetUsageConfig().contains_helpshort_flags("aaa/progname.cpp"));
+  EXPECT_FALSE(
+      flags::GetUsageConfig().contains_helpshort_flags("aaa/progmane.cpp"));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestContainsHelpFlags) {
+  flags::SetProgramInvocationName("usage_config_test");
+
+  auto config = flags::GetUsageConfig();
+  EXPECT_TRUE(config.contains_help_flags("zzz/usage_config_test.cc"));
+  EXPECT_TRUE(
+      config.contains_help_flags("bdir/a/zzz/usage_config_test-main.cc"));
+  EXPECT_TRUE(
+      config.contains_help_flags("//aqse/zzz/usage_config_test_main.cc"));
+  EXPECT_FALSE(config.contains_help_flags("zzz/aa/usage_config_main.cc"));
+
+  absl::FlagsUsageConfig empty_config;
+  empty_config.contains_help_flags = &TstContainsHelpFlags;
+  absl::SetFlagsUsageConfig(empty_config);
+
+  EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags("zzz/main-body.c"));
+  EXPECT_FALSE(
+      flags::GetUsageConfig().contains_help_flags("zzz/dir/main-body.c"));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestContainsHelppackageFlags) {
+  flags::SetProgramInvocationName("usage_config_test");
+
+  auto config = flags::GetUsageConfig();
+  EXPECT_TRUE(config.contains_helppackage_flags("aaa/usage_config_test.cc"));
+  EXPECT_TRUE(
+      config.contains_helppackage_flags("bbdir/aaa/usage_config_test-main.cc"));
+  EXPECT_TRUE(config.contains_helppackage_flags(
+      "//aqswde/aaa/usage_config_test_main.cc"));
+  EXPECT_FALSE(config.contains_helppackage_flags("aadir/usage_config_main.cc"));
+
+  absl::FlagsUsageConfig empty_config;
+  empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags;
+  absl::SetFlagsUsageConfig(empty_config);
+
+  EXPECT_TRUE(
+      flags::GetUsageConfig().contains_helppackage_flags("aaa/main-body.c"));
+  EXPECT_FALSE(
+      flags::GetUsageConfig().contains_helppackage_flags("aadir/main-body.c"));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestVersionString) {
+  flags::SetProgramInvocationName("usage_config_test");
+
+#ifdef NDEBUG
+  std::string expected_output = "usage_config_test\n";
+#else
+  std::string expected_output =
+      "usage_config_test\nDebug build (NDEBUG not #defined)\n";
+#endif
+
+  EXPECT_EQ(flags::GetUsageConfig().version_string(), expected_output);
+
+  absl::FlagsUsageConfig empty_config;
+  empty_config.version_string = &TstVersionString;
+  absl::SetFlagsUsageConfig(empty_config);
+
+  EXPECT_EQ(flags::GetUsageConfig().version_string(), "program 1.0.0");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestNormalizeFilename) {
+  // This tests the default implementation.
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a/a.cc");
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/a/a.cc"), "a/a.cc");
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("///a/a.cc"), "a/a.cc");
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/"), "");
+
+  // This tests that the custom implementation is called.
+  absl::FlagsUsageConfig empty_config;
+  empty_config.normalize_filename = &TstNormalizeFilename;
+  absl::SetFlagsUsageConfig(empty_config);
+
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a.cc");
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("aaa/a.cc"), "a/a.cc");
+
+  // This tests that the default implementation is called.
+  empty_config.normalize_filename = nullptr;
+  absl::SetFlagsUsageConfig(empty_config);
+
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a/a.cc");
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/a/a.cc"), "a/a.cc");
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("///a/a.cc"), "a/a.cc");
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("\\a\\a.cc"), "a\\a.cc");
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("//"), "");
+  EXPECT_EQ(flags::GetUsageConfig().normalize_filename("\\\\"), "");
+}
+
+}  // namespace