From 8ff1374008259719b54a8cb128ef951c02da164c Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 12 Sep 2018 11:03:25 -0700 Subject: Export of internal Abseil changes. -- 821196cfb2a3b943ffdc4c9e75daec92d7ffb28b by Abseil Team : Performance improvements PiperOrigin-RevId: 212668992 -- 704858e2e767016bad27d53eec01d9d48e546b23 by Abseil Team : Low-level Portability enchancements for Abseil Mutex on WebAssembly. Emscripten Pthreads do not use signals, so remove use of pthread_sigmask or other async-signal-safe related handling code. PiperOrigin-RevId: 212527958 -- be3e38cb4d493b755132d20c8c2d1a51e45d5449 by Jon Cohen : Internal change. PiperOrigin-RevId: 212523797 GitOrigin-RevId: 821196cfb2a3b943ffdc4c9e75daec92d7ffb28b Change-Id: I5694e23e4e09364a15dd6fc4e2e3f15e38835687 --- absl/strings/internal/str_format/arg.cc | 80 ++++------ absl/strings/internal/str_format/arg.h | 210 +++++++++++++-------------- absl/strings/internal/str_format/bind.h | 2 +- absl/strings/internal/str_format/extension.h | 10 +- 4 files changed, 136 insertions(+), 166 deletions(-) (limited to 'absl/strings/internal/str_format') diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc index eafb068fe286..b40be8ff3824 100644 --- a/absl/strings/internal/str_format/arg.cc +++ b/absl/strings/internal/str_format/arg.cc @@ -112,7 +112,7 @@ class ConvertedIntInfo { // Note: 'o' conversions do not have a base indicator, it's just that // the '#' flag is specified to modify the precision for 'o' conversions. string_view BaseIndicator(const ConvertedIntInfo &info, - const ConversionSpec &conv) { + const ConversionSpec conv) { bool alt = conv.flags().alt; int radix = conv.conv().radix(); if (conv.conv().id() == ConversionChar::p) @@ -127,7 +127,7 @@ string_view BaseIndicator(const ConvertedIntInfo &info, return {}; } -string_view SignColumn(bool neg, const ConversionSpec &conv) { +string_view SignColumn(bool neg, const ConversionSpec conv) { if (conv.conv().is_signed()) { if (neg) return "-"; if (conv.flags().show_pos) return "+"; @@ -136,7 +136,7 @@ string_view SignColumn(bool neg, const ConversionSpec &conv) { return {}; } -bool ConvertCharImpl(unsigned char v, const ConversionSpec &conv, +bool ConvertCharImpl(unsigned char v, const ConversionSpec conv, FormatSinkImpl *sink) { size_t fill = 0; if (conv.width() >= 0) fill = conv.width(); @@ -148,7 +148,7 @@ bool ConvertCharImpl(unsigned char v, const ConversionSpec &conv, } bool ConvertIntImplInner(const ConvertedIntInfo &info, - const ConversionSpec &conv, FormatSinkImpl *sink) { + const ConversionSpec conv, FormatSinkImpl *sink) { // Print as a sequence of Substrings: // [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces] size_t fill = 0; @@ -202,8 +202,7 @@ bool ConvertIntImplInner(const ConvertedIntInfo &info, } template -bool ConvertIntImplInner(T v, const ConversionSpec &conv, - FormatSinkImpl *sink) { +bool ConvertIntImplInner(T v, const ConversionSpec conv, FormatSinkImpl *sink) { ConvertedIntInfo info(v, conv.conv()); if (conv.flags().basic && conv.conv().id() != ConversionChar::p) { if (info.is_neg()) sink->Append(1, '-'); @@ -218,7 +217,7 @@ bool ConvertIntImplInner(T v, const ConversionSpec &conv, } template -bool ConvertIntArg(T v, const ConversionSpec &conv, FormatSinkImpl *sink) { +bool ConvertIntArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) { if (conv.conv().is_float()) { return FormatConvertImpl(static_cast(v), conv, sink).value; } @@ -234,11 +233,11 @@ bool ConvertIntArg(T v, const ConversionSpec &conv, FormatSinkImpl *sink) { } template -bool ConvertFloatArg(T v, const ConversionSpec &conv, FormatSinkImpl *sink) { +bool ConvertFloatArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) { return conv.conv().is_float() && ConvertFloatImpl(v, conv, sink); } -inline bool ConvertStringArg(string_view v, const ConversionSpec &conv, +inline bool ConvertStringArg(string_view v, const ConversionSpec conv, FormatSinkImpl *sink) { if (conv.conv().id() != ConversionChar::s) return false; @@ -254,19 +253,19 @@ inline bool ConvertStringArg(string_view v, const ConversionSpec &conv, // ==================== Strings ==================== ConvertResult FormatConvertImpl(const std::string &v, - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertStringArg(v, conv, sink)}; } ConvertResult FormatConvertImpl(string_view v, - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertStringArg(v, conv, sink)}; } ConvertResult FormatConvertImpl(const char *v, - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { if (conv.conv().id() == ConversionChar::p) return {FormatConvertImpl(VoidPtr(v), conv, sink).value}; @@ -283,7 +282,7 @@ ConvertResult FormatConvertImpl(const char *v, } // ==================== Raw pointers ==================== -ConvertResult FormatConvertImpl(VoidPtr v, const ConversionSpec &conv, +ConvertResult FormatConvertImpl(VoidPtr v, const ConversionSpec conv, FormatSinkImpl *sink) { if (conv.conv().id() != ConversionChar::p) return {false}; @@ -295,104 +294,83 @@ ConvertResult FormatConvertImpl(VoidPtr v, const ConversionSpec &conv, } // ==================== Floats ==================== -FloatingConvertResult FormatConvertImpl(float v, const ConversionSpec &conv, +FloatingConvertResult FormatConvertImpl(float v, const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertFloatArg(v, conv, sink)}; } -FloatingConvertResult FormatConvertImpl(double v, const ConversionSpec &conv, +FloatingConvertResult FormatConvertImpl(double v, const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertFloatArg(v, conv, sink)}; } FloatingConvertResult FormatConvertImpl(long double v, - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertFloatArg(v, conv, sink)}; } // ==================== Chars ==================== -IntegralConvertResult FormatConvertImpl(char v, const ConversionSpec &conv, +IntegralConvertResult FormatConvertImpl(char v, const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(signed char v, - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(unsigned char v, - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } // ==================== Ints ==================== IntegralConvertResult FormatConvertImpl(short v, // NOLINT - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } -IntegralConvertResult FormatConvertImpl(int v, const ConversionSpec &conv, +IntegralConvertResult FormatConvertImpl(int v, const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } -IntegralConvertResult FormatConvertImpl(unsigned v, const ConversionSpec &conv, +IntegralConvertResult FormatConvertImpl(unsigned v, const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(long v, // NOLINT - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(long long v, // NOLINT - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(absl::uint128 v, - const ConversionSpec &conv, + const ConversionSpec conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } -template struct FormatArgImpl::TypedVTable; - -template struct FormatArgImpl::TypedVTable; -template struct FormatArgImpl::TypedVTable; -template struct FormatArgImpl::TypedVTable; -template struct FormatArgImpl::TypedVTable; -template struct FormatArgImpl::TypedVTable; // NOLINT -template struct FormatArgImpl::TypedVTable; // NOLINT -template struct FormatArgImpl::TypedVTable; -template struct FormatArgImpl::TypedVTable; -template struct FormatArgImpl::TypedVTable; // NOLINT -template struct FormatArgImpl::TypedVTable; // NOLINT -template struct FormatArgImpl::TypedVTable; // NOLINT -template struct FormatArgImpl::TypedVTable; // NOLINT -template struct FormatArgImpl::TypedVTable; - -template struct FormatArgImpl::TypedVTable; -template struct FormatArgImpl::TypedVTable; -template struct FormatArgImpl::TypedVTable; - -template struct FormatArgImpl::TypedVTable; -template struct FormatArgImpl::TypedVTable; -template struct FormatArgImpl::TypedVTable; +ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(); + } // namespace str_format_internal diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index a9562188ea91..3376d48afda2 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -33,7 +33,7 @@ struct HasUserDefinedConvert : std::false_type {}; template struct HasUserDefinedConvert< T, void_t(), std::declval(), + std::declval(), std::declval(), std::declval()))>> : std::true_type {}; template class StreamedWrapper; @@ -50,25 +50,23 @@ struct VoidPtr { : value(ptr ? reinterpret_cast(ptr) : 0) {} uintptr_t value; }; -ConvertResult FormatConvertImpl(VoidPtr v, const ConversionSpec& conv, +ConvertResult FormatConvertImpl(VoidPtr v, ConversionSpec conv, FormatSinkImpl* sink); // Strings. -ConvertResult FormatConvertImpl(const std::string& v, - const ConversionSpec& conv, +ConvertResult FormatConvertImpl(const std::string& v, ConversionSpec conv, FormatSinkImpl* sink); -ConvertResult FormatConvertImpl(string_view v, - const ConversionSpec& conv, +ConvertResult FormatConvertImpl(string_view v, ConversionSpec conv, FormatSinkImpl* sink); ConvertResult FormatConvertImpl(const char* v, - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* sink); template ::value>::type* = nullptr, class AbslCordReader = ::CordReader> ConvertResult FormatConvertImpl(const AbslCord& value, - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* sink) { if (conv.conv().id() != ConversionChar::s) return {false}; @@ -104,51 +102,48 @@ using IntegralConvertResult = using FloatingConvertResult = ConvertResult; // Floats. -FloatingConvertResult FormatConvertImpl(float v, const ConversionSpec& conv, +FloatingConvertResult FormatConvertImpl(float v, ConversionSpec conv, FormatSinkImpl* sink); -FloatingConvertResult FormatConvertImpl(double v, const ConversionSpec& conv, +FloatingConvertResult FormatConvertImpl(double v, ConversionSpec conv, FormatSinkImpl* sink); -FloatingConvertResult FormatConvertImpl(long double v, - const ConversionSpec& conv, +FloatingConvertResult FormatConvertImpl(long double v, ConversionSpec conv, FormatSinkImpl* sink); // Chars. -IntegralConvertResult FormatConvertImpl(char v, const ConversionSpec& conv, +IntegralConvertResult FormatConvertImpl(char v, ConversionSpec conv, FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(signed char v, - const ConversionSpec& conv, +IntegralConvertResult FormatConvertImpl(signed char v, ConversionSpec conv, FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(unsigned char v, - const ConversionSpec& conv, +IntegralConvertResult FormatConvertImpl(unsigned char v, ConversionSpec conv, FormatSinkImpl* sink); // Ints. IntegralConvertResult FormatConvertImpl(short v, // NOLINT - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(int v, const ConversionSpec& conv, +IntegralConvertResult FormatConvertImpl(int v, ConversionSpec conv, FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(unsigned v, const ConversionSpec& conv, +IntegralConvertResult FormatConvertImpl(unsigned v, ConversionSpec conv, FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(long v, // NOLINT - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(long long v, // NOLINT - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(uint128 v, const ConversionSpec& conv, +IntegralConvertResult FormatConvertImpl(uint128 v, ConversionSpec conv, FormatSinkImpl* sink); template ::value, int> = 0> -IntegralConvertResult FormatConvertImpl(T v, const ConversionSpec& conv, +IntegralConvertResult FormatConvertImpl(T v, ConversionSpec conv, FormatSinkImpl* sink) { return FormatConvertImpl(static_cast(v), conv, sink); } @@ -159,11 +154,11 @@ template typename std::enable_if::value && !HasUserDefinedConvert::value, IntegralConvertResult>::type -FormatConvertImpl(T v, const ConversionSpec& conv, FormatSinkImpl* sink); +FormatConvertImpl(T v, ConversionSpec conv, FormatSinkImpl* sink); template ConvertResult FormatConvertImpl(const StreamedWrapper& v, - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* out) { std::ostringstream oss; oss << v.v_; @@ -176,7 +171,7 @@ ConvertResult FormatConvertImpl(const StreamedWrapper& v, struct FormatCountCaptureHelper { template static ConvertResult ConvertHelper(const FormatCountCapture& v, - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* sink) { const absl::enable_if_t& v2 = v; @@ -189,7 +184,7 @@ struct FormatCountCaptureHelper { template ConvertResult FormatConvertImpl(const FormatCountCapture& v, - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* sink) { return FormatCountCaptureHelper::ConvertHelper(v, conv, sink); } @@ -199,20 +194,20 @@ ConvertResult FormatConvertImpl(const FormatCountCapture& v, struct FormatArgImplFriend { template static bool ToInt(Arg arg, int* out) { - if (!arg.vtbl_->to_int) return false; - *out = arg.vtbl_->to_int(arg.data_); - return true; + // A value initialized ConversionSpec has a `none` conv, which tells the + // dispatcher to run the `int` conversion. + return arg.dispatcher_(arg.data_, {}, out); } template - static bool Convert(Arg arg, const str_format_internal::ConversionSpec& conv, + static bool Convert(Arg arg, str_format_internal::ConversionSpec conv, FormatSinkImpl* out) { - return arg.vtbl_->convert(arg.data_, conv, out); + return arg.dispatcher_(arg.data_, conv, out); } template - static const void* GetVTablePtrForTest(Arg arg) { - return arg.vtbl_; + static typename Arg::Dispatcher GetVTablePtrForTest(Arg arg) { + return arg.dispatcher_; } }; @@ -229,11 +224,7 @@ class FormatArgImpl { char buf[kInlinedSpace]; }; - struct VTable { - bool (*convert)(Data, const str_format_internal::ConversionSpec& conv, - FormatSinkImpl* out); - int (*to_int)(Data); - }; + using Dispatcher = bool (*)(Data, ConversionSpec, void* out); template struct store_by_value @@ -253,10 +244,6 @@ class FormatArgImpl { : ByPointer))> { }; - // An instance of an FormatArgImpl::VTable suitable for 'T'. - template - struct TypedVTable; - // To reduce the number of vtables we will decay values before hand. // Anything with a user-defined Convert will get its own vtable. // For everything else: @@ -338,7 +325,10 @@ class FormatArgImpl { }; template - void Init(const T& value); + void Init(const T& value) { + data_ = Manager::SetValue(value); + dispatcher_ = &Dispatch; + } template static int ToIntVal(const T& val) { @@ -355,79 +345,75 @@ class FormatArgImpl { return static_cast(val); } - Data data_; - const VTable* vtbl_; -}; - -template -struct FormatArgImpl::TypedVTable { - private: - static bool ConvertImpl(Data arg, - const str_format_internal::ConversionSpec& conv, - FormatSinkImpl* out) { - return str_format_internal::FormatConvertImpl(Manager::Value(arg), conv, - out) - .value; + template + static bool ToInt(Data arg, int* out, std::true_type /* is_integral */, + std::false_type) { + *out = ToIntVal(Manager::Value(arg)); + return true; } - template - struct ToIntImpl { - static constexpr int (*value)(Data) = nullptr; - }; + template + static bool ToInt(Data arg, int* out, std::false_type, + std::true_type /* is_enum */) { + *out = ToIntVal(static_cast::type>( + Manager::Value(arg))); + return true; + } - template - struct ToIntImpl::value>::type> { - static int Invoke(Data arg) { return ToIntVal(Manager::Value(arg)); } - static constexpr int (*value)(Data) = &Invoke; - }; + template + static bool ToInt(Data, int*, std::false_type, std::false_type) { + return false; + } - template - struct ToIntImpl::value>::type> { - static int Invoke(Data arg) { - return ToIntVal(static_cast::type>( - Manager::Value(arg))); + template + static bool Dispatch(Data arg, ConversionSpec spec, void* out) { + // A `none` conv indicates that we want the `int` conversion. + if (ABSL_PREDICT_FALSE(spec.conv().id() == ConversionChar::none)) { + return ToInt(arg, static_cast(out), std::is_integral(), + std::is_enum()); } - static constexpr int (*value)(Data) = &Invoke; - }; - public: - static constexpr VTable value{&ConvertImpl, ToIntImpl<>::value}; -}; + return str_format_internal::FormatConvertImpl( + Manager::Value(arg), spec, static_cast(out)) + .value; + } -template -constexpr FormatArgImpl::VTable FormatArgImpl::TypedVTable::value; + Data data_; + Dispatcher dispatcher_; +}; -template -void FormatArgImpl::Init(const T& value) { - data_ = Manager::SetValue(value); - vtbl_ = &TypedVTable::value; -} +#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \ + E template bool FormatArgImpl::Dispatch(Data, ConversionSpec, void*) + +#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \ + __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(bool, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(char, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(signed char, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned char, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(short, __VA_ARGS__); /* NOLINT */ \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned short, /* NOLINT */ \ + __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned int, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long, __VA_ARGS__); /* NOLINT */ \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long, /* NOLINT */ \ + __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long long, /* NOLINT */ \ + __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */ \ + __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__) + +ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern); -extern template struct FormatArgImpl::TypedVTable; - -extern template struct FormatArgImpl::TypedVTable; -extern template struct FormatArgImpl::TypedVTable; -extern template struct FormatArgImpl::TypedVTable; -extern template struct FormatArgImpl::TypedVTable; -extern template struct FormatArgImpl::TypedVTable; // NOLINT -extern template struct FormatArgImpl::TypedVTable; // NOLINT -extern template struct FormatArgImpl::TypedVTable; -extern template struct FormatArgImpl::TypedVTable; -extern template struct FormatArgImpl::TypedVTable; // NOLINT -extern template struct FormatArgImpl::TypedVTable; // NOLINT -extern template struct FormatArgImpl::TypedVTable; // NOLINT -extern template struct FormatArgImpl::TypedVTable< - unsigned long long>; // NOLINT -extern template struct FormatArgImpl::TypedVTable; - -extern template struct FormatArgImpl::TypedVTable; -extern template struct FormatArgImpl::TypedVTable; -extern template struct FormatArgImpl::TypedVTable; - -extern template struct FormatArgImpl::TypedVTable; -extern template struct FormatArgImpl::TypedVTable; -extern template struct FormatArgImpl::TypedVTable; } // namespace str_format_internal } // namespace absl diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h index a503b19bb675..1b52df9c7f56 100644 --- a/absl/strings/internal/str_format/bind.h +++ b/absl/strings/internal/str_format/bind.h @@ -186,7 +186,7 @@ class StreamedWrapper { private: template friend ConvertResult FormatConvertImpl(const StreamedWrapper& v, - const ConversionSpec& conv, + ConversionSpec conv, FormatSinkImpl* out); const T& v_; }; diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h index f43195c127b1..11b996aefd37 100644 --- a/absl/strings/internal/str_format/extension.h +++ b/absl/strings/internal/str_format/extension.h @@ -18,6 +18,7 @@ #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ #include +#include #include #include @@ -307,7 +308,12 @@ class ConversionSpec { public: Flags flags() const { return flags_; } LengthMod length_mod() const { return length_mod_; } - ConversionChar conv() const { return conv_; } + ConversionChar conv() const { + // Keep this field first in the struct . It generates better code when + // accessing it when ConversionSpec is passed by value in registers. + static_assert(offsetof(ConversionSpec, conv_) == 0, ""); + return conv_; + } // Returns the specified width. If width is unspecfied, it returns a negative // value. @@ -324,9 +330,9 @@ class ConversionSpec { void set_left(bool b) { flags_.left = b; } private: + ConversionChar conv_; Flags flags_; LengthMod length_mod_; - ConversionChar conv_; int width_; int precision_; }; -- cgit 1.4.1