From a3d9a943253f596bd88538f18cc6b07aaba6d3c0 Mon Sep 17 00:00:00 2001 From: Greg Falcon Date: Mon, 12 Jun 2023 08:25:06 -0700 Subject: Fix behaviors of StrCat() and StrFormat() regarding char types and enum types. This is a conservative change, in that it only contains bugfixes and allows new patterns that used to be compile errors. There are other changes we would like to make (as reflected in the comments in char_formatting_test.cc), but we are being careful about the implications of such behavior changes. The two implementation changes are: * Apply integral promotions to enums before printing them, so they are always treated as integers (and not chars) by StrCat and StrFormat. * Classify `unsigned char` and `signed char` as integer-like rather than char-like, so that `StrFormat("%v", v)` accepts those types as integers (consistent with `StrCat()`.) The behavior changes are: * StrCat() now accepts char-backed enums (rather than failing to compile). * StrFormat("%v") now accepts `signed char` and `unsigned char` as integral (rather than failing to compile). * StrFormat("%v") now correctly formats 8-bit enums as integers (rather than failing internally and emitting nothing). Tested: Modified the char_formatting_test.cc case to reflect changes. Re-ran all other tests. PiperOrigin-RevId: 539659674 Change-Id: Ief56335f5a57e4582af396d00eaa9e7b6be4ddc6 --- absl/strings/internal/str_format/arg.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'absl/strings/internal/str_format/arg.h') diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index e4b16628..3ce30feb 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -279,14 +279,14 @@ FloatingConvertResult FormatConvertImpl(long double v, // Chars. CharConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); -CharConvertResult FormatConvertImpl(signed char v, - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); -CharConvertResult FormatConvertImpl(unsigned char v, - FormatConversionSpecImpl conv, - FormatSinkImpl* sink); // Ints. +IntegralConvertResult FormatConvertImpl(signed char v, + FormatConversionSpecImpl conv, + FormatSinkImpl* sink); +IntegralConvertResult FormatConvertImpl(unsigned char v, + FormatConversionSpecImpl conv, + FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(short v, // NOLINT FormatConversionSpecImpl conv, FormatSinkImpl* sink); @@ -441,7 +441,7 @@ class FormatArgImpl { // For everything else: // - Decay char* and char arrays into `const char*` // - Decay any other pointer to `const void*` - // - Decay all enums to their underlying type. + // - Decay all enums to the integral promotion of their underlying type. // - Decay function pointers to void*. template struct DecayType { @@ -461,7 +461,7 @@ class FormatArgImpl { !str_format_internal::HasUserDefinedConvert::value && !strings_internal::HasAbslStringify::value && std::is_enum::value>::type> { - using type = typename std::underlying_type::type; + using type = decltype(+typename std::underlying_type::type()); }; public: -- cgit v1.2.3