diff options
Diffstat (limited to 'absl/flags/internal')
-rw-r--r-- | absl/flags/internal/commandlineflag.cc | 7 | ||||
-rw-r--r-- | absl/flags/internal/commandlineflag.h | 47 | ||||
-rw-r--r-- | absl/flags/internal/flag.cc | 5 | ||||
-rw-r--r-- | absl/flags/internal/flag.h | 89 | ||||
-rw-r--r-- | absl/flags/internal/registry.cc | 6 |
5 files changed, 92 insertions, 62 deletions
diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc index caf33bc4892b..88f91e16d196 100644 --- a/absl/flags/internal/commandlineflag.cc +++ b/absl/flags/internal/commandlineflag.cc @@ -56,12 +56,5 @@ std::string CommandLineFlag::Filename() const { return flags_internal::GetUsageConfig().normalize_filename(filename_); } -std::string HelpText::GetHelpText() const { - if (help_function_) return help_function_(); - if (help_message_) return help_message_; - - return {}; -} - } // namespace flags_internal } // namespace absl diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h index 13a3352e80f4..7964f1bf8c4a 100644 --- a/absl/flags/internal/commandlineflag.h +++ b/absl/flags/internal/commandlineflag.h @@ -60,14 +60,6 @@ enum ValueSource { kProgrammaticChange, }; -// Signature for the help generation function used as an argument for the -// absl::Flag constructor. -using HelpGenFunc = std::string (*)(); - -// Signature for the function generating the initial flag value based (usually -// based on default value supplied in flag's definition) -using InitialValGenFunc = void* (*)(); - extern const char kStrippedFlagHelp[]; // The per-type function @@ -149,34 +141,6 @@ inline size_t Sizeof(FlagOpFn op) { op(flags_internal::kSizeof, nullptr, nullptr))); } -// 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_; -}; - // Handle to FlagState objects. Specific flag state objects will restore state // of a flag produced this flag state from method CommandLineFlag::SaveState(). class FlagStateInterface { @@ -190,9 +154,8 @@ class FlagStateInterface { // Holds all information for a flag. class CommandLineFlag { public: - constexpr CommandLineFlag(const char* name, HelpText help_text, - const char* filename) - : name_(name), help_(help_text), filename_(filename) {} + constexpr CommandLineFlag(const char* name, const char* filename) + : name_(name), filename_(filename) {} // Virtual destructor virtual void Destroy() const = 0; @@ -203,7 +166,6 @@ class CommandLineFlag { // Non-polymorphic access methods. absl::string_view Name() const { return name_; } - std::string Help() const { return help_.GetHelpText(); } absl::string_view Typename() const; std::string Filename() const; @@ -250,6 +212,8 @@ class CommandLineFlag { // Polymorphic access methods + // Returns help message associated with this flag + virtual std::string Help() const = 0; // Returns true iff this object corresponds to retired flag virtual bool IsRetired() const { return false; } // Returns true iff this is a handle to an Abseil Flag. @@ -285,12 +249,11 @@ class CommandLineFlag { // flag's value type. virtual void CheckDefaultValueParsingRoundtrip() const = 0; - // Constant configuration for a particular flag. protected: ~CommandLineFlag() = default; + // Constant configuration for a particular flag. const char* const name_; // Flags name passed to ABSL_FLAG as second arg. - const HelpText help_; // The function generating help message. const char* const filename_; // The file name where ABSL_FLAG resides. private: diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc index 061113d76557..d087f79e891c 100644 --- a/absl/flags/internal/flag.cc +++ b/absl/flags/internal/flag.cc @@ -85,6 +85,11 @@ void FlagImpl::Destroy() const { delete locks_; } +std::string FlagImpl::Help() const { + return help_source_kind_ == FlagHelpSrcKind::kLiteral ? help_.literal + : help_.gen_func(); +} + bool FlagImpl::IsModified() const { absl::MutexLock l(DataGuard()); return modified_; diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index ce0ccf2d31d2..d79902543a22 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -61,6 +61,68 @@ class FlagState : public flags_internal::FlagStateInterface { int64_t counter_; }; +// This is help argument for absl::Flag encapsulating the string literal pointer +// or pointer to function generating it as well as enum descriminating two +// cases. +using HelpGenFunc = std::string (*)(); + +union FlagHelpSrc { + constexpr explicit FlagHelpSrc(const char* help_msg) : literal(help_msg) {} + constexpr explicit FlagHelpSrc(HelpGenFunc help_gen) : gen_func(help_gen) {} + + const char* literal; + HelpGenFunc gen_func; +}; + +enum class FlagHelpSrcKind : int8_t { kLiteral, kGenFunc }; + +struct HelpInitArg { + FlagHelpSrc source; + FlagHelpSrcKind kind; +}; + +// HelpConstexprWrap is used by struct AbslFlagHelpGenFor##name generated by +// ABSL_FLAG macro. It is only used to silence the compiler in the case where +// help message expression is not constexpr and does not have type const char*. +// If help message expression is indeed constexpr const char* HelpConstexprWrap +// is just a trivial identity function. +template <typename T> +const char* HelpConstexprWrap(const T&) { + return nullptr; +} +constexpr const char* HelpConstexprWrap(const char* p) { return p; } +constexpr const char* HelpConstexprWrap(char* p) { return p; } + +// These two HelpArg overloads allows us to select at compile time one of two +// way to pass Help argument to absl::Flag. We'll be passing +// AbslFlagHelpGenFor##name as T and integer 0 as a single argument to prefer +// first overload if possible. If T::Const is evaluatable on constexpr +// context (see non template int parameter below) we'll choose first overload. +// In this case the help message expression is immediately evaluated and is used +// to construct the absl::Flag. No additionl code is generated by ABSL_FLAG. +// Otherwise SFINAE kicks in and first overload is dropped from the +// consideration, in which case the second overload will be used. The second +// overload does not attempt to evaluate the help message expression +// immediately and instead delays the evaluation by returing the function +// pointer (&T::NonConst) genering the help message when necessary. This is +// evaluatable in constexpr context, but the cost is an extra function being +// generated in the ABSL_FLAG code. +template <typename T, int = (T::Const(), 1)> +constexpr flags_internal::HelpInitArg HelpArg(int) { + return {flags_internal::FlagHelpSrc(T::Const()), + flags_internal::FlagHelpSrcKind::kLiteral}; +} + +template <typename T> +constexpr flags_internal::HelpInitArg HelpArg(char) { + return {flags_internal::FlagHelpSrc(&T::NonConst), + flags_internal::FlagHelpSrcKind::kGenFunc}; +} + +// 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. @@ -74,15 +136,19 @@ class FlagImpl { public: constexpr FlagImpl(const flags_internal::FlagOpFn op, const flags_internal::FlagMarshallingOpFn marshalling_op, - const flags_internal::InitialValGenFunc initial_value_gen) + const flags_internal::InitialValGenFunc initial_value_gen, + const HelpInitArg help) : op_(op), marshalling_op_(marshalling_op), - initial_value_gen_(initial_value_gen) {} + initial_value_gen_(initial_value_gen), + help_(help.source), + help_source_kind_(help.kind) {} // Forces destruction of the Flag's data. void Destroy() const; // Constant access methods + std::string Help() const; bool IsModified() const ABSL_LOCKS_EXCLUDED(locks_->primary_mu); bool IsSpecifiedOnCommandLine() const ABSL_LOCKS_EXCLUDED(locks_->primary_mu); std::string DefaultValue() const ABSL_LOCKS_EXCLUDED(locks_->primary_mu); @@ -149,9 +215,12 @@ class FlagImpl { absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED(locks_->primary_mu); // Immutable Flag's data. - const FlagOpFn op_; // Type-specific handler - const FlagMarshallingOpFn marshalling_op_; // Marshalling ops handler - const InitialValGenFunc initial_value_gen_; // Makes flag's initial value + const FlagOpFn op_; // Type-specific handler. + const FlagMarshallingOpFn marshalling_op_; // Marshalling ops handler. + const InitialValGenFunc initial_value_gen_; // Makes flag's initial value. + const FlagHelpSrc help_; // Help message literal or function to generate it. + // Indicates if help message was supplied as literal or generator func. + const FlagHelpSrcKind help_source_kind_; // Mutable Flag's data. (guarded by locks_->primary_mu). // Indicates that locks_, cur_ and def_ fields have been lazily initialized. @@ -191,14 +260,13 @@ class FlagImpl { template <typename T> class Flag final : public flags_internal::CommandLineFlag { public: - constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen, + constexpr Flag(const char* name, const flags_internal::HelpInitArg help, const char* filename, const flags_internal::FlagMarshallingOpFn marshalling_op, const flags_internal::InitialValGenFunc initial_value_gen) - : flags_internal::CommandLineFlag( - name, flags_internal::HelpText::FromFunctionPointer(help_gen), - filename), - impl_(&flags_internal::FlagOps<T>, marshalling_op, initial_value_gen) {} + : flags_internal::CommandLineFlag(name, filename), + impl_(&flags_internal::FlagOps<T>, marshalling_op, initial_value_gen, + help) {} T Get() const { // See implementation notes in CommandLineFlag::Get(). @@ -222,6 +290,7 @@ class Flag final : public flags_internal::CommandLineFlag { } // CommandLineFlag interface + std::string Help() const override { return impl_.Help(); } bool IsModified() const override { return impl_.IsModified(); } bool IsSpecifiedOnCommandLine() const override { return impl_.IsSpecifiedOnCommandLine(); diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc index ae7671a967e8..52d9f3c716f3 100644 --- a/absl/flags/internal/registry.cc +++ b/absl/flags/internal/registry.cc @@ -276,9 +276,8 @@ namespace { class RetiredFlagObj final : public flags_internal::CommandLineFlag { public: constexpr RetiredFlagObj(const char* name, FlagOpFn ops) - : flags_internal::CommandLineFlag( - name, flags_internal::HelpText::FromStaticCString(nullptr), - /*filename=*/"RETIRED"), + : flags_internal::CommandLineFlag(name, + /*filename=*/"RETIRED"), op_(ops) {} private: @@ -288,6 +287,7 @@ class RetiredFlagObj final : public flags_internal::CommandLineFlag { } flags_internal::FlagOpFn TypeId() const override { return op_; } + std::string Help() const override { return ""; } bool IsRetired() const override { return true; } bool IsModified() const override { return false; } bool IsSpecifiedOnCommandLine() const override { return false; } |