From cf1a02e2dc5a1bc9d095f4c996306de448ca200f Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 20 May 2020 00:23:37 -0700 Subject: Export of internal Abseil changes -- 30e5e00a54cabc50118a3e1055826ea02a0d32e4 by Gennadiy Rozental : Move flag help into flag_cold section. To facilitate this we set flag help not in a constructor, but during flag registration. This allows us to place flag name as static variable inside non constexpr lambda and invoke it immediately in FlagRegistrar argument location. PiperOrigin-RevId: 312432625 -- efd91b05152b68df648cff5ba38e9669a817c12f by Gennadiy Rozental : Make CommandLineFlag public. PiperOrigin-RevId: 312404666 -- dc7f5fb73487766fa8a76d6b97d28116e5334445 by Mark Barolak : Internal change. PiperOrigin-RevId: 312297164 GitOrigin-RevId: 30e5e00a54cabc50118a3e1055826ea02a0d32e4 Change-Id: Ic46ab011bb804645264572caddff0becba5f9170 --- absl/flags/internal/flag.h | 62 +++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 26 deletions(-) (limited to 'absl/flags/internal/flag.h') diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index e374ecde..97ddb5f9 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -28,8 +28,8 @@ #include "absl/base/call_once.h" #include "absl/base/config.h" #include "absl/base/thread_annotations.h" +#include "absl/flags/commandlineflag.h" #include "absl/flags/config.h" -#include "absl/flags/internal/commandlineflag.h" #include "absl/flags/internal/registry.h" #include "absl/flags/marshalling.h" #include "absl/memory/memory.h" @@ -168,6 +168,28 @@ inline const std::type_info* GenRuntimeTypeId() { // cases. using HelpGenFunc = std::string (*)(); +template +struct FixedCharArray { + char value[N]; + + template + static constexpr FixedCharArray FromLiteralString( + absl::string_view str, absl::index_sequence) { + return (void)str, FixedCharArray({{str[I]..., '\0'}}); + } +}; + +template +constexpr FixedCharArray HelpStringAsArray(int) { + return FixedCharArray::FromLiteralString( + Gen::Value(), absl::make_index_sequence{}); +} + +template +constexpr std::false_type HelpStringAsArray(char) { + return std::false_type{}; +} + union FlagHelpMsg { constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {} constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {} @@ -185,40 +207,28 @@ struct FlagHelpArg { extern const char kStrippedFlagHelp[]; -// HelpConstexprWrap is used by struct AbslFlagHelpGenFor##name generated by -// ABSL_FLAG macro. It is only used to silence the compiler in the case where -// help message expression is not constexpr and does not have type const char*. -// If help message expression is indeed constexpr const char* HelpConstexprWrap -// is just a trivial identity function. -template -const char* HelpConstexprWrap(const T&) { - return nullptr; -} -constexpr const char* HelpConstexprWrap(const char* p) { return p; } -constexpr const char* HelpConstexprWrap(char* p) { return p; } - // These two HelpArg overloads allows us to select at compile time one of two // way to pass Help argument to absl::Flag. We'll be passing -// AbslFlagHelpGenFor##name as T and integer 0 as a single argument to prefer -// first overload if possible. If T::Const is evaluatable on constexpr -// context (see non template int parameter below) we'll choose first overload. -// In this case the help message expression is immediately evaluated and is used -// to construct the absl::Flag. No additionl code is generated by ABSL_FLAG. -// Otherwise SFINAE kicks in and first overload is dropped from the +// AbslFlagHelpGenFor##name as Gen and integer 0 as a single argument to prefer +// first overload if possible. If help message is evaluatable on constexpr +// context We'll be able to make FixedCharArray out of it and we'll choose first +// overload. In this case the help message expression is immediately evaluated +// and is used to construct the absl::Flag. No additionl code is generated by +// ABSL_FLAG Otherwise SFINAE kicks in and first overload is dropped from the // consideration, in which case the second overload will be used. The second // overload does not attempt to evaluate the help message expression // immediately and instead delays the evaluation by returing the function // pointer (&T::NonConst) genering the help message when necessary. This is // evaluatable in constexpr context, but the cost is an extra function being // generated in the ABSL_FLAG code. -template -constexpr FlagHelpArg HelpArg(int) { - return {FlagHelpMsg(T::Const()), FlagHelpKind::kLiteral}; +template +constexpr FlagHelpArg HelpArg(const FixedCharArray& value) { + return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral}; } -template -constexpr FlagHelpArg HelpArg(char) { - return {FlagHelpMsg(&T::NonConst), FlagHelpKind::kGenFunc}; +template +constexpr FlagHelpArg HelpArg(std::false_type) { + return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc}; } /////////////////////////////////////////////////////////////////////////////// @@ -419,7 +429,7 @@ struct DynValueDeleter { class FlagState; -class FlagImpl final : public flags_internal::CommandLineFlag { +class FlagImpl final : public CommandLineFlag { public: constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op, FlagHelpArg help, FlagValueStorageKind value_kind, -- cgit v1.2.3