about summary refs log tree commit diff
path: root/absl/flags/flag.h
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@google.com>2020-06-17T13·53+0100
committerVincent Ambo <tazjin@google.com>2020-06-17T13·53+0100
commit8f2828c4b4ce502d242eca80a80269448857f4a6 (patch)
treecc3fad62dff6f279ce77f17047c4eef5ebbaf251 /absl/flags/flag.h
parent768eb2ca2857342673fcd462792ce04b8bac3fa3 (diff)
Squashed 'third_party/abseil_cpp/' changes from 768eb2ca2..ccdbb5941
ccdbb5941 Export of internal Abseil changes
01f5f81f9 Export of internal Abseil changes
2c92bdc7c Export of internal Abseil changes
e7ebf9803 Export of internal Abseil changes
2eba343b5 Export of internal Abseil changes
a8b03d90e Export of internal Abseil changes
1d31b5c36 Export of internal Abseil changes
da3a87690 Export of internal Abseil changes
8faf20461 Exclude empty directories (#697)
2069dc796 Export of internal Abseil changes
4832bf6bf Added a BUILD file in root to expose license. (#695)
af8f994af Export of internal Abseil changes
33caf1097 Export of internal Abseil changes
cf1a02e2d Export of internal Abseil changes

git-subtree-dir: third_party/abseil_cpp
git-subtree-split: ccdbb5941f992fabda7eae3ce72f55efc17c826a
Diffstat (limited to 'absl/flags/flag.h')
-rw-r--r--absl/flags/flag.h142
1 files changed, 75 insertions, 67 deletions
diff --git a/absl/flags/flag.h b/absl/flags/flag.h
index ca7d581fce71..90dc2894df54 100644
--- a/absl/flags/flag.h
+++ b/absl/flags/flag.h
@@ -33,14 +33,11 @@
 #include <type_traits>
 
 #include "absl/base/attributes.h"
-#include "absl/base/casts.h"
 #include "absl/base/config.h"
+#include "absl/base/optimization.h"
 #include "absl/flags/config.h"
-#include "absl/flags/declare.h"
-#include "absl/flags/internal/commandlineflag.h"
 #include "absl/flags/internal/flag.h"
 #include "absl/flags/internal/registry.h"
-#include "absl/flags/marshalling.h"
 #include "absl/strings/string_view.h"
 
 namespace absl {
@@ -111,12 +108,12 @@ class Flag {
         impl_(nullptr) {}
 #endif
 
-  flags_internal::Flag<T>* GetImpl() const {
+  flags_internal::Flag<T>& GetImpl() const {
     if (!inited_.load(std::memory_order_acquire)) {
       absl::MutexLock l(flags_internal::GetGlobalConstructionGuard());
 
       if (inited_.load(std::memory_order_acquire)) {
-        return impl_;
+        return *impl_;
       }
 
       impl_ = new flags_internal::Flag<T>(
@@ -128,28 +125,30 @@ class Flag {
       inited_.store(true, std::memory_order_release);
     }
 
-    return impl_;
+    return *impl_;
   }
 
   // Public methods of `absl::Flag<T>` are NOT part of the Abseil Flags API.
   // See https://abseil.io/docs/cpp/guides/flags
-  bool IsRetired() const { return GetImpl()->IsRetired(); }
-  absl::string_view Name() const { return GetImpl()->Name(); }
-  std::string Help() const { return GetImpl()->Help(); }
-  bool IsModified() const { return GetImpl()->IsModified(); }
+  bool IsRetired() const { return GetImpl().IsRetired(); }
+  absl::string_view Name() const { return GetImpl().Name(); }
+  std::string Help() const { return GetImpl().Help(); }
+  bool IsModified() const { return GetImpl().IsModified(); }
   bool IsSpecifiedOnCommandLine() const {
-    return GetImpl()->IsSpecifiedOnCommandLine();
+    return GetImpl().IsSpecifiedOnCommandLine();
   }
-  std::string Filename() const { return GetImpl()->Filename(); }
-  std::string DefaultValue() const { return GetImpl()->DefaultValue(); }
-  std::string CurrentValue() const { return GetImpl()->CurrentValue(); }
+  std::string Filename() const { return GetImpl().Filename(); }
+  std::string DefaultValue() const { return GetImpl().DefaultValue(); }
+  std::string CurrentValue() const { return GetImpl().CurrentValue(); }
   template <typename U>
   inline bool IsOfType() const {
-    return GetImpl()->template IsOfType<U>();
+    return GetImpl().template IsOfType<U>();
   }
-  T Get() const { return GetImpl()->Get(); }
-  void Set(const T& v) { GetImpl()->Set(v); }
-  void InvokeCallback() { GetImpl()->InvokeCallback(); }
+  T Get() const { return GetImpl().Get(); }
+  void Set(const T& v) { GetImpl().Set(v); }
+  void InvokeCallback() { GetImpl().InvokeCallback(); }
+
+  const CommandLineFlag& Reflect() const { return GetImpl().Reflect(); }
 
   // The data members are logically private, but they need to be public for
   // this to be an aggregate type.
@@ -205,6 +204,21 @@ void SetFlag(absl::Flag<T>* flag, const V& v) {
   flag->Set(value);
 }
 
+// GetFlagReflectionHandle()
+//
+// Returns the reflection handle corresponding to specified Abseil Flag
+// instance. Use this handle to access flag's reflection information, like name,
+// location, default value etc.
+//
+// Example:
+//
+//   std::string = absl::GetFlagReflectionHandle(FLAGS_count).DefaultValue();
+
+template <typename T>
+const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
+  return f.Reflect();
+}
+
 ABSL_NAMESPACE_END
 }  // namespace absl
 
@@ -265,27 +279,29 @@ ABSL_NAMESPACE_END
 // -----------------------------------------------------------------------------
 
 // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES
+#if !defined(_MSC_VER) || defined(__clang__)
+#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag
+#define ABSL_FLAG_IMPL_HELP_ARG(name)                      \
+  absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \
+      FLAGS_help_storage_##name)
+#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) \
+  absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)
+#else
+#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag.GetImpl()
+#define ABSL_FLAG_IMPL_HELP_ARG(name) &AbslFlagHelpGenFor##name::NonConst
+#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) &AbslFlagDefaultGenFor##name::Gen
+#endif
 
 #if ABSL_FLAGS_STRIP_NAMES
 #define ABSL_FLAG_IMPL_FLAGNAME(txt) ""
 #define ABSL_FLAG_IMPL_FILENAME() ""
-#if !defined(_MSC_VER) || defined(__clang__)
 #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, false>(&flag)
-#else
-#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, false>(flag.GetImpl())
-#endif
+  absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
 #else
 #define ABSL_FLAG_IMPL_FLAGNAME(txt) txt
 #define ABSL_FLAG_IMPL_FILENAME() __FILE__
-#if !defined(_MSC_VER) || defined(__clang__)
 #define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, true>(&flag)
-#else
-#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
-  absl::flags_internal::FlagRegistrar<T, true>(flag.GetImpl())
-#endif
+  absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag))
 #endif
 
 // ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
@@ -301,15 +317,24 @@ ABSL_NAMESPACE_END
 // between the two via the call to HelpArg in absl::Flag instantiation below.
 // If help message expression is constexpr evaluable compiler will optimize
 // away this whole struct.
-#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt)                     \
-  struct AbslFlagHelpGenFor##name {                                        \
-    template <typename T = void>                                           \
-    static constexpr const char* Const() {                                 \
-      return absl::flags_internal::HelpConstexprWrap(                      \
-          ABSL_FLAG_IMPL_FLAGHELP(txt));                                   \
-    }                                                                      \
-    static std::string NonConst() { return ABSL_FLAG_IMPL_FLAGHELP(txt); } \
-  }
+// TODO(rogeeff): place these generated structs into local namespace and apply
+// ABSL_INTERNAL_UNIQUE_SHORT_NAME.
+// TODO(rogeeff): Apply __attribute__((nodebug)) to FLAGS_help_storage_##name
+#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt)                       \
+  struct AbslFlagHelpGenFor##name {                                          \
+    /* The expression is run in the caller as part of the   */               \
+    /* default value argument. That keeps temporaries alive */               \
+    /* long enough for NonConst to work correctly.          */               \
+    static constexpr absl::string_view Value(                                \
+        absl::string_view v = ABSL_FLAG_IMPL_FLAGHELP(txt)) {                \
+      return v;                                                              \
+    }                                                                        \
+    static std::string NonConst() { return std::string(Value()); }           \
+  };                                                                         \
+  constexpr auto FLAGS_help_storage_##name ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
+      ABSL_ATTRIBUTE_SECTION_VARIABLE(flags_help_cold) =                     \
+          absl::flags_internal::HelpStringAsArray<AbslFlagHelpGenFor##name>( \
+              0);
 
 #define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)     \
   struct AbslFlagDefaultGenFor##name {                                        \
@@ -317,40 +342,23 @@ ABSL_NAMESPACE_END
     static void Gen(void* p) {                                                \
       new (p) Type(AbslFlagDefaultGenFor##name{}.value);                      \
     }                                                                         \
-  }
+  };
 
 // ABSL_FLAG_IMPL
 //
 // Note: Name of registrar object is not arbitrary. It is used to "grab"
 // global name for FLAGS_no<flag_name> symbol, thus preventing the possibility
 // of defining two flags with names foo and nofoo.
-#if !defined(_MSC_VER) || defined(__clang__)
-
-#define ABSL_FLAG_IMPL(Type, name, default_value, help)                        \
-  namespace absl /* block flags in namespaces */ {}                            \
-  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value);           \
-  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help);                             \
-  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                               \
-      ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(),               \
-      absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>(0),              \
-      absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)}; \
-  extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;              \
-  absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =                    \
+#define ABSL_FLAG_IMPL(Type, name, default_value, help)                       \
+  namespace absl /* block flags in namespaces */ {}                           \
+  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value)           \
+  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help)                             \
+  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                              \
+      ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(),              \
+      ABSL_FLAG_IMPL_HELP_ARG(name), ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \
+  extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;             \
+  absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =                   \
       ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
-#else
-// MSVC version uses aggregate initialization. We also do not try to
-// optimize away help wrapper.
-#define ABSL_FLAG_IMPL(Type, name, default_value, help)                        \
-  namespace absl /* block flags in namespaces */ {}                            \
-  ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value);           \
-  ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help);                             \
-  ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{                               \
-      ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(),               \
-      &AbslFlagHelpGenFor##name::NonConst, &AbslFlagDefaultGenFor##name::Gen}; \
-  extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name;              \
-  absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name =                    \
-      ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
-#endif
 
 // ABSL_RETIRED_FLAG
 //