summaryrefslogtreecommitdiff
path: root/absl/flags
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2020-06-03 14:03:13 -0700
committerGravatar Gennadiy Rozental <rogeeff@google.com>2020-06-03 18:19:47 -0400
commit1d31b5c365e975d3c8a8f90492c3d9de35ef024f (patch)
treefbc8093e8aad757b8790fb2688c0e4694e082fa4 /absl/flags
parentda3a87690c56f965705b6a233d25ba5a3294067c (diff)
Export of internal Abseil changes
-- 9e8b4a286d70df9487bff080816bd07ae38af5f8 by Evan Brown <ezb@google.com>: Add btree_node::transfer_n/transfer_n_backward and replace usage of uninitialized_move_n and value_destroy_n. PiperOrigin-RevId: 314600027 -- 6c452aa1ee7e46ab941ba7d1fa636da8ea3d7370 by Laramie Leavitt <lar@google.com>: Remove the MockingBitGenBase base class in favor of type-erasure in BitGenRef. In Abseil random, mocking was split across two different classes, MockingBitGenBase and MockingBitGen. This split existed because Google Mock is a test-only library that we don't link into production, so MockingBitGenBase provided a low-overhead scaffold used to lookup mocks when in test code, but which is unused in production code. That has been replaced by type-erasure which looks for a method named CallImpl with the correct signature. Weaken the coupling between MockingBitGen, DistributionCaller, and MockOverloadSet. Rename CallImpl to InvokeMock() Previously, the implementation of DistributionCaller was also split across different files using explicit instantiation of the DistributionCaller struct and some details in the Mocking classes. Now Distribution caller uses the presence of the InvokeMock() method to choose whether to use the mockable call path or the default call path. PiperOrigin-RevId: 314584095 -- 07853c47dc98698d67d65a3b9b662a65ab9def0a by Abseil Team <absl-team@google.com>: Add PC / backtrace / symbolization support for Apple platforms. Full backtrace support requires iOS 9+ PiperOrigin-RevId: 314415072 -- 43889f17a132b31f6558c6482721cbbc776128fd by Gennadiy Rozental <rogeeff@google.com>: Consolidate all reflection interface in the new module 'reflection' and expose interface to locate reflection handle by name. PiperOrigin-RevId: 314390358 GitOrigin-RevId: 9e8b4a286d70df9487bff080816bd07ae38af5f8 Change-Id: I8e0910437740cf9ea9da5000adddfcef127e1158
Diffstat (limited to 'absl/flags')
-rw-r--r--absl/flags/BUILD.bazel31
-rw-r--r--absl/flags/CMakeLists.txt33
-rw-r--r--absl/flags/commandlineflag_test.cc31
-rw-r--r--absl/flags/flag_test.cc43
-rw-r--r--absl/flags/internal/registry.h13
-rw-r--r--absl/flags/internal/type_erased.cc86
-rw-r--r--absl/flags/internal/type_erased.h80
-rw-r--r--absl/flags/internal/type_erased_test.cc156
-rw-r--r--absl/flags/internal/usage_test.cc12
-rw-r--r--absl/flags/parse.cc6
-rw-r--r--absl/flags/parse_test.cc2
-rw-r--r--absl/flags/reflection.cc (renamed from absl/flags/internal/registry.cc)218
-rw-r--r--absl/flags/reflection.h47
-rw-r--r--absl/flags/reflection_test.cc60
14 files changed, 278 insertions, 540 deletions
diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel
index 6ffd07ce..37c9a105 100644
--- a/absl/flags/BUILD.bazel
+++ b/absl/flags/BUILD.bazel
@@ -159,14 +159,13 @@ cc_library(
)
cc_library(
- name = "registry",
+ name = "reflection",
srcs = [
- "internal/registry.cc",
- "internal/type_erased.cc",
+ "reflection.cc",
],
hdrs = [
"internal/registry.h",
- "internal/type_erased.h",
+ "reflection.h",
],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -180,7 +179,6 @@ cc_library(
":private_handle_accessor",
"//absl/base:config",
"//absl/base:core_headers",
- "//absl/base:raw_logging_internal",
"//absl/strings",
"//absl/synchronization",
],
@@ -202,7 +200,7 @@ cc_library(
":commandlineflag_internal",
":config",
":marshalling",
- ":registry",
+ ":reflection",
"//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
@@ -228,7 +226,7 @@ cc_library(
deps = [
":config",
":flag_internal",
- ":registry",
+ ":reflection",
"//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
@@ -257,7 +255,7 @@ cc_library(
":path_util",
":private_handle_accessor",
":program_name",
- ":registry",
+ ":reflection",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/strings",
@@ -300,7 +298,7 @@ cc_library(
":flag_internal",
":private_handle_accessor",
":program_name",
- ":registry",
+ ":reflection",
":usage",
":usage_internal",
"//absl/base:config",
@@ -327,7 +325,7 @@ cc_test(
":config",
":flag",
":private_handle_accessor",
- ":registry",
+ ":reflection",
"//absl/memory",
"//absl/strings",
"@com_google_googletest//:gtest_main",
@@ -362,7 +360,7 @@ cc_test(
":flag",
":flag_internal",
":marshalling",
- ":registry",
+ ":reflection",
"//absl/base:core_headers",
"//absl/base:malloc_internal",
"//absl/strings",
@@ -415,7 +413,7 @@ cc_test(
deps = [
":flag",
":parse",
- ":registry",
+ ":reflection",
"//absl/base:raw_logging_internal",
"//absl/base:scoped_set_env",
"//absl/strings",
@@ -454,17 +452,18 @@ cc_test(
)
cc_test(
- name = "type_erased_test",
+ name = "reflection_test",
size = "small",
srcs = [
- "internal/type_erased_test.cc",
+ "reflection_test.cc",
],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":commandlineflag_internal",
":flag",
- ":registry",
+ ":marshalling",
+ ":reflection",
"//absl/memory",
"@com_google_googletest//:gtest_main",
],
@@ -501,7 +500,7 @@ cc_test(
":parse",
":path_util",
":program_name",
- ":registry",
+ ":reflection",
":usage",
":usage_internal",
"//absl/strings",
diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt
index 2dc7cf45..ef75db8e 100644
--- a/absl/flags/CMakeLists.txt
+++ b/absl/flags/CMakeLists.txt
@@ -144,16 +144,14 @@ absl_cc_library(
absl::strings
)
-# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
- flags_registry
+ flags_reflection
SRCS
- "internal/registry.cc"
- "internal/type_erased.cc"
+ "reflection.cc"
HDRS
+ "reflection.h"
"internal/registry.h"
- "internal/type_erased.h"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
@@ -161,10 +159,8 @@ absl_cc_library(
DEPS
absl::config
absl::flags_commandlineflag
- absl::flags_config
absl::flags_private_handle_accessor
- absl::core_headers
- absl::raw_logging_internal
+ absl::flags_config
absl::strings
absl::synchronization
)
@@ -187,7 +183,6 @@ absl_cc_library(
absl::flags_commandlineflag_internal
absl::flags_config
absl::flags_marshalling
- absl::flags_registry
absl::synchronization
absl::meta
absl::utility
@@ -211,7 +206,7 @@ absl_cc_library(
absl::flags_commandlineflag
absl::flags_config
absl::flags_internal
- absl::flags_registry
+ absl::flags_reflection
absl::base
absl::core_headers
absl::strings
@@ -238,7 +233,7 @@ absl_cc_library(
absl::flags_path_util
absl::flags_private_handle_accessor
absl::flags_program_name
- absl::flags_registry
+ absl::flags_reflection
absl::strings
absl::synchronization
)
@@ -284,7 +279,7 @@ absl_cc_library(
absl::flags_internal
absl::flags_private_handle_accessor
absl::flags_program_name
- absl::flags_registry
+ absl::flags_reflection
absl::flags_usage
absl::strings
absl::synchronization
@@ -306,7 +301,7 @@ absl_cc_test(
absl::flags_commandlineflag_internal
absl::flags_config
absl::flags_private_handle_accessor
- absl::flags_registry
+ absl::flags_reflection
absl::memory
absl::strings
gtest_main
@@ -338,7 +333,7 @@ absl_cc_test(
absl::flags_config
absl::flags_internal
absl::flags_marshalling
- absl::flags_registry
+ absl::flags_reflection
absl::strings
absl::time
gtest_main
@@ -366,7 +361,7 @@ absl_cc_test(
DEPS
absl::flags
absl::flags_parse
- absl::flags_registry
+ absl::flags_reflection
absl::raw_logging_internal
absl::scoped_set_env
absl::span
@@ -401,15 +396,15 @@ absl_cc_test(
absl_cc_test(
NAME
- flags_type_erased_test
+ flags_reflection_test
SRCS
- "internal/type_erased_test.cc"
+ "reflection_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::flags_commandlineflag_internal
absl::flags
- absl::flags_registry
+ absl::flags_reflection
absl::memory
absl::strings
gtest_main
@@ -443,7 +438,7 @@ absl_cc_test(
absl::flags_path_util
absl::flags_program_name
absl::flags_parse
- absl::flags_registry
+ absl::flags_reflection
absl::flags_usage
absl::strings
gtest
diff --git a/absl/flags/commandlineflag_test.cc b/absl/flags/commandlineflag_test.cc
index 570bbe2f..cc8eae91 100644
--- a/absl/flags/commandlineflag_test.cc
+++ b/absl/flags/commandlineflag_test.cc
@@ -22,7 +22,7 @@
#include "absl/flags/flag.h"
#include "absl/flags/internal/commandlineflag.h"
#include "absl/flags/internal/private_handle_accessor.h"
-#include "absl/flags/internal/registry.h"
+#include "absl/flags/reflection.h"
#include "absl/flags/usage_config.h"
#include "absl/memory/memory.h"
#include "absl/strings/match.h"
@@ -64,7 +64,7 @@ class CommandLineFlagTest : public testing::Test {
};
TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
- auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
ASSERT_TRUE(flag_01);
EXPECT_EQ(flag_01->Name(), "int_flag");
@@ -77,7 +77,7 @@ TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
"absl/flags/commandlineflag_test.cc"))
<< flag_01->Filename();
- auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag");
ASSERT_TRUE(flag_02);
EXPECT_EQ(flag_02->Name(), "string_flag");
@@ -89,31 +89,20 @@ TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
EXPECT_TRUE(absl::EndsWith(flag_02->Filename(),
"absl/flags/commandlineflag_test.cc"))
<< flag_02->Filename();
-
- auto* flag_03 = flags::FindRetiredFlag("bool_retired_flag");
-
- ASSERT_TRUE(flag_03);
- EXPECT_EQ(flag_03->Name(), "bool_retired_flag");
- EXPECT_EQ(flag_03->Help(), "");
- EXPECT_TRUE(flag_03->IsRetired());
- EXPECT_TRUE(flag_03->IsOfType<bool>());
- EXPECT_TRUE(!flag_03->IsOfType<int>());
- EXPECT_TRUE(!flag_03->IsOfType<std::string>());
- EXPECT_EQ(flag_03->Filename(), "RETIRED");
}
// --------------------------------------------------------------------
TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
absl::SetFlag(&FLAGS_int_flag, 301);
- auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+ auto* flag_01 = absl::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");
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag");
ASSERT_TRUE(flag_02);
EXPECT_EQ(flag_02->CurrentValue(), "new_str_value");
@@ -125,7 +114,7 @@ TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
std::string err;
- auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
EXPECT_FALSE(
flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
@@ -173,7 +162,7 @@ TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
*flag_01, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'");
- auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag");
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
*flag_02, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
err));
@@ -189,14 +178,14 @@ TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {
std::string err;
- auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
*flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
err));
EXPECT_EQ(flag_01->DefaultValue(), "111");
- auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag");
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
*flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
@@ -209,7 +198,7 @@ TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {
TEST_F(CommandLineFlagTest, TestParseFromIfDefault) {
std::string err;
- auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
*flag_01, "22", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc
index 71661d39..0c88e24a 100644
--- a/absl/flags/flag_test.cc
+++ b/absl/flags/flag_test.cc
@@ -29,8 +29,8 @@
#include "absl/flags/config.h"
#include "absl/flags/declare.h"
#include "absl/flags/internal/flag.h"
-#include "absl/flags/internal/registry.h"
#include "absl/flags/marshalling.h"
+#include "absl/flags/reflection.h"
#include "absl/flags/usage_config.h"
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
@@ -555,29 +555,29 @@ TEST_F(FlagTest, TestGetSet) {
// --------------------------------------------------------------------
TEST_F(FlagTest, TestGetViaReflection) {
- auto* handle = flags::FindCommandLineFlag("test_flag_01");
+ auto* handle = absl::FindCommandLineFlag("test_flag_01");
EXPECT_EQ(*handle->TryGet<bool>(), true);
- handle = flags::FindCommandLineFlag("test_flag_02");
+ handle = absl::FindCommandLineFlag("test_flag_02");
EXPECT_EQ(*handle->TryGet<int>(), 1234);
- handle = flags::FindCommandLineFlag("test_flag_03");
+ handle = absl::FindCommandLineFlag("test_flag_03");
EXPECT_EQ(*handle->TryGet<int16_t>(), -34);
- handle = flags::FindCommandLineFlag("test_flag_04");
+ handle = absl::FindCommandLineFlag("test_flag_04");
EXPECT_EQ(*handle->TryGet<uint16_t>(), 189);
- handle = flags::FindCommandLineFlag("test_flag_05");
+ handle = absl::FindCommandLineFlag("test_flag_05");
EXPECT_EQ(*handle->TryGet<int32_t>(), 10765);
- handle = flags::FindCommandLineFlag("test_flag_06");
+ handle = absl::FindCommandLineFlag("test_flag_06");
EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000);
- handle = flags::FindCommandLineFlag("test_flag_07");
+ handle = absl::FindCommandLineFlag("test_flag_07");
EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567);
- handle = flags::FindCommandLineFlag("test_flag_08");
+ handle = absl::FindCommandLineFlag("test_flag_08");
EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543);
- handle = flags::FindCommandLineFlag("test_flag_09");
+ handle = absl::FindCommandLineFlag("test_flag_09");
EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55);
- handle = flags::FindCommandLineFlag("test_flag_10");
+ handle = absl::FindCommandLineFlag("test_flag_10");
EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f);
- handle = flags::FindCommandLineFlag("test_flag_11");
+ handle = absl::FindCommandLineFlag("test_flag_11");
EXPECT_EQ(*handle->TryGet<std::string>(), "");
- handle = flags::FindCommandLineFlag("test_flag_12");
+ handle = absl::FindCommandLineFlag("test_flag_12");
EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10));
}
@@ -815,14 +815,15 @@ ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
namespace {
TEST_F(FlagTest, TestRetiredFlagRegistration) {
- bool is_bool = false;
- EXPECT_TRUE(flags::IsRetiredFlag("old_bool_flag", &is_bool));
- EXPECT_TRUE(is_bool);
- EXPECT_TRUE(flags::IsRetiredFlag("old_int_flag", &is_bool));
- EXPECT_FALSE(is_bool);
- EXPECT_TRUE(flags::IsRetiredFlag("old_str_flag", &is_bool));
- EXPECT_FALSE(is_bool);
- EXPECT_FALSE(flags::IsRetiredFlag("some_other_flag", &is_bool));
+ auto* handle = absl::FindCommandLineFlag("old_bool_flag");
+ EXPECT_TRUE(handle->IsOfType<bool>());
+ EXPECT_TRUE(handle->IsRetired());
+ handle = absl::FindCommandLineFlag("old_int_flag");
+ EXPECT_TRUE(handle->IsOfType<int>());
+ EXPECT_TRUE(handle->IsRetired());
+ handle = absl::FindCommandLineFlag("old_str_flag");
+ EXPECT_TRUE(handle->IsOfType<std::string>());
+ EXPECT_TRUE(handle->IsRetired());
}
} // namespace
diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h
index d207c225..1e655a3e 100644
--- a/absl/flags/internal/registry.h
+++ b/absl/flags/internal/registry.h
@@ -28,10 +28,14 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace flags_internal {
+// TODO(rogeeff): remove this declaration
CommandLineFlag* FindCommandLineFlag(absl::string_view name);
-CommandLineFlag* FindRetiredFlag(absl::string_view name);
+
+namespace flags_internal {
+
+// TODO(rogeeff): remove this alias
+using absl::FindCommandLineFlag;
// Executes specified visitor for each non-retired flag in the registry.
// Requires the caller hold the registry lock.
@@ -85,11 +89,6 @@ inline bool RetiredFlag(const char* flag_name) {
return flags_internal::Retire(flag_name, base_internal::FastTypeId<T>());
}
-// If the flag is retired, returns true and indicates in |*type_is_bool|
-// whether the type of the retired flag is a bool.
-// Only to be called by code that needs to explicitly ignore retired flags.
-bool IsRetiredFlag(absl::string_view name, bool* type_is_bool);
-
//-----------------------------------------------------------------------------
// Saves the states (value, default value, whether the user has set
// the flag, registered validators, etc) of all flags, and restores
diff --git a/absl/flags/internal/type_erased.cc b/absl/flags/internal/type_erased.cc
deleted file mode 100644
index b2523b24..00000000
--- a/absl/flags/internal/type_erased.cc
+++ /dev/null
@@ -1,86 +0,0 @@
-//
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/flags/internal/type_erased.h"
-
-#include <assert.h>
-
-#include <string>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/flags/commandlineflag.h"
-#include "absl/flags/internal/private_handle_accessor.h"
-#include "absl/flags/internal/registry.h"
-#include "absl/flags/usage_config.h"
-#include "absl/strings/string_view.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace flags_internal {
-
-bool GetCommandLineOption(absl::string_view name, std::string* value) {
- if (name.empty()) return false;
- assert(value);
-
- CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
- if (flag == nullptr || flag->IsRetired()) {
- return false;
- }
-
- *value = flag->CurrentValue();
- return true;
-}
-
-bool SetCommandLineOption(absl::string_view name, absl::string_view value) {
- return SetCommandLineOptionWithMode(name, value,
- flags_internal::SET_FLAGS_VALUE);
-}
-
-bool SetCommandLineOptionWithMode(absl::string_view name,
- absl::string_view value,
- FlagSettingMode set_mode) {
- CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-
- if (!flag || flag->IsRetired()) return false;
-
- std::string error;
- if (!flags_internal::PrivateHandleAccessor::ParseFrom(
- *flag, value, set_mode, kProgrammaticChange, error)) {
- // Errors here are all of the form: the provided name was a recognized
- // flag, but the value was invalid (bad type, or validation failed).
- flags_internal::ReportUsageError(error, false);
- return false;
- }
-
- return true;
-}
-
-// --------------------------------------------------------------------
-
-bool IsValidFlagValue(absl::string_view name, absl::string_view value) {
- CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
-
- return flag != nullptr &&
- (flag->IsRetired() ||
- flags_internal::PrivateHandleAccessor::ValidateInputValue(*flag,
- value));
-}
-
-// --------------------------------------------------------------------
-
-} // namespace flags_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/absl/flags/internal/type_erased.h b/absl/flags/internal/type_erased.h
deleted file mode 100644
index 437a8c28..00000000
--- a/absl/flags/internal/type_erased.h
+++ /dev/null
@@ -1,80 +0,0 @@
-//
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
-#define ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
-
-#include <string>
-
-#include "absl/base/config.h"
-#include "absl/flags/commandlineflag.h"
-#include "absl/flags/internal/commandlineflag.h"
-#include "absl/flags/internal/registry.h"
-#include "absl/strings/string_view.h"
-
-// --------------------------------------------------------------------
-// Registry interfaces operating on type erased handles.
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace flags_internal {
-
-// If a flag named "name" exists, store its current value in *OUTPUT
-// and return true. Else return false without changing *OUTPUT.
-// Thread-safe.
-bool GetCommandLineOption(absl::string_view name, std::string* value);
-
-// Set the value of the flag named "name" to value. If successful,
-// returns true. If not successful (e.g., the flag was not found or
-// the value is not a valid value), returns false.
-// Thread-safe.
-bool SetCommandLineOption(absl::string_view name, absl::string_view value);
-
-bool SetCommandLineOptionWithMode(absl::string_view name,
- absl::string_view value,
- FlagSettingMode set_mode);
-
-//-----------------------------------------------------------------------------
-
-// Returns true iff all of the following conditions are true:
-// (a) "name" names a registered flag
-// (b) "value" can be parsed succesfully according to the type of the flag
-// (c) parsed value passes any validator associated with the flag
-bool IsValidFlagValue(absl::string_view name, absl::string_view value);
-
-//-----------------------------------------------------------------------------
-
-// If a flag with specified "name" exists and has type T, store
-// its current value in *dst and return true. Else return false
-// without touching *dst. T must obey all of the requirements for
-// types passed to DEFINE_FLAG.
-template <typename T>
-inline bool GetByName(absl::string_view name, T* dst) {
- CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
- if (!flag) return false;
-
- if (auto val = flag->TryGet<T>()) {
- *dst = *val;
- return true;
- }
-
- return false;
-}
-
-} // namespace flags_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
diff --git a/absl/flags/internal/type_erased_test.cc b/absl/flags/internal/type_erased_test.cc
deleted file mode 100644
index 42f374dc..00000000
--- a/absl/flags/internal/type_erased_test.cc
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// Copyright 2019 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/flags/internal/type_erased.h"
-
-#include <memory>
-#include <string>
-
-#include "gtest/gtest.h"
-#include "absl/flags/flag.h"
-#include "absl/flags/internal/commandlineflag.h"
-#include "absl/flags/internal/registry.h"
-#include "absl/memory/memory.h"
-
-ABSL_FLAG(int, int_flag, 1, "int_flag help");
-ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
-ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
-
-namespace {
-
-namespace flags = absl::flags_internal;
-
-class TypeErasedTest : public testing::Test {
- protected:
- void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); }
- void TearDown() override { flag_saver_.reset(); }
-
- private:
- std::unique_ptr<flags::FlagSaver> flag_saver_;
-};
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestGetCommandLineOption) {
- std::string value;
- EXPECT_TRUE(flags::GetCommandLineOption("int_flag", &value));
- EXPECT_EQ(value, "1");
-
- EXPECT_TRUE(flags::GetCommandLineOption("string_flag", &value));
- EXPECT_EQ(value, "dflt");
-
- EXPECT_FALSE(flags::GetCommandLineOption("bool_retired_flag", &value));
-
- EXPECT_FALSE(flags::GetCommandLineOption("unknown_flag", &value));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOption) {
- EXPECT_TRUE(flags::SetCommandLineOption("int_flag", "101"));
- EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
- EXPECT_TRUE(flags::SetCommandLineOption("string_flag", "asdfgh"));
- EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
- EXPECT_FALSE(flags::SetCommandLineOption("bool_retired_flag", "true"));
-
- EXPECT_FALSE(flags::SetCommandLineOption("unknown_flag", "true"));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_VALUE) {
- EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
- flags::SET_FLAGS_VALUE));
- EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
- EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
- flags::SET_FLAGS_VALUE));
- EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
- EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
- flags::SET_FLAGS_VALUE));
-
- EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
- flags::SET_FLAGS_VALUE));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAG_IF_DEFAULT) {
- EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
- flags::SET_FLAG_IF_DEFAULT));
- EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
- // This semantic is broken. We return true instead of false. Value is not
- // updated.
- EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202",
- flags::SET_FLAG_IF_DEFAULT));
- EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
-
- EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
- flags::SET_FLAG_IF_DEFAULT));
- EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
- EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
- flags::SET_FLAG_IF_DEFAULT));
-
- EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
- flags::SET_FLAG_IF_DEFAULT));
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_DEFAULT) {
- EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
- flags::SET_FLAGS_DEFAULT));
-
- // Set it again to ensure that resetting logic is covered.
- EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "102",
- flags::SET_FLAGS_DEFAULT));
-
- EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "103",
- flags::SET_FLAGS_DEFAULT));
-
- EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
- flags::SET_FLAGS_DEFAULT));
- EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
-
- EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
- flags::SET_FLAGS_DEFAULT));
-
- EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
- flags::SET_FLAGS_DEFAULT));
-
- // This should be successfull, since flag is still is not set
- EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202",
- flags::SET_FLAG_IF_DEFAULT));
- EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 202);
-}
-
-// --------------------------------------------------------------------
-
-TEST_F(TypeErasedTest, TestIsValidFlagValue) {
- EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "57"));
- EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "-101"));
- EXPECT_FALSE(flags::IsValidFlagValue("int_flag", "1.1"));
-
- EXPECT_TRUE(flags::IsValidFlagValue("string_flag", "#%^#%^$%DGHDG$W%adsf"));
-
- EXPECT_TRUE(flags::IsValidFlagValue("bool_retired_flag", "true"));
-}
-
-} // namespace
diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc
index 53b4d983..46f85b55 100644
--- a/absl/flags/internal/usage_test.cc
+++ b/absl/flags/internal/usage_test.cc
@@ -25,7 +25,7 @@
#include "absl/flags/internal/parse.h"
#include "absl/flags/internal/path_util.h"
#include "absl/flags/internal/program_name.h"
-#include "absl/flags/internal/registry.h"
+#include "absl/flags/reflection.h"
#include "absl/flags/usage.h"
#include "absl/flags/usage_config.h"
#include "absl/strings/match.h"
@@ -110,7 +110,7 @@ TEST_F(UsageReportingDeathTest, TestSetProgramUsageMessage) {
// --------------------------------------------------------------------
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {
- const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_01");
+ const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_01");
std::stringstream test_buf;
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
@@ -122,7 +122,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {
}
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
- const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_02");
+ const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_02");
std::stringstream test_buf;
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
@@ -134,7 +134,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
}
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {
- const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_03");
+ const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_03");
std::stringstream test_buf;
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
@@ -146,7 +146,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {
}
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
- const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_04");
+ const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_04");
std::stringstream test_buf;
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
@@ -158,7 +158,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
}
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) {
- const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_05");
+ const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_05");
std::stringstream test_buf;
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc
index f0a131f2..e2c88ff8 100644
--- a/absl/flags/parse.cc
+++ b/absl/flags/parse.cc
@@ -42,8 +42,8 @@
#include "absl/flags/internal/parse.h"
#include "absl/flags/internal/private_handle_accessor.h"
#include "absl/flags/internal/program_name.h"
-#include "absl/flags/internal/registry.h"
#include "absl/flags/internal/usage.h"
+#include "absl/flags/reflection.h"
#include "absl/flags/usage.h"
#include "absl/flags/usage_config.h"
#include "absl/strings/ascii.h"
@@ -290,11 +290,11 @@ std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue(
// found flag or nullptr
// is negative in case of --nofoo
std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
- CommandLineFlag* flag = flags_internal::FindCommandLineFlag(flag_name);
+ CommandLineFlag* flag = absl::FindCommandLineFlag(flag_name);
bool is_negative = false;
if (!flag && absl::ConsumePrefix(&flag_name, "no")) {
- flag = flags_internal::FindCommandLineFlag(flag_name);
+ flag = absl::FindCommandLineFlag(flag_name);
is_negative = true;
}
diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc
index aea068ee..1ab87690 100644
--- a/absl/flags/parse_test.cc
+++ b/absl/flags/parse_test.cc
@@ -28,7 +28,7 @@
#include "absl/flags/declare.h"
#include "absl/flags/flag.h"
#include "absl/flags/internal/parse.h"
-#include "absl/flags/internal/registry.h"
+#include "absl/flags/reflection.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
diff --git a/absl/flags/internal/registry.cc b/absl/flags/reflection.cc
index e582d79d..02bb6c2e 100644
--- a/absl/flags/internal/registry.cc
+++ b/absl/flags/reflection.cc
@@ -1,5 +1,5 @@
//
-// Copyright 2019 The Abseil Authors.
+// Copyright 2020 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -13,47 +13,34 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/flags/internal/registry.h"
+#include "absl/flags/reflection.h"
#include <assert.h>
-#include <stdlib.h>
-#include <functional>
#include <map>
-#include <memory>
#include <string>
-#include <utility>
-#include <vector>
#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
#include "absl/base/thread_annotations.h"
#include "absl/flags/commandlineflag.h"
-#include "absl/flags/internal/commandlineflag.h"
#include "absl/flags/internal/private_handle_accessor.h"
+#include "absl/flags/internal/registry.h"
#include "absl/flags/usage_config.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
-// --------------------------------------------------------------------
-// FlagRegistry implementation
-// A FlagRegistry holds all flag objects indexed
-// by their names so that if you know a flag's name you can access or
-// set it.
-
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace flags_internal {
// --------------------------------------------------------------------
// FlagRegistry
-// A FlagRegistry singleton object holds all flag objects indexed
-// by their names so that if you know a flag's name (as a C
-// string), you can access or set it. If the function is named
-// FooLocked(), you must own the registry lock before calling
-// the function; otherwise, you should *not* hold the lock, and
-// the function will acquire it itself if needed.
+// A FlagRegistry singleton object holds all flag objects indexed by their
+// names so that if you know a flag's name, you can access or set it. If the
+// function is named FooLocked(), you must own the registry lock before
+// calling the function; otherwise, you should *not* hold the lock, and the
+// function will acquire it itself if needed.
// --------------------------------------------------------------------
class FlagRegistry {
@@ -95,9 +82,27 @@ class FlagRegistry {
FlagRegistry& operator=(const FlagRegistry&);
};
-FlagRegistry& FlagRegistry::GlobalRegistry() {
- static FlagRegistry* global_registry = new FlagRegistry;
- return *global_registry;
+CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) {
+ FlagConstIterator i = flags_.find(name);
+ if (i == flags_.end()) {
+ return nullptr;
+ }
+
+ if (i->second->IsRetired()) {
+ flags_internal::ReportUsageError(
+ absl::StrCat("Accessing retired flag '", name, "'"), false);
+ }
+
+ return i->second;
+}
+
+CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) {
+ FlagConstIterator i = flags_.find(name);
+ if (i == flags_.end() || !i->second->IsRetired()) {
+ return nullptr;
+ }
+
+ return i->second;
}
namespace {
@@ -161,98 +166,9 @@ void FlagRegistry::RegisterFlag(CommandLineFlag& flag) {
}
}
-CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) {
- FlagConstIterator i = flags_.find(name);
- if (i == flags_.end()) {
- return nullptr;
- }
-
- if (i->second->IsRetired()) {
- flags_internal::ReportUsageError(
- absl::StrCat("Accessing retired flag '", name, "'"), false);
- }
-
- return i->second;
-}
-
-CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) {
- FlagConstIterator i = flags_.find(name);
- if (i == flags_.end() || !i->second->IsRetired()) {
- return nullptr;
- }
-
- return i->second;
-}
-
-// --------------------------------------------------------------------
-// FlagSaver
-// FlagSaverImpl
-// This class stores the states of all flags at construct time,
-// and restores all flags to that state at destruct time.
-// Its major implementation challenge is that it never modifies
-// pointers in the 'main' registry, so global FLAG_* vars always
-// point to the right place.
-// --------------------------------------------------------------------
-
-class FlagSaverImpl {
- public:
- FlagSaverImpl() = default;
- FlagSaverImpl(const FlagSaverImpl&) = delete;
- void operator=(const FlagSaverImpl&) = delete;
-
- // Saves the flag states from the flag registry into this object.
- // It's an error to call this more than once.
- void SaveFromRegistry() {
- assert(backup_registry_.empty()); // call only once!
- flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
- if (auto flag_state =
- flags_internal::PrivateHandleAccessor::SaveState(flag)) {
- backup_registry_.emplace_back(std::move(flag_state));
- }
- });
- }
-
- // Restores the saved flag states into the flag registry.
- void RestoreToRegistry() {
- for (const auto& flag_state : backup_registry_) {
- flag_state->Restore();
- }
- }
-
- private:
- std::vector<std::unique_ptr<flags_internal::FlagStateInterface>>
- backup_registry_;
-};
-
-FlagSaver::FlagSaver() : impl_(new FlagSaverImpl) { impl_->SaveFromRegistry(); }
-
-void FlagSaver::Ignore() {
- delete impl_;
- impl_ = nullptr;
-}
-
-FlagSaver::~FlagSaver() {
- if (!impl_) return;
-
- impl_->RestoreToRegistry();
- delete impl_;
-}
-
-// --------------------------------------------------------------------
-
-CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
- if (name.empty()) return nullptr;
- FlagRegistry& registry = FlagRegistry::GlobalRegistry();
- FlagRegistryLock frl(registry);
-
- return registry.FindFlagLocked(name);
-}
-
-CommandLineFlag* FindRetiredFlag(absl::string_view name) {
- FlagRegistry& registry = FlagRegistry::GlobalRegistry();
- FlagRegistryLock frl(registry);
-
- return registry.FindRetiredFlagLocked(name);
+FlagRegistry& FlagRegistry::GlobalRegistry() {
+ static FlagRegistry* global_registry = new FlagRegistry;
+ return *global_registry;
}
// --------------------------------------------------------------------
@@ -333,17 +249,71 @@ bool Retire(const char* name, FlagFastTypeId type_id) {
// --------------------------------------------------------------------
-bool IsRetiredFlag(absl::string_view name, bool* type_is_bool) {
- assert(!name.empty());
- CommandLineFlag* flag = flags_internal::FindRetiredFlag(name);
- if (flag == nullptr) {
- return false;
+// FlagSaver
+// FlagSaverImpl
+// This class stores the states of all flags at construct time,
+// and restores all flags to that state at destruct time.
+// Its major implementation challenge is that it never modifies
+// pointers in the 'main' registry, so global FLAG_* vars always
+// point to the right place.
+// --------------------------------------------------------------------
+
+class FlagSaverImpl {
+ public:
+ FlagSaverImpl() = default;
+ FlagSaverImpl(const FlagSaverImpl&) = delete;
+ void operator=(const FlagSaverImpl&) = delete;
+
+ // Saves the flag states from the flag registry into this object.
+ // It's an error to call this more than once.
+ void SaveFromRegistry() {
+ assert(backup_registry_.empty()); // call only once!
+ flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+ if (auto flag_state =
+ flags_internal::PrivateHandleAccessor::SaveState(flag)) {
+ backup_registry_.emplace_back(std::move(flag_state));
+ }
+ });
}
- assert(type_is_bool);
- *type_is_bool = flag->IsOfType<bool>();
- return true;
+
+ // Restores the saved flag states into the flag registry.
+ void RestoreToRegistry() {
+ for (const auto& flag_state : backup_registry_) {
+ flag_state->Restore();
+ }
+ }
+
+ private:
+ std::vector<std::unique_ptr<flags_internal::FlagStateInterface>>
+ backup_registry_;
+};
+
+FlagSaver::FlagSaver() : impl_(new FlagSaverImpl) { impl_->SaveFromRegistry(); }
+
+void FlagSaver::Ignore() {
+ delete impl_;
+ impl_ = nullptr;
+}
+
+FlagSaver::~FlagSaver() {
+ if (!impl_) return;
+
+ impl_->RestoreToRegistry();
+ delete impl_;
}
+// --------------------------------------------------------------------
+
} // namespace flags_internal
+
+CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
+ if (name.empty()) return nullptr;
+ flags_internal::FlagRegistry& registry =
+ flags_internal::FlagRegistry::GlobalRegistry();
+ flags_internal::FlagRegistryLock frl(registry);
+
+ return registry.FindFlagLocked(name);
+}
+
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/absl/flags/reflection.h b/absl/flags/reflection.h
new file mode 100644
index 00000000..e8e24f68
--- /dev/null
+++ b/absl/flags/reflection.h
@@ -0,0 +1,47 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: reflection.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the routines to access and operate on an Abseil Flag's
+// reflection handle.
+
+#ifndef ABSL_FLAGS_REFLECTION_H_
+#define ABSL_FLAGS_REFLECTION_H_
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// FindCommandLineFlag()
+//
+// Returns the reflection handle of an Abseil flag of the specified name, or
+// `nullptr` if not found. This function will emit a warning if the name of a
+// 'retired' flag is specified.
+CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+
+//-----------------------------------------------------------------------------
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_REFLECTION_H_
diff --git a/absl/flags/reflection_test.cc b/absl/flags/reflection_test.cc
new file mode 100644
index 00000000..2a137bf7
--- /dev/null
+++ b/absl/flags/reflection_test.cc
@@ -0,0 +1,60 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/reflection.h"
+
+#include <memory>
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/memory/memory.h"
+
+ABSL_FLAG(int, int_flag, 1, "int_flag help");
+ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
+ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+class ReflectionTest : public testing::Test {
+ protected:
+ void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); }
+ void TearDown() override { flag_saver_.reset(); }
+
+ private:
+ std::unique_ptr<flags::FlagSaver> flag_saver_;
+};
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestFindCommandLineFlag) {
+ auto* handle = absl::FindCommandLineFlag("some_flag");
+ EXPECT_EQ(handle, nullptr);
+
+ handle = absl::FindCommandLineFlag("int_flag");
+ EXPECT_NE(handle, nullptr);
+
+ handle = absl::FindCommandLineFlag("string_flag");
+ EXPECT_NE(handle, nullptr);
+
+ handle = absl::FindCommandLineFlag("bool_retired_flag");
+ EXPECT_NE(handle, nullptr);
+}
+
+} // namespace