From 4491d606df34c44efda47b6d17b605262f17e182 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 21 Jun 2018 12:55:12 -0700 Subject: Export of internal Abseil changes. -- 70f43a482d7d4ae4a255f17ca02b0106653dd600 by Shaindel Schwartz : Internal change PiperOrigin-RevId: 201571193 -- 93e6e9c2e683158be49d9dd1f5cb1a91d0c0f556 by Abseil Team : Internal change. PiperOrigin-RevId: 201567108 -- fbd8ee94fbe9f2448e5adf5e88706f9c8216048f by Juemin Yang : str_format release PiperOrigin-RevId: 201565129 -- 387faa301555a8a888c4429df52734aa806dca46 by Abseil Team : Adds a defaulted allocator parameter to the size_type constructor of InlinedVector PiperOrigin-RevId: 201558711 -- 39b15ea2c68d7129d70cbde7e71af900032595ec by Matt Calabrese : Update the variant implementation to eliminate unnecessary checking on alternative access when the index is known or required to be correct. PiperOrigin-RevId: 201529535 -- adab77f1f7bb363aa534297f22aae2b0f08889ea by Abseil Team : Import of CCTZ from GitHub. PiperOrigin-RevId: 201458388 -- a701dc0ba62e3cadf0de14203415b91df4ee8151 by Greg Falcon : Internal cleanup PiperOrigin-RevId: 201394836 -- 8a7191410b8f440fdfa27f722ff05e451502ab61 by Abseil Team : Import of CCTZ from GitHub. PiperOrigin-RevId: 201369269 GitOrigin-RevId: 70f43a482d7d4ae4a255f17ca02b0106653dd600 Change-Id: I8ab073b30b4e27405a3b6da2c826bb4f3f0b9af6 --- absl/strings/internal/str_format/convert_test.cc | 575 +++++++++++++++++++++++ 1 file changed, 575 insertions(+) create mode 100644 absl/strings/internal/str_format/convert_test.cc (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc new file mode 100644 index 00000000..32f8a0f9 --- /dev/null +++ b/absl/strings/internal/str_format/convert_test.cc @@ -0,0 +1,575 @@ +#include +#include +#include +#include +#include + +#include "gtest/gtest.h" +#include "absl/strings/internal/str_format/bind.h" + +namespace absl { +namespace str_format_internal { +namespace { + +template +size_t ArraySize(T (&)[N]) { + return N; +} + +std::string LengthModFor(float) { return ""; } +std::string LengthModFor(double) { return ""; } +std::string LengthModFor(long double) { return "L"; } +std::string LengthModFor(char) { return "hh"; } +std::string LengthModFor(signed char) { return "hh"; } +std::string LengthModFor(unsigned char) { return "hh"; } +std::string LengthModFor(short) { return "h"; } // NOLINT +std::string LengthModFor(unsigned short) { return "h"; } // NOLINT +std::string LengthModFor(int) { return ""; } +std::string LengthModFor(unsigned) { return ""; } +std::string LengthModFor(long) { return "l"; } // NOLINT +std::string LengthModFor(unsigned long) { return "l"; } // NOLINT +std::string LengthModFor(long long) { return "ll"; } // NOLINT +std::string LengthModFor(unsigned long long) { return "ll"; } // NOLINT + +std::string EscCharImpl(int v) { + if (isprint(v)) return std::string(1, static_cast(v)); + char buf[64]; + int n = snprintf(buf, sizeof(buf), "\\%#.2x", + static_cast(v & 0xff)); + assert(n > 0 && n < sizeof(buf)); + return std::string(buf, n); +} + +std::string Esc(char v) { return EscCharImpl(v); } +std::string Esc(signed char v) { return EscCharImpl(v); } +std::string Esc(unsigned char v) { return EscCharImpl(v); } + +template +std::string Esc(const T &v) { + std::ostringstream oss; + oss << v; + return oss.str(); +} + +void StrAppend(std::string *dst, const char *format, va_list ap) { + // First try with a small fixed size buffer + static const int kSpaceLength = 1024; + char space[kSpaceLength]; + + // It's possible for methods that use a va_list to invalidate + // the data in it upon use. The fix is to make a copy + // of the structure before using it and use that copy instead. + va_list backup_ap; + va_copy(backup_ap, ap); + int result = vsnprintf(space, kSpaceLength, format, backup_ap); + va_end(backup_ap); + if (result < kSpaceLength) { + if (result >= 0) { + // Normal case -- everything fit. + dst->append(space, result); + return; + } + if (result < 0) { + // Just an error. + return; + } + } + + // Increase the buffer size to the size requested by vsnprintf, + // plus one for the closing \0. + int length = result + 1; + char *buf = new char[length]; + + // Restore the va_list before we use it again + va_copy(backup_ap, ap); + result = vsnprintf(buf, length, format, backup_ap); + va_end(backup_ap); + + if (result >= 0 && result < length) { + // It fit + dst->append(buf, result); + } + delete[] buf; +} + +std::string StrPrint(const char *format, ...) { + va_list ap; + va_start(ap, format); + std::string result; + StrAppend(&result, format, ap); + va_end(ap); + return result; +} + +class FormatConvertTest : public ::testing::Test { }; + +template +void TestStringConvert(const T& str) { + const FormatArgImpl args[] = {FormatArgImpl(str)}; + struct Expectation { + const char *out; + const char *fmt; + }; + const Expectation kExpect[] = { + {"hello", "%1$s" }, + {"", "%1$.s" }, + {"", "%1$.0s" }, + {"h", "%1$.1s" }, + {"he", "%1$.2s" }, + {"hello", "%1$.10s" }, + {" hello", "%1$6s" }, + {" he", "%1$5.2s" }, + {"he ", "%1$-5.2s" }, + {"hello ", "%1$-6.10s" }, + }; + for (const Expectation &e : kExpect) { + UntypedFormatSpecImpl format(e.fmt); + EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))); + } +} + +TEST_F(FormatConvertTest, BasicString) { + TestStringConvert("hello"); // As char array. + TestStringConvert(static_cast("hello")); + TestStringConvert(std::string("hello")); + TestStringConvert(string_view("hello")); +} + +TEST_F(FormatConvertTest, NullString) { + const char* p = nullptr; + UntypedFormatSpecImpl format("%s"); + EXPECT_EQ("", FormatPack(format, {FormatArgImpl(p)})); +} + +TEST_F(FormatConvertTest, StringPrecision) { + // We cap at the precision. + char c = 'a'; + const char* p = &c; + UntypedFormatSpecImpl format("%.1s"); + EXPECT_EQ("a", FormatPack(format, {FormatArgImpl(p)})); + + // We cap at the nul terminator. + p = "ABC"; + UntypedFormatSpecImpl format2("%.10s"); + EXPECT_EQ("ABC", FormatPack(format2, {FormatArgImpl(p)})); +} + +TEST_F(FormatConvertTest, Pointer) { +#if _MSC_VER + // MSVC's printf implementation prints pointers differently. We can't easily + // compare our implementation to theirs. + return; +#endif + static int x = 0; + const int *xp = &x; + char c = 'h'; + char *mcp = &c; + const char *cp = "hi"; + const char *cnil = nullptr; + const int *inil = nullptr; + using VoidF = void (*)(); + VoidF fp = [] {}, fnil = nullptr; + volatile char vc; + volatile char* vcp = &vc; + volatile char* vcnil = nullptr; + const FormatArgImpl args[] = { + FormatArgImpl(xp), FormatArgImpl(cp), FormatArgImpl(inil), + FormatArgImpl(cnil), FormatArgImpl(mcp), FormatArgImpl(fp), + FormatArgImpl(fnil), FormatArgImpl(vcp), FormatArgImpl(vcnil), + }; + struct Expectation { + std::string out; + const char *fmt; + }; + const Expectation kExpect[] = { + {StrPrint("%p", &x), "%p"}, + {StrPrint("%20p", &x), "%20p"}, + {StrPrint("%.1p", &x), "%.1p"}, + {StrPrint("%.20p", &x), "%.20p"}, + {StrPrint("%30.20p", &x), "%30.20p"}, + + {StrPrint("%-p", &x), "%-p"}, + {StrPrint("%-20p", &x), "%-20p"}, + {StrPrint("%-.1p", &x), "%-.1p"}, + {StrPrint("%.20p", &x), "%.20p"}, + {StrPrint("%-30.20p", &x), "%-30.20p"}, + + {StrPrint("%p", cp), "%2$p"}, // const char* + {"(nil)", "%3$p"}, // null const char * + {"(nil)", "%4$p"}, // null const int * + {StrPrint("%p", mcp), "%5$p"}, // nonconst char* + + {StrPrint("%p", fp), "%6$p"}, // function pointer + {StrPrint("%p", vcp), "%8$p"}, // function pointer + +#ifndef __APPLE__ + // Apple's printf differs here (0x0 vs. nil) + {StrPrint("%p", fnil), "%7$p"}, // null function pointer + {StrPrint("%p", vcnil), "%9$p"}, // null function pointer +#endif + }; + for (const Expectation &e : kExpect) { + UntypedFormatSpecImpl format(e.fmt); + EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))) << e.fmt; + } +} + +struct Cardinal { + enum Pos { k1 = 1, k2 = 2, k3 = 3 }; + enum Neg { kM1 = -1, kM2 = -2, kM3 = -3 }; +}; + +TEST_F(FormatConvertTest, Enum) { + const Cardinal::Pos k3 = Cardinal::k3; + const Cardinal::Neg km3 = Cardinal::kM3; + const FormatArgImpl args[] = {FormatArgImpl(k3), FormatArgImpl(km3)}; + UntypedFormatSpecImpl format("%1$d"); + UntypedFormatSpecImpl format2("%2$d"); + EXPECT_EQ("3", FormatPack(format, absl::MakeSpan(args))); + EXPECT_EQ("-3", FormatPack(format2, absl::MakeSpan(args))); +} + +template +class TypedFormatConvertTest : public FormatConvertTest { }; + +TYPED_TEST_CASE_P(TypedFormatConvertTest); + +std::vector AllFlagCombinations() { + const char kFlags[] = {'-', '#', '0', '+', ' '}; + std::vector result; + for (size_t fsi = 0; fsi < (1ull << ArraySize(kFlags)); ++fsi) { + std::string flag_set; + for (size_t fi = 0; fi < ArraySize(kFlags); ++fi) + if (fsi & (1ull << fi)) + flag_set += kFlags[fi]; + result.push_back(flag_set); + } + return result; +} + +TYPED_TEST_P(TypedFormatConvertTest, AllIntsWithFlags) { + typedef TypeParam T; + typedef typename std::make_unsigned::type UnsignedT; + using remove_volatile_t = typename std::remove_volatile::type; + const T kMin = std::numeric_limits::min(); + const T kMax = std::numeric_limits::max(); + const T kVals[] = { + remove_volatile_t(1), + remove_volatile_t(2), + remove_volatile_t(3), + remove_volatile_t(123), + remove_volatile_t(-1), + remove_volatile_t(-2), + remove_volatile_t(-3), + remove_volatile_t(-123), + remove_volatile_t(0), + kMax - remove_volatile_t(1), + kMax, + kMin + remove_volatile_t(1), + kMin, + }; + const char kConvChars[] = {'d', 'i', 'u', 'o', 'x', 'X'}; + const std::string kWid[] = {"", "4", "10"}; + const std::string kPrec[] = {"", ".", ".0", ".4", ".10"}; + + const std::vector flag_sets = AllFlagCombinations(); + + for (size_t vi = 0; vi < ArraySize(kVals); ++vi) { + const T val = kVals[vi]; + SCOPED_TRACE(Esc(val)); + const FormatArgImpl args[] = {FormatArgImpl(val)}; + for (size_t ci = 0; ci < ArraySize(kConvChars); ++ci) { + const char conv_char = kConvChars[ci]; + for (size_t fsi = 0; fsi < flag_sets.size(); ++fsi) { + const std::string &flag_set = flag_sets[fsi]; + for (size_t wi = 0; wi < ArraySize(kWid); ++wi) { + const std::string &wid = kWid[wi]; + for (size_t pi = 0; pi < ArraySize(kPrec); ++pi) { + const std::string &prec = kPrec[pi]; + + const bool is_signed_conv = (conv_char == 'd' || conv_char == 'i'); + const bool is_unsigned_to_signed = + !std::is_signed::value && is_signed_conv; + // Don't consider sign-related flags '+' and ' ' when doing + // unsigned to signed conversions. + if (is_unsigned_to_signed && + flag_set.find_first_of("+ ") != std::string::npos) { + continue; + } + + std::string new_fmt("%"); + new_fmt += flag_set; + new_fmt += wid; + new_fmt += prec; + // old and new always agree up to here. + std::string old_fmt = new_fmt; + new_fmt += conv_char; + std::string old_result; + if (is_unsigned_to_signed) { + // don't expect agreement on unsigned formatted as signed, + // as printf can't do that conversion properly. For those + // cases, we do expect agreement with printf with a "%u" + // and the unsigned equivalent of 'val'. + UnsignedT uval = val; + old_fmt += LengthModFor(uval); + old_fmt += "u"; + old_result = StrPrint(old_fmt.c_str(), uval); + } else { + old_fmt += LengthModFor(val); + old_fmt += conv_char; + old_result = StrPrint(old_fmt.c_str(), val); + } + + SCOPED_TRACE(std::string() + " old_fmt: \"" + old_fmt + + "\"'" + " new_fmt: \"" + + new_fmt + "\""); + UntypedFormatSpecImpl format(new_fmt); + EXPECT_EQ(old_result, FormatPack(format, absl::MakeSpan(args))); + } + } + } + } + } +} + +TYPED_TEST_P(TypedFormatConvertTest, Char) { + typedef TypeParam T; + using remove_volatile_t = typename std::remove_volatile::type; + static const T kMin = std::numeric_limits::min(); + static const T kMax = std::numeric_limits::max(); + T kVals[] = { + remove_volatile_t(1), remove_volatile_t(2), remove_volatile_t(10), + remove_volatile_t(-1), remove_volatile_t(-2), remove_volatile_t(-10), + remove_volatile_t(0), + kMin + remove_volatile_t(1), kMin, + kMax - remove_volatile_t(1), kMax + }; + for (const T &c : kVals) { + const FormatArgImpl args[] = {FormatArgImpl(c)}; + UntypedFormatSpecImpl format("%c"); + EXPECT_EQ(StrPrint("%c", c), FormatPack(format, absl::MakeSpan(args))); + } +} + +REGISTER_TYPED_TEST_CASE_P(TypedFormatConvertTest, AllIntsWithFlags, Char); + +typedef ::testing::Types< + int, unsigned, volatile int, + short, unsigned short, + long, unsigned long, + long long, unsigned long long, + signed char, unsigned char, char> + AllIntTypes; +INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes, + TypedFormatConvertTest, AllIntTypes); +TEST_F(FormatConvertTest, Uint128) { + absl::uint128 v = static_cast(0x1234567890abcdef) * 1979; + absl::uint128 max = absl::Uint128Max(); + const FormatArgImpl args[] = {FormatArgImpl(v), FormatArgImpl(max)}; + + struct Case { + const char* format; + const char* expected; + } cases[] = { + {"%1$d", "2595989796776606496405"}, + {"%1$30d", " 2595989796776606496405"}, + {"%1$-30d", "2595989796776606496405 "}, + {"%1$u", "2595989796776606496405"}, + {"%1$x", "8cba9876066020f695"}, + {"%2$d", "340282366920938463463374607431768211455"}, + {"%2$u", "340282366920938463463374607431768211455"}, + {"%2$x", "ffffffffffffffffffffffffffffffff"}, + }; + + for (auto c : cases) { + UntypedFormatSpecImpl format(c.format); + EXPECT_EQ(c.expected, FormatPack(format, absl::MakeSpan(args))); + } +} + +TEST_F(FormatConvertTest, Float) { +#if _MSC_VER + // MSVC has a different rounding policy than us so we can't test our + // implementation against the native one there. + return; +#endif // _MSC_VER + + const char *const kFormats[] = { + "%", "%.3", "%8.5", "%9", "%.60", "%.30", "%03", "%+", + "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; + + std::vector doubles = {0.0, + -0.0, + .99999999999999, + 99999999999999., + std::numeric_limits::max(), + -std::numeric_limits::max(), + std::numeric_limits::min(), + -std::numeric_limits::min(), + std::numeric_limits::lowest(), + -std::numeric_limits::lowest(), + std::numeric_limits::epsilon(), + std::numeric_limits::epsilon() + 1, + std::numeric_limits::infinity(), + -std::numeric_limits::infinity()}; + +#ifndef __APPLE__ + // Apple formats NaN differently (+nan) vs. (nan) + doubles.push_back(std::nan("")); +#endif + + // Some regression tests. + doubles.push_back(0.99999999999999989); + + if (std::numeric_limits::has_denorm != std::denorm_absent) { + doubles.push_back(std::numeric_limits::denorm_min()); + doubles.push_back(-std::numeric_limits::denorm_min()); + } + + for (double base : + {1., 12., 123., 1234., 12345., 123456., 1234567., 12345678., 123456789., + 1234567890., 12345678901., 123456789012., 1234567890123.}) { + for (int exp = -123; exp <= 123; ++exp) { + for (int sign : {1, -1}) { + doubles.push_back(sign * std::ldexp(base, exp)); + } + } + } + + for (const char *fmt : kFormats) { + for (char f : {'f', 'F', // + 'g', 'G', // + 'a', 'A', // + 'e', 'E'}) { + std::string fmt_str = std::string(fmt) + f; + for (double d : doubles) { + int i = -10; + FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)}; + UntypedFormatSpecImpl format(fmt_str); + // We use ASSERT_EQ here because failures are usually correlated and a + // bug would print way too many failed expectations causing the test to + // time out. + ASSERT_EQ(StrPrint(fmt_str.c_str(), d, i), + FormatPack(format, absl::MakeSpan(args))) + << fmt_str << " " << StrPrint("%.18g", d) << " " + << StrPrint("%.999f", d); + } + } + } +} + +TEST_F(FormatConvertTest, LongDouble) { + const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", + "%.60", "%+", "% ", "%-10"}; + + // This value is not representable in double, but it is in long double that + // uses the extended format. + // This is to verify that we are not truncating the value mistakenly through a + // double. + long double very_precise = 10000000000000000.25L; + + std::vector doubles = { + 0.0, + -0.0, + very_precise, + 1 / very_precise, + std::numeric_limits::max(), + -std::numeric_limits::max(), + std::numeric_limits::min(), + -std::numeric_limits::min(), + std::numeric_limits::infinity(), + -std::numeric_limits::infinity()}; + + for (const char *fmt : kFormats) { + for (char f : {'f', 'F', // + 'g', 'G', // + 'a', 'A', // + 'e', 'E'}) { + std::string fmt_str = std::string(fmt) + 'L' + f; + for (auto d : doubles) { + FormatArgImpl arg(d); + UntypedFormatSpecImpl format(fmt_str); + // We use ASSERT_EQ here because failures are usually correlated and a + // bug would print way too many failed expectations causing the test to + // time out. + ASSERT_EQ(StrPrint(fmt_str.c_str(), d), + FormatPack(format, {&arg, 1})) + << fmt_str << " " << StrPrint("%.18Lg", d) << " " + << StrPrint("%.999Lf", d); + } + } + } +} + +TEST_F(FormatConvertTest, IntAsFloat) { + const int kMin = std::numeric_limits::min(); + const int kMax = std::numeric_limits::max(); + const int ia[] = { + 1, 2, 3, 123, + -1, -2, -3, -123, + 0, kMax - 1, kMax, kMin + 1, kMin }; + for (const int fx : ia) { + SCOPED_TRACE(fx); + const FormatArgImpl args[] = {FormatArgImpl(fx)}; + struct Expectation { + int line; + std::string out; + const char *fmt; + }; + const double dx = static_cast(fx); + const Expectation kExpect[] = { + { __LINE__, StrPrint("%f", dx), "%f" }, + { __LINE__, StrPrint("%12f", dx), "%12f" }, + { __LINE__, StrPrint("%.12f", dx), "%.12f" }, + { __LINE__, StrPrint("%12a", dx), "%12a" }, + { __LINE__, StrPrint("%.12a", dx), "%.12a" }, + }; + for (const Expectation &e : kExpect) { + SCOPED_TRACE(e.line); + SCOPED_TRACE(e.fmt); + UntypedFormatSpecImpl format(e.fmt); + EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))); + } + } +} + +template +bool FormatFails(const char* test_format, T value) { + std::string format_string = std::string("<<") + test_format + ">>"; + UntypedFormatSpecImpl format(format_string); + + int one = 1; + const FormatArgImpl args[] = {FormatArgImpl(value), FormatArgImpl(one)}; + EXPECT_EQ(FormatPack(format, absl::MakeSpan(args)), "") + << "format=" << test_format << " value=" << value; + return FormatPack(format, absl::MakeSpan(args)).empty(); +} + +TEST_F(FormatConvertTest, ExpectedFailures) { + // Int input + EXPECT_TRUE(FormatFails("%p", 1)); + EXPECT_TRUE(FormatFails("%s", 1)); + EXPECT_TRUE(FormatFails("%n", 1)); + + // Double input + EXPECT_TRUE(FormatFails("%p", 1.)); + EXPECT_TRUE(FormatFails("%s", 1.)); + EXPECT_TRUE(FormatFails("%n", 1.)); + EXPECT_TRUE(FormatFails("%c", 1.)); + EXPECT_TRUE(FormatFails("%d", 1.)); + EXPECT_TRUE(FormatFails("%x", 1.)); + EXPECT_TRUE(FormatFails("%*d", 1.)); + + // String input + EXPECT_TRUE(FormatFails("%n", "")); + EXPECT_TRUE(FormatFails("%c", "")); + EXPECT_TRUE(FormatFails("%d", "")); + EXPECT_TRUE(FormatFails("%x", "")); + EXPECT_TRUE(FormatFails("%f", "")); + EXPECT_TRUE(FormatFails("%*d", "")); +} + +} // namespace +} // namespace str_format_internal +} // namespace absl -- cgit v1.2.3 From 5eea0f713c14ac17788b83e496f11903f8e2bbb0 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 11 Jan 2019 10:16:39 -0800 Subject: Export of internal Abseil changes. -- 70b243f160a2f0f222066f62e06cc4346aea683d by Gennadiy Civil : Replace tests with new googletest Test Suite APIs PiperOrigin-RevId: 228901526 -- 28fe449f416c3d3fe882ef3dfa4289b94be5f8af by CJ Johnson : Changes the style of enable_if on InlinedVector::insert(...) to match all others PiperOrigin-RevId: 228878640 -- 5b4732f783d16cfb19c8c42962201aafe12b3c0f by Abseil Team : Update the absl::FromDateTime() deprecation message to refer to absl::FromCivil(), the recommended replacement despite a slight change in behavior for skipped civil times. PiperOrigin-RevId: 228820837 -- ee77056d753bb8665236a173064af85d935acfc4 by Gennadiy Civil : Bump googletest to the latest PiperOrigin-RevId: 228792994 -- aebc04f76b83a26432dba8e6199c971d5b69df0f by CJ Johnson : Switches InlinedVector input/forward iterator tagged dispatch from callsite to template decorator PiperOrigin-RevId: 228771063 GitOrigin-RevId: 70b243f160a2f0f222066f62e06cc4346aea683d Change-Id: I5f8cd05685ff642eff81187b8e207a0bdbcf073a --- WORKSPACE | 6 +- absl/container/flat_hash_map_test.cc | 6 +- absl/container/flat_hash_set_test.cc | 6 +- absl/container/inlined_vector.h | 73 +++++++++++++--------- absl/container/inlined_vector_test.cc | 2 +- .../internal/hash_function_defaults_test.cc | 10 +-- .../internal/unordered_map_constructor_test.h | 2 +- .../container/internal/unordered_map_lookup_test.h | 2 +- .../internal/unordered_map_modifiers_test.h | 2 +- absl/container/internal/unordered_map_test.cc | 6 +- .../internal/unordered_set_constructor_test.h | 2 +- .../container/internal/unordered_set_lookup_test.h | 2 +- .../internal/unordered_set_modifiers_test.h | 2 +- absl/container/internal/unordered_set_test.cc | 6 +- absl/container/node_hash_map_test.cc | 6 +- absl/container/node_hash_set_test.cc | 6 +- absl/debugging/failure_signal_handler_test.cc | 6 +- absl/hash/hash_test.cc | 4 +- absl/numeric/int128_test.cc | 4 +- absl/strings/internal/str_format/convert_test.cc | 2 +- absl/synchronization/mutex_test.cc | 16 ++--- absl/time/time.h | 4 +- absl/types/variant_test.cc | 2 +- 23 files changed, 97 insertions(+), 80 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/WORKSPACE b/WORKSPACE index 72ef1398..49e2d3cb 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -15,9 +15,9 @@ http_archive( # GoogleTest/GoogleMock framework. Used by most unit-tests. http_archive( name = "com_google_googletest", - urls = ["https://github.com/google/googletest/archive/b4d4438df9479675a632b2f11125e57133822ece.zip"], # 2018-07-16 - strip_prefix = "googletest-b4d4438df9479675a632b2f11125e57133822ece", - sha256 = "5aaa5d566517cae711e2a3505ea9a6438be1b37fcaae0ebcb96ccba9aa56f23a", + urls = ["https://github.com/google/googletest/archive/b6cd405286ed8635ece71c72f118e659f4ade3fb.zip"], # 2019-01-07 + strip_prefix = "googletest-b6cd405286ed8635ece71c72f118e659f4ade3fb", + sha256 = "ff7a82736e158c077e76188232eac77913a15dac0b22508c390ab3f88e6d6d86", ) # Google benchmark. diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc index 2c6f2515..ccc055f7 100644 --- a/absl/container/flat_hash_map_test.cc +++ b/absl/container/flat_hash_map_test.cc @@ -40,9 +40,9 @@ using MapTypes = Map, Map, Map>; -INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, ConstructorTest, MapTypes); -INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, LookupTest, MapTypes); -INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, ModifiersTest, MapTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ConstructorTest, MapTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, LookupTest, MapTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ModifiersTest, MapTypes); TEST(FlatHashMap, StandardLayout) { struct Int { diff --git a/absl/container/flat_hash_set_test.cc b/absl/container/flat_hash_set_test.cc index e52fd532..afbe7748 100644 --- a/absl/container/flat_hash_set_test.cc +++ b/absl/container/flat_hash_set_test.cc @@ -40,9 +40,9 @@ using Set = using SetTypes = ::testing::Types, Set, Set, Set>; -INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, ConstructorTest, SetTypes); -INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, LookupTest, SetTypes); -INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, ModifiersTest, SetTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ConstructorTest, SetTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, LookupTest, SetTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ModifiersTest, SetTypes); TEST(FlatHashSet, EmplaceString) { std::vector v = {"a", "b"}; diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index c2f9d44b..7c574aec 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -71,18 +71,31 @@ class InlinedVector { return static_cast(N); } + template + using IsAtLeastInputIterator = std::is_convertible< + typename std::iterator_traits::iterator_category, + std::input_iterator_tag>; + + template + using IsAtLeastForwardIterator = std::is_convertible< + typename std::iterator_traits::iterator_category, + std::forward_iterator_tag>; + template using DisableIfIntegral = absl::enable_if_t::value>; template - using EnableIfInputIterator = absl::enable_if_t::iterator_category, - std::input_iterator_tag>::value>; + using EnableIfAtLeastInputIterator = + absl::enable_if_t::value>; + + template + using EnableIfAtLeastForwardIterator = + absl::enable_if_t::value>; template - using IteratorCategory = - typename std::iterator_traits::iterator_category; + using DisableIfAtLeastForwardIterator = + absl::enable_if_t::value>; using rvalue_reference = typename A::value_type&&; @@ -130,8 +143,7 @@ class InlinedVector { InlinedVector(std::initializer_list init_list, const allocator_type& alloc = allocator_type()) : allocator_and_tag_(alloc) { - AppendRange(init_list.begin(), init_list.end(), - IteratorCategory{}); + AppendRange(init_list.begin(), init_list.end()); } // Creates an inlined vector with elements constructed from the provided @@ -144,7 +156,7 @@ class InlinedVector { InlinedVector(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()) : allocator_and_tag_(alloc) { - AppendRange(first, last, IteratorCategory{}); + AppendRange(first, last); } // Creates a copy of `other` using `other`'s allocator. @@ -422,8 +434,7 @@ class InlinedVector { // Replaces the contents of the inlined vector with copies of the elements in // the provided `std::initializer_list`. InlinedVector& operator=(std::initializer_list init_list) { - AssignRange(init_list.begin(), init_list.end(), - IteratorCategory{}); + AssignRange(init_list.begin(), init_list.end()); return *this; } @@ -500,15 +511,14 @@ class InlinedVector { // inlined vector with copies of the values in the provided // `std::initializer_list`. void assign(std::initializer_list init_list) { - AssignRange(init_list.begin(), init_list.end(), - IteratorCategory{}); + AssignRange(init_list.begin(), init_list.end()); } // Overload of `InlinedVector::assign()` to replace the contents of the // inlined vector with values constructed from the range [`first`, `last`). template * = nullptr> void assign(InputIterator first, InputIterator last) { - AssignRange(first, last, IteratorCategory{}); + AssignRange(first, last); } // `InlinedVector::resize()` @@ -593,11 +603,10 @@ class InlinedVector { // NOTE: The `enable_if` is intended to disambiguate the two three-argument // overloads of `insert()`. template > + EnableIfAtLeastInputIterator* = nullptr> iterator insert(const_iterator position, InputIterator first, InputIterator last) { - return InsertWithRange(position, first, last, - IteratorCategory()); + return InsertWithRange(position, first, last); } // `InlinedVector::emplace()` @@ -1077,8 +1086,9 @@ class InlinedVector { } } - template - void AssignRange(Iterator first, Iterator last, std::forward_iterator_tag) { + template * = nullptr> + void AssignRange(ForwardIterator first, ForwardIterator last) { auto length = std::distance(first, last); // Prefer reassignment to copy construction for elements. if (static_cast(length) <= size()) { @@ -1097,8 +1107,9 @@ class InlinedVector { } } - template - void AssignRange(Iterator first, Iterator last, std::input_iterator_tag) { + template * = nullptr> + void AssignRange(InputIterator first, InputIterator last) { // Optimized to avoid reallocation. // Prefer reassignment to copy construction for elements. iterator out = begin(); @@ -1109,8 +1120,9 @@ class InlinedVector { std::copy(first, last, std::back_inserter(*this)); } - template - void AppendRange(Iterator first, Iterator last, std::forward_iterator_tag) { + template * = nullptr> + void AppendRange(ForwardIterator first, ForwardIterator last) { auto length = std::distance(first, last); reserve(size() + length); if (allocated()) { @@ -1122,8 +1134,9 @@ class InlinedVector { } } - template - void AppendRange(Iterator first, Iterator last, std::input_iterator_tag) { + template * = nullptr> + void AppendRange(InputIterator first, InputIterator last) { std::copy(first, last, std::back_inserter(*this)); } @@ -1140,9 +1153,10 @@ class InlinedVector { return it_pair.first; } - template + template * = nullptr> iterator InsertWithRange(const_iterator position, ForwardIterator first, - ForwardIterator last, std::forward_iterator_tag) { + ForwardIterator last) { assert(position >= begin() && position <= end()); if (ABSL_PREDICT_FALSE(first == last)) return const_cast(position); @@ -1150,15 +1164,16 @@ class InlinedVector { auto n = std::distance(first, last); std::pair it_pair = ShiftRight(position, n); size_type used_spots = it_pair.second - it_pair.first; - ForwardIterator open_spot = std::next(first, used_spots); + auto open_spot = std::next(first, used_spots); std::copy(first, open_spot, it_pair.first); UninitializedCopy(open_spot, last, it_pair.second); return it_pair.first; } - template + template * = nullptr> iterator InsertWithRange(const_iterator position, InputIterator first, - InputIterator last, std::input_iterator_tag) { + InputIterator last) { assert(position >= begin() && position <= end()); size_type index = position - cbegin(); size_type i = index; diff --git a/absl/container/inlined_vector_test.cc b/absl/container/inlined_vector_test.cc index b3dcc7f0..9408ee9d 100644 --- a/absl/container/inlined_vector_test.cc +++ b/absl/container/inlined_vector_test.cc @@ -70,7 +70,7 @@ MATCHER_P(ValueIs, e, "") { // test_instance_tracker.h. template class InstanceTest : public ::testing::Test {}; -TYPED_TEST_CASE_P(InstanceTest); +TYPED_TEST_SUITE_P(InstanceTest); // A simple reference counted class to make sure that the proper elements are // destroyed in the erase(begin, end) test. diff --git a/absl/container/internal/hash_function_defaults_test.cc b/absl/container/internal/hash_function_defaults_test.cc index 464baae0..e8f62503 100644 --- a/absl/container/internal/hash_function_defaults_test.cc +++ b/absl/container/internal/hash_function_defaults_test.cc @@ -77,14 +77,14 @@ struct EqString : ::testing::Test { hash_default_eq key_eq; }; -TYPED_TEST_CASE(EqString, StringTypes); +TYPED_TEST_SUITE(EqString, StringTypes); template struct HashString : ::testing::Test { hash_default_hash hasher; }; -TYPED_TEST_CASE(HashString, StringTypes); +TYPED_TEST_SUITE(HashString, StringTypes); TYPED_TEST(EqString, Works) { auto eq = this->key_eq; @@ -121,14 +121,14 @@ struct EqPointer : ::testing::Test { hash_default_eq key_eq; }; -TYPED_TEST_CASE(EqPointer, PointerTypes); +TYPED_TEST_SUITE(EqPointer, PointerTypes); template struct HashPointer : ::testing::Test { hash_default_hash hasher; }; -TYPED_TEST_CASE(HashPointer, PointerTypes); +TYPED_TEST_SUITE(HashPointer, PointerTypes); TYPED_TEST(EqPointer, Works) { int dummy; @@ -248,7 +248,7 @@ TYPED_TEST_P(StringLikeTest, HashEq) { EXPECT_NE(this->hash(this->a1), this->hash(this->b2)); } -TYPED_TEST_CASE(StringLikeTest, StringTypesCartesianProduct); +TYPED_TEST_SUITE(StringLikeTest, StringTypesCartesianProduct); } // namespace } // namespace container_internal diff --git a/absl/container/internal/unordered_map_constructor_test.h b/absl/container/internal/unordered_map_constructor_test.h index 87d6c3c3..e70c191a 100644 --- a/absl/container/internal/unordered_map_constructor_test.h +++ b/absl/container/internal/unordered_map_constructor_test.h @@ -29,7 +29,7 @@ namespace container_internal { template class ConstructorTest : public ::testing::Test {}; -TYPED_TEST_CASE_P(ConstructorTest); +TYPED_TEST_SUITE_P(ConstructorTest); TYPED_TEST_P(ConstructorTest, NoArgs) { TypeParam m; diff --git a/absl/container/internal/unordered_map_lookup_test.h b/absl/container/internal/unordered_map_lookup_test.h index a3d21595..488e340d 100644 --- a/absl/container/internal/unordered_map_lookup_test.h +++ b/absl/container/internal/unordered_map_lookup_test.h @@ -26,7 +26,7 @@ namespace container_internal { template class LookupTest : public ::testing::Test {}; -TYPED_TEST_CASE_P(LookupTest); +TYPED_TEST_SUITE_P(LookupTest); TYPED_TEST_P(LookupTest, At) { using T = hash_internal::GeneratedType; diff --git a/absl/container/internal/unordered_map_modifiers_test.h b/absl/container/internal/unordered_map_modifiers_test.h index 61ae7d63..2e1cd633 100644 --- a/absl/container/internal/unordered_map_modifiers_test.h +++ b/absl/container/internal/unordered_map_modifiers_test.h @@ -26,7 +26,7 @@ namespace container_internal { template class ModifiersTest : public ::testing::Test {}; -TYPED_TEST_CASE_P(ModifiersTest); +TYPED_TEST_SUITE_P(ModifiersTest); TYPED_TEST_P(ModifiersTest, Clear) { using T = hash_internal::GeneratedType; diff --git a/absl/container/internal/unordered_map_test.cc b/absl/container/internal/unordered_map_test.cc index 40e799cd..2752cb76 100644 --- a/absl/container/internal/unordered_map_test.cc +++ b/absl/container/internal/unordered_map_test.cc @@ -29,9 +29,9 @@ using MapTypes = ::testing::Types< StatefulTestingEqual, Alloc>>>; -INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, ConstructorTest, MapTypes); -INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, LookupTest, MapTypes); -INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, ModifiersTest, MapTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ConstructorTest, MapTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, LookupTest, MapTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ModifiersTest, MapTypes); } // namespace } // namespace container_internal diff --git a/absl/container/internal/unordered_set_constructor_test.h b/absl/container/internal/unordered_set_constructor_test.h index 9516e5ba..8997046a 100644 --- a/absl/container/internal/unordered_set_constructor_test.h +++ b/absl/container/internal/unordered_set_constructor_test.h @@ -29,7 +29,7 @@ namespace container_internal { template class ConstructorTest : public ::testing::Test {}; -TYPED_TEST_CASE_P(ConstructorTest); +TYPED_TEST_SUITE_P(ConstructorTest); TYPED_TEST_P(ConstructorTest, NoArgs) { TypeParam m; diff --git a/absl/container/internal/unordered_set_lookup_test.h b/absl/container/internal/unordered_set_lookup_test.h index 1421e7b6..69f43142 100644 --- a/absl/container/internal/unordered_set_lookup_test.h +++ b/absl/container/internal/unordered_set_lookup_test.h @@ -26,7 +26,7 @@ namespace container_internal { template class LookupTest : public ::testing::Test {}; -TYPED_TEST_CASE_P(LookupTest); +TYPED_TEST_SUITE_P(LookupTest); TYPED_TEST_P(LookupTest, Count) { using T = hash_internal::GeneratedType; diff --git a/absl/container/internal/unordered_set_modifiers_test.h b/absl/container/internal/unordered_set_modifiers_test.h index 445dcec4..853c4e31 100644 --- a/absl/container/internal/unordered_set_modifiers_test.h +++ b/absl/container/internal/unordered_set_modifiers_test.h @@ -26,7 +26,7 @@ namespace container_internal { template class ModifiersTest : public ::testing::Test {}; -TYPED_TEST_CASE_P(ModifiersTest); +TYPED_TEST_SUITE_P(ModifiersTest); TYPED_TEST_P(ModifiersTest, Clear) { using T = hash_internal::GeneratedType; diff --git a/absl/container/internal/unordered_set_test.cc b/absl/container/internal/unordered_set_test.cc index 1281ce53..04533bf0 100644 --- a/absl/container/internal/unordered_set_test.cc +++ b/absl/container/internal/unordered_set_test.cc @@ -28,9 +28,9 @@ using SetTypes = std::unordered_set>>; -INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, ConstructorTest, SetTypes); -INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, LookupTest, SetTypes); -INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, ModifiersTest, SetTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ConstructorTest, SetTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, LookupTest, SetTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ModifiersTest, SetTypes); } // namespace } // namespace container_internal diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc index bd789644..87ea4560 100644 --- a/absl/container/node_hash_map_test.cc +++ b/absl/container/node_hash_map_test.cc @@ -34,9 +34,9 @@ using MapTypes = ::testing::Types< StatefulTestingEqual, Alloc>>>; -INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, ConstructorTest, MapTypes); -INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, LookupTest, MapTypes); -INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, ModifiersTest, MapTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ConstructorTest, MapTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, LookupTest, MapTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ModifiersTest, MapTypes); using M = absl::node_hash_map>; diff --git a/absl/container/node_hash_set_test.cc b/absl/container/node_hash_set_test.cc index 7e498f0f..09cb7a98 100644 --- a/absl/container/node_hash_set_test.cc +++ b/absl/container/node_hash_set_test.cc @@ -34,9 +34,9 @@ using SetTypes = ::testing::Types< node_hash_set>>; -INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, ConstructorTest, SetTypes); -INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, LookupTest, SetTypes); -INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, ModifiersTest, SetTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ConstructorTest, SetTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, LookupTest, SetTypes); +INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ModifiersTest, SetTypes); TEST(NodeHashSet, MoveableNotCopyableCompiles) { node_hash_set> t; diff --git a/absl/debugging/failure_signal_handler_test.cc b/absl/debugging/failure_signal_handler_test.cc index ba520910..b0fe8f25 100644 --- a/absl/debugging/failure_signal_handler_test.cc +++ b/absl/debugging/failure_signal_handler_test.cc @@ -140,9 +140,9 @@ std::string SignalParamToString(const ::testing::TestParamInfo& info) { return result; } -INSTANTIATE_TEST_CASE_P(AbslDeathTest, FailureSignalHandlerDeathTest, - ::testing::ValuesIn(kFailureSignals), - SignalParamToString); +INSTANTIATE_TEST_SUITE_P(AbslDeathTest, FailureSignalHandlerDeathTest, + ::testing::ValuesIn(kFailureSignals), + SignalParamToString); #endif // GTEST_HAS_DEATH_TEST diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc index 7b6fb2e7..224832b1 100644 --- a/absl/hash/hash_test.cc +++ b/absl/hash/hash_test.cc @@ -50,7 +50,7 @@ using absl::hash_internal::SpyHashState; template class HashValueIntTest : public testing::Test { }; -TYPED_TEST_CASE_P(HashValueIntTest); +TYPED_TEST_SUITE_P(HashValueIntTest); template SpyHashState SpyHash(const T& value) { @@ -273,7 +273,7 @@ TEST(HashTest, NoOpsAreEquivalent) { template class HashIntTest : public testing::Test { }; -TYPED_TEST_CASE_P(HashIntTest); +TYPED_TEST_SUITE_P(HashIntTest); TYPED_TEST_P(HashIntTest, BasicUsage) { EXPECT_NE(Hash()({}), Hash()(0)); diff --git a/absl/numeric/int128_test.cc b/absl/numeric/int128_test.cc index dfe3475a..81c868d7 100644 --- a/absl/numeric/int128_test.cc +++ b/absl/numeric/int128_test.cc @@ -51,7 +51,7 @@ template class Uint128FloatTraitsTest : public ::testing::Test {}; typedef ::testing::Types FloatingPointTypes; -TYPED_TEST_CASE(Uint128IntegerTraitsTest, IntegerTypes); +TYPED_TEST_SUITE(Uint128IntegerTraitsTest, IntegerTypes); TYPED_TEST(Uint128IntegerTraitsTest, ConstructAssignTest) { static_assert(std::is_constructible::value, @@ -62,7 +62,7 @@ TYPED_TEST(Uint128IntegerTraitsTest, ConstructAssignTest) { "TypeParam must not be assignable from absl::uint128"); } -TYPED_TEST_CASE(Uint128FloatTraitsTest, FloatingPointTypes); +TYPED_TEST_SUITE(Uint128FloatTraitsTest, FloatingPointTypes); TYPED_TEST(Uint128FloatTraitsTest, ConstructAssignTest) { static_assert(std::is_constructible::value, diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 32f8a0f9..5d77856d 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -232,7 +232,7 @@ TEST_F(FormatConvertTest, Enum) { template class TypedFormatConvertTest : public FormatConvertTest { }; -TYPED_TEST_CASE_P(TypedFormatConvertTest); +TYPED_TEST_SUITE_P(TypedFormatConvertTest); std::vector AllFlagCombinations() { const char kFlags[] = {'-', '#', '0', '+', ' '}; diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc index b2820e20..92fcd53d 100644 --- a/absl/synchronization/mutex_test.cc +++ b/absl/synchronization/mutex_test.cc @@ -610,9 +610,9 @@ TEST_P(CondVarWaitDeadlock, Test) { waiter2.reset(); // "join" waiter2 } -INSTANTIATE_TEST_CASE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock, - ::testing::Range(0, 8), - ::testing::PrintToStringParamName()); +INSTANTIATE_TEST_SUITE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock, + ::testing::Range(0, 8), + ::testing::PrintToStringParamName()); // -------------------------------------------------------- // Test for fix of bug in DequeueAllWakeable() @@ -1367,8 +1367,8 @@ std::vector MakeTimeoutTestParamValues() { } // Instantiate `TimeoutTest` with `MakeTimeoutTestParamValues()`. -INSTANTIATE_TEST_CASE_P(All, TimeoutTest, - testing::ValuesIn(MakeTimeoutTestParamValues())); +INSTANTIATE_TEST_SUITE_P(All, TimeoutTest, + testing::ValuesIn(MakeTimeoutTestParamValues())); TEST_P(TimeoutTest, Await) { const TimeoutTestParam params = GetParam(); @@ -1548,9 +1548,9 @@ static std::vector AllThreadCountValues() { class MutexVariableThreadCountTest : public ::testing::TestWithParam {}; // Instantiate the above with AllThreadCountOptions(). -INSTANTIATE_TEST_CASE_P(ThreadCounts, MutexVariableThreadCountTest, - ::testing::ValuesIn(AllThreadCountValues()), - ::testing::PrintToStringParamName()); +INSTANTIATE_TEST_SUITE_P(ThreadCounts, MutexVariableThreadCountTest, + ::testing::ValuesIn(AllThreadCountValues()), + ::testing::PrintToStringParamName()); // Reduces iterations by some factor for slow platforms // (determined empirically). diff --git a/absl/time/time.h b/absl/time/time.h index ae3b3fad..3cf9ac02 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -1149,7 +1149,9 @@ TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour, // absl::Time t = absl::FromDateTime(2017, 9, 26, 9, 30, 0, lax); // // t = 2017-09-26 09:30:00 -0700 // -// Deprecated. Use `absl::TimeZone::At(CivilSecond).pre`. +// Deprecated. Use `absl::FromCivil(CivilSecond, TimeZone)`. Note that the +// behavior of `FromCivil()` differs from `FromDateTime()` for skipped civil +// times. If you care about that see `absl::TimeZone::At(absl::CivilSecond)`. inline Time FromDateTime(int64_t year, int mon, int day, int hour, int min, int sec, TimeZone tz) { return ConvertDateTime(year, mon, day, hour, min, sec, tz).pre; diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc index f47f3a72..80e8467e 100644 --- a/absl/types/variant_test.cc +++ b/absl/types/variant_test.cc @@ -257,7 +257,7 @@ class NonCopyable { // each type. template class VariantTypesTest : public ::testing::Test {}; -TYPED_TEST_CASE(VariantTypesTest, VariantTypes); +TYPED_TEST_SUITE(VariantTypesTest, VariantTypes); //////////////////// // [variant.ctor] // -- cgit v1.2.3 From bf29470384a101b307873b26d358433138c857fc Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 19 Mar 2019 11:14:01 -0700 Subject: Export of internal Abseil changes. -- bdce7e57e9e886eff1114d0266781b443f7ec639 by Derek Mauro : Change {Get|Set}EnvironmentVariable to {Get|Set}EnvironmentVariableA for compatibility with /DUNICODE. PiperOrigin-RevId: 239229514 -- 2276ed502326a044a84060d34eb19d499e3a3be2 by Derek Mauro : Import of CCTZ from GitHub. PiperOrigin-RevId: 239228622 -- a462efb970ff43b08a362ef2343fb75ac1295a50 by Derek Mauro : Adding linking of CoreFoundation to CMakeLists in absl/time. Import https://github.com/abseil/abseil-cpp/pull/280. Fix #283 PiperOrigin-RevId: 239220785 -- fc23327b97f940c682aae1956cf7a1bf87f88c06 by Derek Mauro : Add hermetic test script that uses Docker to build with a very recent version of gcc (8.3.0 today) with libstdc++ and bazel. PiperOrigin-RevId: 239220448 -- 418c08a8f6a53e63b84e39473035774417ca3aa7 by Derek Mauro : Disable part of the variant exeception safety test on move assignment when using versions of libstd++ that contain a bug. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7 PiperOrigin-RevId: 239062455 -- 799722217aeda79679577843c91d5be62cbcbb42 by Matt Calabrese : Add internal-only IsSwappable traits corresponding to std::is_swappable and std::is_nothrow_swappable, which are used with the swap implementations of optional and variant. PiperOrigin-RevId: 239049448 -- aa46a036038a3de5c68ac5e5d3b4bf76f818d2ea by CJ Johnson : Make InlinedVectorStorage constructor explicit PiperOrigin-RevId: 239044361 -- 17949715b3aa21c794701f69f2154e91b6acabc3 by CJ Johnson : Add absl namesapce to internal/inlined_vector.h PiperOrigin-RevId: 239030789 -- 834628325953078cc08ed10d23bb8890e5bec897 by Derek Mauro : Add test script that uses Docker to build Abseil with gcc-4.8, libstdc++, and cmake. PiperOrigin-RevId: 239028433 -- 80fe24149ed73ed2ced995ad1e372fb060c60427 by CJ Johnson : Factors data members of InlinedVector into an impl type called InlinedVectorStorage so that (in future changes) the contents of a vector can be grouped together with a single pointer. PiperOrigin-RevId: 239021086 -- 585331436d5d4d79f845e45dcf79d918a0dc6169 by Derek Mauro : Add -Wno-missing-field-initializers to gcc compiler flags. gcc-4.x has spurious missing field initializer warnings. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750 PiperOrigin-RevId: 239017217 -- 94602fe4e33ee3a552a7f2939c0f57a992f55075 by Abseil Team : Formatting fixes. PiperOrigin-RevId: 238983038 -- a1c1b63c08505574e0a8c491561840cecb2bb93e by Derek Mauro : Add hermetic test script that uses Docker to build with a very recent version of clang with libc++ and bazel. PiperOrigin-RevId: 238669118 -- e525f8d20bc2f79a0d69336b902f63858f3bff9d by Derek Mauro : Disable the test optionalTest.InPlaceTSFINAEBug until libc++ is updated. PiperOrigin-RevId: 238661703 -- f99a2a0b5ec424a059678f7f226600f137b4c74e by Derek Mauro : Correct the check for the FlatHashMap-Any test bug (list conditions instead of platforms when possible) PiperOrigin-RevId: 238653344 -- 777928035dbcbf39f361eb7d10dc3696822f692f by Jon Cohen : Add install rules for Abseil CMake. These are attempted to be limited to in-project installation. This serves two purposes -- first it's morally the same as using Abseil in-source, except you don't have to rebuild us every time. Second, the presence of an install rule makes life massively simpler for package manager maintainers. Currently this doesn't install absl tests or testonly libraries. This can be added in a follow-up patch. Fixes #38, Fixes #80, Closes #182 PiperOrigin-RevId: 238645836 -- ded1c6ce697c191b7a6ff14572b3e6d183117b2c by Derek Mauro : Add hermetic test script that uses Docker to build with a very recent version of clang with libstdc++ and bazel. PiperOrigin-RevId: 238517815 GitOrigin-RevId: bdce7e57e9e886eff1114d0266781b443f7ec639 Change-Id: I6f745869cb8ef63851891ccac05ae9a7dd241c4f --- CMake/AbseilHelpers.cmake | 39 +++-- CMake/abslConfig.cmake.in | 6 + CMakeLists.txt | 47 ++++++ absl/algorithm/container.h | 2 - absl/base/const_init.h | 1 - absl/base/dynamic_annotations.h | 1 + absl/base/internal/cycleclock.h | 1 - absl/base/internal/low_level_alloc.h | 1 + absl/base/internal/low_level_alloc_test.cc | 1 + absl/base/internal/low_level_scheduling.h | 3 +- absl/base/internal/raw_logging.h | 1 + absl/base/internal/scoped_set_env.cc | 6 +- absl/base/internal/scoped_set_env_test.cc | 4 +- absl/base/internal/thread_identity.h | 1 + absl/base/internal/unscaledcycleclock.h | 2 + absl/base/log_severity.h | 1 - absl/base/spinlock_test_common.cc | 2 + absl/base/thread_annotations.h | 2 +- absl/compiler_config_setting.bzl | 1 - absl/container/BUILD.bazel | 10 ++ absl/container/CMakeLists.txt | 12 ++ absl/container/fixed_array.h | 1 + absl/container/flat_hash_map_test.cc | 7 +- absl/container/inlined_vector.h | 180 +++++++-------------- absl/container/internal/hashtablez_sampler.h | 1 - absl/container/internal/inlined_vector.h | 130 +++++++++++++++ absl/container/internal/raw_hash_set_test.cc | 2 + absl/copts/GENERATED_AbseilCopts.cmake | 1 + absl/copts/GENERATED_copts.bzl | 1 + absl/copts/copts.py | 5 + absl/debugging/internal/address_is_readable.h | 1 - absl/debugging/internal/demangle_test.cc | 1 + absl/debugging/internal/stacktrace_x86-inl.inc | 1 + absl/debugging/leak_check.cc | 1 + absl/debugging/stacktrace.cc | 1 + absl/hash/hash.h | 1 + absl/hash/hash_test.cc | 1 + absl/hash/internal/city.h | 1 - absl/meta/type_traits.h | 61 +++++++ absl/meta/type_traits_test.cc | 81 ++++++++++ absl/numeric/int128.h | 1 - absl/strings/BUILD.bazel | 1 - absl/strings/escaping.h | 2 - absl/strings/internal/str_format/arg.h | 2 + absl/strings/internal/str_format/convert_test.cc | 1 + absl/strings/internal/str_format/extension.h | 1 - absl/strings/internal/str_format/extension_test.cc | 1 + absl/strings/internal/str_format/output_test.cc | 1 - absl/strings/internal/utf8.h | 1 - absl/strings/str_cat.h | 1 - absl/strings/str_format.h | 1 + absl/strings/str_split.h | 1 - absl/strings/string_view.h | 2 +- absl/strings/substitute.h | 1 - .../internal/create_thread_identity.h | 1 + absl/synchronization/internal/kernel_timeout.h | 2 + absl/synchronization/internal/per_thread_sem.cc | 1 + absl/synchronization/internal/per_thread_sem.h | 1 + absl/synchronization/internal/waiter.cc | 2 + absl/synchronization/mutex.cc | 1 + absl/synchronization/mutex.h | 4 + absl/synchronization/mutex_test.cc | 6 +- absl/synchronization/notification.h | 1 + absl/time/civil_time.h | 1 - absl/time/duration.cc | 1 + absl/time/internal/cctz/src/time_zone_lookup.cc | 2 +- absl/time/time.cc | 1 + absl/time/time.h | 3 +- absl/types/any_exception_safety_test.cc | 1 + absl/types/internal/variant.h | 5 +- absl/types/optional.h | 19 +-- absl/types/optional_test.cc | 2 + absl/types/variant.h | 17 +- absl/types/variant_exception_safety_test.cc | 9 ++ absl/types/variant_test.cc | 1 + absl/utility/utility.h | 1 - ci/linux_clang-latest_libcxx_bazel.sh | 62 +++++++ ci/linux_clang-latest_libstdcxx_bazel.sh | 61 +++++++ ci/linux_gcc-4.8_libstdcxx_cmake.sh | 61 +++++++ ci/linux_gcc-latest_libstdcxx_bazel.sh | 59 +++++++ 80 files changed, 770 insertions(+), 194 deletions(-) create mode 100644 CMake/abslConfig.cmake.in create mode 100644 absl/container/internal/inlined_vector.h create mode 100755 ci/linux_clang-latest_libcxx_bazel.sh create mode 100755 ci/linux_clang-latest_libstdcxx_bazel.sh create mode 100755 ci/linux_gcc-4.8_libstdcxx_cmake.sh create mode 100755 ci/linux_gcc-latest_libstdcxx_bazel.sh (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/CMake/AbseilHelpers.cmake b/CMake/AbseilHelpers.cmake index 8fdd510f..6d26169d 100644 --- a/CMake/AbseilHelpers.cmake +++ b/CMake/AbseilHelpers.cmake @@ -16,6 +16,7 @@ include(CMakeParseArguments) include(AbseilConfigureCopts) +include(GNUInstallDirs) # The IDE folder for Abseil that will be used if Abseil is included in a CMake # project that sets @@ -59,20 +60,17 @@ set(ABSL_IDE_FOLDER Abseil) # "b.cc" # DEPS # absl_internal_awesome # not "awesome"! +# PUBLIC # ) # -# If PUBLIC is set, absl_cc_library will instead create a target named -# absl_${NAME} and still an alias absl::${NAME}. -# # absl_cc_library( # NAME # main_lib # ... -# PUBLIC +# DEPS +# absl::fantastic_lib # since fantastic_lib is public # ) # -# User can then use the library as absl::main_lib (although absl_main_lib is defined too). -# # TODO: Implement "ALWAYSLINK" function(absl_cc_library) cmake_parse_arguments(ABSL_CC_LIB @@ -83,7 +81,7 @@ function(absl_cc_library) ) if (NOT ABSL_CC_LIB_TESTONLY OR ABSL_RUN_TESTS) - set(_NAME "absl_${ABSL_CC_LIB_NAME}") + set(_NAME "${ABSL_CC_LIB_NAME}") # Check if this is a header-only library # Note that as of February 2019, many popular OS's (for example, Ubuntu @@ -105,7 +103,10 @@ function(absl_cc_library) add_library(${_NAME} STATIC "") target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) target_include_directories(${_NAME} - PUBLIC ${ABSL_COMMON_INCLUDE_DIRS}) + PUBLIC + $ + $ + ) target_compile_options(${_NAME} PRIVATE ${ABSL_CC_LIB_COPTS}) target_link_libraries(${_NAME} @@ -126,17 +127,37 @@ function(absl_cc_library) # INTERFACE libraries can't have the CXX_STANDARD property set set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD}) set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON) + + # When being installed, we lose the absl_ prefix. We want to put it back + # to have properly named lib files. This is a no-op when we are not being + # installed. + set_target_properties(${_NAME} PROPERTIES + OUTPUT_NAME "absl_${_NAME}" + ) else() # Generating header-only library add_library(${_NAME} INTERFACE) target_include_directories(${_NAME} - INTERFACE ${ABSL_COMMON_INCLUDE_DIRS}) + INTERFACE + $ + $ + ) target_link_libraries(${_NAME} INTERFACE ${ABSL_CC_LIB_DEPS} ${ABSL_CC_LIB_LINKOPTS} ) target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES}) endif() + # TODO currently we don't install googletest alongside abseil sources, so + # installed abseil can't be tested. + if (NOT ABSL_CC_LIB_TESTONLY) + install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + endif() + add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME}) endif() endfunction() diff --git a/CMake/abslConfig.cmake.in b/CMake/abslConfig.cmake.in new file mode 100644 index 00000000..bf8c4f6a --- /dev/null +++ b/CMake/abslConfig.cmake.in @@ -0,0 +1,6 @@ +## absl CMake configuration file. Note that there is no corresponding +# abslConfigVersion.cmake since non-LTS Abseil isn't versioned. + +@PACKAGE_INIT@ + +include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 571e48c5..e3bb8d05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,14 +26,26 @@ if (POLICY CMP0025) cmake_policy(SET CMP0025 NEW) endif() +# if command can use IN_LIST +cmake_policy(SET CMP0057 NEW) + project(absl) +# when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp)) +# in the source tree of a project that uses it, install rules are disabled. +if(NOT "^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$") + set(ABSL_ENABLE_INSTALL FALSE) +else() + set(ABSL_ENABLE_INSTALL TRUE) +endif() + list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/CMake ${CMAKE_CURRENT_LIST_DIR}/absl/copts ) include(GNUInstallDirs) +include(CMakePackageConfigHelpers) include(AbseilHelpers) @@ -73,11 +85,23 @@ if(${ABSL_RUN_TESTS}) enable_testing() endif() +# We don't support system-wide installation +list(APPEND SYSTEM_INSTALL_DIRS "/usr/local" "/usr" "/opt/" "/opt/local" "c:/Program Files/${PROJECT_NAME}") +if(NOT DEFINED CMAKE_INSTALL_PREFIX OR CMAKE_INSTALL_PREFIX IN_LIST SYSTEM_INSTALL_DIRS) + message(WARNING "\ +The default and system-level install directories are unsupported except in LTS \ +releases of Abseil. Please set CMAKE_INSTALL_PREFIX to install Abseil in your \ +source or build tree directly.\ + ") +endif() + ## check targets if(BUILD_TESTING) if(${ABSL_USE_GOOGLETEST_HEAD}) include(CMake/DownloadGTest.cmake) + set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src) + set(absl_gtest_build_dir ${CMAKE_BINARY_DIR}/googletest-build) endif() check_target(gtest) @@ -93,3 +117,26 @@ if(BUILD_TESTING) endif() add_subdirectory(absl) + +# install as a subdirectory only +install(EXPORT ${PROJECT_NAME}Targets + NAMESPACE absl:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake" +) + +configure_package_config_file( + CMake/abslConfig.cmake.in + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake" +) + +install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake +) + +install(DIRECTORY absl + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING + PATTERN "*.inc" + PATTERN "*.h" +) diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h index 7348d632..752e47b2 100644 --- a/absl/algorithm/container.h +++ b/absl/algorithm/container.h @@ -36,7 +36,6 @@ // For template parameter and variable naming, `C` indicates the container type // to which the function is applied, `Pred` indicates the predicate object type // to be used by the function and `T` indicates the applicable element type. -// #ifndef ABSL_ALGORITHM_CONTAINER_H_ #define ABSL_ALGORITHM_CONTAINER_H_ @@ -648,7 +647,6 @@ container_algorithm_internal::ContainerIter c_generate_n(C& c, Size n, // and `unique()` are omitted, because it's not clear whether or not such // functions should call erase on their supplied sequences afterwards. Either // behavior would be surprising for a different set of users. -// // c_remove_copy() // diff --git a/absl/base/const_init.h b/absl/base/const_init.h index 1b2b8c2b..17858a77 100644 --- a/absl/base/const_init.h +++ b/absl/base/const_init.h @@ -60,7 +60,6 @@ // // The absl::kConstInit tag should only be used to define objects with static // or thread_local storage duration. -// namespace absl { diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h index cdeb18c2..ac33df9e 100644 --- a/absl/base/dynamic_annotations.h +++ b/absl/base/dynamic_annotations.h @@ -139,6 +139,7 @@ #define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) /* empty */ #define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) /* empty */ #endif /* DYNAMIC_ANNOTATIONS_ENABLED || MEMORY_SANITIZER */ + /* TODO(delesley) -- Replace __CLANG_SUPPORT_DYN_ANNOTATION__ with the appropriate feature ID. */ #if defined(__clang__) && (!defined(SWIG)) \ diff --git a/absl/base/internal/cycleclock.h b/absl/base/internal/cycleclock.h index 7874db71..794564e1 100644 --- a/absl/base/internal/cycleclock.h +++ b/absl/base/internal/cycleclock.h @@ -28,7 +28,6 @@ // not necessarily "CPU cycles" and code should not rely on that behavior, even // if experimentally observed. // -// // An arbitrary offset may have been added to the counter at power on. // // On some platforms, the rate and offset of the counter may differ diff --git a/absl/base/internal/low_level_alloc.h b/absl/base/internal/low_level_alloc.h index f83c7bc8..b35673de 100644 --- a/absl/base/internal/low_level_alloc.h +++ b/absl/base/internal/low_level_alloc.h @@ -119,4 +119,5 @@ class LowLevelAlloc { } // namespace base_internal } // namespace absl + #endif // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_ diff --git a/absl/base/internal/low_level_alloc_test.cc b/absl/base/internal/low_level_alloc_test.cc index d2d31820..34a080cb 100644 --- a/absl/base/internal/low_level_alloc_test.cc +++ b/absl/base/internal/low_level_alloc_test.cc @@ -137,6 +137,7 @@ static void Test(bool use_new_arena, bool call_malloc_hook, int n) { TEST_ASSERT(LowLevelAlloc::DeleteArena(arena)); } } + // LowLevelAlloc is designed to be safe to call before main(). static struct BeforeMain { BeforeMain() { diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 2a5a3847..0fcc8d3b 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -86,6 +86,7 @@ class SchedulingGuard { //------------------------------------------------------------------------------ // End of public interfaces. //------------------------------------------------------------------------------ + inline bool SchedulingGuard::ReschedulingIsAllowed() { return false; } @@ -98,7 +99,7 @@ inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) { return; } - } // namespace base_internal } // namespace absl + #endif // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_ diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h index 4cbbbe59..6a4c0936 100644 --- a/absl/base/internal/raw_logging.h +++ b/absl/base/internal/raw_logging.h @@ -38,6 +38,7 @@ // ABSL_RAW_LOG(ERROR, "Failed foo with %i: %s", status, error); // This will print an almost standard log line like this to stderr only: // E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file + #define ABSL_RAW_LOG(severity, ...) \ do { \ constexpr const char* absl_raw_logging_internal_basename = \ diff --git a/absl/base/internal/scoped_set_env.cc b/absl/base/internal/scoped_set_env.cc index 9b164124..3ac3f68d 100644 --- a/absl/base/internal/scoped_set_env.cc +++ b/absl/base/internal/scoped_set_env.cc @@ -33,7 +33,7 @@ const int kMaxEnvVarValueSize = 1024; void SetEnvVar(const char* name, const char* value) { #ifdef _WIN32 - SetEnvironmentVariable(name, value); + SetEnvironmentVariableA(name, value); #else if (value == nullptr) { ::unsetenv(name); @@ -49,7 +49,7 @@ ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value) : var_name_(var_name), was_unset_(false) { #ifdef _WIN32 char buf[kMaxEnvVarValueSize]; - auto get_res = GetEnvironmentVariable(var_name_.c_str(), buf, sizeof(buf)); + auto get_res = GetEnvironmentVariableA(var_name_.c_str(), buf, sizeof(buf)); ABSL_INTERNAL_CHECK(get_res < sizeof(buf), "value exceeds buffer size"); if (get_res == 0) { @@ -58,7 +58,7 @@ ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value) old_value_.assign(buf, get_res); } - SetEnvironmentVariable(var_name_.c_str(), new_value); + SetEnvironmentVariableA(var_name_.c_str(), new_value); #else const char* val = ::getenv(var_name_.c_str()); if (val == nullptr) { diff --git a/absl/base/internal/scoped_set_env_test.cc b/absl/base/internal/scoped_set_env_test.cc index 4bd68c48..5cbad246 100644 --- a/absl/base/internal/scoped_set_env_test.cc +++ b/absl/base/internal/scoped_set_env_test.cc @@ -26,8 +26,8 @@ using absl::base_internal::ScopedSetEnv; std::string GetEnvVar(const char* name) { #ifdef _WIN32 char buf[1024]; - auto get_res = GetEnvironmentVariable(name, buf, sizeof(buf)); - if (get_res == sizeof(buf)) { + auto get_res = GetEnvironmentVariableA(name, buf, sizeof(buf)); + if (get_res >= sizeof(buf)) { return "TOO_BIG"; } diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h index dde3e010..b34674a6 100644 --- a/absl/base/internal/thread_identity.h +++ b/absl/base/internal/thread_identity.h @@ -237,4 +237,5 @@ inline ThreadIdentity* CurrentThreadIdentityIfPresent() { } // namespace base_internal } // namespace absl + #endif // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_ diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h index d5e186a9..58950cc2 100644 --- a/absl/base/internal/unscaledcycleclock.h +++ b/absl/base/internal/unscaledcycleclock.h @@ -83,6 +83,7 @@ defined(_M_IX86) || defined(_M_X64)) #define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY #endif + namespace absl { namespace time_internal { class UnscaledCycleClockWrapperForGetCurrentTime; @@ -114,6 +115,7 @@ class UnscaledCycleClock { } // namespace base_internal } // namespace absl + #endif // ABSL_USE_UNSCALED_CYCLECLOCK #endif // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_ diff --git a/absl/base/log_severity.h b/absl/base/log_severity.h index 4b9833eb..b19a7ffa 100644 --- a/absl/base/log_severity.h +++ b/absl/base/log_severity.h @@ -11,7 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// #ifndef ABSL_BASE_INTERNAL_LOG_SEVERITY_H_ #define ABSL_BASE_INTERNAL_LOG_SEVERITY_H_ diff --git a/absl/base/spinlock_test_common.cc b/absl/base/spinlock_test_common.cc index b32cea29..e62b2eae 100644 --- a/absl/base/spinlock_test_common.cc +++ b/absl/base/spinlock_test_common.cc @@ -54,6 +54,7 @@ namespace { static constexpr int kArrayLength = 10; static uint32_t values[kArrayLength]; + static SpinLock static_spinlock(base_internal::kLinkerInitialized); static SpinLock static_cooperative_spinlock( base_internal::kLinkerInitialized, @@ -189,6 +190,7 @@ TEST(SpinLock, WaitCyclesEncoding) { SpinLockTest::DecodeWaitCycles(before_max_value); EXPECT_GT(expected_max_value_decoded, before_max_value_decoded); } + TEST(SpinLockWithThreads, StaticSpinLock) { ThreadedTest(&static_spinlock); } diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h index a8162d41..0b2c306c 100644 --- a/absl/base/thread_annotations.h +++ b/absl/base/thread_annotations.h @@ -21,7 +21,6 @@ // code. The annotations can also help program analysis tools to identify // potential thread safety issues. // -// // These annotations are implemented using compiler attributes. Using the macros // defined here instead of raw attributes allow for portability and future // compatibility. @@ -34,6 +33,7 @@ #ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_ #define ABSL_BASE_THREAD_ANNOTATIONS_H_ + #if defined(__clang__) #define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) #else diff --git a/absl/compiler_config_setting.bzl b/absl/compiler_config_setting.bzl index e03f94ec..66962294 100644 --- a/absl/compiler_config_setting.bzl +++ b/absl/compiler_config_setting.bzl @@ -12,7 +12,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# """Creates config_setting that allows selecting based on 'compiler' value.""" diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index b6592ca5..cd914baf 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel @@ -111,11 +111,21 @@ cc_test( ], ) +cc_library( + name = "inlined_vector_internal", + hdrs = ["internal/inlined_vector.h"], + copts = ABSL_DEFAULT_COPTS, + deps = [ + "//absl/meta:type_traits", + ], +) + cc_library( name = "inlined_vector", hdrs = ["inlined_vector.h"], copts = ABSL_DEFAULT_COPTS, deps = [ + ":inlined_vector_internal", "//absl/algorithm", "//absl/base:core_headers", "//absl/base:throw_delegate", diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index 76542be1..292fea2a 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt @@ -107,6 +107,18 @@ absl_cc_test( gmock_main ) +absl_cc_library( + NAME + inlined_vector_internal + HDRS + "internal/inlined_vector.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::type_traits + PUBLIC +) + absl_cc_library( NAME inlined_vector diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h index 0161d0a9..2a8240ae 100644 --- a/absl/container/fixed_array.h +++ b/absl/container/fixed_array.h @@ -515,4 +515,5 @@ void FixedArray::NonEmptyInlinedStorage::AnnotateDestruct( static_cast(n); // Mark used when not in asan mode } } // namespace absl + #endif // ABSL_CONTAINER_FIXED_ARRAY_H_ diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc index bae5c15d..ebcb560f 100644 --- a/absl/container/flat_hash_map_test.cc +++ b/absl/container/flat_hash_map_test.cc @@ -206,7 +206,9 @@ TEST(FlatHashMap, MergeExtractInsert) { m.insert(std::move(node)); EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 17), Pair(2, 9))); } -#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__) + +#if (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) && \ + !defined(__EMSCRIPTEN__) TEST(FlatHashMap, Any) { absl::flat_hash_map m; m.emplace(1, 7); @@ -237,7 +239,8 @@ TEST(FlatHashMap, Any) { ASSERT_NE(it2, m2.end()); EXPECT_EQ(7, it2->second); } -#endif // __ANDROID__ +#endif // (defined(ABSL_HAVE_STD_ANY) || !defined(_LIBCPP_VERSION)) && + // !defined(__EMSCRIPTEN__) } // namespace } // namespace container_internal diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index 80929e36..68308750 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -1,4 +1,4 @@ -// Copyright 2018 The Abseil Authors. +// Copyright 2019 The Abseil Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -50,6 +50,7 @@ #include "absl/base/internal/throw_delegate.h" #include "absl/base/optimization.h" #include "absl/base/port.h" +#include "absl/container/internal/inlined_vector.h" #include "absl/memory/memory.h" namespace absl { @@ -65,10 +66,10 @@ namespace absl { // designed to cover the same API footprint as covered by `std::vector`. template > class InlinedVector { - static_assert(N > 0, "InlinedVector requires inline capacity greater than 0"); - constexpr static typename A::size_type GetInlinedCapacity() { - return static_cast(N); - } + using Storage = inlined_vector_internal::InlinedVectorStorage; + using Tag = typename Storage::Tag; + using AllocatorAndTag = typename Storage::AllocatorAndTag; + using Allocation = typename Storage::Allocation; template using IsAtLeastForwardIterator = std::is_convertible< @@ -83,21 +84,21 @@ class InlinedVector { using DisableIfAtLeastForwardIterator = absl::enable_if_t::value>; - using rvalue_reference = typename A::value_type&&; + using rvalue_reference = typename Storage::rvalue_reference; public: - using allocator_type = A; - using value_type = typename allocator_type::value_type; - using pointer = typename allocator_type::pointer; - using const_pointer = typename allocator_type::const_pointer; - using reference = typename allocator_type::reference; - using const_reference = typename allocator_type::const_reference; - using size_type = typename allocator_type::size_type; - using difference_type = typename allocator_type::difference_type; - using iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; + using allocator_type = typename Storage::allocator_type; + using value_type = typename Storage::value_type; + using pointer = typename Storage::pointer; + using const_pointer = typename Storage::const_pointer; + using reference = typename Storage::reference; + using const_reference = typename Storage::const_reference; + using size_type = typename Storage::size_type; + using difference_type = typename Storage::difference_type; + using iterator = typename Storage::iterator; + using const_iterator = typename Storage::const_iterator; + using reverse_iterator = typename Storage::reverse_iterator; + using const_reverse_iterator = typename Storage::const_reverse_iterator; // --------------------------------------------------------------------------- // InlinedVector Constructors and Destructor @@ -105,30 +106,30 @@ class InlinedVector { // Creates an empty inlined vector with a default initialized allocator. InlinedVector() noexcept(noexcept(allocator_type())) - : allocator_and_tag_(allocator_type()) {} + : storage_(allocator_type()) {} // Creates an empty inlined vector with a specified allocator. explicit InlinedVector(const allocator_type& alloc) noexcept - : allocator_and_tag_(alloc) {} + : storage_(alloc) {} // Creates an inlined vector with `n` copies of `value_type()`. explicit InlinedVector(size_type n, const allocator_type& alloc = allocator_type()) - : allocator_and_tag_(alloc) { + : storage_(alloc) { InitAssign(n); } // Creates an inlined vector with `n` copies of `v`. InlinedVector(size_type n, const_reference v, const allocator_type& alloc = allocator_type()) - : allocator_and_tag_(alloc) { + : storage_(alloc) { InitAssign(n, v); } // Creates an inlined vector of copies of the values in `list`. InlinedVector(std::initializer_list list, const allocator_type& alloc = allocator_type()) - : allocator_and_tag_(alloc) { + : storage_(alloc) { AppendForwardRange(list.begin(), list.end()); } @@ -142,7 +143,7 @@ class InlinedVector { EnableIfAtLeastForwardIterator* = nullptr> InlinedVector(ForwardIterator first, ForwardIterator last, const allocator_type& alloc = allocator_type()) - : allocator_and_tag_(alloc) { + : storage_(alloc) { AppendForwardRange(first, last); } @@ -152,7 +153,7 @@ class InlinedVector { DisableIfAtLeastForwardIterator* = nullptr> InlinedVector(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()) - : allocator_and_tag_(alloc) { + : storage_(alloc) { std::copy(first, last, std::back_inserter(*this)); } @@ -162,7 +163,7 @@ class InlinedVector { // Creates a copy of an `other` inlined vector using a specified allocator. InlinedVector(const InlinedVector& other, const allocator_type& alloc) - : allocator_and_tag_(alloc) { + : storage_(alloc) { reserve(other.size()); if (allocated()) { UninitializedCopy(other.begin(), other.end(), allocated_space()); @@ -191,7 +192,7 @@ class InlinedVector { InlinedVector(InlinedVector&& other) noexcept( absl::allocator_is_nothrow::value || std::is_nothrow_move_constructible::value) - : allocator_and_tag_(other.allocator()) { + : storage_(other.allocator()) { if (other.allocated()) { // We can just steal the underlying buffer from the source. // That leaves the source empty, so we clear its size. @@ -222,7 +223,7 @@ class InlinedVector { // ownership of `other`'s allocated memory. InlinedVector(InlinedVector&& other, const allocator_type& alloc) noexcept( absl::allocator_is_nothrow::value) - : allocator_and_tag_(alloc) { + : storage_(alloc) { if (other.allocated()) { if (alloc == other.allocator()) { // We can just steal the allocation from the source. @@ -282,7 +283,8 @@ class InlinedVector { // will no longer be inlined and `capacity()` will equal its capacity on the // allocated heap. size_type capacity() const noexcept { - return allocated() ? allocation().capacity() : GetInlinedCapacity(); + return allocated() ? allocation().capacity() + : Storage::GetInlinedCapacity(); } // `InlinedVector::data()` @@ -800,19 +802,19 @@ class InlinedVector { // `InlinedVector::shrink_to_fit()` // // Reduces memory usage by freeing unused memory. After this call, calls to - // `capacity()` will be equal to `(std::max)(GetInlinedCapacity(), size())`. + // `capacity()` will be equal to `max(Storage::GetInlinedCapacity(), size())`. // - // If `size() <= GetInlinedCapacity()` and the elements are currently stored - // on the heap, they will be moved to the inlined storage and the heap memory - // will be deallocated. + // If `size() <= Storage::GetInlinedCapacity()` and the elements are currently + // stored on the heap, they will be moved to the inlined storage and the heap + // memory will be deallocated. // - // If `size() > GetInlinedCapacity()` and `size() < capacity()` the elements - // will be moved to a smaller heap allocation. + // If `size() > Storage::GetInlinedCapacity()` and `size() < capacity()` the + // elements will be moved to a smaller heap allocation. void shrink_to_fit() { const auto s = size(); if (ABSL_PREDICT_FALSE(!allocated() || s == capacity())) return; - if (s <= GetInlinedCapacity()) { + if (s <= Storage::GetInlinedCapacity()) { // Move the elements to the inlined storage. // We have to do this using a temporary, because `inlined_storage` and // `allocation_storage` are in a union field. @@ -845,88 +847,33 @@ class InlinedVector { template friend auto AbslHashValue(H h, const InlinedVector& v) -> H; - // Holds whether the vector is allocated or not in the lowest bit and the size - // in the high bits: - // `size_ = (size << 1) | is_allocated;` - class Tag { - public: - Tag() : size_(0) {} - size_type size() const { return size_ / 2; } - void add_size(size_type n) { size_ += n * 2; } - void set_inline_size(size_type n) { size_ = n * 2; } - void set_allocated_size(size_type n) { size_ = (n * 2) + 1; } - bool allocated() const { return size_ % 2; } - - private: - size_type size_; - }; - - // Derives from `allocator_type` to use the empty base class optimization. - // If the `allocator_type` is stateless, we can store our instance for free. - class AllocatorAndTag : private allocator_type { - public: - explicit AllocatorAndTag(const allocator_type& a) : allocator_type(a) {} - - Tag& tag() { return tag_; } - const Tag& tag() const { return tag_; } - - allocator_type& allocator() { return *this; } - const allocator_type& allocator() const { return *this; } - - private: - Tag tag_; - }; - - class Allocation { - public: - Allocation(allocator_type& a, size_type capacity) - : capacity_(capacity), buffer_(Create(a, capacity)) {} - - void Dealloc(allocator_type& a) { - std::allocator_traits::deallocate(a, buffer_, capacity_); - } - - size_type capacity() const { return capacity_; } - - const_pointer buffer() const { return buffer_; } - - pointer buffer() { return buffer_; } + const Tag& tag() const { return storage_.allocator_and_tag_.tag(); } - private: - static pointer Create(allocator_type& a, size_type n) { - return std::allocator_traits::allocate(a, n); - } - - size_type capacity_; - pointer buffer_; - }; - - const Tag& tag() const { return allocator_and_tag_.tag(); } - - Tag& tag() { return allocator_and_tag_.tag(); } + Tag& tag() { return storage_.allocator_and_tag_.tag(); } Allocation& allocation() { - return reinterpret_cast(rep_.allocation_storage.allocation); + return reinterpret_cast( + storage_.rep_.allocation_storage.allocation); } const Allocation& allocation() const { return reinterpret_cast( - rep_.allocation_storage.allocation); + storage_.rep_.allocation_storage.allocation); } void init_allocation(const Allocation& allocation) { - new (&rep_.allocation_storage.allocation) Allocation(allocation); + new (&storage_.rep_.allocation_storage.allocation) Allocation(allocation); } // TODO(absl-team): investigate whether the reinterpret_cast is appropriate. pointer inlined_space() { return reinterpret_cast( - std::addressof(rep_.inlined_storage.inlined[0])); + std::addressof(storage_.rep_.inlined_storage.inlined[0])); } const_pointer inlined_space() const { return reinterpret_cast( - std::addressof(rep_.inlined_storage.inlined[0])); + std::addressof(storage_.rep_.inlined_storage.inlined[0])); } pointer allocated_space() { return allocation().buffer(); } @@ -934,10 +881,12 @@ class InlinedVector { const_pointer allocated_space() const { return allocation().buffer(); } const allocator_type& allocator() const { - return allocator_and_tag_.allocator(); + return storage_.allocator_and_tag_.allocator(); } - allocator_type& allocator() { return allocator_and_tag_.allocator(); } + allocator_type& allocator() { + return storage_.allocator_and_tag_.allocator(); + } bool allocated() const { return tag().allocated(); } @@ -994,7 +943,7 @@ class InlinedVector { const size_type s = size(); assert(s <= capacity()); - size_type target = (std::max)(GetInlinedCapacity(), s + delta); + size_type target = (std::max)(Storage::GetInlinedCapacity(), s + delta); // Compute new capacity by repeatedly doubling current capacity // TODO(psrc): Check and avoid overflow? @@ -1097,7 +1046,7 @@ class InlinedVector { } void InitAssign(size_type n) { - if (n > GetInlinedCapacity()) { + if (n > Storage::GetInlinedCapacity()) { Allocation new_allocation(allocator(), n); init_allocation(new_allocation); UninitializedFill(allocated_space(), allocated_space() + n); @@ -1109,7 +1058,7 @@ class InlinedVector { } void InitAssign(size_type n, const_reference v) { - if (n > GetInlinedCapacity()) { + if (n > Storage::GetInlinedCapacity()) { Allocation new_allocation(allocator(), n); init_allocation(new_allocation); UninitializedFill(allocated_space(), allocated_space() + n, v); @@ -1267,28 +1216,7 @@ class InlinedVector { assert(a->size() == b_size); } - // Stores either the inlined or allocated representation - union Rep { - using ValueTypeBuffer = - absl::aligned_storage_t; - using AllocationBuffer = - absl::aligned_storage_t; - - // Structs wrap the buffers to perform indirection that solves a bizarre - // compilation error on Visual Studio (all known versions). - struct InlinedRep { - ValueTypeBuffer inlined[N]; - }; - struct AllocatedRep { - AllocationBuffer allocation; - }; - - InlinedRep inlined_storage; - AllocatedRep allocation_storage; - }; - - AllocatorAndTag allocator_and_tag_; - Rep rep_; + Storage storage_; }; // ----------------------------------------------------------------------------- diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h index aff8d15f..a308e788 100644 --- a/absl/container/internal/hashtablez_sampler.h +++ b/absl/container/internal/hashtablez_sampler.h @@ -34,7 +34,6 @@ // are using a table in an unusual circumstance where allocation or calling a // linux syscall is unacceptable, this could interfere. // -// // This utility is internal-only. Use at your own risk. #ifndef ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_ diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h new file mode 100644 index 00000000..30850609 --- /dev/null +++ b/absl/container/internal/inlined_vector.h @@ -0,0 +1,130 @@ +// Copyright 2019 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_ +#define ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_ + +#include +#include +#include + +#include "absl/meta/type_traits.h" + +namespace absl { +namespace inlined_vector_internal { + +template +class InlinedVectorStorage { + static_assert( + N > 0, "InlinedVector cannot be instantiated with `0` inline elements."); + + public: + using allocator_type = A; + using value_type = typename allocator_type::value_type; + using pointer = typename allocator_type::pointer; + using const_pointer = typename allocator_type::const_pointer; + using reference = typename allocator_type::reference; + using const_reference = typename allocator_type::const_reference; + using rvalue_reference = typename allocator_type::value_type&&; + using size_type = typename allocator_type::size_type; + using difference_type = typename allocator_type::difference_type; + using iterator = pointer; + using const_iterator = const_pointer; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + constexpr static size_type GetInlinedCapacity() { + return static_cast(N); + } + + explicit InlinedVectorStorage(const allocator_type& a) + : allocator_and_tag_(a) {} + + // TODO(johnsoncj): Make the below types and members private after migration + + // Holds whether the vector is allocated or not in the lowest bit and the size + // in the high bits: + // `size_ = (size << 1) | is_allocated;` + class Tag { + size_type size_; + + public: + Tag() : size_(0) {} + size_type size() const { return size_ / 2; } + void add_size(size_type n) { size_ += n * 2; } + void set_inline_size(size_type n) { size_ = n * 2; } + void set_allocated_size(size_type n) { size_ = (n * 2) + 1; } + bool allocated() const { return size_ % 2; } + }; + + // Derives from `allocator_type` to use the empty base class optimization. + // If the `allocator_type` is stateless, we can store our instance for free. + class AllocatorAndTag : private allocator_type { + Tag tag_; + + public: + explicit AllocatorAndTag(const allocator_type& a) : allocator_type(a) {} + Tag& tag() { return tag_; } + const Tag& tag() const { return tag_; } + allocator_type& allocator() { return *this; } + const allocator_type& allocator() const { return *this; } + }; + + class Allocation { + size_type capacity_; + pointer buffer_; + + public: + Allocation(allocator_type& a, size_type capacity) + : capacity_(capacity), buffer_(Create(a, capacity)) {} + void Dealloc(allocator_type& a) { + std::allocator_traits::deallocate(a, buffer_, capacity_); + } + size_type capacity() const { return capacity_; } + const_pointer buffer() const { return buffer_; } + pointer buffer() { return buffer_; } + static pointer Create(allocator_type& a, size_type n) { + return std::allocator_traits::allocate(a, n); + } + }; + + // Stores either the inlined or allocated representation + union Rep { + using ValueTypeBuffer = + absl::aligned_storage_t; + using AllocationBuffer = + absl::aligned_storage_t; + + // Structs wrap the buffers to perform indirection that solves a bizarre + // compilation error on Visual Studio (all known versions). + struct InlinedRep { + ValueTypeBuffer inlined[N]; + }; + + struct AllocatedRep { + AllocationBuffer allocation; + }; + + InlinedRep inlined_storage; + AllocatedRep allocation_storage; + }; + + AllocatorAndTag allocator_and_tag_; + Rep rep_; +}; + +} // namespace inlined_vector_internal +} // namespace absl + +#endif // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_ diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index 9e79cb38..87511148 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -1080,6 +1080,7 @@ ExpectedStats XorSeedExpectedStats() { ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width"); return {}; } + TEST(Table, DISABLED_EnsureNonQuadraticTopNXorSeedByProbeSeqLength) { ProbeStatsPerSize stats; std::vector sizes = {Group::kWidth << 5, Group::kWidth << 10}; @@ -1173,6 +1174,7 @@ ExpectedStats LinearTransformExpectedStats() { ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width"); return {}; } + TEST(Table, DISABLED_EnsureNonQuadraticTopNLinearTransformByProbeSeqLength) { ProbeStatsPerSize stats; std::vector sizes = {Group::kWidth << 5, Group::kWidth << 10}; diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake index 80c98193..d02ea193 100644 --- a/absl/copts/GENERATED_AbseilCopts.cmake +++ b/absl/copts/GENERATED_AbseilCopts.cmake @@ -20,6 +20,7 @@ list(APPEND GCC_FLAGS "-Wvarargs" "-Wvla" "-Wwrite-strings" + "-Wno-missing-field-initializers" "-Wno-sign-compare" ) diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl index a001347d..d23f4069 100644 --- a/absl/copts/GENERATED_copts.bzl +++ b/absl/copts/GENERATED_copts.bzl @@ -21,6 +21,7 @@ GCC_FLAGS = [ "-Wvarargs", "-Wvla", "-Wwrite-strings", + "-Wno-missing-field-initializers", "-Wno-sign-compare", ] diff --git a/absl/copts/copts.py b/absl/copts/copts.py index 4da8442d..5a2d91a3 100644 --- a/absl/copts/copts.py +++ b/absl/copts/copts.py @@ -10,6 +10,7 @@ compilation options: The generated copts are consumed by configure_copts.bzl and AbseilConfigureCopts.cmake. """ + COPT_VARS = { "GCC_FLAGS": [ "-Wall", @@ -24,6 +25,10 @@ COPT_VARS = { "-Wvarargs", "-Wvla", # variable-length array "-Wwrite-strings", + # gcc-4.x has spurious missing field initializer warnings. + # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750 + # Remove when gcc-4.x is no longer supported. + "-Wno-missing-field-initializers", # Google style does not use unsigned integers, though STL containers # have unsigned types. "-Wno-sign-compare", diff --git a/absl/debugging/internal/address_is_readable.h b/absl/debugging/internal/address_is_readable.h index 64c3f1ea..ca8003e6 100644 --- a/absl/debugging/internal/address_is_readable.h +++ b/absl/debugging/internal/address_is_readable.h @@ -11,7 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -// #ifndef ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_ #define ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_ diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index d410a232..883b92db 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -176,6 +176,7 @@ static void TestOnInput(const char* input) { TEST(DemangleRegression, NegativeLength) { TestOnInput("_ZZn4"); } + TEST(DemangleRegression, DeeplyNestedArrayType) { const int depth = 100000; std::string data = "_ZStI"; diff --git a/absl/debugging/internal/stacktrace_x86-inl.inc b/absl/debugging/internal/stacktrace_x86-inl.inc index 248966b0..25aa8bdf 100644 --- a/absl/debugging/internal/stacktrace_x86-inl.inc +++ b/absl/debugging/internal/stacktrace_x86-inl.inc @@ -33,6 +33,7 @@ #include "absl/debugging/internal/address_is_readable.h" #include "absl/debugging/internal/vdso_support.h" // a no-op on non-elf or non-glibc systems #include "absl/debugging/stacktrace.h" + #include "absl/base/internal/raw_logging.h" #if defined(__linux__) && defined(__i386__) diff --git a/absl/debugging/leak_check.cc b/absl/debugging/leak_check.cc index a1cae969..ffe3d1bd 100644 --- a/absl/debugging/leak_check.cc +++ b/absl/debugging/leak_check.cc @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. + // Wrappers around lsan_interface functions. // When lsan is not linked in, these functions are not available, // therefore Abseil code which depends on these functions is conditioned on the diff --git a/absl/debugging/stacktrace.cc b/absl/debugging/stacktrace.cc index 9935adfa..9de8782f 100644 --- a/absl/debugging/stacktrace.cc +++ b/absl/debugging/stacktrace.cc @@ -46,6 +46,7 @@ #include ABSL_STACKTRACE_INL_HEADER #else # error Cannot calculate stack trace: will need to write for your environment + # include "absl/debugging/internal/stacktrace_aarch64-inl.inc" # include "absl/debugging/internal/stacktrace_arm-inl.inc" # include "absl/debugging/internal/stacktrace_generic-inl.inc" diff --git a/absl/hash/hash.h b/absl/hash/hash.h index 94cb6747..c0ede35a 100644 --- a/absl/hash/hash.h +++ b/absl/hash/hash.h @@ -309,4 +309,5 @@ class HashState : public hash_internal::HashStateBase { }; } // namespace absl + #endif // ABSL_HASH_HASH_H_ diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc index a2430e7a..af959385 100644 --- a/absl/hash/hash_test.cc +++ b/absl/hash/hash_test.cc @@ -276,6 +276,7 @@ TEST(HashValueTest, Strings) { const std::string dup = "foofoo"; const std::string large = "large"; const std::string huge = std::string(5000, 'a'); + EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( std::string(), absl::string_view(), std::string(""), absl::string_view(""), diff --git a/absl/hash/internal/city.h b/absl/hash/internal/city.h index 1b3b4ef9..b43d3407 100644 --- a/absl/hash/internal/city.h +++ b/absl/hash/internal/city.h @@ -49,7 +49,6 @@ #include // for size_t. #include - namespace absl { namespace hash_internal { diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index 8a788dea..b1b14914 100644 --- a/absl/meta/type_traits.h +++ b/absl/meta/type_traits.h @@ -485,4 +485,65 @@ inline void AssertHashEnabled() { } // namespace absl +// An internal namespace that is required to implement the C++17 swap traits. +// +// NOTE: This is its own top-level namespace to avoid subtleties due to +// functions named "swap" that may appear in the absl namespace. +namespace absl_internal_swap { + +using std::swap; + +template +using IsSwappableImpl = decltype(swap(std::declval(), std::declval())); + +// NOTE: This dance with the default template parameter is for MSVC. +template (), std::declval()))>> +using IsNothrowSwappableImpl = typename std::enable_if::type; + +// IsSwappable +// +// Determines whether the standard swap idiom is a valid expression for +// arguments of type `T`. +template +struct IsSwappable + : absl::type_traits_internal::is_detected {}; + +// IsNothrowSwappable +// +// Determines whether the standard swap idiom is a valid expression for +// arguments of type `T` and is noexcept. +template +struct IsNothrowSwappable + : absl::type_traits_internal::is_detected {}; + +// Swap() +// +// Performs the swap idiom from a namespace with no additional `swap` overloads. +template ::value, int> = 0> +void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable::value) { + swap(lhs, rhs); +} + +} // namespace absl_internal_swap + +namespace absl { +namespace type_traits_internal { + +// Make the swap-related traits/function accessible from this namespace. +using absl_internal_swap::IsNothrowSwappable; +using absl_internal_swap::IsSwappable; +using absl_internal_swap::Swap; + +// StdSwapIsUnconstrained +// +// Some standard library implementations are broken in that they do not +// constrain `std::swap`. This will effectively tell us if we are dealing with +// one of those implementations. +using StdSwapIsUnconstrained = IsSwappable; + +} // namespace type_traits_internal +} // namespace absl + #endif // ABSL_META_TYPE_TRAITS_H_ diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc index 29a6db69..912336e9 100644 --- a/absl/meta/type_traits_test.cc +++ b/absl/meta/type_traits_test.cc @@ -953,4 +953,85 @@ TEST(TypeTraitsTest, IsMoveAssignable) { #endif // _LIBCPP_VERSION } +namespace adl_namespace { + +struct DeletedSwap { +}; + +void swap(DeletedSwap&, DeletedSwap&) = delete; + +struct SpecialNoexceptSwap { + SpecialNoexceptSwap(SpecialNoexceptSwap&&) {} + SpecialNoexceptSwap& operator=(SpecialNoexceptSwap&&) { return *this; } + ~SpecialNoexceptSwap() = default; +}; + +void swap(SpecialNoexceptSwap&, SpecialNoexceptSwap&) noexcept {} + +} // namespace adl_namespace + +TEST(TypeTraitsTest, IsSwappable) { + using absl::type_traits_internal::IsSwappable; + using absl::type_traits_internal::StdSwapIsUnconstrained; + + EXPECT_TRUE(IsSwappable::value); + + struct S {}; + EXPECT_TRUE(IsSwappable::value); + + struct NoConstruct { + NoConstruct(NoConstruct&&) = delete; + NoConstruct& operator=(NoConstruct&&) { return *this; } + ~NoConstruct() = default; + }; + + EXPECT_EQ(IsSwappable::value, StdSwapIsUnconstrained::value); + struct NoAssign { + NoAssign(NoAssign&&) {} + NoAssign& operator=(NoAssign&&) = delete; + ~NoAssign() = default; + }; + + EXPECT_EQ(IsSwappable::value, StdSwapIsUnconstrained::value); + + EXPECT_FALSE(IsSwappable::value); + + EXPECT_TRUE(IsSwappable::value); +} + +TEST(TypeTraitsTest, IsNothrowSwappable) { + using absl::type_traits_internal::IsNothrowSwappable; + using absl::type_traits_internal::StdSwapIsUnconstrained; + + EXPECT_TRUE(IsNothrowSwappable::value); + + struct NonNoexceptMoves { + NonNoexceptMoves(NonNoexceptMoves&&) {} + NonNoexceptMoves& operator=(NonNoexceptMoves&&) { return *this; } + ~NonNoexceptMoves() = default; + }; + + EXPECT_FALSE(IsNothrowSwappable::value); + + struct NoConstruct { + NoConstruct(NoConstruct&&) = delete; + NoConstruct& operator=(NoConstruct&&) { return *this; } + ~NoConstruct() = default; + }; + + EXPECT_FALSE(IsNothrowSwappable::value); + + struct NoAssign { + NoAssign(NoAssign&&) {} + NoAssign& operator=(NoAssign&&) = delete; + ~NoAssign() = default; + }; + + EXPECT_FALSE(IsNothrowSwappable::value); + + EXPECT_FALSE(IsNothrowSwappable::value); + + EXPECT_TRUE(IsNothrowSwappable::value); +} + } // namespace diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h index c0ec03d4..2f5b8ad7 100644 --- a/absl/numeric/int128.h +++ b/absl/numeric/int128.h @@ -53,7 +53,6 @@ namespace absl { - // uint128 // // An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 8afe8177..9640ff46 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -12,7 +12,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# load( "//absl:copts/configure_copts.bzl", diff --git a/absl/strings/escaping.h b/absl/strings/escaping.h index 03ab0ae7..fd9be786 100644 --- a/absl/strings/escaping.h +++ b/absl/strings/escaping.h @@ -19,7 +19,6 @@ // // This header file contains string utilities involved in escaping and // unescaping strings in various ways. -// #ifndef ABSL_STRINGS_ESCAPING_H_ #define ABSL_STRINGS_ESCAPING_H_ @@ -56,7 +55,6 @@ namespace absl { // UTF-8. (E.g., `\u2019` unescapes to the three bytes 0xE2, 0x80, and // 0x99). // -// // If any errors are encountered, this function returns `false`, leaving the // `dest` output parameter in an unspecified state, and stores the first // encountered error in `error`. To disable error reporting, set `error` to diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index c54cd1ab..4d48af06 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -35,12 +35,14 @@ struct HasUserDefinedConvert< T, void_t(), std::declval(), std::declval()))>> : std::true_type {}; + template class StreamedWrapper; // If 'v' can be converted (in the printf sense) according to 'conv', // then convert it, appending to `sink` and return `true`. // Otherwise fail and return `false`. + // Raw pointers. struct VoidPtr { VoidPtr() = default; diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 5d77856d..99cc0afe 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -363,6 +363,7 @@ typedef ::testing::Types< AllIntTypes; INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes, TypedFormatConvertTest, AllIntTypes); + TEST_F(FormatConvertTest, Uint128) { absl::uint128 v = static_cast(0x1234567890abcdef) * 1979; absl::uint128 max = absl::Uint128Max(); diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h index 30235e08..eb81f8a1 100644 --- a/absl/strings/internal/str_format/extension.h +++ b/absl/strings/internal/str_format/extension.h @@ -13,7 +13,6 @@ // See the License for the specific language governing permissions and // limitations under the License. // -// #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ #define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ diff --git a/absl/strings/internal/str_format/extension_test.cc b/absl/strings/internal/str_format/extension_test.cc index 334a1484..4e23fefb 100644 --- a/absl/strings/internal/str_format/extension_test.cc +++ b/absl/strings/internal/str_format/extension_test.cc @@ -18,6 +18,7 @@ #include #include + #include "absl/strings/str_format.h" #include "gtest/gtest.h" diff --git a/absl/strings/internal/str_format/output_test.cc b/absl/strings/internal/str_format/output_test.cc index ca93d1e3..6e04abef 100644 --- a/absl/strings/internal/str_format/output_test.cc +++ b/absl/strings/internal/str_format/output_test.cc @@ -17,7 +17,6 @@ #include #include - #include "gmock/gmock.h" #include "gtest/gtest.h" diff --git a/absl/strings/internal/utf8.h b/absl/strings/internal/utf8.h index 445d4c35..04236304 100644 --- a/absl/strings/internal/utf8.h +++ b/absl/strings/internal/utf8.h @@ -13,7 +13,6 @@ // limitations under the License. // // UTF8 utilities, implemented to reduce dependencies. -// #ifndef ABSL_STRINGS_INTERNAL_UTF8_H_ #define ABSL_STRINGS_INTERNAL_UTF8_H_ diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h index 69d6eaad..cba8ceb0 100644 --- a/absl/strings/str_cat.h +++ b/absl/strings/str_cat.h @@ -42,7 +42,6 @@ // Floating point numbers are formatted with six-digit precision, which is // the default for "std::cout <<" or printf "%g" (the same as "%.6g"). // -// // You can convert to hexadecimal output rather than decimal output using the // `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to // `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h index 486fe0eb..539d9516 100644 --- a/absl/strings/str_format.h +++ b/absl/strings/str_format.h @@ -513,4 +513,5 @@ ABSL_MUST_USE_RESULT inline bool FormatUntyped( } } // namespace absl + #endif // ABSL_STRINGS_STR_FORMAT_H_ diff --git a/absl/strings/str_split.h b/absl/strings/str_split.h index 8eb55089..73330789 100644 --- a/absl/strings/str_split.h +++ b/absl/strings/str_split.h @@ -71,7 +71,6 @@ namespace absl { // - `ByLength` // - `MaxSplits` // -// // A Delimiter's `Find()` member function will be passed an input `text` that is // to be split and a position (`pos`) to begin searching for the next delimiter // in `text`. The returned absl::string_view should refer to the next occurrence diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h index bd894e1d..f8b20015 100644 --- a/absl/strings/string_view.h +++ b/absl/strings/string_view.h @@ -101,7 +101,6 @@ namespace absl { // example, when splitting a string, `std::vector` is a // natural data type for the output. // -// // When constructed from a source which is nul-terminated, the `string_view` // itself will not include the nul-terminator unless a specific size (including // the nul) is passed to the constructor. As a result, common idioms that work @@ -508,6 +507,7 @@ inline bool operator==(string_view x, string_view y) noexcept { if (len != y.size()) { return false; } + return x.data() == y.data() || len <= 0 || memcmp(x.data(), y.data(), len) == 0; } diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h index a45ff039..507bc4ff 100644 --- a/absl/strings/substitute.h +++ b/absl/strings/substitute.h @@ -45,7 +45,6 @@ // SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5); // EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s); // -// // Supported types: // * absl::string_view, std::string, const char* (null is equivalent to "") // * int32_t, int64_t, uint32_t, uint64 diff --git a/absl/synchronization/internal/create_thread_identity.h b/absl/synchronization/internal/create_thread_identity.h index b2525b72..ebb16c56 100644 --- a/absl/synchronization/internal/create_thread_identity.h +++ b/absl/synchronization/internal/create_thread_identity.h @@ -50,4 +50,5 @@ inline base_internal::ThreadIdentity* GetOrCreateCurrentThreadIdentity() { } // namespace synchronization_internal } // namespace absl + #endif // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_ diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h index 543c4a03..61c72e75 100644 --- a/absl/synchronization/internal/kernel_timeout.h +++ b/absl/synchronization/internal/kernel_timeout.h @@ -53,6 +53,7 @@ class KernelTimeout { // We explicitly do not support other custom formats: timespec, int64_t nanos. // Unify on this and absl::Time, please. + bool has_timeout() const { return ns_ != 0; } private: @@ -148,4 +149,5 @@ class KernelTimeout { } // namespace synchronization_internal } // namespace absl + #endif // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_ diff --git a/absl/synchronization/internal/per_thread_sem.cc b/absl/synchronization/internal/per_thread_sem.cc index d22539dc..b7014fb2 100644 --- a/absl/synchronization/internal/per_thread_sem.cc +++ b/absl/synchronization/internal/per_thread_sem.cc @@ -89,6 +89,7 @@ ABSL_ATTRIBUTE_WEAK bool AbslInternalPerThreadSemWait( if (identity->blocked_count_ptr != nullptr) { identity->blocked_count_ptr->fetch_sub(1, std::memory_order_relaxed); } + identity->is_idle.store(false, std::memory_order_relaxed); identity->wait_start.store(0, std::memory_order_relaxed); return !timeout; diff --git a/absl/synchronization/internal/per_thread_sem.h b/absl/synchronization/internal/per_thread_sem.h index d373f63b..e7da070b 100644 --- a/absl/synchronization/internal/per_thread_sem.h +++ b/absl/synchronization/internal/per_thread_sem.h @@ -104,4 +104,5 @@ bool absl::synchronization_internal::PerThreadSem::Wait( absl::synchronization_internal::KernelTimeout t) { return AbslInternalPerThreadSemWait(t); } + #endif // ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_ diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc index bab6d1a1..74b09650 100644 --- a/absl/synchronization/internal/waiter.cc +++ b/absl/synchronization/internal/waiter.cc @@ -40,6 +40,7 @@ #include #include #include + #include "absl/base/internal/raw_logging.h" #include "absl/base/internal/thread_identity.h" #include "absl/base/optimization.h" @@ -81,6 +82,7 @@ static void MaybeBecomeIdle() { #define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF #endif #endif + class Futex { public: static int WaitUntil(std::atomic *v, int32_t val, diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index f4ed0d00..6b2eb331 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -265,6 +265,7 @@ static const struct { { 0, "Signal on " }, { 0, "SignalAll on " }, }; + static absl::base_internal::SpinLock synch_event_mu( absl::base_internal::kLinkerInitialized); // protects synch_event diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h index cf0f86dc..c38e3561 100644 --- a/absl/synchronization/mutex.h +++ b/absl/synchronization/mutex.h @@ -157,6 +157,7 @@ class LOCKABLE Mutex { // ABSL_CONST_INIT Mutex mu(absl::kConstInit); // } explicit constexpr Mutex(absl::ConstInitType); + ~Mutex(); // Mutex::Lock() @@ -900,10 +901,12 @@ class SCOPED_LOCKABLE ReleasableMutexLock { #ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX inline constexpr Mutex::Mutex(absl::ConstInitType) : impl_(absl::kConstInit) {} + #else inline Mutex::Mutex() : mu_(0) { ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static); } + inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {} inline CondVar::CondVar() : cv_(0) {} @@ -1047,4 +1050,5 @@ void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode); extern "C" { void AbslInternalMutexYield(); } // extern "C" + #endif // ABSL_SYNCHRONIZATION_MUTEX_H_ diff --git a/absl/synchronization/mutex_test.cc b/absl/synchronization/mutex_test.cc index 53c1f744..10211229 100644 --- a/absl/synchronization/mutex_test.cc +++ b/absl/synchronization/mutex_test.cc @@ -1032,9 +1032,9 @@ class ScopedDisableBazelTestWarnings { ScopedDisableBazelTestWarnings() { #ifdef WIN32 char file[MAX_PATH]; - if (GetEnvironmentVariable(kVarName, file, sizeof(file)) < sizeof(file)) { + if (GetEnvironmentVariableA(kVarName, file, sizeof(file)) < sizeof(file)) { warnings_output_file_ = file; - SetEnvironmentVariable(kVarName, nullptr); + SetEnvironmentVariableA(kVarName, nullptr); } #else const char *file = getenv(kVarName); @@ -1048,7 +1048,7 @@ class ScopedDisableBazelTestWarnings { ~ScopedDisableBazelTestWarnings() { if (!warnings_output_file_.empty()) { #ifdef WIN32 - SetEnvironmentVariable(kVarName, warnings_output_file_.c_str()); + SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str()); #else setenv(kVarName, warnings_output_file_.c_str(), 0); #endif diff --git a/absl/synchronization/notification.h b/absl/synchronization/notification.h index 19f51de7..82d111a5 100644 --- a/absl/synchronization/notification.h +++ b/absl/synchronization/notification.h @@ -110,4 +110,5 @@ class Notification { }; } // namespace absl + #endif // ABSL_SYNCHRONIZATION_NOTIFICATION_H_ diff --git a/absl/time/civil_time.h b/absl/time/civil_time.h index f231e4f8..2dfcbd27 100644 --- a/absl/time/civil_time.h +++ b/absl/time/civil_time.h @@ -66,7 +66,6 @@ // // // Valid in C++14 // constexpr absl::CivilDay cd(1969, 07, 20); -// #ifndef ABSL_TIME_CIVIL_TIME_H_ #define ABSL_TIME_CIVIL_TIME_H_ diff --git a/absl/time/duration.cc b/absl/time/duration.cc index 8ce4acbb..67791fee 100644 --- a/absl/time/duration.cc +++ b/absl/time/duration.cc @@ -901,6 +901,7 @@ bool ParseDuration(const std::string& dur_string, Duration* d) { *d = dur; return true; } + bool ParseFlag(const std::string& text, Duration* dst, std::string* ) { return ParseDuration(text, dst); } diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc index 4a68c7d5..fd04e2df 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup.cc @@ -127,7 +127,7 @@ time_zone local_time_zone() { #if defined(_MSC_VER) _dupenv_s(&tz_env, nullptr, "TZ"); #elif defined(__APPLE__) - CFTimeZoneRef system_time_zone = CFTimeZoneCopySystem(); + CFTimeZoneRef system_time_zone = CFTimeZoneCopyDefault(); CFStringRef tz_name = CFTimeZoneGetName(system_time_zone); tz_env = strdup(CFStringGetCStringPtr(tz_name, CFStringGetSystemEncoding())); CFRelease(system_time_zone); diff --git a/absl/time/time.cc b/absl/time/time.cc index 799bf859..977a9517 100644 --- a/absl/time/time.cc +++ b/absl/time/time.cc @@ -41,6 +41,7 @@ #include "absl/time/internal/cctz/include/cctz/time_zone.h" namespace cctz = absl::time_internal::cctz; + namespace absl { namespace { diff --git a/absl/time/time.h b/absl/time/time.h index 59e1dc64..594396c7 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -58,7 +58,6 @@ // std::string s = absl::FormatTime( // "My flight will land in Sydney on %Y-%m-%d at %H:%M:%S", // landing, syd); -// #ifndef ABSL_TIME_TIME_H_ #define ABSL_TIME_TIME_H_ @@ -569,7 +568,6 @@ std::string UnparseFlag(Duration d); // The `absl::Time` class represents an instant in time as a count of clock // ticks of some granularity (resolution) from some starting point (epoch). // -// // `absl::Time` uses a resolution that is high enough to avoid loss in // precision, and a range that is wide enough to avoid overflow, when // converting between tick counts in most Google time scales (i.e., resolution @@ -1450,6 +1448,7 @@ T ToChronoDuration(Duration d) { } } // namespace time_internal + constexpr Duration Nanoseconds(int64_t n) { return time_internal::FromInt64(n, std::nano{}); } diff --git a/absl/types/any_exception_safety_test.cc b/absl/types/any_exception_safety_test.cc index 00d0fb72..5d7d8a5c 100644 --- a/absl/types/any_exception_safety_test.cc +++ b/absl/types/any_exception_safety_test.cc @@ -135,6 +135,7 @@ TEST(AnyExceptionSafety, Assignment) { EXPECT_TRUE(strong_empty_any_tester.Test(assign_val)); EXPECT_TRUE(strong_empty_any_tester.Test(move)); } + // libstdc++ std::any fails this test #if !defined(ABSL_HAVE_STD_ANY) TEST(AnyExceptionSafety, Emplace) { diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h index 4926b321..5ca66e29 100644 --- a/absl/types/internal/variant.h +++ b/absl/types/internal/variant.h @@ -15,7 +15,6 @@ // Implementation details of absl/types/variant.h, pulled into a // separate file to avoid cluttering the top of the API header with // implementation details. -// #ifndef ABSL_TYPES_variant_internal_H_ #define ABSL_TYPES_variant_internal_H_ @@ -1549,8 +1548,8 @@ struct SwapSameIndex { variant* w; template void operator()(SizeT) const { - using std::swap; - swap(VariantCoreAccess::Access(*v), VariantCoreAccess::Access(*w)); + type_traits_internal::Swap(VariantCoreAccess::Access(*v), + VariantCoreAccess::Access(*w)); } void operator()(SizeT) const {} diff --git a/absl/types/optional.h b/absl/types/optional.h index c0488797..58906aa4 100644 --- a/absl/types/optional.h +++ b/absl/types/optional.h @@ -114,10 +114,6 @@ namespace absl { // need the inline variable support in C++17 for external linkage. // * Throws `absl::bad_optional_access` instead of // `std::bad_optional_access`. -// * `optional::swap()` and `absl::swap()` relies on -// `std::is_(nothrow_)swappable()`, which has been introduced in C++17. -// As a workaround, we assume `is_swappable()` is always `true` -// and `is_nothrow_swappable()` is the same as `std::is_trivial()`. // * `make_optional()` cannot be declared `constexpr` due to the absence of // guaranteed copy elision. // * The move constructor's `noexcept` specification is stronger, i.e. if the @@ -753,11 +749,10 @@ class optional : private optional_internal::optional_data, // Swap, standard semantics void swap(optional& rhs) noexcept( std::is_nothrow_move_constructible::value&& - std::is_trivial::value) { + type_traits_internal::IsNothrowSwappable::value) { if (*this) { if (rhs) { - using std::swap; - swap(**this, *rhs); + type_traits_internal::Swap(**this, *rhs); } else { rhs.construct(std::move(**this)); this->destruct(); @@ -909,12 +904,10 @@ class optional : private optional_internal::optional_data, // // Performs a swap between two `absl::optional` objects, using standard // semantics. -// -// NOTE: we assume `is_swappable()` is always `true`. A compile error will -// result if this is not the case. -template ::value, - bool>::type = false> +template ::value && + type_traits_internal::IsSwappable::value, + bool>::type = false> void swap(optional& a, optional& b) noexcept(noexcept(a.swap(b))) { a.swap(b); } diff --git a/absl/types/optional_test.cc b/absl/types/optional_test.cc index 68842abb..0665488e 100644 --- a/absl/types/optional_test.cc +++ b/absl/types/optional_test.cc @@ -1636,6 +1636,7 @@ TEST(optionalTest, AssignmentConstraints) { EXPECT_TRUE(absl::is_copy_assignable>::value); } +#if !defined(ABSL_HAVE_STD_OPTIONAL) && !defined(_LIBCPP_VERSION) struct NestedClassBug { struct Inner { bool dummy = false; @@ -1658,5 +1659,6 @@ TEST(optionalTest, InPlaceTSFINAEBug) { o.emplace(); EXPECT_TRUE(o.has_value()); } +#endif // !defined(ABSL_HAVE_STD_OPTIONAL) && !defined(_LIBCPP_VERSION) } // namespace diff --git a/absl/types/variant.h b/absl/types/variant.h index 8d8b5dbd..ebd52d28 100644 --- a/absl/types/variant.h +++ b/absl/types/variant.h @@ -129,7 +129,12 @@ class variant; // type (in which case, they will be swapped) or to two different types (in // which case the values will need to be moved). // -template +template < + typename... Ts, + absl::enable_if_t< + absl::conjunction..., + type_traits_internal::IsSwappable...>::value, + int> = 0> void swap(variant& v, variant& w) noexcept(noexcept(v.swap(w))) { v.swap(w); } @@ -688,12 +693,12 @@ class variant : private variant_internal::VariantBase { // // Swaps the values of two variant objects. // - // TODO(calabrese) - // `variant::swap()` and `swap()` rely on `std::is_(nothrow)_swappable()` - // which is introduced in C++17. So we assume `is_swappable()` is always - // true and `is_nothrow_swappable()` is same as `std::is_trivial()`. void swap(variant& rhs) noexcept( - absl::conjunction, std::is_trivial...>::value) { + absl::conjunction< + std::is_nothrow_move_constructible, + std::is_nothrow_move_constructible..., + type_traits_internal::IsNothrowSwappable, + type_traits_internal::IsNothrowSwappable...>::value) { return variant_internal::VisitIndices::Run( variant_internal::Swap{this, &rhs}, rhs.index()); } diff --git a/absl/types/variant_exception_safety_test.cc b/absl/types/variant_exception_safety_test.cc index 086fcff0..76beb595 100644 --- a/absl/types/variant_exception_safety_test.cc +++ b/absl/types/variant_exception_safety_test.cc @@ -24,6 +24,7 @@ #include "absl/base/config.h" #include "absl/base/internal/exception_safety_testing.h" #include "absl/memory/memory.h" + // See comment in absl/base/config.h #if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) @@ -315,6 +316,12 @@ TEST(VariantExceptionSafetyTest, MoveAssign) { EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test()); } { + // libstdc++ introduced a regression between 2018-09-25 and 2019-01-06. + // The fix is targeted for gcc-9. + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7 + // https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614 +#if !(defined(ABSL_HAVE_STD_VARIANT) && \ + defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8) // - otherwise (index() != j), equivalent to // emplace(get(std::move(rhs))) // - If an exception is thrown during the call to Tj's move construction @@ -330,6 +337,8 @@ TEST(VariantExceptionSafetyTest, MoveAssign) { auto copy = rhs; *lhs = std::move(copy); })); +#endif // !(defined(ABSL_HAVE_STD_VARIANT) && + // defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8) } } diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc index 9df702df..ab40ed2a 100644 --- a/absl/types/variant_test.cc +++ b/absl/types/variant_test.cc @@ -561,6 +561,7 @@ TEST(VariantTest, TestDtor) { } #ifdef ABSL_HAVE_EXCEPTIONS + // See comment in absl/base/config.h #if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) TEST(VariantTest, DISABLED_TestDtorValuelessByException) diff --git a/absl/utility/utility.h b/absl/utility/utility.h index 62ce6f3a..853c1fb8 100644 --- a/absl/utility/utility.h +++ b/absl/utility/utility.h @@ -35,7 +35,6 @@ // https://en.cppreference.com/w/cpp/utility/integer_sequence // https://en.cppreference.com/w/cpp/utility/apply // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html -// #ifndef ABSL_UTILITY_UTILITY_H_ #define ABSL_UTILITY_UTILITY_H_ diff --git a/ci/linux_clang-latest_libcxx_bazel.sh b/ci/linux_clang-latest_libcxx_bazel.sh new file mode 100755 index 00000000..741e48c4 --- /dev/null +++ b/ci/linux_clang-latest_libcxx_bazel.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# +# Copyright 2019 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script that can be invoked to test abseil-cpp in a hermetic environment +# using a Docker image on Linux. You must have Docker installed to use this +# script. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${STD:-} ]; then + STD="c++11 c++14 c++17" +fi + +if [ -z ${COMPILATION_MODE:-} ]; then + COMPILATION_MODE="fastbuild opt" +fi + +for std in ${STD}; do + for compilation_mode in ${COMPILATION_MODE}; do + echo "--------------------------------------------------------------------" + echo "Testing with --compilation_mode=${compilation_mode} and --std=${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CC="/opt/llvm/clang/bin/clang" \ + -e BAZEL_COMPILER="llvm" \ + -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \ + -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \ + -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx/include/c++/v1" \ + gcr.io/google.com/absl-177019/linux_clang-latest:20190313 \ + /usr/local/bin/bazel test ... \ + --compilation_mode=${compilation_mode} \ + --copt=-Werror \ + --define="absl=1" \ + --keep_going \ + --show_timestamps \ + --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters=-benchmark + done +done diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh new file mode 100755 index 00000000..d703a776 --- /dev/null +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# +# Copyright 2019 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script that can be invoked to test abseil-cpp in a hermetic environment +# using a Docker image on Linux. You must have Docker installed to use this +# script. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${STD:-} ]; then + STD="c++11 c++14 c++17" +fi + +if [ -z ${COMPILATION_MODE:-} ]; then + COMPILATION_MODE="fastbuild opt" +fi + +for std in ${STD}; do + for compilation_mode in ${COMPILATION_MODE}; do + echo "--------------------------------------------------------------------" + echo "Testing with --compilation_mode=${compilation_mode} and --std=${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CC="/opt/llvm/clang/bin/clang" \ + -e BAZEL_COMPILER="llvm" \ + -e BAZEL_CXXOPTS="-std=${std}" \ + -e CPLUS_INCLUDE_PATH="/usr/include/c++/6" \ + gcr.io/google.com/absl-177019/linux_clang-latest:20190313 \ + /usr/local/bin/bazel test ... \ + --compilation_mode=${compilation_mode} \ + --copt=-Werror \ + --define="absl=1" \ + --keep_going \ + --show_timestamps \ + --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters=-benchmark + done +done diff --git a/ci/linux_gcc-4.8_libstdcxx_cmake.sh b/ci/linux_gcc-4.8_libstdcxx_cmake.sh new file mode 100755 index 00000000..4f964e2b --- /dev/null +++ b/ci/linux_gcc-4.8_libstdcxx_cmake.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# +# Copyright 2019 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# TODO(absl-team): This script isn't fully hermetic because +# -DABSL_USE_GOOGLETEST_HEAD=ON means that this script isn't pinned to a fixed +# version of GoogleTest. This means that an upstream change to GoogleTest could +# break this test. Fix this by allowing this script to pin to a known-good +# version of GoogleTest. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]; then + ABSL_CMAKE_CXX_STANDARDS="11 14" +fi + +if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then + ABSL_CMAKE_BUILD_TYPES="Debug Release" +fi + +for std in ${ABSL_CMAKE_CXX_STANDARDS}; do + for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do + echo "--------------------------------------------------------------------" + echo "Testing with CMAKE_BUILD_TYPE=${compilation_mode} and -std=c++${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --tmpfs=/buildfs:exec \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CFLAGS="-Werror" \ + -e CXXFLAGS="-Werror" \ + gcr.io/google.com/absl-177019/linux_gcc-4.8:20190316 \ + /bin/bash -c " + cd /buildfs && \ + cmake /abseil-cpp \ + -DABSL_USE_GOOGLETEST_HEAD=ON \ + -DABSL_RUN_TESTS=ON \ + -DCMAKE_BUILD_TYPE=${compilation_mode} \ + -DCMAKE_CXX_STANDARD=${std} && \ + make -j$(nproc) VERBOSE=1 && \ + ctest -j$(nproc) --output-on-failure" + done +done diff --git a/ci/linux_gcc-latest_libstdcxx_bazel.sh b/ci/linux_gcc-latest_libstdcxx_bazel.sh new file mode 100755 index 00000000..e14a019c --- /dev/null +++ b/ci/linux_gcc-latest_libstdcxx_bazel.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# +# Copyright 2019 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script that can be invoked to test abseil-cpp in a hermetic environment +# using a Docker image on Linux. You must have Docker installed to use this +# script. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +if [ -z ${STD:-} ]; then + STD="c++11 c++14 c++17" +fi + +if [ -z ${COMPILATION_MODE:-} ]; then + COMPILATION_MODE="fastbuild opt" +fi + +for std in ${STD}; do + for compilation_mode in ${COMPILATION_MODE}; do + echo "--------------------------------------------------------------------" + echo "Testing with --compilation_mode=${compilation_mode} and --std=${std}" + + time docker run \ + --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \ + --workdir=/abseil-cpp \ + --cap-add=SYS_PTRACE \ + --rm \ + -e CC="/usr/local/bin/gcc" \ + -e BAZEL_CXXOPTS="-std=${std}" \ + gcr.io/google.com/absl-177019/linux_gcc-latest:20190318 \ + /usr/local/bin/bazel test ... \ + --compilation_mode=${compilation_mode} \ + --copt=-Werror \ + --define="absl=1" \ + --keep_going \ + --show_timestamps \ + --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ + --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters=-benchmark + done +done -- cgit v1.2.3 From 044da8a29c923506af0f0b46bc46f43c1e1300b5 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 8 Apr 2019 09:55:58 -0700 Subject: Export of internal Abseil changes. -- 7c43cf69f00a02d8ed1e669cad12105de667a5ec by Abseil Team : tagging benchmark tests as benchmarks PiperOrigin-RevId: 242480880 -- 3d8d518cde58cddc3d651ea6394ac0722f1f3149 by Samuel Benzaquen : Implement %f natively for any input. It evaluates the input at runtime and allocates stack space accordingly. This removes a potential fallback into snprintf, improves performance, and removes all memory allocations in this formatting path. PiperOrigin-RevId: 242474325 -- de2dc59909cd6c61960f46e647d297c17cb784b5 by Derek Mauro : Add a script to test MacOS/Xcode/CMake PiperOrigin-RevId: 242283929 -- dbc90e3dec22939d99397cd8894760bfe62480ec by Derek Mauro : Release macos_xcode_bazel.sh PiperOrigin-RevId: 242153782 -- 92cda8a7ff7b4b974b0ae6a185cc449476336609 by Derek Mauro : Add a script to test MacOS/Xcode/Bazel PiperOrigin-RevId: 242144494 GitOrigin-RevId: 7c43cf69f00a02d8ed1e669cad12105de667a5ec Change-Id: I3ae1f144a25a968cd4da0b2da0a3b268c81fd3bb --- absl/strings/BUILD.bazel | 1 + absl/strings/CMakeLists.txt | 1 + absl/strings/internal/str_format/convert_test.cc | 74 ++- .../internal/str_format/float_conversion.cc | 497 ++++++++++++++++++++- ci/macos_xcode_bazel.sh | 41 ++ ci/macos_xcode_cmake.sh | 43 ++ 6 files changed, 631 insertions(+), 26 deletions(-) create mode 100644 ci/macos_xcode_bazel.sh create mode 100644 ci/macos_xcode_cmake.sh (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 9640ff46..acf91e57 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -557,6 +557,7 @@ cc_library( visibility = ["//visibility:private"], deps = [ ":strings", + "//absl/base:bits", "//absl/base:core_headers", "//absl/container:inlined_vector", "//absl/meta:type_traits", diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index d3393a39..461b279d 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -384,6 +384,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::bits absl::strings absl::core_headers absl::inlined_vector diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 99cc0afe..b272dd7b 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "gtest/gtest.h" @@ -397,8 +398,8 @@ TEST_F(FormatConvertTest, Float) { #endif // _MSC_VER const char *const kFormats[] = { - "%", "%.3", "%8.5", "%9", "%.60", "%.30", "%03", "%+", - "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; + "%", "%.3", "%8.5", "%9", "%.5000", "%.60", "%.30", "%03", + "%+", "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; std::vector doubles = {0.0, -0.0, @@ -438,12 +439,36 @@ TEST_F(FormatConvertTest, Float) { } } + // Workaround libc bug. + // https://sourceware.org/bugzilla/show_bug.cgi?id=22142 + if (StrPrint("%f", std::numeric_limits::max()) != + "1797693134862315708145274237317043567980705675258449965989174768031" + "5726078002853876058955863276687817154045895351438246423432132688946" + "4182768467546703537516986049910576551282076245490090389328944075868" + "5084551339423045832369032229481658085593321233482747978262041447231" + "68738177180919299881250404026184124858368.000000") { + for (auto &d : doubles) { + using L = std::numeric_limits; + double d2 = std::abs(d); + if (d2 == L::max() || d2 == L::min() || d2 == L::denorm_min()) { + d = 0; + } + } + } + for (const char *fmt : kFormats) { for (char f : {'f', 'F', // 'g', 'G', // 'a', 'A', // 'e', 'E'}) { std::string fmt_str = std::string(fmt) + f; + + if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { + // This particular test takes way too long with snprintf. + // Disable for the case we are not implementing natively. + continue; + } + for (double d : doubles) { int i = -10; FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)}; @@ -454,27 +479,24 @@ TEST_F(FormatConvertTest, Float) { ASSERT_EQ(StrPrint(fmt_str.c_str(), d, i), FormatPack(format, absl::MakeSpan(args))) << fmt_str << " " << StrPrint("%.18g", d) << " " - << StrPrint("%.999f", d); + << StrPrint("%a", d) << " " << StrPrint("%.1080f", d); } } } } TEST_F(FormatConvertTest, LongDouble) { - const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", +#if _MSC_VER + // MSVC has a different rounding policy than us so we can't test our + // implementation against the native one there. + return; +#endif // _MSC_VER + const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000", "%.60", "%+", "% ", "%-10"}; - // This value is not representable in double, but it is in long double that - // uses the extended format. - // This is to verify that we are not truncating the value mistakenly through a - // double. - long double very_precise = 10000000000000000.25L; - std::vector doubles = { 0.0, -0.0, - very_precise, - 1 / very_precise, std::numeric_limits::max(), -std::numeric_limits::max(), std::numeric_limits::min(), @@ -482,22 +504,44 @@ TEST_F(FormatConvertTest, LongDouble) { std::numeric_limits::infinity(), -std::numeric_limits::infinity()}; + for (long double base : {1.L, 12.L, 123.L, 1234.L, 12345.L, 123456.L, + 1234567.L, 12345678.L, 123456789.L, 1234567890.L, + 12345678901.L, 123456789012.L, 1234567890123.L, + // This value is not representable in double, but it + // is in long double that uses the extended format. + // This is to verify that we are not truncating the + // value mistakenly through a double. + 10000000000000000.25L}) { + for (int exp : {-1000, -500, 0, 500, 1000}) { + for (int sign : {1, -1}) { + doubles.push_back(sign * std::ldexp(base, exp)); + doubles.push_back(sign / std::ldexp(base, exp)); + } + } + } + for (const char *fmt : kFormats) { for (char f : {'f', 'F', // 'g', 'G', // 'a', 'A', // 'e', 'E'}) { std::string fmt_str = std::string(fmt) + 'L' + f; + + if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { + // This particular test takes way too long with snprintf. + // Disable for the case we are not implementing natively. + continue; + } + for (auto d : doubles) { FormatArgImpl arg(d); UntypedFormatSpecImpl format(fmt_str); // We use ASSERT_EQ here because failures are usually correlated and a // bug would print way too many failed expectations causing the test to // time out. - ASSERT_EQ(StrPrint(fmt_str.c_str(), d), - FormatPack(format, {&arg, 1})) + ASSERT_EQ(StrPrint(fmt_str.c_str(), d), FormatPack(format, {&arg, 1})) << fmt_str << " " << StrPrint("%.18Lg", d) << " " - << StrPrint("%.999Lf", d); + << StrPrint("%La", d) << " " << StrPrint("%.1080Lf", d); } } } diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index 6176db9c..20012b58 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -2,15 +2,476 @@ #include #include +#include #include #include +#include #include +#include "absl/base/attributes.h" +#include "absl/base/internal/bits.h" +#include "absl/base/optimization.h" +#include "absl/meta/type_traits.h" +#include "absl/numeric/int128.h" +#include "absl/types/span.h" + namespace absl { namespace str_format_internal { namespace { +// Calculates `10 * (*v) + carry` and stores the result in `*v` and returns +// the carry. +template +inline Int MultiplyBy10WithCarry(Int *v, Int carry) { + using NextInt = absl::conditional_t; + static_assert(sizeof(void *) >= sizeof(Int), + "Don't want to use uint128 in 32-bit mode. It is too slow."); + NextInt tmp = 10 * static_cast(*v) + carry; + *v = static_cast(tmp); + return static_cast(tmp >> (sizeof(Int) * 8)); +} + +// Calculates `(2^64 * carry + *v) / 10`. +// Stores the quotient in `*v` and returns the remainder. +// Requires: `0 <= carry <= 9` +inline uint64_t DivideBy10WithCarry(uint64_t *v, uint64_t carry) { + constexpr uint64_t divisor = 10; + // 2^64 / divisor = word_quotient + word_remainder / divisor + constexpr uint64_t word_quotient = (uint64_t{1} << 63) / (divisor / 2); + constexpr uint64_t word_remainder = uint64_t{} - word_quotient * divisor; + + const uint64_t mod = *v % divisor; + const uint64_t next_carry = word_remainder * carry + mod; + *v = *v / divisor + carry * word_quotient + next_carry / divisor; + return next_carry % divisor; +} + +int LeadingZeros(uint64_t v) { return base_internal::CountLeadingZeros64(v); } +int LeadingZeros(uint128 v) { + auto high = static_cast(v >> 64); + auto low = static_cast(v); + return high != 0 ? base_internal::CountLeadingZeros64(high) + : 64 + base_internal::CountLeadingZeros64(low); +} + +int TrailingZeros(uint64_t v) { + return base_internal::CountTrailingZerosNonZero64(v); +} +int TrailingZeros(uint128 v) { + auto high = static_cast(v >> 64); + auto low = static_cast(v); + return low == 0 ? 64 + base_internal::CountTrailingZerosNonZero64(high) + : base_internal::CountTrailingZerosNonZero64(low); +} + +// The buffer must have an extra digit that is known to not need rounding. +// This is done below by having an extra '0' digit on the left. +void RoundUp(char *last_digit) { + char *p = last_digit; + while (*p == '9' || *p == '.') { + if (*p == '9') *p = '0'; + --p; + } + ++*p; +} + +void RoundToEven(char *last_digit) { + char *p = last_digit; + if (*p == '.') --p; + if (*p % 2 == 1) RoundUp(p); +} + +char *PrintIntegralDigitsFromRightDynamic(uint128 v, Span array, + int exp, char *p) { + if (v == 0) { + *--p = '0'; + return p; + } + + int w = exp / 32; + const int offset = exp % 32; + // Left shift v by exp bits. + array[w] = static_cast(v << offset); + for (v >>= (32 - offset); v; v >>= 32) array[++w] = static_cast(v); + + // While we have more than one word available, go in chunks of 1e9. + // We are guaranteed to have at least those many digits. + // `w` holds the largest populated word, so keep it updated. + while (w > 0) { + uint32_t carry = 0; + for (int i = w; i >= 0; --i) { + uint64_t tmp = uint64_t{array[i]} + (uint64_t{carry} << 32); + array[i] = tmp / uint64_t{1000000000}; + carry = tmp % uint64_t{1000000000}; + } + // If the highest word is now empty, remove it from view. + if (array[w] == 0) --w; + + for (int i = 0; i < 9; ++i, carry /= 10) { + *--p = carry % 10 + '0'; + } + } + + // Print the leftover of the last word. + for (auto last = array[0]; last != 0; last /= 10) { + *--p = last % 10 + '0'; + } + + return p; +} + +struct FractionalResult { + const char *end; + int precision; +}; + +FractionalResult PrintFractionalDigitsDynamic(uint128 v, Span array, + char *p, int exp, int precision) { + int w = exp / 32; + const int offset = exp % 32; + + // Right shift `v` by `exp` bits. + array[w] = static_cast(v << (32 - offset)); + v >>= offset; + // Make sure we don't overflow the array. We already calculated that non-zero + // bits fit, so we might not have space for leading zero bits. + for (int pos = w; v; v >>= 32) array[--pos] = static_cast(v); + + // Multiply the whole sequence by 10. + // On each iteration, the leftover carry word is the next digit. + // `w` holds the largest populated word, so keep it updated. + for (; w >= 0 && precision > 0; --precision) { + uint32_t carry = 0; + for (int i = w; i >= 0; --i) { + carry = MultiplyBy10WithCarry(&array[i], carry); + } + // If the lowest word is now empty, remove it from view. + if (array[w] == 0) --w; + *p++ = carry + '0'; + } + + constexpr uint32_t threshold = 0x80000000; + if (array[0] < threshold) { + // We round down, so nothing to do. + } else if (array[0] > threshold || + std::any_of(&array[1], &array[w + 1], + [](uint32_t word) { return word != 0; })) { + RoundUp(p - 1); + } else { + RoundToEven(p - 1); + } + return {p, precision}; +} + +// Generic digit printer. +// `bits` determines how many bits of termporary space it needs for the +// calcualtions. +template +class DigitPrinter { + static constexpr int kInts = (bits + 31) / 32; + + public: + // Quick upper bound for the number of decimal digits we need. + // This would be std::ceil(std::log10(std::pow(2, bits))), but that is not + // constexpr. + static constexpr int kDigits10 = 1 + (bits + 9) / 10 * 3 + bits / 900; + using InputType = uint128; + + static char *PrintIntegralDigitsFromRight(InputType v, int exp, char *end) { + std::array array{}; + return PrintIntegralDigitsFromRightDynamic(v, absl::MakeSpan(array), exp, + end); + } + + static FractionalResult PrintFractionalDigits(InputType v, char *p, int exp, + int precision) { + std::array array{}; + return PrintFractionalDigitsDynamic(v, absl::MakeSpan(array), p, exp, + precision); + } +}; + +// Specialiation for 64-bit working space. +// This is a performance optimization over the generic primary template. +// Only enabled in 64-bit platforms. The generic one is faster in 32-bit +// platforms. +template +class DigitPrinter= + sizeof(uint64_t))>> { + public: + static constexpr size_t kDigits10 = 20; + using InputType = uint64_t; + + static char *PrintIntegralDigitsFromRight(uint64_t v, int exp, char *p) { + v <<= exp; + do { + *--p = DivideBy10WithCarry(&v, 0) + '0'; + } while (v != 0); + return p; + } + + static FractionalResult PrintFractionalDigits(uint64_t v, char *p, int exp, + int precision) { + v <<= (64 - exp); + while (precision > 0) { + if (!v) return {p, precision}; + *p++ = MultiplyBy10WithCarry(&v, uint64_t{}) + '0'; + --precision; + } + + // We need to round. + if (v < 0x8000000000000000) { + // We round down, so nothing to do. + } else if (v > 0x8000000000000000) { + // We round up. + RoundUp(p - 1); + } else { + RoundToEven(p - 1); + } + + assert(precision == 0); + // Precision can only be zero here. Return a constant instead. + return {p, 0}; + } +}; + +// Specialiation for 128-bit working space. +// This is a performance optimization over the generic primary template. +template +class DigitPrinter= + sizeof(uint64_t))>> { + public: + static constexpr size_t kDigits10 = 40; + using InputType = uint128; + + static char *PrintIntegralDigitsFromRight(uint128 v, int exp, char *p) { + v <<= exp; + auto high = static_cast(v >> 64); + auto low = static_cast(v); + + do { + uint64_t carry = DivideBy10WithCarry(&high, 0); + carry = DivideBy10WithCarry(&low, carry); + *--p = carry + '0'; + } while (high != 0u); + + while (low != 0u) { + *--p = DivideBy10WithCarry(&low, 0) + '0'; + } + return p; + } + + static FractionalResult PrintFractionalDigits(uint128 v, char *p, int exp, + int precision) { + v <<= (128 - exp); + auto high = static_cast(v >> 64); + auto low = static_cast(v); + + // While we have digits to print and `low` is not empty, do the long + // multiplication. + while (precision > 0 && low != 0) { + uint64_t carry = MultiplyBy10WithCarry(&low, uint64_t{}); + carry = MultiplyBy10WithCarry(&high, carry); + + *p++ = carry + '0'; + --precision; + } + + // Now `low` is empty, so use a faster approach for the rest of the digits. + // This block is pretty much the same as the main loop for the 64-bit case + // above. + while (precision > 0) { + if (!high) return {p, precision}; + *p++ = MultiplyBy10WithCarry(&high, uint64_t{}) + '0'; + --precision; + } + + // We need to round. + if (high < 0x8000000000000000) { + // We round down, so nothing to do. + } else if (high > 0x8000000000000000 || low != 0) { + // We round up. + RoundUp(p - 1); + } else { + RoundToEven(p - 1); + } + + assert(precision == 0); + // Precision can only be zero here. Return a constant instead. + return {p, 0}; + } +}; + +struct FormatState { + char sign_char; + int precision; + const ConversionSpec &conv; + FormatSinkImpl *sink; +}; + +void FinalPrint(string_view data, int trailing_zeros, + const FormatState &state) { + if (state.conv.width() < 0) { + // No width specified. Fast-path. + if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); + state.sink->Append(data); + state.sink->Append(trailing_zeros, '0'); + return; + } + + int left_spaces = 0, zeros = 0, right_spaces = 0; + int total_size = (state.sign_char != 0 ? 1 : 0) + + static_cast(data.size()) + trailing_zeros; + int missing_chars = std::max(state.conv.width() - total_size, 0); + if (state.conv.flags().left) { + right_spaces = missing_chars; + } else if (state.conv.flags().zero) { + zeros = missing_chars; + } else { + left_spaces = missing_chars; + } + + state.sink->Append(left_spaces, ' '); + if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); + state.sink->Append(zeros, '0'); + state.sink->Append(data); + state.sink->Append(trailing_zeros, '0'); + state.sink->Append(right_spaces, ' '); +} + +template +void FormatFPositiveExp(Int v, int exp, const FormatState &state) { + using IntegralPrinter = DigitPrinter; + char buffer[IntegralPrinter::kDigits10 + /* . */ 1]; + buffer[IntegralPrinter::kDigits10] = '.'; + + const char *digits = IntegralPrinter::PrintIntegralDigitsFromRight( + static_cast(v), exp, + buffer + sizeof(buffer) - 1); + size_t size = buffer + sizeof(buffer) - digits; + + // In `alt` mode (flag #) we keep the `.` even if there are no fractional + // digits. In non-alt mode, we strip it. + if (ABSL_PREDICT_FALSE(state.precision == 0 && !state.conv.flags().alt)) { + --size; + } + + FinalPrint(string_view(digits, size), state.precision, state); +} + +template +void FormatFNegativeExp(Int v, int exp, const FormatState &state) { + constexpr int input_bits = sizeof(Int) * 8; + + using IntegralPrinter = DigitPrinter; + using FractionalPrinter = DigitPrinter; + + static constexpr size_t integral_size = + 1 + /* in case we need to round up an extra digit */ + IntegralPrinter::kDigits10 + 1; + char buffer[integral_size + /* . */ 1 + num_bits]; + buffer[integral_size] = '.'; + char *const integral_digits_end = buffer + integral_size; + char *integral_digits_start; + char *const fractional_digits_start = buffer + integral_size + 1; + + if (exp < input_bits) { + integral_digits_start = IntegralPrinter::PrintIntegralDigitsFromRight( + v >> exp, 0, integral_digits_end); + } else { + integral_digits_start = integral_digits_end - 1; + *integral_digits_start = '0'; + } + + // PrintFractionalDigits may pull a carried 1 all the way up through the + // integral portion. + integral_digits_start[-1] = '0'; + auto fractional_result = FractionalPrinter::PrintFractionalDigits( + static_cast(v), + fractional_digits_start, exp, state.precision); + if (integral_digits_start[-1] != '0') --integral_digits_start; + + size_t size = fractional_result.end - integral_digits_start; + + // In `alt` mode (flag #) we keep the `.` even if there are no fractional + // digits. In non-alt mode, we strip it. + if (ABSL_PREDICT_FALSE(state.precision == 0 && !state.conv.flags().alt)) { + --size; + } + FinalPrint(string_view(integral_digits_start, size), + fractional_result.precision, state); +} + +template +void FormatF(Int mantissa, int exp, const FormatState &state) { + // Remove trailing zeros as they are not useful. + // This helps use faster implementations/less stack space in some cases. + if (mantissa != 0) { + int trailing = TrailingZeros(mantissa); + mantissa >>= trailing; + exp += trailing; + } + + // The table driven dispatch gives us two benefits: fast distpatch and + // prevent inlining. + // We must not inline any of the functions below (other than the ones for + // 64-bit) to avoid blowing up this stack frame. + + if (exp >= 0) { + // We will left shift the mantissa. Calculate how many bits we need. + // Special case 64-bit as we will use a uint64_t for it. Use a table for the + // rest and unconditionally use uint128. + const int total_bits = sizeof(Int) * 8 - LeadingZeros(mantissa) + exp; + + if (total_bits <= 64) { + return FormatFPositiveExp<64>(mantissa, exp, state); + } else { + using Formatter = void (*)(uint128, int, const FormatState &); + static constexpr Formatter kFormatters[] = { + FormatFPositiveExp<1 << 7>, FormatFPositiveExp<1 << 8>, + FormatFPositiveExp<1 << 9>, FormatFPositiveExp<1 << 10>, + FormatFPositiveExp<1 << 11>, FormatFPositiveExp<1 << 12>, + FormatFPositiveExp<1 << 13>, FormatFPositiveExp<1 << 14>, + FormatFPositiveExp<1 << 15>, + }; + static constexpr int max_total_bits = + sizeof(Int) * 8 + std::numeric_limits::max_exponent; + assert(total_bits <= max_total_bits); + static_assert(max_total_bits <= (1 << 15), ""); + const int log2 = + 64 - LeadingZeros((static_cast(total_bits) - 1) / 128); + assert(log2 < std::end(kFormatters) - std::begin(kFormatters)); + kFormatters[log2](mantissa, exp, state); + } + } else { + exp = -exp; + + // We know we don't need more than Int itself for the integral part. + // We need `precision` fractional digits, but there are at most `exp` + // non-zero digits after the decimal point. The rest will be zeros. + // Special case 64-bit as we will use a uint64_t for it. Use a table for the + // rest and unconditionally use uint128. + + if (exp <= 64) { + return FormatFNegativeExp<64>(mantissa, exp, state); + } else { + using Formatter = void (*)(uint128, int, const FormatState &); + static constexpr Formatter kFormatters[] = { + FormatFNegativeExp<1 << 7>, FormatFNegativeExp<1 << 8>, + FormatFNegativeExp<1 << 9>, FormatFNegativeExp<1 << 10>, + FormatFNegativeExp<1 << 11>, FormatFNegativeExp<1 << 12>, + FormatFNegativeExp<1 << 13>, FormatFNegativeExp<1 << 14>}; + static_assert( + -std::numeric_limits::min_exponent <= (1 << 14), ""); + const int log2 = + 64 - LeadingZeros((static_cast(exp) - 1) / 128); + assert(log2 < std::end(kFormatters) - std::begin(kFormatters)); + kFormatters[log2](mantissa, exp, state); + } + } +} + char *CopyStringTo(string_view v, char *out) { std::memcpy(out, v.data(), v.size()); return out + v.size(); @@ -95,7 +556,7 @@ template bool ConvertNonNumericFloats(char sign_char, Float v, const ConversionSpec &conv, FormatSinkImpl *sink) { char text[4], *ptr = text; - if (sign_char) *ptr++ = sign_char; + if (sign_char != '\0') *ptr++ = sign_char; if (std::isnan(v)) { ptr = std::copy_n(conv.conv().upper() ? "NAN" : "nan", 3, ptr); } else if (std::isinf(v)) { @@ -165,7 +626,12 @@ constexpr bool CanFitMantissa() { template struct Decomposed { - Float mantissa; + using MantissaType = + absl::conditional_t::value, uint128, + uint64_t>; + static_assert(std::numeric_limits::digits <= sizeof(MantissaType) * 8, + ""); + MantissaType mantissa; int exponent; }; @@ -176,7 +642,8 @@ Decomposed Decompose(Float v) { Float m = std::frexp(v, &exp); m = std::ldexp(m, std::numeric_limits::digits); exp -= std::numeric_limits::digits; - return {m, exp}; + + return {static_cast::MantissaType>(m), exp}; } // Print 'digits' as decimal. @@ -334,7 +801,7 @@ bool FloatToBuffer(Decomposed decomposed, int precision, Buffer *out, static_cast(decomposed.exponent), precision, out, exp)) return true; -#if defined(__SIZEOF_INT128__) +#if defined(ABSL_HAVE_INTRINSIC_INT128) // If that is not enough, try with __uint128_t. return CanFitMantissa() && FloatToBufferImpl<__uint128_t, Float, mode>( @@ -362,7 +829,7 @@ void WriteBufferToSink(char sign_char, string_view str, } sink->Append(left_spaces, ' '); - if (sign_char) sink->Append(1, sign_char); + if (sign_char != '\0') sink->Append(1, sign_char); sink->Append(zeros, '0'); sink->Append(str); sink->Append(right_spaces, ' '); @@ -399,12 +866,9 @@ bool FloatToSink(const Float v, const ConversionSpec &conv, switch (conv.conv().id()) { case ConversionChar::f: case ConversionChar::F: - if (!FloatToBuffer(decomposed, precision, &buffer, - nullptr)) { - return FallbackToSnprintf(v, conv, sink); - } - if (!conv.flags().alt && buffer.back() == '.') buffer.pop_back(); - break; + FormatF(decomposed.mantissa, decomposed.exponent, + {sign_char, precision, conv, sink}); + return true; case ConversionChar::e: case ConversionChar::E: @@ -466,11 +930,22 @@ bool FloatToSink(const Float v, const ConversionSpec &conv, bool ConvertFloatImpl(long double v, const ConversionSpec &conv, FormatSinkImpl *sink) { + if (std::numeric_limits::digits == + 2 * std::numeric_limits::digits) { + // This is the `double-double` representation of `long double`. + // We do not handle it natively. Fallback to snprintf. + return FallbackToSnprintf(v, conv, sink); + } + return FloatToSink(v, conv, sink); } bool ConvertFloatImpl(float v, const ConversionSpec &conv, FormatSinkImpl *sink) { + // DivideBy10WithCarry is not actually used in some builds. This here silences + // the "unused" warning. We just need to put it in any function that is really + // used. + (void)&DivideBy10WithCarry; return FloatToSink(v, conv, sink); } diff --git a/ci/macos_xcode_bazel.sh b/ci/macos_xcode_bazel.sh new file mode 100644 index 00000000..e840e9d0 --- /dev/null +++ b/ci/macos_xcode_bazel.sh @@ -0,0 +1,41 @@ +#!/bin/bash +# +# Copyright 2019 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script is invoked on Kokoro to test Abseil on MacOS. +# It is not hermetic and may break when Kokoro is updated. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(realpath $(dirname ${0})/..)" +fi + +# Print the default compiler and Bazel versions. +echo "---------------" +gcc -v +echo "---------------" +bazel version +echo "---------------" + +cd ${ABSEIL_ROOT} + +bazel test ... \ + --copt=-Werror \ + --keep_going \ + --show_timestamps \ + --test_env="TZDIR=${ABSEIL_ROOT}/absl/time/internal/cctz/testdata/zoneinfo" \ + --test_output=errors \ + --test_tag_filters=-benchmark diff --git a/ci/macos_xcode_cmake.sh b/ci/macos_xcode_cmake.sh new file mode 100644 index 00000000..4892e26e --- /dev/null +++ b/ci/macos_xcode_cmake.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# +# Copyright 2019 The Abseil Authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This script is invoked on Kokoro to test Abseil on MacOS. +# It is not hermetic and may break when Kokoro is updated. + +set -euox pipefail + +if [ -z ${ABSEIL_ROOT:-} ]; then + ABSEIL_ROOT="$(dirname ${0})/.." +fi +ABSEIL_ROOT=$(realpath ${ABSEIL_ROOT}) + +if [ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]; then + ABSL_CMAKE_BUILD_TYPES="Debug" +fi + +for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do + BUILD_DIR=$(mktemp -d ${compilation_mode}.XXXXXXXX) + cd ${BUILD_DIR} + + # TODO(absl-team): Enable -Werror once all warnings are fixed. + time cmake ${ABSEIL_ROOT} \ + -GXcode \ + -DCMAKE_BUILD_TYPE=${compilation_mode} \ + -DABSL_USE_GOOGLETEST_HEAD=ON \ + -DABSL_RUN_TESTS=ON + time cmake --build . + time ctest -C ${compilation_mode} --output-on-failure +done -- cgit v1.2.3 From dbae8764fbd429bf7d7745e24bcf73962177a7c0 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 9 Apr 2019 08:22:32 -0700 Subject: Export of internal Abseil changes. -- 3f04cd3c25a99df91ff913977b8c5b343532db5d by Abseil Team : Stricter memory order constraints for CycleClock callback. PiperOrigin-RevId: 242670115 -- 216db48375306490f1722a11aaf33080939d9f2f by Abseil Team : internal/optional.h: move macro from types/optional.h ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS is only used within this file. additionally check the macro with #ifdef rather than #if, fixes -Wundef warning: 'ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS' is not defined, evaluates to 0 PiperOrigin-RevId: 242548205 -- fbe22e7d8dc5c0b3d43ac26297e97ddbaeab3d39 by Samuel Benzaquen : Implement %f natively for any input. It evaluates the input at runtime and allocates stack space accordingly. This removes a potential fallback into snprintf, improves performance, and removes all memory allocations in this formatting path. PiperOrigin-RevId: 242531736 -- 1458f9ba2a79ef0534e46527cd34770dee54164d by Greg Falcon : Add explicit check for NVCC in compressed_tuple.h. NVCC claims to be MSVC, but does not implement this MSVC attribute. PiperOrigin-RevId: 242513453 GitOrigin-RevId: 3f04cd3c25a99df91ff913977b8c5b343532db5d Change-Id: I0742e8619c5248c7607961113e406486bc0e279b --- absl/base/internal/cycleclock.cc | 18 +- absl/container/internal/compressed_tuple.h | 6 +- absl/strings/BUILD.bazel | 1 - absl/strings/CMakeLists.txt | 1 - absl/strings/internal/str_format/convert_test.cc | 74 +-- .../internal/str_format/float_conversion.cc | 497 +-------------------- absl/types/internal/optional.h | 36 +- absl/types/optional.h | 29 -- 8 files changed, 78 insertions(+), 584 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/base/internal/cycleclock.cc b/absl/base/internal/cycleclock.cc index 4b553c29..e9844b71 100644 --- a/absl/base/internal/cycleclock.cc +++ b/absl/base/internal/cycleclock.cc @@ -55,10 +55,23 @@ static constexpr int32_t kShift = 2; static constexpr double kFrequencyScale = 1.0 / (1 << kShift); static std::atomic cycle_clock_source; +CycleClockSourceFunc LoadCycleClockSource() { + // Optimize for the common case (no callback) by first doing a relaxed load; + // this is significantly faster on non-x86 platforms. + if (cycle_clock_source.load(std::memory_order_relaxed) == nullptr) { + return nullptr; + } + // This corresponds to the store(std::memory_order_release) in + // CycleClockSource::Register, and makes sure that any updates made prior to + // registering the callback are visible to this thread before the callback is + // invoked. + return cycle_clock_source.load(std::memory_order_acquire); +} + } // namespace int64_t CycleClock::Now() { - auto fn = cycle_clock_source.load(std::memory_order_relaxed); + auto fn = LoadCycleClockSource(); if (fn == nullptr) { return base_internal::UnscaledCycleClock::Now() >> kShift; } @@ -70,7 +83,8 @@ double CycleClock::Frequency() { } void CycleClockSource::Register(CycleClockSourceFunc source) { - cycle_clock_source.store(source, std::memory_order_relaxed); + // Corresponds to the load(std::memory_order_acquire) in LoadCycleClockSource. + cycle_clock_source.store(source, std::memory_order_release); } #else diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h index b9bd91af..bb3471f5 100644 --- a/absl/container/internal/compressed_tuple.h +++ b/absl/container/internal/compressed_tuple.h @@ -38,13 +38,13 @@ #include "absl/utility/utility.h" -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__NVCC__) // We need to mark these classes with this declspec to ensure that // CompressedTuple happens. #define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases) -#else // _MSC_VER +#else #define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC -#endif // _MSC_VER +#endif namespace absl { namespace container_internal { diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index acf91e57..9640ff46 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -557,7 +557,6 @@ cc_library( visibility = ["//visibility:private"], deps = [ ":strings", - "//absl/base:bits", "//absl/base:core_headers", "//absl/container:inlined_vector", "//absl/meta:type_traits", diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index 461b279d..d3393a39 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -384,7 +384,6 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS - absl::bits absl::strings absl::core_headers absl::inlined_vector diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index b272dd7b..99cc0afe 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -2,7 +2,6 @@ #include #include #include -#include #include #include "gtest/gtest.h" @@ -398,8 +397,8 @@ TEST_F(FormatConvertTest, Float) { #endif // _MSC_VER const char *const kFormats[] = { - "%", "%.3", "%8.5", "%9", "%.5000", "%.60", "%.30", "%03", - "%+", "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; + "%", "%.3", "%8.5", "%9", "%.60", "%.30", "%03", "%+", + "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; std::vector doubles = {0.0, -0.0, @@ -439,36 +438,12 @@ TEST_F(FormatConvertTest, Float) { } } - // Workaround libc bug. - // https://sourceware.org/bugzilla/show_bug.cgi?id=22142 - if (StrPrint("%f", std::numeric_limits::max()) != - "1797693134862315708145274237317043567980705675258449965989174768031" - "5726078002853876058955863276687817154045895351438246423432132688946" - "4182768467546703537516986049910576551282076245490090389328944075868" - "5084551339423045832369032229481658085593321233482747978262041447231" - "68738177180919299881250404026184124858368.000000") { - for (auto &d : doubles) { - using L = std::numeric_limits; - double d2 = std::abs(d); - if (d2 == L::max() || d2 == L::min() || d2 == L::denorm_min()) { - d = 0; - } - } - } - for (const char *fmt : kFormats) { for (char f : {'f', 'F', // 'g', 'G', // 'a', 'A', // 'e', 'E'}) { std::string fmt_str = std::string(fmt) + f; - - if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { - // This particular test takes way too long with snprintf. - // Disable for the case we are not implementing natively. - continue; - } - for (double d : doubles) { int i = -10; FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)}; @@ -479,24 +454,27 @@ TEST_F(FormatConvertTest, Float) { ASSERT_EQ(StrPrint(fmt_str.c_str(), d, i), FormatPack(format, absl::MakeSpan(args))) << fmt_str << " " << StrPrint("%.18g", d) << " " - << StrPrint("%a", d) << " " << StrPrint("%.1080f", d); + << StrPrint("%.999f", d); } } } } TEST_F(FormatConvertTest, LongDouble) { -#if _MSC_VER - // MSVC has a different rounding policy than us so we can't test our - // implementation against the native one there. - return; -#endif // _MSC_VER - const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000", + const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.60", "%+", "% ", "%-10"}; + // This value is not representable in double, but it is in long double that + // uses the extended format. + // This is to verify that we are not truncating the value mistakenly through a + // double. + long double very_precise = 10000000000000000.25L; + std::vector doubles = { 0.0, -0.0, + very_precise, + 1 / very_precise, std::numeric_limits::max(), -std::numeric_limits::max(), std::numeric_limits::min(), @@ -504,44 +482,22 @@ TEST_F(FormatConvertTest, LongDouble) { std::numeric_limits::infinity(), -std::numeric_limits::infinity()}; - for (long double base : {1.L, 12.L, 123.L, 1234.L, 12345.L, 123456.L, - 1234567.L, 12345678.L, 123456789.L, 1234567890.L, - 12345678901.L, 123456789012.L, 1234567890123.L, - // This value is not representable in double, but it - // is in long double that uses the extended format. - // This is to verify that we are not truncating the - // value mistakenly through a double. - 10000000000000000.25L}) { - for (int exp : {-1000, -500, 0, 500, 1000}) { - for (int sign : {1, -1}) { - doubles.push_back(sign * std::ldexp(base, exp)); - doubles.push_back(sign / std::ldexp(base, exp)); - } - } - } - for (const char *fmt : kFormats) { for (char f : {'f', 'F', // 'g', 'G', // 'a', 'A', // 'e', 'E'}) { std::string fmt_str = std::string(fmt) + 'L' + f; - - if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { - // This particular test takes way too long with snprintf. - // Disable for the case we are not implementing natively. - continue; - } - for (auto d : doubles) { FormatArgImpl arg(d); UntypedFormatSpecImpl format(fmt_str); // We use ASSERT_EQ here because failures are usually correlated and a // bug would print way too many failed expectations causing the test to // time out. - ASSERT_EQ(StrPrint(fmt_str.c_str(), d), FormatPack(format, {&arg, 1})) + ASSERT_EQ(StrPrint(fmt_str.c_str(), d), + FormatPack(format, {&arg, 1})) << fmt_str << " " << StrPrint("%.18Lg", d) << " " - << StrPrint("%La", d) << " " << StrPrint("%.1080Lf", d); + << StrPrint("%.999Lf", d); } } } diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index 20012b58..6176db9c 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -2,476 +2,15 @@ #include #include -#include #include #include -#include #include -#include "absl/base/attributes.h" -#include "absl/base/internal/bits.h" -#include "absl/base/optimization.h" -#include "absl/meta/type_traits.h" -#include "absl/numeric/int128.h" -#include "absl/types/span.h" - namespace absl { namespace str_format_internal { namespace { -// Calculates `10 * (*v) + carry` and stores the result in `*v` and returns -// the carry. -template -inline Int MultiplyBy10WithCarry(Int *v, Int carry) { - using NextInt = absl::conditional_t; - static_assert(sizeof(void *) >= sizeof(Int), - "Don't want to use uint128 in 32-bit mode. It is too slow."); - NextInt tmp = 10 * static_cast(*v) + carry; - *v = static_cast(tmp); - return static_cast(tmp >> (sizeof(Int) * 8)); -} - -// Calculates `(2^64 * carry + *v) / 10`. -// Stores the quotient in `*v` and returns the remainder. -// Requires: `0 <= carry <= 9` -inline uint64_t DivideBy10WithCarry(uint64_t *v, uint64_t carry) { - constexpr uint64_t divisor = 10; - // 2^64 / divisor = word_quotient + word_remainder / divisor - constexpr uint64_t word_quotient = (uint64_t{1} << 63) / (divisor / 2); - constexpr uint64_t word_remainder = uint64_t{} - word_quotient * divisor; - - const uint64_t mod = *v % divisor; - const uint64_t next_carry = word_remainder * carry + mod; - *v = *v / divisor + carry * word_quotient + next_carry / divisor; - return next_carry % divisor; -} - -int LeadingZeros(uint64_t v) { return base_internal::CountLeadingZeros64(v); } -int LeadingZeros(uint128 v) { - auto high = static_cast(v >> 64); - auto low = static_cast(v); - return high != 0 ? base_internal::CountLeadingZeros64(high) - : 64 + base_internal::CountLeadingZeros64(low); -} - -int TrailingZeros(uint64_t v) { - return base_internal::CountTrailingZerosNonZero64(v); -} -int TrailingZeros(uint128 v) { - auto high = static_cast(v >> 64); - auto low = static_cast(v); - return low == 0 ? 64 + base_internal::CountTrailingZerosNonZero64(high) - : base_internal::CountTrailingZerosNonZero64(low); -} - -// The buffer must have an extra digit that is known to not need rounding. -// This is done below by having an extra '0' digit on the left. -void RoundUp(char *last_digit) { - char *p = last_digit; - while (*p == '9' || *p == '.') { - if (*p == '9') *p = '0'; - --p; - } - ++*p; -} - -void RoundToEven(char *last_digit) { - char *p = last_digit; - if (*p == '.') --p; - if (*p % 2 == 1) RoundUp(p); -} - -char *PrintIntegralDigitsFromRightDynamic(uint128 v, Span array, - int exp, char *p) { - if (v == 0) { - *--p = '0'; - return p; - } - - int w = exp / 32; - const int offset = exp % 32; - // Left shift v by exp bits. - array[w] = static_cast(v << offset); - for (v >>= (32 - offset); v; v >>= 32) array[++w] = static_cast(v); - - // While we have more than one word available, go in chunks of 1e9. - // We are guaranteed to have at least those many digits. - // `w` holds the largest populated word, so keep it updated. - while (w > 0) { - uint32_t carry = 0; - for (int i = w; i >= 0; --i) { - uint64_t tmp = uint64_t{array[i]} + (uint64_t{carry} << 32); - array[i] = tmp / uint64_t{1000000000}; - carry = tmp % uint64_t{1000000000}; - } - // If the highest word is now empty, remove it from view. - if (array[w] == 0) --w; - - for (int i = 0; i < 9; ++i, carry /= 10) { - *--p = carry % 10 + '0'; - } - } - - // Print the leftover of the last word. - for (auto last = array[0]; last != 0; last /= 10) { - *--p = last % 10 + '0'; - } - - return p; -} - -struct FractionalResult { - const char *end; - int precision; -}; - -FractionalResult PrintFractionalDigitsDynamic(uint128 v, Span array, - char *p, int exp, int precision) { - int w = exp / 32; - const int offset = exp % 32; - - // Right shift `v` by `exp` bits. - array[w] = static_cast(v << (32 - offset)); - v >>= offset; - // Make sure we don't overflow the array. We already calculated that non-zero - // bits fit, so we might not have space for leading zero bits. - for (int pos = w; v; v >>= 32) array[--pos] = static_cast(v); - - // Multiply the whole sequence by 10. - // On each iteration, the leftover carry word is the next digit. - // `w` holds the largest populated word, so keep it updated. - for (; w >= 0 && precision > 0; --precision) { - uint32_t carry = 0; - for (int i = w; i >= 0; --i) { - carry = MultiplyBy10WithCarry(&array[i], carry); - } - // If the lowest word is now empty, remove it from view. - if (array[w] == 0) --w; - *p++ = carry + '0'; - } - - constexpr uint32_t threshold = 0x80000000; - if (array[0] < threshold) { - // We round down, so nothing to do. - } else if (array[0] > threshold || - std::any_of(&array[1], &array[w + 1], - [](uint32_t word) { return word != 0; })) { - RoundUp(p - 1); - } else { - RoundToEven(p - 1); - } - return {p, precision}; -} - -// Generic digit printer. -// `bits` determines how many bits of termporary space it needs for the -// calcualtions. -template -class DigitPrinter { - static constexpr int kInts = (bits + 31) / 32; - - public: - // Quick upper bound for the number of decimal digits we need. - // This would be std::ceil(std::log10(std::pow(2, bits))), but that is not - // constexpr. - static constexpr int kDigits10 = 1 + (bits + 9) / 10 * 3 + bits / 900; - using InputType = uint128; - - static char *PrintIntegralDigitsFromRight(InputType v, int exp, char *end) { - std::array array{}; - return PrintIntegralDigitsFromRightDynamic(v, absl::MakeSpan(array), exp, - end); - } - - static FractionalResult PrintFractionalDigits(InputType v, char *p, int exp, - int precision) { - std::array array{}; - return PrintFractionalDigitsDynamic(v, absl::MakeSpan(array), p, exp, - precision); - } -}; - -// Specialiation for 64-bit working space. -// This is a performance optimization over the generic primary template. -// Only enabled in 64-bit platforms. The generic one is faster in 32-bit -// platforms. -template -class DigitPrinter= - sizeof(uint64_t))>> { - public: - static constexpr size_t kDigits10 = 20; - using InputType = uint64_t; - - static char *PrintIntegralDigitsFromRight(uint64_t v, int exp, char *p) { - v <<= exp; - do { - *--p = DivideBy10WithCarry(&v, 0) + '0'; - } while (v != 0); - return p; - } - - static FractionalResult PrintFractionalDigits(uint64_t v, char *p, int exp, - int precision) { - v <<= (64 - exp); - while (precision > 0) { - if (!v) return {p, precision}; - *p++ = MultiplyBy10WithCarry(&v, uint64_t{}) + '0'; - --precision; - } - - // We need to round. - if (v < 0x8000000000000000) { - // We round down, so nothing to do. - } else if (v > 0x8000000000000000) { - // We round up. - RoundUp(p - 1); - } else { - RoundToEven(p - 1); - } - - assert(precision == 0); - // Precision can only be zero here. Return a constant instead. - return {p, 0}; - } -}; - -// Specialiation for 128-bit working space. -// This is a performance optimization over the generic primary template. -template -class DigitPrinter= - sizeof(uint64_t))>> { - public: - static constexpr size_t kDigits10 = 40; - using InputType = uint128; - - static char *PrintIntegralDigitsFromRight(uint128 v, int exp, char *p) { - v <<= exp; - auto high = static_cast(v >> 64); - auto low = static_cast(v); - - do { - uint64_t carry = DivideBy10WithCarry(&high, 0); - carry = DivideBy10WithCarry(&low, carry); - *--p = carry + '0'; - } while (high != 0u); - - while (low != 0u) { - *--p = DivideBy10WithCarry(&low, 0) + '0'; - } - return p; - } - - static FractionalResult PrintFractionalDigits(uint128 v, char *p, int exp, - int precision) { - v <<= (128 - exp); - auto high = static_cast(v >> 64); - auto low = static_cast(v); - - // While we have digits to print and `low` is not empty, do the long - // multiplication. - while (precision > 0 && low != 0) { - uint64_t carry = MultiplyBy10WithCarry(&low, uint64_t{}); - carry = MultiplyBy10WithCarry(&high, carry); - - *p++ = carry + '0'; - --precision; - } - - // Now `low` is empty, so use a faster approach for the rest of the digits. - // This block is pretty much the same as the main loop for the 64-bit case - // above. - while (precision > 0) { - if (!high) return {p, precision}; - *p++ = MultiplyBy10WithCarry(&high, uint64_t{}) + '0'; - --precision; - } - - // We need to round. - if (high < 0x8000000000000000) { - // We round down, so nothing to do. - } else if (high > 0x8000000000000000 || low != 0) { - // We round up. - RoundUp(p - 1); - } else { - RoundToEven(p - 1); - } - - assert(precision == 0); - // Precision can only be zero here. Return a constant instead. - return {p, 0}; - } -}; - -struct FormatState { - char sign_char; - int precision; - const ConversionSpec &conv; - FormatSinkImpl *sink; -}; - -void FinalPrint(string_view data, int trailing_zeros, - const FormatState &state) { - if (state.conv.width() < 0) { - // No width specified. Fast-path. - if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); - state.sink->Append(data); - state.sink->Append(trailing_zeros, '0'); - return; - } - - int left_spaces = 0, zeros = 0, right_spaces = 0; - int total_size = (state.sign_char != 0 ? 1 : 0) + - static_cast(data.size()) + trailing_zeros; - int missing_chars = std::max(state.conv.width() - total_size, 0); - if (state.conv.flags().left) { - right_spaces = missing_chars; - } else if (state.conv.flags().zero) { - zeros = missing_chars; - } else { - left_spaces = missing_chars; - } - - state.sink->Append(left_spaces, ' '); - if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); - state.sink->Append(zeros, '0'); - state.sink->Append(data); - state.sink->Append(trailing_zeros, '0'); - state.sink->Append(right_spaces, ' '); -} - -template -void FormatFPositiveExp(Int v, int exp, const FormatState &state) { - using IntegralPrinter = DigitPrinter; - char buffer[IntegralPrinter::kDigits10 + /* . */ 1]; - buffer[IntegralPrinter::kDigits10] = '.'; - - const char *digits = IntegralPrinter::PrintIntegralDigitsFromRight( - static_cast(v), exp, - buffer + sizeof(buffer) - 1); - size_t size = buffer + sizeof(buffer) - digits; - - // In `alt` mode (flag #) we keep the `.` even if there are no fractional - // digits. In non-alt mode, we strip it. - if (ABSL_PREDICT_FALSE(state.precision == 0 && !state.conv.flags().alt)) { - --size; - } - - FinalPrint(string_view(digits, size), state.precision, state); -} - -template -void FormatFNegativeExp(Int v, int exp, const FormatState &state) { - constexpr int input_bits = sizeof(Int) * 8; - - using IntegralPrinter = DigitPrinter; - using FractionalPrinter = DigitPrinter; - - static constexpr size_t integral_size = - 1 + /* in case we need to round up an extra digit */ - IntegralPrinter::kDigits10 + 1; - char buffer[integral_size + /* . */ 1 + num_bits]; - buffer[integral_size] = '.'; - char *const integral_digits_end = buffer + integral_size; - char *integral_digits_start; - char *const fractional_digits_start = buffer + integral_size + 1; - - if (exp < input_bits) { - integral_digits_start = IntegralPrinter::PrintIntegralDigitsFromRight( - v >> exp, 0, integral_digits_end); - } else { - integral_digits_start = integral_digits_end - 1; - *integral_digits_start = '0'; - } - - // PrintFractionalDigits may pull a carried 1 all the way up through the - // integral portion. - integral_digits_start[-1] = '0'; - auto fractional_result = FractionalPrinter::PrintFractionalDigits( - static_cast(v), - fractional_digits_start, exp, state.precision); - if (integral_digits_start[-1] != '0') --integral_digits_start; - - size_t size = fractional_result.end - integral_digits_start; - - // In `alt` mode (flag #) we keep the `.` even if there are no fractional - // digits. In non-alt mode, we strip it. - if (ABSL_PREDICT_FALSE(state.precision == 0 && !state.conv.flags().alt)) { - --size; - } - FinalPrint(string_view(integral_digits_start, size), - fractional_result.precision, state); -} - -template -void FormatF(Int mantissa, int exp, const FormatState &state) { - // Remove trailing zeros as they are not useful. - // This helps use faster implementations/less stack space in some cases. - if (mantissa != 0) { - int trailing = TrailingZeros(mantissa); - mantissa >>= trailing; - exp += trailing; - } - - // The table driven dispatch gives us two benefits: fast distpatch and - // prevent inlining. - // We must not inline any of the functions below (other than the ones for - // 64-bit) to avoid blowing up this stack frame. - - if (exp >= 0) { - // We will left shift the mantissa. Calculate how many bits we need. - // Special case 64-bit as we will use a uint64_t for it. Use a table for the - // rest and unconditionally use uint128. - const int total_bits = sizeof(Int) * 8 - LeadingZeros(mantissa) + exp; - - if (total_bits <= 64) { - return FormatFPositiveExp<64>(mantissa, exp, state); - } else { - using Formatter = void (*)(uint128, int, const FormatState &); - static constexpr Formatter kFormatters[] = { - FormatFPositiveExp<1 << 7>, FormatFPositiveExp<1 << 8>, - FormatFPositiveExp<1 << 9>, FormatFPositiveExp<1 << 10>, - FormatFPositiveExp<1 << 11>, FormatFPositiveExp<1 << 12>, - FormatFPositiveExp<1 << 13>, FormatFPositiveExp<1 << 14>, - FormatFPositiveExp<1 << 15>, - }; - static constexpr int max_total_bits = - sizeof(Int) * 8 + std::numeric_limits::max_exponent; - assert(total_bits <= max_total_bits); - static_assert(max_total_bits <= (1 << 15), ""); - const int log2 = - 64 - LeadingZeros((static_cast(total_bits) - 1) / 128); - assert(log2 < std::end(kFormatters) - std::begin(kFormatters)); - kFormatters[log2](mantissa, exp, state); - } - } else { - exp = -exp; - - // We know we don't need more than Int itself for the integral part. - // We need `precision` fractional digits, but there are at most `exp` - // non-zero digits after the decimal point. The rest will be zeros. - // Special case 64-bit as we will use a uint64_t for it. Use a table for the - // rest and unconditionally use uint128. - - if (exp <= 64) { - return FormatFNegativeExp<64>(mantissa, exp, state); - } else { - using Formatter = void (*)(uint128, int, const FormatState &); - static constexpr Formatter kFormatters[] = { - FormatFNegativeExp<1 << 7>, FormatFNegativeExp<1 << 8>, - FormatFNegativeExp<1 << 9>, FormatFNegativeExp<1 << 10>, - FormatFNegativeExp<1 << 11>, FormatFNegativeExp<1 << 12>, - FormatFNegativeExp<1 << 13>, FormatFNegativeExp<1 << 14>}; - static_assert( - -std::numeric_limits::min_exponent <= (1 << 14), ""); - const int log2 = - 64 - LeadingZeros((static_cast(exp) - 1) / 128); - assert(log2 < std::end(kFormatters) - std::begin(kFormatters)); - kFormatters[log2](mantissa, exp, state); - } - } -} - char *CopyStringTo(string_view v, char *out) { std::memcpy(out, v.data(), v.size()); return out + v.size(); @@ -556,7 +95,7 @@ template bool ConvertNonNumericFloats(char sign_char, Float v, const ConversionSpec &conv, FormatSinkImpl *sink) { char text[4], *ptr = text; - if (sign_char != '\0') *ptr++ = sign_char; + if (sign_char) *ptr++ = sign_char; if (std::isnan(v)) { ptr = std::copy_n(conv.conv().upper() ? "NAN" : "nan", 3, ptr); } else if (std::isinf(v)) { @@ -626,12 +165,7 @@ constexpr bool CanFitMantissa() { template struct Decomposed { - using MantissaType = - absl::conditional_t::value, uint128, - uint64_t>; - static_assert(std::numeric_limits::digits <= sizeof(MantissaType) * 8, - ""); - MantissaType mantissa; + Float mantissa; int exponent; }; @@ -642,8 +176,7 @@ Decomposed Decompose(Float v) { Float m = std::frexp(v, &exp); m = std::ldexp(m, std::numeric_limits::digits); exp -= std::numeric_limits::digits; - - return {static_cast::MantissaType>(m), exp}; + return {m, exp}; } // Print 'digits' as decimal. @@ -801,7 +334,7 @@ bool FloatToBuffer(Decomposed decomposed, int precision, Buffer *out, static_cast(decomposed.exponent), precision, out, exp)) return true; -#if defined(ABSL_HAVE_INTRINSIC_INT128) +#if defined(__SIZEOF_INT128__) // If that is not enough, try with __uint128_t. return CanFitMantissa() && FloatToBufferImpl<__uint128_t, Float, mode>( @@ -829,7 +362,7 @@ void WriteBufferToSink(char sign_char, string_view str, } sink->Append(left_spaces, ' '); - if (sign_char != '\0') sink->Append(1, sign_char); + if (sign_char) sink->Append(1, sign_char); sink->Append(zeros, '0'); sink->Append(str); sink->Append(right_spaces, ' '); @@ -866,9 +399,12 @@ bool FloatToSink(const Float v, const ConversionSpec &conv, switch (conv.conv().id()) { case ConversionChar::f: case ConversionChar::F: - FormatF(decomposed.mantissa, decomposed.exponent, - {sign_char, precision, conv, sink}); - return true; + if (!FloatToBuffer(decomposed, precision, &buffer, + nullptr)) { + return FallbackToSnprintf(v, conv, sink); + } + if (!conv.flags().alt && buffer.back() == '.') buffer.pop_back(); + break; case ConversionChar::e: case ConversionChar::E: @@ -930,22 +466,11 @@ bool FloatToSink(const Float v, const ConversionSpec &conv, bool ConvertFloatImpl(long double v, const ConversionSpec &conv, FormatSinkImpl *sink) { - if (std::numeric_limits::digits == - 2 * std::numeric_limits::digits) { - // This is the `double-double` representation of `long double`. - // We do not handle it natively. Fallback to snprintf. - return FallbackToSnprintf(v, conv, sink); - } - return FloatToSink(v, conv, sink); } bool ConvertFloatImpl(float v, const ConversionSpec &conv, FormatSinkImpl *sink) { - // DivideBy10WithCarry is not actually used in some builds. This here silences - // the "unused" warning. We just need to put it in any function that is really - // used. - (void)&DivideBy10WithCarry; return FloatToSink(v, conv, sink); } diff --git a/absl/types/internal/optional.h b/absl/types/internal/optional.h index 562c84ef..8acbda20 100644 --- a/absl/types/internal/optional.h +++ b/absl/types/internal/optional.h @@ -25,6 +25,34 @@ #include "absl/meta/type_traits.h" #include "absl/utility/utility.h" +// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS +// +// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015. +// __cpp_inheriting_constructors is a predefined macro and a recommended way to +// check for this language feature, but GCC doesn't support it until 5.0 and +// Clang doesn't support it until 3.6. +// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template +// constructor. For example, the following code won't work on MSVC 2015 Update3: +// struct Base { +// int t; +// template +// constexpr Base(T t_) : t(t_) {} +// }; +// struct Foo : Base { +// using Base::Base; +// } +// constexpr Foo foo(0); // doesn't work on MSVC 2015 +#if defined(__clang__) +#if __has_feature(cxx_inheriting_constructors) +#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1 +#endif +#elif (defined(__GNUC__) && \ + (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \ + (__cpp_inheriting_constructors >= 200802) || \ + (defined(_MSC_VER) && _MSC_VER >= 1910) +#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1 +#endif + namespace absl { // Forward declaration @@ -108,7 +136,7 @@ template class optional_data_base : public optional_data_dtor_base { protected: using base = optional_data_dtor_base; -#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS +#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS using base::base; #else optional_data_base() = default; @@ -151,7 +179,7 @@ class optional_data; template class optional_data : public optional_data_base { protected: -#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS +#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS using optional_data_base::optional_data_base; #else optional_data() = default; @@ -165,7 +193,7 @@ class optional_data : public optional_data_base { template class optional_data : public optional_data_base { protected: -#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS +#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS using optional_data_base::optional_data_base; #else template @@ -361,4 +389,6 @@ struct optional_hash_base >()( } // namespace optional_internal } // namespace absl +#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS + #endif // ABSL_TYPES_INTERNAL_OPTIONAL_H_ diff --git a/absl/types/optional.h b/absl/types/optional.h index 17f78984..57983319 100644 --- a/absl/types/optional.h +++ b/absl/types/optional.h @@ -64,34 +64,6 @@ using std::nullopt; #include "absl/types/bad_optional_access.h" #include "absl/types/internal/optional.h" -// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS -// -// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015. -// __cpp_inheriting_constructors is a predefined macro and a recommended way to -// check for this language feature, but GCC doesn't support it until 5.0 and -// Clang doesn't support it until 3.6. -// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template -// constructor. For example, the following code won't work on MSVC 2015 Update3: -// struct Base { -// int t; -// template -// constexpr Base(T t_) : t(t_) {} -// }; -// struct Foo : Base { -// using Base::Base; -// } -// constexpr Foo foo(0); // doesn't work on MSVC 2015 -#if defined(__clang__) -#if __has_feature(cxx_inheriting_constructors) -#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1 -#endif -#elif (defined(__GNUC__) && \ - (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \ - (__cpp_inheriting_constructors >= 200802) || \ - (defined(_MSC_VER) && _MSC_VER >= 1910) -#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1 -#endif - namespace absl { // nullopt_t @@ -791,7 +763,6 @@ struct hash > } // namespace std -#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS #undef ABSL_MSVC_CONSTEXPR_BUG_IN_UNION_LIKE_CLASS #endif // ABSL_HAVE_STD_OPTIONAL -- cgit v1.2.3 From ca3f87560a0eef716195cadf66dc6b938a579ec6 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 23 Apr 2019 12:04:13 -0700 Subject: Export of internal Abseil changes. -- 5a5dba4252e764e6737070bf0a31074bf23a3b41 by Abseil Team : Internal change. PiperOrigin-RevId: 244898913 -- 3eb7d5b445ffbf08a104e39cd15aecf568417333 by Matt Calabrese : Introduce absl::is_trivially_move_constructible and absl::is_trivially_move_assignable, and update the absl::is_trivially_copy_constructible and absl::is_trivially_copy_assignable traits to use similar techniques (should now be closer to the standard behavior). PiperOrigin-RevId: 244859015 -- 7da05a24fa786cab3985de0c39a186d73dcbcfb5 by Abseil Team : Fix misspellings in comments in raw_hash_set.h. PiperOrigin-RevId: 244754700 -- 5c057be96048f21473d5ec45005ab4dcd8dd354f by Derek Mauro : Internal change PiperOrigin-RevId: 244744239 -- 592394e3c2e98f1238d3fb6fcb0d20c3e3739ba9 by Derek Mauro : Limit the raw_hash_set prefetch test to x86-64. PiperOrigin-RevId: 244737534 -- 99ebe4e003633c8ff7838b035b31a827994879ef by Derek Mauro : Workaround warning 4091 in an MSVC header. PiperOrigin-RevId: 244701744 -- 0aa23f09a32efe7985ee55b0217190f08da42477 by Abseil Team : Fix comment typo. PiperOrigin-RevId: 244659371 -- c6cdb87e9f28062c8daa29b3d8d68182ecc16383 by Derek Mauro : Fix -Wundef warnings and support -Wundef. PiperOrigin-RevId: 244244968 -- 06b81245f7696b20c3c63b0618d33ac25e29cad6 by Abseil Team : Fix a typo in inlined_vector.h. PiperOrigin-RevId: 244230809 -- 94877a2125d2cfe837384240e4d6551f39d737e4 by Greg Falcon : Fix sysinfo_test for emscripten. PiperOrigin-RevId: 244198804 -- ec7783531ef7f9df2da37d341d61f7cb2bf843f0 by Shaindel Schwartz : Import of CCTZ from GitHub. Fixes #291. PiperOrigin-RevId: 244184598 -- b652c14fa95ea206c217487ee713b11f5d1762b3 by Matt Calabrese : Emulate the `in_place_index` and `in_place_type` variable templates such that they are syntactically usable in C++11 with `any` and `variant`. Also pull in the variable templates from namespace std when available. The main observable differences here are: 1) The types of `in_place_index_t` and `in_place_type_t` become function pointer types rather than structs when using the implementation that is not an alias of the std equivalents. 2) The types of `in_place_index` and `in_place_type` are not directly `in_place_index_t` and `in_place_type_t`, but rather they become function types that decay to the corresponding function pointer types. 3) The default constructor for `in_place_index_t` and `in_place_type_t` instantiations is no longer explicit, but for these templates I think that's less important than for something like `in_place_t` since the _type_t and _index_t versions basically never have their template parameter non-deduced when participating in overload resolution with conflicting candidates. 4) While idiomatic usage of `in_place_type_t` and `in_place_index_t` with std::variant and std::any should not be affected, there is the possibility that strange, non-idiomatic uses may be affected in the wild. 5) Default construction (rather than value-initialization) leads to a default-constructed pointer. PiperOrigin-RevId: 244180003 -- b9ac5a96581837ffa24532117b7ea302a5569751 by Derek Mauro : Fix MSVC debug assertion. isprint is undefined for values not representable as unsigned char or EOF. PiperOrigin-RevId: 244083005 -- 41758be6137c2f25e84b50f23938e49484be2903 by Shaindel Schwartz : Update config settings for Apple platforms. PiperOrigin-RevId: 244040587 -- c90df6a26db94b0305a0c954455a621542a89d91 by Abseil Team : Internal change PiperOrigin-RevId: 244024427 -- c71e9ceb89495354eca7d02bd905ffeaa9029aec by Derek Mauro : Adds missing ABSL_DEFAULT_COPTS and ABSL_TEST_COPTS to CMakeLists.txt Don't error on deprecated declarations in tests. It is completely reasonable to test that code marked deprecated still works. PiperOrigin-RevId: 244003941 -- e1326a96527a8ba9b8d120161545260da9c4562e by Abseil Team : Internal change. PiperOrigin-RevId: 243990623 -- 90b8e12934c7711e1bfcc0117d21288bf9220dee by Abseil Team : Add variation of absl::Base64Escape/WebSafeBase64Escape that directly returns its result. PiperOrigin-RevId: 243894308 -- 317fef3344481ebc5c35712d42f5d8a0fa64dff4 by Abseil Team : Enable raw logging in Emscripten builds. PiperOrigin-RevId: 243893705 GitOrigin-RevId: 5a5dba4252e764e6737070bf0a31074bf23a3b41 Change-Id: I19293aab73cc98d9e9bf6a9fdc30819764adb9db --- absl/BUILD.bazel | 15 +- absl/algorithm/CMakeLists.txt | 4 + absl/base/CMakeLists.txt | 34 ++++ absl/base/internal/raw_logging.cc | 3 +- absl/base/internal/sysinfo_test.cc | 6 +- absl/base/internal/unscaledcycleclock.h | 3 +- absl/container/CMakeLists.txt | 43 ++++- absl/container/inlined_vector.h | 6 +- absl/container/internal/raw_hash_set.h | 8 +- absl/container/internal/raw_hash_set_test.cc | 11 +- absl/copts/GENERATED_AbseilCopts.cmake | 6 +- absl/copts/GENERATED_copts.bzl | 6 +- absl/copts/copts.py | 8 +- absl/debugging/CMakeLists.txt | 12 ++ absl/debugging/internal/demangle_test.cc | 5 +- absl/debugging/symbolize_win32.inc | 6 + absl/hash/CMakeLists.txt | 6 +- absl/hash/internal/hash.h | 2 +- absl/memory/memory_test.cc | 4 +- absl/meta/CMakeLists.txt | 2 + absl/meta/type_traits.h | 109 +++++++++++- absl/meta/type_traits_test.cc | 191 +++++++++++++++++++++ absl/numeric/CMakeLists.txt | 2 + absl/strings/CMakeLists.txt | 2 + absl/strings/escaping.cc | 22 ++- absl/strings/escaping.h | 12 +- absl/strings/escaping_test.cc | 3 + absl/strings/internal/str_format/convert_test.cc | 9 +- absl/synchronization/CMakeLists.txt | 2 + absl/time/internal/cctz/BUILD.bazel | 23 +++ .../internal/cctz/include/cctz/civil_time_detail.h | 2 +- absl/time/internal/cctz/src/civil_time_test.cc | 4 +- absl/time/internal/cctz/src/time_zone_lookup.cc | 4 +- absl/time/time_test.cc | 2 +- absl/types/any_test.cc | 68 +++++++- absl/types/variant_test.cc | 110 +++++++++--- absl/utility/utility.h | 26 ++- 37 files changed, 694 insertions(+), 87 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel index 8e3c1773..853330d4 100644 --- a/absl/BUILD.bazel +++ b/absl/BUILD.bazel @@ -25,13 +25,18 @@ create_llvm_config( visibility = [":__subpackages__"], ) -# following configs are based on mapping defined in: https://git.io/v5Ijz +config_setting( + name = "osx", + constraint_values = [ + "@bazel_tools//platforms:osx", + ], +) + config_setting( name = "ios", - values = { - "cpu": "darwin", - }, - visibility = [":__subpackages__"], + constraint_values = [ + "@bazel_tools//platforms:ios", + ], ) config_setting( diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt index c51eb10e..9fbe36f6 100644 --- a/absl/algorithm/CMakeLists.txt +++ b/absl/algorithm/CMakeLists.txt @@ -29,6 +29,8 @@ absl_cc_test( algorithm_test SRCS "algorithm_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::algorithm gmock_main @@ -53,6 +55,8 @@ absl_cc_test( container_test SRCS "container_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::algorithm_container absl::base diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 5042f156..b9f35bc0 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -26,6 +26,8 @@ absl_cc_library( "internal/spinlock_posix.inc" "internal/spinlock_wait.cc" "internal/spinlock_win32.inc" + COPTS + ${ABSL_DEFAULT_COPTS} DEPS absl::core_headers ) @@ -221,6 +223,8 @@ absl_cc_test( atomic_hook_test SRCS "internal/atomic_hook_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base absl::core_headers @@ -232,6 +236,8 @@ absl_cc_test( bit_cast_test SRCS "bit_cast_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base absl::core_headers @@ -243,6 +249,8 @@ absl_cc_test( throw_delegate_test SRCS "throw_delegate_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base absl::throw_delegate @@ -257,6 +265,8 @@ absl_cc_test( "inline_variable_test.cc" "inline_variable_test_a.cc" "inline_variable_test_b.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base_internal gtest_main @@ -267,6 +277,8 @@ absl_cc_test( invoke_test SRCS "invoke_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base_internal absl::memory @@ -297,6 +309,8 @@ absl_cc_test( spinlock_test SRCS "spinlock_test_common.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base absl::core_headers @@ -324,6 +338,8 @@ absl_cc_test( endian_test SRCS "internal/endian_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base absl::config @@ -336,6 +352,8 @@ absl_cc_test( config_test SRCS "config_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::config absl::synchronization @@ -347,6 +365,8 @@ absl_cc_test( call_once_test SRCS "call_once_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base absl::core_headers @@ -359,6 +379,8 @@ absl_cc_test( raw_logging_test SRCS "raw_logging_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base absl::strings @@ -370,6 +392,8 @@ absl_cc_test( sysinfo_test SRCS "internal/sysinfo_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base absl::synchronization @@ -381,6 +405,8 @@ absl_cc_test( low_level_alloc_test SRCS "internal/low_level_alloc_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::malloc_internal Threads::Threads @@ -391,6 +417,8 @@ absl_cc_test( thread_identity_test SRCS "internal/thread_identity_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base absl::core_headers @@ -415,6 +443,8 @@ absl_cc_test( bits_test SRCS "internal/bits_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::bits gtest_main @@ -438,6 +468,8 @@ absl_cc_test( scoped_set_env_test SRCS "internal/scoped_set_env_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::scoped_set_env gtest_main @@ -448,6 +480,8 @@ absl_cc_test( cmake_thread_test SRCS "internal/cmake_thread_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::base ) diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc index b5a05e8c..878fe6c6 100644 --- a/absl/base/internal/raw_logging.cc +++ b/absl/base/internal/raw_logging.cc @@ -36,7 +36,8 @@ // This preprocessor token is also defined in raw_io.cc. If you need to copy // this, consider moving both to config.h instead. #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \ - defined(__Fuchsia__) || defined(__native_client__) + defined(__Fuchsia__) || defined(__native_client__) || \ + defined(__EMSCRIPTEN__) #include diff --git a/absl/base/internal/sysinfo_test.cc b/absl/base/internal/sysinfo_test.cc index 247f3d88..82bbcc2b 100644 --- a/absl/base/internal/sysinfo_test.cc +++ b/absl/base/internal/sysinfo_test.cc @@ -37,12 +37,12 @@ TEST(SysinfoTest, NumCPUs) { } TEST(SysinfoTest, NominalCPUFrequency) { -#if !(defined(__aarch64__) && defined(__linux__)) +#if !(defined(__aarch64__) && defined(__linux__)) && !defined(__EMSCRIPTEN__) EXPECT_GE(NominalCPUFrequency(), 1000.0) << "NominalCPUFrequency() did not return a reasonable value"; #else - // TODO(absl-team): Aarch64 cannot read the CPU frequency from sysfs, so we - // get back 1.0. Fix once the value is available. + // Aarch64 cannot read the CPU frequency from sysfs, so we get back 1.0. + // Emscripten does not have a sysfs to read from at all. EXPECT_EQ(NominalCPUFrequency(), 1.0) << "CPU frequency detection was fixed! Please update unittest."; #endif diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h index 58950cc2..2d361e96 100644 --- a/absl/base/internal/unscaledcycleclock.h +++ b/absl/base/internal/unscaledcycleclock.h @@ -59,7 +59,8 @@ // CycleClock that runs at atleast 1 MHz. We've found some Android // ARM64 devices where this is not the case, so we disable it by // default on Android ARM64. -#if defined(__native_client__) || TARGET_OS_IPHONE || \ +#if defined(__native_client__) || \ + (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \ (defined(__ANDROID__) && defined(__aarch64__)) #define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0 #else diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index 3c44bd0e..9531d7f9 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt @@ -27,7 +27,9 @@ absl_cc_library( NAME compressed_tuple HDRS - "internal/compressed_tuple.h" + "internal/compressed_tuple.h" + COPTS + ${ABSL_DEFAULT_COPTS} DEPS absl::utility PUBLIC @@ -38,6 +40,8 @@ absl_cc_test( compressed_tuple_test SRCS "internal/compressed_tuple_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::compressed_tuple absl::memory @@ -68,6 +72,7 @@ absl_cc_test( SRCS "fixed_array_test.cc" COPTS + ${ABSL_TEST_COPTS} ${ABSL_EXCEPTIONS_FLAG} LINKOPTS ${ABSL_EXCEPTIONS_FLAG_LINKOPTS} @@ -84,6 +89,8 @@ absl_cc_test( fixed_array_test_noexceptions SRCS "fixed_array_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::fixed_array absl::exception_testing @@ -98,6 +105,7 @@ absl_cc_test( SRCS "fixed_array_exception_safety_test.cc" COPTS + ${ABSL_TEST_COPTS} ${ABSL_EXCEPTIONS_FLAG} LINKOPTS ${ABSL_EXCEPTIONS_FLAG_LINKOPTS} @@ -151,6 +159,7 @@ absl_cc_test( SRCS "inlined_vector_test.cc" COPTS + ${ABSL_TEST_COPTS} ${ABSL_EXCEPTIONS_FLAG} LINKOPTS ${ABSL_EXCEPTIONS_FLAG_LINKOPTS} @@ -172,6 +181,8 @@ absl_cc_test( inlined_vector_test_noexceptions SRCS "inlined_vector_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::inlined_vector absl::test_instance_tracker @@ -201,6 +212,8 @@ absl_cc_test( test_instance_tracker_test SRCS "internal/test_instance_tracker_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::test_instance_tracker gmock_main @@ -227,6 +240,8 @@ absl_cc_test( flat_hash_map_test SRCS "flat_hash_map_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::flat_hash_map absl::hash_generator_testing @@ -261,6 +276,7 @@ absl_cc_test( SRCS "flat_hash_set_test.cc" COPTS + ${ABSL_TEST_COPTS} "-DUNORDERED_SET_CXX17" DEPS absl::flat_hash_set @@ -296,6 +312,8 @@ absl_cc_test( node_hash_map_test SRCS "node_hash_map_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::hash_generator_testing absl::node_hash_map @@ -329,6 +347,7 @@ absl_cc_test( SRCS "node_hash_set_test.cc" COPTS + ${ABSL_TEST_COPTS} "-DUNORDERED_SET_CXX17" DEPS absl::hash_generator_testing @@ -358,6 +377,8 @@ absl_cc_test( container_memory_test SRCS "internal/container_memory_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::container_memory absl::strings @@ -383,6 +404,8 @@ absl_cc_test( hash_function_defaults_test SRCS "internal/hash_function_defaults_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::hash_function_defaults absl::hash @@ -424,6 +447,8 @@ absl_cc_test( hash_policy_testing_test SRCS "internal/hash_policy_testing_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::hash_policy_testing gmock_main @@ -446,6 +471,8 @@ absl_cc_test( hash_policy_traits_test SRCS "internal/hash_policy_traits_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::hash_policy_traits gmock_main @@ -472,6 +499,8 @@ absl_cc_test( hashtablez_sampler_test SRCS "internal/hashtablez_sampler_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::hashtablez_sampler absl::have_sse @@ -523,6 +552,8 @@ absl_cc_test( node_hash_policy_test SRCS "internal/node_hash_policy_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::hash_policy_traits absl::node_hash_policy @@ -587,6 +618,8 @@ absl_cc_test( raw_hash_set_test SRCS "internal/raw_hash_set_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::container_memory absl::hash_function_defaults @@ -604,6 +637,8 @@ absl_cc_test( raw_hash_set_allocator_test SRCS "internal/raw_hash_set_allocator_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::raw_hash_set absl::tracked @@ -632,6 +667,8 @@ absl_cc_test( layout_test SRCS "internal/layout_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::layout absl::base @@ -765,6 +802,8 @@ absl_cc_test( unordered_set_test SRCS "internal/unordered_set_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::unordered_set_constructor_test absl::unordered_set_lookup_test @@ -778,6 +817,8 @@ absl_cc_test( unordered_map_test SRCS "internal/unordered_map_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::unordered_map_constructor_test absl::unordered_map_lookup_test diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index 978d5033..34e9aa0a 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -174,9 +174,9 @@ class InlinedVector { // Creates an inlined vector by moving in the contents of an `other` inlined // vector without performing any allocations. If `other` contains allocated // memory, the newly-created instance will take ownership of that memory - // (leaving `other` itself empty). However, if `other` does not contain any - // allocated memory, the new inlined vector will will perform element-wise - // move construction of `other`s elements. + // (leaving `other` empty). However, if `other` does not contain allocated + // memory (i.e. is inlined), the new inlined vector will perform element-wise + // move construction of `other`'s elements. // // NOTE: since no allocation is performed for the inlined vector in either // case, the `noexcept(...)` specification depends on whether moving the diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 9c926812..8ac0dda2 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -1437,15 +1437,15 @@ class raw_hash_set { void initialize_slots() { assert(capacity_); - // Folks with custom allocators often make unwaranted assumptions about the + // Folks with custom allocators often make unwarranted assumptions about the // behavior of their classes vis-a-vis trivial destructability and what // calls they will or wont make. Avoid sampling for people with custom - // allocators to get us out of this mess. This is not a hard guarntee but a - // workaround while we plan the exact guarantee we want to provide. + // allocators to get us out of this mess. This is not a hard guarantee but + // a workaround while we plan the exact guarantee we want to provide. // // People are often sloppy with the exact type of their allocator (sometimes // it has an extra const or is missing the pair, but rebinds made it work - // anyway). To avoid the ambiguitity, we work off SlotAlloc which we have + // anyway). To avoid the ambiguity, we work off SlotAlloc which we have // bound more carefully. if (std::is_same>::value && slots_ == nullptr) { diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index cb845121..ed4ca8c8 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -433,9 +433,10 @@ TEST(Table, Prefetch) { // Do not run in debug mode, when prefetch is not implemented, or when // sanitizers are enabled, or on WebAssembly. -#if defined(NDEBUG) && defined(__GNUC__) && !defined(ADDRESS_SANITIZER) && \ - !defined(MEMORY_SANITIZER) && !defined(THREAD_SANITIZER) && \ - !defined(UNDEFINED_BEHAVIOR_SANITIZER) && !defined(__EMSCRIPTEN__) +#if defined(NDEBUG) && defined(__GNUC__) && defined(__x86_64__) && \ + !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) && \ + !defined(THREAD_SANITIZER) && !defined(UNDEFINED_BEHAVIOR_SANITIZER) && \ + !defined(__EMSCRIPTEN__) const auto now = [] { return absl::base_internal::CycleClock::Now(); }; // Make size enough to not fit in L2 cache (16.7 Mb) @@ -1080,7 +1081,7 @@ ProbeStats CollectProbeStatsOnKeysXoredWithSeed(const std::vector& keys ExpectedStats XorSeedExpectedStats() { constexpr bool kRandomizesInserts = -#if NDEBUG +#ifdef NDEBUG false; #else // NDEBUG true; @@ -1174,7 +1175,7 @@ ProbeStats CollectProbeStatsOnLinearlyTransformedKeys( ExpectedStats LinearTransformExpectedStats() { constexpr bool kRandomizesInserts = -#if NDEBUG +#ifdef NDEBUG false; #else // NDEBUG true; diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake index 5543638c..27e6f5a0 100644 --- a/absl/copts/GENERATED_AbseilCopts.cmake +++ b/absl/copts/GENERATED_AbseilCopts.cmake @@ -37,7 +37,6 @@ list(APPEND ABSL_CLANG_CL_FLAGS "-Wno-shorten-64-to-32" "-Wno-switch-enum" "-Wno-thread-safety-negative" - "-Wno-undef" "-Wno-unknown-warning-option" "-Wno-unreachable-code" "-Wno-unused-macros" @@ -62,6 +61,7 @@ list(APPEND ABSL_CLANG_CL_FLAGS list(APPEND ABSL_CLANG_CL_TEST_FLAGS "-Wno-c99-extensions" + "-Wno-deprecated-declarations" "-Wno-missing-noreturn" "-Wno-missing-prototypes" "-Wno-missing-variable-declarations" @@ -103,6 +103,7 @@ list(APPEND ABSL_GCC_FLAGS list(APPEND ABSL_GCC_TEST_FLAGS "-Wno-conversion-null" + "-Wno-deprecated-declarations" "-Wno-missing-declarations" "-Wno-sign-compare" "-Wno-unused-function" @@ -144,7 +145,6 @@ list(APPEND ABSL_LLVM_FLAGS "-Wno-shorten-64-to-32" "-Wno-switch-enum" "-Wno-thread-safety-negative" - "-Wno-undef" "-Wno-unknown-warning-option" "-Wno-unreachable-code" "-Wno-unused-macros" @@ -164,6 +164,7 @@ list(APPEND ABSL_LLVM_FLAGS list(APPEND ABSL_LLVM_TEST_FLAGS "-Wno-c99-extensions" + "-Wno-deprecated-declarations" "-Wno-missing-noreturn" "-Wno-missing-prototypes" "-Wno-missing-variable-declarations" @@ -211,5 +212,6 @@ list(APPEND ABSL_MSVC_TEST_FLAGS "/wd4018" "/wd4101" "/wd4503" + "/wd4996" "/DNOMINMAX" ) diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl index 10caa78a..0feb0f4b 100644 --- a/absl/copts/GENERATED_copts.bzl +++ b/absl/copts/GENERATED_copts.bzl @@ -38,7 +38,6 @@ ABSL_CLANG_CL_FLAGS = [ "-Wno-shorten-64-to-32", "-Wno-switch-enum", "-Wno-thread-safety-negative", - "-Wno-undef", "-Wno-unknown-warning-option", "-Wno-unreachable-code", "-Wno-unused-macros", @@ -63,6 +62,7 @@ ABSL_CLANG_CL_FLAGS = [ ABSL_CLANG_CL_TEST_FLAGS = [ "-Wno-c99-extensions", + "-Wno-deprecated-declarations", "-Wno-missing-noreturn", "-Wno-missing-prototypes", "-Wno-missing-variable-declarations", @@ -104,6 +104,7 @@ ABSL_GCC_FLAGS = [ ABSL_GCC_TEST_FLAGS = [ "-Wno-conversion-null", + "-Wno-deprecated-declarations", "-Wno-missing-declarations", "-Wno-sign-compare", "-Wno-unused-function", @@ -145,7 +146,6 @@ ABSL_LLVM_FLAGS = [ "-Wno-shorten-64-to-32", "-Wno-switch-enum", "-Wno-thread-safety-negative", - "-Wno-undef", "-Wno-unknown-warning-option", "-Wno-unreachable-code", "-Wno-unused-macros", @@ -165,6 +165,7 @@ ABSL_LLVM_FLAGS = [ ABSL_LLVM_TEST_FLAGS = [ "-Wno-c99-extensions", + "-Wno-deprecated-declarations", "-Wno-missing-noreturn", "-Wno-missing-prototypes", "-Wno-missing-variable-declarations", @@ -212,5 +213,6 @@ ABSL_MSVC_TEST_FLAGS = [ "/wd4018", "/wd4101", "/wd4503", + "/wd4996", "/DNOMINMAX", ] diff --git a/absl/copts/copts.py b/absl/copts/copts.py index cdcf61d6..154c0ce6 100644 --- a/absl/copts/copts.py +++ b/absl/copts/copts.py @@ -65,7 +65,6 @@ LLVM_DISABLE_WARNINGS_FLAGS = [ "-Wno-shorten-64-to-32", "-Wno-switch-enum", "-Wno-thread-safety-negative", - "-Wno-undef", "-Wno-unknown-warning-option", "-Wno-unreachable-code", # Causes warnings on include guards @@ -89,6 +88,7 @@ LLVM_DISABLE_WARNINGS_FLAGS = [ LLVM_TEST_DISABLE_WARNINGS_FLAGS = [ "-Wno-c99-extensions", + "-Wno-deprecated-declarations", "-Wno-missing-noreturn", "-Wno-missing-prototypes", "-Wno-missing-variable-declarations", @@ -110,7 +110,9 @@ LLVM_TEST_DISABLE_WARNINGS_FLAGS = [ ] MSVC_STYLE_EXCEPTIONS_FLAGS = [ - "/U_HAS_EXCEPTIONS", "/D_HAS_EXCEPTIONS=1", "/EHsc" + "/U_HAS_EXCEPTIONS", + "/D_HAS_EXCEPTIONS=1", + "/EHsc" ] MSVC_DEFINES = [ @@ -148,6 +150,7 @@ COPT_VARS = { ], "ABSL_GCC_TEST_FLAGS": [ "-Wno-conversion-null", + "-Wno-deprecated-declarations", "-Wno-missing-declarations", "-Wno-sign-compare", "-Wno-unused-function", @@ -183,6 +186,7 @@ COPT_VARS = { "/wd4018", # signed/unsigned mismatch "/wd4101", # unreferenced local variable "/wd4503", # decorated name length exceeded, name was truncated + "/wd4996", # use of deprecated symbol "/DNOMINMAX", # disable the min() and max() macros from ], "ABSL_MSVC_EXCEPTIONS_FLAGS": diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt index dccd4a56..d813fede 100644 --- a/absl/debugging/CMakeLists.txt +++ b/absl/debugging/CMakeLists.txt @@ -43,6 +43,8 @@ absl_cc_library( "symbolize_win32.inc" COPTS ${ABSL_DEFAULT_COPTS} + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} DEPS absl::debugging_internal absl::demangle_internal @@ -196,6 +198,8 @@ absl_cc_library( leak_check_disable SRCS "leak_check_disable.cc" + COPTS + ${ABSL_DEFAULT_COPTS} PUBLIC ) @@ -207,6 +211,7 @@ absl_cc_library( SRCS "leak_check.cc" COPTS + ${ABSL_DEFAULT_COPTS} $<$:-DLEAK_SANITIZER> TESTONLY ) @@ -219,6 +224,7 @@ absl_cc_library( SRCS "leak_check.cc" COPTS + ${ABSL_DEFAULT_COPTS} "-ULEAK_SANITIZER" TESTONLY ) @@ -229,6 +235,7 @@ absl_cc_test( SRCS "leak_check_test.cc" COPTS + ${ABSL_DEFAULT_COPTS} "$<$:-DABSL_EXPECT_LEAK_SANITIZER>" LINKOPTS "${ABSL_LSAN_LINKOPTS}" @@ -244,6 +251,7 @@ absl_cc_test( SRCS "leak_check_test.cc" COPTS + ${ABSL_TEST_COPTS} "-UABSL_EXPECT_LEAK_SANITIZER" DEPS absl::leak_check_api_disabled_for_testing @@ -256,6 +264,8 @@ absl_cc_test( disabled_leak_check_test SRCS "leak_check_fail_test.cc" + COPTS + ${ABSL_TEST_COPTS} LINKOPTS "${ABSL_LSAN_LINKOPTS}" DEPS @@ -298,6 +308,8 @@ absl_cc_test( absl_cc_library( NAME debugging + COPTS + ${ABSL_DEFAULT_COPTS} DEPS absl::stacktrace absl::leak_check diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index 883b92db..a68ce324 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -81,8 +81,9 @@ TEST(Demangle, Clones) { // Tests that verify that Demangle footprint is within some limit. // They are not to be run under sanitizers as the sanitizers increase // stack consumption by about 4x. -#if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) && \ - !ADDRESS_SANITIZER && !MEMORY_SANITIZER && !THREAD_SANITIZER +#if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) && \ + !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) && \ + !defined(THREAD_SANITIZER) static const char *g_mangled; static char g_demangle_buffer[4096]; diff --git a/absl/debugging/symbolize_win32.inc b/absl/debugging/symbolize_win32.inc index 17ea618a..7ed3bd3a 100644 --- a/absl/debugging/symbolize_win32.inc +++ b/absl/debugging/symbolize_win32.inc @@ -16,7 +16,13 @@ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms680578(v=vs.85).aspx #include + +// MSVC header DbgHelp.h has a warning for an ignored typedef. +#pragma warning(push) +#pragma warning(disable:4091) #include +#pragma warning(pop) + #pragma comment(lib, "DbgHelp") #include diff --git a/absl/hash/CMakeLists.txt b/absl/hash/CMakeLists.txt index 4cafc133..febc551f 100644 --- a/absl/hash/CMakeLists.txt +++ b/absl/hash/CMakeLists.txt @@ -43,6 +43,8 @@ absl_cc_library( hash_testing HDRS "hash_testing.h" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::spy_hash_state absl::meta @@ -56,7 +58,9 @@ absl_cc_test( NAME hash_test SRCS - "hash_test.cc" + "hash_test.cc" + COPTS + ${ABSL_TEST_COPTS} DEPS absl::hash absl::hash_testing diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h index 9ab98901..18665173 100644 --- a/absl/hash/internal/hash.h +++ b/absl/hash/internal/hash.h @@ -615,7 +615,7 @@ struct HashSelect { public: // Probe each implementation in order. - // disjunction provides short circuting wrt instantiation. + // disjunction provides short circuiting wrt instantiation. template using Apply = absl::disjunction< // Probe, // diff --git a/absl/memory/memory_test.cc b/absl/memory/memory_test.cc index 8905433c..c47820e5 100644 --- a/absl/memory/memory_test.cc +++ b/absl/memory/memory_test.cc @@ -620,7 +620,7 @@ TEST(AllocatorTraits, FunctionsFull) { } TEST(AllocatorNoThrowTest, DefaultAllocator) { -#if ABSL_ALLOCATOR_NOTHROW +#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW EXPECT_TRUE(absl::default_allocator_is_nothrow::value); #else EXPECT_FALSE(absl::default_allocator_is_nothrow::value); @@ -628,7 +628,7 @@ TEST(AllocatorNoThrowTest, DefaultAllocator) { } TEST(AllocatorNoThrowTest, StdAllocator) { -#if ABSL_ALLOCATOR_NOTHROW +#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW EXPECT_TRUE(absl::allocator_is_nothrow>::value); #else EXPECT_FALSE(absl::allocator_is_nothrow>::value); diff --git a/absl/meta/CMakeLists.txt b/absl/meta/CMakeLists.txt index f866e54e..672ead2f 100644 --- a/absl/meta/CMakeLists.txt +++ b/absl/meta/CMakeLists.txt @@ -42,6 +42,8 @@ absl_cc_test( absl_cc_library( NAME meta + COPTS + ${ABSL_DEFAULT_COPTS} DEPS absl::type_traits PUBLIC diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index a8068e31..c08e3754 100644 --- a/absl/meta/type_traits.h +++ b/absl/meta/type_traits.h @@ -43,8 +43,39 @@ namespace absl { +// Defined and documented later on in this file. +template +struct is_trivially_move_assignable; + namespace type_traits_internal { +// Silence MSVC warnings about the destructor being defined as deleted. +#if defined(_MSC_VER) && !defined(__GNUC__) +#pragma warning(push) +#pragma warning(disable : 4624) +#endif // defined(_MSC_VER) && !defined(__GNUC__) + +template +union SingleMemberUnion { + T t; +}; + +// Restore the state of the destructor warning that was silenced above. +#if defined(_MSC_VER) && !defined(__GNUC__) +#pragma warning(pop) +#endif // defined(_MSC_VER) && !defined(__GNUC__) + +template +struct IsTriviallyMoveAssignableReference : std::false_type {}; + +template +struct IsTriviallyMoveAssignableReference + : absl::is_trivially_move_assignable::type {}; + +template +struct IsTriviallyMoveAssignableReference + : absl::is_trivially_move_assignable::type {}; + template struct VoidTImpl { using type = void; @@ -275,6 +306,40 @@ struct is_trivially_default_constructible #endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE }; +// is_trivially_move_constructible() +// +// Determines whether the passed type `T` is trivially move constructible. +// +// This metafunction is designed to be a drop-in replacement for the C++11 +// `std::is_trivially_move_constructible()` metafunction for platforms that have +// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do +// fully support C++11, we check whether this yields the same result as the std +// implementation. +// +// NOTE: `T obj(declval());` needs to be well-formed and not call any +// nontrivial operation. Nontrivially destructible types will cause the +// expression to be nontrivial. +template +struct is_trivially_move_constructible + : std::conditional< + std::is_object::value && !std::is_array::value, + std::is_move_constructible< + type_traits_internal::SingleMemberUnion>, + std::is_reference>::type::type { +#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE + private: + static constexpr bool compliant = + std::is_trivially_move_constructible::value == + is_trivially_move_constructible::value; + static_assert(compliant || std::is_trivially_move_constructible::value, + "Not compliant with std::is_trivially_move_constructible; " + "Standard: false, Implementation: true"); + static_assert(compliant || !std::is_trivially_move_constructible::value, + "Not compliant with std::is_trivially_move_constructible; " + "Standard: true, Implementation: false"); +#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE +}; + // is_trivially_copy_constructible() // // Determines whether the passed type `T` is trivially copy constructible. @@ -290,9 +355,11 @@ struct is_trivially_default_constructible // expression to be nontrivial. template struct is_trivially_copy_constructible - : std::integral_constant::value && - is_trivially_destructible::value> { + : std::conditional< + std::is_object::value && !std::is_array::value, + std::is_copy_constructible< + type_traits_internal::SingleMemberUnion>, + std::is_lvalue_reference>::type::type { #ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE private: static constexpr bool compliant = @@ -307,6 +374,42 @@ struct is_trivially_copy_constructible #endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE }; +// is_trivially_move_assignable() +// +// Determines whether the passed type `T` is trivially move assignable. +// +// This metafunction is designed to be a drop-in replacement for the C++11 +// `std::is_trivially_move_assignable()` metafunction for platforms that have +// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do +// fully support C++11, we check whether this yields the same result as the std +// implementation. +// +// NOTE: `is_assignable::value` is `true` if the expression +// `declval() = declval()` is well-formed when treated as an unevaluated +// operand. `is_trivially_assignable` requires the assignment to call no +// operation that is not trivial. `is_trivially_copy_assignable` is simply +// `is_trivially_assignable`. +template +struct is_trivially_move_assignable + : std::conditional< + std::is_object::value && !std::is_array::value, + std::is_move_assignable>, + type_traits_internal::IsTriviallyMoveAssignableReference>::type:: + type { +#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE + private: + static constexpr bool compliant = + std::is_trivially_move_assignable::value == + is_trivially_move_assignable::value; + static_assert(compliant || std::is_trivially_move_assignable::value, + "Not compliant with std::is_trivially_move_assignable; " + "Standard: false, Implementation: true"); + static_assert(compliant || !std::is_trivially_move_assignable::value, + "Not compliant with std::is_trivially_move_assignable; " + "Standard: true, Implementation: false"); +#endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE +}; + // is_trivially_copy_assignable() // // Determines whether the passed type `T` is trivially copy assignable. diff --git a/absl/meta/type_traits_test.cc b/absl/meta/type_traits_test.cc index d3ead6d0..82b1be51 100644 --- a/absl/meta/type_traits_test.cc +++ b/absl/meta/type_traits_test.cc @@ -214,6 +214,29 @@ class DeletedDefaultCtor { int n_; }; +class TrivialMoveCtor { + public: + explicit TrivialMoveCtor(int n) : n_(n) {} + TrivialMoveCtor(TrivialMoveCtor&&) = default; + TrivialMoveCtor& operator=(const TrivialMoveCtor& t) { + n_ = t.n_; + return *this; + } + + private: + int n_; +}; + +class NontrivialMoveCtor { + public: + explicit NontrivialMoveCtor(int n) : n_(n) {} + NontrivialMoveCtor(NontrivialMoveCtor&& t) noexcept : n_(t.n_) {} + NontrivialMoveCtor& operator=(const NontrivialMoveCtor&) = default; + + private: + int n_; +}; + class TrivialCopyCtor { public: explicit TrivialCopyCtor(int n) : n_(n) {} @@ -247,6 +270,29 @@ class DeletedCopyCtor { int n_; }; +class TrivialMoveAssign { + public: + explicit TrivialMoveAssign(int n) : n_(n) {} + TrivialMoveAssign(const TrivialMoveAssign& t) : n_(t.n_) {} + TrivialMoveAssign& operator=(TrivialMoveAssign&&) = default; + ~TrivialMoveAssign() {} // can have nontrivial destructor + private: + int n_; +}; + +class NontrivialMoveAssign { + public: + explicit NontrivialMoveAssign(int n) : n_(n) {} + NontrivialMoveAssign(const NontrivialMoveAssign&) = default; + NontrivialMoveAssign& operator=(NontrivialMoveAssign&& t) noexcept { + n_ = t.n_; + return *this; + } + + private: + int n_; +}; + class TrivialCopyAssign { public: explicit TrivialCopyAssign(int n) : n_(n) {} @@ -484,6 +530,79 @@ TEST(TypeTraitsTest, TestTrivialDefaultCtor) { #endif } +TEST(TypeTraitsTest, TestTrivialMoveCtor) { + // Verify that arithmetic types and pointers have trivial move + // constructors. + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + + // Reference types + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + + // types with compiler generated move ctors + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + EXPECT_TRUE(absl::is_trivially_move_constructible::value); + + // Verify that types without them (i.e. nontrivial or deleted) are not. + EXPECT_FALSE( + absl::is_trivially_move_constructible::value); + EXPECT_FALSE(absl::is_trivially_move_constructible::value); + EXPECT_FALSE( + absl::is_trivially_move_constructible::value); + +#ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE + // type with nontrivial destructor are nontrivial move construbtible + EXPECT_FALSE( + absl::is_trivially_move_constructible::value); +#endif + + // types with vtables + EXPECT_FALSE(absl::is_trivially_move_constructible::value); + + // Verify that simple_pair of such types is trivially move constructible + EXPECT_TRUE( + (absl::is_trivially_move_constructible>::value)); + EXPECT_TRUE(( + absl::is_trivially_move_constructible>::value)); + EXPECT_TRUE((absl::is_trivially_move_constructible< + simple_pair>::value)); + + // Verify that types without trivial move constructors are + // correctly marked as such. + EXPECT_FALSE(absl::is_trivially_move_constructible::value); + EXPECT_FALSE(absl::is_trivially_move_constructible>::value); + + // Verify that simple_pairs of types without trivial move constructors + // are not marked as trivial. + EXPECT_FALSE((absl::is_trivially_move_constructible< + simple_pair>::value)); + EXPECT_FALSE((absl::is_trivially_move_constructible< + simple_pair>::value)); + + // Verify that arrays are not + using int10 = int[10]; + EXPECT_FALSE(absl::is_trivially_move_constructible::value); +} + TEST(TypeTraitsTest, TestTrivialCopyCtor) { // Verify that arithmetic types and pointers have trivial copy // constructors. @@ -508,6 +627,10 @@ TEST(TypeTraitsTest, TestTrivialCopyCtor) { EXPECT_TRUE(absl::is_trivially_copy_constructible::value); EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + // Reference types + EXPECT_TRUE(absl::is_trivially_copy_constructible::value); + EXPECT_FALSE(absl::is_trivially_copy_constructible::value); + // types with compiler generated copy ctors EXPECT_TRUE(absl::is_trivially_copy_constructible::value); EXPECT_TRUE(absl::is_trivially_copy_constructible::value); @@ -555,6 +678,74 @@ TEST(TypeTraitsTest, TestTrivialCopyCtor) { EXPECT_FALSE(absl::is_trivially_copy_constructible::value); } +TEST(TypeTraitsTest, TestTrivialMoveAssign) { + // Verify that arithmetic types and pointers have trivial move + // assignment operators. + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + + // const qualified types are not assignable + EXPECT_FALSE(absl::is_trivially_move_assignable::value); + + // types with compiler generated move assignment + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + + // Verify that types without them (i.e. nontrivial or deleted) are not. + EXPECT_FALSE(absl::is_trivially_move_assignable::value); + EXPECT_FALSE(absl::is_trivially_move_assignable::value); + EXPECT_FALSE(absl::is_trivially_move_assignable::value); + + // types with vtables + EXPECT_FALSE(absl::is_trivially_move_assignable::value); + + // Verify that simple_pair is trivially assignable + EXPECT_TRUE( + (absl::is_trivially_move_assignable>::value)); + EXPECT_TRUE( + (absl::is_trivially_move_assignable>::value)); + EXPECT_TRUE((absl::is_trivially_move_assignable< + simple_pair>::value)); + + // Verify that types not trivially move assignable are + // correctly marked as such. + EXPECT_FALSE(absl::is_trivially_move_assignable::value); + EXPECT_FALSE(absl::is_trivially_move_assignable>::value); + + // Verify that simple_pairs of types not trivially move assignable + // are not marked as trivial. + EXPECT_FALSE((absl::is_trivially_move_assignable< + simple_pair>::value)); + EXPECT_FALSE((absl::is_trivially_move_assignable< + simple_pair>::value)); + + // Verify that arrays are not trivially move assignable + using int10 = int[10]; + EXPECT_FALSE(absl::is_trivially_move_assignable::value); + + // Verify that references are handled correctly + EXPECT_TRUE(absl::is_trivially_move_assignable::value); + EXPECT_TRUE(absl::is_trivially_move_assignable::value); +} + TEST(TypeTraitsTest, TestTrivialCopyAssign) { // Verify that arithmetic types and pointers have trivial copy // assignment operators. diff --git a/absl/numeric/CMakeLists.txt b/absl/numeric/CMakeLists.txt index d26141c7..242889f0 100644 --- a/absl/numeric/CMakeLists.txt +++ b/absl/numeric/CMakeLists.txt @@ -52,6 +52,8 @@ absl_cc_test( absl_cc_library( NAME numeric + COPTS + ${ABSL_DEFAULT_COPTS} DEPS absl::int128 PUBLIC diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index d3393a39..8515ec2b 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -501,6 +501,8 @@ absl_cc_library( "internal/pow10_helper.h" SRCS "internal/pow10_helper.cc" + COPTS + ${ABSL_TEST_COPTS} TESTONLY ) diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc index bc8307e1..0d336e3f 100644 --- a/absl/strings/escaping.cc +++ b/absl/strings/escaping.cc @@ -1055,10 +1055,10 @@ std::string Utf8SafeCHexEscape(absl::string_view src) { } // ---------------------------------------------------------------------- -// ptrdiff_t Base64Unescape() - base64 decoder -// ptrdiff_t Base64Escape() - base64 encoder -// ptrdiff_t WebSafeBase64Unescape() - Google's variation of base64 decoder -// ptrdiff_t WebSafeBase64Escape() - Google's variation of base64 encoder +// Base64Unescape() - base64 decoder +// Base64Escape() - base64 encoder +// WebSafeBase64Unescape() - Google's variation of base64 decoder +// WebSafeBase64Escape() - Google's variation of base64 encoder // // Check out // http://tools.ietf.org/html/rfc2045 for formal description, but what we @@ -1096,6 +1096,20 @@ void WebSafeBase64Escape(absl::string_view src, std::string* dest) { src.size(), dest, false, kWebSafeBase64Chars); } +std::string Base64Escape(absl::string_view src) { + std::string dest; + Base64EscapeInternal(reinterpret_cast(src.data()), + src.size(), &dest, true, kBase64Chars); + return dest; +} + +std::string WebSafeBase64Escape(absl::string_view src) { + std::string dest; + Base64EscapeInternal(reinterpret_cast(src.data()), + src.size(), &dest, false, kWebSafeBase64Chars); + return dest; +} + std::string HexStringToBytes(absl::string_view from) { std::string result; const auto num = from.size() / 2; diff --git a/absl/strings/escaping.h b/absl/strings/escaping.h index fd9be786..198b9348 100644 --- a/absl/strings/escaping.h +++ b/absl/strings/escaping.h @@ -132,16 +132,18 @@ bool WebSafeBase64Unescape(absl::string_view src, std::string* dest); // Base64Escape() // -// Encodes a `src` string into a `dest` buffer using base64 encoding, with -// padding characters. This function conforms with RFC 4648 section 4 (base64). +// Encodes a `src` string into a base64-encoded string, with padding characters. +// This function conforms with RFC 4648 section 4 (base64). void Base64Escape(absl::string_view src, std::string* dest); +std::string Base64Escape(absl::string_view src); // WebSafeBase64Escape() // -// Encodes a `src` string into a `dest` buffer using '-' instead of '+' and -// '_' instead of '/', and without padding. This function conforms with RFC 4648 -// section 5 (base64url). +// Encodes a `src` string into a base64-like string, using '-' instead of '+' +// and '_' instead of '/', and without padding. This function conforms with RFC +// 4648 section 5 (base64url). void WebSafeBase64Escape(absl::string_view src, std::string* dest); +std::string WebSafeBase64Escape(absl::string_view src); // HexStringToBytes() // diff --git a/absl/strings/escaping_test.cc b/absl/strings/escaping_test.cc index d433b4c5..6a633cdc 100644 --- a/absl/strings/escaping_test.cc +++ b/absl/strings/escaping_test.cc @@ -556,6 +556,7 @@ void TestEscapeAndUnescape() { StringType encoded("this junk should be ignored"); absl::Base64Escape(tc.plaintext, &encoded); EXPECT_EQ(encoded, tc.cyphertext); + EXPECT_EQ(absl::Base64Escape(tc.plaintext), tc.cyphertext); StringType decoded("this junk should be ignored"); EXPECT_TRUE(absl::Base64Unescape(encoded, &decoded)); @@ -574,6 +575,7 @@ void TestEscapeAndUnescape() { encoded = "this junk should be ignored"; absl::WebSafeBase64Escape(tc.plaintext, &encoded); EXPECT_EQ(encoded, websafe); + EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), websafe); // Let's try the std::string version of the decoder decoded = "this junk should be ignored"; @@ -586,6 +588,7 @@ void TestEscapeAndUnescape() { StringType buffer; absl::WebSafeBase64Escape(tc.plaintext, &buffer); EXPECT_EQ(tc.cyphertext, buffer); + EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), tc.cyphertext); } // Verify the behavior when decoding bad data diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 99cc0afe..3b4d4b0c 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -32,7 +33,9 @@ std::string LengthModFor(long long) { return "ll"; } // NOLINT std::string LengthModFor(unsigned long long) { return "ll"; } // NOLINT std::string EscCharImpl(int v) { - if (isprint(v)) return std::string(1, static_cast(v)); + if (std::isprint(static_cast(v))) { + return std::string(1, static_cast(v)); + } char buf[64]; int n = snprintf(buf, sizeof(buf), "\\%#.2x", static_cast(v & 0xff)); @@ -155,7 +158,7 @@ TEST_F(FormatConvertTest, StringPrecision) { } TEST_F(FormatConvertTest, Pointer) { -#if _MSC_VER +#ifdef _MSC_VER // MSVC's printf implementation prints pointers differently. We can't easily // compare our implementation to theirs. return; @@ -390,7 +393,7 @@ TEST_F(FormatConvertTest, Uint128) { } TEST_F(FormatConvertTest, Float) { -#if _MSC_VER +#ifdef _MSC_VER // MSVC has a different rounding policy than us so we can't test our // implementation against the native one there. return; diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt index 9156f5ad..6fdbcb28 100644 --- a/absl/synchronization/CMakeLists.txt +++ b/absl/synchronization/CMakeLists.txt @@ -113,6 +113,8 @@ absl_cc_library( thread_pool HDRS "internal/thread_pool.h" + COPTS + ${ABSL_DEFAULT_COPTS} DEPS absl::synchronization absl::core_headers diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel index 05f56bca..b05c2347 100644 --- a/absl/time/internal/cctz/BUILD.bazel +++ b/absl/time/internal/cctz/BUILD.bazel @@ -16,6 +16,20 @@ package(features = ["-parse_headers"]) licenses(["notice"]) # Apache License +config_setting( + name = "osx", + constraint_values = [ + "@bazel_tools//platforms:osx", + ], +) + +config_setting( + name = "ios", + constraint_values = [ + "@bazel_tools//platforms:ios", + ], +) + ### libraries cc_library( @@ -62,6 +76,15 @@ cc_library( "include/cctz/time_zone.h", "include/cctz/zone_info_source.h", ], + linkopts = select({ + ":osx": [ + "-framework Foundation", + ], + ":ios": [ + "-framework Foundation", + ], + "//conditions:default": [], + }), visibility = ["//visibility:public"], deps = [":civil_time"], ) diff --git a/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/absl/time/internal/cctz/include/cctz/civil_time_detail.h index a5923f13..bb191b3f 100644 --- a/absl/time/internal/cctz/include/cctz/civil_time_detail.h +++ b/absl/time/internal/cctz/include/cctz/civil_time_detail.h @@ -21,7 +21,7 @@ #include // Disable constexpr support unless we are in C++14 mode. -#if __cpp_constexpr >= 201304 || _MSC_VER >= 1910 +#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) #define CONSTEXPR_D constexpr // data #define CONSTEXPR_F constexpr // function #define CONSTEXPR_M constexpr // member diff --git a/absl/time/internal/cctz/src/civil_time_test.cc b/absl/time/internal/cctz/src/civil_time_test.cc index e590ee30..dc7e5a1d 100644 --- a/absl/time/internal/cctz/src/civil_time_test.cc +++ b/absl/time/internal/cctz/src/civil_time_test.cc @@ -37,7 +37,7 @@ std::string Format(const T& t) { } // namespace -#if __cpp_constexpr >= 201304 || _MSC_VER >= 1910 +#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) // Construction constexpr tests TEST(CivilTime, Normal) { @@ -319,7 +319,7 @@ TEST(CivilTime, YearDay) { constexpr int yd = get_yearday(cd); static_assert(yd == 28, "YearDay"); } -#endif // __cpp_constexpr >= 201304 || _MSC_VER >= 1910 +#endif // __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910) // The remaining tests do not use constexpr. diff --git a/absl/time/internal/cctz/src/time_zone_lookup.cc b/absl/time/internal/cctz/src/time_zone_lookup.cc index a27bfc13..3c53dd1a 100644 --- a/absl/time/internal/cctz/src/time_zone_lookup.cc +++ b/absl/time/internal/cctz/src/time_zone_lookup.cc @@ -16,7 +16,7 @@ #if defined(__ANDROID__) #include -#if __ANDROID_API__ >= 21 +#if defined(__ANDROID_API__) && __ANDROID_API__ >= 21 #include #endif #endif @@ -37,7 +37,7 @@ namespace absl { namespace time_internal { namespace cctz { -#if defined(__ANDROID__) && __ANDROID_API__ >= 21 +#if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21 namespace { // Android 'L' removes __system_property_get() from the NDK, however // it is still a hidden symbol in libc so we use dlsym() to access it. diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc index 74148d58..4d791f4d 100644 --- a/absl/time/time_test.cc +++ b/absl/time/time_test.cc @@ -28,7 +28,7 @@ namespace { -#if GTEST_USES_SIMPLE_RE +#if defined(GTEST_USES_SIMPLE_RE) && GTEST_USES_SIMPLE_RE const char kZoneAbbrRE[] = ".*"; // just punt #else const char kZoneAbbrRE[] = "[A-Za-z]{3,4}|[-+][0-9]{2}([0-9]{2})?"; diff --git a/absl/types/any_test.cc b/absl/types/any_test.cc index a6351bf9..87104721 100644 --- a/absl/types/any_test.cc +++ b/absl/types/any_test.cc @@ -154,6 +154,14 @@ TEST(AnyTest, InPlaceConstruction) { EXPECT_EQ(5, v.value); } +TEST(AnyTest, InPlaceConstructionVariableTemplate) { + const CopyOnly copy_only{}; + absl::any o(absl::in_place_type, 5, MoveOnly(), + copy_only); + auto& v = absl::any_cast(o); + EXPECT_EQ(5, v.value); +} + TEST(AnyTest, InPlaceConstructionWithCV) { const CopyOnly copy_only{}; absl::any o(absl::in_place_type_t(), 5, @@ -162,12 +170,26 @@ TEST(AnyTest, InPlaceConstructionWithCV) { EXPECT_EQ(5, v.value); } +TEST(AnyTest, InPlaceConstructionWithCVVariableTemplate) { + const CopyOnly copy_only{}; + absl::any o(absl::in_place_type, 5, + MoveOnly(), copy_only); + auto& v = absl::any_cast(o); + EXPECT_EQ(5, v.value); +} + TEST(AnyTest, InPlaceConstructionWithFunction) { absl::any o(absl::in_place_type_t(), FunctionToEmplace); FunctionType*& construction_result = absl::any_cast(o); EXPECT_EQ(&FunctionToEmplace, construction_result); } +TEST(AnyTest, InPlaceConstructionWithFunctionVariableTemplate) { + absl::any o(absl::in_place_type, FunctionToEmplace); + auto& construction_result = absl::any_cast(o); + EXPECT_EQ(&FunctionToEmplace, construction_result); +} + TEST(AnyTest, InPlaceConstructionWithArray) { ArrayType ar = {5, 42}; absl::any o(absl::in_place_type_t(), ar); @@ -175,6 +197,13 @@ TEST(AnyTest, InPlaceConstructionWithArray) { EXPECT_EQ(&ar[0], construction_result); } +TEST(AnyTest, InPlaceConstructionWithArrayVariableTemplate) { + ArrayType ar = {5, 42}; + absl::any o(absl::in_place_type, ar); + auto& construction_result = absl::any_cast(o); + EXPECT_EQ(&ar[0], construction_result); +} + TEST(AnyTest, InPlaceConstructionIlist) { const CopyOnly copy_only{}; absl::any o(absl::in_place_type_t(), {1, 2, 3, 4}, @@ -184,6 +213,15 @@ TEST(AnyTest, InPlaceConstructionIlist) { EXPECT_EQ(expected_values, v.values); } +TEST(AnyTest, InPlaceConstructionIlistVariableTemplate) { + const CopyOnly copy_only{}; + absl::any o(absl::in_place_type, {1, 2, 3, 4}, + MoveOnly(), copy_only); + auto& v = absl::any_cast(o); + std::vector expected_values = {1, 2, 3, 4}; + EXPECT_EQ(expected_values, v.values); +} + TEST(AnyTest, InPlaceConstructionIlistWithCV) { const CopyOnly copy_only{}; absl::any o(absl::in_place_type_t(), @@ -193,11 +231,25 @@ TEST(AnyTest, InPlaceConstructionIlistWithCV) { EXPECT_EQ(expected_values, v.values); } +TEST(AnyTest, InPlaceConstructionIlistWithCVVariableTemplate) { + const CopyOnly copy_only{}; + absl::any o(absl::in_place_type, + {1, 2, 3, 4}, MoveOnly(), copy_only); + auto& v = absl::any_cast(o); + std::vector expected_values = {1, 2, 3, 4}; + EXPECT_EQ(expected_values, v.values); +} + TEST(AnyTest, InPlaceNoArgs) { absl::any o(absl::in_place_type_t{}); EXPECT_EQ(0, absl::any_cast(o)); } +TEST(AnyTest, InPlaceNoArgsVariableTemplate) { + absl::any o(absl::in_place_type); + EXPECT_EQ(0, absl::any_cast(o)); +} + template struct CanEmplaceAnyImpl : std::false_type {}; @@ -501,7 +553,7 @@ TEST(AnyTest, Copy) { InstanceTracker tracker_raii; { - absl::any o(absl::in_place_type_t{}, 123); + absl::any o(absl::in_place_type, 123); CopyableOnlyInstance* f1 = absl::any_cast(&o); absl::any o2(o); @@ -622,7 +674,7 @@ TEST(AnyTest, ThrowBadAlloc) { } { - absl::any a(absl::in_place_type_t{}); + absl::any a(absl::in_place_type); ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast(a)); ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast(a)); ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast(absl::any{})); @@ -665,7 +717,7 @@ TEST(AnyTest, FailedCopy) { } { - absl::any src(absl::in_place_type_t{}); + absl::any src(absl::in_place_type); ABSL_ANY_TEST_EXPECT_BAD_COPY(absl::any{src}); } @@ -677,21 +729,21 @@ TEST(AnyTest, FailedCopy) { { BadCopyable bad; - absl::any target(absl::in_place_type_t{}); + absl::any target(absl::in_place_type); ABSL_ANY_TEST_EXPECT_BAD_COPY(target = bad); EXPECT_TRUE(target.has_value()); } { - absl::any src(absl::in_place_type_t{}); + absl::any src(absl::in_place_type); absl::any target; ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src); EXPECT_FALSE(target.has_value()); } { - absl::any src(absl::in_place_type_t{}); - absl::any target(absl::in_place_type_t{}); + absl::any src(absl::in_place_type); + absl::any target(absl::in_place_type); ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src); EXPECT_TRUE(target.has_value()); } @@ -707,7 +759,7 @@ TEST(AnyTest, FailedEmplace) { { BadCopyable bad; - absl::any target(absl::in_place_type_t{}); + absl::any target(absl::in_place_type); ABSL_ANY_TEST_EXPECT_BAD_COPY(target.emplace(bad)); #if defined(ABSL_HAVE_STD_ANY) && defined(__GLIBCXX__) // libstdc++ std::any::emplace() implementation (as of 7.2) has a bug: if an diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc index ab40ed2a..b9c98118 100644 --- a/absl/types/variant_test.cc +++ b/absl/types/variant_test.cc @@ -384,7 +384,7 @@ struct MoveOnly { TEST(VariantTest, TestMoveConstruct) { using V = variant, MoveOnly, MoveOnly>; - V v(in_place_index_t<1>{}, 10); + V v(in_place_index<1>, 10); V v2 = absl::move(v); EXPECT_EQ(10, absl::get<1>(v2).value); } @@ -483,6 +483,29 @@ TEST(VariantTest, InPlaceType) { EXPECT_THAT(absl::get>(v5), ::testing::ElementsAre(1, 2, 3)); } +TEST(VariantTest, InPlaceTypeVariableTemplate) { + using Var = variant>; + + Var v1(in_place_type, 7); + ASSERT_TRUE(absl::holds_alternative(v1)); + EXPECT_EQ(7, absl::get(v1)); + + Var v2(in_place_type, "ABC"); + ASSERT_TRUE(absl::holds_alternative(v2)); + EXPECT_EQ("ABC", absl::get(v2)); + + Var v3(in_place_type, "ABC", 2); + ASSERT_TRUE(absl::holds_alternative(v3)); + EXPECT_EQ("AB", absl::get(v3)); + + Var v4(in_place_type); + ASSERT_TRUE(absl::holds_alternative(v4)); + + Var v5(in_place_type>, {1, 2, 3}); + ASSERT_TRUE(absl::holds_alternative>(v5)); + EXPECT_THAT(absl::get>(v5), ::testing::ElementsAre(1, 2, 3)); +} + TEST(VariantTest, InPlaceTypeInitializerList) { using Var = variant; @@ -492,6 +515,15 @@ TEST(VariantTest, InPlaceTypeInitializerList) { EXPECT_EQ(6, absl::get(v1).value); } +TEST(VariantTest, InPlaceTypeInitializerListVariabletemplate) { + using Var = + variant; + + Var v1(in_place_type, {1, 2, 3, 4, 5}, 6); + ASSERT_TRUE(absl::holds_alternative(v1)); + EXPECT_EQ(6, absl::get(v1).value); +} + TEST(VariantTest, InPlaceIndex) { using Var = variant>; @@ -519,6 +551,33 @@ TEST(VariantTest, InPlaceIndex) { EXPECT_THAT(absl::get>(v5), ::testing::ElementsAre(1, 2, 3)); } +TEST(VariantTest, InPlaceIndexVariableTemplate) { + using Var = variant>; + + Var v1(in_place_index<0>, 7); + ASSERT_TRUE(absl::holds_alternative(v1)); + EXPECT_EQ(7, absl::get(v1)); + + Var v2(in_place_index<1>, "ABC"); + ASSERT_TRUE(absl::holds_alternative(v2)); + EXPECT_EQ("ABC", absl::get(v2)); + + Var v3(in_place_index<1>, "ABC", 2); + ASSERT_TRUE(absl::holds_alternative(v3)); + EXPECT_EQ("AB", absl::get(v3)); + + Var v4(in_place_index<2>); + EXPECT_TRUE(absl::holds_alternative(v4)); + + // Verify that a variant with only non-copyables can still be constructed. + EXPECT_TRUE(absl::holds_alternative( + variant(in_place_index<0>))); + + Var v5(in_place_index<3>, {1, 2, 3}); + ASSERT_TRUE(absl::holds_alternative>(v5)); + EXPECT_THAT(absl::get>(v5), ::testing::ElementsAre(1, 2, 3)); +} + TEST(VariantTest, InPlaceIndexInitializerList) { using Var = variant; @@ -528,6 +587,15 @@ TEST(VariantTest, InPlaceIndexInitializerList) { EXPECT_EQ(6, absl::get(v1).value); } +TEST(VariantTest, InPlaceIndexInitializerListVariableTemplate) { + using Var = + variant; + + Var v1(in_place_index<3>, {1, 2, 3, 4, 5}, 6); + ASSERT_TRUE(absl::holds_alternative(v1)); + EXPECT_EQ(6, absl::get(v1).value); +} + //////////////////// // [variant.dtor] // //////////////////// @@ -576,7 +644,7 @@ TEST(VariantTest, TestDtorValuelessByException) { using Variant = VariantFactory::Type; - Variant v(in_place_index_t<0>(), counter_adjuster); + Variant v(in_place_index<0>, counter_adjuster); EXPECT_EQ(0, counter); ToValuelessByException(v); @@ -810,7 +878,7 @@ TEST(VariantTest, TestBackupAssign) { TEST(VariantTest, TestEmplaceBasic) { using Variant = variant; - Variant v(absl::in_place_index_t<0>{}, 0); + Variant v(absl::in_place_index<0>, 0); { char& emplace_result = v.emplace(); @@ -837,7 +905,7 @@ TEST(VariantTest, TestEmplaceInitializerList) { using Var = variant; - Var v1(absl::in_place_index_t<0>{}, 555); + Var v1(absl::in_place_index<0>, 555); MoveOnlyWithListConstructor& emplace_result = v1.emplace({1, 2, 3, 4, 5}, 6); ASSERT_TRUE(absl::holds_alternative(v1)); @@ -848,7 +916,7 @@ TEST(VariantTest, TestEmplaceInitializerList) { TEST(VariantTest, TestEmplaceIndex) { using Variant = variant; - Variant v(absl::in_place_index_t<0>{}, 555); + Variant v(absl::in_place_index<0>, 555); { char& emplace_result = v.emplace<1>(); @@ -875,7 +943,7 @@ TEST(VariantTest, TestEmplaceIndexInitializerList) { using Var = variant; - Var v1(absl::in_place_index_t<0>{}, 555); + Var v1(absl::in_place_index<0>, 555); MoveOnlyWithListConstructor& emplace_result = v1.emplace<3>({1, 2, 3, 4, 5}, 6); ASSERT_TRUE(absl::holds_alternative(v1)); @@ -924,7 +992,7 @@ TEST(VariantTest, NotValuelessByException) { TEST(VariantTest, IndexValuelessByException) { using Var = variant; - Var v(absl::in_place_index_t<0>{}); + Var v(absl::in_place_index<0>); EXPECT_EQ(0, v.index()); ToValuelessByException(v); EXPECT_EQ(absl::variant_npos, v.index()); @@ -935,7 +1003,7 @@ TEST(VariantTest, IndexValuelessByException) { TEST(VariantTest, ValuelessByException) { using Var = variant; - Var v(absl::in_place_index_t<0>{}); + Var v(absl::in_place_index<0>); EXPECT_FALSE(v.valueless_by_exception()); ToValuelessByException(v); EXPECT_TRUE(v.valueless_by_exception()); @@ -966,7 +1034,7 @@ TEST(VariantTest, MemberSwap) { using V = variant; int i = 33; std::string s = "abc"; - V valueless(in_place_index_t<0>{}); + V valueless(in_place_index<0>); ToValuelessByException(valueless); { // lhs and rhs holds different alternative @@ -1127,7 +1195,7 @@ TEST(VariantTest, GetIndex) { using Var = variant; { - Var v(absl::in_place_index_t<0>{}, 0); + Var v(absl::in_place_index<0>, 0); using LValueGetType = decltype(absl::get<0>(v)); using RValueGetType = decltype(absl::get<0>(absl::move(v))); @@ -1187,7 +1255,7 @@ TEST(VariantTest, GetIndex) { } { - Var v(absl::in_place_index_t<0>{}, 0); + Var v(absl::in_place_index<0>, 0); v.emplace<3>(1); using LValueGetType = decltype(absl::get<3>(v)); @@ -1334,7 +1402,7 @@ TEST(VariantTest, GetIfIndex) { using Var = variant; { - Var v(absl::in_place_index_t<0>{}, 0); + Var v(absl::in_place_index<0>, 0); EXPECT_TRUE(noexcept(absl::get_if<0>(&v))); { @@ -1492,7 +1560,7 @@ TEST(VariantTest, GetIfIndex) { } { - Var v(absl::in_place_index_t<0>{}, 0); + Var v(absl::in_place_index<0>, 0); v.emplace<3>(1); EXPECT_TRUE(noexcept(absl::get_if<3>(&v))); @@ -1638,8 +1706,8 @@ TEST(VariantTest, OperatorRelational) { TEST(VariantTest, ValuelessOperatorEquals) { variant int_v(1), string_v("Hello"), - valueless(absl::in_place_index_t<0>{}), - other_valueless(absl::in_place_index_t<0>{}); + valueless(absl::in_place_index<0>), + other_valueless(absl::in_place_index<0>); ToValuelessByException(valueless); ToValuelessByException(other_valueless); @@ -1660,8 +1728,8 @@ TEST(VariantTest, ValuelessOperatorEquals) { TEST(VariantTest, ValuelessOperatorRelational) { variant int_v(1), string_v("Hello"), - valueless(absl::in_place_index_t<0>{}), - other_valueless(absl::in_place_index_t<0>{}); + valueless(absl::in_place_index<0>), + other_valueless(absl::in_place_index<0>); ToValuelessByException(valueless); ToValuelessByException(other_valueless); @@ -2008,8 +2076,8 @@ TEST(VariantTest, Hash) { #if !(defined(_MSC_VER) && defined(ABSL_HAVE_STD_VARIANT)) { // same value as different alternative - variant v0(in_place_index_t<0>{}, 42); - variant v1(in_place_index_t<1>{}, 42); + variant v0(in_place_index<0>, 42); + variant v1(in_place_index<1>, 42); std::hash> hash; EXPECT_NE(hash(v0), hash(v1)); } @@ -2605,7 +2673,7 @@ TEST(VariantTest, MoveCtorBug) { }; { using V = absl::variant; - V v1(absl::in_place_index_t<0>{}); + V v1(absl::in_place_index<0>); // this should invoke the move ctor, rather than the trivial copy ctor. V v2(std::move(v1)); EXPECT_TRUE(absl::get<0>(v2).called); @@ -2613,7 +2681,7 @@ TEST(VariantTest, MoveCtorBug) { { // this case failed to compile before our fix due to a GCC bug. using V = absl::variant; - V v1(absl::in_place_index_t<1>{}); + V v1(absl::in_place_index<1>); // this should invoke the move ctor, rather than the trivial copy ctor. V v2(std::move(v1)); EXPECT_TRUE(absl::get<1>(v2).called); diff --git a/absl/utility/utility.h b/absl/utility/utility.h index 853c1fb8..7686db12 100644 --- a/absl/utility/utility.h +++ b/absl/utility/utility.h @@ -113,6 +113,20 @@ struct Gen { using type = integer_sequence; }; +template +struct InPlaceTypeTag { + explicit InPlaceTypeTag() = delete; + InPlaceTypeTag(const InPlaceTypeTag&) = delete; + InPlaceTypeTag& operator=(const InPlaceTypeTag&) = delete; +}; + +template +struct InPlaceIndexTag { + explicit InPlaceIndexTag() = delete; + InPlaceIndexTag(const InPlaceIndexTag&) = delete; + InPlaceIndexTag& operator=(const InPlaceIndexTag&) = delete; +}; + } // namespace utility_internal // Compile-time sequences of integers @@ -162,6 +176,7 @@ ABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {}); #endif // ABSL_HAVE_STD_OPTIONAL #if defined(ABSL_HAVE_STD_ANY) || defined(ABSL_HAVE_STD_VARIANT) +using std::in_place_type; using std::in_place_type_t; #else @@ -171,10 +186,14 @@ using std::in_place_type_t; // be specified, such as with `absl::any`, designed to be a drop-in replacement // for C++17's `std::in_place_type_t`. template -struct in_place_type_t {}; +using in_place_type_t = void (*)(utility_internal::InPlaceTypeTag); + +template +void in_place_type(utility_internal::InPlaceTypeTag) {} #endif // ABSL_HAVE_STD_ANY || ABSL_HAVE_STD_VARIANT #ifdef ABSL_HAVE_STD_VARIANT +using std::in_place_index; using std::in_place_index_t; #else @@ -184,7 +203,10 @@ using std::in_place_index_t; // be specified, such as with `absl::any`, designed to be a drop-in replacement // for C++17's `std::in_place_index_t`. template -struct in_place_index_t {}; +using in_place_index_t = void (*)(utility_internal::InPlaceIndexTag); + +template +void in_place_index(utility_internal::InPlaceIndexTag) {} #endif // ABSL_HAVE_STD_VARIANT // Constexpr move and forward -- cgit v1.2.3 From 8a394b19c149cab50534b04c5e21d42bc2217a7d Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Fri, 17 May 2019 10:51:37 -0700 Subject: Export of internal Abseil changes. -- cae9f0c87632d690ec3f471e181be247fe4fb025 by Abseil Team : Run IWYU on some headers. PiperOrigin-RevId: 248749194 -- f57dcac97cacbe31769a8646020a99b6686987dc by Samuel Benzaquen : Accept vector::reference in StrFormat and friends. The proxy types might overload `operator&`. Use std::addressof instead. PiperOrigin-RevId: 248619661 GitOrigin-RevId: cae9f0c87632d690ec3f471e181be247fe4fb025 Change-Id: Iacf5d46a59d1d5f1fa1fd4a1e0d0de8c6cbedb3e --- absl/base/call_once.h | 2 ++ absl/base/casts.h | 1 + absl/base/internal/low_level_alloc.h | 1 + absl/base/internal/spinlock.h | 1 + absl/base/macros.h | 1 + absl/strings/internal/str_format/arg.h | 3 ++- absl/strings/internal/str_format/convert_test.cc | 11 +++++++++++ 7 files changed, 19 insertions(+), 1 deletion(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/base/call_once.h b/absl/base/call_once.h index 8c4f297c..e7fc2300 100644 --- a/absl/base/call_once.h +++ b/absl/base/call_once.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "absl/base/internal/invoke.h" #include "absl/base/internal/low_level_scheduling.h" @@ -36,6 +37,7 @@ #include "absl/base/internal/scheduling_mode.h" #include "absl/base/internal/spinlock_wait.h" #include "absl/base/macros.h" +#include "absl/base/optimization.h" #include "absl/base/port.h" namespace absl { diff --git a/absl/base/casts.h b/absl/base/casts.h index a381c427..aba01782 100644 --- a/absl/base/casts.h +++ b/absl/base/casts.h @@ -27,6 +27,7 @@ #include #include #include +#include #include "absl/base/internal/identity.h" #include "absl/base/macros.h" diff --git a/absl/base/internal/low_level_alloc.h b/absl/base/internal/low_level_alloc.h index b35673de..c98cdb30 100644 --- a/absl/base/internal/low_level_alloc.h +++ b/absl/base/internal/low_level_alloc.h @@ -25,6 +25,7 @@ // IWYU pragma: private, include "base/low_level_alloc.h" #include + #include #include "absl/base/attributes.h" diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h index 940f56af..a55aa20b 100644 --- a/absl/base/internal/spinlock.h +++ b/absl/base/internal/spinlock.h @@ -32,6 +32,7 @@ #include #include + #include #include "absl/base/attributes.h" diff --git a/absl/base/macros.h b/absl/base/macros.h index ca620792..606a90ac 100644 --- a/absl/base/macros.h +++ b/absl/base/macros.h @@ -31,6 +31,7 @@ #include #include +#include "absl/base/optimization.h" #include "absl/base/port.h" // ABSL_ARRAYSIZE() diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index 4d48af06..5cb3a14d 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -292,7 +293,7 @@ class FormatArgImpl { struct Manager { static Data SetValue(const T& value) { Data data; - data.ptr = &value; + data.ptr = std::addressof(value); return data; } diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 3b4d4b0c..814ccf4c 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -367,6 +367,17 @@ typedef ::testing::Types< INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes, TypedFormatConvertTest, AllIntTypes); +TEST_F(FormatConvertTest, VectorBool) { + // Make sure vector's values behave as bools. + std::vector v = {true, false}; + const std::vector cv = {true, false}; + EXPECT_EQ("1,0,1,0", + FormatPack(UntypedFormatSpecImpl("%d,%d,%d,%d"), + absl::Span( + {FormatArgImpl(v[0]), FormatArgImpl(v[1]), + FormatArgImpl(cv[0]), FormatArgImpl(cv[1])}))); +} + TEST_F(FormatConvertTest, Uint128) { absl::uint128 v = static_cast(0x1234567890abcdef) * 1979; absl::uint128 max = absl::Uint128Max(); -- cgit v1.2.3 From ab3552a18964e7063c8324f45b3896a6a20b08a8 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 15 Oct 2019 18:18:40 -0700 Subject: Export of internal Abseil changes -- f13697e3d33803f9667d124072da4f6dd8bfbf85 by Andy Soffer : Addressing https://github.com/abseil/abseil-cpp/issues/314, fixing CMakeLists.txt to reference ABSL_TEST_COPTS rather than ABSL_DEFAULT_COPTS. ABSL_TEST_COPTS should be preferred for all tests so that they are configured consistently (moreover, CMake should agree with Bazel). PiperOrigin-RevId: 274932312 -- c31c24a1fa6bb98136adf51ef37c0818ac366690 by Derek Mauro : Silence MSAN in the stack consumption test utility PiperOrigin-RevId: 274912950 -- 2412913c05a246cd527cd4c31452f126e9129f3a by CJ Johnson : Internal change PiperOrigin-RevId: 274847103 -- 75e984a93b5760873501b96ac3229ccfd955daf8 by Abseil Team : Reformat BUILD file to current standards. PiperOrigin-RevId: 274815392 -- a2780e085f1df1e4ca2c814a58c893d1b78a1d9c by Samuel Benzaquen : Fix invalid result regarding leading zeros in the exponent. PiperOrigin-RevId: 274808017 -- dd402e1cb5c4ebacb576372ae24bf289d729d323 by Samuel Benzaquen : Make string_view's relational operators constexpr when possible. PiperOrigin-RevId: 274807873 -- b4ef32565653a5da1cb8bb8d0351586d23519658 by Abseil Team : Internal rework. PiperOrigin-RevId: 274787159 -- 70d81971c5914e6785b8e8a9d4f6eb2655dd62c0 by Gennadiy Rozental : Internal rework. PiperOrigin-RevId: 274715557 -- 14f5b0440e353b899cafaaa15b53e77f98f401af by Gennadiy Rozental : Make deprecated statements about ParseFLag/UnparseFlag consistent in a file. PiperOrigin-RevId: 274668123 -- 2e85adbdbb92612e4d750bc34fbca3333128b42d by Abseil Team : Allow absl::c_equal to be used with arrays. This is achieved by allowing container size computation for arrays. PiperOrigin-RevId: 274426830 -- 219719f107226d328773e6cec99fb473f5d3119c by Gennadiy Rozental : Release correct extension interfaces to support usage of absl::Time and absl::Duration as ABSL_FLAG PiperOrigin-RevId: 274273788 -- 47a77f93fda23b69b4a6bdbd506fe643c69a5579 by Gennadiy Rozental : Rework of flags persistence/FlagSaver internals. PiperOrigin-RevId: 274225213 -- 7807be3fe757c19e3b0c487298387683d4c9f5b3 by Abseil Team : Switch reference to sdkddkver.h to lowercase, matching conventions used in the Windows SDK and other uses. This helps to avoid confusion on case-sensitive filesystems. PiperOrigin-RevId: 274061877 -- 561304090087a19f1d10f0475f564fe132ebf06e by Andy Getzendanner : Fix ABSL_WAITER_MODE detection for mingw Import of https://github.com/abseil/abseil-cpp/pull/342 PiperOrigin-RevId: 274030071 -- 9b3caac2cf202b9d440dfa1b4ffd538ac4bf715b by Derek Mauro : Support using Abseil with the musl libc implementation. Only test changes were required: * Workaround for a bug in sigaltstack() on musl * printf-style pointer formatting (%p) is implementation defined, so verify StrFromat produces something compatible * Fix detection of feenableexcept() PiperOrigin-RevId: 274011666 -- 73e8a938fc139e1cc8670d4513a445bacc855539 by Abseil Team : nvcc workaround: explicitly specify the definition of node_handle::Base PiperOrigin-RevId: 274011392 -- ab9cc6d042aca7d48e16c504ab10eab39433f4b2 by Andy Soffer : Internal change PiperOrigin-RevId: 273996318 -- e567c4979ca99c7e71821ec1523b8f5edd2c76ac by Abseil Team : Introduce a type alias to work around an nvcc bug. On the previous code, nvcc gets confused thinking that T has to be a parameter pack, as IsDecomposable accepts one. PiperOrigin-RevId: 273980472 -- 105b6e6339b77a32f4432de05f44cd3f9c436751 by Eric Fiselier : Import of CCTZ from GitHub. PiperOrigin-RevId: 273955589 -- 8feb87ff1d7e721fe094855e67c19539d5e582b7 by Abseil Team : Avoid dual-exporting scheduling_mode.h PiperOrigin-RevId: 273825112 -- fbc37854776d295dae98fb9d06a541f296daab95 by Andy Getzendanner : Fix ABSL_HAVE_ALARM check on mingw Import of https://github.com/abseil/abseil-cpp/pull/341 PiperOrigin-RevId: 273817839 -- 6aedcd63a735b9133e143b043744ba0a25407f6f by Andy Soffer : Remove bit_gen_view.h now that all callers have been migrated to bit_gen_ref.h Tested: TGP - https://test.corp.google.com/ui#id=OCL:273762409:BASE:273743370:1570639020744:3001bcb5 PiperOrigin-RevId: 273810331 -- 6573de24a66ba715c579f7f32b5c48a1d743c7f8 by Abseil Team : Internal change. PiperOrigin-RevId: 273589963 -- 91c8c28b6dca26d98b39e8e06a8ed17c701ff793 by Abseil Team : Update macro name for `ABSL_GUARDED_BY()` in the example section. PiperOrigin-RevId: 273286983 -- 0ff7d1a93d70f8ecd693f8dbb98b7a4a016ca2a4 by Abseil Team : Fix potential integer overflow in the absl time library. In absl::FromTM, the tm.tm_year is added by 1900 regarding that tm.tm_year represents the years since 1900. This change checks integer overflow before doing the arithmetic operation. PiperOrigin-RevId: 273092952 -- b41c2a1310086807be09a833099ae6d4009f037c by Gennadiy Rozental : Correctly Unlock the global mutex in case of concurrent flag initialization. Fixes #386 PiperOrigin-RevId: 272979749 -- c53103e71b2a6063af3c6d4ff68aa2d8f9ae9e06 by Abseil Team : Try to become idle only when there is no wakeup. Immediately after waking up (when futex wait returns), the current thread tries to become idle doing bunch of memory loads and a branch. Problem is that there is a good chance that we woke up due to a wakeup, especially for actively used threads. For such wakeups, calling MaybeBecomeIdle() would be a waste of cycles. Instead, call MaybeBecomeIdle() only when we are sure there is no wakeup. For idle threads the net effect should be the same. For active, threads this will be more efficient. Moreover, since MaybeBecomeIdle() is called before waiting on the futex, the current thread will try to become idle before sleeping. This should result in more accurate idleness and more efficient release of thread resources. PiperOrigin-RevId: 272940381 GitOrigin-RevId: f13697e3d33803f9667d124072da4f6dd8bfbf85 Change-Id: I36de05aec12595183725652dd362dfa58fb095d0 --- absl/BUILD.bazel | 7 +- absl/algorithm/container.h | 18 +++- absl/algorithm/container_test.cc | 6 ++ absl/base/BUILD.bazel | 16 +-- absl/base/CMakeLists.txt | 9 +- absl/base/attributes.h | 1 - .../inlined_vector_exception_safety_test.cc | 4 +- absl/container/internal/common.h | 4 +- absl/container/internal/raw_hash_set.h | 11 ++- absl/copts/configure_copts.bzl | 2 + absl/debugging/CMakeLists.txt | 2 +- absl/debugging/internal/stack_consumption.cc | 12 ++- absl/flags/BUILD.bazel | 3 + absl/flags/flag.cc | 4 +- absl/flags/flag.h | 8 +- absl/flags/internal/commandlineflag.cc | 6 ++ absl/flags/internal/commandlineflag.h | 24 +++-- absl/flags/internal/flag.h | 85 ++++++++++++++-- absl/flags/internal/registry.cc | 106 +++----------------- absl/random/BUILD.bazel | 2 +- absl/random/distribution_format_traits.h | 22 +---- absl/random/distributions.h | 56 ++++++++--- absl/random/internal/distributions.h | 30 ------ absl/random/internal/uniform_helper.h | 12 ++- absl/strings/BUILD.bazel | 1 + absl/strings/CMakeLists.txt | 1 + absl/strings/charconv_test.cc | 7 ++ absl/strings/internal/charconv_parse.cc | 6 ++ absl/strings/internal/str_format/convert_test.cc | 110 +++++++++++++-------- absl/strings/numbers_test.cc | 14 +-- absl/strings/string_view.h | 62 +++++++----- absl/strings/string_view_test.cc | 23 +++++ absl/synchronization/internal/waiter.cc | 27 +++-- absl/synchronization/internal/waiter.h | 2 +- absl/synchronization/mutex.h | 2 +- absl/time/duration.cc | 5 + absl/time/format.cc | 8 ++ absl/time/internal/cctz/src/time_zone_impl.cc | 11 ++- absl/time/time.cc | 14 ++- absl/time/time.h | 9 ++ absl/time/time_test.cc | 24 +++++ 41 files changed, 485 insertions(+), 291 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel index 853330d4..5a03acf8 100644 --- a/absl/BUILD.bazel +++ b/absl/BUILD.bazel @@ -14,12 +14,15 @@ # limitations under the License. # +load( + ":compiler_config_setting.bzl", + "create_llvm_config", +) + package(default_visibility = ["//visibility:public"]) licenses(["notice"]) # Apache 2.0 -load(":compiler_config_setting.bzl", "create_llvm_config") - create_llvm_config( name = "llvm_compiler", visibility = [":__subpackages__"], diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h index c84de461..adcea8a7 100644 --- a/absl/algorithm/container.h +++ b/absl/algorithm/container.h @@ -112,6 +112,18 @@ template struct IsUnorderedContainer> : std::true_type {}; +// container_algorithm_internal::c_size. It is meant for internal use only. + +template +auto c_size(C& c) -> decltype(c.size()) { + return c.size(); +} + +template +constexpr std::size_t c_size(T (&)[N]) { + return N; +} + } // namespace container_algorithm_internal // PUBLIC API @@ -365,7 +377,8 @@ c_mismatch(C1& c1, C2& c2, BinaryPredicate&& pred) { template bool c_equal(const C1& c1, const C2& c2) { - return ((c1.size() == c2.size()) && + return ((container_algorithm_internal::c_size(c1) == + container_algorithm_internal::c_size(c2)) && std::equal(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2))); @@ -375,7 +388,8 @@ bool c_equal(const C1& c1, const C2& c2) { // the function's test condition. template bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) { - return ((c1.size() == c2.size()) && + return ((container_algorithm_internal::c_size(c1) == + container_algorithm_internal::c_size(c2)) && std::equal(container_algorithm_internal::c_begin(c1), container_algorithm_internal::c_end(c1), container_algorithm_internal::c_begin(c2), diff --git a/absl/algorithm/container_test.cc b/absl/algorithm/container_test.cc index 86bf9d3e..0a4abe94 100644 --- a/absl/algorithm/container_test.cc +++ b/absl/algorithm/container_test.cc @@ -163,23 +163,29 @@ TEST_F(NonMutatingTest, MismatchWithPredicate) { TEST_F(NonMutatingTest, Equal) { EXPECT_TRUE(absl::c_equal(vector_, sequence_)); EXPECT_TRUE(absl::c_equal(sequence_, vector_)); + EXPECT_TRUE(absl::c_equal(sequence_, array_)); + EXPECT_TRUE(absl::c_equal(array_, vector_)); // Test that behavior appropriately differs from that of equal(). std::vector vector_plus = {1, 2, 3}; vector_plus.push_back(4); EXPECT_FALSE(absl::c_equal(vector_plus, sequence_)); EXPECT_FALSE(absl::c_equal(sequence_, vector_plus)); + EXPECT_FALSE(absl::c_equal(array_, vector_plus)); } TEST_F(NonMutatingTest, EqualWithPredicate) { EXPECT_TRUE(absl::c_equal(vector_, sequence_, Equals)); EXPECT_TRUE(absl::c_equal(sequence_, vector_, Equals)); + EXPECT_TRUE(absl::c_equal(array_, sequence_, Equals)); + EXPECT_TRUE(absl::c_equal(vector_, array_, Equals)); // Test that behavior appropriately differs from that of equal(). std::vector vector_plus = {1, 2, 3}; vector_plus.push_back(4); EXPECT_FALSE(absl::c_equal(vector_plus, sequence_, Equals)); EXPECT_FALSE(absl::c_equal(sequence_, vector_plus, Equals)); + EXPECT_FALSE(absl::c_equal(vector_plus, array_, Equals)); } TEST_F(NonMutatingTest, IsPermutation) { diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 1e1f0d2d..d74bac63 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -71,16 +71,16 @@ cc_library( "internal/spinlock_wait.cc", "internal/spinlock_win32.inc", ], - hdrs = [ - "internal/scheduling_mode.h", - "internal/spinlock_wait.h", - ], + hdrs = ["internal/spinlock_wait.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = [ "//absl/base:__pkg__", ], - deps = [":core_headers"], + deps = [ + ":base_internal", + ":core_headers", + ], ) cc_library( @@ -141,11 +141,11 @@ cc_library( ], deps = [ ":base", + ":base_internal", ":config", ":core_headers", ":dynamic_annotations", ":raw_logging_internal", - ":spinlock_wait", ], ) @@ -369,8 +369,8 @@ cc_library( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":base", + ":base_internal", ":core_headers", - ":spinlock_wait", "//absl/synchronization", "@com_google_googletest//:gtest", ], @@ -385,8 +385,8 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":base", + ":base_internal", ":core_headers", - ":spinlock_wait", "//absl/synchronization", "@com_google_googletest//:gtest_main", ], diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 51705a5a..79ee5b93 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -56,7 +56,6 @@ absl_cc_library( NAME spinlock_wait HDRS - "internal/scheduling_mode.h" "internal/spinlock_wait.h" SRCS "internal/spinlock_akaros.inc" @@ -67,6 +66,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::base_internal absl::core_headers ) @@ -125,11 +125,11 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} DEPS absl::base + absl::base_internal absl::config absl::core_headers absl::dynamic_annotations absl::raw_logging_internal - absl::spinlock_wait Threads::Threads ) @@ -141,6 +141,7 @@ absl_cc_library( "internal/identity.h" "internal/inline_variable.h" "internal/invoke.h" + "internal/scheduling_mode.h" COPTS ${ABSL_DEFAULT_COPTS} DEPS @@ -348,8 +349,8 @@ absl_cc_library( ${ABSL_TEST_COPTS} DEPS absl::base + absl::base_internal absl::core_headers - absl::spinlock_wait absl::synchronization gtest TESTONLY @@ -365,8 +366,8 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::base + absl::base_internal absl::core_headers - absl::spinlock_wait absl::synchronization gtest_main ) diff --git a/absl/base/attributes.h b/absl/base/attributes.h index f298297e..7b7656a8 100644 --- a/absl/base/attributes.h +++ b/absl/base/attributes.h @@ -599,7 +599,6 @@ // // Note that this attribute is redundant if the variable is declared constexpr. #if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) -// NOLINTNEXTLINE(whitespace/braces) #define ABSL_CONST_INIT [[clang::require_constant_initialization]] #else #define ABSL_CONST_INIT diff --git a/absl/container/inlined_vector_exception_safety_test.cc b/absl/container/inlined_vector_exception_safety_test.cc index 25994f16..937e43a5 100644 --- a/absl/container/inlined_vector_exception_safety_test.cc +++ b/absl/container/inlined_vector_exception_safety_test.cc @@ -16,7 +16,7 @@ #include "absl/base/config.h" -#ifdef ABSL_HAVE_EXCEPTIONS +#if defined(ABSL_HAVE_EXCEPTIONS) #include #include @@ -493,4 +493,4 @@ TYPED_TEST(TwoSizeTest, Swap) { } // namespace -#endif // ABSL_HAVE_EXCEPTIONS +#endif // defined(ABSL_HAVE_EXCEPTIONS) diff --git a/absl/container/internal/common.h b/absl/container/internal/common.h index 591d3ea1..4bd5d469 100644 --- a/absl/container/internal/common.h +++ b/absl/container/internal/common.h @@ -117,7 +117,7 @@ class node_handle_base { template class node_handle : public node_handle_base { - using Base = typename node_handle::node_handle_base; + using Base = node_handle_base; public: using value_type = typename PolicyTraits::value_type; @@ -137,7 +137,7 @@ template class node_handle> : public node_handle_base { - using Base = typename node_handle::node_handle_base; + using Base = node_handle_base; public: using key_type = typename Policy::key_type; diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 2e6f4dd3..42b3c468 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -938,8 +938,11 @@ class raw_hash_set { // // flat_hash_map m; // m.insert(std::make_pair("abc", 42)); + // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc + // bug. template = 0, - typename std::enable_if::value, int>::type = 0, + class T2 = T, + typename std::enable_if::value, int>::type = 0, T* = nullptr> std::pair insert(T&& value) { return emplace(std::forward(value)); @@ -975,8 +978,10 @@ class raw_hash_set { return emplace(std::move(value)); } - template = 0, - typename std::enable_if::value, int>::type = 0, + // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc + // bug. + template = 0, class T2 = T, + typename std::enable_if::value, int>::type = 0, T* = nullptr> iterator insert(const_iterator, T&& value) { return insert(std::forward(value)).first; diff --git a/absl/copts/configure_copts.bzl b/absl/copts/configure_copts.bzl index 2829e4ec..9dd6bd0a 100644 --- a/absl/copts/configure_copts.bzl +++ b/absl/copts/configure_copts.bzl @@ -6,6 +6,8 @@ change Abseil copts, edit absl/copts/copts.py load( "//absl:copts/GENERATED_copts.bzl", + "ABSL_CLANG_CL_FLAGS", + "ABSL_CLANG_CL_TEST_FLAGS", "ABSL_GCC_FLAGS", "ABSL_GCC_TEST_FLAGS", "ABSL_LLVM_FLAGS", diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt index c409e33e..81492c0c 100644 --- a/absl/debugging/CMakeLists.txt +++ b/absl/debugging/CMakeLists.txt @@ -238,7 +238,7 @@ absl_cc_test( SRCS "leak_check_test.cc" COPTS - ${ABSL_DEFAULT_COPTS} + ${ABSL_TEST_COPTS} "$<$:-DABSL_EXPECT_LEAK_SANITIZER>" LINKOPTS "${ABSL_LSAN_LINKOPTS}" diff --git a/absl/debugging/internal/stack_consumption.cc b/absl/debugging/internal/stack_consumption.cc index 4b05f495..d4703264 100644 --- a/absl/debugging/internal/stack_consumption.cc +++ b/absl/debugging/internal/stack_consumption.cc @@ -115,10 +115,11 @@ int GetSignalHandlerStackConsumption(void (*signal_handler)(int)) { // Set up the alt-signal-stack (and save the older one). stack_t sigstk; memset(&sigstk, 0, sizeof(sigstk)); - stack_t old_sigstk; sigstk.ss_sp = altstack; sigstk.ss_size = kAlternateStackSize; sigstk.ss_flags = 0; + stack_t old_sigstk; + memset(&old_sigstk, 0, sizeof(old_sigstk)); ABSL_RAW_CHECK(sigaltstack(&sigstk, &old_sigstk) == 0, "sigaltstack() failed"); @@ -152,6 +153,15 @@ int GetSignalHandlerStackConsumption(void (*signal_handler)(int)) { int signal_handler_stack_consumption = GetStackConsumption(altstack); // Now restore the old alt-signal-stack and signal handlers. + if (old_sigstk.ss_sp == nullptr && old_sigstk.ss_size == 0 && + (old_sigstk.ss_flags & SS_DISABLE)) { + // https://git.musl-libc.org/cgit/musl/commit/src/signal/sigaltstack.c?id=7829f42a2c8944555439380498ab8b924d0f2070 + // The original stack has ss_size==0 and ss_flags==SS_DISABLE, but some + // versions of musl have a bug that rejects ss_size==0. Work around this by + // setting ss_size to MINSIGSTKSZ, which should be ignored by the kernel + // when SS_DISABLE is set. + old_sigstk.ss_size = MINSIGSTKSZ; + } ABSL_RAW_CHECK(sigaltstack(&old_sigstk, nullptr) == 0, "sigaltstack() failed"); ABSL_RAW_CHECK(sigaction(SIGUSR1, &old_sa1, nullptr) == 0, diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index 2bf562f8..2e0dc389 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -40,6 +40,8 @@ cc_library( deps = [ ":handle", ":registry", + "//absl/memory", + "//absl/strings", "//absl/synchronization", ], ) @@ -184,6 +186,7 @@ cc_library( ":marshalling", "//absl/base", "//absl/base:core_headers", + "//absl/memory", "//absl/strings", ], ) diff --git a/absl/flags/flag.cc b/absl/flags/flag.cc index a02d069e..69038bbf 100644 --- a/absl/flags/flag.cc +++ b/absl/flags/flag.cc @@ -49,9 +49,7 @@ namespace flags_internal { ABSL_CONST_INIT static absl::Mutex construction_guard(absl::kConstInit); -void LockGlobalConstructionGuard() { construction_guard.Lock(); } - -void UnlockGlobalConstructionGuard() { construction_guard.Unlock(); } +absl::Mutex* GetGlobalConstructionGuard() { return &construction_guard; } } // namespace flags_internal diff --git a/absl/flags/flag.h b/absl/flags/flag.h index 86ad59dd..4927757b 100644 --- a/absl/flags/flag.h +++ b/absl/flags/flag.h @@ -80,8 +80,7 @@ using Flag = flags_internal::Flag; // if two threads attempt to construct the flag concurrently only one wins. namespace flags_internal { -void LockGlobalConstructionGuard(); -void UnlockGlobalConstructionGuard(); +absl::Mutex* GetGlobalConstructionGuard(); } // namespace flags_internal template @@ -100,7 +99,7 @@ class Flag { flags_internal::Flag* GetImpl() const { if (!inited_.load(std::memory_order_acquire)) { - flags_internal::LockGlobalConstructionGuard(); + absl::MutexLock l(flags_internal::GetGlobalConstructionGuard()); if (inited_.load(std::memory_order_acquire)) { return impl_; @@ -109,8 +108,6 @@ class Flag { impl_ = new flags_internal::Flag(name_, help_gen_, filename_, marshalling_op_, initial_value_gen_); inited_.store(true, std::memory_order_release); - - flags_internal::UnlockGlobalConstructionGuard(); } return impl_; @@ -130,7 +127,6 @@ class Flag { std::string Filename() const { return GetImpl()->Filename(); } std::string DefaultValue() const { return GetImpl()->DefaultValue(); } std::string CurrentValue() const { return GetImpl()->CurrentValue(); } - bool HasValidatorFn() const { return GetImpl()->HasValidatorFn(); } bool InvokeValidator(const void* value) const { return GetImpl()->InvokeValidator(value); } diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc index 53e2b84e..99f73611 100644 --- a/absl/flags/internal/commandlineflag.cc +++ b/absl/flags/internal/commandlineflag.cc @@ -149,6 +149,12 @@ std::string CommandLineFlag::CurrentValue() const { return Unparse(marshalling_op_, cur_); } +int64_t CommandLineFlag::MutationCounter() const { + absl::MutexLock l(InitFlagIfNecessary()); + + return counter_; +} + // Attempts to parse supplied `value` string using parsing routine in the `flag` // argument. If parsing is successful, it will try to validate that the parsed // value is valid for the specified 'flag'. Finally this function stores the diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h index 284286b6..528d3106 100644 --- a/absl/flags/internal/commandlineflag.h +++ b/absl/flags/internal/commandlineflag.h @@ -17,6 +17,7 @@ #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ #include +#include #include "absl/base/macros.h" #include "absl/flags/marshalling.h" @@ -186,6 +187,16 @@ class HelpText { 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 { + public: + virtual ~FlagStateInterface() {} + + // Restores the flag originated this object to the saved state. + virtual void Restore() const = 0; +}; + // Holds all information for a flag. class CommandLineFlag { public: @@ -239,7 +250,6 @@ class CommandLineFlag { virtual void StoreAtomic() {} // Interfaces to operate on validators. - virtual bool HasValidatorFn() const { return false; } virtual bool InvokeValidator(const void* /*value*/) const { return true; } // Invoke the flag validators for old flags. // TODO(rogeeff): implement proper validators for Abseil Flags @@ -264,6 +274,10 @@ class CommandLineFlag { return res; } + // Interface to save flag to some persistent state. Returns current flag state + // or nullptr if flag does not support saving and restoring a state. + virtual std::unique_ptr SaveState() = 0; + // Interfaces to overate on callbacks. virtual void InvokeCallback() {} @@ -285,6 +299,9 @@ class CommandLineFlag { protected: ~CommandLineFlag() = default; + // Thread safe access to mutation counter. + int64_t MutationCounter() const; + const char* const name_; const HelpText help_; const char* const filename_; @@ -323,11 +340,6 @@ class CommandLineFlag { friend bool TryParseLocked(CommandLineFlag* flag, void* dst, absl::string_view value, std::string* err); friend absl::Mutex* InitFlag(CommandLineFlag* flag); - - // This is a short term, until we completely rework persistent state - // storage API. - virtual void* GetValidator() const { return nullptr; } - virtual bool SetValidator(void*) { return false; } }; // Update any copy of the flag value that is stored in an atomic word. diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index 16330380..2b21c440 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -20,12 +20,44 @@ #include "absl/flags/internal/commandlineflag.h" #include "absl/flags/internal/registry.h" +#include "absl/memory/memory.h" +#include "absl/strings/str_cat.h" namespace absl { namespace flags_internal { constexpr int64_t AtomicInit() { return 0xababababababababll; } +template +class Flag; + +template +class FlagState : public flags_internal::FlagStateInterface { + public: + FlagState(Flag* flag, T&& cur, bool modified, bool on_command_line, + int64_t counter) + : flag_(flag), + cur_value_(std::move(cur)), + modified_(modified), + on_command_line_(on_command_line), + counter_(counter) {} + + ~FlagState() override = default; + + private: + friend class Flag; + + // Restores the flag to the saved state. + void Restore() const override; + + // Flag and saved flag data. + Flag* flag_; + T cur_value_; + bool modified_; + bool on_command_line_; + int64_t counter_; +}; + // Signature for the mutation callback used by watched Flags // The callback is noexcept. // TODO(rogeeff): add noexcept after C++17 support is added. @@ -98,15 +130,12 @@ class Flag final : public flags_internal::CommandLineFlag { InvokeCallback(); } - void InvokeCallback() override - ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) { - flags_internal::InvokeCallback(&locks_->primary_mu, &locks_->callback_mu, - callback_); - } private: + friend class FlagState; + void Destroy() const override { - // Values are heap allocated Abseil Flags. + // Values are heap allocated for Abseil Flags. if (cur_) Delete(op_, cur_); if (def_) Delete(op_, def_); @@ -121,6 +150,41 @@ class Flag final : public flags_internal::CommandLineFlag { } } + // Interfaces to save and restore flags to/from persistent state. + // Returns current flag state or nullptr if flag does not support + // saving and restoring a state. + std::unique_ptr SaveState() override { + T curr_value = Get(); + + absl::MutexLock l(InitFlagIfNecessary()); + + return absl::make_unique>( + this, std::move(curr_value), modified_, on_command_line_, counter_); + } + + // Restores the flag state to the supplied state object. If there is + // nothing to restore returns false. Otherwise returns true. + bool RestoreState(const flags_internal::FlagState& flag_state) { + if (MutationCounter() == flag_state.counter_) return false; + + Set(flag_state.cur_value_); + + // Race condition here? This should disappear once we move the rest of the + // flag's data into Flag's internals. + + absl::MutexLock l(InitFlagIfNecessary()); + modified_ = flag_state.modified_; + on_command_line_ = flag_state.on_command_line_; + return true; + } + + // Interfaces to overate on callbacks. + void InvokeCallback() override + ABSL_EXCLUSIVE_LOCKS_REQUIRED(locks_->primary_mu) { + flags_internal::InvokeCallback(&locks_->primary_mu, &locks_->callback_mu, + callback_); + } + // Flag's data // For some types, a copy of the current value is kept in an atomically // accessible field. @@ -128,6 +192,15 @@ class Flag final : public flags_internal::CommandLineFlag { FlagCallback callback_; // Mutation callback }; +template +inline void FlagState::Restore() const { + if (flag_->RestoreState(*this)) { + ABSL_INTERNAL_LOG(INFO, + absl::StrCat("Restore saved value of ", flag_->Name(), + " to: ", flag_->CurrentValue())); + } +} + // This class facilitates Flag object registration and tail expression-based // flag definition, for example: // ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher); diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc index 4bea313b..6b2564d1 100644 --- a/absl/flags/internal/registry.cc +++ b/absl/flags/internal/registry.cc @@ -188,114 +188,34 @@ CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) { class FlagSaverImpl { public: - // Constructs an empty FlagSaverImpl object. - FlagSaverImpl() {} - ~FlagSaverImpl() { - // reclaim memory from each of our CommandLineFlags - for (const SavedFlag& src : backup_registry_) { - Delete(src.op, src.current); - Delete(src.op, src.default_value); - } - } + FlagSaverImpl() = default; + FlagSaverImpl(const FlagSaverImpl&) = delete; + void operator=(const FlagSaverImpl&) = delete; // Saves the flag states from the flag registry into this object. // It's an error to call this more than once. - // Must be called when the registry mutex is not held. void SaveFromRegistry() { assert(backup_registry_.empty()); // call only once! - SavedFlag saved; flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) { - if (flag->IsRetired()) return; - - saved.name = flag->Name(); - saved.op = flag->op_; - saved.marshalling_op = flag->marshalling_op_; - { - absl::MutexLock l(flag->InitFlagIfNecessary()); - saved.validator = flag->GetValidator(); - saved.modified = flag->modified_; - saved.on_command_line = flag->on_command_line_; - saved.current = Clone(saved.op, flag->cur_); - saved.default_value = Clone(saved.op, flag->def_); - saved.counter = flag->counter_; + if (auto flag_state = flag->SaveState()) { + backup_registry_.emplace_back(std::move(flag_state)); } - backup_registry_.push_back(saved); }); } - // Restores the saved flag states into the flag registry. We - // assume no flags were added or deleted from the registry since - // the SaveFromRegistry; if they were, that's trouble! Must be - // called when the registry mutex is not held. + // Restores the saved flag states into the flag registry. void RestoreToRegistry() { - FlagRegistry* const global_registry = FlagRegistry::GlobalRegistry(); - FlagRegistryLock frl(global_registry); - for (const SavedFlag& src : backup_registry_) { - CommandLineFlag* flag = global_registry->FindFlagLocked(src.name); - // If null, flag got deleted from registry. - if (!flag) continue; - - bool restored = false; - { - // This function encapsulate the lock. - flag->SetValidator(src.validator); - - absl::MutexLock l(flag->InitFlagIfNecessary()); - flag->modified_ = src.modified; - flag->on_command_line_ = src.on_command_line; - if (flag->counter_ != src.counter || - ChangedDirectly(flag, src.default_value, flag->def_)) { - restored = true; - Copy(src.op, src.default_value, flag->def_); - } - if (flag->counter_ != src.counter || - ChangedDirectly(flag, src.current, flag->cur_)) { - restored = true; - Copy(src.op, src.current, flag->cur_); - UpdateCopy(flag); - flag->InvokeCallback(); - } - } - - if (restored) { - flag->counter_++; - - // Revalidate the flag because the validator might store state based - // on the flag's value, which just changed due to the restore. - // Failing validation is ignored because it's assumed that the flag - // was valid previously and there's little that can be done about it - // here, anyway. - flag->ValidateInputValue(flag->CurrentValue()); - - ABSL_INTERNAL_LOG( - INFO, absl::StrCat("Restore saved value of ", flag->Name(), ": ", - Unparse(src.marshalling_op, src.current))); - } + for (const auto& flag_state : backup_registry_) { + flag_state->Restore(); } } private: - struct SavedFlag { - absl::string_view name; - FlagOpFn op; - FlagMarshallingOpFn marshalling_op; - int64_t counter; - void* validator; - bool modified; - bool on_command_line; - const void* current; // nullptr after restore - const void* default_value; // nullptr after restore - }; - - std::vector backup_registry_; - - FlagSaverImpl(const FlagSaverImpl&); // no copying! - void operator=(const FlagSaverImpl&); + std::vector> + backup_registry_; }; -FlagSaver::FlagSaver() : impl_(new FlagSaverImpl()) { - impl_->SaveFromRegistry(); -} +FlagSaver::FlagSaver() : impl_(new FlagSaverImpl) { impl_->SaveFromRegistry(); } void FlagSaver::Ignore() { delete impl_; @@ -376,6 +296,10 @@ class RetiredFlagObj final : public flags_internal::CommandLineFlag { delete this; } + + std::unique_ptr SaveState() override { + return nullptr; + } }; } // namespace diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel index c904618d..92111827 100644 --- a/absl/random/BUILD.bazel +++ b/absl/random/BUILD.bazel @@ -26,7 +26,7 @@ load( package(default_visibility = ["//visibility:public"]) -licenses(["notice"]) # Apache 2.0 +licenses(["notice"]) cc_library( name = "random", diff --git a/absl/random/distribution_format_traits.h b/absl/random/distribution_format_traits.h index 3298c2cd..f9f07058 100644 --- a/absl/random/distribution_format_traits.h +++ b/absl/random/distribution_format_traits.h @@ -249,12 +249,12 @@ struct DistributionFormatTraits> { } }; -template +template struct UniformDistributionWrapper; -template -struct DistributionFormatTraits> { - using distribution_t = UniformDistributionWrapper; +template +struct DistributionFormatTraits> { + using distribution_t = UniformDistributionWrapper; using result_t = NumType; static constexpr const char* Name() { return "Uniform"; } @@ -263,19 +263,7 @@ struct DistributionFormatTraits> { return absl::StrCat(Name(), "<", ScalarTypeName(), ">"); } static std::string FormatArgs(const distribution_t& d) { - absl::string_view tag; - if (std::is_same::value) { - tag = "IntervalClosedClosed"; - } else if (std::is_same::value) { - tag = "IntervalClosedOpen"; - } else if (std::is_same::value) { - tag = "IntervalOpenClosed"; - } else if (std::is_same::value) { - tag = "IntervalOpenOpen"; - } else { - tag = "[[unknown tag type]]"; - } - return absl::StrCat(tag, ", ", (d.min)(), ", ", (d.max)()); + return absl::StrCat((d.min)(), ", ", (d.max)()); } static std::string FormatResults(absl::Span results) { return absl::StrJoin(results, ", "); diff --git a/absl/random/distributions.h b/absl/random/distributions.h index 3a4e93ab..6ced6061 100644 --- a/absl/random/distributions.h +++ b/absl/random/distributions.h @@ -124,7 +124,15 @@ Uniform(TagType tag, URBG&& urbg, // NOLINT(runtime/references) R lo, R hi) { using gen_t = absl::decay_t; - return random_internal::UniformImpl(tag, urbg, lo, hi); + using distribution_t = random_internal::UniformDistributionWrapper; + using format_t = random_internal::DistributionFormatTraits; + + auto a = random_internal::uniform_lower_bound(tag, lo, hi); + auto b = random_internal::uniform_upper_bound(tag, lo, hi); + if (a > b) return a; + + return random_internal::DistributionCaller::template Call< + distribution_t, format_t>(&urbg, tag, lo, hi); } // absl::Uniform(bitgen, lo, hi) @@ -135,11 +143,17 @@ template typename absl::enable_if_t::value, R> // Uniform(URBG&& urbg, // NOLINT(runtime/references) R lo, R hi) { - constexpr auto tag = absl::IntervalClosedOpen; - using tag_t = decltype(tag); using gen_t = absl::decay_t; + using distribution_t = random_internal::UniformDistributionWrapper; + using format_t = random_internal::DistributionFormatTraits; + + constexpr auto tag = absl::IntervalClosedOpen; + auto a = random_internal::uniform_lower_bound(tag, lo, hi); + auto b = random_internal::uniform_upper_bound(tag, lo, hi); + if (a > b) return a; - return random_internal::UniformImpl(tag, urbg, lo, hi); + return random_internal::DistributionCaller::template Call< + distribution_t, format_t>(&urbg, lo, hi); } // absl::Uniform(tag, bitgen, lo, hi) @@ -156,9 +170,16 @@ Uniform(TagType tag, A lo, B hi) { using gen_t = absl::decay_t; using return_t = typename random_internal::uniform_inferred_return_t; + using distribution_t = random_internal::UniformDistributionWrapper; + using format_t = random_internal::DistributionFormatTraits; - return random_internal::UniformImpl(tag, urbg, lo, - hi); + auto a = random_internal::uniform_lower_bound(tag, lo, hi); + auto b = random_internal::uniform_upper_bound(tag, lo, hi); + if (a > b) return a; + + return random_internal::DistributionCaller::template Call< + distribution_t, format_t>(&urbg, tag, static_cast(lo), + static_cast(hi)); } // absl::Uniform(bitgen, lo, hi) @@ -171,13 +192,19 @@ typename absl::enable_if_t::value, random_internal::uniform_inferred_return_t> Uniform(URBG&& urbg, // NOLINT(runtime/references) A lo, B hi) { - constexpr auto tag = absl::IntervalClosedOpen; - using tag_t = decltype(tag); using gen_t = absl::decay_t; using return_t = typename random_internal::uniform_inferred_return_t; + using distribution_t = random_internal::UniformDistributionWrapper; + using format_t = random_internal::DistributionFormatTraits; - return random_internal::UniformImpl(tag, urbg, lo, - hi); + constexpr auto tag = absl::IntervalClosedOpen; + auto a = random_internal::uniform_lower_bound(tag, lo, hi); + auto b = random_internal::uniform_upper_bound(tag, lo, hi); + if (a > b) return a; + + return random_internal::DistributionCaller::template Call< + distribution_t, format_t>(&urbg, static_cast(lo), + static_cast(hi)); } // absl::Uniform(bitgen) @@ -187,13 +214,12 @@ Uniform(URBG&& urbg, // NOLINT(runtime/references) template typename absl::enable_if_t::value, R> // Uniform(URBG&& urbg) { // NOLINT(runtime/references) - constexpr auto tag = absl::IntervalClosedClosed; - constexpr auto lo = std::numeric_limits::lowest(); - constexpr auto hi = (std::numeric_limits::max)(); - using tag_t = decltype(tag); using gen_t = absl::decay_t; + using distribution_t = random_internal::UniformDistributionWrapper; + using format_t = random_internal::DistributionFormatTraits; - return random_internal::UniformImpl(tag, urbg, lo, hi); + return random_internal::DistributionCaller::template Call< + distribution_t, format_t>(&urbg); } // ----------------------------------------------------------------------------- diff --git a/absl/random/internal/distributions.h b/absl/random/internal/distributions.h index 96f8bae3..c8cec02b 100644 --- a/absl/random/internal/distributions.h +++ b/absl/random/internal/distributions.h @@ -24,36 +24,6 @@ namespace absl { namespace random_internal { -template -struct DistributionFormatTraits; - -// UniformImpl implements the core logic of the Uniform call, which is to -// select the correct distribution type, compute the bounds based on the -// interval tag, and then generate a value. -template -NumType UniformImpl(TagType tag, - URBG& urbg, // NOLINT(runtime/references) - NumType lo, NumType hi) { - static_assert( - std::is_arithmetic::value, - "absl::Uniform() must use an integer or real parameter type."); - - using distribution_t = - UniformDistributionWrapper, NumType>; - using format_t = random_internal::DistributionFormatTraits; - auto a = uniform_lower_bound(tag, lo, hi); - auto b = uniform_upper_bound(tag, lo, hi); - - // TODO(lar): it doesn't make a lot of sense to ask for a random number in an - // empty range. Right now we just return a boundary--even though that - // boundary is not an acceptable value! Is there something better we can do - // here? - if (a > b) return a; - - using gen_t = absl::decay_t; - return DistributionCaller::template Call( - &urbg, tag, lo, hi); -} // In the absence of an explicitly provided return-type, the template // "uniform_inferred_return_t" is used to derive a suitable type, based on diff --git a/absl/random/internal/uniform_helper.h b/absl/random/internal/uniform_helper.h index 2929407e..f68b1823 100644 --- a/absl/random/internal/uniform_helper.h +++ b/absl/random/internal/uniform_helper.h @@ -154,12 +154,22 @@ using UniformDistribution = absl::uniform_int_distribution, absl::uniform_real_distribution>::type; -template +template struct UniformDistributionWrapper : public UniformDistribution { + template explicit UniformDistributionWrapper(TagType, NumType lo, NumType hi) : UniformDistribution( uniform_lower_bound(TagType{}, lo, hi), uniform_upper_bound(TagType{}, lo, hi)) {} + + explicit UniformDistributionWrapper(NumType lo, NumType hi) + : UniformDistribution( + uniform_lower_bound(IntervalClosedOpenTag(), lo, hi), + uniform_upper_bound(IntervalClosedOpenTag(), lo, hi)) {} + + explicit UniformDistributionWrapper() + : UniformDistribution(std::numeric_limits::lowest(), + (std::numeric_limits::max)()) {} }; } // namespace random_internal diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 729bdd76..4863ead2 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -630,6 +630,7 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":str_format_internal", + "//absl/base:raw_logging_internal", "//absl/numeric:int128", "@com_google_googletest//:gtest_main", ], diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index ccff4441..3f907957 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -461,6 +461,7 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::str_format_internal + absl::raw_logging_internal absl::int128 gmock_main ) diff --git a/absl/strings/charconv_test.cc b/absl/strings/charconv_test.cc index b58fad26..9090e9c8 100644 --- a/absl/strings/charconv_test.cc +++ b/absl/strings/charconv_test.cc @@ -511,6 +511,13 @@ TEST(FromChars, Overflow) { EXPECT_EQ(f, std::numeric_limits::max()); } +TEST(FromChars, RegressionTestsFromFuzzer) { + absl::string_view src = "0x21900000p00000000099"; + float f; + auto result = absl::from_chars(src.data(), src.data() + src.size(), f); + EXPECT_EQ(result.ec, std::errc::result_out_of_range); +} + TEST(FromChars, ReturnValuePtr) { // Check that `ptr` points one past the number scanned, even if that number // is not representable. diff --git a/absl/strings/internal/charconv_parse.cc b/absl/strings/internal/charconv_parse.cc index f3c72324..fa9a8965 100644 --- a/absl/strings/internal/charconv_parse.cc +++ b/absl/strings/internal/charconv_parse.cc @@ -253,6 +253,12 @@ std::size_t ConsumeDigits(const char* begin, const char* end, int max_digits, assert(max_digits * 4 <= std::numeric_limits::digits); } const char* const original_begin = begin; + + // Skip leading zeros, but only if *out is zero. + // They don't cause an overflow so we don't have to count them for + // `max_digits`. + while (!*out && end != begin && *begin == '0') ++begin; + T accumulator = *out; const char* significant_digits_end = (end - begin > max_digits) ? begin + max_digits : end; diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 814ccf4c..ab8d5391 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -5,7 +5,9 @@ #include #include +#include "gmock/gmock.h" #include "gtest/gtest.h" +#include "absl/base/internal/raw_logging.h" #include "absl/strings/internal/str_format/bind.h" namespace absl { @@ -157,12 +159,20 @@ TEST_F(FormatConvertTest, StringPrecision) { EXPECT_EQ("ABC", FormatPack(format2, {FormatArgImpl(p)})); } +// Pointer formatting is implementation defined. This checks that the argument +// can be matched to `ptr`. +MATCHER_P(MatchesPointerString, ptr, "") { + if (ptr == nullptr && arg == "(nil)") { + return true; + } + void* parsed = nullptr; + if (sscanf(arg.c_str(), "%p", &parsed) != 1) { + ABSL_RAW_LOG(FATAL, "Could not parse %s", arg.c_str()); + } + return ptr == parsed; +} + TEST_F(FormatConvertTest, Pointer) { -#ifdef _MSC_VER - // MSVC's printf implementation prints pointers differently. We can't easily - // compare our implementation to theirs. - return; -#endif static int x = 0; const int *xp = &x; char c = 'h'; @@ -173,48 +183,62 @@ TEST_F(FormatConvertTest, Pointer) { using VoidF = void (*)(); VoidF fp = [] {}, fnil = nullptr; volatile char vc; - volatile char* vcp = &vc; - volatile char* vcnil = nullptr; - const FormatArgImpl args[] = { + volatile char *vcp = &vc; + volatile char *vcnil = nullptr; + const FormatArgImpl args_array[] = { FormatArgImpl(xp), FormatArgImpl(cp), FormatArgImpl(inil), FormatArgImpl(cnil), FormatArgImpl(mcp), FormatArgImpl(fp), FormatArgImpl(fnil), FormatArgImpl(vcp), FormatArgImpl(vcnil), }; - struct Expectation { - std::string out; - const char *fmt; - }; - const Expectation kExpect[] = { - {StrPrint("%p", &x), "%p"}, - {StrPrint("%20p", &x), "%20p"}, - {StrPrint("%.1p", &x), "%.1p"}, - {StrPrint("%.20p", &x), "%.20p"}, - {StrPrint("%30.20p", &x), "%30.20p"}, - - {StrPrint("%-p", &x), "%-p"}, - {StrPrint("%-20p", &x), "%-20p"}, - {StrPrint("%-.1p", &x), "%-.1p"}, - {StrPrint("%.20p", &x), "%.20p"}, - {StrPrint("%-30.20p", &x), "%-30.20p"}, - - {StrPrint("%p", cp), "%2$p"}, // const char* - {"(nil)", "%3$p"}, // null const char * - {"(nil)", "%4$p"}, // null const int * - {StrPrint("%p", mcp), "%5$p"}, // nonconst char* - - {StrPrint("%p", fp), "%6$p"}, // function pointer - {StrPrint("%p", vcp), "%8$p"}, // function pointer - -#ifndef __APPLE__ - // Apple's printf differs here (0x0 vs. nil) - {StrPrint("%p", fnil), "%7$p"}, // null function pointer - {StrPrint("%p", vcnil), "%9$p"}, // null function pointer -#endif - }; - for (const Expectation &e : kExpect) { - UntypedFormatSpecImpl format(e.fmt); - EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))) << e.fmt; - } + auto args = absl::MakeConstSpan(args_array); + + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%p"), args), + MatchesPointerString(&x)); + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%20p"), args), + MatchesPointerString(&x)); + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.1p"), args), + MatchesPointerString(&x)); + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args), + MatchesPointerString(&x)); + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%30.20p"), args), + MatchesPointerString(&x)); + + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-p"), args), + MatchesPointerString(&x)); + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-20p"), args), + MatchesPointerString(&x)); + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-.1p"), args), + MatchesPointerString(&x)); + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args), + MatchesPointerString(&x)); + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-30.20p"), args), + MatchesPointerString(&x)); + + // const char* + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%2$p"), args), + MatchesPointerString(cp)); + // null const int* + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%3$p"), args), + MatchesPointerString(nullptr)); + // null const char* + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%4$p"), args), + MatchesPointerString(nullptr)); + // nonconst char* + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%5$p"), args), + MatchesPointerString(mcp)); + + // function pointers + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%6$p"), args), + MatchesPointerString(reinterpret_cast(fp))); + EXPECT_THAT( + FormatPack(UntypedFormatSpecImpl("%8$p"), args), + MatchesPointerString(reinterpret_cast(vcp))); + + // null function pointers + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%7$p"), args), + MatchesPointerString(nullptr)); + EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%9$p"), args), + MatchesPointerString(nullptr)); } struct Cardinal { diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc index 77d7e783..4edf8891 100644 --- a/absl/strings/numbers_test.cc +++ b/absl/strings/numbers_test.cc @@ -713,11 +713,11 @@ TEST(stringtest, safe_strtou64_base_length_delimited) { } } -// feenableexcept() and fedisableexcept() are missing on macOS, MSVC, -// and WebAssembly. -#if defined(_MSC_VER) || defined(__APPLE__) || defined(__EMSCRIPTEN__) -#define ABSL_MISSING_FEENABLEEXCEPT 1 -#define ABSL_MISSING_FEDISABLEEXCEPT 1 +// feenableexcept() and fedisableexcept() are extensions supported by some libc +// implementations. +#if defined(__GLIBC__) || defined(__BIONIC__) +#define ABSL_HAVE_FEENABLEEXCEPT 1 +#define ABSL_HAVE_FEDISABLEEXCEPT 1 #endif class SimpleDtoaTest : public testing::Test { @@ -725,7 +725,7 @@ class SimpleDtoaTest : public testing::Test { void SetUp() override { // Store the current floating point env & clear away any pending exceptions. feholdexcept(&fp_env_); -#ifndef ABSL_MISSING_FEENABLEEXCEPT +#ifdef ABSL_HAVE_FEENABLEEXCEPT // Turn on floating point exceptions. feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); #endif @@ -735,7 +735,7 @@ class SimpleDtoaTest : public testing::Test { // Restore the floating point environment to the original state. // In theory fedisableexcept is unnecessary; fesetenv will also do it. // In practice, our toolchains have subtle bugs. -#ifndef ABSL_MISSING_FEDISABLEEXCEPT +#ifdef ABSL_HAVE_FEDISABLEEXCEPT fedisableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); #endif fesetenv(&fp_env_); diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h index 82344eb2..3438ccc1 100644 --- a/absl/strings/string_view.h +++ b/absl/strings/string_view.h @@ -40,6 +40,13 @@ using std::string_view; #else // ABSL_HAVE_STD_STRING_VIEW +#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \ + (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_INTERNAL_STRING_VIEW_MEMCMP __builtin_memcmp +#else // ABSL_HAVE_BUILTIN(__builtin_memcmp) +#define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp +#endif // ABSL_HAVE_BUILTIN(__builtin_memcmp) + #include #include #include @@ -381,16 +388,13 @@ class string_view { // view. Note that in the case of data equality, a further comparison is made // on the respective sizes of the two `string_view`s to determine which is // smaller, equal, or greater. - int compare(string_view x) const noexcept { - auto min_length = (std::min)(length_, x.length_); - if (min_length > 0) { - int r = memcmp(ptr_, x.ptr_, min_length); - if (r < 0) return -1; - if (r > 0) return 1; - } - if (length_ < x.length_) return -1; - if (length_ > x.length_) return 1; - return 0; + constexpr int compare(string_view x) const noexcept { + return CompareImpl( + length_, x.length_, + length_ == 0 || x.length_ == 0 + ? 0 + : ABSL_INTERNAL_STRING_VIEW_MEMCMP( + ptr_, x.ptr_, length_ < x.length_ ? length_ : x.length_)); } // Overload of `string_view::compare()` for comparing a substring of the @@ -528,6 +532,14 @@ class string_view { #endif } + static constexpr int CompareImpl(size_type length_a, size_type length_b, + int compare_result) { + return compare_result == 0 ? static_cast(length_a > length_b) - + static_cast(length_a < length_b) + : static_cast(compare_result > 0) - + static_cast(compare_result < 0); + } + const char* ptr_; size_type length_; }; @@ -535,33 +547,29 @@ class string_view { // This large function is defined inline so that in a fairly common case where // one of the arguments is a literal, the compiler can elide a lot of the // following comparisons. -inline bool operator==(string_view x, string_view y) noexcept { - auto len = x.size(); - if (len != y.size()) { - return false; - } - - return x.data() == y.data() || len <= 0 || - memcmp(x.data(), y.data(), len) == 0; +constexpr bool operator==(string_view x, string_view y) noexcept { + return x.size() == y.size() && + (x.empty() || + ABSL_INTERNAL_STRING_VIEW_MEMCMP(x.data(), y.data(), x.size()) == 0); } -inline bool operator!=(string_view x, string_view y) noexcept { +constexpr bool operator!=(string_view x, string_view y) noexcept { return !(x == y); } -inline bool operator<(string_view x, string_view y) noexcept { - auto min_size = (std::min)(x.size(), y.size()); - const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size); - return (r < 0) || (r == 0 && x.size() < y.size()); +constexpr bool operator<(string_view x, string_view y) noexcept { + return x.compare(y) < 0; } -inline bool operator>(string_view x, string_view y) noexcept { return y < x; } +constexpr bool operator>(string_view x, string_view y) noexcept { + return y < x; +} -inline bool operator<=(string_view x, string_view y) noexcept { +constexpr bool operator<=(string_view x, string_view y) noexcept { return !(y < x); } -inline bool operator>=(string_view x, string_view y) noexcept { +constexpr bool operator>=(string_view x, string_view y) noexcept { return !(x < y); } @@ -570,6 +578,8 @@ std::ostream& operator<<(std::ostream& o, string_view piece); } // namespace absl +#undef ABSL_INTERNAL_STRING_VIEW_MEMCMP + #endif // ABSL_HAVE_STD_STRING_VIEW namespace absl { diff --git a/absl/strings/string_view_test.cc b/absl/strings/string_view_test.cc index eb8b170b..86f2fbcd 100644 --- a/absl/strings/string_view_test.cc +++ b/absl/strings/string_view_test.cc @@ -974,6 +974,29 @@ TEST(StringViewTest, ConstexprCompiles) { EXPECT_EQ(cstr_strlen.length(), 3); constexpr absl::string_view cstr_strlen2 = "bar"; EXPECT_EQ(cstr_strlen2, "bar"); + +#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \ + (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_COMPARISON 1 +#endif +#ifdef ABSL_HAVE_CONSTEXPR_STRING_VIEW_COMPARISON + constexpr absl::string_view foo = "foo"; + constexpr absl::string_view bar = "bar"; + constexpr bool foo_eq_bar = foo == bar; + constexpr bool foo_ne_bar = foo != bar; + constexpr bool foo_lt_bar = foo < bar; + constexpr bool foo_le_bar = foo <= bar; + constexpr bool foo_gt_bar = foo > bar; + constexpr bool foo_ge_bar = foo >= bar; + constexpr int foo_compare_bar = foo.compare(bar); + EXPECT_FALSE(foo_eq_bar); + EXPECT_TRUE(foo_ne_bar); + EXPECT_FALSE(foo_lt_bar); + EXPECT_FALSE(foo_le_bar); + EXPECT_TRUE(foo_gt_bar); + EXPECT_TRUE(foo_ge_bar); + EXPECT_GT(foo_compare_bar, 0); +#endif #endif #if !defined(__clang__) || 3 < __clang_major__ || \ diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc index 96145780..d83d8087 100644 --- a/absl/synchronization/internal/waiter.cc +++ b/absl/synchronization/internal/waiter.cc @@ -129,6 +129,9 @@ void Waiter::Init() { bool Waiter::Wait(KernelTimeout t) { // Loop until we can atomically decrement futex from a positive // value, waiting on a futex while we believe it is zero. + // Note that, since the thread ticker is just reset, we don't need to check + // whether the thread is idle on the very first pass of the loop. + bool first_pass = true; while (true) { int32_t x = futex_.load(std::memory_order_relaxed); if (x != 0) { @@ -140,6 +143,8 @@ bool Waiter::Wait(KernelTimeout t) { return true; // Consumed a wakeup, we are done. } + + if (!first_pass) MaybeBecomeIdle(); const int err = Futex::WaitUntil(&futex_, 0, t); if (err != 0) { if (err == -EINTR || err == -EWOULDBLOCK) { @@ -150,8 +155,7 @@ bool Waiter::Wait(KernelTimeout t) { ABSL_RAW_LOG(FATAL, "Futex operation failed with error %d\n", err); } } - - MaybeBecomeIdle(); + first_pass = false; } } @@ -219,6 +223,9 @@ bool Waiter::Wait(KernelTimeout t) { PthreadMutexHolder h(&mu_); waiter_count_.fetch_add(1, std::memory_order_relaxed); // Loop until we find a wakeup to consume or timeout. + // Note that, since the thread ticker is just reset, we don't need to check + // whether the thread is idle on the very first pass of the loop. + bool first_pass = true; while (true) { int x = wakeup_count_.load(std::memory_order_relaxed); if (x != 0) { @@ -232,6 +239,7 @@ bool Waiter::Wait(KernelTimeout t) { return true; } + if (!first_pass) MaybeBecomeIdle(); // No wakeups available, time to wait. if (!t.has_timeout()) { const int err = pthread_cond_wait(&cv_, &mu_); @@ -248,7 +256,7 @@ bool Waiter::Wait(KernelTimeout t) { ABSL_RAW_LOG(FATAL, "pthread_cond_wait failed: %d", err); } } - MaybeBecomeIdle(); + first_pass = false; } } @@ -288,6 +296,9 @@ bool Waiter::Wait(KernelTimeout t) { } // Loop until we timeout or consume a wakeup. + // Note that, since the thread ticker is just reset, we don't need to check + // whether the thread is idle on the very first pass of the loop. + bool first_pass = true; while (true) { int x = wakeups_.load(std::memory_order_relaxed); if (x != 0) { @@ -300,6 +311,7 @@ bool Waiter::Wait(KernelTimeout t) { return true; } + if (!first_pass) MaybeBecomeIdle(); // Nothing to consume, wait (looping on EINTR). while (true) { if (!t.has_timeout()) { @@ -313,7 +325,7 @@ bool Waiter::Wait(KernelTimeout t) { ABSL_RAW_LOG(FATAL, "sem_timedwait failed: %d", errno); } } - MaybeBecomeIdle(); + first_pass = false; } } @@ -401,6 +413,9 @@ bool Waiter::Wait(KernelTimeout t) { waiter_count_.fetch_add(1, std::memory_order_relaxed); // Loop until we find a wakeup to consume or timeout. + // Note that, since the thread ticker is just reset, we don't need to check + // whether the thread is idle on the very first pass of the loop. + bool first_pass = true; while (true) { int x = wakeup_count_.load(std::memory_order_relaxed); if (x != 0) { @@ -414,6 +429,7 @@ bool Waiter::Wait(KernelTimeout t) { return true; } + if (!first_pass) MaybeBecomeIdle(); // No wakeups available, time to wait. if (!SleepConditionVariableSRW(cv, mu, t.InMillisecondsFromNow(), 0)) { // GetLastError() returns a Win32 DWORD, but we assign to @@ -427,8 +443,7 @@ bool Waiter::Wait(KernelTimeout t) { ABSL_RAW_LOG(FATAL, "SleepConditionVariableSRW failed: %lu", err); } } - - MaybeBecomeIdle(); + first_pass = false; } } diff --git a/absl/synchronization/internal/waiter.h b/absl/synchronization/internal/waiter.h index 0757b91d..09993545 100644 --- a/absl/synchronization/internal/waiter.h +++ b/absl/synchronization/internal/waiter.h @@ -19,7 +19,7 @@ #include "absl/base/config.h" #ifdef _WIN32 -#include +#include #else #include #endif diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h index d33318d3..ccd94618 100644 --- a/absl/synchronization/mutex.h +++ b/absl/synchronization/mutex.h @@ -628,7 +628,7 @@ class ABSL_SCOPED_LOCKABLE WriterMutexLock { // Example: // // // assume count_ is not internal reference count -// int count_ GUARDED_BY(mu_); +// int count_ ABSL_GUARDED_BY(mu_); // // mu_.LockWhen(Condition(+[](int* count) { return *count == 0; }, // &count_)); diff --git a/absl/time/duration.cc b/absl/time/duration.cc index a3ac61a9..9a876811 100644 --- a/absl/time/duration.cc +++ b/absl/time/duration.cc @@ -906,6 +906,11 @@ bool ParseDuration(const std::string& dur_string, Duration* d) { return true; } +bool AbslParseFlag(absl::string_view text, Duration* dst, std::string*) { + return ParseDuration(std::string(text), dst); +} + +std::string AbslUnparseFlag(Duration d) { return FormatDuration(d); } bool ParseFlag(const std::string& text, Duration* dst, std::string* ) { return ParseDuration(text, dst); } diff --git a/absl/time/format.cc b/absl/time/format.cc index d6ca8600..ebe872cf 100644 --- a/absl/time/format.cc +++ b/absl/time/format.cc @@ -129,6 +129,14 @@ bool ParseTime(const std::string& format, const std::string& input, } // Functions required to support absl::Time flags. +bool AbslParseFlag(absl::string_view text, absl::Time* t, std::string* error) { + return absl::ParseTime(RFC3339_full, std::string(text), absl::UTCTimeZone(), + t, error); +} + +std::string AbslUnparseFlag(absl::Time t) { + return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone()); +} bool ParseFlag(const std::string& text, absl::Time* t, std::string* error) { return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error); } diff --git a/absl/time/internal/cctz/src/time_zone_impl.cc b/absl/time/internal/cctz/src/time_zone_impl.cc index a26151d3..a241e951 100644 --- a/absl/time/internal/cctz/src/time_zone_impl.cc +++ b/absl/time/internal/cctz/src/time_zone_impl.cc @@ -14,6 +14,7 @@ #include "time_zone_impl.h" +#include #include #include #include @@ -91,8 +92,14 @@ bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) { void time_zone::Impl::ClearTimeZoneMapTestOnly() { std::lock_guard lock(TimeZoneMutex()); if (time_zone_map != nullptr) { - // Existing time_zone::Impl* entries are in the wild, so we simply - // leak them. Future requests will result in reloading the data. + // Existing time_zone::Impl* entries are in the wild, so we can't delete + // them. Instead, we move them to a private container, where they are + // logically unreachable but not "leaked". Future requests will result + // in reloading the data. + static auto* cleared = new std::deque; + for (const auto& element : *time_zone_map) { + cleared->push_back(element.second); + } time_zone_map->clear(); } } diff --git a/absl/time/time.cc b/absl/time/time.cc index 6a387bce..60382be7 100644 --- a/absl/time/time.cc +++ b/absl/time/time.cc @@ -430,9 +430,17 @@ absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour, } absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) { - const CivilSecond cs(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, - tm.tm_hour, tm.tm_min, tm.tm_sec); - const auto ti = tz.At(cs); + civil_year_t tm_year = tm.tm_year; + // Avoids years that are too extreme for CivilSecond to normalize. + if (tm_year > 300000000000ll) return InfiniteFuture(); + if (tm_year < -300000000000ll) return InfinitePast(); + int tm_mon = tm.tm_mon; + if (tm_mon == std::numeric_limits::max()) { + tm_mon -= 12; + tm_year += 1; + } + const auto ti = tz.At(CivilSecond(tm_year + 1900, tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec)); return tm.tm_isdst == 0 ? ti.post : ti.pre; } diff --git a/absl/time/time.h b/absl/time/time.h index 9c8f3177..0b7312ee 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -83,6 +83,7 @@ struct timeval; #include #include +#include "absl/base/macros.h" #include "absl/strings/string_view.h" #include "absl/time/civil_time.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" @@ -545,7 +546,11 @@ bool ParseDuration(const std::string& dur_string, Duration* d); // Support for flag values of type Duration. Duration flags must be specified // in a format that is valid input for absl::ParseDuration(). +bool AbslParseFlag(absl::string_view text, Duration* dst, std::string* error); +std::string AbslUnparseFlag(Duration d); +ABSL_DEPRECATED("Use AbslParseFlag() instead.") bool ParseFlag(const std::string& text, Duration* dst, std::string* error); +ABSL_DEPRECATED("Use AbslUnparseFlag() instead.") std::string UnparseFlag(Duration d); // Time @@ -815,7 +820,11 @@ std::chrono::system_clock::time_point ToChronoTime(Time); // Additionally, if you'd like to specify a time as a count of // seconds/milliseconds/etc from the Unix epoch, use an absl::Duration flag // and add that duration to absl::UnixEpoch() to get an absl::Time. +bool AbslParseFlag(absl::string_view text, Time* t, std::string* error); +std::string AbslUnparseFlag(Time t); +ABSL_DEPRECATED("Use AbslParseFlag() instead.") bool ParseFlag(const std::string& text, Time* t, std::string* error); +ABSL_DEPRECATED("Use AbslUnparseFlag() instead.") std::string UnparseFlag(Time t); // TimeZone diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc index 37af39d9..9c4709e6 100644 --- a/absl/time/time_test.cc +++ b/absl/time/time_test.cc @@ -795,6 +795,30 @@ TEST(Time, FromTM) { tm.tm_isdst = 1; t = FromTM(tm, nyc); EXPECT_EQ("2014-03-09T03:30:42-04:00", absl::FormatTime(t, nyc)); // DST + + // Adjusts tm to refer to a time with a year larger than 2147483647. + tm.tm_year = 2147483647 - 1900 + 1; + tm.tm_mon = 6 - 1; + tm.tm_mday = 28; + tm.tm_hour = 1; + tm.tm_min = 2; + tm.tm_sec = 3; + tm.tm_isdst = -1; + t = FromTM(tm, absl::UTCTimeZone()); + EXPECT_EQ("2147483648-06-28T01:02:03+00:00", + absl::FormatTime(t, absl::UTCTimeZone())); + + // Adjusts tm to refer to a time with a very large month. + tm.tm_year = 2019 - 1900; + tm.tm_mon = 2147483647; + tm.tm_mday = 28; + tm.tm_hour = 1; + tm.tm_min = 2; + tm.tm_sec = 3; + tm.tm_isdst = -1; + t = FromTM(tm, absl::UTCTimeZone()); + EXPECT_EQ("178958989-08-28T01:02:03+00:00", + absl::FormatTime(t, absl::UTCTimeZone())); } TEST(Time, TMRoundTrip) { -- cgit v1.2.3 From 2103fd9acdf58279f739860bff3f8c9f4b845605 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 18 Nov 2019 11:02:26 -0800 Subject: Export of internal Abseil changes -- d447fdcb801036cf08197eece193a5a706661120 by Gennadiy Rozental : Eliminate the need for static function holding help message. This decreases the cost of ABSL_FLAG abstraction by 120 bytes under clang. PiperOrigin-RevId: 281107806 -- 0aa6b91189f0e8b2381438c33465673a7ae02487 by Derek Mauro : Disable the weak symbol CCTZ extension in the time test_util on MinGW, which does not support it. PiperOrigin-RevId: 280719769 -- 67322c41c3e776eb541de90fa4526bdb49422eb6 by Abseil Team : Tune PeriodicSampler implementation (for internal-use only) PiperOrigin-RevId: 280708943 -- 3a48c346340c7ed03816645cd327e1ff07729aa4 by Abseil Team : Clean up public headers not to have warnings for "-Wcomma" PiperOrigin-RevId: 280695373 -- 981acd1ef3b13a83a84f04f11c8931f4ed4451c9 by Matthew Brown : Release absl::int128. PiperOrigin-RevId: 280690817 -- d30fae9d2ec30b81322d2eb5afe7e13e45b4b422 by Derek Mauro : Fix -Wundef warnings in random platform detection PiperOrigin-RevId: 280669598 GitOrigin-RevId: d447fdcb801036cf08197eece193a5a706661120 Change-Id: Ie5e10e567c54b7de211833607689f233d4ddf734 --- absl/base/internal/bits.h | 35 +- absl/base/internal/periodic_sampler.cc | 6 +- absl/base/internal/periodic_sampler.h | 62 +- absl/flags/flag.h | 57 +- absl/flags/flag_test.cc | 17 +- absl/flags/internal/commandlineflag.cc | 7 - absl/flags/internal/commandlineflag.h | 47 +- absl/flags/internal/flag.cc | 5 + absl/flags/internal/flag.h | 89 ++- absl/flags/internal/registry.cc | 6 +- absl/numeric/int128.cc | 129 ++++ absl/numeric/int128.h | 363 ++++++++++- absl/numeric/int128_have_intrinsic.inc | 284 +++++++++ absl/numeric/int128_no_intrinsic.inc | 290 +++++++++ absl/numeric/int128_stream_test.cc | 729 ++++++++++++++++++++++ absl/numeric/int128_test.cc | 743 +++++++++++++++++++++++ absl/random/internal/platform.h | 3 +- absl/strings/internal/str_format/arg.cc | 12 + absl/strings/internal/str_format/arg.h | 4 + absl/strings/internal/str_format/convert_test.cc | 37 +- absl/strings/string_view.h | 5 +- absl/time/internal/test_util.cc | 3 + absl/time/time.h | 3 +- 23 files changed, 2800 insertions(+), 136 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/base/internal/bits.h b/absl/base/internal/bits.h index b0780f2d..450b923f 100644 --- a/absl/base/internal/bits.h +++ b/absl/base/internal/bits.h @@ -50,10 +50,22 @@ namespace base_internal { ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64Slow(uint64_t n) { int zeroes = 60; - if (n >> 32) zeroes -= 32, n >>= 32; - if (n >> 16) zeroes -= 16, n >>= 16; - if (n >> 8) zeroes -= 8, n >>= 8; - if (n >> 4) zeroes -= 4, n >>= 4; + if (n >> 32) { + zeroes -= 32; + n >>= 32; + } + if (n >> 16) { + zeroes -= 16; + n >>= 16; + } + if (n >> 8) { + zeroes -= 8; + n >>= 8; + } + if (n >> 4) { + zeroes -= 4; + n >>= 4; + } return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes; } @@ -95,9 +107,18 @@ ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64(uint64_t n) { ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32Slow(uint64_t n) { int zeroes = 28; - if (n >> 16) zeroes -= 16, n >>= 16; - if (n >> 8) zeroes -= 8, n >>= 8; - if (n >> 4) zeroes -= 4, n >>= 4; + if (n >> 16) { + zeroes -= 16; + n >>= 16; + } + if (n >> 8) { + zeroes -= 8; + n >>= 8; + } + if (n >> 4) { + zeroes -= 4; + n >>= 4; + } return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes; } diff --git a/absl/base/internal/periodic_sampler.cc b/absl/base/internal/periodic_sampler.cc index 439745d0..69656c8a 100644 --- a/absl/base/internal/periodic_sampler.cc +++ b/absl/base/internal/periodic_sampler.cc @@ -36,13 +36,13 @@ bool PeriodicSamplerBase::SubtleConfirmSample() noexcept { // Check if this is the first call to Sample() if (ABSL_PREDICT_FALSE(stride_ == 1)) { - stride_ = -1 - GetExponentialBiased(current_period); - if (stride_ < -1) { + stride_ = static_cast(-1 - GetExponentialBiased(current_period)); + if (static_cast(stride_) < -1) { ++stride_; return false; } } - stride_ = -1 - GetExponentialBiased(current_period); + stride_ = static_cast(-1 - GetExponentialBiased(current_period)); return true; } diff --git a/absl/base/internal/periodic_sampler.h b/absl/base/internal/periodic_sampler.h index 2c0600f0..23879742 100644 --- a/absl/base/internal/periodic_sampler.h +++ b/absl/base/internal/periodic_sampler.h @@ -111,33 +111,49 @@ class PeriodicSamplerBase { // Returns the current period of this sampler. Thread-safe. virtual int period() const noexcept = 0; - int64_t stride_ = 0; + // Keep and decrement stride_ as an unsigned integer, but compare the value + // to zero casted as a signed int. clang and msvc do not create optimum code + // if we use signed for the combined decrement and sign comparison. + // + // Below 3 alternative options, all compiles generate the best code + // using the unsigned increment <---> signed int comparison option. + // + // Option 1: + // int64_t stride_; + // if (ABSL_PREDICT_TRUE(++stride_ < 0)) { ... } + // + // GCC x64 (OK) : https://gcc.godbolt.org/z/R5MzzA + // GCC ppc (OK) : https://gcc.godbolt.org/z/z7NZAt + // Clang x64 (BAD): https://gcc.godbolt.org/z/t4gPsd + // ICC x64 (OK) : https://gcc.godbolt.org/z/rE6s8W + // MSVC x64 (OK) : https://gcc.godbolt.org/z/ARMXqS + // + // Option 2: + // int64_t stride_ = 0; + // if (ABSL_PREDICT_TRUE(--stride_ >= 0)) { ... } + // + // GCC x64 (OK) : https://gcc.godbolt.org/z/jSQxYK + // GCC ppc (OK) : https://gcc.godbolt.org/z/VJdYaA + // Clang x64 (BAD): https://gcc.godbolt.org/z/Xm4NjX + // ICC x64 (OK) : https://gcc.godbolt.org/z/4snaFd + // MSVC x64 (BAD): https://gcc.godbolt.org/z/BgnEKE + // + // Option 3: + // uint64_t stride_; + // if (ABSL_PREDICT_TRUE(static_cast(++stride_) < 0)) { ... } + // + // GCC x64 (OK) : https://gcc.godbolt.org/z/bFbfPy + // GCC ppc (OK) : https://gcc.godbolt.org/z/S9KkUE + // Clang x64 (OK) : https://gcc.godbolt.org/z/UYzRb4 + // ICC x64 (OK) : https://gcc.godbolt.org/z/ptTNfD + // MSVC x64 (OK) : https://gcc.godbolt.org/z/76j4-5 + uint64_t stride_ = 0; ExponentialBiased rng_; }; inline bool PeriodicSamplerBase::SubtleMaybeSample() noexcept { - // We explicitly count up and not down, as the compiler does not generate - // ideal code for counting down. See also https://gcc.godbolt.org/z/FTPDSM - // - // With `if (ABSL_PREDICT_FALSE(++stride_ < 0))` - // add QWORD PTR fs:sampler@tpoff+8, 1 - // jns .L15 - // ret - // - // With `if (ABSL_PREDICT_FALSE(--stride_ > 0))` - // mov rax, QWORD PTR fs:sampler@tpoff+8 - // sub rax, 1 - // mov QWORD PTR fs:sampler@tpoff+8, rax - // test rax, rax - // jle .L15 - // ret - // add QWORD PTR fs:sampler@tpoff+8, 1 - // jns .L15 - // ret - // - // --stride >= 0 does work, but makes our logic slightly harder as in that - // case we have less convenient zero-init and over-run values. - if (ABSL_PREDICT_FALSE(++stride_ < 0)) { + // See comments on `stride_` for the unsigned increment / signed compare. + if (ABSL_PREDICT_TRUE(static_cast(++stride_) < 0)) { return false; } return true; diff --git a/absl/flags/flag.h b/absl/flags/flag.h index 356ddb61..09af47a0 100644 --- a/absl/flags/flag.h +++ b/absl/flags/flag.h @@ -96,8 +96,7 @@ class Flag { constexpr Flag(const char* name, const flags_internal::HelpGenFunc help_gen, const char* filename, const flags_internal::FlagMarshallingOpFn marshalling_op, - const flags_internal::InitialValGenFunc initial_value_gen, - bool, void*) + const flags_internal::InitialValGenFunc initial_value_gen) : name_(name), help_gen_(help_gen), filename_(filename), @@ -115,8 +114,11 @@ class Flag { return impl_; } - impl_ = new flags_internal::Flag(name_, help_gen_, filename_, - marshalling_op_, initial_value_gen_); + impl_ = new flags_internal::Flag( + name_, + {flags_internal::FlagHelpSrc(help_gen_), + flags_internal::FlagHelpSrcKind::kGenFunc}, + filename_, marshalling_op_, initial_value_gen_); inited_.store(true, std::memory_order_release); } @@ -307,9 +309,19 @@ void SetFlag(absl::Flag* flag, const V& v) { #define ABSL_FLAG_IMPL_FLAGHELP(txt) txt #endif -#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt) \ - static std::string AbslFlagsWrapHelp##name() { \ - return ABSL_FLAG_IMPL_FLAGHELP(txt); \ +// AbslFlagHelpGenFor##name is used to encapsulate both immediate (method Const) +// and lazy (method NonConst) evaluation of help message expression. We choose +// 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 \ + 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); } \ } #define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \ @@ -326,29 +338,28 @@ void SetFlag(absl::Flag* flag, const V& v) { #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_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help); \ ABSL_CONST_INIT absl::Flag FLAGS_##name{ \ - ABSL_FLAG_IMPL_FLAGNAME(#name), &AbslFlagsWrapHelp##name, \ + ABSL_FLAG_IMPL_FLAGNAME(#name), \ + absl::flags_internal::HelpArg(0), \ ABSL_FLAG_IMPL_FILENAME(), \ &absl::flags_internal::FlagMarshallingOps, \ &AbslFlagsInitFlag##name}; \ extern bool FLAGS_no##name; \ bool FLAGS_no##name = ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name) #else -// MSVC version uses aggregate initialization. -#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 FLAGS_##name{ \ - ABSL_FLAG_IMPL_FLAGNAME(#name), \ - &AbslFlagsWrapHelp##name, \ - ABSL_FLAG_IMPL_FILENAME(), \ - &absl::flags_internal::FlagMarshallingOps, \ - &AbslFlagsInitFlag##name, \ - false, \ - nullptr}; \ - extern bool FLAGS_no##name; \ +// 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 FLAGS_##name{ \ + ABSL_FLAG_IMPL_FLAGNAME(#name), &AbslFlagHelpGenFor##name::NonConst, \ + ABSL_FLAG_IMPL_FILENAME(), \ + &absl::flags_internal::FlagMarshallingOps, \ + &AbslFlagsInitFlag##name}; \ + extern bool FLAGS_no##name; \ bool FLAGS_no##name = ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name) #endif diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc index 59dc579c..4e08da85 100644 --- a/absl/flags/flag_test.cc +++ b/absl/flags/flag_test.cc @@ -32,7 +32,7 @@ namespace { namespace flags = absl::flags_internal; -std::string TestHelpMsg() { return "help"; } +std::string TestHelpMsg() { return "dynamic help"; } template void* TestMakeDflt() { return new T{}; @@ -41,19 +41,22 @@ void TestCallback() {} template bool TestConstructionFor() { - constexpr flags::Flag f1("f1", &TestHelpMsg, "file", + constexpr flags::HelpInitArg help_arg{flags::FlagHelpSrc("literal help"), + flags::FlagHelpSrcKind::kLiteral}; + constexpr flags::Flag f1("f1", help_arg, "file", &flags::FlagMarshallingOps, &TestMakeDflt); EXPECT_EQ(f1.Name(), "f1"); - EXPECT_EQ(f1.Help(), "help"); + EXPECT_EQ(f1.Help(), "literal help"); EXPECT_EQ(f1.Filename(), "file"); - ABSL_CONST_INIT static flags::Flag f2("f2", &TestHelpMsg, "file", - &flags::FlagMarshallingOps, - &TestMakeDflt); + ABSL_CONST_INIT static flags::Flag f2( + "f2", + {flags::FlagHelpSrc(&TestHelpMsg), flags::FlagHelpSrcKind::kGenFunc}, + "file", &flags::FlagMarshallingOps, &TestMakeDflt); flags::FlagRegistrar(&f2).OnUpdate(TestCallback); EXPECT_EQ(f2.Name(), "f2"); - EXPECT_EQ(f2.Help(), "help"); + EXPECT_EQ(f2.Help(), "dynamic help"); EXPECT_EQ(f2.Filename(), "file"); return true; diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc index caf33bc4..88f91e16 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 13a3352e..7964f1bf 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 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 061113d7..d087f79e 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 ce0ccf2d..d7990254 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 +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 +constexpr flags_internal::HelpInitArg HelpArg(int) { + return {flags_internal::FlagHelpSrc(T::Const()), + flags_internal::FlagHelpSrcKind::kLiteral}; +} + +template +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 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, marshalling_op, initial_value_gen) {} + : flags_internal::CommandLineFlag(name, filename), + impl_(&flags_internal::FlagOps, 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 ae7671a9..52d9f3c7 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; } diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc index 93b62c52..1eba09de 100644 --- a/absl/numeric/int128.cc +++ b/absl/numeric/int128.cc @@ -244,6 +244,111 @@ std::ostream& operator<<(std::ostream& os, uint128 v) { return os << rep; } +namespace { + +uint128 UnsignedAbsoluteValue(int128 v) { + // Cast to uint128 before possibly negating because -Int128Min() is undefined. + return Int128High64(v) < 0 ? -uint128(v) : uint128(v); +} + +} // namespace + +#if !defined(ABSL_HAVE_INTRINSIC_INT128) +namespace { + +template +int128 MakeInt128FromFloat(T v) { + // Conversion when v is NaN or cannot fit into int128 would be undefined + // behavior if using an intrinsic 128-bit integer. + assert(std::isfinite(v) && (std::numeric_limits::max_exponent <= 127 || + (v >= -std::ldexp(static_cast(1), 127) && + v < std::ldexp(static_cast(1), 127)))); + + // We must convert the absolute value and then negate as needed, because + // floating point types are typically sign-magnitude. Otherwise, the + // difference between the high and low 64 bits when interpreted as two's + // complement overwhelms the precision of the mantissa. + uint128 result = v < 0 ? -MakeUint128FromFloat(-v) : MakeUint128FromFloat(v); + return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)), + Uint128Low64(result)); +} + +} // namespace + +int128::int128(float v) : int128(MakeInt128FromFloat(v)) {} +int128::int128(double v) : int128(MakeInt128FromFloat(v)) {} +int128::int128(long double v) : int128(MakeInt128FromFloat(v)) {} + +int128 operator/(int128 lhs, int128 rhs) { + assert(lhs != Int128Min() || rhs != -1); // UB on two's complement. + + uint128 quotient = 0; + uint128 remainder = 0; + DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs), + "ient, &remainder); + if ((Int128High64(lhs) < 0) != (Int128High64(rhs) < 0)) quotient = -quotient; + return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(quotient)), + Uint128Low64(quotient)); +} + +int128 operator%(int128 lhs, int128 rhs) { + assert(lhs != Int128Min() || rhs != -1); // UB on two's complement. + + uint128 quotient = 0; + uint128 remainder = 0; + DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs), + "ient, &remainder); + if (Int128High64(lhs) < 0) remainder = -remainder; + return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(remainder)), + Uint128Low64(remainder)); +} +#endif // ABSL_HAVE_INTRINSIC_INT128 + +std::ostream& operator<<(std::ostream& os, int128 v) { + std::ios_base::fmtflags flags = os.flags(); + std::string rep; + + // Add the sign if needed. + bool print_as_decimal = + (flags & std::ios::basefield) == std::ios::dec || + (flags & std::ios::basefield) == std::ios_base::fmtflags(); + if (print_as_decimal) { + if (Int128High64(v) < 0) { + rep = "-"; + } else if (flags & std::ios::showpos) { + rep = "+"; + } + } + + rep.append(Uint128ToFormattedString( + print_as_decimal ? UnsignedAbsoluteValue(v) : uint128(v), os.flags())); + + // Add the requisite padding. + std::streamsize width = os.width(0); + if (static_cast(width) > rep.size()) { + switch (flags & std::ios::adjustfield) { + case std::ios::left: + rep.append(width - rep.size(), os.fill()); + break; + case std::ios::internal: + if (print_as_decimal && (rep[0] == '+' || rep[0] == '-')) { + rep.insert(1, width - rep.size(), os.fill()); + } else if ((flags & std::ios::basefield) == std::ios::hex && + (flags & std::ios::showbase) && v != 0) { + rep.insert(2, width - rep.size(), os.fill()); + } else { + rep.insert(0, width - rep.size(), os.fill()); + } + break; + default: // std::ios::right + rep.insert(0, width - rep.size(), os.fill()); + break; + } + } + + return os << rep; +} + } // namespace absl namespace std { @@ -270,4 +375,28 @@ constexpr int numeric_limits::max_exponent; constexpr int numeric_limits::max_exponent10; constexpr bool numeric_limits::traps; constexpr bool numeric_limits::tinyness_before; + +constexpr bool numeric_limits::is_specialized; +constexpr bool numeric_limits::is_signed; +constexpr bool numeric_limits::is_integer; +constexpr bool numeric_limits::is_exact; +constexpr bool numeric_limits::has_infinity; +constexpr bool numeric_limits::has_quiet_NaN; +constexpr bool numeric_limits::has_signaling_NaN; +constexpr float_denorm_style numeric_limits::has_denorm; +constexpr bool numeric_limits::has_denorm_loss; +constexpr float_round_style numeric_limits::round_style; +constexpr bool numeric_limits::is_iec559; +constexpr bool numeric_limits::is_bounded; +constexpr bool numeric_limits::is_modulo; +constexpr int numeric_limits::digits; +constexpr int numeric_limits::digits10; +constexpr int numeric_limits::max_digits10; +constexpr int numeric_limits::radix; +constexpr int numeric_limits::min_exponent; +constexpr int numeric_limits::min_exponent10; +constexpr int numeric_limits::max_exponent; +constexpr int numeric_limits::max_exponent10; +constexpr bool numeric_limits::traps; +constexpr bool numeric_limits::tinyness_before; } // namespace std diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h index 4f965686..50617612 100644 --- a/absl/numeric/int128.h +++ b/absl/numeric/int128.h @@ -17,10 +17,7 @@ // File: int128.h // ----------------------------------------------------------------------------- // -// This header file defines 128-bit integer types. -// -// Currently, this file defines `uint128`, an unsigned 128-bit integer; -// a signed 128-bit integer is forthcoming. +// This header file defines 128-bit integer types, `uint128` and `int128`. #ifndef ABSL_NUMERIC_INT128_H_ #define ABSL_NUMERIC_INT128_H_ @@ -53,6 +50,8 @@ namespace absl { +class int128; + // uint128 // // An unsigned 128-bit integer type. The API is meant to mimic an intrinsic type @@ -116,6 +115,7 @@ class constexpr uint128(__int128 v); // NOLINT(runtime/explicit) constexpr uint128(unsigned __int128 v); // NOLINT(runtime/explicit) #endif // ABSL_HAVE_INTRINSIC_INT128 + constexpr uint128(int128 v); // NOLINT(runtime/explicit) explicit uint128(float v); explicit uint128(double v); explicit uint128(long double v); @@ -131,6 +131,7 @@ class uint128& operator=(__int128 v); uint128& operator=(unsigned __int128 v); #endif // ABSL_HAVE_INTRINSIC_INT128 + uint128& operator=(int128 v); // Conversion operators to other arithmetic types constexpr explicit operator bool() const; @@ -291,7 +292,238 @@ class numeric_limits { }; } // namespace std -// TODO(absl-team): Implement signed 128-bit type +namespace absl { + +// int128 +// +// A signed 128-bit integer type. The API is meant to mimic an intrinsic +// integral type as closely as is practical, including exhibiting undefined +// behavior in analogous cases (e.g. division by zero). +// +// An `int128` supports the following: +// +// * Implicit construction from integral types +// * Explicit conversion to integral types +// +// However, an `int128` differs from intrinsic integral types in the following +// ways: +// +// * It is not implicitly convertible to other integral types. +// * Requires explicit construction from and conversion to floating point +// types. + +// Additionally, if your compiler supports `__int128`, `int128` is +// interoperable with that type. (Abseil checks for this compatibility through +// the `ABSL_HAVE_INTRINSIC_INT128` macro.) +// +// The design goal for `int128` is that it will be compatible with a future +// `int128_t`, if that type becomes a part of the standard. +// +// Example: +// +// float y = absl::int128(17); // Error. int128 cannot be implicitly +// // converted to float. +// +// absl::int128 v; +// int64_t i = v; // Error +// int64_t i = static_cast(v); // OK +// +class int128 { + public: + int128() = default; + + // Constructors from arithmetic types + constexpr int128(int v); // NOLINT(runtime/explicit) + constexpr int128(unsigned int v); // NOLINT(runtime/explicit) + constexpr int128(long v); // NOLINT(runtime/int) + constexpr int128(unsigned long v); // NOLINT(runtime/int) + constexpr int128(long long v); // NOLINT(runtime/int) + constexpr int128(unsigned long long v); // NOLINT(runtime/int) +#ifdef ABSL_HAVE_INTRINSIC_INT128 + constexpr int128(__int128 v); // NOLINT(runtime/explicit) + constexpr explicit int128(unsigned __int128 v); +#endif // ABSL_HAVE_INTRINSIC_INT128 + constexpr explicit int128(uint128 v); + explicit int128(float v); + explicit int128(double v); + explicit int128(long double v); + + // Assignment operators from arithmetic types + int128& operator=(int v); + int128& operator=(unsigned int v); + int128& operator=(long v); // NOLINT(runtime/int) + int128& operator=(unsigned long v); // NOLINT(runtime/int) + int128& operator=(long long v); // NOLINT(runtime/int) + int128& operator=(unsigned long long v); // NOLINT(runtime/int) +#ifdef ABSL_HAVE_INTRINSIC_INT128 + int128& operator=(__int128 v); +#endif // ABSL_HAVE_INTRINSIC_INT128 + + // Conversion operators to other arithmetic types + constexpr explicit operator bool() const; + constexpr explicit operator char() const; + constexpr explicit operator signed char() const; + constexpr explicit operator unsigned char() const; + constexpr explicit operator char16_t() const; + constexpr explicit operator char32_t() const; + constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const; + constexpr explicit operator short() const; // NOLINT(runtime/int) + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator unsigned short() const; + constexpr explicit operator int() const; + constexpr explicit operator unsigned int() const; + constexpr explicit operator long() const; // NOLINT(runtime/int) + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator unsigned long() const; + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator long long() const; + // NOLINTNEXTLINE(runtime/int) + constexpr explicit operator unsigned long long() const; +#ifdef ABSL_HAVE_INTRINSIC_INT128 + constexpr explicit operator __int128() const; + constexpr explicit operator unsigned __int128() const; +#endif // ABSL_HAVE_INTRINSIC_INT128 + explicit operator float() const; + explicit operator double() const; + explicit operator long double() const; + + // Trivial copy constructor, assignment operator and destructor. + + // Arithmetic operators + int128& operator+=(int128 other); + int128& operator-=(int128 other); + int128& operator*=(int128 other); + int128& operator/=(int128 other); + int128& operator%=(int128 other); + int128 operator++(int); // postfix increment: i++ + int128 operator--(int); // postfix decrement: i-- + int128& operator++(); // prefix increment: ++i + int128& operator--(); // prefix decrement: --i + int128& operator&=(int128 other); + int128& operator|=(int128 other); + int128& operator^=(int128 other); + int128& operator<<=(int amount); + int128& operator>>=(int amount); + + // Int128Low64() + // + // Returns the lower 64-bit value of a `int128` value. + friend constexpr uint64_t Int128Low64(int128 v); + + // Int128High64() + // + // Returns the higher 64-bit value of a `int128` value. + friend constexpr int64_t Int128High64(int128 v); + + // MakeInt128() + // + // Constructs a `int128` numeric value from two 64-bit integers. Note that + // signedness is conveyed in the upper `high` value. + // + // (absl::int128(1) << 64) * high + low + // + // Note that this factory function is the only way to construct a `int128` + // from integer values greater than 2^64 or less than -2^64. + // + // Example: + // + // absl::int128 big = absl::MakeInt128(1, 0); + // absl::int128 big_n = absl::MakeInt128(-1, 0); + friend constexpr int128 MakeInt128(int64_t high, uint64_t low); + + // Int128Max() + // + // Returns the maximum value for a 128-bit signed integer. + friend constexpr int128 Int128Max(); + + // Int128Min() + // + // Returns the minimum value for a 128-bit signed integer. + friend constexpr int128 Int128Min(); + + // Support for absl::Hash. + template + friend H AbslHashValue(H h, int128 v) { + return H::combine(std::move(h), Int128High64(v), Int128Low64(v)); + } + + private: + constexpr int128(int64_t high, uint64_t low); + +#if defined(ABSL_HAVE_INTRINSIC_INT128) + __int128 v_; +#else // ABSL_HAVE_INTRINSIC_INT128 +#if defined(ABSL_IS_LITTLE_ENDIAN) + uint64_t lo_; + int64_t hi_; +#elif defined(ABSL_IS_BIG_ENDIAN) + int64_t hi_; + uint64_t lo_; +#else // byte order +#error "Unsupported byte order: must be little-endian or big-endian." +#endif // byte order +#endif // ABSL_HAVE_INTRINSIC_INT128 +}; + +std::ostream& operator<<(std::ostream& os, int128 v); + +// TODO(absl-team) add operator>>(std::istream&, int128) + +constexpr int128 Int128Max() { + return int128((std::numeric_limits::max)(), + (std::numeric_limits::max)()); +} + +constexpr int128 Int128Min() { + return int128((std::numeric_limits::min)(), 0); +} + +} // namespace absl + +// Specialized numeric_limits for int128. +namespace std { +template <> +class numeric_limits { + public: + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + static constexpr float_round_style round_style = round_toward_zero; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 127; + static constexpr int digits10 = 38; + static constexpr int max_digits10 = 0; + static constexpr int radix = 2; + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; +#ifdef ABSL_HAVE_INTRINSIC_INT128 + static constexpr bool traps = numeric_limits<__int128>::traps; +#else // ABSL_HAVE_INTRINSIC_INT128 + static constexpr bool traps = numeric_limits::traps; +#endif // ABSL_HAVE_INTRINSIC_INT128 + static constexpr bool tinyness_before = false; + + static constexpr absl::int128 (min)() { return absl::Int128Min(); } + static constexpr absl::int128 lowest() { return absl::Int128Min(); } + static constexpr absl::int128 (max)() { return absl::Int128Max(); } + static constexpr absl::int128 epsilon() { return 0; } + static constexpr absl::int128 round_error() { return 0; } + static constexpr absl::int128 infinity() { return 0; } + static constexpr absl::int128 quiet_NaN() { return 0; } + static constexpr absl::int128 signaling_NaN() { return 0; } + static constexpr absl::int128 denorm_min() { return 0; } +}; +} // namespace std // -------------------------------------------------------------------------- // Implementation details follow @@ -339,6 +571,10 @@ inline uint128& uint128::operator=(unsigned __int128 v) { } #endif // ABSL_HAVE_INTRINSIC_INT128 +inline uint128& uint128::operator=(int128 v) { + return *this = uint128(v); +} + // Arithmetic operators. uint128 operator<<(uint128 lhs, int amount); @@ -420,6 +656,9 @@ constexpr uint128::uint128(unsigned __int128 v) hi_{static_cast(v >> 64)} {} #endif // ABSL_HAVE_INTRINSIC_INT128 +constexpr uint128::uint128(int128 v) + : lo_{Int128Low64(v)}, hi_{static_cast(Int128High64(v))} {} + #elif defined(ABSL_IS_BIG_ENDIAN) constexpr uint128::uint128(uint64_t high, uint64_t low) @@ -450,6 +689,9 @@ constexpr uint128::uint128(unsigned __int128 v) lo_{static_cast(v & ~uint64_t{0})} {} #endif // ABSL_HAVE_INTRINSIC_INT128 +constexpr uint128::uint128(int128 v) + : hi_{static_cast(Int128High64(v))}, lo_{Int128Low64(v)} {} + #else // byte order #error "Unsupported byte order: must be little-endian or big-endian." #endif // byte order @@ -719,6 +961,117 @@ inline uint128& uint128::operator--() { return *this; } +constexpr int128 MakeInt128(int64_t high, uint64_t low) { + return int128(high, low); +} + +// Assignment from integer types. +inline int128& int128::operator=(int v) { + return *this = int128(v); +} + +inline int128& int128::operator=(unsigned int v) { + return *this = int128(v); +} + +inline int128& int128::operator=(long v) { // NOLINT(runtime/int) + return *this = int128(v); +} + +// NOLINTNEXTLINE(runtime/int) +inline int128& int128::operator=(unsigned long v) { + return *this = int128(v); +} + +// NOLINTNEXTLINE(runtime/int) +inline int128& int128::operator=(long long v) { + return *this = int128(v); +} + +// NOLINTNEXTLINE(runtime/int) +inline int128& int128::operator=(unsigned long long v) { + return *this = int128(v); +} + +// Arithmetic operators. + +int128 operator+(int128 lhs, int128 rhs); +int128 operator-(int128 lhs, int128 rhs); +int128 operator*(int128 lhs, int128 rhs); +int128 operator/(int128 lhs, int128 rhs); +int128 operator%(int128 lhs, int128 rhs); +int128 operator|(int128 lhs, int128 rhs); +int128 operator&(int128 lhs, int128 rhs); +int128 operator^(int128 lhs, int128 rhs); +int128 operator<<(int128 lhs, int amount); +int128 operator>>(int128 lhs, int amount); + +inline int128& int128::operator+=(int128 other) { + *this = *this + other; + return *this; +} + +inline int128& int128::operator-=(int128 other) { + *this = *this - other; + return *this; +} + +inline int128& int128::operator*=(int128 other) { + *this = *this * other; + return *this; +} + +inline int128& int128::operator/=(int128 other) { + *this = *this / other; + return *this; +} + +inline int128& int128::operator%=(int128 other) { + *this = *this % other; + return *this; +} + +inline int128& int128::operator|=(int128 other) { + *this = *this | other; + return *this; +} + +inline int128& int128::operator&=(int128 other) { + *this = *this & other; + return *this; +} + +inline int128& int128::operator^=(int128 other) { + *this = *this ^ other; + return *this; +} + +inline int128& int128::operator<<=(int amount) { + *this = *this << amount; + return *this; +} + +inline int128& int128::operator>>=(int amount) { + *this = *this >> amount; + return *this; +} + +namespace int128_internal { + +// Casts from unsigned to signed while preserving the underlying binary +// representation. +constexpr int64_t BitCastToSigned(uint64_t v) { + // Casting an unsigned integer to a signed integer of the same + // width is implementation defined behavior if the source value would not fit + // in the destination type. We step around it with a roundtrip bitwise not + // operation to make sure this function remains constexpr. Clang, GCC, and + // MSVC optimize this to a no-op on x86-64. + return v & (uint64_t{1} << 63) ? ~static_cast(~v) + : static_cast(v); +} + +} // namespace int128_internal + #if defined(ABSL_HAVE_INTRINSIC_INT128) #include "absl/numeric/int128_have_intrinsic.inc" // IWYU pragma: export #else // ABSL_HAVE_INTRINSIC_INT128 diff --git a/absl/numeric/int128_have_intrinsic.inc b/absl/numeric/int128_have_intrinsic.inc index c7ea6834..d6c76dd3 100644 --- a/absl/numeric/int128_have_intrinsic.inc +++ b/absl/numeric/int128_have_intrinsic.inc @@ -16,3 +16,287 @@ // This file contains :int128 implementation details that depend on internal // representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is // included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined. + +namespace int128_internal { + +// Casts from unsigned to signed while preserving the underlying binary +// representation. +constexpr __int128 BitCastToSigned(unsigned __int128 v) { + // Casting an unsigned integer to a signed integer of the same + // width is implementation defined behavior if the source value would not fit + // in the destination type. We step around it with a roundtrip bitwise not + // operation to make sure this function remains constexpr. Clang and GCC + // optimize this to a no-op on x86-64. + return v & (static_cast(1) << 127) + ? ~static_cast<__int128>(~v) + : static_cast<__int128>(v); +} + +} // namespace int128_internal + +inline int128& int128::operator=(__int128 v) { + v_ = v; + return *this; +} + +constexpr uint64_t Int128Low64(int128 v) { + return static_cast(v.v_ & ~uint64_t{0}); +} + +constexpr int64_t Int128High64(int128 v) { + // Initially cast to unsigned to prevent a right shift on a negative value. + return int128_internal::BitCastToSigned( + static_cast(static_cast(v.v_) >> 64)); +} + +constexpr int128::int128(int64_t high, uint64_t low) + // Initially cast to unsigned to prevent a left shift that overflows. + : v_(int128_internal::BitCastToSigned(static_cast(high) + << 64) | + low) {} + + +constexpr int128::int128(int v) : v_{v} {} + +constexpr int128::int128(long v) : v_{v} {} // NOLINT(runtime/int) + +constexpr int128::int128(long long v) : v_{v} {} // NOLINT(runtime/int) + +constexpr int128::int128(__int128 v) : v_{v} {} + +constexpr int128::int128(unsigned int v) : v_{v} {} + +constexpr int128::int128(unsigned long v) : v_{v} {} // NOLINT(runtime/int) + +// NOLINTNEXTLINE(runtime/int) +constexpr int128::int128(unsigned long long v) : v_{v} {} + +constexpr int128::int128(unsigned __int128 v) : v_{static_cast<__int128>(v)} {} + +inline int128::int128(float v) { + v_ = static_cast<__int128>(v); +} + +inline int128::int128(double v) { + v_ = static_cast<__int128>(v); +} + +inline int128::int128(long double v) { + v_ = static_cast<__int128>(v); +} + +constexpr int128::int128(uint128 v) : v_{static_cast<__int128>(v)} {} + +constexpr int128::operator bool() const { return static_cast(v_); } + +constexpr int128::operator char() const { return static_cast(v_); } + +constexpr int128::operator signed char() const { + return static_cast(v_); +} + +constexpr int128::operator unsigned char() const { + return static_cast(v_); +} + +constexpr int128::operator char16_t() const { + return static_cast(v_); +} + +constexpr int128::operator char32_t() const { + return static_cast(v_); +} + +constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const { + return static_cast(v_); +} + +constexpr int128::operator short() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator unsigned short() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator int() const { + return static_cast(v_); +} + +constexpr int128::operator unsigned int() const { + return static_cast(v_); +} + +constexpr int128::operator long() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator unsigned long() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator long long() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int) + return static_cast(v_); // NOLINT(runtime/int) +} + +constexpr int128::operator __int128() const { return v_; } + +constexpr int128::operator unsigned __int128() const { + return static_cast(v_); +} + +// Clang on PowerPC sometimes produces incorrect __int128 to floating point +// conversions. In that case, we do the conversion with a similar implementation +// to the conversion operators in int128_no_intrinsic.inc. +#if defined(__clang__) && !defined(__ppc64__) +inline int128::operator float() const { return static_cast(v_); } + +inline int128::operator double () const { return static_cast(v_); } + +inline int128::operator long double() const { + return static_cast(v_); +} + +#else // Clang on PowerPC +// Forward declaration for conversion operators to floating point types. +int128 operator-(int128 v); +bool operator!=(int128 lhs, int128 rhs); + +inline int128::operator float() const { + // We must convert the absolute value and then negate as needed, because + // floating point types are typically sign-magnitude. Otherwise, the + // difference between the high and low 64 bits when interpreted as two's + // complement overwhelms the precision of the mantissa. + // + // Also check to make sure we don't negate Int128Min() + return v_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(Int128Low64(*this)) + + std::ldexp(static_cast(Int128High64(*this)), 64); +} + +inline int128::operator double() const { + // See comment in int128::operator float() above. + return v_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(Int128Low64(*this)) + + std::ldexp(static_cast(Int128High64(*this)), 64); +} + +inline int128::operator long double() const { + // See comment in int128::operator float() above. + return v_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(Int128Low64(*this)) + + std::ldexp(static_cast(Int128High64(*this)), + 64); +} +#endif // Clang on PowerPC + +// Comparison operators. + +inline bool operator==(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) == static_cast<__int128>(rhs); +} + +inline bool operator!=(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) != static_cast<__int128>(rhs); +} + +inline bool operator<(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) < static_cast<__int128>(rhs); +} + +inline bool operator>(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) > static_cast<__int128>(rhs); +} + +inline bool operator<=(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) <= static_cast<__int128>(rhs); +} + +inline bool operator>=(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) >= static_cast<__int128>(rhs); +} + +// Unary operators. + +inline int128 operator-(int128 v) { + return -static_cast<__int128>(v); +} + +inline bool operator!(int128 v) { + return !static_cast<__int128>(v); +} + +inline int128 operator~(int128 val) { + return ~static_cast<__int128>(val); +} + +// Arithmetic operators. + +inline int128 operator+(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) + static_cast<__int128>(rhs); +} + +inline int128 operator-(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) - static_cast<__int128>(rhs); +} + +inline int128 operator*(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) * static_cast<__int128>(rhs); +} + +inline int128 operator/(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) / static_cast<__int128>(rhs); +} + +inline int128 operator%(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) % static_cast<__int128>(rhs); +} + +inline int128 int128::operator++(int) { + int128 tmp(*this); + ++v_; + return tmp; +} + +inline int128 int128::operator--(int) { + int128 tmp(*this); + --v_; + return tmp; +} + +inline int128& int128::operator++() { + ++v_; + return *this; +} + +inline int128& int128::operator--() { + --v_; + return *this; +} + +inline int128 operator|(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) | static_cast<__int128>(rhs); +} + +inline int128 operator&(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) & static_cast<__int128>(rhs); +} + +inline int128 operator^(int128 lhs, int128 rhs) { + return static_cast<__int128>(lhs) ^ static_cast<__int128>(rhs); +} + +inline int128 operator<<(int128 lhs, int amount) { + return static_cast<__int128>(lhs) << amount; +} + +inline int128 operator>>(int128 lhs, int amount) { + return static_cast<__int128>(lhs) >> amount; +} diff --git a/absl/numeric/int128_no_intrinsic.inc b/absl/numeric/int128_no_intrinsic.inc index 046cb9b3..c753771a 100644 --- a/absl/numeric/int128_no_intrinsic.inc +++ b/absl/numeric/int128_no_intrinsic.inc @@ -16,3 +16,293 @@ // This file contains :int128 implementation details that depend on internal // representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file // is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined. + +constexpr uint64_t Int128Low64(int128 v) { return v.lo_; } + +constexpr int64_t Int128High64(int128 v) { return v.hi_; } + +#if defined(ABSL_IS_LITTLE_ENDIAN) + +constexpr int128::int128(int64_t high, uint64_t low) : + lo_(low), hi_(high) {} + +constexpr int128::int128(int v) + : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} +constexpr int128::int128(long v) // NOLINT(runtime/int) + : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} +constexpr int128::int128(long long v) // NOLINT(runtime/int) + : lo_{static_cast(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {} + +constexpr int128::int128(unsigned int v) : lo_{v}, hi_{0} {} +// NOLINTNEXTLINE(runtime/int) +constexpr int128::int128(unsigned long v) : lo_{v}, hi_{0} {} +// NOLINTNEXTLINE(runtime/int) +constexpr int128::int128(unsigned long long v) : lo_{v}, hi_{0} {} + +constexpr int128::int128(uint128 v) + : lo_{Uint128Low64(v)}, hi_{static_cast(Uint128High64(v))} {} + +#elif defined(ABSL_IS_BIG_ENDIAN) + +constexpr int128::int128(int64_t high, uint64_t low) : + hi_{high}, lo_{low} {} + +constexpr int128::int128(int v) + : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} +constexpr int128::int128(long v) // NOLINT(runtime/int) + : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} +constexpr int128::int128(long long v) // NOLINT(runtime/int) + : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast(v)} {} + +constexpr int128::int128(unsigned int v) : hi_{0}, lo_{v} {} +// NOLINTNEXTLINE(runtime/int) +constexpr int128::int128(unsigned long v) : hi_{0}, lo_{v} {} +// NOLINTNEXTLINE(runtime/int) +constexpr int128::int128(unsigned long long v) : hi_{0}, lo_{v} {} + +constexpr int128::int128(uint128 v) + : hi_{static_cast(Uint128High64(v))}, lo_{Uint128Low64(v)} {} + +#else // byte order +#error "Unsupported byte order: must be little-endian or big-endian." +#endif // byte order + +constexpr int128::operator bool() const { return lo_ || hi_; } + +constexpr int128::operator char() const { + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator signed char() const { + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator unsigned char() const { + return static_cast(lo_); +} + +constexpr int128::operator char16_t() const { + return static_cast(lo_); +} + +constexpr int128::operator char32_t() const { + return static_cast(lo_); +} + +constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const { + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator short() const { // NOLINT(runtime/int) + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator unsigned short() const { // NOLINT(runtime/int) + return static_cast(lo_); // NOLINT(runtime/int) +} + +constexpr int128::operator int() const { + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator unsigned int() const { + return static_cast(lo_); +} + +constexpr int128::operator long() const { // NOLINT(runtime/int) + // NOLINTNEXTLINE(runtime/int) + return static_cast(static_cast(*this)); +} + +constexpr int128::operator unsigned long() const { // NOLINT(runtime/int) + return static_cast(lo_); // NOLINT(runtime/int) +} + +constexpr int128::operator long long() const { // NOLINT(runtime/int) + // We don't bother checking the value of hi_. If *this < 0, lo_'s high bit + // must be set in order for the value to fit into a long long. Conversely, if + // lo_'s high bit is set, *this must be < 0 for the value to fit. + return int128_internal::BitCastToSigned(lo_); +} + +constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int) + return static_cast(lo_); // NOLINT(runtime/int) +} + +// Forward declaration for conversion operators to floating point types. +int128 operator-(int128 v); +bool operator!=(int128 lhs, int128 rhs); + +inline int128::operator float() const { + // We must convert the absolute value and then negate as needed, because + // floating point types are typically sign-magnitude. Otherwise, the + // difference between the high and low 64 bits when interpreted as two's + // complement overwhelms the precision of the mantissa. + // + // Also check to make sure we don't negate Int128Min() + return hi_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(lo_) + + std::ldexp(static_cast(hi_), 64); +} + +inline int128::operator double() const { + // See comment in int128::operator float() above. + return hi_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(lo_) + + std::ldexp(static_cast(hi_), 64); +} + +inline int128::operator long double() const { + // See comment in int128::operator float() above. + return hi_ < 0 && *this != Int128Min() + ? -static_cast(-*this) + : static_cast(lo_) + + std::ldexp(static_cast(hi_), 64); +} + +// Comparison operators. + +inline bool operator==(int128 lhs, int128 rhs) { + return (Int128Low64(lhs) == Int128Low64(rhs) && + Int128High64(lhs) == Int128High64(rhs)); +} + +inline bool operator!=(int128 lhs, int128 rhs) { + return !(lhs == rhs); +} + +inline bool operator<(int128 lhs, int128 rhs) { + return (Int128High64(lhs) == Int128High64(rhs)) + ? (Int128Low64(lhs) < Int128Low64(rhs)) + : (Int128High64(lhs) < Int128High64(rhs)); +} + +inline bool operator>(int128 lhs, int128 rhs) { + return (Int128High64(lhs) == Int128High64(rhs)) + ? (Int128Low64(lhs) > Int128Low64(rhs)) + : (Int128High64(lhs) > Int128High64(rhs)); +} + +inline bool operator<=(int128 lhs, int128 rhs) { + return !(lhs > rhs); +} + +inline bool operator>=(int128 lhs, int128 rhs) { + return !(lhs < rhs); +} + +// Unary operators. + +inline int128 operator-(int128 v) { + int64_t hi = ~Int128High64(v); + uint64_t lo = ~Int128Low64(v) + 1; + if (lo == 0) ++hi; // carry + return MakeInt128(hi, lo); +} + +inline bool operator!(int128 v) { + return !Int128Low64(v) && !Int128High64(v); +} + +inline int128 operator~(int128 val) { + return MakeInt128(~Int128High64(val), ~Int128Low64(val)); +} + +// Arithmetic operators. + +inline int128 operator+(int128 lhs, int128 rhs) { + int128 result = MakeInt128(Int128High64(lhs) + Int128High64(rhs), + Int128Low64(lhs) + Int128Low64(rhs)); + if (Int128Low64(result) < Int128Low64(lhs)) { // check for carry + return MakeInt128(Int128High64(result) + 1, Int128Low64(result)); + } + return result; +} + +inline int128 operator-(int128 lhs, int128 rhs) { + int128 result = MakeInt128(Int128High64(lhs) - Int128High64(rhs), + Int128Low64(lhs) - Int128Low64(rhs)); + if (Int128Low64(lhs) < Int128Low64(rhs)) { // check for carry + return MakeInt128(Int128High64(result) - 1, Int128Low64(result)); + } + return result; +} + +inline int128 operator*(int128 lhs, int128 rhs) { + uint128 result = uint128(lhs) * rhs; + return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)), + Uint128Low64(result)); +} + +inline int128 int128::operator++(int) { + int128 tmp(*this); + *this += 1; + return tmp; +} + +inline int128 int128::operator--(int) { + int128 tmp(*this); + *this -= 1; + return tmp; +} + +inline int128& int128::operator++() { + *this += 1; + return *this; +} + +inline int128& int128::operator--() { + *this -= 1; + return *this; +} + +inline int128 operator|(int128 lhs, int128 rhs) { + return MakeInt128(Int128High64(lhs) | Int128High64(rhs), + Int128Low64(lhs) | Int128Low64(rhs)); +} + +inline int128 operator&(int128 lhs, int128 rhs) { + return MakeInt128(Int128High64(lhs) & Int128High64(rhs), + Int128Low64(lhs) & Int128Low64(rhs)); +} + +inline int128 operator^(int128 lhs, int128 rhs) { + return MakeInt128(Int128High64(lhs) ^ Int128High64(rhs), + Int128Low64(lhs) ^ Int128Low64(rhs)); +} + +inline int128 operator<<(int128 lhs, int amount) { + // uint64_t shifts of >= 64 are undefined, so we need some special-casing. + if (amount < 64) { + if (amount != 0) { + return MakeInt128( + (Int128High64(lhs) << amount) | + static_cast(Int128Low64(lhs) >> (64 - amount)), + Int128Low64(lhs) << amount); + } + return lhs; + } + return MakeInt128(static_cast(Int128Low64(lhs) << (amount - 64)), 0); +} + +inline int128 operator>>(int128 lhs, int amount) { + // uint64_t shifts of >= 64 are undefined, so we need some special-casing. + if (amount < 64) { + if (amount != 0) { + return MakeInt128( + Int128High64(lhs) >> amount, + (Int128Low64(lhs) >> amount) | + (static_cast(Int128High64(lhs)) << (64 - amount))); + } + return lhs; + } + return MakeInt128(0, + static_cast(Int128High64(lhs) >> (amount - 64))); +} diff --git a/absl/numeric/int128_stream_test.cc b/absl/numeric/int128_stream_test.cc index 3cfa9dc1..479ad66c 100644 --- a/absl/numeric/int128_stream_test.cc +++ b/absl/numeric/int128_stream_test.cc @@ -147,6 +147,735 @@ TEST(Uint128, OStreamFormatTest) { } } +struct Int128TestCase { + absl::int128 value; + std::ios_base::fmtflags flags; + std::streamsize width; + const char* expected; +}; + +void CheckInt128Case(const Int128TestCase& test_case) { + std::ostringstream os; + os.flags(test_case.flags); + os.width(test_case.width); + os.fill(kFill); + os << test_case.value; + SCOPED_TRACE(StreamFormatToString(test_case.flags, test_case.width)); + EXPECT_EQ(test_case.expected, os.str()); +} + +TEST(Int128, OStreamValueTest) { + CheckInt128Case({1, kDec, /*width = */ 0, "1"}); + CheckInt128Case({1, kOct, /*width = */ 0, "1"}); + CheckInt128Case({1, kHex, /*width = */ 0, "1"}); + CheckInt128Case({9, kDec, /*width = */ 0, "9"}); + CheckInt128Case({9, kOct, /*width = */ 0, "11"}); + CheckInt128Case({9, kHex, /*width = */ 0, "9"}); + CheckInt128Case({12345, kDec, /*width = */ 0, "12345"}); + CheckInt128Case({12345, kOct, /*width = */ 0, "30071"}); + CheckInt128Case({12345, kHex, /*width = */ 0, "3039"}); + CheckInt128Case( + {0x8000000000000000, kDec, /*width = */ 0, "9223372036854775808"}); + CheckInt128Case( + {0x8000000000000000, kOct, /*width = */ 0, "1000000000000000000000"}); + CheckInt128Case( + {0x8000000000000000, kHex, /*width = */ 0, "8000000000000000"}); + CheckInt128Case({std::numeric_limits::max(), kDec, + /*width = */ 0, "18446744073709551615"}); + CheckInt128Case({std::numeric_limits::max(), kOct, + /*width = */ 0, "1777777777777777777777"}); + CheckInt128Case({std::numeric_limits::max(), kHex, + /*width = */ 0, "ffffffffffffffff"}); + CheckInt128Case( + {absl::MakeInt128(1, 0), kDec, /*width = */ 0, "18446744073709551616"}); + CheckInt128Case( + {absl::MakeInt128(1, 0), kOct, /*width = */ 0, "2000000000000000000000"}); + CheckInt128Case( + {absl::MakeInt128(1, 0), kHex, /*width = */ 0, "10000000000000000"}); + CheckInt128Case({absl::MakeInt128(std::numeric_limits::max(), + std::numeric_limits::max()), + std::ios::dec, /*width = */ 0, + "170141183460469231731687303715884105727"}); + CheckInt128Case({absl::MakeInt128(std::numeric_limits::max(), + std::numeric_limits::max()), + std::ios::oct, /*width = */ 0, + "1777777777777777777777777777777777777777777"}); + CheckInt128Case({absl::MakeInt128(std::numeric_limits::max(), + std::numeric_limits::max()), + std::ios::hex, /*width = */ 0, + "7fffffffffffffffffffffffffffffff"}); + CheckInt128Case({absl::MakeInt128(std::numeric_limits::min(), 0), + std::ios::dec, /*width = */ 0, + "-170141183460469231731687303715884105728"}); + CheckInt128Case({absl::MakeInt128(std::numeric_limits::min(), 0), + std::ios::oct, /*width = */ 0, + "2000000000000000000000000000000000000000000"}); + CheckInt128Case({absl::MakeInt128(std::numeric_limits::min(), 0), + std::ios::hex, /*width = */ 0, + "80000000000000000000000000000000"}); + CheckInt128Case({-1, std::ios::dec, /*width = */ 0, "-1"}); + CheckInt128Case({-1, std::ios::oct, /*width = */ 0, + "3777777777777777777777777777777777777777777"}); + CheckInt128Case( + {-1, std::ios::hex, /*width = */ 0, "ffffffffffffffffffffffffffffffff"}); + CheckInt128Case({-12345, std::ios::dec, /*width = */ 0, "-12345"}); + CheckInt128Case({-12345, std::ios::oct, /*width = */ 0, + "3777777777777777777777777777777777777747707"}); + CheckInt128Case({-12345, std::ios::hex, /*width = */ 0, + "ffffffffffffffffffffffffffffcfc7"}); +} + +std::vector GetInt128FormatCases(); +TEST(Int128, OStreamFormatTest) { + for (const Int128TestCase& test_case : GetInt128FormatCases()) { + CheckInt128Case(test_case); + } +} + +std::vector GetInt128FormatCases() { + return { + {0, std::ios_base::fmtflags(), /*width = */ 0, "0"}, + {0, std::ios_base::fmtflags(), /*width = */ 6, "_____0"}, + {0, kPos, /*width = */ 0, "+0"}, + {0, kPos, /*width = */ 6, "____+0"}, + {0, kBase, /*width = */ 0, "0"}, + {0, kBase, /*width = */ 6, "_____0"}, + {0, kBase | kPos, /*width = */ 0, "+0"}, + {0, kBase | kPos, /*width = */ 6, "____+0"}, + {0, kUpper, /*width = */ 0, "0"}, + {0, kUpper, /*width = */ 6, "_____0"}, + {0, kUpper | kPos, /*width = */ 0, "+0"}, + {0, kUpper | kPos, /*width = */ 6, "____+0"}, + {0, kUpper | kBase, /*width = */ 0, "0"}, + {0, kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kUpper | kBase | kPos, /*width = */ 0, "+0"}, + {0, kUpper | kBase | kPos, /*width = */ 6, "____+0"}, + {0, kLeft, /*width = */ 0, "0"}, + {0, kLeft, /*width = */ 6, "0_____"}, + {0, kLeft | kPos, /*width = */ 0, "+0"}, + {0, kLeft | kPos, /*width = */ 6, "+0____"}, + {0, kLeft | kBase, /*width = */ 0, "0"}, + {0, kLeft | kBase, /*width = */ 6, "0_____"}, + {0, kLeft | kBase | kPos, /*width = */ 0, "+0"}, + {0, kLeft | kBase | kPos, /*width = */ 6, "+0____"}, + {0, kLeft | kUpper, /*width = */ 0, "0"}, + {0, kLeft | kUpper, /*width = */ 6, "0_____"}, + {0, kLeft | kUpper | kPos, /*width = */ 0, "+0"}, + {0, kLeft | kUpper | kPos, /*width = */ 6, "+0____"}, + {0, kLeft | kUpper | kBase, /*width = */ 0, "0"}, + {0, kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, + {0, kLeft | kUpper | kBase | kPos, /*width = */ 0, "+0"}, + {0, kLeft | kUpper | kBase | kPos, /*width = */ 6, "+0____"}, + {0, kInt, /*width = */ 0, "0"}, + {0, kInt, /*width = */ 6, "_____0"}, + {0, kInt | kPos, /*width = */ 0, "+0"}, + {0, kInt | kPos, /*width = */ 6, "+____0"}, + {0, kInt | kBase, /*width = */ 0, "0"}, + {0, kInt | kBase, /*width = */ 6, "_____0"}, + {0, kInt | kBase | kPos, /*width = */ 0, "+0"}, + {0, kInt | kBase | kPos, /*width = */ 6, "+____0"}, + {0, kInt | kUpper, /*width = */ 0, "0"}, + {0, kInt | kUpper, /*width = */ 6, "_____0"}, + {0, kInt | kUpper | kPos, /*width = */ 0, "+0"}, + {0, kInt | kUpper | kPos, /*width = */ 6, "+____0"}, + {0, kInt | kUpper | kBase, /*width = */ 0, "0"}, + {0, kInt | kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kInt | kUpper | kBase | kPos, /*width = */ 0, "+0"}, + {0, kInt | kUpper | kBase | kPos, /*width = */ 6, "+____0"}, + {0, kRight, /*width = */ 0, "0"}, + {0, kRight, /*width = */ 6, "_____0"}, + {0, kRight | kPos, /*width = */ 0, "+0"}, + {0, kRight | kPos, /*width = */ 6, "____+0"}, + {0, kRight | kBase, /*width = */ 0, "0"}, + {0, kRight | kBase, /*width = */ 6, "_____0"}, + {0, kRight | kBase | kPos, /*width = */ 0, "+0"}, + {0, kRight | kBase | kPos, /*width = */ 6, "____+0"}, + {0, kRight | kUpper, /*width = */ 0, "0"}, + {0, kRight | kUpper, /*width = */ 6, "_____0"}, + {0, kRight | kUpper | kPos, /*width = */ 0, "+0"}, + {0, kRight | kUpper | kPos, /*width = */ 6, "____+0"}, + {0, kRight | kUpper | kBase, /*width = */ 0, "0"}, + {0, kRight | kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kRight | kUpper | kBase | kPos, /*width = */ 0, "+0"}, + {0, kRight | kUpper | kBase | kPos, /*width = */ 6, "____+0"}, + {0, kDec, /*width = */ 0, "0"}, + {0, kDec, /*width = */ 6, "_____0"}, + {0, kDec | kPos, /*width = */ 0, "+0"}, + {0, kDec | kPos, /*width = */ 6, "____+0"}, + {0, kDec | kBase, /*width = */ 0, "0"}, + {0, kDec | kBase, /*width = */ 6, "_____0"}, + {0, kDec | kBase | kPos, /*width = */ 0, "+0"}, + {0, kDec | kBase | kPos, /*width = */ 6, "____+0"}, + {0, kDec | kUpper, /*width = */ 0, "0"}, + {0, kDec | kUpper, /*width = */ 6, "_____0"}, + {0, kDec | kUpper | kPos, /*width = */ 0, "+0"}, + {0, kDec | kUpper | kPos, /*width = */ 6, "____+0"}, + {0, kDec | kUpper | kBase, /*width = */ 0, "0"}, + {0, kDec | kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kDec | kUpper | kBase | kPos, /*width = */ 0, "+0"}, + {0, kDec | kUpper | kBase | kPos, /*width = */ 6, "____+0"}, + {0, kDec | kLeft, /*width = */ 0, "0"}, + {0, kDec | kLeft, /*width = */ 6, "0_____"}, + {0, kDec | kLeft | kPos, /*width = */ 0, "+0"}, + {0, kDec | kLeft | kPos, /*width = */ 6, "+0____"}, + {0, kDec | kLeft | kBase, /*width = */ 0, "0"}, + {0, kDec | kLeft | kBase, /*width = */ 6, "0_____"}, + {0, kDec | kLeft | kBase | kPos, /*width = */ 0, "+0"}, + {0, kDec | kLeft | kBase | kPos, /*width = */ 6, "+0____"}, + {0, kDec | kLeft | kUpper, /*width = */ 0, "0"}, + {0, kDec | kLeft | kUpper, /*width = */ 6, "0_____"}, + {0, kDec | kLeft | kUpper | kPos, /*width = */ 0, "+0"}, + {0, kDec | kLeft | kUpper | kPos, /*width = */ 6, "+0____"}, + {0, kDec | kLeft | kUpper | kBase, /*width = */ 0, "0"}, + {0, kDec | kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, + {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "+0"}, + {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "+0____"}, + {0, kDec | kInt, /*width = */ 0, "0"}, + {0, kDec | kInt, /*width = */ 6, "_____0"}, + {0, kDec | kInt | kPos, /*width = */ 0, "+0"}, + {0, kDec | kInt | kPos, /*width = */ 6, "+____0"}, + {0, kDec | kInt | kBase, /*width = */ 0, "0"}, + {0, kDec | kInt | kBase, /*width = */ 6, "_____0"}, + {0, kDec | kInt | kBase | kPos, /*width = */ 0, "+0"}, + {0, kDec | kInt | kBase | kPos, /*width = */ 6, "+____0"}, + {0, kDec | kInt | kUpper, /*width = */ 0, "0"}, + {0, kDec | kInt | kUpper, /*width = */ 6, "_____0"}, + {0, kDec | kInt | kUpper | kPos, /*width = */ 0, "+0"}, + {0, kDec | kInt | kUpper | kPos, /*width = */ 6, "+____0"}, + {0, kDec | kInt | kUpper | kBase, /*width = */ 0, "0"}, + {0, kDec | kInt | kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "+0"}, + {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "+____0"}, + {0, kDec | kRight, /*width = */ 0, "0"}, + {0, kDec | kRight, /*width = */ 6, "_____0"}, + {0, kDec | kRight | kPos, /*width = */ 0, "+0"}, + {0, kDec | kRight | kPos, /*width = */ 6, "____+0"}, + {0, kDec | kRight | kBase, /*width = */ 0, "0"}, + {0, kDec | kRight | kBase, /*width = */ 6, "_____0"}, + {0, kDec | kRight | kBase | kPos, /*width = */ 0, "+0"}, + {0, kDec | kRight | kBase | kPos, /*width = */ 6, "____+0"}, + {0, kDec | kRight | kUpper, /*width = */ 0, "0"}, + {0, kDec | kRight | kUpper, /*width = */ 6, "_____0"}, + {0, kDec | kRight | kUpper | kPos, /*width = */ 0, "+0"}, + {0, kDec | kRight | kUpper | kPos, /*width = */ 6, "____+0"}, + {0, kDec | kRight | kUpper | kBase, /*width = */ 0, "0"}, + {0, kDec | kRight | kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "+0"}, + {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "____+0"}, + {0, kOct, /*width = */ 0, "0"}, + {0, kOct, /*width = */ 6, "_____0"}, + {0, kOct | kPos, /*width = */ 0, "0"}, + {0, kOct | kPos, /*width = */ 6, "_____0"}, + {0, kOct | kBase, /*width = */ 0, "0"}, + {0, kOct | kBase, /*width = */ 6, "_____0"}, + {0, kOct | kBase | kPos, /*width = */ 0, "0"}, + {0, kOct | kBase | kPos, /*width = */ 6, "_____0"}, + {0, kOct | kUpper, /*width = */ 0, "0"}, + {0, kOct | kUpper, /*width = */ 6, "_____0"}, + {0, kOct | kUpper | kPos, /*width = */ 0, "0"}, + {0, kOct | kUpper | kPos, /*width = */ 6, "_____0"}, + {0, kOct | kUpper | kBase, /*width = */ 0, "0"}, + {0, kOct | kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kOct | kUpper | kBase | kPos, /*width = */ 0, "0"}, + {0, kOct | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, + {0, kOct | kLeft, /*width = */ 0, "0"}, + {0, kOct | kLeft, /*width = */ 6, "0_____"}, + {0, kOct | kLeft | kPos, /*width = */ 0, "0"}, + {0, kOct | kLeft | kPos, /*width = */ 6, "0_____"}, + {0, kOct | kLeft | kBase, /*width = */ 0, "0"}, + {0, kOct | kLeft | kBase, /*width = */ 6, "0_____"}, + {0, kOct | kLeft | kBase | kPos, /*width = */ 0, "0"}, + {0, kOct | kLeft | kBase | kPos, /*width = */ 6, "0_____"}, + {0, kOct | kLeft | kUpper, /*width = */ 0, "0"}, + {0, kOct | kLeft | kUpper, /*width = */ 6, "0_____"}, + {0, kOct | kLeft | kUpper | kPos, /*width = */ 0, "0"}, + {0, kOct | kLeft | kUpper | kPos, /*width = */ 6, "0_____"}, + {0, kOct | kLeft | kUpper | kBase, /*width = */ 0, "0"}, + {0, kOct | kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, + {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"}, + {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"}, + {0, kOct | kInt, /*width = */ 0, "0"}, + {0, kOct | kInt, /*width = */ 6, "_____0"}, + {0, kOct | kInt | kPos, /*width = */ 0, "0"}, + {0, kOct | kInt | kPos, /*width = */ 6, "_____0"}, + {0, kOct | kInt | kBase, /*width = */ 0, "0"}, + {0, kOct | kInt | kBase, /*width = */ 6, "_____0"}, + {0, kOct | kInt | kBase | kPos, /*width = */ 0, "0"}, + {0, kOct | kInt | kBase | kPos, /*width = */ 6, "_____0"}, + {0, kOct | kInt | kUpper, /*width = */ 0, "0"}, + {0, kOct | kInt | kUpper, /*width = */ 6, "_____0"}, + {0, kOct | kInt | kUpper | kPos, /*width = */ 0, "0"}, + {0, kOct | kInt | kUpper | kPos, /*width = */ 6, "_____0"}, + {0, kOct | kInt | kUpper | kBase, /*width = */ 0, "0"}, + {0, kOct | kInt | kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, "0"}, + {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, + {0, kOct | kRight, /*width = */ 0, "0"}, + {0, kOct | kRight, /*width = */ 6, "_____0"}, + {0, kOct | kRight | kPos, /*width = */ 0, "0"}, + {0, kOct | kRight | kPos, /*width = */ 6, "_____0"}, + {0, kOct | kRight | kBase, /*width = */ 0, "0"}, + {0, kOct | kRight | kBase, /*width = */ 6, "_____0"}, + {0, kOct | kRight | kBase | kPos, /*width = */ 0, "0"}, + {0, kOct | kRight | kBase | kPos, /*width = */ 6, "_____0"}, + {0, kOct | kRight | kUpper, /*width = */ 0, "0"}, + {0, kOct | kRight | kUpper, /*width = */ 6, "_____0"}, + {0, kOct | kRight | kUpper | kPos, /*width = */ 0, "0"}, + {0, kOct | kRight | kUpper | kPos, /*width = */ 6, "_____0"}, + {0, kOct | kRight | kUpper | kBase, /*width = */ 0, "0"}, + {0, kOct | kRight | kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, "0"}, + {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, + {0, kHex, /*width = */ 0, "0"}, + {0, kHex, /*width = */ 6, "_____0"}, + {0, kHex | kPos, /*width = */ 0, "0"}, + {0, kHex | kPos, /*width = */ 6, "_____0"}, + {0, kHex | kBase, /*width = */ 0, "0"}, + {0, kHex | kBase, /*width = */ 6, "_____0"}, + {0, kHex | kBase | kPos, /*width = */ 0, "0"}, + {0, kHex | kBase | kPos, /*width = */ 6, "_____0"}, + {0, kHex | kUpper, /*width = */ 0, "0"}, + {0, kHex | kUpper, /*width = */ 6, "_____0"}, + {0, kHex | kUpper | kPos, /*width = */ 0, "0"}, + {0, kHex | kUpper | kPos, /*width = */ 6, "_____0"}, + {0, kHex | kUpper | kBase, /*width = */ 0, "0"}, + {0, kHex | kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kHex | kUpper | kBase | kPos, /*width = */ 0, "0"}, + {0, kHex | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, + {0, kHex | kLeft, /*width = */ 0, "0"}, + {0, kHex | kLeft, /*width = */ 6, "0_____"}, + {0, kHex | kLeft | kPos, /*width = */ 0, "0"}, + {0, kHex | kLeft | kPos, /*width = */ 6, "0_____"}, + {0, kHex | kLeft | kBase, /*width = */ 0, "0"}, + {0, kHex | kLeft | kBase, /*width = */ 6, "0_____"}, + {0, kHex | kLeft | kBase | kPos, /*width = */ 0, "0"}, + {0, kHex | kLeft | kBase | kPos, /*width = */ 6, "0_____"}, + {0, kHex | kLeft | kUpper, /*width = */ 0, "0"}, + {0, kHex | kLeft | kUpper, /*width = */ 6, "0_____"}, + {0, kHex | kLeft | kUpper | kPos, /*width = */ 0, "0"}, + {0, kHex | kLeft | kUpper | kPos, /*width = */ 6, "0_____"}, + {0, kHex | kLeft | kUpper | kBase, /*width = */ 0, "0"}, + {0, kHex | kLeft | kUpper | kBase, /*width = */ 6, "0_____"}, + {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"}, + {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"}, + {0, kHex | kInt, /*width = */ 0, "0"}, + {0, kHex | kInt, /*width = */ 6, "_____0"}, + {0, kHex | kInt | kPos, /*width = */ 0, "0"}, + {0, kHex | kInt | kPos, /*width = */ 6, "_____0"}, + {0, kHex | kInt | kBase, /*width = */ 0, "0"}, + {0, kHex | kInt | kBase, /*width = */ 6, "_____0"}, + {0, kHex | kInt | kBase | kPos, /*width = */ 0, "0"}, + {0, kHex | kInt | kBase | kPos, /*width = */ 6, "_____0"}, + {0, kHex | kInt | kUpper, /*width = */ 0, "0"}, + {0, kHex | kInt | kUpper, /*width = */ 6, "_____0"}, + {0, kHex | kInt | kUpper | kPos, /*width = */ 0, "0"}, + {0, kHex | kInt | kUpper | kPos, /*width = */ 6, "_____0"}, + {0, kHex | kInt | kUpper | kBase, /*width = */ 0, "0"}, + {0, kHex | kInt | kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, "0"}, + {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, + {0, kHex | kRight, /*width = */ 0, "0"}, + {0, kHex | kRight, /*width = */ 6, "_____0"}, + {0, kHex | kRight | kPos, /*width = */ 0, "0"}, + {0, kHex | kRight | kPos, /*width = */ 6, "_____0"}, + {0, kHex | kRight | kBase, /*width = */ 0, "0"}, + {0, kHex | kRight | kBase, /*width = */ 6, "_____0"}, + {0, kHex | kRight | kBase | kPos, /*width = */ 0, "0"}, + {0, kHex | kRight | kBase | kPos, /*width = */ 6, "_____0"}, + {0, kHex | kRight | kUpper, /*width = */ 0, "0"}, + {0, kHex | kRight | kUpper, /*width = */ 6, "_____0"}, + {0, kHex | kRight | kUpper | kPos, /*width = */ 0, "0"}, + {0, kHex | kRight | kUpper | kPos, /*width = */ 6, "_____0"}, + {0, kHex | kRight | kUpper | kBase, /*width = */ 0, "0"}, + {0, kHex | kRight | kUpper | kBase, /*width = */ 6, "_____0"}, + {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, "0"}, + {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"}, + {42, std::ios_base::fmtflags(), /*width = */ 0, "42"}, + {42, std::ios_base::fmtflags(), /*width = */ 6, "____42"}, + {42, kPos, /*width = */ 0, "+42"}, + {42, kPos, /*width = */ 6, "___+42"}, + {42, kBase, /*width = */ 0, "42"}, + {42, kBase, /*width = */ 6, "____42"}, + {42, kBase | kPos, /*width = */ 0, "+42"}, + {42, kBase | kPos, /*width = */ 6, "___+42"}, + {42, kUpper, /*width = */ 0, "42"}, + {42, kUpper, /*width = */ 6, "____42"}, + {42, kUpper | kPos, /*width = */ 0, "+42"}, + {42, kUpper | kPos, /*width = */ 6, "___+42"}, + {42, kUpper | kBase, /*width = */ 0, "42"}, + {42, kUpper | kBase, /*width = */ 6, "____42"}, + {42, kUpper | kBase | kPos, /*width = */ 0, "+42"}, + {42, kUpper | kBase | kPos, /*width = */ 6, "___+42"}, + {42, kLeft, /*width = */ 0, "42"}, + {42, kLeft, /*width = */ 6, "42____"}, + {42, kLeft | kPos, /*width = */ 0, "+42"}, + {42, kLeft | kPos, /*width = */ 6, "+42___"}, + {42, kLeft | kBase, /*width = */ 0, "42"}, + {42, kLeft | kBase, /*width = */ 6, "42____"}, + {42, kLeft | kBase | kPos, /*width = */ 0, "+42"}, + {42, kLeft | kBase | kPos, /*width = */ 6, "+42___"}, + {42, kLeft | kUpper, /*width = */ 0, "42"}, + {42, kLeft | kUpper, /*width = */ 6, "42____"}, + {42, kLeft | kUpper | kPos, /*width = */ 0, "+42"}, + {42, kLeft | kUpper | kPos, /*width = */ 6, "+42___"}, + {42, kLeft | kUpper | kBase, /*width = */ 0, "42"}, + {42, kLeft | kUpper | kBase, /*width = */ 6, "42____"}, + {42, kLeft | kUpper | kBase | kPos, /*width = */ 0, "+42"}, + {42, kLeft | kUpper | kBase | kPos, /*width = */ 6, "+42___"}, + {42, kInt, /*width = */ 0, "42"}, + {42, kInt, /*width = */ 6, "____42"}, + {42, kInt | kPos, /*width = */ 0, "+42"}, + {42, kInt | kPos, /*width = */ 6, "+___42"}, + {42, kInt | kBase, /*width = */ 0, "42"}, + {42, kInt | kBase, /*width = */ 6, "____42"}, + {42, kInt | kBase | kPos, /*width = */ 0, "+42"}, + {42, kInt | kBase | kPos, /*width = */ 6, "+___42"}, + {42, kInt | kUpper, /*width = */ 0, "42"}, + {42, kInt | kUpper, /*width = */ 6, "____42"}, + {42, kInt | kUpper | kPos, /*width = */ 0, "+42"}, + {42, kInt | kUpper | kPos, /*width = */ 6, "+___42"}, + {42, kInt | kUpper | kBase, /*width = */ 0, "42"}, + {42, kInt | kUpper | kBase, /*width = */ 6, "____42"}, + {42, kInt | kUpper | kBase | kPos, /*width = */ 0, "+42"}, + {42, kInt | kUpper | kBase | kPos, /*width = */ 6, "+___42"}, + {42, kRight, /*width = */ 0, "42"}, + {42, kRight, /*width = */ 6, "____42"}, + {42, kRight | kPos, /*width = */ 0, "+42"}, + {42, kRight | kPos, /*width = */ 6, "___+42"}, + {42, kRight | kBase, /*width = */ 0, "42"}, + {42, kRight | kBase, /*width = */ 6, "____42"}, + {42, kRight | kBase | kPos, /*width = */ 0, "+42"}, + {42, kRight | kBase | kPos, /*width = */ 6, "___+42"}, + {42, kRight | kUpper, /*width = */ 0, "42"}, + {42, kRight | kUpper, /*width = */ 6, "____42"}, + {42, kRight | kUpper | kPos, /*width = */ 0, "+42"}, + {42, kRight | kUpper | kPos, /*width = */ 6, "___+42"}, + {42, kRight | kUpper | kBase, /*width = */ 0, "42"}, + {42, kRight | kUpper | kBase, /*width = */ 6, "____42"}, + {42, kRight | kUpper | kBase | kPos, /*width = */ 0, "+42"}, + {42, kRight | kUpper | kBase | kPos, /*width = */ 6, "___+42"}, + {42, kDec, /*width = */ 0, "42"}, + {42, kDec, /*width = */ 6, "____42"}, + {42, kDec | kPos, /*width = */ 0, "+42"}, + {42, kDec | kPos, /*width = */ 6, "___+42"}, + {42, kDec | kBase, /*width = */ 0, "42"}, + {42, kDec | kBase, /*width = */ 6, "____42"}, + {42, kDec | kBase | kPos, /*width = */ 0, "+42"}, + {42, kDec | kBase | kPos, /*width = */ 6, "___+42"}, + {42, kDec | kUpper, /*width = */ 0, "42"}, + {42, kDec | kUpper, /*width = */ 6, "____42"}, + {42, kDec | kUpper | kPos, /*width = */ 0, "+42"}, + {42, kDec | kUpper | kPos, /*width = */ 6, "___+42"}, + {42, kDec | kUpper | kBase, /*width = */ 0, "42"}, + {42, kDec | kUpper | kBase, /*width = */ 6, "____42"}, + {42, kDec | kUpper | kBase | kPos, /*width = */ 0, "+42"}, + {42, kDec | kUpper | kBase | kPos, /*width = */ 6, "___+42"}, + {42, kDec | kLeft, /*width = */ 0, "42"}, + {42, kDec | kLeft, /*width = */ 6, "42____"}, + {42, kDec | kLeft | kPos, /*width = */ 0, "+42"}, + {42, kDec | kLeft | kPos, /*width = */ 6, "+42___"}, + {42, kDec | kLeft | kBase, /*width = */ 0, "42"}, + {42, kDec | kLeft | kBase, /*width = */ 6, "42____"}, + {42, kDec | kLeft | kBase | kPos, /*width = */ 0, "+42"}, + {42, kDec | kLeft | kBase | kPos, /*width = */ 6, "+42___"}, + {42, kDec | kLeft | kUpper, /*width = */ 0, "42"}, + {42, kDec | kLeft | kUpper, /*width = */ 6, "42____"}, + {42, kDec | kLeft | kUpper | kPos, /*width = */ 0, "+42"}, + {42, kDec | kLeft | kUpper | kPos, /*width = */ 6, "+42___"}, + {42, kDec | kLeft | kUpper | kBase, /*width = */ 0, "42"}, + {42, kDec | kLeft | kUpper | kBase, /*width = */ 6, "42____"}, + {42, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "+42"}, + {42, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "+42___"}, + {42, kDec | kInt, /*width = */ 0, "42"}, + {42, kDec | kInt, /*width = */ 6, "____42"}, + {42, kDec | kInt | kPos, /*width = */ 0, "+42"}, + {42, kDec | kInt | kPos, /*width = */ 6, "+___42"}, + {42, kDec | kInt | kBase, /*width = */ 0, "42"}, + {42, kDec | kInt | kBase, /*width = */ 6, "____42"}, + {42, kDec | kInt | kBase | kPos, /*width = */ 0, "+42"}, + {42, kDec | kInt | kBase | kPos, /*width = */ 6, "+___42"}, + {42, kDec | kInt | kUpper, /*width = */ 0, "42"}, + {42, kDec | kInt | kUpper, /*width = */ 6, "____42"}, + {42, kDec | kInt | kUpper | kPos, /*width = */ 0, "+42"}, + {42, kDec | kInt | kUpper | kPos, /*width = */ 6, "+___42"}, + {42, kDec | kInt | kUpper | kBase, /*width = */ 0, "42"}, + {42, kDec | kInt | kUpper | kBase, /*width = */ 6, "____42"}, + {42, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "+42"}, + {42, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "+___42"}, + {42, kDec | kRight, /*width = */ 0, "42"}, + {42, kDec | kRight, /*width = */ 6, "____42"}, + {42, kDec | kRight | kPos, /*width = */ 0, "+42"}, + {42, kDec | kRight | kPos, /*width = */ 6, "___+42"}, + {42, kDec | kRight | kBase, /*width = */ 0, "42"}, + {42, kDec | kRight | kBase, /*width = */ 6, "____42"}, + {42, kDec | kRight | kBase | kPos, /*width = */ 0, "+42"}, + {42, kDec | kRight | kBase | kPos, /*width = */ 6, "___+42"}, + {42, kDec | kRight | kUpper, /*width = */ 0, "42"}, + {42, kDec | kRight | kUpper, /*width = */ 6, "____42"}, + {42, kDec | kRight | kUpper | kPos, /*width = */ 0, "+42"}, + {42, kDec | kRight | kUpper | kPos, /*width = */ 6, "___+42"}, + {42, kDec | kRight | kUpper | kBase, /*width = */ 0, "42"}, + {42, kDec | kRight | kUpper | kBase, /*width = */ 6, "____42"}, + {42, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "+42"}, + {42, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "___+42"}, + {42, kOct, /*width = */ 0, "52"}, + {42, kOct, /*width = */ 6, "____52"}, + {42, kOct | kPos, /*width = */ 0, "52"}, + {42, kOct | kPos, /*width = */ 6, "____52"}, + {42, kOct | kBase, /*width = */ 0, "052"}, + {42, kOct | kBase, /*width = */ 6, "___052"}, + {42, kOct | kBase | kPos, /*width = */ 0, "052"}, + {42, kOct | kBase | kPos, /*width = */ 6, "___052"}, + {42, kOct | kUpper, /*width = */ 0, "52"}, + {42, kOct | kUpper, /*width = */ 6, "____52"}, + {42, kOct | kUpper | kPos, /*width = */ 0, "52"}, + {42, kOct | kUpper | kPos, /*width = */ 6, "____52"}, + {42, kOct | kUpper | kBase, /*width = */ 0, "052"}, + {42, kOct | kUpper | kBase, /*width = */ 6, "___052"}, + {42, kOct | kUpper | kBase | kPos, /*width = */ 0, "052"}, + {42, kOct | kUpper | kBase | kPos, /*width = */ 6, "___052"}, + {42, kOct | kLeft, /*width = */ 0, "52"}, + {42, kOct | kLeft, /*width = */ 6, "52____"}, + {42, kOct | kLeft | kPos, /*width = */ 0, "52"}, + {42, kOct | kLeft | kPos, /*width = */ 6, "52____"}, + {42, kOct | kLeft | kBase, /*width = */ 0, "052"}, + {42, kOct | kLeft | kBase, /*width = */ 6, "052___"}, + {42, kOct | kLeft | kBase | kPos, /*width = */ 0, "052"}, + {42, kOct | kLeft | kBase | kPos, /*width = */ 6, "052___"}, + {42, kOct | kLeft | kUpper, /*width = */ 0, "52"}, + {42, kOct | kLeft | kUpper, /*width = */ 6, "52____"}, + {42, kOct | kLeft | kUpper | kPos, /*width = */ 0, "52"}, + {42, kOct | kLeft | kUpper | kPos, /*width = */ 6, "52____"}, + {42, kOct | kLeft | kUpper | kBase, /*width = */ 0, "052"}, + {42, kOct | kLeft | kUpper | kBase, /*width = */ 6, "052___"}, + {42, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, "052"}, + {42, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, "052___"}, + {42, kOct | kInt, /*width = */ 0, "52"}, + {42, kOct | kInt, /*width = */ 6, "____52"}, + {42, kOct | kInt | kPos, /*width = */ 0, "52"}, + {42, kOct | kInt | kPos, /*width = */ 6, "____52"}, + {42, kOct | kInt | kBase, /*width = */ 0, "052"}, + {42, kOct | kInt | kBase, /*width = */ 6, "___052"}, + {42, kOct | kInt | kBase | kPos, /*width = */ 0, "052"}, + {42, kOct | kInt | kBase | kPos, /*width = */ 6, "___052"}, + {42, kOct | kInt | kUpper, /*width = */ 0, "52"}, + {42, kOct | kInt | kUpper, /*width = */ 6, "____52"}, + {42, kOct | kInt | kUpper | kPos, /*width = */ 0, "52"}, + {42, kOct | kInt | kUpper | kPos, /*width = */ 6, "____52"}, + {42, kOct | kInt | kUpper | kBase, /*width = */ 0, "052"}, + {42, kOct | kInt | kUpper | kBase, /*width = */ 6, "___052"}, + {42, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, "052"}, + {42, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, "___052"}, + {42, kOct | kRight, /*width = */ 0, "52"}, + {42, kOct | kRight, /*width = */ 6, "____52"}, + {42, kOct | kRight | kPos, /*width = */ 0, "52"}, + {42, kOct | kRight | kPos, /*width = */ 6, "____52"}, + {42, kOct | kRight | kBase, /*width = */ 0, "052"}, + {42, kOct | kRight | kBase, /*width = */ 6, "___052"}, + {42, kOct | kRight | kBase | kPos, /*width = */ 0, "052"}, + {42, kOct | kRight | kBase | kPos, /*width = */ 6, "___052"}, + {42, kOct | kRight | kUpper, /*width = */ 0, "52"}, + {42, kOct | kRight | kUpper, /*width = */ 6, "____52"}, + {42, kOct | kRight | kUpper | kPos, /*width = */ 0, "52"}, + {42, kOct | kRight | kUpper | kPos, /*width = */ 6, "____52"}, + {42, kOct | kRight | kUpper | kBase, /*width = */ 0, "052"}, + {42, kOct | kRight | kUpper | kBase, /*width = */ 6, "___052"}, + {42, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, "052"}, + {42, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, "___052"}, + {42, kHex, /*width = */ 0, "2a"}, + {42, kHex, /*width = */ 6, "____2a"}, + {42, kHex | kPos, /*width = */ 0, "2a"}, + {42, kHex | kPos, /*width = */ 6, "____2a"}, + {42, kHex | kBase, /*width = */ 0, "0x2a"}, + {42, kHex | kBase, /*width = */ 6, "__0x2a"}, + {42, kHex | kBase | kPos, /*width = */ 0, "0x2a"}, + {42, kHex | kBase | kPos, /*width = */ 6, "__0x2a"}, + {42, kHex | kUpper, /*width = */ 0, "2A"}, + {42, kHex | kUpper, /*width = */ 6, "____2A"}, + {42, kHex | kUpper | kPos, /*width = */ 0, "2A"}, + {42, kHex | kUpper | kPos, /*width = */ 6, "____2A"}, + {42, kHex | kUpper | kBase, /*width = */ 0, "0X2A"}, + {42, kHex | kUpper | kBase, /*width = */ 6, "__0X2A"}, + {42, kHex | kUpper | kBase | kPos, /*width = */ 0, "0X2A"}, + {42, kHex | kUpper | kBase | kPos, /*width = */ 6, "__0X2A"}, + {42, kHex | kLeft, /*width = */ 0, "2a"}, + {42, kHex | kLeft, /*width = */ 6, "2a____"}, + {42, kHex | kLeft | kPos, /*width = */ 0, "2a"}, + {42, kHex | kLeft | kPos, /*width = */ 6, "2a____"}, + {42, kHex | kLeft | kBase, /*width = */ 0, "0x2a"}, + {42, kHex | kLeft | kBase, /*width = */ 6, "0x2a__"}, + {42, kHex | kLeft | kBase | kPos, /*width = */ 0, "0x2a"}, + {42, kHex | kLeft | kBase | kPos, /*width = */ 6, "0x2a__"}, + {42, kHex | kLeft | kUpper, /*width = */ 0, "2A"}, + {42, kHex | kLeft | kUpper, /*width = */ 6, "2A____"}, + {42, kHex | kLeft | kUpper | kPos, /*width = */ 0, "2A"}, + {42, kHex | kLeft | kUpper | kPos, /*width = */ 6, "2A____"}, + {42, kHex | kLeft | kUpper | kBase, /*width = */ 0, "0X2A"}, + {42, kHex | kLeft | kUpper | kBase, /*width = */ 6, "0X2A__"}, + {42, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0X2A"}, + {42, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0X2A__"}, + {42, kHex | kInt, /*width = */ 0, "2a"}, + {42, kHex | kInt, /*width = */ 6, "____2a"}, + {42, kHex | kInt | kPos, /*width = */ 0, "2a"}, + {42, kHex | kInt | kPos, /*width = */ 6, "____2a"}, + {42, kHex | kInt | kBase, /*width = */ 0, "0x2a"}, + {42, kHex | kInt | kBase, /*width = */ 6, "0x__2a"}, + {42, kHex | kInt | kBase | kPos, /*width = */ 0, "0x2a"}, + {42, kHex | kInt | kBase | kPos, /*width = */ 6, "0x__2a"}, + {42, kHex | kInt | kUpper, /*width = */ 0, "2A"}, + {42, kHex | kInt | kUpper, /*width = */ 6, "____2A"}, + {42, kHex | kInt | kUpper | kPos, /*width = */ 0, "2A"}, + {42, kHex | kInt | kUpper | kPos, /*width = */ 6, "____2A"}, + {42, kHex | kInt | kUpper | kBase, /*width = */ 0, "0X2A"}, + {42, kHex | kInt | kUpper | kBase, /*width = */ 6, "0X__2A"}, + {42, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, "0X2A"}, + {42, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, "0X__2A"}, + {42, kHex | kRight, /*width = */ 0, "2a"}, + {42, kHex | kRight, /*width = */ 6, "____2a"}, + {42, kHex | kRight | kPos, /*width = */ 0, "2a"}, + {42, kHex | kRight | kPos, /*width = */ 6, "____2a"}, + {42, kHex | kRight | kBase, /*width = */ 0, "0x2a"}, + {42, kHex | kRight | kBase, /*width = */ 6, "__0x2a"}, + {42, kHex | kRight | kBase | kPos, /*width = */ 0, "0x2a"}, + {42, kHex | kRight | kBase | kPos, /*width = */ 6, "__0x2a"}, + {42, kHex | kRight | kUpper, /*width = */ 0, "2A"}, + {42, kHex | kRight | kUpper, /*width = */ 6, "____2A"}, + {42, kHex | kRight | kUpper | kPos, /*width = */ 0, "2A"}, + {42, kHex | kRight | kUpper | kPos, /*width = */ 6, "____2A"}, + {42, kHex | kRight | kUpper | kBase, /*width = */ 0, "0X2A"}, + {42, kHex | kRight | kUpper | kBase, /*width = */ 6, "__0X2A"}, + {42, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, "0X2A"}, + {42, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, "__0X2A"}, + {-321, std::ios_base::fmtflags(), /*width = */ 0, "-321"}, + {-321, std::ios_base::fmtflags(), /*width = */ 6, "__-321"}, + {-321, kPos, /*width = */ 0, "-321"}, + {-321, kPos, /*width = */ 6, "__-321"}, + {-321, kBase, /*width = */ 0, "-321"}, + {-321, kBase, /*width = */ 6, "__-321"}, + {-321, kBase | kPos, /*width = */ 0, "-321"}, + {-321, kBase | kPos, /*width = */ 6, "__-321"}, + {-321, kUpper, /*width = */ 0, "-321"}, + {-321, kUpper, /*width = */ 6, "__-321"}, + {-321, kUpper | kPos, /*width = */ 0, "-321"}, + {-321, kUpper | kPos, /*width = */ 6, "__-321"}, + {-321, kUpper | kBase, /*width = */ 0, "-321"}, + {-321, kUpper | kBase, /*width = */ 6, "__-321"}, + {-321, kUpper | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kUpper | kBase | kPos, /*width = */ 6, "__-321"}, + {-321, kLeft, /*width = */ 0, "-321"}, + {-321, kLeft, /*width = */ 6, "-321__"}, + {-321, kLeft | kPos, /*width = */ 0, "-321"}, + {-321, kLeft | kPos, /*width = */ 6, "-321__"}, + {-321, kLeft | kBase, /*width = */ 0, "-321"}, + {-321, kLeft | kBase, /*width = */ 6, "-321__"}, + {-321, kLeft | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kLeft | kBase | kPos, /*width = */ 6, "-321__"}, + {-321, kLeft | kUpper, /*width = */ 0, "-321"}, + {-321, kLeft | kUpper, /*width = */ 6, "-321__"}, + {-321, kLeft | kUpper | kPos, /*width = */ 0, "-321"}, + {-321, kLeft | kUpper | kPos, /*width = */ 6, "-321__"}, + {-321, kLeft | kUpper | kBase, /*width = */ 0, "-321"}, + {-321, kLeft | kUpper | kBase, /*width = */ 6, "-321__"}, + {-321, kLeft | kUpper | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kLeft | kUpper | kBase | kPos, /*width = */ 6, "-321__"}, + {-321, kInt, /*width = */ 0, "-321"}, + {-321, kInt, /*width = */ 6, "-__321"}, + {-321, kInt | kPos, /*width = */ 0, "-321"}, + {-321, kInt | kPos, /*width = */ 6, "-__321"}, + {-321, kInt | kBase, /*width = */ 0, "-321"}, + {-321, kInt | kBase, /*width = */ 6, "-__321"}, + {-321, kInt | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kInt | kBase | kPos, /*width = */ 6, "-__321"}, + {-321, kInt | kUpper, /*width = */ 0, "-321"}, + {-321, kInt | kUpper, /*width = */ 6, "-__321"}, + {-321, kInt | kUpper | kPos, /*width = */ 0, "-321"}, + {-321, kInt | kUpper | kPos, /*width = */ 6, "-__321"}, + {-321, kInt | kUpper | kBase, /*width = */ 0, "-321"}, + {-321, kInt | kUpper | kBase, /*width = */ 6, "-__321"}, + {-321, kInt | kUpper | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kInt | kUpper | kBase | kPos, /*width = */ 6, "-__321"}, + {-321, kRight, /*width = */ 0, "-321"}, + {-321, kRight, /*width = */ 6, "__-321"}, + {-321, kRight | kPos, /*width = */ 0, "-321"}, + {-321, kRight | kPos, /*width = */ 6, "__-321"}, + {-321, kRight | kBase, /*width = */ 0, "-321"}, + {-321, kRight | kBase, /*width = */ 6, "__-321"}, + {-321, kRight | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kRight | kBase | kPos, /*width = */ 6, "__-321"}, + {-321, kRight | kUpper, /*width = */ 0, "-321"}, + {-321, kRight | kUpper, /*width = */ 6, "__-321"}, + {-321, kRight | kUpper | kPos, /*width = */ 0, "-321"}, + {-321, kRight | kUpper | kPos, /*width = */ 6, "__-321"}, + {-321, kRight | kUpper | kBase, /*width = */ 0, "-321"}, + {-321, kRight | kUpper | kBase, /*width = */ 6, "__-321"}, + {-321, kRight | kUpper | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kRight | kUpper | kBase | kPos, /*width = */ 6, "__-321"}, + {-321, kDec, /*width = */ 0, "-321"}, + {-321, kDec, /*width = */ 6, "__-321"}, + {-321, kDec | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kPos, /*width = */ 6, "__-321"}, + {-321, kDec | kBase, /*width = */ 0, "-321"}, + {-321, kDec | kBase, /*width = */ 6, "__-321"}, + {-321, kDec | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kBase | kPos, /*width = */ 6, "__-321"}, + {-321, kDec | kUpper, /*width = */ 0, "-321"}, + {-321, kDec | kUpper, /*width = */ 6, "__-321"}, + {-321, kDec | kUpper | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kUpper | kPos, /*width = */ 6, "__-321"}, + {-321, kDec | kUpper | kBase, /*width = */ 0, "-321"}, + {-321, kDec | kUpper | kBase, /*width = */ 6, "__-321"}, + {-321, kDec | kUpper | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kUpper | kBase | kPos, /*width = */ 6, "__-321"}, + {-321, kDec | kLeft, /*width = */ 0, "-321"}, + {-321, kDec | kLeft, /*width = */ 6, "-321__"}, + {-321, kDec | kLeft | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kLeft | kPos, /*width = */ 6, "-321__"}, + {-321, kDec | kLeft | kBase, /*width = */ 0, "-321"}, + {-321, kDec | kLeft | kBase, /*width = */ 6, "-321__"}, + {-321, kDec | kLeft | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kLeft | kBase | kPos, /*width = */ 6, "-321__"}, + {-321, kDec | kLeft | kUpper, /*width = */ 0, "-321"}, + {-321, kDec | kLeft | kUpper, /*width = */ 6, "-321__"}, + {-321, kDec | kLeft | kUpper | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kLeft | kUpper | kPos, /*width = */ 6, "-321__"}, + {-321, kDec | kLeft | kUpper | kBase, /*width = */ 0, "-321"}, + {-321, kDec | kLeft | kUpper | kBase, /*width = */ 6, "-321__"}, + {-321, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "-321__"}, + {-321, kDec | kInt, /*width = */ 0, "-321"}, + {-321, kDec | kInt, /*width = */ 6, "-__321"}, + {-321, kDec | kInt | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kInt | kPos, /*width = */ 6, "-__321"}, + {-321, kDec | kInt | kBase, /*width = */ 0, "-321"}, + {-321, kDec | kInt | kBase, /*width = */ 6, "-__321"}, + {-321, kDec | kInt | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kInt | kBase | kPos, /*width = */ 6, "-__321"}, + {-321, kDec | kInt | kUpper, /*width = */ 0, "-321"}, + {-321, kDec | kInt | kUpper, /*width = */ 6, "-__321"}, + {-321, kDec | kInt | kUpper | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kInt | kUpper | kPos, /*width = */ 6, "-__321"}, + {-321, kDec | kInt | kUpper | kBase, /*width = */ 0, "-321"}, + {-321, kDec | kInt | kUpper | kBase, /*width = */ 6, "-__321"}, + {-321, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "-__321"}, + {-321, kDec | kRight, /*width = */ 0, "-321"}, + {-321, kDec | kRight, /*width = */ 6, "__-321"}, + {-321, kDec | kRight | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kRight | kPos, /*width = */ 6, "__-321"}, + {-321, kDec | kRight | kBase, /*width = */ 0, "-321"}, + {-321, kDec | kRight | kBase, /*width = */ 6, "__-321"}, + {-321, kDec | kRight | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kRight | kBase | kPos, /*width = */ 6, "__-321"}, + {-321, kDec | kRight | kUpper, /*width = */ 0, "-321"}, + {-321, kDec | kRight | kUpper, /*width = */ 6, "__-321"}, + {-321, kDec | kRight | kUpper | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kRight | kUpper | kPos, /*width = */ 6, "__-321"}, + {-321, kDec | kRight | kUpper | kBase, /*width = */ 0, "-321"}, + {-321, kDec | kRight | kUpper | kBase, /*width = */ 6, "__-321"}, + {-321, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "-321"}, + {-321, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "__-321"}}; +} + std::vector GetUint128FormatCases() { return { {0, std::ios_base::fmtflags(), /*width = */ 0, "0"}, diff --git a/absl/numeric/int128_test.cc b/absl/numeric/int128_test.cc index 5e1b5ec3..bc86c714 100644 --- a/absl/numeric/int128_test.cc +++ b/absl/numeric/int128_test.cc @@ -479,4 +479,747 @@ TEST(Uint128, Hash) { })); } + +TEST(Int128Uint128, ConversionTest) { + absl::int128 nonnegative_signed_values[] = { + 0, + 1, + 0xffeeddccbbaa9988, + absl::MakeInt128(0x7766554433221100, 0), + absl::MakeInt128(0x1234567890abcdef, 0xfedcba0987654321), + absl::Int128Max()}; + for (absl::int128 value : nonnegative_signed_values) { + EXPECT_EQ(value, absl::int128(absl::uint128(value))); + + absl::uint128 assigned_value; + assigned_value = value; + EXPECT_EQ(value, absl::int128(assigned_value)); + } + + absl::int128 negative_values[] = { + -1, -0x1234567890abcdef, + absl::MakeInt128(-0x5544332211ffeedd, 0), + -absl::MakeInt128(0x76543210fedcba98, 0xabcdef0123456789)}; + for (absl::int128 value : negative_values) { + EXPECT_EQ(absl::uint128(-value), -absl::uint128(value)); + + absl::uint128 assigned_value; + assigned_value = value; + EXPECT_EQ(absl::uint128(-value), -assigned_value); + } +} + +template +class Int128IntegerTraitsTest : public ::testing::Test {}; + +TYPED_TEST_SUITE(Int128IntegerTraitsTest, IntegerTypes); + +TYPED_TEST(Int128IntegerTraitsTest, ConstructAssignTest) { + static_assert(std::is_constructible::value, + "absl::int128 must be constructible from TypeParam"); + static_assert(std::is_assignable::value, + "absl::int128 must be assignable from TypeParam"); + static_assert(!std::is_assignable::value, + "TypeParam must not be assignable from absl::int128"); +} + +template +class Int128FloatTraitsTest : public ::testing::Test {}; + +TYPED_TEST_SUITE(Int128FloatTraitsTest, FloatingPointTypes); + +TYPED_TEST(Int128FloatTraitsTest, ConstructAssignTest) { + static_assert(std::is_constructible::value, + "absl::int128 must be constructible from TypeParam"); + static_assert(!std::is_assignable::value, + "absl::int128 must not be assignable from TypeParam"); + static_assert(!std::is_assignable::value, + "TypeParam must not be assignable from absl::int128"); +} + +#ifdef ABSL_HAVE_INTRINSIC_INT128 +// These type traits done separately as TYPED_TEST requires typeinfo, and not +// all platforms have this for __int128 even though they define the type. +TEST(Int128, IntrinsicTypeTraitsTest) { + static_assert(std::is_constructible::value, + "absl::int128 must be constructible from __int128"); + static_assert(std::is_assignable::value, + "absl::int128 must be assignable from __int128"); + static_assert(!std::is_assignable<__int128&, absl::int128>::value, + "__int128 must not be assignable from absl::int128"); + + static_assert(std::is_constructible::value, + "absl::int128 must be constructible from unsigned __int128"); + static_assert(!std::is_assignable::value, + "absl::int128 must be assignable from unsigned __int128"); + static_assert(!std::is_assignable::value, + "unsigned __int128 must not be assignable from absl::int128"); +} +#endif // ABSL_HAVE_INTRINSIC_INT128 + +TEST(Int128, TrivialTraitsTest) { + static_assert(absl::is_trivially_default_constructible::value, + ""); + static_assert(absl::is_trivially_copy_constructible::value, ""); + static_assert(absl::is_trivially_copy_assignable::value, ""); + static_assert(std::is_trivially_destructible::value, ""); +} + +TEST(Int128, BoolConversionTest) { + EXPECT_FALSE(absl::int128(0)); + for (int i = 0; i < 64; ++i) { + EXPECT_TRUE(absl::MakeInt128(0, uint64_t{1} << i)); + } + for (int i = 0; i < 63; ++i) { + EXPECT_TRUE(absl::MakeInt128(int64_t{1} << i, 0)); + } + EXPECT_TRUE(absl::Int128Min()); + + EXPECT_EQ(absl::int128(1), absl::int128(true)); + EXPECT_EQ(absl::int128(0), absl::int128(false)); +} + +template +class Int128IntegerConversionTest : public ::testing::Test {}; + +TYPED_TEST_SUITE(Int128IntegerConversionTest, IntegerTypes); + +TYPED_TEST(Int128IntegerConversionTest, RoundTripTest) { + EXPECT_EQ(TypeParam{0}, static_cast(absl::int128(0))); + EXPECT_EQ(std::numeric_limits::min(), + static_cast( + absl::int128(std::numeric_limits::min()))); + EXPECT_EQ(std::numeric_limits::max(), + static_cast( + absl::int128(std::numeric_limits::max()))); +} + +template +class Int128FloatConversionTest : public ::testing::Test {}; + +TYPED_TEST_SUITE(Int128FloatConversionTest, FloatingPointTypes); + +TYPED_TEST(Int128FloatConversionTest, ConstructAndCastTest) { + // Conversions where the floating point values should be exactly the same. + // 0x9f5b is a randomly chosen small value. + for (int i = 0; i < 110; ++i) { // 110 = 126 - #bits in 0x9f5b + SCOPED_TRACE(::testing::Message() << "i = " << i); + + TypeParam float_value = std::ldexp(static_cast(0x9f5b), i); + absl::int128 int_value = absl::int128(0x9f5b) << i; + + EXPECT_EQ(float_value, static_cast(int_value)); + EXPECT_EQ(-float_value, static_cast(-int_value)); + EXPECT_EQ(int_value, absl::int128(float_value)); + EXPECT_EQ(-int_value, absl::int128(-float_value)); + } + + // Round trip conversions with a small sample of randomly generated uint64_t + // values (less than int64_t max so that value * 2^64 fits into int128). + uint64_t values[] = {0x6d4492c24fb86199, 0x26ead65e4cb359b5, + 0x2c43407433ba3fd1, 0x3b574ec668df6b55, + 0x1c750e55a29f4f0f}; + for (uint64_t value : values) { + for (int i = 0; i <= 64; ++i) { + SCOPED_TRACE(::testing::Message() + << "value = " << value << "; i = " << i); + + TypeParam fvalue = std::ldexp(static_cast(value), i); + EXPECT_DOUBLE_EQ(fvalue, static_cast(absl::int128(fvalue))); + EXPECT_DOUBLE_EQ(-fvalue, static_cast(-absl::int128(fvalue))); + EXPECT_DOUBLE_EQ(-fvalue, static_cast(absl::int128(-fvalue))); + EXPECT_DOUBLE_EQ(fvalue, static_cast(-absl::int128(-fvalue))); + } + } + + // Round trip conversions with a small sample of random large positive values. + absl::int128 large_values[] = { + absl::MakeInt128(0x5b0640d96c7b3d9f, 0xb7a7189e51d18622), + absl::MakeInt128(0x34bed042c6f65270, 0x73b236570669a089), + absl::MakeInt128(0x43deba9e6da12724, 0xf7f0f83da686797d), + absl::MakeInt128(0x71e8d383be4e5589, 0x75c3f96fb00752b6)}; + for (absl::int128 value : large_values) { + // Make value have as many significant bits as can be represented by + // the mantissa, also making sure the highest and lowest bit in the range + // are set. + value >>= (127 - std::numeric_limits::digits); + value |= absl::int128(1) << (std::numeric_limits::digits - 1); + value |= 1; + for (int i = 0; i < 127 - std::numeric_limits::digits; ++i) { + absl::int128 int_value = value << i; + EXPECT_EQ(int_value, + static_cast(static_cast(int_value))); + EXPECT_EQ(-int_value, + static_cast(static_cast(-int_value))); + } + } + + // Small sample of checks that rounding is toward zero + EXPECT_EQ(0, absl::int128(TypeParam(0.1))); + EXPECT_EQ(17, absl::int128(TypeParam(17.8))); + EXPECT_EQ(0, absl::int128(TypeParam(-0.8))); + EXPECT_EQ(-53, absl::int128(TypeParam(-53.1))); + EXPECT_EQ(0, absl::int128(TypeParam(0.5))); + EXPECT_EQ(0, absl::int128(TypeParam(-0.5))); + TypeParam just_lt_one = std::nexttoward(TypeParam(1), TypeParam(0)); + EXPECT_EQ(0, absl::int128(just_lt_one)); + TypeParam just_gt_minus_one = std::nexttoward(TypeParam(-1), TypeParam(0)); + EXPECT_EQ(0, absl::int128(just_gt_minus_one)); + + // Check limits + EXPECT_DOUBLE_EQ(std::ldexp(static_cast(1), 127), + static_cast(absl::Int128Max())); + EXPECT_DOUBLE_EQ(-std::ldexp(static_cast(1), 127), + static_cast(absl::Int128Min())); +} + +TEST(Int128, FactoryTest) { + EXPECT_EQ(absl::int128(-1), absl::MakeInt128(-1, -1)); + EXPECT_EQ(absl::int128(-31), absl::MakeInt128(-1, -31)); + EXPECT_EQ(absl::int128(std::numeric_limits::min()), + absl::MakeInt128(-1, std::numeric_limits::min())); + EXPECT_EQ(absl::int128(0), absl::MakeInt128(0, 0)); + EXPECT_EQ(absl::int128(1), absl::MakeInt128(0, 1)); + EXPECT_EQ(absl::int128(std::numeric_limits::max()), + absl::MakeInt128(0, std::numeric_limits::max())); +} + +TEST(Int128, HighLowTest) { + struct HighLowPair { + int64_t high; + uint64_t low; + }; + HighLowPair values[]{{0, 0}, {0, 1}, {1, 0}, {123, 456}, {-654, 321}}; + for (const HighLowPair& pair : values) { + absl::int128 value = absl::MakeInt128(pair.high, pair.low); + EXPECT_EQ(pair.low, absl::Int128Low64(value)); + EXPECT_EQ(pair.high, absl::Int128High64(value)); + } +} + +TEST(Int128, LimitsTest) { + EXPECT_EQ(absl::MakeInt128(0x7fffffffffffffff, 0xffffffffffffffff), + absl::Int128Max()); + EXPECT_EQ(absl::Int128Max(), ~absl::Int128Min()); +} + +#if defined(ABSL_HAVE_INTRINSIC_INT128) +TEST(Int128, IntrinsicConversionTest) { + __int128 intrinsic = + (static_cast<__int128>(0x3a5b76c209de76f6) << 64) + 0x1f25e1d63a2b46c5; + absl::int128 custom = + absl::MakeInt128(0x3a5b76c209de76f6, 0x1f25e1d63a2b46c5); + + EXPECT_EQ(custom, absl::int128(intrinsic)); + EXPECT_EQ(intrinsic, static_cast<__int128>(custom)); +} +#endif // ABSL_HAVE_INTRINSIC_INT128 + +TEST(Int128, ConstexprTest) { + constexpr absl::int128 zero = absl::int128(); + constexpr absl::int128 one = 1; + constexpr absl::int128 minus_two = -2; + constexpr absl::int128 min = absl::Int128Min(); + constexpr absl::int128 max = absl::Int128Max(); + EXPECT_EQ(zero, absl::int128(0)); + EXPECT_EQ(one, absl::int128(1)); + EXPECT_EQ(minus_two, absl::MakeInt128(-1, -2)); + EXPECT_GT(max, one); + EXPECT_LT(min, minus_two); +} + +TEST(Int128, ComparisonTest) { + struct TestCase { + absl::int128 smaller; + absl::int128 larger; + }; + TestCase cases[] = { + {absl::int128(0), absl::int128(123)}, + {absl::MakeInt128(-12, 34), absl::MakeInt128(12, 34)}, + {absl::MakeInt128(1, 1000), absl::MakeInt128(1000, 1)}, + {absl::MakeInt128(-1000, 1000), absl::MakeInt128(-1, 1)}, + }; + for (const TestCase& pair : cases) { + SCOPED_TRACE(::testing::Message() << "pair.smaller = " << pair.smaller + << "; pair.larger = " << pair.larger); + + EXPECT_TRUE(pair.smaller == pair.smaller); // NOLINT(readability/check) + EXPECT_TRUE(pair.larger == pair.larger); // NOLINT(readability/check) + EXPECT_FALSE(pair.smaller == pair.larger); // NOLINT(readability/check) + + EXPECT_TRUE(pair.smaller != pair.larger); // NOLINT(readability/check) + EXPECT_FALSE(pair.smaller != pair.smaller); // NOLINT(readability/check) + EXPECT_FALSE(pair.larger != pair.larger); // NOLINT(readability/check) + + EXPECT_TRUE(pair.smaller < pair.larger); // NOLINT(readability/check) + EXPECT_FALSE(pair.larger < pair.smaller); // NOLINT(readability/check) + + EXPECT_TRUE(pair.larger > pair.smaller); // NOLINT(readability/check) + EXPECT_FALSE(pair.smaller > pair.larger); // NOLINT(readability/check) + + EXPECT_TRUE(pair.smaller <= pair.larger); // NOLINT(readability/check) + EXPECT_FALSE(pair.larger <= pair.smaller); // NOLINT(readability/check) + EXPECT_TRUE(pair.smaller <= pair.smaller); // NOLINT(readability/check) + EXPECT_TRUE(pair.larger <= pair.larger); // NOLINT(readability/check) + + EXPECT_TRUE(pair.larger >= pair.smaller); // NOLINT(readability/check) + EXPECT_FALSE(pair.smaller >= pair.larger); // NOLINT(readability/check) + EXPECT_TRUE(pair.smaller >= pair.smaller); // NOLINT(readability/check) + EXPECT_TRUE(pair.larger >= pair.larger); // NOLINT(readability/check) + } +} + +TEST(Int128, UnaryNegationTest) { + int64_t values64[] = {0, 1, 12345, 0x4000000000000000, + std::numeric_limits::max()}; + for (int64_t value : values64) { + SCOPED_TRACE(::testing::Message() << "value = " << value); + + EXPECT_EQ(absl::int128(-value), -absl::int128(value)); + EXPECT_EQ(absl::int128(value), -absl::int128(-value)); + EXPECT_EQ(absl::MakeInt128(-value, 0), -absl::MakeInt128(value, 0)); + EXPECT_EQ(absl::MakeInt128(value, 0), -absl::MakeInt128(-value, 0)); + } +} + +TEST(Int128, LogicalNotTest) { + EXPECT_TRUE(!absl::int128(0)); + for (int i = 0; i < 64; ++i) { + EXPECT_FALSE(!absl::MakeInt128(0, uint64_t{1} << i)); + } + for (int i = 0; i < 63; ++i) { + EXPECT_FALSE(!absl::MakeInt128(int64_t{1} << i, 0)); + } +} + +TEST(Int128, AdditionSubtractionTest) { + // 64 bit pairs that will not cause overflow / underflow. These test negative + // carry; positive carry must be checked separately. + std::pair cases[]{ + {0, 0}, // 0, 0 + {0, 2945781290834}, // 0, + + {1908357619234, 0}, // +, 0 + {0, -1204895918245}, // 0, - + {-2957928523560, 0}, // -, 0 + {89023982312461, 98346012567134}, // +, + + {-63454234568239, -23456235230773}, // -, - + {98263457263502, -21428561935925}, // +, - + {-88235237438467, 15923659234573}, // -, + + }; + for (const auto& pair : cases) { + SCOPED_TRACE(::testing::Message() + << "pair = {" << pair.first << ", " << pair.second << '}'); + + EXPECT_EQ(absl::int128(pair.first + pair.second), + absl::int128(pair.first) + absl::int128(pair.second)); + EXPECT_EQ(absl::int128(pair.second + pair.first), + absl::int128(pair.second) += absl::int128(pair.first)); + + EXPECT_EQ(absl::int128(pair.first - pair.second), + absl::int128(pair.first) - absl::int128(pair.second)); + EXPECT_EQ(absl::int128(pair.second - pair.first), + absl::int128(pair.second) -= absl::int128(pair.first)); + + EXPECT_EQ( + absl::MakeInt128(pair.second + pair.first, 0), + absl::MakeInt128(pair.second, 0) + absl::MakeInt128(pair.first, 0)); + EXPECT_EQ( + absl::MakeInt128(pair.first + pair.second, 0), + absl::MakeInt128(pair.first, 0) += absl::MakeInt128(pair.second, 0)); + + EXPECT_EQ( + absl::MakeInt128(pair.second - pair.first, 0), + absl::MakeInt128(pair.second, 0) - absl::MakeInt128(pair.first, 0)); + EXPECT_EQ( + absl::MakeInt128(pair.first - pair.second, 0), + absl::MakeInt128(pair.first, 0) -= absl::MakeInt128(pair.second, 0)); + } + + // check positive carry + EXPECT_EQ(absl::MakeInt128(31, 0), + absl::MakeInt128(20, 1) + + absl::MakeInt128(10, std::numeric_limits::max())); +} + +TEST(Int128, IncrementDecrementTest) { + absl::int128 value = 0; + EXPECT_EQ(0, value++); + EXPECT_EQ(1, value); + EXPECT_EQ(1, value--); + EXPECT_EQ(0, value); + EXPECT_EQ(-1, --value); + EXPECT_EQ(-1, value); + EXPECT_EQ(0, ++value); + EXPECT_EQ(0, value); +} + +TEST(Int128, MultiplicationTest) { + // 1 bit x 1 bit, and negative combinations + for (int i = 0; i < 64; ++i) { + for (int j = 0; j < 127 - i; ++j) { + SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); + absl::int128 a = absl::int128(1) << i; + absl::int128 b = absl::int128(1) << j; + absl::int128 c = absl::int128(1) << (i + j); + + EXPECT_EQ(c, a * b); + EXPECT_EQ(-c, -a * b); + EXPECT_EQ(-c, a * -b); + EXPECT_EQ(c, -a * -b); + + EXPECT_EQ(c, absl::int128(a) *= b); + EXPECT_EQ(-c, absl::int128(-a) *= b); + EXPECT_EQ(-c, absl::int128(a) *= -b); + EXPECT_EQ(c, absl::int128(-a) *= -b); + } + } + + // Pairs of random values that will not overflow signed 64-bit multiplication + std::pair small_values[] = { + {0x5e61, 0xf29f79ca14b4}, // +, + + {0x3e033b, -0x612c0ee549}, // +, - + {-0x052ce7e8, 0x7c728f0f}, // -, + + {-0x3af7054626, -0xfb1e1d}, // -, - + }; + for (const std::pair& pair : small_values) { + SCOPED_TRACE(::testing::Message() + << "pair = {" << pair.first << ", " << pair.second << '}'); + + EXPECT_EQ(absl::int128(pair.first * pair.second), + absl::int128(pair.first) * absl::int128(pair.second)); + EXPECT_EQ(absl::int128(pair.first * pair.second), + absl::int128(pair.first) *= absl::int128(pair.second)); + + EXPECT_EQ(absl::MakeInt128(pair.first * pair.second, 0), + absl::MakeInt128(pair.first, 0) * absl::int128(pair.second)); + EXPECT_EQ(absl::MakeInt128(pair.first * pair.second, 0), + absl::MakeInt128(pair.first, 0) *= absl::int128(pair.second)); + } + + // Pairs of positive random values that will not overflow 64-bit + // multiplication and can be left shifted by 32 without overflow + std::pair small_values2[] = { + {0x1bb0a110, 0x31487671}, + {0x4792784e, 0x28add7d7}, + {0x7b66553a, 0x11dff8ef}, + }; + for (const std::pair& pair : small_values2) { + SCOPED_TRACE(::testing::Message() + << "pair = {" << pair.first << ", " << pair.second << '}'); + + absl::int128 a = absl::int128(pair.first << 32); + absl::int128 b = absl::int128(pair.second << 32); + absl::int128 c = absl::MakeInt128(pair.first * pair.second, 0); + + EXPECT_EQ(c, a * b); + EXPECT_EQ(-c, -a * b); + EXPECT_EQ(-c, a * -b); + EXPECT_EQ(c, -a * -b); + + EXPECT_EQ(c, absl::int128(a) *= b); + EXPECT_EQ(-c, absl::int128(-a) *= b); + EXPECT_EQ(-c, absl::int128(a) *= -b); + EXPECT_EQ(c, absl::int128(-a) *= -b); + } + + // check 0, 1, and -1 behavior with large values + absl::int128 large_values[] = { + {absl::MakeInt128(0xd66f061af02d0408, 0x727d2846cb475b53)}, + {absl::MakeInt128(0x27b8d5ed6104452d, 0x03f8a33b0ee1df4f)}, + {-absl::MakeInt128(0x621b6626b9e8d042, 0x27311ac99df00938)}, + {-absl::MakeInt128(0x34e0656f1e95fb60, 0x4281cfd731257a47)}, + }; + for (absl::int128 value : large_values) { + EXPECT_EQ(0, 0 * value); + EXPECT_EQ(0, value * 0); + EXPECT_EQ(0, absl::int128(0) *= value); + EXPECT_EQ(0, value *= 0); + + EXPECT_EQ(value, 1 * value); + EXPECT_EQ(value, value * 1); + EXPECT_EQ(value, absl::int128(1) *= value); + EXPECT_EQ(value, value *= 1); + + EXPECT_EQ(-value, -1 * value); + EXPECT_EQ(-value, value * -1); + EXPECT_EQ(-value, absl::int128(-1) *= value); + EXPECT_EQ(-value, value *= -1); + } + + // Manually calculated random large value cases + EXPECT_EQ(absl::MakeInt128(0xcd0efd3442219bb, 0xde47c05bcd9df6e1), + absl::MakeInt128(0x7c6448, 0x3bc4285c47a9d253) * 0x1a6037537b); + EXPECT_EQ(-absl::MakeInt128(0x1f8f149850b1e5e6, 0x1e50d6b52d272c3e), + -absl::MakeInt128(0x23, 0x2e68a513ca1b8859) * 0xe5a434cd14866e); + EXPECT_EQ(-absl::MakeInt128(0x55cae732029d1fce, 0xca6474b6423263e4), + 0xa9b98a8ddf66bc * -absl::MakeInt128(0x81, 0x672e58231e2469d7)); + EXPECT_EQ(absl::MakeInt128(0x19c8b7620b507dc4, 0xfec042b71a5f29a4), + -0x3e39341147 * -absl::MakeInt128(0x6a14b2, 0x5ed34cca42327b3c)); + + EXPECT_EQ(absl::MakeInt128(0xcd0efd3442219bb, 0xde47c05bcd9df6e1), + absl::MakeInt128(0x7c6448, 0x3bc4285c47a9d253) *= 0x1a6037537b); + EXPECT_EQ(-absl::MakeInt128(0x1f8f149850b1e5e6, 0x1e50d6b52d272c3e), + -absl::MakeInt128(0x23, 0x2e68a513ca1b8859) *= 0xe5a434cd14866e); + EXPECT_EQ(-absl::MakeInt128(0x55cae732029d1fce, 0xca6474b6423263e4), + absl::int128(0xa9b98a8ddf66bc) *= + -absl::MakeInt128(0x81, 0x672e58231e2469d7)); + EXPECT_EQ(absl::MakeInt128(0x19c8b7620b507dc4, 0xfec042b71a5f29a4), + absl::int128(-0x3e39341147) *= + -absl::MakeInt128(0x6a14b2, 0x5ed34cca42327b3c)); +} + +TEST(Int128, DivisionAndModuloTest) { + // Check against 64 bit division and modulo operators with a sample of + // randomly generated pairs. + std::pair small_pairs[] = { + {0x15f2a64138, 0x67da05}, {0x5e56d194af43045f, 0xcf1543fb99}, + {0x15e61ed052036a, -0xc8e6}, {0x88125a341e85, -0xd23fb77683}, + {-0xc06e20, 0x5a}, {-0x4f100219aea3e85d, 0xdcc56cb4efe993}, + {-0x168d629105, -0xa7}, {-0x7b44e92f03ab2375, -0x6516}, + }; + for (const std::pair& pair : small_pairs) { + SCOPED_TRACE(::testing::Message() + << "pair = {" << pair.first << ", " << pair.second << '}'); + + absl::int128 dividend = pair.first; + absl::int128 divisor = pair.second; + int64_t quotient = pair.first / pair.second; + int64_t remainder = pair.first % pair.second; + + EXPECT_EQ(quotient, dividend / divisor); + EXPECT_EQ(quotient, absl::int128(dividend) /= divisor); + EXPECT_EQ(remainder, dividend % divisor); + EXPECT_EQ(remainder, absl::int128(dividend) %= divisor); + } + + // Test behavior with 0, 1, and -1 with a sample of randomly generated large + // values. + absl::int128 values[] = { + absl::MakeInt128(0x63d26ee688a962b2, 0x9e1411abda5c1d70), + absl::MakeInt128(0x152f385159d6f986, 0xbf8d48ef63da395d), + -absl::MakeInt128(0x3098d7567030038c, 0x14e7a8a098dc2164), + -absl::MakeInt128(0x49a037aca35c809f, 0xa6a87525480ef330), + }; + for (absl::int128 value : values) { + SCOPED_TRACE(::testing::Message() << "value = " << value); + + EXPECT_EQ(0, 0 / value); + EXPECT_EQ(0, absl::int128(0) /= value); + EXPECT_EQ(0, 0 % value); + EXPECT_EQ(0, absl::int128(0) %= value); + + EXPECT_EQ(value, value / 1); + EXPECT_EQ(value, absl::int128(value) /= 1); + EXPECT_EQ(0, value % 1); + EXPECT_EQ(0, absl::int128(value) %= 1); + + EXPECT_EQ(-value, value / -1); + EXPECT_EQ(-value, absl::int128(value) /= -1); + EXPECT_EQ(0, value % -1); + EXPECT_EQ(0, absl::int128(value) %= -1); + } + + // Min and max values + EXPECT_EQ(0, absl::Int128Max() / absl::Int128Min()); + EXPECT_EQ(absl::Int128Max(), absl::Int128Max() % absl::Int128Min()); + EXPECT_EQ(-1, absl::Int128Min() / absl::Int128Max()); + EXPECT_EQ(-1, absl::Int128Min() % absl::Int128Max()); + + // Power of two division and modulo of random large dividends + absl::int128 positive_values[] = { + absl::MakeInt128(0x21e1a1cc69574620, 0xe7ac447fab2fc869), + absl::MakeInt128(0x32c2ff3ab89e66e8, 0x03379a613fd1ce74), + absl::MakeInt128(0x6f32ca786184dcaf, 0x046f9c9ecb3a9ce1), + absl::MakeInt128(0x1aeb469dd990e0ee, 0xda2740f243cd37eb), + }; + for (absl::int128 value : positive_values) { + for (int i = 0; i < 127; ++i) { + SCOPED_TRACE(::testing::Message() + << "value = " << value << "; i = " << i); + absl::int128 power_of_two = absl::int128(1) << i; + + EXPECT_EQ(value >> i, value / power_of_two); + EXPECT_EQ(value >> i, absl::int128(value) /= power_of_two); + EXPECT_EQ(value & (power_of_two - 1), value % power_of_two); + EXPECT_EQ(value & (power_of_two - 1), + absl::int128(value) %= power_of_two); + } + } + + // Manually calculated cases with random large dividends + struct DivisionModCase { + absl::int128 dividend; + absl::int128 divisor; + absl::int128 quotient; + absl::int128 remainder; + }; + DivisionModCase manual_cases[] = { + {absl::MakeInt128(0x6ada48d489007966, 0x3c9c5c98150d5d69), + absl::MakeInt128(0x8bc308fb, 0x8cb9cc9a3b803344), 0xc3b87e08, + absl::MakeInt128(0x1b7db5e1, 0xd9eca34b7af04b49)}, + {absl::MakeInt128(0xd6946511b5b, 0x4886c5c96546bf5f), + -absl::MakeInt128(0x263b, 0xfd516279efcfe2dc), -0x59cbabf0, + absl::MakeInt128(0x622, 0xf462909155651d1f)}, + {-absl::MakeInt128(0x33db734f9e8d1399, 0x8447ac92482bca4d), 0x37495078240, + -absl::MakeInt128(0xf01f1, 0xbc0368bf9a77eae8), -0x21a508f404d}, + {-absl::MakeInt128(0x13f837b409a07e7d, 0x7fc8e248a7d73560), -0x1b9f, + absl::MakeInt128(0xb9157556d724, 0xb14f635714d7563e), -0x1ade}, + }; + for (const DivisionModCase test_case : manual_cases) { + EXPECT_EQ(test_case.quotient, test_case.dividend / test_case.divisor); + EXPECT_EQ(test_case.quotient, + absl::int128(test_case.dividend) /= test_case.divisor); + EXPECT_EQ(test_case.remainder, test_case.dividend % test_case.divisor); + EXPECT_EQ(test_case.remainder, + absl::int128(test_case.dividend) %= test_case.divisor); + } +} + +TEST(Int128, BitwiseLogicTest) { + EXPECT_EQ(absl::int128(-1), ~absl::int128(0)); + + absl::int128 values[]{ + 0, -1, 0xde400bee05c3ff6b, absl::MakeInt128(0x7f32178dd81d634a, 0), + absl::MakeInt128(0xaf539057055613a9, 0x7d104d7d946c2e4d)}; + for (absl::int128 value : values) { + EXPECT_EQ(value, ~~value); + + EXPECT_EQ(value, value | value); + EXPECT_EQ(value, value & value); + EXPECT_EQ(0, value ^ value); + + EXPECT_EQ(value, absl::int128(value) |= value); + EXPECT_EQ(value, absl::int128(value) &= value); + EXPECT_EQ(0, absl::int128(value) ^= value); + + EXPECT_EQ(value, value | 0); + EXPECT_EQ(0, value & 0); + EXPECT_EQ(value, value ^ 0); + + EXPECT_EQ(absl::int128(-1), value | absl::int128(-1)); + EXPECT_EQ(value, value & absl::int128(-1)); + EXPECT_EQ(~value, value ^ absl::int128(-1)); + } + + // small sample of randomly generated int64_t's + std::pair pairs64[]{ + {0x7f86797f5e991af4, 0x1ee30494fb007c97}, + {0x0b278282bacf01af, 0x58780e0a57a49e86}, + {0x059f266ccb93a666, 0x3d5b731bae9286f5}, + {0x63c0c4820f12108c, 0x58166713c12e1c3a}, + {0x381488bb2ed2a66e, 0x2220a3eb76a3698c}, + {0x2a0a0dfb81e06f21, 0x4b60585927f5523c}, + {0x555b1c3a03698537, 0x25478cd19d8e53cb}, + {0x4750f6f27d779225, 0x16397553c6ff05fc}, + }; + for (const std::pair& pair : pairs64) { + SCOPED_TRACE(::testing::Message() + << "pair = {" << pair.first << ", " << pair.second << '}'); + + EXPECT_EQ(absl::MakeInt128(~pair.first, ~pair.second), + ~absl::MakeInt128(pair.first, pair.second)); + + EXPECT_EQ(absl::int128(pair.first & pair.second), + absl::int128(pair.first) & absl::int128(pair.second)); + EXPECT_EQ(absl::int128(pair.first | pair.second), + absl::int128(pair.first) | absl::int128(pair.second)); + EXPECT_EQ(absl::int128(pair.first ^ pair.second), + absl::int128(pair.first) ^ absl::int128(pair.second)); + + EXPECT_EQ(absl::int128(pair.first & pair.second), + absl::int128(pair.first) &= absl::int128(pair.second)); + EXPECT_EQ(absl::int128(pair.first | pair.second), + absl::int128(pair.first) |= absl::int128(pair.second)); + EXPECT_EQ(absl::int128(pair.first ^ pair.second), + absl::int128(pair.first) ^= absl::int128(pair.second)); + + EXPECT_EQ( + absl::MakeInt128(pair.first & pair.second, 0), + absl::MakeInt128(pair.first, 0) & absl::MakeInt128(pair.second, 0)); + EXPECT_EQ( + absl::MakeInt128(pair.first | pair.second, 0), + absl::MakeInt128(pair.first, 0) | absl::MakeInt128(pair.second, 0)); + EXPECT_EQ( + absl::MakeInt128(pair.first ^ pair.second, 0), + absl::MakeInt128(pair.first, 0) ^ absl::MakeInt128(pair.second, 0)); + + EXPECT_EQ( + absl::MakeInt128(pair.first & pair.second, 0), + absl::MakeInt128(pair.first, 0) &= absl::MakeInt128(pair.second, 0)); + EXPECT_EQ( + absl::MakeInt128(pair.first | pair.second, 0), + absl::MakeInt128(pair.first, 0) |= absl::MakeInt128(pair.second, 0)); + EXPECT_EQ( + absl::MakeInt128(pair.first ^ pair.second, 0), + absl::MakeInt128(pair.first, 0) ^= absl::MakeInt128(pair.second, 0)); + } +} + +TEST(Int128, BitwiseShiftTest) { + for (int i = 0; i < 64; ++i) { + for (int j = 0; j <= i; ++j) { + // Left shift from j-th bit to i-th bit. + SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); + EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) << (i - j)); + EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) <<= (i - j)); + } + } + for (int i = 0; i < 63; ++i) { + for (int j = 0; j < 64; ++j) { + // Left shift from j-th bit to (i + 64)-th bit. + SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); + EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), + absl::int128(uint64_t{1} << j) << (i + 64 - j)); + EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), + absl::int128(uint64_t{1} << j) <<= (i + 64 - j)); + } + for (int j = 0; j <= i; ++j) { + // Left shift from (j + 64)-th bit to (i + 64)-th bit. + SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); + EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), + absl::MakeInt128(uint64_t{1} << j, 0) << (i - j)); + EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), + absl::MakeInt128(uint64_t{1} << j, 0) <<= (i - j)); + } + } + + for (int i = 0; i < 64; ++i) { + for (int j = i; j < 64; ++j) { + // Right shift from j-th bit to i-th bit. + SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); + EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) >> (j - i)); + EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) >>= (j - i)); + } + for (int j = 0; j < 63; ++j) { + // Right shift from (j + 64)-th bit to i-th bit. + SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); + EXPECT_EQ(uint64_t{1} << i, + absl::MakeInt128(uint64_t{1} << j, 0) >> (j + 64 - i)); + EXPECT_EQ(uint64_t{1} << i, + absl::MakeInt128(uint64_t{1} << j, 0) >>= (j + 64 - i)); + } + } + for (int i = 0; i < 63; ++i) { + for (int j = i; j < 63; ++j) { + // Right shift from (j + 64)-th bit to (i + 64)-th bit. + SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j); + EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), + absl::MakeInt128(uint64_t{1} << j, 0) >> (j - i)); + EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0), + absl::MakeInt128(uint64_t{1} << j, 0) >>= (j - i)); + } + } +} + +TEST(Int128, NumericLimitsTest) { + static_assert(std::numeric_limits::is_specialized, ""); + static_assert(std::numeric_limits::is_signed, ""); + static_assert(std::numeric_limits::is_integer, ""); + EXPECT_EQ(static_cast(127 * std::log10(2)), + std::numeric_limits::digits10); + EXPECT_EQ(absl::Int128Min(), std::numeric_limits::min()); + EXPECT_EQ(absl::Int128Min(), std::numeric_limits::lowest()); + EXPECT_EQ(absl::Int128Max(), std::numeric_limits::max()); +} + } // namespace diff --git a/absl/random/internal/platform.h b/absl/random/internal/platform.h index a5a42cbb..bbdb4e62 100644 --- a/absl/random/internal/platform.h +++ b/absl/random/internal/platform.h @@ -162,7 +162,8 @@ // iOS does not support dispatch, even on x86, since applications // should be bundled as fat binaries, with a different build tailored for // each specific supported platform/architecture. -#if defined(__APPLE__) && (TARGET_OS_IPHONE || TARGET_OS_IPHONE_SIMULATOR) +#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \ + (defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR) #undef ABSL_RANDOM_INTERNAL_AES_DISPATCH #define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0 #endif diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc index b40be8ff..b567a5c5 100644 --- a/absl/strings/internal/str_format/arg.cc +++ b/absl/strings/internal/str_format/arg.cc @@ -32,6 +32,10 @@ void ReducePadding(size_t n, size_t *capacity) { template struct MakeUnsigned : std::make_unsigned {}; template <> +struct MakeUnsigned { + using type = absl::uint128; +}; +template <> struct MakeUnsigned { using type = absl::uint128; }; @@ -39,6 +43,8 @@ struct MakeUnsigned { template struct IsSigned : std::is_signed {}; template <> +struct IsSigned : std::true_type {}; +template <> struct IsSigned : std::false_type {}; class ConvertedIntInfo { @@ -363,6 +369,11 @@ IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } +IntegralConvertResult FormatConvertImpl(absl::int128 v, + const ConversionSpec conv, + FormatSinkImpl *sink) { + return {ConvertIntArg(v, conv, sink)}; +} IntegralConvertResult FormatConvertImpl(absl::uint128 v, const ConversionSpec conv, FormatSinkImpl *sink) { @@ -372,6 +383,7 @@ IntegralConvertResult FormatConvertImpl(absl::uint128 v, ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(); + } // namespace str_format_internal } // namespace absl diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index 5cb3a14d..2119ca00 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -144,6 +144,8 @@ IntegralConvertResult FormatConvertImpl(long long v, // NOLINT IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT ConversionSpec conv, FormatSinkImpl* sink); +IntegralConvertResult FormatConvertImpl(int128 v, ConversionSpec conv, + FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(uint128 v, ConversionSpec conv, FormatSinkImpl* sink); template ::value, int> = 0> @@ -408,6 +410,7 @@ class FormatArgImpl { __VA_ARGS__); \ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */ \ __VA_ARGS__); \ + ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __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__); \ @@ -418,6 +421,7 @@ class FormatArgImpl { ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern); + } // namespace str_format_internal } // namespace absl diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index ab8d5391..5f198059 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -390,7 +390,6 @@ typedef ::testing::Types< AllIntTypes; INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes, TypedFormatConvertTest, AllIntTypes); - TEST_F(FormatConvertTest, VectorBool) { // Make sure vector's values behave as bools. std::vector v = {true, false}; @@ -402,6 +401,42 @@ TEST_F(FormatConvertTest, VectorBool) { FormatArgImpl(cv[0]), FormatArgImpl(cv[1])}))); } + +TEST_F(FormatConvertTest, Int128) { + absl::int128 positive = static_cast(0x1234567890abcdef) * 1979; + absl::int128 negative = -positive; + absl::int128 max = absl::Int128Max(), min = absl::Int128Min(); + const FormatArgImpl args[] = {FormatArgImpl(positive), + FormatArgImpl(negative), FormatArgImpl(max), + FormatArgImpl(min)}; + + struct Case { + const char* format; + const char* expected; + } cases[] = { + {"%1$d", "2595989796776606496405"}, + {"%1$30d", " 2595989796776606496405"}, + {"%1$-30d", "2595989796776606496405 "}, + {"%1$u", "2595989796776606496405"}, + {"%1$x", "8cba9876066020f695"}, + {"%2$d", "-2595989796776606496405"}, + {"%2$30d", " -2595989796776606496405"}, + {"%2$-30d", "-2595989796776606496405 "}, + {"%2$u", "340282366920938460867384810655161715051"}, + {"%2$x", "ffffffffffffff73456789f99fdf096b"}, + {"%3$d", "170141183460469231731687303715884105727"}, + {"%3$u", "170141183460469231731687303715884105727"}, + {"%3$x", "7fffffffffffffffffffffffffffffff"}, + {"%4$d", "-170141183460469231731687303715884105728"}, + {"%4$x", "80000000000000000000000000000000"}, + }; + + for (auto c : cases) { + UntypedFormatSpecImpl format(c.format); + EXPECT_EQ(c.expected, FormatPack(format, absl::MakeSpan(args))); + } +} + TEST_F(FormatConvertTest, Uint128) { absl::uint128 v = static_cast(0x1234567890abcdef) * 1979; absl::uint128 max = absl::Uint128Max(); diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h index 07075e80..6a650874 100644 --- a/absl/strings/string_view.h +++ b/absl/strings/string_view.h @@ -290,7 +290,8 @@ class string_view { constexpr const_reference at(size_type i) const { return ABSL_PREDICT_TRUE(i < size()) ? ptr_[i] - : (base_internal::ThrowStdOutOfRange("absl::string_view::at"), + : ((void)base_internal::ThrowStdOutOfRange( + "absl::string_view::at"), ptr_[i]); } @@ -511,7 +512,7 @@ class string_view { (std::numeric_limits::max)(); static constexpr size_type CheckLengthInternal(size_type len) { - return ABSL_ASSERT(len <= kMaxSize), len; + return (void)ABSL_ASSERT(len <= kMaxSize), len; } static constexpr size_type StrlenInternal(const char* str) { diff --git a/absl/time/internal/test_util.cc b/absl/time/internal/test_util.cc index 59166a7c..fbddbb73 100644 --- a/absl/time/internal/test_util.cc +++ b/absl/time/internal/test_util.cc @@ -116,7 +116,10 @@ std::unique_ptr TestFactory( } // namespace +#if !defined(__MINGW32__) +// MinGW does not support the weak symbol extension mechanism. ZoneInfoSourceFactory zone_info_source_factory = TestFactory; +#endif } // namespace cctz_extension } // namespace time_internal diff --git a/absl/time/time.h b/absl/time/time.h index 46ac26b3..be064813 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -1412,8 +1412,7 @@ constexpr Duration FromInt64(int64_t v, std::ratio<3600>) { // IsValidRep64(0) is true if the expression `int64_t{std::declval()}` is // valid. That is, if a T can be assigned to an int64_t without narrowing. template -constexpr auto IsValidRep64(int) - -> decltype(int64_t{std::declval()}, bool()) { +constexpr auto IsValidRep64(int) -> decltype(int64_t{std::declval()} == 0) { return true; } template -- cgit v1.2.3 From 12bc53e0318d80569270a5b26ccbc62b52022b89 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 12 Dec 2019 10:36:03 -0800 Subject: Export of internal Abseil changes -- c99f979ad34f155fbeeea69b88bdc7458d89a21c by Derek Mauro : Remove a floating point division by zero test. This isn't testing behavior related to the library, and MSVC warns about it in opt mode. PiperOrigin-RevId: 285220804 -- 68b015491f0dbf1ab547994673281abd1f34cd4b by Gennadiy Rozental : This CL introduces following changes to the class FlagImpl: * We eliminate the CommandLineFlagLocks struct. Instead callback guard and callback function are combined into a single CallbackData struct, while primary data lock is stored separately. * CallbackData member of class FlagImpl is initially set to be nullptr and is only allocated and initialized when a flag's callback is being set. For most flags we do not pay for the extra space and extra absl::Mutex now. * Primary data guard is stored in data_guard_ data member. This is a properly aligned character buffer of necessary size. During initialization of the flag we construct absl::Mutex in this space using placement new call. * We now avoid extra value copy after successful attempt to parse value out of string. Instead we swap flag's current value with tentative value we just produced. PiperOrigin-RevId: 285132636 -- ed45d118fb818969eb13094cf7827c885dfc562c by Tom Manshreck : Change null-term* (and nul-term*) to NUL-term* in comments PiperOrigin-RevId: 285036610 -- 729619017944db895ce8d6d29c1995aa2e5628a5 by Derek Mauro : Use the Posix implementation of thread identity on MinGW. Some versions of MinGW suffer from thread_local bugs. PiperOrigin-RevId: 285022920 -- 39a25493503c76885bc3254c28f66a251c5b5bb0 by Greg Falcon : Implementation detail change. Add further ABSL_NAMESPACE_BEGIN and _END annotation macros to files in Abseil. PiperOrigin-RevId: 285012012 GitOrigin-RevId: c99f979ad34f155fbeeea69b88bdc7458d89a21c Change-Id: I4c85d3704e45d11a9ac50d562f39640a6adbedc1 --- absl/algorithm/BUILD.bazel | 1 + absl/algorithm/CMakeLists.txt | 2 + absl/algorithm/algorithm.h | 4 + absl/algorithm/container.h | 2 + absl/base/internal/raw_logging.h | 2 +- absl/base/internal/thread_identity.h | 2 +- absl/container/BUILD.bazel | 8 ++ absl/container/CMakeLists.txt | 8 ++ absl/container/btree_map.h | 2 + absl/container/btree_set.h | 2 + absl/container/btree_test.cc | 2 + absl/container/btree_test.h | 2 + absl/container/fixed_array.h | 2 + .../container/fixed_array_exception_safety_test.cc | 2 + absl/container/flat_hash_map.h | 2 + absl/container/flat_hash_map_test.cc | 2 + absl/container/flat_hash_set.h | 2 + absl/container/flat_hash_set_test.cc | 2 + absl/container/inlined_vector.h | 2 + absl/container/internal/btree.h | 2 + absl/container/internal/btree_container.h | 2 + absl/container/internal/common.h | 2 + absl/container/internal/compressed_tuple.h | 2 + absl/container/internal/compressed_tuple_test.cc | 2 + absl/container/internal/container_memory.h | 2 + absl/container/internal/container_memory_test.cc | 2 + absl/container/internal/counting_allocator.h | 4 + absl/container/internal/hash_function_defaults.h | 2 + .../internal/hash_function_defaults_test.cc | 4 + absl/container/internal/hash_generator_testing.cc | 2 + absl/container/internal/hash_generator_testing.h | 2 + absl/container/internal/hash_policy_testing.h | 2 + .../container/internal/hash_policy_testing_test.cc | 2 + absl/container/internal/hash_policy_traits.h | 2 + absl/container/internal/hash_policy_traits_test.cc | 2 + absl/container/internal/hashtable_debug.h | 2 + absl/container/internal/hashtable_debug_hooks.h | 4 + absl/container/internal/hashtablez_sampler.cc | 2 + absl/container/internal/hashtablez_sampler.h | 2 + .../hashtablez_sampler_force_weak_definition.cc | 2 + absl/container/internal/hashtablez_sampler_test.cc | 2 + absl/container/internal/inlined_vector.h | 2 + absl/container/internal/layout.h | 2 + absl/container/internal/layout_test.cc | 2 + absl/container/internal/node_hash_policy.h | 4 + absl/container/internal/node_hash_policy_test.cc | 2 + absl/container/internal/raw_hash_map.h | 2 + absl/container/internal/raw_hash_set.cc | 2 + absl/container/internal/raw_hash_set.h | 2 + .../internal/raw_hash_set_allocator_test.cc | 2 + absl/container/internal/raw_hash_set_test.cc | 2 + absl/container/internal/test_instance_tracker.cc | 2 + absl/container/internal/test_instance_tracker.h | 2 + absl/container/internal/tracked.h | 5 + .../internal/unordered_map_constructor_test.h | 2 + .../container/internal/unordered_map_lookup_test.h | 2 + .../internal/unordered_map_members_test.h | 2 + .../internal/unordered_map_modifiers_test.h | 2 + absl/container/internal/unordered_map_test.cc | 2 + .../internal/unordered_set_constructor_test.h | 2 + .../container/internal/unordered_set_lookup_test.h | 2 + .../internal/unordered_set_members_test.h | 2 + .../internal/unordered_set_modifiers_test.h | 2 + absl/container/internal/unordered_set_test.cc | 2 + absl/container/node_hash_map.h | 2 + absl/container/node_hash_map_test.cc | 2 + absl/container/node_hash_set.h | 2 + absl/container/node_hash_set_test.cc | 2 + absl/debugging/BUILD.bazel | 18 +++- absl/debugging/CMakeLists.txt | 6 ++ absl/debugging/failure_signal_handler.cc | 2 + absl/debugging/failure_signal_handler.h | 4 + absl/debugging/internal/address_is_readable.cc | 4 + absl/debugging/internal/address_is_readable.h | 4 + absl/debugging/internal/demangle.cc | 2 + absl/debugging/internal/demangle.h | 4 + absl/debugging/internal/demangle_test.cc | 2 + absl/debugging/internal/elf_mem_image.cc | 2 + absl/debugging/internal/elf_mem_image.h | 4 + absl/debugging/internal/examine_stack.cc | 2 + absl/debugging/internal/examine_stack.h | 4 + absl/debugging/internal/stack_consumption.cc | 2 + absl/debugging/internal/stack_consumption.h | 4 + absl/debugging/internal/stack_consumption_test.cc | 2 + absl/debugging/internal/stacktrace_aarch64-inl.inc | 2 + absl/debugging/internal/stacktrace_arm-inl.inc | 2 + absl/debugging/internal/stacktrace_generic-inl.inc | 2 + absl/debugging/internal/stacktrace_powerpc-inl.inc | 2 + .../internal/stacktrace_unimplemented-inl.inc | 2 + absl/debugging/internal/stacktrace_win32-inl.inc | 2 + absl/debugging/internal/stacktrace_x86-inl.inc | 2 + absl/debugging/internal/symbolize.h | 6 ++ absl/debugging/internal/vdso_support.cc | 2 + absl/debugging/internal/vdso_support.h | 2 + absl/debugging/leak_check.cc | 4 + absl/debugging/leak_check.h | 4 + absl/debugging/stacktrace.cc | 2 + absl/debugging/stacktrace.h | 4 + absl/debugging/symbolize.h | 2 + absl/debugging/symbolize_elf.inc | 2 + absl/debugging/symbolize_unimplemented.inc | 2 + absl/debugging/symbolize_win32.inc | 2 + absl/flags/declare.h | 2 + absl/flags/flag.cc | 2 + absl/flags/flag.h | 2 + absl/flags/flag_test_defs.cc | 2 + absl/flags/internal/commandlineflag.cc | 2 + absl/flags/internal/commandlineflag.h | 4 +- absl/flags/internal/flag.cc | 113 ++++++++++++++------- absl/flags/internal/flag.h | 54 +++++----- absl/flags/internal/parse.h | 2 + absl/flags/internal/path_util.h | 2 + absl/flags/internal/program_name.cc | 2 + absl/flags/internal/program_name.h | 2 + absl/flags/internal/registry.cc | 4 +- absl/flags/internal/registry.h | 2 + absl/flags/internal/type_erased.cc | 2 + absl/flags/internal/type_erased.h | 2 + absl/flags/internal/usage.cc | 2 + absl/flags/internal/usage.h | 2 + absl/flags/marshalling.cc | 2 + absl/flags/marshalling.h | 2 + absl/flags/parse.cc | 4 + absl/flags/parse.h | 2 + absl/flags/usage.cc | 2 + absl/flags/usage.h | 2 + absl/flags/usage_config.cc | 2 + absl/flags/usage_config.h | 2 + absl/functional/function_ref.h | 2 + absl/functional/function_ref_benchmark.cc | 2 + absl/functional/function_ref_test.cc | 2 + absl/functional/internal/function_ref.h | 2 + absl/hash/hash.h | 2 + absl/hash/hash_test.cc | 2 + absl/hash/hash_testing.h | 2 + absl/hash/internal/city.cc | 2 + absl/hash/internal/city.h | 5 + absl/hash/internal/city_test.cc | 2 + absl/hash/internal/hash.cc | 2 + absl/hash/internal/hash.h | 2 + absl/hash/internal/spy_hash_state.h | 2 + absl/memory/memory.h | 2 + absl/memory/memory_exception_safety_test.cc | 2 + absl/meta/type_traits.h | 2 + absl/numeric/int128.cc | 2 + absl/numeric/int128.h | 6 ++ absl/random/CMakeLists.txt | 14 +++ absl/random/bernoulli_distribution.h | 2 + absl/random/beta_distribution.h | 2 + absl/random/bit_gen_ref.h | 2 + absl/random/bit_gen_ref_test.cc | 2 + absl/random/discrete_distribution.cc | 2 + absl/random/discrete_distribution.h | 2 + absl/random/distribution_format_traits.h | 2 + absl/random/distributions.h | 2 + absl/random/exponential_distribution.h | 2 + absl/random/gaussian_distribution.cc | 2 + absl/random/gaussian_distribution.h | 2 + absl/random/internal/BUILD.bazel | 9 ++ absl/random/internal/chi_square.cc | 2 + absl/random/internal/chi_square.h | 4 + absl/random/internal/distribution_caller.h | 4 + absl/random/internal/distribution_test_util.cc | 2 + absl/random/internal/distribution_test_util.h | 2 + absl/random/internal/distributions.h | 2 + absl/random/internal/explicit_seed_seq.h | 4 + absl/random/internal/fast_uniform_bits.h | 4 + absl/random/internal/fast_uniform_bits_test.cc | 2 + absl/random/internal/fastmath.h | 2 + .../internal/gaussian_distribution_gentables.cc | 2 + absl/random/internal/generate_real.h | 2 + absl/random/internal/iostream_state_saver.h | 2 + absl/random/internal/mock_overload_set.h | 2 + absl/random/internal/mocking_bit_gen_base.h | 2 + absl/random/internal/nanobenchmark.cc | 2 + absl/random/internal/nanobenchmark.h | 4 + absl/random/internal/nanobenchmark_test.cc | 2 + absl/random/internal/nonsecure_base.h | 2 + absl/random/internal/pcg_engine.h | 2 + absl/random/internal/pool_urbg.cc | 2 + absl/random/internal/pool_urbg.h | 2 + absl/random/internal/randen.cc | 2 + absl/random/internal/randen.h | 2 + absl/random/internal/randen_detect.cc | 2 + absl/random/internal/randen_detect.h | 4 + absl/random/internal/randen_engine.h | 2 + absl/random/internal/randen_hwaes.cc | 4 + absl/random/internal/randen_hwaes.h | 4 + absl/random/internal/randen_slow.cc | 2 + absl/random/internal/randen_slow.h | 4 + absl/random/internal/randen_traits.h | 4 + absl/random/internal/salted_seed_seq.h | 2 + absl/random/internal/seed_material.cc | 2 + absl/random/internal/seed_material.h | 2 + absl/random/internal/sequence_urbg.h | 4 + absl/random/internal/traits.h | 2 + absl/random/internal/uniform_helper.h | 2 + absl/random/internal/wide_multiply.h | 2 + absl/random/log_uniform_int_distribution.h | 2 + absl/random/mock_distributions.h | 2 + absl/random/mocking_bit_gen.cc | 2 + absl/random/mocking_bit_gen.h | 2 + absl/random/poisson_distribution.h | 2 + absl/random/random.h | 2 + absl/random/seed_gen_exception.cc | 2 + absl/random/seed_gen_exception.h | 4 + absl/random/seed_sequences.cc | 2 + absl/random/seed_sequences.h | 2 + absl/random/uniform_int_distribution.h | 2 + absl/random/uniform_real_distribution.h | 2 + absl/random/zipf_distribution.h | 2 + absl/strings/BUILD.bazel | 5 + absl/strings/CMakeLists.txt | 6 ++ absl/strings/ascii.cc | 2 + absl/strings/ascii.h | 2 + absl/strings/charconv.cc | 2 + absl/strings/charconv.h | 4 + absl/strings/escaping.cc | 2 + absl/strings/escaping.h | 2 + absl/strings/internal/char_map.h | 2 + absl/strings/internal/charconv_bigint.cc | 2 + absl/strings/internal/charconv_bigint.h | 2 + absl/strings/internal/charconv_bigint_test.cc | 2 + absl/strings/internal/charconv_parse.cc | 2 + absl/strings/internal/charconv_parse.h | 3 + absl/strings/internal/escaping_test_common.h | 2 + absl/strings/internal/memutil.cc | 2 + absl/strings/internal/memutil.h | 2 + absl/strings/internal/numbers_test_common.h | 4 + absl/strings/internal/ostringstream.cc | 2 + absl/strings/internal/ostringstream.h | 2 + absl/strings/internal/pow10_helper.cc | 2 + absl/strings/internal/pow10_helper.h | 4 + absl/strings/internal/pow10_helper_test.cc | 2 + absl/strings/internal/resize_uninitialized.h | 2 + absl/strings/internal/stl_type_traits.h | 2 + absl/strings/internal/str_format/arg.cc | 2 + absl/strings/internal/str_format/arg.h | 2 + absl/strings/internal/str_format/arg_test.cc | 2 + absl/strings/internal/str_format/bind.cc | 2 + absl/strings/internal/str_format/bind.h | 2 + absl/strings/internal/str_format/bind_test.cc | 2 + absl/strings/internal/str_format/checker.h | 2 + absl/strings/internal/str_format/checker_test.cc | 2 + absl/strings/internal/str_format/convert_test.cc | 2 + absl/strings/internal/str_format/extension.cc | 2 + absl/strings/internal/str_format/extension.h | 2 + .../internal/str_format/float_conversion.cc | 2 + .../strings/internal/str_format/float_conversion.h | 2 + absl/strings/internal/str_format/output.cc | 2 + absl/strings/internal/str_format/output.h | 2 + absl/strings/internal/str_format/output_test.cc | 2 + absl/strings/internal/str_format/parser.cc | 2 + absl/strings/internal/str_format/parser.h | 2 + absl/strings/internal/str_format/parser_test.cc | 2 + absl/strings/internal/str_join_internal.h | 2 + absl/strings/internal/str_split_internal.h | 2 + absl/strings/internal/utf8.cc | 2 + absl/strings/internal/utf8.h | 4 + absl/strings/match.cc | 2 + absl/strings/match.h | 4 +- absl/strings/numbers.cc | 2 + absl/strings/numbers.h | 4 + absl/strings/str_cat.cc | 2 + absl/strings/str_cat.h | 2 + absl/strings/str_format.h | 2 + absl/strings/str_format_test.cc | 2 + absl/strings/str_join.h | 2 + absl/strings/str_replace.cc | 2 + absl/strings/str_replace.h | 2 + absl/strings/str_split.cc | 2 + absl/strings/str_split.h | 2 + absl/strings/string_view.cc | 2 + absl/strings/string_view.h | 20 ++-- absl/strings/strip.h | 2 + absl/strings/substitute.cc | 2 + absl/strings/substitute.h | 2 + absl/synchronization/BUILD.bazel | 1 + absl/synchronization/CMakeLists.txt | 1 + absl/synchronization/barrier.cc | 2 + absl/synchronization/barrier.h | 2 + absl/synchronization/blocking_counter.cc | 2 + absl/synchronization/blocking_counter.h | 2 + absl/synchronization/blocking_counter_test.cc | 2 + .../internal/create_thread_identity.cc | 2 + .../internal/create_thread_identity.h | 2 + absl/synchronization/internal/graphcycles.cc | 2 + absl/synchronization/internal/graphcycles.h | 4 + absl/synchronization/internal/graphcycles_test.cc | 2 + absl/synchronization/internal/kernel_timeout.h | 2 + absl/synchronization/internal/mutex_nonprod.cc | 2 + absl/synchronization/internal/mutex_nonprod.inc | 2 + absl/synchronization/internal/per_thread_sem.cc | 2 + absl/synchronization/internal/per_thread_sem.h | 2 + .../internal/per_thread_sem_test.cc | 2 + absl/synchronization/internal/thread_pool.h | 2 + absl/synchronization/internal/waiter.cc | 2 + absl/synchronization/internal/waiter.h | 2 + absl/synchronization/mutex.cc | 4 +- absl/synchronization/mutex.h | 4 +- absl/synchronization/notification.cc | 2 + absl/synchronization/notification.h | 2 + absl/synchronization/notification_test.cc | 2 + absl/time/civil_time.cc | 2 + absl/time/civil_time.h | 2 + absl/time/clock.cc | 8 ++ absl/time/clock.h | 2 + absl/time/duration.cc | 2 + absl/time/duration_test.cc | 5 - absl/time/format.cc | 2 + absl/time/internal/get_current_time_chrono.inc | 2 + absl/time/internal/get_current_time_posix.inc | 2 + absl/time/internal/test_util.cc | 4 + absl/time/internal/test_util.h | 2 + absl/time/time.cc | 2 + absl/time/time.h | 2 + absl/types/any.h | 4 + absl/types/bad_any_cast.cc | 2 + absl/types/bad_any_cast.h | 4 + absl/types/bad_optional_access.cc | 2 + absl/types/bad_optional_access.h | 4 + absl/types/bad_variant_access.cc | 2 + absl/types/bad_variant_access.h | 4 + absl/types/compare.h | 2 + absl/types/compare_test.cc | 2 + absl/types/internal/conformance_aliases.h | 2 + absl/types/internal/conformance_archetype.h | 2 + absl/types/internal/conformance_profile.h | 2 + absl/types/internal/optional.h | 2 + absl/types/internal/span.h | 2 + absl/types/internal/variant.h | 2 + absl/types/optional.h | 4 + absl/types/optional_exception_safety_test.cc | 2 + absl/types/span.h | 2 + absl/types/variant.h | 6 ++ absl/types/variant_benchmark.cc | 2 + absl/types/variant_exception_safety_test.cc | 2 + absl/types/variant_test.cc | 2 + absl/utility/utility.h | 2 + 339 files changed, 949 insertions(+), 83 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/algorithm/BUILD.bazel b/absl/algorithm/BUILD.bazel index 2ee8c09e..6a96420b 100644 --- a/absl/algorithm/BUILD.bazel +++ b/absl/algorithm/BUILD.bazel @@ -31,6 +31,7 @@ cc_library( hdrs = ["algorithm.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, + deps = ["//absl/base:config"], ) cc_test( diff --git a/absl/algorithm/CMakeLists.txt b/absl/algorithm/CMakeLists.txt index 9fbe36f6..56cd0fb8 100644 --- a/absl/algorithm/CMakeLists.txt +++ b/absl/algorithm/CMakeLists.txt @@ -21,6 +21,8 @@ absl_cc_library( "algorithm.h" COPTS ${ABSL_DEFAULT_COPTS} + DEPS + absl::config PUBLIC ) diff --git a/absl/algorithm/algorithm.h b/absl/algorithm/algorithm.h index 771228a0..e9b47338 100644 --- a/absl/algorithm/algorithm.h +++ b/absl/algorithm/algorithm.h @@ -26,7 +26,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace algorithm_internal { @@ -150,6 +153,7 @@ ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, ForwardIterator>()); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_ALGORITHM_ALGORITHM_H_ diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h index 5dae9fd6..d72532de 100644 --- a/absl/algorithm/container.h +++ b/absl/algorithm/container.h @@ -55,6 +55,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_algorithm_internal { // NOTE: it is important to defer to ADL lookup for building with C++ modules, @@ -1720,6 +1721,7 @@ OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first, output_first, std::forward(op)); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_ALGORITHM_CONTAINER_H_ diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h index 12145c48..cff45058 100644 --- a/absl/base/internal/raw_logging.h +++ b/absl/base/internal/raw_logging.h @@ -154,7 +154,7 @@ using LogPrefixHook = bool (*)(absl::LogSeverity severity, const char* file, // // 'file' and 'line' are the file and line number where the ABSL_RAW_LOG macro // was located. -// The null-terminated logged message lives in the buffer between 'buf_start' +// The NUL-terminated logged message lives in the buffer between 'buf_start' // and 'buf_end'. 'prefix_end' points to the first non-prefix character of the // buffer (as written by the LogPrefixHook.) using AbortHook = void (*)(const char* file, int line, const char* buf_start, diff --git a/absl/base/internal/thread_identity.h b/absl/base/internal/thread_identity.h index a1aa45ff..5dfd0715 100644 --- a/absl/base/internal/thread_identity.h +++ b/absl/base/internal/thread_identity.h @@ -209,7 +209,7 @@ void ClearCurrentThreadIdentity(); #error ABSL_THREAD_IDENTITY_MODE cannot be direcly set #elif defined(ABSL_FORCE_THREAD_IDENTITY_MODE) #define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE -#elif defined(_WIN32) +#elif defined(_WIN32) && !defined(__MINGW32__) #define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11 #elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \ (__GOOGLE_GRTE_VERSION__ >= 20140228L) diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index e60979b2..1f7abe07 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel @@ -141,6 +141,7 @@ cc_library( copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, visibility = ["//visibility:private"], + deps = ["//absl/base:config"], ) cc_test( @@ -478,6 +479,9 @@ cc_library( hdrs = ["internal/hashtable_debug_hooks.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + "//absl/base:config", + ], ) cc_library( @@ -521,6 +525,7 @@ cc_library( hdrs = ["internal/node_hash_policy.h"], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, + deps = ["//absl/base:config"], ) cc_test( @@ -662,6 +667,9 @@ cc_library( hdrs = ["internal/tracked.h"], copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + "//absl/base:config", + ], ) cc_library( diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index aa33659b..a931f334 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt @@ -204,6 +204,8 @@ absl_cc_library( "internal/counting_allocator.h" COPTS ${ABSL_DEFAULT_COPTS} + DEPS + absl::config ) absl_cc_test( @@ -574,6 +576,8 @@ absl_cc_library( "internal/hashtable_debug_hooks.h" COPTS ${ABSL_DEFAULT_COPTS} + DEPS + absl::config PUBLIC ) @@ -593,6 +597,8 @@ absl_cc_library( "internal/node_hash_policy.h" COPTS ${ABSL_DEFAULT_COPTS} + DEPS + absl::config PUBLIC ) @@ -735,6 +741,8 @@ absl_cc_library( "internal/tracked.h" COPTS ${ABSL_TEST_COPTS} + DEPS + absl::config TESTONLY ) diff --git a/absl/container/btree_map.h b/absl/container/btree_map.h index 9f35f639..470e3197 100644 --- a/absl/container/btree_map.h +++ b/absl/container/btree_map.h @@ -51,6 +51,7 @@ #include "absl/container/internal/btree_container.h" // IWYU pragma: export namespace absl { +ABSL_NAMESPACE_BEGIN // absl::btree_map<> // @@ -700,6 +701,7 @@ void swap(btree_multimap &x, btree_multimap &y) { return x.swap(y); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_BTREE_MAP_H_ diff --git a/absl/container/btree_set.h b/absl/container/btree_set.h index 6e47b4aa..2a4d0ace 100644 --- a/absl/container/btree_set.h +++ b/absl/container/btree_set.h @@ -51,6 +51,7 @@ #include "absl/container/internal/btree_container.h" // IWYU pragma: export namespace absl { +ABSL_NAMESPACE_BEGIN // absl::btree_set<> // @@ -648,6 +649,7 @@ void swap(btree_multiset &x, btree_multiset &y) { return x.swap(y); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_BTREE_SET_H_ diff --git a/absl/container/btree_test.cc b/absl/container/btree_test.cc index ea73f032..f8aadd62 100644 --- a/absl/container/btree_test.cc +++ b/absl/container/btree_test.cc @@ -42,6 +42,7 @@ ABSL_FLAG(int, test_values, 10000, "The number of values to use for tests"); namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -2304,4 +2305,5 @@ TEST(Btree, EmptyTree) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/btree_test.h b/absl/container/btree_test.h index 5ecf43ce..218ba41d 100644 --- a/absl/container/btree_test.h +++ b/absl/container/btree_test.h @@ -28,6 +28,7 @@ #include "absl/time/time.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // Like remove_const but propagates the removal through std::pair. @@ -148,6 +149,7 @@ std::vector GenerateValuesWithSeed(int n, int maxval, int seed) { } } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_BTREE_TEST_H_ diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h index 70e94ad5..a9ce99ba 100644 --- a/absl/container/fixed_array.h +++ b/absl/container/fixed_array.h @@ -50,6 +50,7 @@ #include "absl/memory/memory.h" namespace absl { +ABSL_NAMESPACE_BEGIN constexpr static auto kFixedArrayUseDefault = static_cast(-1); @@ -508,6 +509,7 @@ void FixedArray::NonEmptyInlinedStorage::AnnotateDestruct( #endif // ADDRESS_SANITIZER static_cast(n); // Mark used when not in asan mode } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_FIXED_ARRAY_H_ diff --git a/absl/container/fixed_array_exception_safety_test.cc b/absl/container/fixed_array_exception_safety_test.cc index 5ebeac05..a5bb009d 100644 --- a/absl/container/fixed_array_exception_safety_test.cc +++ b/absl/container/fixed_array_exception_safety_test.cc @@ -23,6 +23,7 @@ #include "absl/base/internal/exception_safety_testing.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { @@ -195,6 +196,7 @@ TEST(FixedArrayExceptionSafety, FillWithAlloc) { } // namespace +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HAVE_EXCEPTIONS diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h index 283f2439..fb570cd4 100644 --- a/absl/container/flat_hash_map.h +++ b/absl/container/flat_hash_map.h @@ -42,6 +42,7 @@ #include "absl/memory/memory.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template struct FlatHashMapPolicy; @@ -584,6 +585,7 @@ struct IsUnorderedContainer< } // namespace container_algorithm_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_FLAT_HASH_MAP_H_ diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc index 02d1f879..dae8e003 100644 --- a/absl/container/flat_hash_map_test.cc +++ b/absl/container/flat_hash_map_test.cc @@ -24,6 +24,7 @@ #include "absl/types/any.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { using ::absl::container_internal::hash_internal::Enum; @@ -251,4 +252,5 @@ TEST(FlatHashMap, Any) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h index 2a51c341..930107ea 100644 --- a/absl/container/flat_hash_set.h +++ b/absl/container/flat_hash_set.h @@ -40,6 +40,7 @@ #include "absl/memory/memory.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template struct FlatHashSetPolicy; @@ -488,6 +489,7 @@ struct IsUnorderedContainer> } // namespace container_algorithm_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_FLAT_HASH_SET_H_ diff --git a/absl/container/flat_hash_set_test.cc b/absl/container/flat_hash_set_test.cc index b55be59b..6eacb1bb 100644 --- a/absl/container/flat_hash_set_test.cc +++ b/absl/container/flat_hash_set_test.cc @@ -25,6 +25,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -125,4 +126,5 @@ TEST(FlatHashSet, MergeExtractInsert) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index d5c67db5..2388d471 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -54,6 +54,7 @@ #include "absl/memory/memory.h" namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // InlinedVector // ----------------------------------------------------------------------------- @@ -841,6 +842,7 @@ H AbslHashValue(H h, const absl::InlinedVector& a) { return H::combine(H::combine_contiguous(std::move(h), a.data(), size), size); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INLINED_VECTOR_H_ diff --git a/absl/container/internal/btree.h b/absl/container/internal/btree.h index 40217dd5..aef861dc 100644 --- a/absl/container/internal/btree.h +++ b/absl/container/internal/btree.h @@ -70,6 +70,7 @@ #include "absl/utility/utility.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // A helper class that indicates if the Compare parameter is a key-compare-to @@ -2606,6 +2607,7 @@ int btree

::internal_verify( } } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_BTREE_H_ diff --git a/absl/container/internal/btree_container.h b/absl/container/internal/btree_container.h index 774412d9..04795c2e 100644 --- a/absl/container/internal/btree_container.h +++ b/absl/container/internal/btree_container.h @@ -26,6 +26,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // A common base class for btree_set, btree_map, btree_multiset, and @@ -602,6 +603,7 @@ class btree_multimap_container : public btree_multiset_container { }; } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_ diff --git a/absl/container/internal/common.h b/absl/container/internal/common.h index cc7633dc..853a5b21 100644 --- a/absl/container/internal/common.h +++ b/absl/container/internal/common.h @@ -22,6 +22,7 @@ #include "absl/types/optional.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -196,6 +197,7 @@ struct InsertReturnType { }; } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_CONTAINER_H_ diff --git a/absl/container/internal/compressed_tuple.h b/absl/container/internal/compressed_tuple.h index 7d08e370..4bfe92fd 100644 --- a/absl/container/internal/compressed_tuple.h +++ b/absl/container/internal/compressed_tuple.h @@ -48,6 +48,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -256,6 +257,7 @@ template <> class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {}; } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC diff --git a/absl/container/internal/compressed_tuple_test.cc b/absl/container/internal/compressed_tuple_test.cc index 19af8f10..76bc9213 100644 --- a/absl/container/internal/compressed_tuple_test.cc +++ b/absl/container/internal/compressed_tuple_test.cc @@ -48,6 +48,7 @@ struct TwoValues { namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -408,4 +409,5 @@ TEST(CompressedTupleTest, EmptyFinalClass) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/container_memory.h b/absl/container/internal/container_memory.h index e5bb9773..d24b0f84 100644 --- a/absl/container/internal/container_memory.h +++ b/absl/container/internal/container_memory.h @@ -34,6 +34,7 @@ #include "absl/utility/utility.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // Allocates at least n bytes aligned to the specified alignment. @@ -433,6 +434,7 @@ struct map_slot_policy { }; } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_ diff --git a/absl/container/internal/container_memory_test.cc b/absl/container/internal/container_memory_test.cc index d6b0495f..7942c7be 100644 --- a/absl/container/internal/container_memory_test.cc +++ b/absl/container/internal/container_memory_test.cc @@ -23,6 +23,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -185,4 +186,5 @@ TEST(DecomposePair, NotDecomposable) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/counting_allocator.h b/absl/container/internal/counting_allocator.h index 4e717bef..9efdc662 100644 --- a/absl/container/internal/counting_allocator.h +++ b/absl/container/internal/counting_allocator.h @@ -19,7 +19,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // This is a stateful allocator, but the state lives outside of the @@ -74,6 +77,7 @@ class CountingAllocator : public std::allocator { }; } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_ diff --git a/absl/container/internal/hash_function_defaults.h b/absl/container/internal/hash_function_defaults.h index cb8f03c8..401ddf4d 100644 --- a/absl/container/internal/hash_function_defaults.h +++ b/absl/container/internal/hash_function_defaults.h @@ -56,6 +56,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // The hash of an object of type T is computed by using absl::Hash. @@ -139,6 +140,7 @@ template using hash_default_eq = typename container_internal::HashEq::Eq; } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_ diff --git a/absl/container/internal/hash_function_defaults_test.cc b/absl/container/internal/hash_function_defaults_test.cc index 82708dbe..2eefc7e0 100644 --- a/absl/container/internal/hash_function_defaults_test.cc +++ b/absl/container/internal/hash_function_defaults_test.cc @@ -22,6 +22,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -248,6 +249,7 @@ TYPED_TEST_SUITE(StringLikeTest, StringTypesCartesianProduct); } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl enum Hash : size_t { @@ -278,6 +280,7 @@ struct hash> { } // namespace std namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -292,4 +295,5 @@ TEST(Delegate, HashDispatch) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/hash_generator_testing.cc b/absl/container/internal/hash_generator_testing.cc index 37a23d60..75c4db6c 100644 --- a/absl/container/internal/hash_generator_testing.cc +++ b/absl/container/internal/hash_generator_testing.cc @@ -17,6 +17,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace hash_internal { namespace { @@ -69,4 +70,5 @@ absl::string_view Generator::operator()() const { } // namespace hash_internal } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/hash_generator_testing.h b/absl/container/internal/hash_generator_testing.h index 477215cd..6869fe45 100644 --- a/absl/container/internal/hash_generator_testing.h +++ b/absl/container/internal/hash_generator_testing.h @@ -33,6 +33,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace hash_internal { namespace generator_internal { @@ -154,6 +155,7 @@ using GeneratedType = decltype( } // namespace hash_internal } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_ diff --git a/absl/container/internal/hash_policy_testing.h b/absl/container/internal/hash_policy_testing.h index c57407a0..01c40d2e 100644 --- a/absl/container/internal/hash_policy_testing.h +++ b/absl/container/internal/hash_policy_testing.h @@ -30,6 +30,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace hash_testing_internal { @@ -162,6 +163,7 @@ auto keys(const Set& s) } } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl // ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS is false for glibcxx versions diff --git a/absl/container/internal/hash_policy_testing_test.cc b/absl/container/internal/hash_policy_testing_test.cc index 0c95eb5e..f0b20fe3 100644 --- a/absl/container/internal/hash_policy_testing_test.cc +++ b/absl/container/internal/hash_policy_testing_test.cc @@ -17,6 +17,7 @@ #include "gtest/gtest.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -40,4 +41,5 @@ TEST(_, Hash) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/hash_policy_traits.h b/absl/container/internal/hash_policy_traits.h index fd007de7..3e1209c6 100644 --- a/absl/container/internal/hash_policy_traits.h +++ b/absl/container/internal/hash_policy_traits.h @@ -23,6 +23,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // Defines how slots are initialized/destroyed/moved. @@ -184,6 +185,7 @@ struct hash_policy_traits { }; } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_HASH_POLICY_TRAITS_H_ diff --git a/absl/container/internal/hash_policy_traits_test.cc b/absl/container/internal/hash_policy_traits_test.cc index e643d189..6ef8b9e0 100644 --- a/absl/container/internal/hash_policy_traits_test.cc +++ b/absl/container/internal/hash_policy_traits_test.cc @@ -22,6 +22,7 @@ #include "gtest/gtest.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -139,4 +140,5 @@ TEST_F(Test, with_transfer) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/hashtable_debug.h b/absl/container/internal/hashtable_debug.h index 71930004..19d52121 100644 --- a/absl/container/internal/hashtable_debug.h +++ b/absl/container/internal/hashtable_debug.h @@ -38,6 +38,7 @@ #include "absl/container/internal/hashtable_debug_hooks.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // Returns the number of probes required to lookup `key`. Returns 0 for a @@ -103,6 +104,7 @@ size_t LowerBoundAllocatedByteSize(size_t num_elements) { } } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_ diff --git a/absl/container/internal/hashtable_debug_hooks.h b/absl/container/internal/hashtable_debug_hooks.h index 371ce81f..3e9ea595 100644 --- a/absl/container/internal/hashtable_debug_hooks.h +++ b/absl/container/internal/hashtable_debug_hooks.h @@ -23,7 +23,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace hashtable_debug_internal { @@ -76,6 +79,7 @@ struct HashtableDebugAccess { } // namespace hashtable_debug_internal } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_HOOKS_H_ diff --git a/absl/container/internal/hashtablez_sampler.cc b/absl/container/internal/hashtablez_sampler.cc index 6deeca44..e15f4444 100644 --- a/absl/container/internal/hashtablez_sampler.cc +++ b/absl/container/internal/hashtablez_sampler.cc @@ -28,6 +28,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { constexpr int HashtablezInfo::kMaxStackDepth; @@ -265,4 +266,5 @@ void SetHashtablezMaxSamples(int32_t max) { } } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/hashtablez_sampler.h b/absl/container/internal/hashtablez_sampler.h index c694df05..c4f9629f 100644 --- a/absl/container/internal/hashtablez_sampler.h +++ b/absl/container/internal/hashtablez_sampler.h @@ -51,6 +51,7 @@ #include "absl/utility/utility.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // Stores information about a sampled hashtable. All mutations to this *must* @@ -281,6 +282,7 @@ void SetHashtablezMaxSamples(int32_t max); extern "C" bool AbslContainerInternalSampleEverything(); } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_ diff --git a/absl/container/internal/hashtablez_sampler_force_weak_definition.cc b/absl/container/internal/hashtablez_sampler_force_weak_definition.cc index 984dce5d..78b9d362 100644 --- a/absl/container/internal/hashtablez_sampler_force_weak_definition.cc +++ b/absl/container/internal/hashtablez_sampler_force_weak_definition.cc @@ -17,6 +17,7 @@ #include "absl/base/attributes.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // See hashtablez_sampler.h for details. @@ -25,4 +26,5 @@ extern "C" ABSL_ATTRIBUTE_WEAK bool AbslContainerInternalSampleEverything() { } } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/hashtablez_sampler_test.cc b/absl/container/internal/hashtablez_sampler_test.cc index af4b5ee1..102b2375 100644 --- a/absl/container/internal/hashtablez_sampler_test.cc +++ b/absl/container/internal/hashtablez_sampler_test.cc @@ -36,6 +36,7 @@ constexpr int kProbeLength = 8; #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { class HashtablezInfoHandlePeer { public: @@ -354,4 +355,5 @@ TEST(HashtablezSamplerTest, Callback) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h index 84aa785a..4d80b727 100644 --- a/absl/container/internal/inlined_vector.h +++ b/absl/container/internal/inlined_vector.h @@ -30,6 +30,7 @@ #include "absl/types/span.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace inlined_vector_internal { template @@ -885,6 +886,7 @@ auto Storage::Swap(Storage* other_storage_ptr) -> void { } } // namespace inlined_vector_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_ diff --git a/absl/container/internal/layout.h b/absl/container/internal/layout.h index bbdde507..69cc85dd 100644 --- a/absl/container/internal/layout.h +++ b/absl/container/internal/layout.h @@ -188,6 +188,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // A type wrapper that instructs `Layout` to use the specific alignment for the @@ -734,6 +735,7 @@ class Layout : public internal_layout::LayoutType { }; } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_LAYOUT_H_ diff --git a/absl/container/internal/layout_test.cc b/absl/container/internal/layout_test.cc index 33b72bd3..8f3628a1 100644 --- a/absl/container/internal/layout_test.cc +++ b/absl/container/internal/layout_test.cc @@ -28,6 +28,7 @@ #include "absl/types/span.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -1562,4 +1563,5 @@ TEST(CompactString, Works) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/node_hash_policy.h b/absl/container/internal/node_hash_policy.h index 19b4fc09..4617162f 100644 --- a/absl/container/internal/node_hash_policy.h +++ b/absl/container/internal/node_hash_policy.h @@ -39,7 +39,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -83,6 +86,7 @@ struct node_hash_policy { }; } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_NODE_HASH_POLICY_H_ diff --git a/absl/container/internal/node_hash_policy_test.cc b/absl/container/internal/node_hash_policy_test.cc index f1d3ec30..84aabba9 100644 --- a/absl/container/internal/node_hash_policy_test.cc +++ b/absl/container/internal/node_hash_policy_test.cc @@ -21,6 +21,7 @@ #include "absl/container/internal/hash_policy_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -64,4 +65,5 @@ TEST_F(NodeTest, transfer) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/raw_hash_map.h b/absl/container/internal/raw_hash_map.h index 7dad120a..0a02757d 100644 --- a/absl/container/internal/raw_hash_map.h +++ b/absl/container/internal/raw_hash_map.h @@ -24,6 +24,7 @@ #include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -190,6 +191,7 @@ class raw_hash_map : public raw_hash_set { }; } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_RAW_HASH_MAP_H_ diff --git a/absl/container/internal/raw_hash_set.cc b/absl/container/internal/raw_hash_set.cc index ac2d10a7..919ac074 100644 --- a/absl/container/internal/raw_hash_set.cc +++ b/absl/container/internal/raw_hash_set.cc @@ -20,6 +20,7 @@ #include "absl/base/config.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { constexpr size_t Group::kWidth; @@ -43,4 +44,5 @@ bool ShouldInsertBackwards(size_t hash, ctrl_t* ctrl) { } } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index 469226fe..4103e02a 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -118,6 +118,7 @@ #include "absl/utility/utility.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -1861,6 +1862,7 @@ struct HashtableDebugAccess> { } // namespace hashtable_debug_internal } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_ diff --git a/absl/container/internal/raw_hash_set_allocator_test.cc b/absl/container/internal/raw_hash_set_allocator_test.cc index a5eff0b3..7ac4b9f7 100644 --- a/absl/container/internal/raw_hash_set_allocator_test.cc +++ b/absl/container/internal/raw_hash_set_allocator_test.cc @@ -20,6 +20,7 @@ #include "absl/container/internal/tracked.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -425,4 +426,5 @@ TEST_F(PropagateOnAll, Swap) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index ec8f9231..38e5e0e8 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -35,6 +35,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { struct RawHashSetTestOnlyAccess { @@ -1913,4 +1914,5 @@ TEST(Sanitizer, PoisoningOnErase) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/test_instance_tracker.cc b/absl/container/internal/test_instance_tracker.cc index 5a66cb4d..f9947f04 100644 --- a/absl/container/internal/test_instance_tracker.cc +++ b/absl/container/internal/test_instance_tracker.cc @@ -15,6 +15,7 @@ #include "absl/container/internal/test_instance_tracker.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace test_internal { int BaseCountedInstance::num_instances_ = 0; int BaseCountedInstance::num_live_instances_ = 0; @@ -24,4 +25,5 @@ int BaseCountedInstance::num_swaps_ = 0; int BaseCountedInstance::num_comparisons_ = 0; } // namespace test_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/test_instance_tracker.h b/absl/container/internal/test_instance_tracker.h index c4731dbe..5ff6fd71 100644 --- a/absl/container/internal/test_instance_tracker.h +++ b/absl/container/internal/test_instance_tracker.h @@ -21,6 +21,7 @@ #include "absl/types/compare.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace test_internal { // A type that counts number of occurrences of the type, the live occurrences of @@ -267,6 +268,7 @@ class MovableOnlyInstance : public BaseCountedInstance { }; } // namespace test_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_ diff --git a/absl/container/internal/tracked.h b/absl/container/internal/tracked.h index 75173ab0..29f5829f 100644 --- a/absl/container/internal/tracked.h +++ b/absl/container/internal/tracked.h @@ -16,10 +16,14 @@ #define ABSL_CONTAINER_INTERNAL_TRACKED_H_ #include + #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { // A class that tracks its copies and moves so that it can be queried in tests. @@ -73,6 +77,7 @@ class Tracked { }; } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_TRACKED_H_ diff --git a/absl/container/internal/unordered_map_constructor_test.h b/absl/container/internal/unordered_map_constructor_test.h index 68817e4e..76ee95e6 100644 --- a/absl/container/internal/unordered_map_constructor_test.h +++ b/absl/container/internal/unordered_map_constructor_test.h @@ -24,6 +24,7 @@ #include "absl/container/internal/hash_policy_testing.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -482,6 +483,7 @@ REGISTER_TYPED_TEST_CASE_P( AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf); } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_ diff --git a/absl/container/internal/unordered_map_lookup_test.h b/absl/container/internal/unordered_map_lookup_test.h index ebd3612b..e76421e5 100644 --- a/absl/container/internal/unordered_map_lookup_test.h +++ b/absl/container/internal/unordered_map_lookup_test.h @@ -21,6 +21,7 @@ #include "absl/container/internal/hash_policy_testing.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -110,6 +111,7 @@ REGISTER_TYPED_TEST_CASE_P(LookupTest, At, OperatorBracket, Count, Find, EqualRange); } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_ diff --git a/absl/container/internal/unordered_map_members_test.h b/absl/container/internal/unordered_map_members_test.h index 1bf31ab4..7d48cdb8 100644 --- a/absl/container/internal/unordered_map_members_test.h +++ b/absl/container/internal/unordered_map_members_test.h @@ -21,6 +21,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -80,6 +81,7 @@ TYPED_TEST_P(MembersTest, BeginEnd) { REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd); } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_ diff --git a/absl/container/internal/unordered_map_modifiers_test.h b/absl/container/internal/unordered_map_modifiers_test.h index f6aff542..b8c513f1 100644 --- a/absl/container/internal/unordered_map_modifiers_test.h +++ b/absl/container/internal/unordered_map_modifiers_test.h @@ -23,6 +23,7 @@ #include "absl/container/internal/hash_policy_testing.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -309,6 +310,7 @@ TYPED_TEST_P(UniquePtrModifiersTest, TryEmplace) { REGISTER_TYPED_TEST_SUITE_P(UniquePtrModifiersTest, TryEmplace); } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_ diff --git a/absl/container/internal/unordered_map_test.cc b/absl/container/internal/unordered_map_test.cc index 114b342d..9cbf512f 100644 --- a/absl/container/internal/unordered_map_test.cc +++ b/absl/container/internal/unordered_map_test.cc @@ -21,6 +21,7 @@ #include "absl/container/internal/unordered_map_modifiers_test.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -45,4 +46,5 @@ INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, UniquePtrModifiersTest, } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/internal/unordered_set_constructor_test.h b/absl/container/internal/unordered_set_constructor_test.h index f4844683..41165b05 100644 --- a/absl/container/internal/unordered_set_constructor_test.h +++ b/absl/container/internal/unordered_set_constructor_test.h @@ -26,6 +26,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -489,6 +490,7 @@ REGISTER_TYPED_TEST_CASE_P( AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf); } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_ diff --git a/absl/container/internal/unordered_set_lookup_test.h b/absl/container/internal/unordered_set_lookup_test.h index 05b32b5d..8f2f4b20 100644 --- a/absl/container/internal/unordered_set_lookup_test.h +++ b/absl/container/internal/unordered_set_lookup_test.h @@ -21,6 +21,7 @@ #include "absl/container/internal/hash_policy_testing.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -84,6 +85,7 @@ TYPED_TEST_P(LookupTest, EqualRange) { REGISTER_TYPED_TEST_CASE_P(LookupTest, Count, Find, EqualRange); } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_ diff --git a/absl/container/internal/unordered_set_members_test.h b/absl/container/internal/unordered_set_members_test.h index b96c945a..4c5e104a 100644 --- a/absl/container/internal/unordered_set_members_test.h +++ b/absl/container/internal/unordered_set_members_test.h @@ -21,6 +21,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -79,6 +80,7 @@ TYPED_TEST_P(MembersTest, BeginEnd) { REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd); } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_ diff --git a/absl/container/internal/unordered_set_modifiers_test.h b/absl/container/internal/unordered_set_modifiers_test.h index 79a8d422..26be58d9 100644 --- a/absl/container/internal/unordered_set_modifiers_test.h +++ b/absl/container/internal/unordered_set_modifiers_test.h @@ -21,6 +21,7 @@ #include "absl/container/internal/hash_policy_testing.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template @@ -183,6 +184,7 @@ REGISTER_TYPED_TEST_CASE_P(ModifiersTest, Clear, Insert, InsertHint, EraseKey, Swap); } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_ diff --git a/absl/container/internal/unordered_set_test.cc b/absl/container/internal/unordered_set_test.cc index 6478fac1..a134b539 100644 --- a/absl/container/internal/unordered_set_test.cc +++ b/absl/container/internal/unordered_set_test.cc @@ -20,6 +20,7 @@ #include "absl/container/internal/unordered_set_modifiers_test.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -36,4 +37,5 @@ INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ModifiersTest, SetTypes); } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h index a718842b..e8065a98 100644 --- a/absl/container/node_hash_map.h +++ b/absl/container/node_hash_map.h @@ -48,6 +48,7 @@ #include "absl/memory/memory.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template class NodeHashMapPolicy; @@ -581,6 +582,7 @@ struct IsUnorderedContainer< } // namespace container_algorithm_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_NODE_HASH_MAP_H_ diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc index 0f2714a7..f923e915 100644 --- a/absl/container/node_hash_map_test.cc +++ b/absl/container/node_hash_map_test.cc @@ -21,6 +21,7 @@ #include "absl/container/internal/unordered_map_modifiers_test.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { @@ -217,4 +218,5 @@ TEST(NodeHashMap, MergeExtractInsert) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h index 0cd1fe57..43ada3f9 100644 --- a/absl/container/node_hash_set.h +++ b/absl/container/node_hash_set.h @@ -44,6 +44,7 @@ #include "absl/memory/memory.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { template struct NodeHashSetPolicy; @@ -483,6 +484,7 @@ struct IsUnorderedContainer> : std::true_type {}; } // namespace container_algorithm_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_CONTAINER_NODE_HASH_SET_H_ diff --git a/absl/container/node_hash_set_test.cc b/absl/container/node_hash_set_test.cc index 0ea76e7c..e1d544ff 100644 --- a/absl/container/node_hash_set_test.cc +++ b/absl/container/node_hash_set_test.cc @@ -20,6 +20,7 @@ #include "absl/container/internal/unordered_set_modifiers_test.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace container_internal { namespace { using ::absl::container_internal::hash_internal::Enum; @@ -102,4 +103,5 @@ TEST(NodeHashSet, MergeExtractInsert) { } // namespace } // namespace container_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel index 2601090b..32cacefd 100644 --- a/absl/debugging/BUILD.bazel +++ b/absl/debugging/BUILD.bazel @@ -38,6 +38,7 @@ cc_library( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":debugging_internal", + "//absl/base:config", "//absl/base:core_headers", ], ) @@ -63,6 +64,7 @@ cc_library( ":debugging_internal", ":demangle_internal", "//absl/base", + "//absl/base:config", "//absl/base:core_headers", "//absl/base:dynamic_annotations", "//absl/base:malloc_internal", @@ -106,6 +108,7 @@ cc_library( deps = [ ":stacktrace", ":symbolize", + "//absl/base:config", "//absl/base:core_headers", "//absl/base:raw_logging_internal", ], @@ -168,6 +171,7 @@ cc_library( copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ + "//absl/base:config", "//absl/base:core_headers", "//absl/base:dynamic_annotations", "//absl/base:raw_logging_internal", @@ -181,6 +185,7 @@ cc_library( copts = ABSL_DEFAULT_COPTS, deps = [ "//absl/base", + "//absl/base:config", "//absl/base:core_headers", ], ) @@ -205,7 +210,10 @@ cc_library( srcs = ["leak_check.cc"], hdrs = ["leak_check.h"], linkopts = ABSL_DEFAULT_LINKOPTS, - deps = ["//absl/base:core_headers"], + deps = [ + "//absl/base:config", + "//absl/base:core_headers", + ], ) # Adding a dependency to leak_check_disable will disable @@ -216,6 +224,7 @@ cc_library( srcs = ["leak_check_disable.cc"], linkopts = ABSL_DEFAULT_LINKOPTS, linkstatic = 1, + deps = ["//absl/base:config"], alwayslink = 1, ) @@ -237,6 +246,9 @@ cc_library( }), linkopts = ABSL_DEFAULT_LINKOPTS, visibility = ["//visibility:private"], + deps = [ + "//absl/base:config", + ], ) cc_library( @@ -247,6 +259,9 @@ cc_library( copts = ["-ULEAK_SANITIZER"], linkopts = ABSL_DEFAULT_LINKOPTS, visibility = ["//visibility:private"], + deps = [ + "//absl/base:config", + ], ) cc_test( @@ -304,6 +319,7 @@ cc_library( linkopts = ABSL_DEFAULT_LINKOPTS, visibility = ["//visibility:private"], deps = [ + "//absl/base:config", "//absl/base:core_headers", "//absl/base:raw_logging_internal", ], diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt index eff504b4..ef9e71fc 100644 --- a/absl/debugging/CMakeLists.txt +++ b/absl/debugging/CMakeLists.txt @@ -25,6 +25,7 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} DEPS absl::debugging_internal + absl::config absl::core_headers PUBLIC ) @@ -49,6 +50,7 @@ absl_cc_library( absl::debugging_internal absl::demangle_internal absl::base + absl::config absl::core_headers absl::dynamic_annotations absl::malloc_internal @@ -88,6 +90,7 @@ absl_cc_library( DEPS absl::stacktrace absl::symbolize + absl::config absl::core_headers absl::raw_logging_internal ) @@ -151,6 +154,7 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} DEPS absl::core_headers + absl::config absl::dynamic_annotations absl::raw_logging_internal ) @@ -196,6 +200,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::core_headers PUBLIC ) @@ -293,6 +298,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::core_headers absl::raw_logging_internal TESTONLY diff --git a/absl/debugging/failure_signal_handler.cc b/absl/debugging/failure_signal_handler.cc index c6a4d962..470d6768 100644 --- a/absl/debugging/failure_signal_handler.cc +++ b/absl/debugging/failure_signal_handler.cc @@ -47,6 +47,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN ABSL_CONST_INIT static FailureSignalHandlerOptions fsh_options; @@ -356,4 +357,5 @@ void InstallFailureSignalHandler(const FailureSignalHandlerOptions& options) { } } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/debugging/failure_signal_handler.h b/absl/debugging/failure_signal_handler.h index 1beb78b9..f5a83962 100644 --- a/absl/debugging/failure_signal_handler.h +++ b/absl/debugging/failure_signal_handler.h @@ -44,7 +44,10 @@ #ifndef ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_ #define ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_ +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN // FailureSignalHandlerOptions // @@ -112,6 +115,7 @@ namespace debugging_internal { const char* FailureSignalToString(int signo); } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_ diff --git a/absl/debugging/internal/address_is_readable.cc b/absl/debugging/internal/address_is_readable.cc index 99c4c64b..f45e59b3 100644 --- a/absl/debugging/internal/address_is_readable.cc +++ b/absl/debugging/internal/address_is_readable.cc @@ -20,12 +20,14 @@ #if !defined(__linux__) || defined(__ANDROID__) namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { // On platforms other than Linux, just return true. bool AddressIsReadable(const void* /* addr */) { return true; } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #else @@ -40,6 +42,7 @@ bool AddressIsReadable(const void* /* addr */) { return true; } #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { // Pack a pid and two file descriptors into a 64-bit word, @@ -128,6 +131,7 @@ bool AddressIsReadable(const void *addr) { } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif diff --git a/absl/debugging/internal/address_is_readable.h b/absl/debugging/internal/address_is_readable.h index ca8003e6..4bbaf4d6 100644 --- a/absl/debugging/internal/address_is_readable.h +++ b/absl/debugging/internal/address_is_readable.h @@ -15,7 +15,10 @@ #ifndef ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_ #define ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_ +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { // Return whether the byte at *addr is readable, without faulting. @@ -23,6 +26,7 @@ namespace debugging_internal { bool AddressIsReadable(const void *addr); } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_ diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc index 3809e496..fc615c3f 100644 --- a/absl/debugging/internal/demangle.cc +++ b/absl/debugging/internal/demangle.cc @@ -24,6 +24,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { typedef struct { @@ -1890,4 +1891,5 @@ bool Demangle(const char *mangled, char *out, int out_size) { } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/debugging/internal/demangle.h b/absl/debugging/internal/demangle.h index 81bb0dfd..c314d9bc 100644 --- a/absl/debugging/internal/demangle.h +++ b/absl/debugging/internal/demangle.h @@ -53,7 +53,10 @@ #ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ #define ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { // Demangle `mangled`. On success, return true and write the @@ -62,6 +65,7 @@ namespace debugging_internal { bool Demangle(const char *mangled, char *out, int out_size); } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_ diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index a68ce324..c6f1ce18 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -23,6 +23,7 @@ #include "absl/memory/memory.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { namespace { @@ -190,4 +191,5 @@ TEST(DemangleRegression, DeeplyNestedArrayType) { } // namespace } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/debugging/internal/elf_mem_image.cc b/absl/debugging/internal/elf_mem_image.cc index e7408bca..24cc0130 100644 --- a/absl/debugging/internal/elf_mem_image.cc +++ b/absl/debugging/internal/elf_mem_image.cc @@ -38,6 +38,7 @@ #define VERSYM_VERSION 0x7fff namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { namespace { @@ -375,6 +376,7 @@ void ElfMemImage::SymbolIterator::Update(int increment) { } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HAVE_ELF_MEM_IMAGE diff --git a/absl/debugging/internal/elf_mem_image.h b/absl/debugging/internal/elf_mem_image.h index d84200db..46bfade3 100644 --- a/absl/debugging/internal/elf_mem_image.h +++ b/absl/debugging/internal/elf_mem_image.h @@ -23,6 +23,8 @@ // used. #include +#include "absl/base/config.h" + // Maybe one day we can rewrite this file not to require the elf // symbol extensions in glibc, but for right now we need them. #ifdef ABSL_HAVE_ELF_MEM_IMAGE @@ -39,6 +41,7 @@ #include // for ElfW namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { // An in-memory ELF image (may not exist on disk). @@ -123,6 +126,7 @@ class ElfMemImage { }; } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HAVE_ELF_MEM_IMAGE diff --git a/absl/debugging/internal/examine_stack.cc b/absl/debugging/internal/examine_stack.cc index 1ebc788f..22f41b46 100644 --- a/absl/debugging/internal/examine_stack.cc +++ b/absl/debugging/internal/examine_stack.cc @@ -30,6 +30,7 @@ #include "absl/debugging/symbolize.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { // Returns the program counter from signal context, nullptr if @@ -150,4 +151,5 @@ void DumpPCAndFrameSizesAndStackTrace( } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/debugging/internal/examine_stack.h b/absl/debugging/internal/examine_stack.h index 56c9763e..39336913 100644 --- a/absl/debugging/internal/examine_stack.h +++ b/absl/debugging/internal/examine_stack.h @@ -17,7 +17,10 @@ #ifndef ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_ #define ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_ +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { // Returns the program counter from signal context, or nullptr if @@ -33,6 +36,7 @@ void DumpPCAndFrameSizesAndStackTrace( void (*writerfn)(const char*, void*), void* writerfn_arg); } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_ diff --git a/absl/debugging/internal/stack_consumption.cc b/absl/debugging/internal/stack_consumption.cc index d4703264..875ca6d9 100644 --- a/absl/debugging/internal/stack_consumption.cc +++ b/absl/debugging/internal/stack_consumption.cc @@ -27,6 +27,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { namespace { @@ -177,6 +178,7 @@ int GetSignalHandlerStackConsumption(void (*signal_handler)(int)) { } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION diff --git a/absl/debugging/internal/stack_consumption.h b/absl/debugging/internal/stack_consumption.h index b860a3c1..5e60ec42 100644 --- a/absl/debugging/internal/stack_consumption.h +++ b/absl/debugging/internal/stack_consumption.h @@ -18,6 +18,8 @@ #ifndef ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_ #define ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_ +#include "absl/base/config.h" + // The code in this module is not portable. // Use this feature test macro to detect its availability. #ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION @@ -27,6 +29,7 @@ #define ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 1 namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { // Returns the stack consumption in bytes for the code exercised by @@ -38,6 +41,7 @@ namespace debugging_internal { int GetSignalHandlerStackConsumption(void (*signal_handler)(int)); } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION diff --git a/absl/debugging/internal/stack_consumption_test.cc b/absl/debugging/internal/stack_consumption_test.cc index 68bfa126..80445bf4 100644 --- a/absl/debugging/internal/stack_consumption_test.cc +++ b/absl/debugging/internal/stack_consumption_test.cc @@ -23,6 +23,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { namespace { @@ -43,6 +44,7 @@ TEST(SignalHandlerStackConsumptionTest, MeasuresStackConsumption) { } // namespace } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION diff --git a/absl/debugging/internal/stacktrace_aarch64-inl.inc b/absl/debugging/internal/stacktrace_aarch64-inl.inc index 7ed6b3eb..411ea308 100644 --- a/absl/debugging/internal/stacktrace_aarch64-inl.inc +++ b/absl/debugging/internal/stacktrace_aarch64-inl.inc @@ -180,11 +180,13 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, } namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { bool StackTraceWorksForTest() { return true; } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_AARCH64_INL_H_ diff --git a/absl/debugging/internal/stacktrace_arm-inl.inc b/absl/debugging/internal/stacktrace_arm-inl.inc index c8408337..fffda968 100644 --- a/absl/debugging/internal/stacktrace_arm-inl.inc +++ b/absl/debugging/internal/stacktrace_arm-inl.inc @@ -113,11 +113,13 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, } namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { bool StackTraceWorksForTest() { return false; } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_ARM_INL_H_ diff --git a/absl/debugging/internal/stacktrace_generic-inl.inc b/absl/debugging/internal/stacktrace_generic-inl.inc index 81a49ef2..ac034c9f 100644 --- a/absl/debugging/internal/stacktrace_generic-inl.inc +++ b/absl/debugging/internal/stacktrace_generic-inl.inc @@ -87,11 +87,13 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, } namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { bool StackTraceWorksForTest() { return true; } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_ diff --git a/absl/debugging/internal/stacktrace_powerpc-inl.inc b/absl/debugging/internal/stacktrace_powerpc-inl.inc index 3a070ee4..2e7c2f40 100644 --- a/absl/debugging/internal/stacktrace_powerpc-inl.inc +++ b/absl/debugging/internal/stacktrace_powerpc-inl.inc @@ -236,11 +236,13 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, } namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { bool StackTraceWorksForTest() { return true; } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_ diff --git a/absl/debugging/internal/stacktrace_unimplemented-inl.inc b/absl/debugging/internal/stacktrace_unimplemented-inl.inc index e256fdd4..5b8fb191 100644 --- a/absl/debugging/internal/stacktrace_unimplemented-inl.inc +++ b/absl/debugging/internal/stacktrace_unimplemented-inl.inc @@ -12,11 +12,13 @@ static int UnwindImpl(void** /* result */, int* /* sizes */, } namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { bool StackTraceWorksForTest() { return false; } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_UNIMPLEMENTED_INL_H_ diff --git a/absl/debugging/internal/stacktrace_win32-inl.inc b/absl/debugging/internal/stacktrace_win32-inl.inc index 247e7428..9c2c5580 100644 --- a/absl/debugging/internal/stacktrace_win32-inl.inc +++ b/absl/debugging/internal/stacktrace_win32-inl.inc @@ -73,11 +73,13 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, } namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { bool StackTraceWorksForTest() { return false; } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_ diff --git a/absl/debugging/internal/stacktrace_x86-inl.inc b/absl/debugging/internal/stacktrace_x86-inl.inc index 9494441e..972febdd 100644 --- a/absl/debugging/internal/stacktrace_x86-inl.inc +++ b/absl/debugging/internal/stacktrace_x86-inl.inc @@ -330,11 +330,13 @@ static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count, } namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { bool StackTraceWorksForTest() { return true; } } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_ diff --git a/absl/debugging/internal/symbolize.h b/absl/debugging/internal/symbolize.h index 3e537893..5d0858b5 100644 --- a/absl/debugging/internal/symbolize.h +++ b/absl/debugging/internal/symbolize.h @@ -21,6 +21,8 @@ #include #include +#include "absl/base/config.h" + #ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE #error ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE cannot be directly set #elif defined(__ELF__) && defined(__GLIBC__) && !defined(__native_client__) && \ @@ -33,6 +35,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { // Iterates over all sections, invoking callback on each with the section name @@ -51,11 +54,13 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len, ElfW(Shdr) *out); } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { struct SymbolDecoratorArgs { @@ -117,6 +122,7 @@ bool GetFileMappingHint(const void** start, const char** filename); } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_ diff --git a/absl/debugging/internal/vdso_support.cc b/absl/debugging/internal/vdso_support.cc index d13ef25d..1e8a78ac 100644 --- a/absl/debugging/internal/vdso_support.cc +++ b/absl/debugging/internal/vdso_support.cc @@ -38,6 +38,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { ABSL_CONST_INIT @@ -187,6 +188,7 @@ static class VDSOInitHelper { } vdso_init_helper; } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HAVE_VDSO_SUPPORT diff --git a/absl/debugging/internal/vdso_support.h b/absl/debugging/internal/vdso_support.h index 9895b48d..6562c6c2 100644 --- a/absl/debugging/internal/vdso_support.h +++ b/absl/debugging/internal/vdso_support.h @@ -53,6 +53,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { // NOTE: this class may be used from within tcmalloc, and can not @@ -149,6 +150,7 @@ class VDSOSupport { int GetCPU(); } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HAVE_ELF_MEM_IMAGE diff --git a/absl/debugging/leak_check.cc b/absl/debugging/leak_check.cc index ffe3d1bd..ff904955 100644 --- a/absl/debugging/leak_check.cc +++ b/absl/debugging/leak_check.cc @@ -21,12 +21,14 @@ #ifndef LEAK_SANITIZER namespace absl { +ABSL_NAMESPACE_BEGIN bool HaveLeakSanitizer() { return false; } void DoIgnoreLeak(const void*) { } void RegisterLivePointers(const void*, size_t) { } void UnRegisterLivePointers(const void*, size_t) { } LeakCheckDisabler::LeakCheckDisabler() { } LeakCheckDisabler::~LeakCheckDisabler() { } +ABSL_NAMESPACE_END } // namespace absl #else @@ -34,6 +36,7 @@ LeakCheckDisabler::~LeakCheckDisabler() { } #include namespace absl { +ABSL_NAMESPACE_BEGIN bool HaveLeakSanitizer() { return true; } void DoIgnoreLeak(const void* ptr) { __lsan_ignore_object(ptr); } void RegisterLivePointers(const void* ptr, size_t size) { @@ -44,6 +47,7 @@ void UnRegisterLivePointers(const void* ptr, size_t size) { } LeakCheckDisabler::LeakCheckDisabler() { __lsan_disable(); } LeakCheckDisabler::~LeakCheckDisabler() { __lsan_enable(); } +ABSL_NAMESPACE_END } // namespace absl #endif // LEAK_SANITIZER diff --git a/absl/debugging/leak_check.h b/absl/debugging/leak_check.h index 4d489c58..7a5a22dd 100644 --- a/absl/debugging/leak_check.h +++ b/absl/debugging/leak_check.h @@ -32,7 +32,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN // HaveLeakSanitizer() // @@ -104,6 +107,7 @@ void RegisterLivePointers(const void* ptr, size_t size); // `RegisterLivePointers()`, enabling leak checking of those pointers. void UnRegisterLivePointers(const void* ptr, size_t size); +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_LEAK_CHECK_H_ diff --git a/absl/debugging/stacktrace.cc b/absl/debugging/stacktrace.cc index 9de8782f..1f7c7d82 100644 --- a/absl/debugging/stacktrace.cc +++ b/absl/debugging/stacktrace.cc @@ -57,6 +57,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace { typedef int (*Unwinder)(void**, int*, int, int, const void*, int*); @@ -135,4 +136,5 @@ int DefaultStackUnwinder(void** pcs, int* sizes, int depth, int skip, return n; } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/debugging/stacktrace.h b/absl/debugging/stacktrace.h index cd8fae76..0ec0ffda 100644 --- a/absl/debugging/stacktrace.h +++ b/absl/debugging/stacktrace.h @@ -31,7 +31,10 @@ #ifndef ABSL_DEBUGGING_STACKTRACE_H_ #define ABSL_DEBUGGING_STACKTRACE_H_ +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN // GetStackFrames() // @@ -222,6 +225,7 @@ namespace debugging_internal { // working. extern bool StackTraceWorksForTest(); } // namespace debugging_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_STACKTRACE_H_ diff --git a/absl/debugging/symbolize.h b/absl/debugging/symbolize.h index a73dbd9e..a8ff3740 100644 --- a/absl/debugging/symbolize.h +++ b/absl/debugging/symbolize.h @@ -55,6 +55,7 @@ #include "absl/debugging/internal/symbolize.h" namespace absl { +ABSL_NAMESPACE_BEGIN // InitializeSymbolizer() // @@ -92,6 +93,7 @@ void InitializeSymbolizer(const char* argv0); // } bool Symbolize(const void *pc, char *out, int out_size); +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_DEBUGGING_SYMBOLIZE_H_ diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc index 14f0c972..c371635f 100644 --- a/absl/debugging/symbolize_elf.inc +++ b/absl/debugging/symbolize_elf.inc @@ -76,6 +76,7 @@ #include "absl/debugging/internal/vdso_support.h" namespace absl { +ABSL_NAMESPACE_BEGIN // Value of argv[0]. Used by MaybeInitializeObjFile(). static char *argv0_value = nullptr; @@ -1475,4 +1476,5 @@ bool Symbolize(const void *pc, char *out, int out_size) { return ok; } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/debugging/symbolize_unimplemented.inc b/absl/debugging/symbolize_unimplemented.inc index 7c580fe4..db24456b 100644 --- a/absl/debugging/symbolize_unimplemented.inc +++ b/absl/debugging/symbolize_unimplemented.inc @@ -17,6 +17,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace debugging_internal { @@ -35,4 +36,5 @@ bool GetFileMappingHint(const void **, const void **, uint64_t *, const char **) void InitializeSymbolizer(const char*) {} bool Symbolize(const void *, char *, int) { return false; } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/debugging/symbolize_win32.inc b/absl/debugging/symbolize_win32.inc index bd6fbd5e..c3df46f6 100644 --- a/absl/debugging/symbolize_win32.inc +++ b/absl/debugging/symbolize_win32.inc @@ -31,6 +31,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN static HANDLE process = NULL; @@ -76,4 +77,5 @@ bool Symbolize(const void* pc, char* out, int out_size) { return true; } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/declare.h b/absl/flags/declare.h index 4926a09e..f7509ce7 100644 --- a/absl/flags/declare.h +++ b/absl/flags/declare.h @@ -28,6 +28,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { // absl::Flag represents a flag of type 'T' created by ABSL_FLAG. @@ -47,6 +48,7 @@ template using Flag = flags_internal::Flag; #endif +ABSL_NAMESPACE_END } // namespace absl // ABSL_DECLARE_FLAG() diff --git a/absl/flags/flag.cc b/absl/flags/flag.cc index 37bbce23..7faa7ade 100644 --- a/absl/flags/flag.cc +++ b/absl/flags/flag.cc @@ -18,6 +18,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN // We want to validate the type mismatch between type definition and // declaration. The lock-free implementation does not allow us to do it, @@ -55,4 +56,5 @@ absl::Mutex* GetGlobalConstructionGuard() { return &construction_guard; } #endif +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/flag.h b/absl/flags/flag.h index 52c3cede..b6fbd116 100644 --- a/absl/flags/flag.h +++ b/absl/flags/flag.h @@ -38,6 +38,7 @@ #include "absl/flags/marshalling.h" namespace absl { +ABSL_NAMESPACE_BEGIN // Flag // @@ -219,6 +220,7 @@ void SetFlag(absl::Flag* flag, const V& v) { flag->Set(value); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/flag_test_defs.cc b/absl/flags/flag_test_defs.cc index 3366c580..49f91dee 100644 --- a/absl/flags/flag_test_defs.cc +++ b/absl/flags/flag_test_defs.cc @@ -20,3 +20,5 @@ ABSL_FLAG(int, mistyped_int_flag, 0, ""); ABSL_FLAG(std::string, mistyped_string_flag, "", ""); +ABSL_RETIRED_FLAG(bool, old_bool_flag, true, + "repetition of retired flag definition"); diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc index 88f91e16..09249274 100644 --- a/absl/flags/internal/commandlineflag.cc +++ b/absl/flags/internal/commandlineflag.cc @@ -18,6 +18,7 @@ #include "absl/flags/usage_config.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { // The help message indicating that the commandline flag has been @@ -57,4 +58,5 @@ std::string CommandLineFlag::Filename() const { } } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h index 7964f1bf..49e13d1e 100644 --- a/absl/flags/internal/commandlineflag.h +++ b/absl/flags/internal/commandlineflag.h @@ -23,6 +23,7 @@ #include "absl/types/optional.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { // Type-specific operations, eg., parsing, copying, etc. are provided @@ -158,7 +159,7 @@ class CommandLineFlag { : name_(name), filename_(filename) {} // Virtual destructor - virtual void Destroy() const = 0; + virtual void Destroy() = 0; // Not copyable/assignable. CommandLineFlag(const CommandLineFlag&) = delete; @@ -280,6 +281,7 @@ class CommandLineFlag { A(float) } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ diff --git a/absl/flags/internal/flag.cc b/absl/flags/internal/flag.cc index 435cc362..599bd7a4 100644 --- a/absl/flags/internal/flag.cc +++ b/absl/flags/internal/flag.cc @@ -19,6 +19,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { namespace { @@ -34,20 +35,40 @@ bool ShouldValidateFlagValue(const CommandLineFlag& flag) { return true; } +// RAII helper used to temporarily unlock and relock `absl::Mutex`. +// This is used when we need to ensure that locks are released while +// invoking user supplied callbacks and then reacquired, since callbacks may +// need to acquire these locks themselves. +class MutexRelock { + public: + explicit MutexRelock(absl::Mutex* mu) : mu_(mu) { mu_->Unlock(); } + ~MutexRelock() { mu_->Lock(); } + + MutexRelock(const MutexRelock&) = delete; + MutexRelock& operator=(const MutexRelock&) = delete; + + private: + absl::Mutex* mu_; +}; + +// This global lock guards the initialization and destruction of data_guard_, +// which is used to guard the other Flag data. +ABSL_CONST_INIT static absl::Mutex flag_mutex_lifetime_guard(absl::kConstInit); + } // namespace void FlagImpl::Init() { - ABSL_CONST_INIT static absl::Mutex init_lock(absl::kConstInit); - { - absl::MutexLock lock(&init_lock); + absl::MutexLock lock(&flag_mutex_lifetime_guard); - if (locks_ == nullptr) { // Must initialize Mutexes for this flag. - locks_ = new FlagImpl::CommandLineFlagLocks; + // Must initialize data guard for this flag. + if (!is_data_guard_inited_) { + new (&data_guard_) absl::Mutex; + is_data_guard_inited_ = true; } } - absl::MutexLock lock(&locks_->primary_mu); + absl::MutexLock lock(reinterpret_cast(&data_guard_)); if (cur_ != nullptr) { inited_.store(true, std::memory_order_release); @@ -67,21 +88,29 @@ absl::Mutex* FlagImpl::DataGuard() const { const_cast(this)->Init(); } - // All fields initialized; locks_ is therefore safe to read. - return &locks_->primary_mu; + // data_guard_ is initialized. + return reinterpret_cast(&data_guard_); } -void FlagImpl::Destroy() const { +void FlagImpl::Destroy() { { absl::MutexLock l(DataGuard()); // Values are heap allocated for Abseil Flags. if (cur_) Delete(op_, cur_); - if (def_kind_ == FlagDefaultSrcKind::kDynamicValue) + + // Release the dynamically allocated default value if any. + if (def_kind_ == FlagDefaultSrcKind::kDynamicValue) { Delete(op_, default_src_.dynamic_value); + } + + // If this flag has an assigned callback, release callback data. + if (callback_data_) delete callback_data_; } - delete locks_; + absl::MutexLock l(&flag_mutex_lifetime_guard); + DataGuard()->~Mutex(); + is_data_guard_inited_ = false; } std::unique_ptr FlagImpl::MakeInitValue() const { @@ -126,13 +155,20 @@ void FlagImpl::SetCallback( const flags_internal::FlagCallback mutation_callback) { absl::MutexLock l(DataGuard()); - callback_ = mutation_callback; + if (callback_data_ == nullptr) { + callback_data_ = new CallbackData; + } + callback_data_->func = mutation_callback; InvokeCallback(); } void FlagImpl::InvokeCallback() const { - if (!callback_) return; + if (!callback_data_) return; + + // Make a copy of the C-style function pointer that we are about to invoke + // before we release the lock guarding it. + FlagCallback cb = callback_data_->func; // If the flag has a mutation callback this function invokes it. While the // callback is being invoked the primary flag's mutex is unlocked and it is @@ -145,14 +181,9 @@ void FlagImpl::InvokeCallback() const { // and it also can be different by the time the callback invocation is // completed. Requires that *primary_lock be held in exclusive mode; it may be // released and reacquired by the implementation. - DataGuard()->Unlock(); - - { - absl::MutexLock lock(&locks_->callback_mu); - callback_(); - } - - DataGuard()->Lock(); + MutexRelock relock(DataGuard()); + absl::MutexLock lock(&callback_data_->guard); + cb(); } bool FlagImpl::RestoreState(const CommandLineFlag& flag, const void* value, @@ -177,12 +208,13 @@ bool FlagImpl::RestoreState(const CommandLineFlag& flag, const void* value, } // Attempts to parse supplied `value` string using parsing routine in the `flag` -// argument. If parsing successful, this function stores the parsed value in -// 'dst' assuming it is a pointer to the flag's value type. In case if any error -// is encountered in either step, the error message is stored in 'err' -bool FlagImpl::TryParse(const CommandLineFlag& flag, void* dst, +// argument. If parsing successful, this function replaces the dst with newly +// parsed value. In case if any error is encountered in either step, the error +// message is stored in 'err' +bool FlagImpl::TryParse(const CommandLineFlag& flag, void** dst, absl::string_view value, std::string* err) const { auto tentative_value = MakeInitValue(); + std::string parse_err; if (!Parse(marshalling_op_, value, tentative_value.get(), &parse_err)) { auto type_name = flag.Typename(); @@ -194,7 +226,10 @@ bool FlagImpl::TryParse(const CommandLineFlag& flag, void* dst, return false; } - Copy(op_, tentative_value.get(), dst); + void* old_val = *dst; + *dst = tentative_value.release(); + tentative_value.reset(old_val); + return true; } @@ -274,7 +309,7 @@ bool FlagImpl::SetFromString(const CommandLineFlag& flag, switch (set_mode) { case SET_FLAGS_VALUE: { // set or modify the flag's value - if (!TryParse(flag, cur_, value, err)) return false; + if (!TryParse(flag, &cur_, value, err)) return false; modified_ = true; counter_++; StoreAtomic(); @@ -288,7 +323,7 @@ bool FlagImpl::SetFromString(const CommandLineFlag& flag, case SET_FLAG_IF_DEFAULT: { // set the flag's value, but only if it hasn't been set by someone else if (!modified_) { - if (!TryParse(flag, cur_, value, err)) return false; + if (!TryParse(flag, &cur_, value, err)) return false; modified_ = true; counter_++; StoreAtomic(); @@ -305,18 +340,19 @@ bool FlagImpl::SetFromString(const CommandLineFlag& flag, break; } case SET_FLAGS_DEFAULT: { - // Flag's new default-value. - auto new_default_value = MakeInitValue(); - - if (!TryParse(flag, new_default_value.get(), value, err)) return false; - if (def_kind_ == FlagDefaultSrcKind::kDynamicValue) { - // Release old default value. - Delete(op_, default_src_.dynamic_value); - } + if (!TryParse(flag, &default_src_.dynamic_value, value, err)) { + return false; + } + } else { + void* new_default_val = nullptr; + if (!TryParse(flag, &new_default_val, value, err)) { + return false; + } - default_src_.dynamic_value = new_default_value.release(); - def_kind_ = FlagDefaultSrcKind::kDynamicValue; + default_src_.dynamic_value = new_default_val; + def_kind_ = FlagDefaultSrcKind::kDynamicValue; + } if (!modified_) { // Need to set both default value *and* current, in this case @@ -361,4 +397,5 @@ bool FlagImpl::ValidateInputValue(absl::string_view value) const { } } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index 947a8cad..20de406f 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -27,6 +27,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { constexpr int64_t AtomicInit() { return 0xababababababababll; } @@ -156,10 +157,11 @@ class FlagImpl { help_(help.source), help_source_kind_(help.kind), def_kind_(flags_internal::FlagDefaultSrcKind::kGenFunc), - default_src_(default_value_gen) {} + default_src_(default_value_gen), + data_guard_{} {} // Forces destruction of the Flag's data. - void Destroy() const; + void Destroy(); // Constant access methods std::string Help() const; @@ -170,9 +172,10 @@ class FlagImpl { void Read(const CommandLineFlag& flag, void* dst, const flags_internal::FlagOpFn dst_op) const ABSL_LOCKS_EXCLUDED(*DataGuard()); - // Attempts to parse supplied `value` std::string. - bool TryParse(const CommandLineFlag& flag, void* dst, absl::string_view value, - std::string* err) const + // Attempts to parse supplied `value` std::string. If parsing is successful, then + // it replaces `dst` with the new value. + bool TryParse(const CommandLineFlag& flag, void** dst, + absl::string_view value, std::string* err) const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); template bool AtomicGet(T* v) const { @@ -226,8 +229,7 @@ class FlagImpl { void Init(); // Ensures that the lazily initialized data is initialized, // and returns pointer to the mutex guarding flags data. - absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED(locks_->primary_mu); - + absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED((absl::Mutex*)&data_guard_); // Returns heap allocated value of type T initialized with default value. std::unique_ptr MakeInitValue() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); @@ -239,9 +241,12 @@ class FlagImpl { // Indicates if help message was supplied as literal or generator func. const FlagHelpSrcKind help_source_kind_; - // Mutable Flag's data. (guarded by DataGuard()). - // Indicates that locks_ and cur_ fields have been lazily initialized. + // Indicates that the Flag state is initialized. std::atomic inited_{false}; + // Mutable Flag state (guarded by data_guard_). + // Additional bool to protect against multiple concurrent constructions + // of `data_guard_`. + bool is_data_guard_inited_ = false; // Has flag value been modified? bool modified_ ABSL_GUARDED_BY(*DataGuard()) = false; // Specified on command line. @@ -261,22 +266,20 @@ class FlagImpl { // For some types, a copy of the current value is kept in an atomically // accessible field. std::atomic atomic_{flags_internal::AtomicInit()}; - // Mutation callback - FlagCallback callback_ = nullptr; - - // Lazily initialized mutexes for this flag value. We cannot inline a - // SpinLock or Mutex here because those have non-constexpr constructors and - // so would prevent constant initialization of this type. - // TODO(rogeeff): fix it once Mutex has constexpr constructor - // The following struct contains the locks in a CommandLineFlag struct. - // They are in a separate struct that is lazily allocated to avoid problems - // with static initialization and to avoid multiple allocations. - struct CommandLineFlagLocks { - absl::Mutex primary_mu; // protects several fields in CommandLineFlag - absl::Mutex callback_mu; // used to serialize callbacks - }; - CommandLineFlagLocks* locks_ = nullptr; // locks, laziliy allocated. + struct CallbackData { + FlagCallback func; + absl::Mutex guard; // Guard for concurrent callback invocations. + }; + CallbackData* callback_data_ ABSL_GUARDED_BY(*DataGuard()) = nullptr; + // This is reserved space for an absl::Mutex to guard flag data. It will be + // initialized in FlagImpl::Init via placement new. + // We can't use "absl::Mutex data_guard_", since this class is not literal. + // We do not want to use "absl::Mutex* data_guard_", since this would require + // heap allocation during initialization, which is both slows program startup + // and can fail. Using reserved space + placement new allows us to avoid both + // problems. + alignas(absl::Mutex) mutable char data_guard_[sizeof(absl::Mutex)]; }; // This is "unspecified" implementation of absl::Flag type. @@ -354,7 +357,7 @@ class Flag final : public flags_internal::CommandLineFlag { private: friend class FlagState; - void Destroy() const override { impl_.Destroy(); } + void Destroy() override { impl_.Destroy(); } void Read(void* dst) const override { impl_.Read(*this, dst, &flags_internal::FlagOps); @@ -414,6 +417,7 @@ T* MakeFromDefaultValue(EmptyBraces) { } } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FLAGS_INTERNAL_FLAG_H_ diff --git a/absl/flags/internal/parse.h b/absl/flags/internal/parse.h index fd3aca61..e534635b 100644 --- a/absl/flags/internal/parse.h +++ b/absl/flags/internal/parse.h @@ -27,6 +27,7 @@ ABSL_DECLARE_FLAG(std::vector, tryfromenv); ABSL_DECLARE_FLAG(std::vector, undefok); namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { enum class ArgvListAction { kRemoveParsedArgs, kKeepParsedArgs }; @@ -43,6 +44,7 @@ std::vector ParseCommandLineImpl(int argc, char* argv[], OnUndefinedFlag on_undef_flag); } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FLAGS_INTERNAL_PARSE_H_ diff --git a/absl/flags/internal/path_util.h b/absl/flags/internal/path_util.h index 5615c0e6..41696377 100644 --- a/absl/flags/internal/path_util.h +++ b/absl/flags/internal/path_util.h @@ -20,6 +20,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { // A portable interface that returns the basename of the filename passed as an @@ -55,6 +56,7 @@ inline absl::string_view Package(absl::string_view filename) { } } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FLAGS_INTERNAL_PATH_UTIL_H_ diff --git a/absl/flags/internal/program_name.cc b/absl/flags/internal/program_name.cc index f0811f14..df0c3309 100644 --- a/absl/flags/internal/program_name.cc +++ b/absl/flags/internal/program_name.cc @@ -21,6 +21,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { ABSL_CONST_INIT static absl::Mutex program_name_guard(absl::kConstInit); @@ -50,4 +51,5 @@ void SetProgramInvocationName(absl::string_view prog_name_str) { } } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/program_name.h b/absl/flags/internal/program_name.h index 326f24bb..317a7c5c 100644 --- a/absl/flags/internal/program_name.h +++ b/absl/flags/internal/program_name.h @@ -24,6 +24,7 @@ // Program name namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { // Returns program invocation name or "UNKNOWN" if `SetProgramInvocationName()` @@ -42,6 +43,7 @@ std::string ShortProgramInvocationName(); void SetProgramInvocationName(absl::string_view prog_name_str); } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_ diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc index 52d9f3c7..5eae933c 100644 --- a/absl/flags/internal/registry.cc +++ b/absl/flags/internal/registry.cc @@ -30,6 +30,7 @@ // set it. namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { // -------------------------------------------------------------------- @@ -281,7 +282,7 @@ class RetiredFlagObj final : public flags_internal::CommandLineFlag { op_(ops) {} private: - void Destroy() const override { + void Destroy() override { // Values are heap allocated for Retired Flags. delete this; } @@ -336,4 +337,5 @@ bool IsRetiredFlag(absl::string_view name, bool* type_is_bool) { } } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h index 1889f3a0..d2145a8a 100644 --- a/absl/flags/internal/registry.h +++ b/absl/flags/internal/registry.h @@ -27,6 +27,7 @@ // Global flags registry API. namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { CommandLineFlag* FindCommandLineFlag(absl::string_view name); @@ -115,6 +116,7 @@ class FlagSaver { }; } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FLAGS_INTERNAL_REGISTRY_H_ diff --git a/absl/flags/internal/type_erased.cc b/absl/flags/internal/type_erased.cc index a1650fcf..7910db8f 100644 --- a/absl/flags/internal/type_erased.cc +++ b/absl/flags/internal/type_erased.cc @@ -21,6 +21,7 @@ #include "absl/strings/str_cat.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { bool GetCommandLineOption(absl::string_view name, std::string* value) { @@ -79,4 +80,5 @@ bool SpecifiedOnCommandLine(absl::string_view name) { } } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/type_erased.h b/absl/flags/internal/type_erased.h index a9551166..6cbd84cd 100644 --- a/absl/flags/internal/type_erased.h +++ b/absl/flags/internal/type_erased.h @@ -25,6 +25,7 @@ // Registry interfaces operating on type erased handles. namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { // If a flag named "name" exists, store its current value in *OUTPUT @@ -81,6 +82,7 @@ inline bool GetByName(absl::string_view name, T* dst) { } } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_ diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc index dc12e32f..4602c019 100644 --- a/absl/flags/internal/usage.cc +++ b/absl/flags/internal/usage.cc @@ -44,6 +44,7 @@ ABSL_FLAG(std::string, helpmatch, "", "show help on modules whose name contains the specified substr"); namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { namespace { @@ -404,4 +405,5 @@ int HandleUsageFlags(std::ostream& out, } } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/usage.h b/absl/flags/internal/usage.h index 76075b08..5e8ca6a1 100644 --- a/absl/flags/internal/usage.h +++ b/absl/flags/internal/usage.h @@ -27,6 +27,7 @@ // Usage reporting interfaces namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { // The format to report the help messages in. @@ -64,6 +65,7 @@ int HandleUsageFlags(std::ostream& out, absl::string_view program_usage_message); } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl ABSL_DECLARE_FLAG(bool, help); diff --git a/absl/flags/marshalling.cc b/absl/flags/marshalling.cc index f4ebe0e3..87020a27 100644 --- a/absl/flags/marshalling.cc +++ b/absl/flags/marshalling.cc @@ -27,6 +27,7 @@ #include "absl/strings/str_split.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { // -------------------------------------------------------------------- @@ -226,4 +227,5 @@ std::string AbslUnparseFlag(absl::LogSeverity v) { return absl::UnparseFlag(static_cast(v)); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/marshalling.h b/absl/flags/marshalling.h index 6d391804..b9fca752 100644 --- a/absl/flags/marshalling.h +++ b/absl/flags/marshalling.h @@ -168,6 +168,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { // Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types. @@ -256,6 +257,7 @@ enum class LogSeverity : int; bool AbslParseFlag(absl::string_view, absl::LogSeverity*, std::string*); std::string AbslUnparseFlag(absl::LogSeverity); +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FLAGS_MARSHALLING_H_ diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc index 16c4d68f..5a56a356 100644 --- a/absl/flags/parse.cc +++ b/absl/flags/parse.cc @@ -38,6 +38,7 @@ // -------------------------------------------------------------------- namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { namespace { @@ -52,6 +53,7 @@ ABSL_CONST_INIT bool tryfromenv_needs_processing } // namespace } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl ABSL_FLAG(std::vector, flagfile, {}, @@ -109,6 +111,7 @@ ABSL_FLAG(std::vector, undefok, {}, "with that name"); namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { namespace { @@ -748,4 +751,5 @@ std::vector ParseCommandLine(int argc, char* argv[]) { flags_internal::OnUndefinedFlag::kAbortIfUndefined); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/parse.h b/absl/flags/parse.h index dbb75101..871fc993 100644 --- a/absl/flags/parse.h +++ b/absl/flags/parse.h @@ -29,6 +29,7 @@ #include "absl/flags/internal/parse.h" namespace absl { +ABSL_NAMESPACE_BEGIN // ParseCommandLine() // @@ -53,6 +54,7 @@ namespace absl { // help messages and then exits the program. std::vector ParseCommandLine(int argc, char* argv[]); +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FLAGS_PARSE_H_ diff --git a/absl/flags/usage.cc b/absl/flags/usage.cc index dff7a3da..60459bc2 100644 --- a/absl/flags/usage.cc +++ b/absl/flags/usage.cc @@ -20,6 +20,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { namespace { ABSL_CONST_INIT absl::Mutex usage_message_guard(absl::kConstInit); @@ -53,4 +54,5 @@ absl::string_view ProgramUsageMessage() { : "Warning: SetProgramUsageMessage() never called"; } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/usage.h b/absl/flags/usage.h index 3a121071..299e5c34 100644 --- a/absl/flags/usage.h +++ b/absl/flags/usage.h @@ -22,6 +22,7 @@ // Usage reporting interfaces namespace absl { +ABSL_NAMESPACE_BEGIN // Sets the "usage" message to be used by help reporting routines. // For example: @@ -35,6 +36,7 @@ void SetProgramUsageMessage(absl::string_view new_usage_message); // Returns the usage message set by SetProgramUsageMessage(). absl::string_view ProgramUsageMessage(); +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FLAGS_USAGE_H_ diff --git a/absl/flags/usage_config.cc b/absl/flags/usage_config.cc index f97bf300..21a2dd01 100644 --- a/absl/flags/usage_config.cc +++ b/absl/flags/usage_config.cc @@ -34,6 +34,7 @@ ABSL_ATTRIBUTE_WEAK void AbslInternalReportFatalUsageError(absl::string_view) {} } // extern "C" namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { namespace { @@ -149,4 +150,5 @@ void SetFlagsUsageConfig(FlagsUsageConfig usage_config) { flags_internal::custom_usage_config = new FlagsUsageConfig(usage_config); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/usage_config.h b/absl/flags/usage_config.h index bfd0eedb..e6428e0a 100644 --- a/absl/flags/usage_config.h +++ b/absl/flags/usage_config.h @@ -54,6 +54,7 @@ // Shows help on modules whose name contains the specified substring namespace absl { +ABSL_NAMESPACE_BEGIN namespace flags_internal { using FlagKindFilter = std::function; @@ -118,6 +119,7 @@ FlagsUsageConfig GetUsageConfig(); void ReportUsageError(absl::string_view msg, bool is_fatal); } // namespace flags_internal +ABSL_NAMESPACE_END } // namespace absl extern "C" { diff --git a/absl/functional/function_ref.h b/absl/functional/function_ref.h index 42d9f16f..370acc55 100644 --- a/absl/functional/function_ref.h +++ b/absl/functional/function_ref.h @@ -54,6 +54,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN // FunctionRef // @@ -132,6 +133,7 @@ class FunctionRef { absl::functional_internal::Invoker invoker_; }; +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FUNCTIONAL_FUNCTION_REF_H_ diff --git a/absl/functional/function_ref_benchmark.cc b/absl/functional/function_ref_benchmark.cc index f6dfcabf..045305bf 100644 --- a/absl/functional/function_ref_benchmark.cc +++ b/absl/functional/function_ref_benchmark.cc @@ -20,6 +20,7 @@ #include "absl/base/attributes.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { int dummy = 0; @@ -137,4 +138,5 @@ void BM_NonTrivialArgsFunctionRef(benchmark::State& state) { BENCHMARK(BM_NonTrivialArgsFunctionRef); } // namespace +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/functional/function_ref_test.cc b/absl/functional/function_ref_test.cc index 90829db0..3aa59745 100644 --- a/absl/functional/function_ref_test.cc +++ b/absl/functional/function_ref_test.cc @@ -22,6 +22,7 @@ #include "absl/memory/memory.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { void RunFun(FunctionRef f) { f(); } @@ -252,4 +253,5 @@ TEST(FunctionRef, PassByValueTypes) { } } // namespace +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/functional/internal/function_ref.h b/absl/functional/internal/function_ref.h index fcb0496c..d1575054 100644 --- a/absl/functional/internal/function_ref.h +++ b/absl/functional/internal/function_ref.h @@ -23,6 +23,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace functional_internal { // Like a void* that can handle function pointers as well. The standard does not @@ -99,6 +100,7 @@ template using EnableIf = typename ::std::enable_if::type; } // namespace functional_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_ diff --git a/absl/hash/hash.h b/absl/hash/hash.h index 297dc9cb..23a65ea8 100644 --- a/absl/hash/hash.h +++ b/absl/hash/hash.h @@ -73,6 +73,7 @@ #include "absl/hash/internal/hash.h" namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // `absl::Hash` @@ -317,6 +318,7 @@ class HashState : public hash_internal::HashStateBase { void (*combine_contiguous_)(void*, const unsigned char*, size_t); }; +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HASH_HASH_H_ diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc index 42c0c3d8..7a9d57f7 100644 --- a/absl/hash/hash_test.cc +++ b/absl/hash/hash_test.cc @@ -681,6 +681,7 @@ H AbslHashValue(H state, CustomHashType t) { } // namespace namespace absl { +ABSL_NAMESPACE_BEGIN namespace hash_internal { template struct is_uniquely_represented< @@ -688,6 +689,7 @@ struct is_uniquely_represented< typename EnableIfContained::type> : std::true_type {}; } // namespace hash_internal +ABSL_NAMESPACE_END } // namespace absl #if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ diff --git a/absl/hash/hash_testing.h b/absl/hash/hash_testing.h index c45bc154..1e1c5741 100644 --- a/absl/hash/hash_testing.h +++ b/absl/hash/hash_testing.h @@ -28,6 +28,7 @@ #include "absl/types/variant.h" namespace absl { +ABSL_NAMESPACE_BEGIN // Run the absl::Hash algorithm over all the elements passed in and verify that // their hash expansion is congruent with their `==` operator. @@ -371,6 +372,7 @@ VerifyTypeImplementsAbslHashCorrectly(std::initializer_list values, equals); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HASH_HASH_TESTING_H_ diff --git a/absl/hash/internal/city.cc b/absl/hash/internal/city.cc index dc7650a7..e122c184 100644 --- a/absl/hash/internal/city.cc +++ b/absl/hash/internal/city.cc @@ -30,6 +30,7 @@ #include "absl/base/optimization.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace hash_internal { #ifdef ABSL_IS_BIG_ENDIAN @@ -341,4 +342,5 @@ uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0, } } // namespace hash_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/hash/internal/city.h b/absl/hash/internal/city.h index b43d3407..161c7748 100644 --- a/absl/hash/internal/city.h +++ b/absl/hash/internal/city.h @@ -47,9 +47,13 @@ #include #include // for size_t. + #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace hash_internal { typedef std::pair uint128; @@ -86,6 +90,7 @@ inline uint64_t Hash128to64(const uint128 &x) { } } // namespace hash_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HASH_INTERNAL_CITY_H_ diff --git a/absl/hash/internal/city_test.cc b/absl/hash/internal/city_test.cc index 71b4ecce..251d381d 100644 --- a/absl/hash/internal/city_test.cc +++ b/absl/hash/internal/city_test.cc @@ -20,6 +20,7 @@ #include "gtest/gtest.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace hash_internal { static const uint64_t k0 = 0xc3a5c85c97cb3127ULL; @@ -590,4 +591,5 @@ TEST(CityHashTest, Unchanging) { } } // namespace hash_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/hash/internal/hash.cc b/absl/hash/internal/hash.cc index c17f3be1..b44ecb3a 100644 --- a/absl/hash/internal/hash.cc +++ b/absl/hash/internal/hash.cc @@ -15,6 +15,7 @@ #include "absl/hash/internal/hash.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace hash_internal { uint64_t CityHashState::CombineLargeContiguousImpl32(uint64_t state, @@ -50,4 +51,5 @@ uint64_t CityHashState::CombineLargeContiguousImpl64(uint64_t state, ABSL_CONST_INIT const void* const CityHashState::kSeed = &kSeed; } // namespace hash_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h index 7d44f57d..2564978a 100644 --- a/absl/hash/internal/hash.h +++ b/absl/hash/internal/hash.h @@ -50,6 +50,7 @@ #include "absl/hash/internal/city.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace hash_internal { class PiecewiseCombiner; @@ -980,6 +981,7 @@ H PiecewiseCombiner::finalize(H state) { } } // namespace hash_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HASH_INTERNAL_HASH_H_ diff --git a/absl/hash/internal/spy_hash_state.h b/absl/hash/internal/spy_hash_state.h index 05c7cafe..c0831208 100644 --- a/absl/hash/internal/spy_hash_state.h +++ b/absl/hash/internal/spy_hash_state.h @@ -25,6 +25,7 @@ #include "absl/strings/str_join.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace hash_internal { // SpyHashState is an implementation of the HashState API that simply @@ -224,6 +225,7 @@ void AbslHashValue(SpyHashStateImpl, const U&); using SpyHashState = SpyHashStateImpl; } // namespace hash_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_ diff --git a/absl/memory/memory.h b/absl/memory/memory.h index 243a5dda..513f7103 100644 --- a/absl/memory/memory.h +++ b/absl/memory/memory.h @@ -34,6 +34,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // Function Template: WrapUnique() @@ -688,6 +689,7 @@ void CopyRange(Allocator& alloc, Iterator destination, InputIterator first, } } } // namespace memory_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_MEMORY_MEMORY_H_ diff --git a/absl/memory/memory_exception_safety_test.cc b/absl/memory/memory_exception_safety_test.cc index 729507e9..c0910dc7 100644 --- a/absl/memory/memory_exception_safety_test.cc +++ b/absl/memory/memory_exception_safety_test.cc @@ -22,6 +22,7 @@ #include "absl/base/internal/exception_safety_testing.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { constexpr int kLength = 50; @@ -53,6 +54,7 @@ TEST(MakeUnique, CheckForLeaks) { } } // namespace +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_HAVE_EXCEPTIONS diff --git a/absl/meta/type_traits.h b/absl/meta/type_traits.h index 8cd5f043..ba87d2f0 100644 --- a/absl/meta/type_traits.h +++ b/absl/meta/type_traits.h @@ -48,6 +48,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN // Defined and documented later on in this file. template @@ -752,6 +753,7 @@ using swap_internal::Swap; using swap_internal::StdSwapIsUnconstrained; } // namespace type_traits_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_META_TYPE_TRAITS_H_ diff --git a/absl/numeric/int128.cc b/absl/numeric/int128.cc index 1eba09de..a20a77e7 100644 --- a/absl/numeric/int128.cc +++ b/absl/numeric/int128.cc @@ -23,6 +23,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN const uint128 kuint128max = MakeUint128(std::numeric_limits::max(), std::numeric_limits::max()); @@ -349,6 +350,7 @@ std::ostream& operator<<(std::ostream& os, int128 v) { return os << rep; } +ABSL_NAMESPACE_END } // namespace absl namespace std { diff --git a/absl/numeric/int128.h b/absl/numeric/int128.h index 50617612..718f70b1 100644 --- a/absl/numeric/int128.h +++ b/absl/numeric/int128.h @@ -49,6 +49,7 @@ #endif // defined(_MSC_VER) namespace absl { +ABSL_NAMESPACE_BEGIN class int128; @@ -245,6 +246,7 @@ constexpr uint128 Uint128Max() { (std::numeric_limits::max)()); } +ABSL_NAMESPACE_END } // namespace absl // Specialized numeric_limits for uint128. @@ -293,6 +295,7 @@ class numeric_limits { } // namespace std namespace absl { +ABSL_NAMESPACE_BEGIN // int128 // @@ -478,6 +481,7 @@ constexpr int128 Int128Min() { return int128((std::numeric_limits::min)(), 0); } +ABSL_NAMESPACE_END } // namespace absl // Specialized numeric_limits for int128. @@ -529,6 +533,7 @@ class numeric_limits { // Implementation details follow // -------------------------------------------------------------------------- namespace absl { +ABSL_NAMESPACE_BEGIN constexpr uint128 MakeUint128(uint64_t high, uint64_t low) { return uint128(high, low); @@ -1078,6 +1083,7 @@ constexpr int64_t BitCastToSigned(uint64_t v) { #include "absl/numeric/int128_no_intrinsic.inc" // IWYU pragma: export #endif // ABSL_HAVE_INTRINSIC_INT128 +ABSL_NAMESPACE_END } // namespace absl #undef ABSL_INTERNAL_WCHAR_T diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt index 13e96357..46dbc3ef 100644 --- a/absl/random/CMakeLists.txt +++ b/absl/random/CMakeLists.txt @@ -526,6 +526,8 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} LINKOPTS ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::config ) # Internal-only target, do not depend on directly. @@ -559,6 +561,8 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} LINKOPTS ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::config ) # Internal-only target, do not depend on directly. @@ -618,6 +622,8 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} LINKOPTS ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::config TESTONLY ) @@ -631,6 +637,8 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} LINKOPTS ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::config TESTONLY ) @@ -782,6 +790,8 @@ absl_cc_library( ${ABSL_DEFAULT_COPTS} LINKOPTS ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::config ) # Internal-only target, do not depend on directly. @@ -816,6 +826,7 @@ absl_cc_library( ${ABSL_DEFAULT_LINKOPTS} DEPS absl::random_internal_platform + absl::config ) # Internal-only target, do not depend on directly. @@ -835,6 +846,7 @@ absl_cc_library( DEPS absl::random_internal_platform absl::random_internal_randen_hwaes_impl + absl::config ) # Internal-only target, do not depend on directly. @@ -851,6 +863,7 @@ absl_cc_library( ${ABSL_DEFAULT_LINKOPTS} DEPS absl::random_internal_platform + absl::config ) # Internal-only target, do not depend on directly. @@ -868,6 +881,7 @@ absl_cc_library( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS + absl::config absl::core_headers absl::raw_logging_internal absl::strings diff --git a/absl/random/bernoulli_distribution.h b/absl/random/bernoulli_distribution.h index 326fcb6e..25bd0d5c 100644 --- a/absl/random/bernoulli_distribution.h +++ b/absl/random/bernoulli_distribution.h @@ -24,6 +24,7 @@ #include "absl/random/internal/iostream_state_saver.h" namespace absl { +ABSL_NAMESPACE_BEGIN // absl::bernoulli_distribution is a drop in replacement for // std::bernoulli_distribution. It guarantees that (given a perfect @@ -193,6 +194,7 @@ bool bernoulli_distribution::Generate(double p, } } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_ diff --git a/absl/random/beta_distribution.h b/absl/random/beta_distribution.h index b09b02f0..c154066f 100644 --- a/absl/random/beta_distribution.h +++ b/absl/random/beta_distribution.h @@ -29,6 +29,7 @@ #include "absl/random/internal/iostream_state_saver.h" namespace absl { +ABSL_NAMESPACE_BEGIN // absl::beta_distribution: // Generate a floating-point variate conforming to a Beta distribution: @@ -420,6 +421,7 @@ std::basic_istream& operator>>( return is; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_BETA_DISTRIBUTION_H_ diff --git a/absl/random/bit_gen_ref.h b/absl/random/bit_gen_ref.h index 00e904f8..e8771162 100644 --- a/absl/random/bit_gen_ref.h +++ b/absl/random/bit_gen_ref.h @@ -31,6 +31,7 @@ #include "absl/random/internal/mocking_bit_gen_base.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { template @@ -146,6 +147,7 @@ struct DistributionCaller { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_BIT_GEN_REF_H_ diff --git a/absl/random/bit_gen_ref_test.cc b/absl/random/bit_gen_ref_test.cc index bc02ca5c..ca0e4d70 100644 --- a/absl/random/bit_gen_ref_test.cc +++ b/absl/random/bit_gen_ref_test.cc @@ -21,6 +21,7 @@ #include "absl/random/random.h" namespace absl { +ABSL_NAMESPACE_BEGIN class ConstBitGen : public absl::random_internal::MockingBitGenBase { bool CallImpl(const std::type_info&, void*, void* result) override { @@ -96,4 +97,5 @@ TEST(BitGenRefTest, MockingBitGenBaseOverrides) { EXPECT_EQ(FnTest(gen_ref), 42); // Copy } } // namespace +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/discrete_distribution.cc b/absl/random/discrete_distribution.cc index e6c09c51..081accee 100644 --- a/absl/random/discrete_distribution.cc +++ b/absl/random/discrete_distribution.cc @@ -15,6 +15,7 @@ #include "absl/random/discrete_distribution.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // Initializes the distribution table for Walker's Aliasing algorithm, described @@ -93,4 +94,5 @@ std::vector> InitDiscreteDistribution( } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/discrete_distribution.h b/absl/random/discrete_distribution.h index 1560f03c..171aa11a 100644 --- a/absl/random/discrete_distribution.h +++ b/absl/random/discrete_distribution.h @@ -29,6 +29,7 @@ #include "absl/random/uniform_int_distribution.h" namespace absl { +ABSL_NAMESPACE_BEGIN // absl::discrete_distribution // @@ -240,6 +241,7 @@ std::basic_istream& operator>>( return is; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_ diff --git a/absl/random/distribution_format_traits.h b/absl/random/distribution_format_traits.h index f9f07058..22b358cc 100644 --- a/absl/random/distribution_format_traits.h +++ b/absl/random/distribution_format_traits.h @@ -36,6 +36,7 @@ #include "absl/types/span.h" namespace absl { +ABSL_NAMESPACE_BEGIN struct IntervalClosedClosedTag; struct IntervalClosedOpenTag; @@ -271,6 +272,7 @@ struct DistributionFormatTraits> { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_DISTRIBUTION_FORMAT_TRAITS_H_ diff --git a/absl/random/distributions.h b/absl/random/distributions.h index 6ced6061..c1fb6650 100644 --- a/absl/random/distributions.h +++ b/absl/random/distributions.h @@ -67,6 +67,7 @@ #include "absl/random/zipf_distribution.h" namespace absl { +ABSL_NAMESPACE_BEGIN ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosedClosed, {}); @@ -458,6 +459,7 @@ IntType Zipf(URBG&& urbg, // NOLINT(runtime/references) distribution_t, format_t>(&urbg, hi, q, v); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_DISTRIBUTIONS_H_ diff --git a/absl/random/exponential_distribution.h b/absl/random/exponential_distribution.h index 24abf57e..b5caf8a1 100644 --- a/absl/random/exponential_distribution.h +++ b/absl/random/exponential_distribution.h @@ -27,6 +27,7 @@ #include "absl/random/internal/iostream_state_saver.h" namespace absl { +ABSL_NAMESPACE_BEGIN // absl::exponential_distribution: // Generates a number conforming to an exponential distribution and is @@ -158,6 +159,7 @@ std::basic_istream& operator>>( return is; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_ diff --git a/absl/random/gaussian_distribution.cc b/absl/random/gaussian_distribution.cc index 5dd84619..c7a72cb2 100644 --- a/absl/random/gaussian_distribution.cc +++ b/absl/random/gaussian_distribution.cc @@ -4,6 +4,7 @@ #include "absl/random/gaussian_distribution.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { const gaussian_distribution_base::Tables @@ -96,6 +97,7 @@ const gaussian_distribution_base::Tables 0.9362826816850632339, 0.9635996931270905952, 1}}; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl // clang-format on diff --git a/absl/random/gaussian_distribution.h b/absl/random/gaussian_distribution.h index c299e944..c1427b06 100644 --- a/absl/random/gaussian_distribution.h +++ b/absl/random/gaussian_distribution.h @@ -33,6 +33,7 @@ #include "absl/random/internal/iostream_state_saver.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // absl::gaussian_distribution_base implements the underlying ziggurat algorithm @@ -267,6 +268,7 @@ inline double gaussian_distribution_base::zignor( } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_ diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel index 952929ea..d7ad4efe 100644 --- a/absl/random/internal/BUILD.bazel +++ b/absl/random/internal/BUILD.bazel @@ -51,6 +51,7 @@ cc_library( visibility = [ "//absl/random:__pkg__", ], + deps = ["//absl/base:config"], ) cc_library( @@ -78,6 +79,7 @@ cc_library( visibility = [ "//absl/random:__pkg__", ], + deps = ["//absl/base:config"], ) cc_library( @@ -138,6 +140,7 @@ cc_library( ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, + deps = ["//absl/base:config"], ) cc_library( @@ -148,6 +151,7 @@ cc_library( ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, + deps = ["//absl/base:config"], ) cc_library( @@ -269,6 +273,7 @@ cc_library( "randen-keys.inc", "platform.h", ], + deps = ["//absl/base:config"], ) cc_library( @@ -297,6 +302,7 @@ cc_library( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":platform", + "//absl/base:config", "//absl/base:core_headers", ], ) @@ -317,6 +323,7 @@ cc_library( deps = [ ":platform", ":randen_hwaes_impl", + "//absl/base:config", ], ) @@ -338,6 +345,7 @@ cc_library( linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ ":platform", + "//absl/base:config", "//absl/base:core_headers", ], ) @@ -368,6 +376,7 @@ cc_library( copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ + "//absl/base:config", "//absl/base:core_headers", "//absl/base:raw_logging_internal", "//absl/strings", diff --git a/absl/random/internal/chi_square.cc b/absl/random/internal/chi_square.cc index c0acc947..640d48ce 100644 --- a/absl/random/internal/chi_square.cc +++ b/absl/random/internal/chi_square.cc @@ -19,6 +19,7 @@ #include "absl/random/internal/distribution_test_util.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { namespace { @@ -227,4 +228,5 @@ double ChiSquarePValue(double chi_square, int dof) { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/internal/chi_square.h b/absl/random/internal/chi_square.h index fa8646f2..07f4fbe5 100644 --- a/absl/random/internal/chi_square.h +++ b/absl/random/internal/chi_square.h @@ -26,7 +26,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { constexpr const char kChiSquared[] = "chi-squared"; @@ -80,6 +83,7 @@ double ChiSquareValue(int dof, double p); double ChiSquarePValue(double chi_square, int dof); } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_CHI_SQUARE_H_ diff --git a/absl/random/internal/distribution_caller.h b/absl/random/internal/distribution_caller.h index 0318e1f8..02603cf8 100644 --- a/absl/random/internal/distribution_caller.h +++ b/absl/random/internal/distribution_caller.h @@ -19,7 +19,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // DistributionCaller provides an opportunity to overload the general @@ -51,6 +54,7 @@ struct DistributionCaller { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_ diff --git a/absl/random/internal/distribution_test_util.cc b/absl/random/internal/distribution_test_util.cc index 85c8d596..e9005658 100644 --- a/absl/random/internal/distribution_test_util.cc +++ b/absl/random/internal/distribution_test_util.cc @@ -25,6 +25,7 @@ #include "absl/strings/str_format.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { namespace { @@ -413,4 +414,5 @@ double MaxErrorTolerance(double acceptance_probability) { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/internal/distribution_test_util.h b/absl/random/internal/distribution_test_util.h index b5ba49fa..6d94cf6c 100644 --- a/absl/random/internal/distribution_test_util.h +++ b/absl/random/internal/distribution_test_util.h @@ -26,6 +26,7 @@ // non-test code. namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // http://webspace.ship.edu/pgmarr/Geo441/Lectures/Lec%205%20-%20Normality%20Testing.pdf @@ -106,6 +107,7 @@ double BetaIncomplete(double x, double p, double q); double BetaIncompleteInv(double p, double q, double alpha); } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_ diff --git a/absl/random/internal/distributions.h b/absl/random/internal/distributions.h index c8cec02b..d7e3c016 100644 --- a/absl/random/internal/distributions.h +++ b/absl/random/internal/distributions.h @@ -23,6 +23,7 @@ #include "absl/random/internal/uniform_helper.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // In the absence of an explicitly provided return-type, the template @@ -45,6 +46,7 @@ using uniform_inferred_return_t = is_widening_convertible::value, B, A>::type>; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_ diff --git a/absl/random/internal/explicit_seed_seq.h b/absl/random/internal/explicit_seed_seq.h index b660ece5..6a743eaf 100644 --- a/absl/random/internal/explicit_seed_seq.h +++ b/absl/random/internal/explicit_seed_seq.h @@ -22,7 +22,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // This class conforms to the C++ Standard "Seed Sequence" concept @@ -82,6 +85,7 @@ class ExplicitSeedSeq { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_EXPLICIT_SEED_SEQ_H_ diff --git a/absl/random/internal/fast_uniform_bits.h b/absl/random/internal/fast_uniform_bits.h index e8df92f3..f13c8729 100644 --- a/absl/random/internal/fast_uniform_bits.h +++ b/absl/random/internal/fast_uniform_bits.h @@ -20,7 +20,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // Returns true if the input value is zero or a power of two. Useful for // determining if the range of output values in a URBG @@ -255,6 +258,7 @@ FastUniformBits::Generate(URBG& g, // NOLINT(runtime/references) } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_ diff --git a/absl/random/internal/fast_uniform_bits_test.cc b/absl/random/internal/fast_uniform_bits_test.cc index 9f2e8268..f5b837e5 100644 --- a/absl/random/internal/fast_uniform_bits_test.cc +++ b/absl/random/internal/fast_uniform_bits_test.cc @@ -19,6 +19,7 @@ #include "gtest/gtest.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { namespace { @@ -269,4 +270,5 @@ TEST(FastUniformBitsTest, URBG32bitRegression) { } // namespace } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/internal/fastmath.h b/absl/random/internal/fastmath.h index 4bd18410..6baeb5a7 100644 --- a/absl/random/internal/fastmath.h +++ b/absl/random/internal/fastmath.h @@ -25,6 +25,7 @@ #include "absl/base/internal/bits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // Returns the position of the first bit set. @@ -67,6 +68,7 @@ inline constexpr uint64_t rotr(uint64_t value, uint8_t bits) { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_FASTMATH_H_ diff --git a/absl/random/internal/gaussian_distribution_gentables.cc b/absl/random/internal/gaussian_distribution_gentables.cc index 16a23cb2..a2bf0394 100644 --- a/absl/random/internal/gaussian_distribution_gentables.cc +++ b/absl/random/internal/gaussian_distribution_gentables.cc @@ -27,6 +27,7 @@ #include "absl/base/macros.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { namespace { @@ -135,6 +136,7 @@ void TableGenerator::Print(std::ostream* os) { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl int main(int, char**) { diff --git a/absl/random/internal/generate_real.h b/absl/random/internal/generate_real.h index 246d863e..20f6d208 100644 --- a/absl/random/internal/generate_real.h +++ b/absl/random/internal/generate_real.h @@ -29,6 +29,7 @@ #include "absl/random/internal/traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // Tristate tag types controlling the output of GenerateRealFromBits. @@ -139,6 +140,7 @@ inline RealType GenerateRealFromBits(uint64_t bits, int exp_bias = 0) { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_ diff --git a/absl/random/internal/iostream_state_saver.h b/absl/random/internal/iostream_state_saver.h index df88fa76..7378829a 100644 --- a/absl/random/internal/iostream_state_saver.h +++ b/absl/random/internal/iostream_state_saver.h @@ -24,6 +24,7 @@ #include "absl/numeric/int128.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // The null_state_saver does nothing. @@ -238,6 +239,7 @@ inline FloatType read_floating_point(IStream& is) { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_ diff --git a/absl/random/internal/mock_overload_set.h b/absl/random/internal/mock_overload_set.h index 539313d7..c2a30d89 100644 --- a/absl/random/internal/mock_overload_set.h +++ b/absl/random/internal/mock_overload_set.h @@ -23,6 +23,7 @@ #include "absl/random/mocking_bit_gen.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { template @@ -85,5 +86,6 @@ struct MockOverloadSet }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_ diff --git a/absl/random/internal/mocking_bit_gen_base.h b/absl/random/internal/mocking_bit_gen_base.h index aff2ba6d..eeeae9d2 100644 --- a/absl/random/internal/mocking_bit_gen_base.h +++ b/absl/random/internal/mocking_bit_gen_base.h @@ -25,6 +25,7 @@ #include "absl/strings/str_cat.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // MockingBitGenExpectationFormatter is invoked to format unsatisfied mocks @@ -113,6 +114,7 @@ class MockingBitGenBase { }; // namespace random_internal } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_MOCKING_BIT_GEN_BASE_H_ diff --git a/absl/random/internal/nanobenchmark.cc b/absl/random/internal/nanobenchmark.cc index feb81c85..8fee77fc 100644 --- a/absl/random/internal/nanobenchmark.cc +++ b/absl/random/internal/nanobenchmark.cc @@ -70,6 +70,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal_nanobenchmark { namespace { @@ -799,4 +800,5 @@ size_t Measure(const Func func, const void* arg, const FuncInput* inputs, } } // namespace random_internal_nanobenchmark +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/internal/nanobenchmark.h b/absl/random/internal/nanobenchmark.h index c2b650d1..a5097ba2 100644 --- a/absl/random/internal/nanobenchmark.h +++ b/absl/random/internal/nanobenchmark.h @@ -50,7 +50,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal_nanobenchmark { // Input influencing the function being measured (e.g. number of bytes to copy). @@ -163,6 +166,7 @@ static inline size_t MeasureClosure(const Closure& closure, } } // namespace random_internal_nanobenchmark +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_NANOBENCHMARK_H_ diff --git a/absl/random/internal/nanobenchmark_test.cc b/absl/random/internal/nanobenchmark_test.cc index 383345a8..ab824ef5 100644 --- a/absl/random/internal/nanobenchmark_test.cc +++ b/absl/random/internal/nanobenchmark_test.cc @@ -18,6 +18,7 @@ #include "absl/strings/numbers.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal_nanobenchmark { namespace { @@ -67,6 +68,7 @@ void RunAll(const int argc, char* argv[]) { } // namespace } // namespace random_internal_nanobenchmark +ABSL_NAMESPACE_END } // namespace absl int main(int argc, char* argv[]) { diff --git a/absl/random/internal/nonsecure_base.h b/absl/random/internal/nonsecure_base.h index 8847e74b..730fa2ea 100644 --- a/absl/random/internal/nonsecure_base.h +++ b/absl/random/internal/nonsecure_base.h @@ -33,6 +33,7 @@ #include "absl/types/span.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // Each instance of NonsecureURBGBase will be seeded by variates produced @@ -143,6 +144,7 @@ class NonsecureURBGBase { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_ diff --git a/absl/random/internal/pcg_engine.h b/absl/random/internal/pcg_engine.h index b5df4eaf..53c23fe1 100644 --- a/absl/random/internal/pcg_engine.h +++ b/absl/random/internal/pcg_engine.h @@ -24,6 +24,7 @@ #include "absl/random/internal/iostream_state_saver.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // pcg_engine is a simplified implementation of Melissa O'Neil's PCG engine in @@ -300,6 +301,7 @@ using pcg32_2018_engine = pcg_engine< random_internal::pcg_xsh_rr_64_32>; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_ diff --git a/absl/random/internal/pool_urbg.cc b/absl/random/internal/pool_urbg.cc index f2e1c1f6..5bee5307 100644 --- a/absl/random/internal/pool_urbg.cc +++ b/absl/random/internal/pool_urbg.cc @@ -37,6 +37,7 @@ using absl::base_internal::SpinLock; using absl::base_internal::SpinLockHolder; namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { namespace { @@ -249,4 +250,5 @@ template class RandenPool; template class RandenPool; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/internal/pool_urbg.h b/absl/random/internal/pool_urbg.h index 9b2dd4bf..05721929 100644 --- a/absl/random/internal/pool_urbg.h +++ b/absl/random/internal/pool_urbg.h @@ -22,6 +22,7 @@ #include "absl/types/span.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // RandenPool is a thread-safe random number generator [random.req.urbg] that @@ -124,6 +125,7 @@ class PoolURBG { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_POOL_URBG_H_ diff --git a/absl/random/internal/randen.cc b/absl/random/internal/randen.cc index bab8075a..78a1e00c 100644 --- a/absl/random/internal/randen.cc +++ b/absl/random/internal/randen.cc @@ -41,6 +41,7 @@ // structured/low-entropy counters to digits of Pi. namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { namespace { @@ -86,4 +87,5 @@ Randen::Randen() { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/internal/randen.h b/absl/random/internal/randen.h index a4ff2545..c2834aaf 100644 --- a/absl/random/internal/randen.h +++ b/absl/random/internal/randen.h @@ -23,6 +23,7 @@ #include "absl/random/internal/randen_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // RANDen = RANDom generator or beetroots in Swiss German. @@ -95,6 +96,7 @@ class Randen { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_RANDEN_H_ diff --git a/absl/random/internal/randen_detect.cc b/absl/random/internal/randen_detect.cc index d5946b21..d63230c2 100644 --- a/absl/random/internal/randen_detect.cc +++ b/absl/random/internal/randen_detect.cc @@ -95,6 +95,7 @@ static uint32_t GetAuxval(uint32_t hwcap_type) { #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // The default return at the end of the function might be unreachable depending @@ -216,4 +217,5 @@ bool CPUSupportsRandenHwAes() { #endif } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/internal/randen_detect.h b/absl/random/internal/randen_detect.h index 44c5c667..f283f432 100644 --- a/absl/random/internal/randen_detect.h +++ b/absl/random/internal/randen_detect.h @@ -15,7 +15,10 @@ #ifndef ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_ #define ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_ +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // Returns whether the current CPU supports RandenHwAes implementation. @@ -24,6 +27,7 @@ namespace random_internal { bool CPUSupportsRandenHwAes(); } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_ diff --git a/absl/random/internal/randen_engine.h b/absl/random/internal/randen_engine.h index 02212a13..6b337313 100644 --- a/absl/random/internal/randen_engine.h +++ b/absl/random/internal/randen_engine.h @@ -28,6 +28,7 @@ #include "absl/random/internal/randen.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // Deterministic pseudorandom byte generator with backtracking resistance @@ -223,6 +224,7 @@ class alignas(16) randen_engine { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_ diff --git a/absl/random/internal/randen_hwaes.cc b/absl/random/internal/randen_hwaes.cc index 6cc36fd3..e23844f1 100644 --- a/absl/random/internal/randen_hwaes.cc +++ b/absl/random/internal/randen_hwaes.cc @@ -75,6 +75,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // No accelerated implementation. @@ -106,6 +107,7 @@ void RandenHwAes::Generate(const void*, void*) { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #else // defined(ABSL_RANDEN_HWAES_IMPL) @@ -518,6 +520,7 @@ inline ABSL_TARGET_CRYPTO void Permute( } // namespace namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { bool HasRandenHwAesImplementation() { return true; } @@ -629,6 +632,7 @@ void ABSL_TARGET_CRYPTO RandenHwAes::Generate(const void* keys, #endif } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // (ABSL_RANDEN_HWAES_IMPL) diff --git a/absl/random/internal/randen_hwaes.h b/absl/random/internal/randen_hwaes.h index d8e6055f..bce36b52 100644 --- a/absl/random/internal/randen_hwaes.h +++ b/absl/random/internal/randen_hwaes.h @@ -15,12 +15,15 @@ #ifndef ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_ #define ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_ +#include "absl/base/config.h" + // HERMETIC NOTE: The randen_hwaes target must not introduce duplicate // symbols from arbitrary system and other headers, since it may be built // with different flags from other targets, using different levels of // optimization, potentially introducing ODR violations. namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // RANDen = RANDom generator or beetroots in Swiss German. @@ -41,6 +44,7 @@ class RandenHwAes { bool HasRandenHwAesImplementation(); } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_ diff --git a/absl/random/internal/randen_slow.cc b/absl/random/internal/randen_slow.cc index e7959c7e..8d074582 100644 --- a/absl/random/internal/randen_slow.cc +++ b/absl/random/internal/randen_slow.cc @@ -462,6 +462,7 @@ inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Permute( } // namespace namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { const void* RandenSlow::GetKeys() { @@ -501,4 +502,5 @@ void RandenSlow::Generate(const void* keys, void* state_void) { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/internal/randen_slow.h b/absl/random/internal/randen_slow.h index 30586130..72f92b54 100644 --- a/absl/random/internal/randen_slow.h +++ b/absl/random/internal/randen_slow.h @@ -17,7 +17,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // RANDen = RANDom generator or beetroots in Swiss German. @@ -38,6 +41,7 @@ class RandenSlow { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_ diff --git a/absl/random/internal/randen_traits.h b/absl/random/internal/randen_traits.h index 4f1f408d..2b8bbe73 100644 --- a/absl/random/internal/randen_traits.h +++ b/absl/random/internal/randen_traits.h @@ -22,7 +22,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // RANDen = RANDom generator or beetroots in Swiss German. @@ -54,6 +57,7 @@ struct RandenTraits { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_ diff --git a/absl/random/internal/salted_seed_seq.h b/absl/random/internal/salted_seed_seq.h index 86487006..5953a090 100644 --- a/absl/random/internal/salted_seed_seq.h +++ b/absl/random/internal/salted_seed_seq.h @@ -30,6 +30,7 @@ #include "absl/types/span.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // This class conforms to the C++ Standard "Seed Sequence" concept @@ -160,6 +161,7 @@ SaltedSeedSeq::type> MakeSaltedSeedSeq(SSeq&& seq) { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_ diff --git a/absl/random/internal/seed_material.cc b/absl/random/internal/seed_material.cc index ab4dd0c2..4d38a574 100644 --- a/absl/random/internal/seed_material.cc +++ b/absl/random/internal/seed_material.cc @@ -61,6 +61,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { namespace { @@ -214,4 +215,5 @@ absl::optional GetSaltMaterial() { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/internal/seed_material.h b/absl/random/internal/seed_material.h index 57de8a24..4be10e92 100644 --- a/absl/random/internal/seed_material.h +++ b/absl/random/internal/seed_material.h @@ -27,6 +27,7 @@ #include "absl/types/span.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // Returns the number of 32-bit blocks needed to contain the given number of @@ -97,6 +98,7 @@ void MixIntoSeedMaterial(absl::Span sequence, absl::optional GetSaltMaterial(); } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_ diff --git a/absl/random/internal/sequence_urbg.h b/absl/random/internal/sequence_urbg.h index 9a9b5773..bc96a12c 100644 --- a/absl/random/internal/sequence_urbg.h +++ b/absl/random/internal/sequence_urbg.h @@ -21,7 +21,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // `sequence_urbg` is a simple random number generator which meets the @@ -51,6 +54,7 @@ class sequence_urbg { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_SEQUENCE_URBG_H_ diff --git a/absl/random/internal/traits.h b/absl/random/internal/traits.h index 40eb011f..75772bd9 100644 --- a/absl/random/internal/traits.h +++ b/absl/random/internal/traits.h @@ -22,6 +22,7 @@ #include "absl/base/config.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // random_internal::is_widening_convertible @@ -94,6 +95,7 @@ struct make_unsigned_bits { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_TRAITS_H_ diff --git a/absl/random/internal/uniform_helper.h b/absl/random/internal/uniform_helper.h index f68b1823..663107cb 100644 --- a/absl/random/internal/uniform_helper.h +++ b/absl/random/internal/uniform_helper.h @@ -22,6 +22,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN template class uniform_int_distribution; @@ -173,6 +174,7 @@ struct UniformDistributionWrapper : public UniformDistribution { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_ diff --git a/absl/random/internal/wide_multiply.h b/absl/random/internal/wide_multiply.h index ebbfa1f2..6e4cf1be 100644 --- a/absl/random/internal/wide_multiply.h +++ b/absl/random/internal/wide_multiply.h @@ -31,6 +31,7 @@ #include "absl/random/internal/traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { // Helper object to multiply two 64-bit values to a 128-bit value. @@ -104,6 +105,7 @@ struct wide_multiply { #endif } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_ diff --git a/absl/random/log_uniform_int_distribution.h b/absl/random/log_uniform_int_distribution.h index de58bdbe..960816e2 100644 --- a/absl/random/log_uniform_int_distribution.h +++ b/absl/random/log_uniform_int_distribution.h @@ -30,6 +30,7 @@ #include "absl/random/uniform_int_distribution.h" namespace absl { +ABSL_NAMESPACE_BEGIN // log_uniform_int_distribution: // @@ -247,6 +248,7 @@ std::basic_istream& operator>>( return is; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_ diff --git a/absl/random/mock_distributions.h b/absl/random/mock_distributions.h index 1af98a24..d36d5ba0 100644 --- a/absl/random/mock_distributions.h +++ b/absl/random/mock_distributions.h @@ -53,6 +53,7 @@ #include "absl/random/mocking_bit_gen.h" namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // absl::MockUniform @@ -254,6 +255,7 @@ using MockZipf = IntType(MockingBitGen&, IntType, double, double)>; +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_ diff --git a/absl/random/mocking_bit_gen.cc b/absl/random/mocking_bit_gen.cc index 73144528..6bb1e414 100644 --- a/absl/random/mocking_bit_gen.cc +++ b/absl/random/mocking_bit_gen.cc @@ -18,6 +18,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN MockingBitGen::~MockingBitGen() { for (const auto& del : deleters_) { @@ -25,4 +26,5 @@ MockingBitGen::~MockingBitGen() { } } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/mocking_bit_gen.h b/absl/random/mocking_bit_gen.h index d1b524a9..36cef911 100644 --- a/absl/random/mocking_bit_gen.h +++ b/absl/random/mocking_bit_gen.h @@ -51,6 +51,7 @@ #include "absl/utility/utility.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace random_internal { @@ -189,6 +190,7 @@ struct DistributionCaller { }; } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_MOCKING_BIT_GEN_H_ diff --git a/absl/random/poisson_distribution.h b/absl/random/poisson_distribution.h index 23a953ff..cb5f5d5d 100644 --- a/absl/random/poisson_distribution.h +++ b/absl/random/poisson_distribution.h @@ -28,6 +28,7 @@ #include "absl/random/internal/iostream_state_saver.h" namespace absl { +ABSL_NAMESPACE_BEGIN // absl::poisson_distribution: // Generates discrete variates conforming to a Poisson distribution. @@ -251,6 +252,7 @@ std::basic_istream& operator>>( return is; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_POISSON_DISTRIBUTION_H_ diff --git a/absl/random/random.h b/absl/random/random.h index dc6852f4..c8f326e6 100644 --- a/absl/random/random.h +++ b/absl/random/random.h @@ -41,6 +41,7 @@ #include "absl/random/seed_sequences.h" // IWYU pragma: export namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // absl::BitGen @@ -182,6 +183,7 @@ using InsecureBitGen = // discards the intermediate results. // --------------------------------------------------------------------------- +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_RANDOM_H_ diff --git a/absl/random/seed_gen_exception.cc b/absl/random/seed_gen_exception.cc index e4271baa..fdcb54a8 100644 --- a/absl/random/seed_gen_exception.cc +++ b/absl/random/seed_gen_exception.cc @@ -19,6 +19,7 @@ #include "absl/base/config.h" namespace absl { +ABSL_NAMESPACE_BEGIN static constexpr const char kExceptionMessage[] = "Failed generating seed-material for URBG."; @@ -41,4 +42,5 @@ void ThrowSeedGenException() { } } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/seed_gen_exception.h b/absl/random/seed_gen_exception.h index b464d52f..53539005 100644 --- a/absl/random/seed_gen_exception.h +++ b/absl/random/seed_gen_exception.h @@ -28,7 +28,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN //------------------------------------------------------------------------------ // SeedGenException @@ -46,6 +49,7 @@ namespace random_internal { [[noreturn]] void ThrowSeedGenException(); } // namespace random_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_SEED_GEN_EXCEPTION_H_ diff --git a/absl/random/seed_sequences.cc b/absl/random/seed_sequences.cc index 9f319615..426eafd3 100644 --- a/absl/random/seed_sequences.cc +++ b/absl/random/seed_sequences.cc @@ -17,6 +17,7 @@ #include "absl/random/internal/pool_urbg.h" namespace absl { +ABSL_NAMESPACE_BEGIN SeedSeq MakeSeedSeq() { SeedSeq::result_type seed_material[8]; @@ -24,4 +25,5 @@ SeedSeq MakeSeedSeq() { return SeedSeq(std::begin(seed_material), std::end(seed_material)); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/random/seed_sequences.h b/absl/random/seed_sequences.h index 631d1ecd..ff1340cc 100644 --- a/absl/random/seed_sequences.h +++ b/absl/random/seed_sequences.h @@ -34,6 +34,7 @@ #include "absl/types/span.h" namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // absl::SeedSeq @@ -103,6 +104,7 @@ SeedSeq CreateSeedSeqFrom(URBG* urbg) { // SeedSeq MakeSeedSeq(); +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_SEED_SEQUENCES_H_ diff --git a/absl/random/uniform_int_distribution.h b/absl/random/uniform_int_distribution.h index dc8ba8c1..da66564a 100644 --- a/absl/random/uniform_int_distribution.h +++ b/absl/random/uniform_int_distribution.h @@ -40,6 +40,7 @@ #include "absl/random/internal/wide_multiply.h" namespace absl { +ABSL_NAMESPACE_BEGIN // absl::uniform_int_distribution // @@ -268,6 +269,7 @@ uniform_int_distribution::Generate( return helper::hi(product); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_ diff --git a/absl/random/uniform_real_distribution.h b/absl/random/uniform_real_distribution.h index bf2ed2c5..5ba17b23 100644 --- a/absl/random/uniform_real_distribution.h +++ b/absl/random/uniform_real_distribution.h @@ -45,6 +45,7 @@ #include "absl/random/internal/iostream_state_saver.h" namespace absl { +ABSL_NAMESPACE_BEGIN // absl::uniform_real_distribution // @@ -195,6 +196,7 @@ std::basic_istream& operator>>( } return is; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_ diff --git a/absl/random/zipf_distribution.h b/absl/random/zipf_distribution.h index d7b4ac38..22ebc756 100644 --- a/absl/random/zipf_distribution.h +++ b/absl/random/zipf_distribution.h @@ -26,6 +26,7 @@ #include "absl/random/uniform_real_distribution.h" namespace absl { +ABSL_NAMESPACE_BEGIN // absl::zipf_distribution produces random integer-values in the range [0, k], // distributed according to the discrete probability function: @@ -264,6 +265,7 @@ std::basic_istream& operator>>( return is; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_RANDOM_ZIPF_DISTRIBUTION_H_ diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index e38c8ad6..8d0a6b6d 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -94,6 +94,7 @@ cc_library( ], copts = ABSL_DEFAULT_COPTS, deps = [ + "//absl/base:config", "//absl/base:core_headers", "//absl/base:endian", "//absl/meta:type_traits", @@ -413,6 +414,7 @@ cc_test( deps = [ ":pow10_helper", ":strings", + "//absl/base:config", "//absl/base:raw_logging_internal", "//absl/random", "//absl/random:distributions", @@ -489,6 +491,7 @@ cc_test( copts = ABSL_TEST_COPTS, deps = [ ":strings", + "//absl/base:config", "//absl/base:raw_logging_internal", "@com_google_googletest//:gtest_main", ], @@ -504,6 +507,7 @@ cc_test( copts = ABSL_TEST_COPTS, deps = [ ":strings", + "//absl/base:config", "@com_google_googletest//:gtest_main", ], ) @@ -668,6 +672,7 @@ cc_library( srcs = ["internal/pow10_helper.cc"], hdrs = ["internal/pow10_helper.h"], visibility = ["//visibility:private"], + deps = ["//absl/base:config"], ) cc_test( diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index cd52a472..98101573 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -81,6 +81,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::config absl::core_headers absl::endian absl::type_traits @@ -276,6 +277,7 @@ absl_cc_test( absl::strings absl::core_headers absl::pow10_helper + absl::config absl::raw_logging_internal absl::random_random absl::random_distributions @@ -331,6 +333,7 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::strings + absl::config absl::raw_logging_internal gmock_main ) @@ -346,6 +349,7 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::strings + absl::config gmock_main ) @@ -502,6 +506,8 @@ absl_cc_library( "internal/pow10_helper.cc" COPTS ${ABSL_TEST_COPTS} + DEPS + absl::config TESTONLY ) diff --git a/absl/strings/ascii.cc b/absl/strings/ascii.cc index 3f7c581f..abea3e4f 100644 --- a/absl/strings/ascii.cc +++ b/absl/strings/ascii.cc @@ -15,6 +15,7 @@ #include "absl/strings/ascii.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace ascii_internal { // # Table generated by this Python code (bit 0x02 is currently unused): @@ -195,4 +196,5 @@ void RemoveExtraAsciiWhitespace(std::string* str) { str->erase(output_it - &(*str)[0]); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/ascii.h b/absl/strings/ascii.h index f9e4fd1d..792aabe5 100644 --- a/absl/strings/ascii.h +++ b/absl/strings/ascii.h @@ -59,6 +59,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace ascii_internal { // Declaration for an array of bitfields holding character information. @@ -234,6 +235,7 @@ inline void StripAsciiWhitespace(std::string* str) { // Removes leading, trailing, and consecutive internal whitespace. void RemoveExtraAsciiWhitespace(std::string*); +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_ASCII_H_ diff --git a/absl/strings/charconv.cc b/absl/strings/charconv.cc index bc07e7ab..d9bc2dd2 100644 --- a/absl/strings/charconv.cc +++ b/absl/strings/charconv.cc @@ -57,6 +57,7 @@ // narrower mantissas. namespace absl { +ABSL_NAMESPACE_BEGIN namespace { template @@ -980,4 +981,5 @@ const int16_t kPower10ExponentTable[] = { }; } // namespace +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/charconv.h b/absl/strings/charconv.h index 3f5891ba..e04be32f 100644 --- a/absl/strings/charconv.h +++ b/absl/strings/charconv.h @@ -17,7 +17,10 @@ #include // NOLINT(build/c++11) +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN // Workalike compatibilty version of std::chars_format from C++17. // @@ -110,6 +113,7 @@ inline chars_format& operator^=(chars_format& lhs, chars_format rhs) { return lhs; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_CHARCONV_H_ diff --git a/absl/strings/escaping.cc b/absl/strings/escaping.cc index 18b746e3..d2fcd9c1 100644 --- a/absl/strings/escaping.cc +++ b/absl/strings/escaping.cc @@ -33,6 +33,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { // These are used for the leave_nulls_escaped argument to CUnescapeInternal(). @@ -1106,4 +1107,5 @@ std::string BytesToHexString(absl::string_view from) { return result; } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/escaping.h b/absl/strings/escaping.h index 198b9348..f5ca26c5 100644 --- a/absl/strings/escaping.h +++ b/absl/strings/escaping.h @@ -33,6 +33,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN // CUnescape() // @@ -157,6 +158,7 @@ std::string HexStringToBytes(absl::string_view from); // `2*from.size()`. std::string BytesToHexString(absl::string_view from); +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_ESCAPING_H_ diff --git a/absl/strings/internal/char_map.h b/absl/strings/internal/char_map.h index b9108b8c..a76e6036 100644 --- a/absl/strings/internal/char_map.h +++ b/absl/strings/internal/char_map.h @@ -28,6 +28,7 @@ #include "absl/base/port.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { class Charmap { @@ -149,6 +150,7 @@ constexpr Charmap GraphCharmap() { return PrintCharmap() & ~SpaceCharmap(); } constexpr Charmap PunctCharmap() { return GraphCharmap() & ~AlnumCharmap(); } } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_CHAR_MAP_H_ diff --git a/absl/strings/internal/charconv_bigint.cc b/absl/strings/internal/charconv_bigint.cc index 95d471d9..860c27b2 100644 --- a/absl/strings/internal/charconv_bigint.cc +++ b/absl/strings/internal/charconv_bigint.cc @@ -19,6 +19,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { namespace { @@ -354,4 +355,5 @@ template class BigUnsigned<4>; template class BigUnsigned<84>; } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/charconv_bigint.h b/absl/strings/internal/charconv_bigint.h index 7da9a7e7..108e1eb2 100644 --- a/absl/strings/internal/charconv_bigint.h +++ b/absl/strings/internal/charconv_bigint.h @@ -25,6 +25,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { // The largest power that 5 that can be raised to, and still fit in a uint32_t. @@ -414,6 +415,7 @@ extern template class BigUnsigned<4>; extern template class BigUnsigned<84>; } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_ diff --git a/absl/strings/internal/charconv_bigint_test.cc b/absl/strings/internal/charconv_bigint_test.cc index 745714ac..363bcb03 100644 --- a/absl/strings/internal/charconv_bigint_test.cc +++ b/absl/strings/internal/charconv_bigint_test.cc @@ -19,6 +19,7 @@ #include "gtest/gtest.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { TEST(BigUnsigned, ShiftLeft) { @@ -200,4 +201,5 @@ TEST(BigUnsigned, TenToTheNth) { } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/charconv_parse.cc b/absl/strings/internal/charconv_parse.cc index fa9a8965..d9a57a78 100644 --- a/absl/strings/internal/charconv_parse.cc +++ b/absl/strings/internal/charconv_parse.cc @@ -22,6 +22,7 @@ #include "absl/strings/internal/memutil.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { // ParseFloat<10> will read the first 19 significant digits of the mantissa. @@ -499,4 +500,5 @@ template ParsedFloat ParseFloat<16>(const char* begin, const char* end, chars_format format_flags); } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/charconv_parse.h b/absl/strings/internal/charconv_parse.h index 44d06b2e..505998b5 100644 --- a/absl/strings/internal/charconv_parse.h +++ b/absl/strings/internal/charconv_parse.h @@ -17,9 +17,11 @@ #include +#include "absl/base/config.h" #include "absl/strings/charconv.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { // Enum indicating whether a parsed float is a number or special value. @@ -92,5 +94,6 @@ extern template ParsedFloat ParseFloat<16>(const char* begin, const char* end, absl::chars_format format_flags); } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_ diff --git a/absl/strings/internal/escaping_test_common.h b/absl/strings/internal/escaping_test_common.h index bd803031..7b18017a 100644 --- a/absl/strings/internal/escaping_test_common.h +++ b/absl/strings/internal/escaping_test_common.h @@ -22,6 +22,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { struct base64_testcase { @@ -126,6 +127,7 @@ inline const std::array& base64_strings() { } } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_ diff --git a/absl/strings/internal/memutil.cc b/absl/strings/internal/memutil.cc index 77aa63c2..2519c688 100644 --- a/absl/strings/internal/memutil.cc +++ b/absl/strings/internal/memutil.cc @@ -17,6 +17,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { int memcasecmp(const char* s1, const char* s2, size_t len) { @@ -107,4 +108,5 @@ const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle, } } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/memutil.h b/absl/strings/internal/memutil.h index 7c071a82..9ad05358 100644 --- a/absl/strings/internal/memutil.h +++ b/absl/strings/internal/memutil.h @@ -69,6 +69,7 @@ #include "absl/strings/ascii.h" // for absl::ascii_tolower namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { inline char* memcat(char* dest, size_t destlen, const char* src, @@ -141,6 +142,7 @@ const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle, size_t neelen); } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_MEMUTIL_H_ diff --git a/absl/strings/internal/numbers_test_common.h b/absl/strings/internal/numbers_test_common.h index a263219e..1a1e50c4 100644 --- a/absl/strings/internal/numbers_test_common.h +++ b/absl/strings/internal/numbers_test_common.h @@ -23,7 +23,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { template @@ -175,6 +178,7 @@ inline const std::array& strtouint64_test_cases() { } } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_ diff --git a/absl/strings/internal/ostringstream.cc b/absl/strings/internal/ostringstream.cc index d0f0f84b..05324c78 100644 --- a/absl/strings/internal/ostringstream.cc +++ b/absl/strings/internal/ostringstream.cc @@ -15,6 +15,7 @@ #include "absl/strings/internal/ostringstream.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { OStringStream::Buf::int_type OStringStream::overflow(int c) { @@ -31,4 +32,5 @@ std::streamsize OStringStream::xsputn(const char* s, std::streamsize n) { } } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/ostringstream.h b/absl/strings/internal/ostringstream.h index 20792015..d25d6047 100644 --- a/absl/strings/internal/ostringstream.h +++ b/absl/strings/internal/ostringstream.h @@ -23,6 +23,7 @@ #include "absl/base/port.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { // The same as std::ostringstream but appends to a user-specified std::string, @@ -82,6 +83,7 @@ class OStringStream : private std::basic_streambuf, public std::ostream { }; } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_ diff --git a/absl/strings/internal/pow10_helper.cc b/absl/strings/internal/pow10_helper.cc index 03ed8d07..42e96c34 100644 --- a/absl/strings/internal/pow10_helper.cc +++ b/absl/strings/internal/pow10_helper.cc @@ -17,6 +17,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { namespace { @@ -117,4 +118,5 @@ double Pow10(int exp) { } } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/pow10_helper.h b/absl/strings/internal/pow10_helper.h index 9d1aa710..c37c2c3f 100644 --- a/absl/strings/internal/pow10_helper.h +++ b/absl/strings/internal/pow10_helper.h @@ -22,7 +22,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { // Computes the precise value of 10^exp. (I.e. the nearest representable @@ -31,6 +34,7 @@ namespace strings_internal { double Pow10(int exp); } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_ diff --git a/absl/strings/internal/pow10_helper_test.cc b/absl/strings/internal/pow10_helper_test.cc index a4a68b5d..a4ff76d3 100644 --- a/absl/strings/internal/pow10_helper_test.cc +++ b/absl/strings/internal/pow10_helper_test.cc @@ -20,6 +20,7 @@ #include "absl/strings/str_format.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { namespace { @@ -117,4 +118,5 @@ TEST(Pow10HelperTest, Works) { } // namespace } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/resize_uninitialized.h b/absl/strings/internal/resize_uninitialized.h index 0f5e964d..e42628e3 100644 --- a/absl/strings/internal/resize_uninitialized.h +++ b/absl/strings/internal/resize_uninitialized.h @@ -25,6 +25,7 @@ #include "absl/meta/type_traits.h" // for void_t namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { // Is a subclass of true_type or false_type, depending on whether or not @@ -66,6 +67,7 @@ inline void STLStringResizeUninitialized(string_type* s, size_t new_size) { } } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_ diff --git a/absl/strings/internal/stl_type_traits.h b/absl/strings/internal/stl_type_traits.h index 202ab374..6035ca45 100644 --- a/absl/strings/internal/stl_type_traits.h +++ b/absl/strings/internal/stl_type_traits.h @@ -40,6 +40,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { template class T> @@ -242,5 +243,6 @@ struct IsStrictlyBaseOfAndConvertibleToSTLContainer IsConvertibleToSTLContainer> {}; } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_ diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc index b567a5c5..875bd99c 100644 --- a/absl/strings/internal/str_format/arg.cc +++ b/absl/strings/internal/str_format/arg.cc @@ -14,6 +14,7 @@ #include "absl/strings/internal/str_format/float_conversion.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { @@ -386,4 +387,5 @@ ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(); } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index a209a927..b672a229 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -19,6 +19,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN class Cord; class FormatCountCapture; @@ -426,6 +427,7 @@ ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern); } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_ diff --git a/absl/strings/internal/str_format/arg_test.cc b/absl/strings/internal/str_format/arg_test.cc index 3421fac1..96c9cfd3 100644 --- a/absl/strings/internal/str_format/arg_test.cc +++ b/absl/strings/internal/str_format/arg_test.cc @@ -14,6 +14,7 @@ #include "absl/strings/str_format.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { @@ -108,4 +109,5 @@ const char kMyArray[] = "ABCDE"; } // namespace } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_format/bind.cc b/absl/strings/internal/str_format/bind.cc index 45e335a3..1ee281af 100644 --- a/absl/strings/internal/str_format/bind.cc +++ b/absl/strings/internal/str_format/bind.cc @@ -6,6 +6,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { @@ -236,4 +237,5 @@ int SnprintF(char* output, size_t size, const UntypedFormatSpecImpl format, } } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h index dafcd610..2bf0c085 100644 --- a/absl/strings/internal/str_format/bind.h +++ b/absl/strings/internal/str_format/bind.h @@ -13,6 +13,7 @@ #include "absl/types/span.h" namespace absl { +ABSL_NAMESPACE_BEGIN class UntypedFormatSpec; @@ -202,6 +203,7 @@ class StreamedWrapper { }; } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_ diff --git a/absl/strings/internal/str_format/bind_test.cc b/absl/strings/internal/str_format/bind_test.cc index 2574801a..f6817419 100644 --- a/absl/strings/internal/str_format/bind_test.cc +++ b/absl/strings/internal/str_format/bind_test.cc @@ -6,6 +6,7 @@ #include "gtest/gtest.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { @@ -138,4 +139,5 @@ TEST_F(FormatBindTest, FormatPack) { } // namespace } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_format/checker.h b/absl/strings/internal/str_format/checker.h index 04a88827..8993a79b 100644 --- a/absl/strings/internal/str_format/checker.h +++ b/absl/strings/internal/str_format/checker.h @@ -14,6 +14,7 @@ #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { constexpr bool AllOf() { return true; } @@ -319,6 +320,7 @@ constexpr bool ValidFormatImpl(string_view format) { #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_ diff --git a/absl/strings/internal/str_format/checker_test.cc b/absl/strings/internal/str_format/checker_test.cc index 7aa194a7..c309e203 100644 --- a/absl/strings/internal/str_format/checker_test.cc +++ b/absl/strings/internal/str_format/checker_test.cc @@ -5,6 +5,7 @@ #include "absl/strings/str_format.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { @@ -147,4 +148,5 @@ TEST(StrFormatChecker, LongFormat) { } // namespace } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 5f198059..ca994346 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -11,6 +11,7 @@ #include "absl/strings/internal/str_format/bind.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { @@ -646,4 +647,5 @@ TEST_F(FormatConvertTest, ExpectedFailures) { } // namespace } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_format/extension.cc b/absl/strings/internal/str_format/extension.cc index d7f58159..559011bf 100644 --- a/absl/strings/internal/str_format/extension.cc +++ b/absl/strings/internal/str_format/extension.cc @@ -20,6 +20,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { // clang-format off @@ -81,4 +82,5 @@ bool FormatSinkImpl::PutPaddedString(string_view v, int w, int p, bool l) { } } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h index 3f4788c9..5726ea5c 100644 --- a/absl/strings/internal/str_format/extension.h +++ b/absl/strings/internal/str_format/extension.h @@ -26,6 +26,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN class Cord; @@ -406,6 +407,7 @@ inline size_t Excess(size_t used, size_t capacity) { } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_ diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index 9236acdc..ebe4da5b 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -9,6 +9,7 @@ #include "absl/base/config.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { @@ -482,4 +483,5 @@ bool ConvertFloatImpl(double v, const ConversionSpec &conv, } } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_format/float_conversion.h b/absl/strings/internal/str_format/float_conversion.h index 8ba5566d..49a6a636 100644 --- a/absl/strings/internal/str_format/float_conversion.h +++ b/absl/strings/internal/str_format/float_conversion.h @@ -4,6 +4,7 @@ #include "absl/strings/internal/str_format/extension.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { bool ConvertFloatImpl(float v, const ConversionSpec &conv, @@ -16,6 +17,7 @@ bool ConvertFloatImpl(long double v, const ConversionSpec &conv, FormatSinkImpl *sink); } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_ diff --git a/absl/strings/internal/str_format/output.cc b/absl/strings/internal/str_format/output.cc index 38987b63..c4b24706 100644 --- a/absl/strings/internal/str_format/output.cc +++ b/absl/strings/internal/str_format/output.cc @@ -18,6 +18,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { @@ -67,4 +68,5 @@ void FILERawSink::Write(string_view v) { } } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_format/output.h b/absl/strings/internal/str_format/output.h index 6dc2f3f7..28b288b7 100644 --- a/absl/strings/internal/str_format/output.h +++ b/absl/strings/internal/str_format/output.h @@ -29,6 +29,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN class Cord; @@ -97,6 +98,7 @@ auto InvokeFlush(T* out, string_view s) } } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_ diff --git a/absl/strings/internal/str_format/output_test.cc b/absl/strings/internal/str_format/output_test.cc index 6e04abef..e54e6f70 100644 --- a/absl/strings/internal/str_format/output_test.cc +++ b/absl/strings/internal/str_format/output_test.cc @@ -21,6 +21,7 @@ #include "gtest/gtest.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { TEST(InvokeFlush, String) { @@ -67,5 +68,6 @@ TEST(BufferRawSink, Limits) { } } // namespace +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_format/parser.cc b/absl/strings/internal/str_format/parser.cc index 9ef5615c..eff68f35 100644 --- a/absl/strings/internal/str_format/parser.cc +++ b/absl/strings/internal/str_format/parser.cc @@ -14,6 +14,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { using CC = ConversionChar::Id; @@ -300,4 +301,5 @@ bool ParsedFormatBase::MatchesConversions( } } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_format/parser.h b/absl/strings/internal/str_format/parser.h index 4b441f71..116dda06 100644 --- a/absl/strings/internal/str_format/parser.h +++ b/absl/strings/internal/str_format/parser.h @@ -16,6 +16,7 @@ #include "absl/strings/internal/str_format/extension.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { // The analyzed properties of a single specified conversion. @@ -317,6 +318,7 @@ class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase { : ParsedFormatBase(s, allow_ignored, {C...}) {} }; } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_ diff --git a/absl/strings/internal/str_format/parser_test.cc b/absl/strings/internal/str_format/parser_test.cc index 6d356093..33ed8f09 100644 --- a/absl/strings/internal/str_format/parser_test.cc +++ b/absl/strings/internal/str_format/parser_test.cc @@ -7,6 +7,7 @@ #include "absl/base/macros.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { @@ -389,4 +390,5 @@ TEST_F(ParsedFormatTest, ParsingFlagOrder) { } // namespace } // namespace str_format_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/str_join_internal.h b/absl/strings/internal/str_join_internal.h index 7c35f4de..31dbf672 100644 --- a/absl/strings/internal/str_join_internal.h +++ b/absl/strings/internal/str_join_internal.h @@ -43,6 +43,7 @@ #include "absl/strings/str_cat.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { // @@ -307,6 +308,7 @@ std::string JoinRange(const Range& range, absl::string_view separator) { } } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_ diff --git a/absl/strings/internal/str_split_internal.h b/absl/strings/internal/str_split_internal.h index 52f62226..b54f6ebe 100644 --- a/absl/strings/internal/str_split_internal.h +++ b/absl/strings/internal/str_split_internal.h @@ -47,6 +47,7 @@ #endif // _GLIBCXX_DEBUG namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { // This class is implicitly constructible from everything that absl::string_view @@ -448,6 +449,7 @@ class Splitter { }; } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_ diff --git a/absl/strings/internal/utf8.cc b/absl/strings/internal/utf8.cc index 82d36c24..8fd8edc1 100644 --- a/absl/strings/internal/utf8.cc +++ b/absl/strings/internal/utf8.cc @@ -17,6 +17,7 @@ #include "absl/strings/internal/utf8.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { size_t EncodeUTF8Char(char *buffer, char32_t utf8_char) { @@ -48,4 +49,5 @@ size_t EncodeUTF8Char(char *buffer, char32_t utf8_char) { } } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/internal/utf8.h b/absl/strings/internal/utf8.h index 04236304..32fb1093 100644 --- a/absl/strings/internal/utf8.h +++ b/absl/strings/internal/utf8.h @@ -20,7 +20,10 @@ #include #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { // For Unicode code points 0 through 0x10FFFF, EncodeUTF8Char writes @@ -41,6 +44,7 @@ enum { kMaxEncodedUTF8Size = 4 }; size_t EncodeUTF8Char(char *buffer, char32_t utf8_char); } // namespace strings_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_INTERNAL_UTF8_H_ diff --git a/absl/strings/match.cc b/absl/strings/match.cc index 7b24241a..8127cb0c 100644 --- a/absl/strings/match.cc +++ b/absl/strings/match.cc @@ -17,6 +17,7 @@ #include "absl/strings/internal/memutil.h" namespace absl { +ABSL_NAMESPACE_BEGIN bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2) { return (piece1.size() == piece2.size() && @@ -35,4 +36,5 @@ bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) { EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/match.h b/absl/strings/match.h index 762f359f..90fca98a 100644 --- a/absl/strings/match.h +++ b/absl/strings/match.h @@ -20,7 +20,7 @@ // This file contains simple utilities for performing string matching checks. // All of these function parameters are specified as `absl::string_view`, // meaning that these functions can accept `std::string`, `absl::string_view` or -// nul-terminated C-style strings. +// NUL-terminated C-style strings. // // Examples: // std::string s = "foo"; @@ -38,6 +38,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN // StrContains() // @@ -83,6 +84,7 @@ bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix); // case in the comparison. bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix); +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_MATCH_H_ diff --git a/absl/strings/numbers.cc b/absl/strings/numbers.cc index 4890bd54..caab4631 100644 --- a/absl/strings/numbers.cc +++ b/absl/strings/numbers.cc @@ -40,6 +40,7 @@ #include "absl/strings/str_cat.h" namespace absl { +ABSL_NAMESPACE_BEGIN bool SimpleAtof(absl::string_view str, float* out) { *out = 0.0; @@ -911,4 +912,5 @@ bool safe_strtou128_base(absl::string_view text, uint128* value, int base) { } } // namespace numbers_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/numbers.h b/absl/strings/numbers.h index 7a0d6f50..61204683 100644 --- a/absl/strings/numbers.h +++ b/absl/strings/numbers.h @@ -51,6 +51,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN // SimpleAtoi() // @@ -95,11 +96,13 @@ ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out); // unspecified state. ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out); +ABSL_NAMESPACE_END } // namespace absl // End of public API. Implementation details follow. namespace absl { +ABSL_NAMESPACE_BEGIN namespace numbers_internal { // Digit conversion. @@ -254,6 +257,7 @@ ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str, return numbers_internal::safe_strtou128_base(str, out, 10); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_NUMBERS_H_ diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc index 4bd56f5f..d9afe2f3 100644 --- a/absl/strings/str_cat.cc +++ b/absl/strings/str_cat.cc @@ -25,6 +25,7 @@ #include "absl/strings/numbers.h" namespace absl { +ABSL_NAMESPACE_BEGIN AlphaNum::AlphaNum(Hex hex) { static_assert(numbers_internal::kFastToBufferSize >= 32, @@ -241,4 +242,5 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b, assert(out == begin + dest->size()); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/str_cat.h b/absl/strings/str_cat.h index 663a1945..292fa235 100644 --- a/absl/strings/str_cat.h +++ b/absl/strings/str_cat.h @@ -64,6 +64,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { // AlphaNumBuffer allows a way to pass a string to StrCat without having to do @@ -401,6 +402,7 @@ SixDigits(double d) { return result; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_STR_CAT_H_ diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h index c11c93a2..fbbfe43d 100644 --- a/absl/strings/str_format.h +++ b/absl/strings/str_format.h @@ -82,6 +82,7 @@ #include "absl/strings/internal/str_format/parser.h" // IWYU pragma: export namespace absl { +ABSL_NAMESPACE_BEGIN // UntypedFormatSpec // @@ -530,6 +531,7 @@ ABSL_MUST_USE_RESULT inline bool FormatUntyped( str_format_internal::UntypedFormatSpecImpl::Extract(format), args); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_STR_FORMAT_H_ diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc index cfd81bb3..d33bcaa2 100644 --- a/absl/strings/str_format_test.cc +++ b/absl/strings/str_format_test.cc @@ -10,6 +10,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { using str_format_internal::FormatArgImpl; @@ -622,6 +623,7 @@ TEST_F(FormatWrapperTest, ParsedFormat) { } } // namespace +ABSL_NAMESPACE_END } // namespace absl // Some codegen thunks that we can use to easily dump the generated assembly for diff --git a/absl/strings/str_join.h b/absl/strings/str_join.h index 4772f5d1..ae5731a4 100644 --- a/absl/strings/str_join.h +++ b/absl/strings/str_join.h @@ -60,6 +60,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // Concept: Formatter @@ -286,6 +287,7 @@ std::string StrJoin(const std::tuple& value, return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter()); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_STR_JOIN_H_ diff --git a/absl/strings/str_replace.cc b/absl/strings/str_replace.cc index 280f63d3..2bd5fa98 100644 --- a/absl/strings/str_replace.cc +++ b/absl/strings/str_replace.cc @@ -17,6 +17,7 @@ #include "absl/strings/str_cat.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace strings_internal { using FixedMapping = @@ -77,4 +78,5 @@ int StrReplaceAll(strings_internal::FixedMapping replacements, return StrReplaceAll(replacements, target); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/str_replace.h b/absl/strings/str_replace.h index 30540d02..273c7077 100644 --- a/absl/strings/str_replace.h +++ b/absl/strings/str_replace.h @@ -46,6 +46,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN // StrReplaceAll() // @@ -212,6 +213,7 @@ int StrReplaceAll(const StrToStrMapping& replacements, std::string* target) { return substitutions; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_STR_REPLACE_H_ diff --git a/absl/strings/str_split.cc b/absl/strings/str_split.cc index 25931307..d0f86669 100644 --- a/absl/strings/str_split.cc +++ b/absl/strings/str_split.cc @@ -27,6 +27,7 @@ #include "absl/strings/ascii.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { @@ -134,4 +135,5 @@ absl::string_view ByLength::Find(absl::string_view text, return absl::string_view(substr.data() + length_, 0); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/str_split.h b/absl/strings/str_split.h index 73330789..a79cd4a0 100644 --- a/absl/strings/str_split.h +++ b/absl/strings/str_split.h @@ -49,6 +49,7 @@ #include "absl/strings/strip.h" namespace absl { +ABSL_NAMESPACE_BEGIN //------------------------------------------------------------------------------ // Delimiters @@ -506,6 +507,7 @@ StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d, std::move(text), DelimiterType(d), std::move(p)); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_STR_SPLIT_H_ diff --git a/absl/strings/string_view.cc b/absl/strings/string_view.cc index d5e1a3de..c5f5de93 100644 --- a/absl/strings/string_view.cc +++ b/absl/strings/string_view.cc @@ -24,6 +24,7 @@ #include "absl/strings/internal/memutil.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { void WritePadding(std::ostream& o, size_t pad) { @@ -228,6 +229,7 @@ constexpr string_view::size_type string_view::npos; ABSL_STRING_VIEW_SELECTANY constexpr string_view::size_type string_view::kMaxSize; +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_USES_STD_STRING_VIEW diff --git a/absl/strings/string_view.h b/absl/strings/string_view.h index 6a650874..4b34e563 100644 --- a/absl/strings/string_view.h +++ b/absl/strings/string_view.h @@ -35,7 +35,9 @@ #include // IWYU pragma: export namespace absl { +ABSL_NAMESPACE_BEGIN using std::string_view; +ABSL_NAMESPACE_END } // namespace absl #else // ABSL_USES_STD_STRING_VIEW @@ -61,6 +63,7 @@ using std::string_view; #include "absl/base/port.h" namespace absl { +ABSL_NAMESPACE_BEGIN // absl::string_view // @@ -109,10 +112,10 @@ namespace absl { // example, when splitting a string, `std::vector` is a // natural data type for the output. // -// When constructed from a source which is nul-terminated, the `string_view` -// itself will not include the nul-terminator unless a specific size (including -// the nul) is passed to the constructor. As a result, common idioms that work -// on nul-terminated strings do not work on `string_view` objects. If you write +// When constructed from a source which is NUL-terminated, the `string_view` +// itself will not include the NUL-terminator unless a specific size (including +// the NUL) is passed to the constructor. As a result, common idioms that work +// on NUL-terminated strings do not work on `string_view` objects. If you write // code that scans a `string_view`, you must check its length rather than test // for nul, for example. Note, however, that nuls may still be embedded within // a `string_view` explicitly. @@ -179,7 +182,7 @@ class string_view { // doesn't need to be reevaluated after `ptr_` is set. : string_view(str.data(), str.size()) {} - // Implicit constructor of a `string_view` from nul-terminated `str`. When + // Implicit constructor of a `string_view` from NUL-terminated `str`. When // accepting possibly null strings, use `absl::NullSafeStringView(str)` // instead (see below). constexpr string_view(const char* str) // NOLINT(runtime/explicit) @@ -309,8 +312,8 @@ class string_view { // // Returns a pointer to the underlying character array (which is of course // stored elsewhere). Note that `string_view::data()` may contain embedded nul - // characters, but the returned buffer may or may not be nul-terminated; - // therefore, do not pass `data()` to a routine that expects a nul-terminated + // characters, but the returned buffer may or may not be NUL-terminated; + // therefore, do not pass `data()` to a routine that expects a NUL-terminated // std::string. constexpr const_pointer data() const noexcept { return ptr_; } @@ -577,6 +580,7 @@ constexpr bool operator>=(string_view x, string_view y) noexcept { // IO Insertion Operator std::ostream& operator<<(std::ostream& o, string_view piece); +ABSL_NAMESPACE_END } // namespace absl #undef ABSL_INTERNAL_STRING_VIEW_MEMCMP @@ -584,6 +588,7 @@ std::ostream& operator<<(std::ostream& o, string_view piece); #endif // ABSL_USES_STD_STRING_VIEW namespace absl { +ABSL_NAMESPACE_BEGIN // ClippedSubstr() // @@ -604,6 +609,7 @@ inline string_view NullSafeStringView(const char* p) { return p ? string_view(p) : string_view(); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_STRING_VIEW_H_ diff --git a/absl/strings/strip.h b/absl/strings/strip.h index e1341e08..111872ca 100644 --- a/absl/strings/strip.h +++ b/absl/strings/strip.h @@ -30,6 +30,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN // ConsumePrefix() // @@ -84,6 +85,7 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripSuffix( return str; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_STRIP_H_ diff --git a/absl/strings/substitute.cc b/absl/strings/substitute.cc index 5d28c528..5b69a3ef 100644 --- a/absl/strings/substitute.cc +++ b/absl/strings/substitute.cc @@ -23,6 +23,7 @@ #include "absl/strings/string_view.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace substitute_internal { void SubstituteAndAppendArray(std::string* output, absl::string_view format, @@ -166,4 +167,5 @@ Arg::Arg(Dec dec) { } } // namespace substitute_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h index 233e9dcf..766aca42 100644 --- a/absl/strings/substitute.h +++ b/absl/strings/substitute.h @@ -86,6 +86,7 @@ #include "absl/strings/strip.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace substitute_internal { // Arg @@ -681,6 +682,7 @@ std::string Substitute( "format std::string doesn't contain all of $0 through $9"); #endif // ABSL_BAD_CALL_IF +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_STRINGS_SUBSTITUTE_H_ diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel index 36dc98f3..3f876b9f 100644 --- a/absl/synchronization/BUILD.bazel +++ b/absl/synchronization/BUILD.bazel @@ -43,6 +43,7 @@ cc_library( deps = [ "//absl/base", "//absl/base:base_internal", + "//absl/base:config", "//absl/base:core_headers", "//absl/base:malloc_internal", "//absl/base:raw_logging_internal", diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt index 3c47a1bc..dfe5d05d 100644 --- a/absl/synchronization/CMakeLists.txt +++ b/absl/synchronization/CMakeLists.txt @@ -26,6 +26,7 @@ absl_cc_library( DEPS absl::base absl::base_internal + absl::config absl::core_headers absl::malloc_internal absl::raw_logging_internal diff --git a/absl/synchronization/barrier.cc b/absl/synchronization/barrier.cc index c2c539ac..0dfd795e 100644 --- a/absl/synchronization/barrier.cc +++ b/absl/synchronization/barrier.cc @@ -18,6 +18,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN // Return whether int *arg is zero. static bool IsZero(void *arg) { @@ -47,4 +48,5 @@ bool Barrier::Block() { return this->num_to_exit_ == 0; } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/synchronization/barrier.h b/absl/synchronization/barrier.h index cb5d821a..d8e75440 100644 --- a/absl/synchronization/barrier.h +++ b/absl/synchronization/barrier.h @@ -23,6 +23,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN // Barrier // @@ -73,5 +74,6 @@ class Barrier { int num_to_exit_ ABSL_GUARDED_BY(lock_); }; +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_SYNCHRONIZATION_BARRIER_H_ diff --git a/absl/synchronization/blocking_counter.cc b/absl/synchronization/blocking_counter.cc index 481a06b2..3cea7aed 100644 --- a/absl/synchronization/blocking_counter.cc +++ b/absl/synchronization/blocking_counter.cc @@ -17,6 +17,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN // Return whether int *arg is zero. static bool IsZero(void *arg) { @@ -52,4 +53,5 @@ void BlockingCounter::Wait() { // after we return from this method. } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/synchronization/blocking_counter.h b/absl/synchronization/blocking_counter.h index 77560fc0..1f53f9f2 100644 --- a/absl/synchronization/blocking_counter.h +++ b/absl/synchronization/blocking_counter.h @@ -24,6 +24,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN // BlockingCounter // @@ -92,6 +93,7 @@ class BlockingCounter { int num_waiting_ ABSL_GUARDED_BY(lock_); }; +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_ diff --git a/absl/synchronization/blocking_counter_test.cc b/absl/synchronization/blocking_counter_test.cc index c63e3392..2926224a 100644 --- a/absl/synchronization/blocking_counter_test.cc +++ b/absl/synchronization/blocking_counter_test.cc @@ -22,6 +22,7 @@ #include "absl/time/time.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { void PauseAndDecreaseCounter(BlockingCounter* counter, int* done) { @@ -63,4 +64,5 @@ TEST(BlockingCounterTest, BasicFunctionality) { } } // namespace +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/synchronization/internal/create_thread_identity.cc b/absl/synchronization/internal/create_thread_identity.cc index ec49d1ca..fa0070a9 100644 --- a/absl/synchronization/internal/create_thread_identity.cc +++ b/absl/synchronization/internal/create_thread_identity.cc @@ -27,6 +27,7 @@ #include "absl/synchronization/internal/per_thread_sem.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { // ThreadIdentity storage is persistent, we maintain a free-list of previously @@ -133,6 +134,7 @@ base_internal::ThreadIdentity* CreateThreadIdentity() { } } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_LOW_LEVEL_ALLOC_MISSING diff --git a/absl/synchronization/internal/create_thread_identity.h b/absl/synchronization/internal/create_thread_identity.h index 97237a6e..e121f683 100644 --- a/absl/synchronization/internal/create_thread_identity.h +++ b/absl/synchronization/internal/create_thread_identity.h @@ -29,6 +29,7 @@ #include "absl/base/port.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { // Allocates and attaches a ThreadIdentity object for the calling thread. @@ -53,6 +54,7 @@ inline base_internal::ThreadIdentity* GetOrCreateCurrentThreadIdentity() { } } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_ diff --git a/absl/synchronization/internal/graphcycles.cc b/absl/synchronization/internal/graphcycles.cc index 0c8c7564..6a2bcdf6 100644 --- a/absl/synchronization/internal/graphcycles.cc +++ b/absl/synchronization/internal/graphcycles.cc @@ -44,6 +44,7 @@ // Do not use STL. This module does not use standard memory allocation. namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { namespace { @@ -690,6 +691,7 @@ int GraphCycles::GetStackTrace(GraphId id, void*** ptr) { } } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_LOW_LEVEL_ALLOC_MISSING diff --git a/absl/synchronization/internal/graphcycles.h b/absl/synchronization/internal/graphcycles.h index e08dc09d..ceba33e4 100644 --- a/absl/synchronization/internal/graphcycles.h +++ b/absl/synchronization/internal/graphcycles.h @@ -40,7 +40,10 @@ #include +#include "absl/base/config.h" + namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { // Opaque identifier for a graph node. @@ -132,6 +135,7 @@ class GraphCycles { }; } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl #endif diff --git a/absl/synchronization/internal/graphcycles_test.cc b/absl/synchronization/internal/graphcycles_test.cc index 58e8477b..74eaffe7 100644 --- a/absl/synchronization/internal/graphcycles_test.cc +++ b/absl/synchronization/internal/graphcycles_test.cc @@ -25,6 +25,7 @@ #include "absl/base/macros.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { // We emulate a GraphCycles object with a node vector and an edge vector. @@ -459,4 +460,5 @@ TEST_F(GraphCyclesTest, ManyEdges) { } } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h index 61c72e75..d6ac5db0 100644 --- a/absl/synchronization/internal/kernel_timeout.h +++ b/absl/synchronization/internal/kernel_timeout.h @@ -34,6 +34,7 @@ #include "absl/time/time.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { class Futex; @@ -148,6 +149,7 @@ class KernelTimeout { }; } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_ diff --git a/absl/synchronization/internal/mutex_nonprod.cc b/absl/synchronization/internal/mutex_nonprod.cc index 267deaff..4590b98d 100644 --- a/absl/synchronization/internal/mutex_nonprod.cc +++ b/absl/synchronization/internal/mutex_nonprod.cc @@ -31,6 +31,7 @@ #include "absl/time/time.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { namespace { @@ -315,4 +316,5 @@ bool Condition::Eval() const { void RegisterSymbolizer(bool (*)(const void*, char*, int)) {} +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/synchronization/internal/mutex_nonprod.inc b/absl/synchronization/internal/mutex_nonprod.inc index b8d5af79..85dae0ff 100644 --- a/absl/synchronization/internal/mutex_nonprod.inc +++ b/absl/synchronization/internal/mutex_nonprod.inc @@ -36,6 +36,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN class Condition; namespace synchronization_internal { @@ -256,4 +257,5 @@ class SynchronizationStorage { }; } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/synchronization/internal/per_thread_sem.cc b/absl/synchronization/internal/per_thread_sem.cc index 2a78b20f..821ca9b4 100644 --- a/absl/synchronization/internal/per_thread_sem.cc +++ b/absl/synchronization/internal/per_thread_sem.cc @@ -25,6 +25,7 @@ #include "absl/synchronization/internal/waiter.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { void PerThreadSem::SetThreadBlockedCounter(std::atomic *counter) { @@ -62,6 +63,7 @@ void PerThreadSem::Tick(base_internal::ThreadIdentity *identity) { } } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl extern "C" { diff --git a/absl/synchronization/internal/per_thread_sem.h b/absl/synchronization/internal/per_thread_sem.h index 113cdfb7..8ab43915 100644 --- a/absl/synchronization/internal/per_thread_sem.h +++ b/absl/synchronization/internal/per_thread_sem.h @@ -32,6 +32,7 @@ #include "absl/synchronization/internal/kernel_timeout.h" namespace absl { +ABSL_NAMESPACE_BEGIN class Mutex; @@ -85,6 +86,7 @@ class PerThreadSem { }; } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl // In some build configurations we pass --detect-odr-violations to the diff --git a/absl/synchronization/internal/per_thread_sem_test.cc b/absl/synchronization/internal/per_thread_sem_test.cc index dba72390..b5a2f6d4 100644 --- a/absl/synchronization/internal/per_thread_sem_test.cc +++ b/absl/synchronization/internal/per_thread_sem_test.cc @@ -33,6 +33,7 @@ // primitives which might use PerThreadSem, most notably absl::Mutex. namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { class SimpleSemaphore { @@ -175,4 +176,5 @@ TEST_F(PerThreadSemTest, Timeouts) { } // namespace } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/synchronization/internal/thread_pool.h b/absl/synchronization/internal/thread_pool.h index a00f2be8..0cb96dac 100644 --- a/absl/synchronization/internal/thread_pool.h +++ b/absl/synchronization/internal/thread_pool.h @@ -26,6 +26,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { // A simple ThreadPool implementation for tests. @@ -86,6 +87,7 @@ class ThreadPool { }; } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_ diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc index e7000d3a..ddd6081e 100644 --- a/absl/synchronization/internal/waiter.cc +++ b/absl/synchronization/internal/waiter.cc @@ -49,6 +49,7 @@ #include "absl/synchronization/internal/kernel_timeout.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { static void MaybeBecomeIdle() { @@ -481,4 +482,5 @@ void Waiter::InternalCondVarPoke() { #endif } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/synchronization/internal/waiter.h b/absl/synchronization/internal/waiter.h index 9540598b..5af5c282 100644 --- a/absl/synchronization/internal/waiter.h +++ b/absl/synchronization/internal/waiter.h @@ -62,6 +62,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN namespace synchronization_internal { // Waiter is an OS-specific semaphore. @@ -157,6 +158,7 @@ class Waiter { }; } // namespace synchronization_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_ diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index 100def2d..46af8a52 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -71,6 +71,7 @@ ABSL_ATTRIBUTE_WEAK void AbslInternalMutexYield() { std::this_thread::yield(); } } // extern "C" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { @@ -295,7 +296,7 @@ static struct SynchEvent { // this is a trivial hash table for the events bool log; // logging turned on // Constant after initialization - char name[1]; // actually longer---null-terminated std::string + char name[1]; // actually longer---NUL-terminated std::string } * synch_event[kNSynchEvent] ABSL_GUARDED_BY(synch_event_mu); // Ensure that the object at "addr" has a SynchEvent struct associated with it, @@ -2720,4 +2721,5 @@ bool Condition::GuaranteedEqual(const Condition *a, const Condition *b) { a->arg_ == b->arg_ && a->method_ == b->method_; } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h index ccd94618..8c70c4ce 100644 --- a/absl/synchronization/mutex.h +++ b/absl/synchronization/mutex.h @@ -82,6 +82,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN class Condition; struct SynchWaitParams; @@ -1000,7 +1001,7 @@ void RegisterCondVarTracer(void (*fn)(const char *msg, const void *cv)); // // 'pc' is the program counter being symbolized, 'out' is the buffer to write // into, and 'out_size' is the size of the buffer. This function can return -// false if symbolizing failed, or true if a null-terminated symbol was written +// false if symbolizing failed, or true if a NUL-terminated symbol was written // to 'out.' // // This has the same memory ordering concerns as RegisterMutexProfiler() above. @@ -1039,6 +1040,7 @@ enum class OnDeadlockCycle { // the manner chosen here. void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode); +ABSL_NAMESPACE_END } // namespace absl // In some build configurations we pass --detect-odr-violations to the diff --git a/absl/synchronization/notification.cc b/absl/synchronization/notification.cc index 1eb7f416..e91b9038 100644 --- a/absl/synchronization/notification.cc +++ b/absl/synchronization/notification.cc @@ -22,6 +22,7 @@ #include "absl/time/time.h" namespace absl { +ABSL_NAMESPACE_BEGIN void Notification::Notify() { MutexLock l(&this->mutex_); @@ -73,4 +74,5 @@ bool Notification::WaitForNotificationWithDeadline(absl::Time deadline) const { return notified; } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/synchronization/notification.h b/absl/synchronization/notification.h index 36c2ce3d..9a354ca2 100644 --- a/absl/synchronization/notification.h +++ b/absl/synchronization/notification.h @@ -57,6 +57,7 @@ #include "absl/time/time.h" namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // Notification @@ -116,6 +117,7 @@ class Notification { std::atomic notified_yet_; // written under mutex_ }; +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_SYNCHRONIZATION_NOTIFICATION_H_ diff --git a/absl/synchronization/notification_test.cc b/absl/synchronization/notification_test.cc index 059d4cd2..100ea76f 100644 --- a/absl/synchronization/notification_test.cc +++ b/absl/synchronization/notification_test.cc @@ -21,6 +21,7 @@ #include "absl/synchronization/mutex.h" namespace absl { +ABSL_NAMESPACE_BEGIN // A thread-safe class that holds a counter. class ThreadSafeCounter { @@ -128,4 +129,5 @@ TEST(NotificationTest, SanityTest) { BasicTests(true, &local_notification2); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/civil_time.cc b/absl/time/civil_time.cc index 7b86fa8b..ada82cbc 100644 --- a/absl/time/civil_time.cc +++ b/absl/time/civil_time.cc @@ -21,6 +21,7 @@ #include "absl/time/time.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { @@ -170,4 +171,5 @@ std::ostream& operator<<(std::ostream& os, CivilSecond s) { } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/civil_time.h b/absl/time/civil_time.h index 77c3be2e..bb460044 100644 --- a/absl/time/civil_time.h +++ b/absl/time/civil_time.h @@ -76,6 +76,7 @@ #include "absl/time/internal/cctz/include/cctz/civil_time.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { struct second_tag : cctz::detail::second_tag {}; @@ -531,6 +532,7 @@ std::ostream& operator<<(std::ostream& os, CivilSecond s); } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_CIVIL_TIME_H_ diff --git a/absl/time/clock.cc b/absl/time/clock.cc index bc6f5ccf..9e9a0386 100644 --- a/absl/time/clock.cc +++ b/absl/time/clock.cc @@ -34,6 +34,7 @@ #include "absl/base/thread_annotations.h" namespace absl { +ABSL_NAMESPACE_BEGIN Time Now() { // TODO(bww): Get a timespec instead so we don't have to divide. int64_t n = absl::GetCurrentTimeNanos(); @@ -43,6 +44,7 @@ Time Now() { } return time_internal::FromUnixDuration(absl::Nanoseconds(n)); } +ABSL_NAMESPACE_END } // namespace absl // Decide if we should use the fast GetCurrentTimeNanos() algorithm @@ -71,9 +73,11 @@ Time Now() { #if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS namespace absl { +ABSL_NAMESPACE_BEGIN int64_t GetCurrentTimeNanos() { return GET_CURRENT_TIME_NANOS_FROM_SYSTEM(); } +ABSL_NAMESPACE_END } // namespace absl #else // Use the cyclecounter-based implementation below. @@ -91,6 +95,7 @@ static int64_t stats_slow_paths; static int64_t stats_fast_slow_paths; namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { // This is a friend wrapper around UnscaledCycleClock::Now() // (needed to access UnscaledCycleClock). @@ -515,10 +520,12 @@ static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns, return estimated_base_ns; } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS namespace absl { +ABSL_NAMESPACE_BEGIN namespace { // Returns the maximum duration that SleepOnce() can sleep for. @@ -546,6 +553,7 @@ void SleepOnce(absl::Duration to_sleep) { } } // namespace +ABSL_NAMESPACE_END } // namespace absl extern "C" { diff --git a/absl/time/clock.h b/absl/time/clock.h index bb52e4f6..27764a92 100644 --- a/absl/time/clock.h +++ b/absl/time/clock.h @@ -26,6 +26,7 @@ #include "absl/time/time.h" namespace absl { +ABSL_NAMESPACE_BEGIN // Now() // @@ -49,6 +50,7 @@ int64_t GetCurrentTimeNanos(); // * Returns immediately when passed a nonpositive duration. void SleepFor(absl::Duration duration); +ABSL_NAMESPACE_END } // namespace absl // ----------------------------------------------------------------------------- diff --git a/absl/time/duration.cc b/absl/time/duration.cc index f0b4631d..b1af8406 100644 --- a/absl/time/duration.cc +++ b/absl/time/duration.cc @@ -71,6 +71,7 @@ #include "absl/time/time.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { @@ -917,4 +918,5 @@ bool ParseFlag(const std::string& text, Duration* dst, std::string* ) { std::string UnparseFlag(Duration d) { return FormatDuration(d); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc index 5dce9ac8..49ebd118 100644 --- a/absl/time/duration_test.cc +++ b/absl/time/duration_test.cc @@ -762,11 +762,6 @@ TEST(Duration, DivisionByZero) { const double dbl_inf = std::numeric_limits::infinity(); const double dbl_denorm = std::numeric_limits::denorm_min(); - // IEEE 754 behavior - double z = 0.0, two = 2.0; - EXPECT_TRUE(std::isinf(two / z)); - EXPECT_TRUE(std::isnan(z / z)); // We'll return inf - // Operator/(Duration, double) EXPECT_EQ(inf, zero / 0.0); EXPECT_EQ(-inf, zero / -0.0); diff --git a/absl/time/format.cc b/absl/time/format.cc index ebe872cf..5997ef0c 100644 --- a/absl/time/format.cc +++ b/absl/time/format.cc @@ -22,6 +22,7 @@ namespace cctz = absl::time_internal::cctz; namespace absl { +ABSL_NAMESPACE_BEGIN extern const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez"; extern const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez"; @@ -145,4 +146,5 @@ std::string UnparseFlag(absl::Time t) { return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone()); } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/get_current_time_chrono.inc b/absl/time/internal/get_current_time_chrono.inc index 5180230d..5eeb6406 100644 --- a/absl/time/internal/get_current_time_chrono.inc +++ b/absl/time/internal/get_current_time_chrono.inc @@ -16,6 +16,7 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { static int64_t GetCurrentTimeNanosFromSystem() { @@ -26,4 +27,5 @@ static int64_t GetCurrentTimeNanosFromSystem() { } } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/get_current_time_posix.inc b/absl/time/internal/get_current_time_posix.inc index 65474ca6..42072000 100644 --- a/absl/time/internal/get_current_time_posix.inc +++ b/absl/time/internal/get_current_time_posix.inc @@ -7,6 +7,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { static int64_t GetCurrentTimeNanosFromSystem() { @@ -19,4 +20,5 @@ static int64_t GetCurrentTimeNanosFromSystem() { } } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/test_util.cc b/absl/time/internal/test_util.cc index fbddbb73..9bffe121 100644 --- a/absl/time/internal/test_util.cc +++ b/absl/time/internal/test_util.cc @@ -24,6 +24,7 @@ namespace cctz = absl::time_internal::cctz; namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { TimeZone LoadTimeZone(const std::string& name) { @@ -33,9 +34,11 @@ TimeZone LoadTimeZone(const std::string& name) { } } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { namespace cctz_extension { namespace { @@ -123,4 +126,5 @@ ZoneInfoSourceFactory zone_info_source_factory = TestFactory; } // namespace cctz_extension } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/internal/test_util.h b/absl/time/internal/test_util.h index d7319ea8..5c4bf1f6 100644 --- a/absl/time/internal/test_util.h +++ b/absl/time/internal/test_util.h @@ -20,12 +20,14 @@ #include "absl/time/time.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace time_internal { // Loads the named timezone, but dies on any failure. absl::TimeZone LoadTimeZone(const std::string& name); } // namespace time_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_INTERNAL_TEST_UTIL_H_ diff --git a/absl/time/time.cc b/absl/time/time.cc index 60382be7..6bb36cb3 100644 --- a/absl/time/time.cc +++ b/absl/time/time.cc @@ -47,6 +47,7 @@ namespace cctz = absl::time_internal::cctz; namespace absl { +ABSL_NAMESPACE_BEGIN namespace { @@ -494,4 +495,5 @@ struct tm ToTM(absl::Time t, absl::TimeZone tz) { return tm; } +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/time/time.h b/absl/time/time.h index be064813..7507b0cd 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -89,6 +89,7 @@ struct timeval; #include "absl/time/internal/cctz/include/cctz/time_zone.h" namespace absl { +ABSL_NAMESPACE_BEGIN class Duration; // Defined below class Time; // Defined below @@ -1574,6 +1575,7 @@ constexpr Time FromTimeT(time_t t) { return time_internal::FromUnixDuration(Seconds(t)); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TIME_TIME_H_ diff --git a/absl/types/any.h b/absl/types/any.h index f7967694..16bda79c 100644 --- a/absl/types/any.h +++ b/absl/types/any.h @@ -61,10 +61,12 @@ #include // IWYU pragma: export namespace absl { +ABSL_NAMESPACE_BEGIN using std::any; using std::any_cast; using std::bad_any_cast; using std::make_any; +ABSL_NAMESPACE_END } // namespace absl #else // ABSL_USES_STD_ANY @@ -91,6 +93,7 @@ using std::make_any; #endif // !defined(__GNUC__) || defined(__GXX_RTTI) namespace absl { +ABSL_NAMESPACE_BEGIN namespace any_internal { @@ -534,6 +537,7 @@ T* any_cast(any* operand) noexcept { : nullptr; } +ABSL_NAMESPACE_END } // namespace absl #undef ABSL_ANY_DETAIL_HAS_RTTI diff --git a/absl/types/bad_any_cast.cc b/absl/types/bad_any_cast.cc index 2a538126..b0592cc9 100644 --- a/absl/types/bad_any_cast.cc +++ b/absl/types/bad_any_cast.cc @@ -22,6 +22,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN bad_any_cast::~bad_any_cast() = default; @@ -39,6 +40,7 @@ void ThrowBadAnyCast() { } } // namespace any_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_USES_STD_ANY diff --git a/absl/types/bad_any_cast.h b/absl/types/bad_any_cast.h index 6a53c010..114cef80 100644 --- a/absl/types/bad_any_cast.h +++ b/absl/types/bad_any_cast.h @@ -30,12 +30,15 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN using std::bad_any_cast; +ABSL_NAMESPACE_END } // namespace absl #else // ABSL_USES_STD_ANY namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // bad_any_cast @@ -64,6 +67,7 @@ namespace any_internal { [[noreturn]] void ThrowBadAnyCast(); } // namespace any_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_USES_STD_ANY diff --git a/absl/types/bad_optional_access.cc b/absl/types/bad_optional_access.cc index d9ec21bf..26aca70d 100644 --- a/absl/types/bad_optional_access.cc +++ b/absl/types/bad_optional_access.cc @@ -22,6 +22,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN bad_optional_access::~bad_optional_access() = default; @@ -41,6 +42,7 @@ void throw_bad_optional_access() { } } // namespace optional_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_USES_STD_OPTIONAL diff --git a/absl/types/bad_optional_access.h b/absl/types/bad_optional_access.h index 32dd6a91..a500286a 100644 --- a/absl/types/bad_optional_access.h +++ b/absl/types/bad_optional_access.h @@ -30,12 +30,15 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN using std::bad_optional_access; +ABSL_NAMESPACE_END } // namespace absl #else // ABSL_USES_STD_OPTIONAL namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // bad_optional_access @@ -67,6 +70,7 @@ namespace optional_internal { [[noreturn]] void throw_bad_optional_access(); } // namespace optional_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_USES_STD_OPTIONAL diff --git a/absl/types/bad_variant_access.cc b/absl/types/bad_variant_access.cc index dbaea9e9..3dc88cc0 100644 --- a/absl/types/bad_variant_access.cc +++ b/absl/types/bad_variant_access.cc @@ -23,6 +23,7 @@ #include "absl/base/internal/raw_logging.h" namespace absl { +ABSL_NAMESPACE_BEGIN ////////////////////////// // [variant.bad.access] // @@ -57,6 +58,7 @@ void Rethrow() { } } // namespace variant_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_USES_STD_VARIANT diff --git a/absl/types/bad_variant_access.h b/absl/types/bad_variant_access.h index 6935d01b..095969f9 100644 --- a/absl/types/bad_variant_access.h +++ b/absl/types/bad_variant_access.h @@ -30,12 +30,15 @@ #include namespace absl { +ABSL_NAMESPACE_BEGIN using std::bad_variant_access; +ABSL_NAMESPACE_END } // namespace absl #else // ABSL_USES_STD_VARIANT namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // bad_variant_access @@ -71,6 +74,7 @@ namespace variant_internal { [[noreturn]] void Rethrow(); } // namespace variant_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_USES_STD_VARIANT diff --git a/absl/types/compare.h b/absl/types/compare.h index a213e0b0..c29ced52 100644 --- a/absl/types/compare.h +++ b/absl/types/compare.h @@ -39,6 +39,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace compare_internal { using value_type = int8_t; @@ -551,6 +552,7 @@ constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare, } } // namespace compare_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TYPES_COMPARE_H_ diff --git a/absl/types/compare_test.cc b/absl/types/compare_test.cc index ee396fc5..955844b5 100644 --- a/absl/types/compare_test.cc +++ b/absl/types/compare_test.cc @@ -18,6 +18,7 @@ #include "absl/base/casts.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { // This is necessary to avoid a bunch of lint warnings suggesting that we use @@ -334,4 +335,5 @@ TEST(Compare, StaticAsserts) { #endif // __cpp_inline_variables } // namespace +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/types/internal/conformance_aliases.h b/absl/types/internal/conformance_aliases.h index 7d5d0e09..0cc6884e 100644 --- a/absl/types/internal/conformance_aliases.h +++ b/absl/types/internal/conformance_aliases.h @@ -26,6 +26,7 @@ #include "absl/types/internal/conformance_profile.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace types_internal { // Creates both a Profile and a corresponding Archetype with root name "name". @@ -438,6 +439,7 @@ using ExpandSupportedProfiles = Receiver< // (potentially) non-noexcept moves. } // namespace types_internal +ABSL_NAMESPACE_END } // namespace absl #undef ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS diff --git a/absl/types/internal/conformance_archetype.h b/absl/types/internal/conformance_archetype.h index 97ee7265..2349e0f7 100644 --- a/absl/types/internal/conformance_archetype.h +++ b/absl/types/internal/conformance_archetype.h @@ -43,6 +43,7 @@ #include "absl/types/internal/conformance_profile.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace types_internal { // A minimum-conforming implementation of a type with properties specified in @@ -961,6 +962,7 @@ struct EnabledHash { }; } // namespace types_internal +ABSL_NAMESPACE_END } // namespace absl namespace std { diff --git a/absl/types/internal/conformance_profile.h b/absl/types/internal/conformance_profile.h index dce3bbee..e62004fd 100644 --- a/absl/types/internal/conformance_profile.h +++ b/absl/types/internal/conformance_profile.h @@ -44,6 +44,7 @@ // TODO(calabrese) Add support for extending profiles. namespace absl { +ABSL_NAMESPACE_BEGIN namespace types_internal { template @@ -369,6 +370,7 @@ template struct IsProfile : IsProfileImpl::type {}; } // namespace types_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_ diff --git a/absl/types/internal/optional.h b/absl/types/internal/optional.h index d41ccc75..92932b60 100644 --- a/absl/types/internal/optional.h +++ b/absl/types/internal/optional.h @@ -54,6 +54,7 @@ #endif namespace absl { +ABSL_NAMESPACE_BEGIN // Forward declaration template @@ -387,6 +388,7 @@ struct optional_hash_base >()( }; } // namespace optional_internal +ABSL_NAMESPACE_END } // namespace absl #undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS diff --git a/absl/types/internal/span.h b/absl/types/internal/span.h index d203aad5..112612f4 100644 --- a/absl/types/internal/span.h +++ b/absl/types/internal/span.h @@ -26,6 +26,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace span_internal { // A constexpr min function @@ -121,6 +122,7 @@ template using EnableIfConvertibleTo = typename std::enable_if::value>::type; } // namespace span_internal +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TYPES_INTERNAL_SPAN_H_ diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h index 58b38592..71bd3adf 100644 --- a/absl/types/internal/variant.h +++ b/absl/types/internal/variant.h @@ -40,6 +40,7 @@ #if !defined(ABSL_USES_STD_VARIANT) namespace absl { +ABSL_NAMESPACE_BEGIN template class variant; @@ -1638,6 +1639,7 @@ struct VariantHashBase // IWYU pragma: export namespace absl { +ABSL_NAMESPACE_BEGIN using std::bad_optional_access; using std::optional; using std::make_optional; using std::nullopt_t; using std::nullopt; +ABSL_NAMESPACE_END } // namespace absl #else // ABSL_USES_STD_OPTIONAL @@ -65,6 +67,7 @@ using std::nullopt; #include "absl/types/internal/optional.h" namespace absl { +ABSL_NAMESPACE_BEGIN // nullopt_t // @@ -754,6 +757,7 @@ constexpr auto operator>=(const U& v, const optional& x) return static_cast(x) ? static_cast(v >= *x) : true; } +ABSL_NAMESPACE_END } // namespace absl namespace std { diff --git a/absl/types/optional_exception_safety_test.cc b/absl/types/optional_exception_safety_test.cc index 0f7fae6c..8e5fe851 100644 --- a/absl/types/optional_exception_safety_test.cc +++ b/absl/types/optional_exception_safety_test.cc @@ -24,6 +24,7 @@ #include "absl/base/internal/exception_safety_testing.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { @@ -285,6 +286,7 @@ TEST(OptionalExceptionSafety, NothrowMoveAssign) { } // namespace +ABSL_NAMESPACE_END } // namespace absl #endif // #if !defined(ABSL_USES_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS) diff --git a/absl/types/span.h b/absl/types/span.h index b007fc1f..3283145a 100644 --- a/absl/types/span.h +++ b/absl/types/span.h @@ -71,6 +71,7 @@ #include "absl/types/internal/span.h" namespace absl { +ABSL_NAMESPACE_BEGIN //------------------------------------------------------------------------------ // Span @@ -707,5 +708,6 @@ template constexpr Span MakeConstSpan(const T (&array)[N]) noexcept { return Span(array, N); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TYPES_SPAN_H_ diff --git a/absl/types/variant.h b/absl/types/variant.h index f3558703..776d19a1 100644 --- a/absl/types/variant.h +++ b/absl/types/variant.h @@ -50,6 +50,7 @@ #include // IWYU pragma: export namespace absl { +ABSL_NAMESPACE_BEGIN using std::bad_variant_access; using std::get; using std::get_if; @@ -62,6 +63,7 @@ using std::variant_npos; using std::variant_size; using std::variant_size_v; using std::visit; +ABSL_NAMESPACE_END } // namespace absl #else // ABSL_USES_STD_VARIANT @@ -77,6 +79,7 @@ using std::visit; #include "absl/types/internal/variant.h" namespace absl { +ABSL_NAMESPACE_BEGIN // ----------------------------------------------------------------------------- // absl::variant @@ -795,6 +798,7 @@ operator>=(const variant& a, const variant& b) { a.index()); } +ABSL_NAMESPACE_END } // namespace absl namespace std { @@ -815,6 +819,7 @@ struct hash> #endif // ABSL_USES_STD_VARIANT namespace absl { +ABSL_NAMESPACE_BEGIN namespace variant_internal { // Helper visitor for converting a variant` into another type (mostly @@ -850,6 +855,7 @@ To ConvertVariantTo(Variant&& variant) { std::forward(variant)); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_TYPES_VARIANT_H_ diff --git a/absl/types/variant_benchmark.cc b/absl/types/variant_benchmark.cc index a5f52164..350b1753 100644 --- a/absl/types/variant_benchmark.cc +++ b/absl/types/variant_benchmark.cc @@ -28,6 +28,7 @@ #include "absl/utility/utility.h" namespace absl { +ABSL_NAMESPACE_BEGIN namespace { template @@ -217,4 +218,5 @@ BENCHMARK_TEMPLATE(BM_RedundantVisit, 4, 2) ->DenseRange(0, integral_pow(4, 2) - 1); } // namespace +ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/types/variant_exception_safety_test.cc b/absl/types/variant_exception_safety_test.cc index b486a71e..439c6e1d 100644 --- a/absl/types/variant_exception_safety_test.cc +++ b/absl/types/variant_exception_safety_test.cc @@ -34,6 +34,7 @@ #if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) namespace absl { +ABSL_NAMESPACE_BEGIN namespace { using ::testing::MakeExceptionSafetyTester; @@ -523,6 +524,7 @@ TEST(VariantExceptionSafetyTest, Swap) { } } // namespace +ABSL_NAMESPACE_END } // namespace absl #endif // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE) diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc index 2913775a..96393333 100644 --- a/absl/types/variant_test.cc +++ b/absl/types/variant_test.cc @@ -70,6 +70,7 @@ struct hash { struct NonHashable {}; namespace absl { +ABSL_NAMESPACE_BEGIN namespace { using ::testing::DoubleEq; @@ -2709,6 +2710,7 @@ TEST(VariantTest, MoveCtorBug) { } } // namespace +ABSL_NAMESPACE_END } // namespace absl #endif // #if !defined(ABSL_USES_STD_VARIANT) diff --git a/absl/utility/utility.h b/absl/utility/utility.h index 5a98c2c3..e6647c7b 100644 --- a/absl/utility/utility.h +++ b/absl/utility/utility.h @@ -51,6 +51,7 @@ #include "absl/meta/type_traits.h" namespace absl { +ABSL_NAMESPACE_BEGIN // integer_sequence // @@ -343,6 +344,7 @@ constexpr T make_from_tuple(Tuple&& tup) { std::tuple_size>::value>{}); } +ABSL_NAMESPACE_END } // namespace absl #endif // ABSL_UTILITY_UTILITY_H_ -- cgit v1.2.3 From 29235139149790f5afc430c11cec8f1eb1677607 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 18 Dec 2019 11:46:26 -0800 Subject: Export of internal Abseil changes -- a7e789be4687681b98060fddbf8bd1c64a8f5908 by Abseil Team : Support C++20 erase_if API in btree. See the reference here: https://en.cppreference.com/w/cpp/container/set/erase_if. PiperOrigin-RevId: 286235196 -- 952dd2fdd8435dd293e2186c97e14ef3f29a1aa6 by Derek Mauro : Avoids accessing an out-of-bounds value during flag parsing PiperOrigin-RevId: 286206167 -- ba24591ade579fc4446a09bb3f23bf3602908c04 by Abseil Team : Change null term* (and nul term*) to NUL-term* in comments. PiperOrigin-RevId: 286066376 -- d770baecf36f3d7a8214ca2033d90696ba353d00 by Andy Soffer : cmake: Fix x86_64 check on Windows for random copts Import of https://github.com/abseil/abseil-cpp/pull/518 PiperOrigin-RevId: 286056395 -- 9ed007e284ecf6ec79547437dbed9ce3023204b9 by Greg Falcon : Manual re-import of CCTZ from GitHub. filegroup() moved as a side effect of an internal change. PiperOrigin-RevId: 286015866 -- 25441cc5cb7ee906177f8dac0dcd524df0e6e305 by Derek Mauro : Fix implicit cycle in debugging build rules due to .inc files PiperOrigin-RevId: 285873346 GitOrigin-RevId: a7e789be4687681b98060fddbf8bd1c64a8f5908 Change-Id: Idef8cce4e723fccae6bdd749e94e11e655908214 --- absl/container/btree_map.h | 28 ++++++++++++++++ absl/container/btree_set.h | 28 ++++++++++++++++ absl/container/btree_test.cc | 42 ++++++++++++++++++++++++ absl/copts/AbseilConfigureCopts.cmake | 2 +- absl/debugging/BUILD.bazel | 16 ++++----- absl/debugging/CMakeLists.txt | 16 ++++----- absl/flags/parse.cc | 2 +- absl/strings/internal/str_format/arg.cc | 2 +- absl/strings/internal/str_format/convert_test.cc | 2 +- absl/strings/str_format.h | 2 +- absl/time/internal/cctz/BUILD.bazel | 10 +++--- 11 files changed, 124 insertions(+), 26 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/container/btree_map.h b/absl/container/btree_map.h index 470e3197..cbfcb58c 100644 --- a/absl/container/btree_map.h +++ b/absl/container/btree_map.h @@ -412,6 +412,20 @@ void swap(btree_map &x, btree_map &y) { return x.swap(y); } +// absl::erase_if(absl::btree_map<>, Pred) +// +// Erases all elements that satisfy the predicate pred from the container. +template +void erase_if(btree_map &map, Pred pred) { + for (auto it = map.begin(); it != map.end();) { + if (pred(*it)) { + it = map.erase(it); + } else { + ++it; + } + } +} + // absl::btree_multimap // // An `absl::btree_multimap` is an ordered associative container of @@ -701,6 +715,20 @@ void swap(btree_multimap &x, btree_multimap &y) { return x.swap(y); } +// absl::erase_if(absl::btree_multimap<>, Pred) +// +// Erases all elements that satisfy the predicate pred from the container. +template +void erase_if(btree_multimap &map, Pred pred) { + for (auto it = map.begin(); it != map.end();) { + if (pred(*it)) { + it = map.erase(it); + } else { + ++it; + } + } +} + ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/btree_set.h b/absl/container/btree_set.h index 2a4d0ace..127fb940 100644 --- a/absl/container/btree_set.h +++ b/absl/container/btree_set.h @@ -360,6 +360,20 @@ void swap(btree_set &x, btree_set &y) { return x.swap(y); } +// absl::erase_if(absl::btree_set<>, Pred) +// +// Erases all elements that satisfy the predicate pred from the container. +template +void erase_if(btree_set &set, Pred pred) { + for (auto it = set.begin(); it != set.end();) { + if (pred(*it)) { + it = set.erase(it); + } else { + ++it; + } + } +} + // absl::btree_multiset<> // // An `absl::btree_multiset` is an ordered associative container of @@ -649,6 +663,20 @@ void swap(btree_multiset &x, btree_multiset &y) { return x.swap(y); } +// absl::erase_if(absl::btree_multiset<>, Pred) +// +// Erases all elements that satisfy the predicate pred from the container. +template +void erase_if(btree_multiset &set, Pred pred) { + for (auto it = set.begin(); it != set.end();) { + if (pred(*it)) { + it = set.erase(it); + } else { + ++it; + } + } +} + ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/container/btree_test.cc b/absl/container/btree_test.cc index f8aadd62..8692b9c2 100644 --- a/absl/container/btree_test.cc +++ b/absl/container/btree_test.cc @@ -51,6 +51,7 @@ using ::absl::test_internal::InstanceTracker; using ::absl::test_internal::MovableOnlyInstance; using ::testing::ElementsAre; using ::testing::ElementsAreArray; +using ::testing::IsEmpty; using ::testing::Pair; template @@ -2303,6 +2304,47 @@ TEST(Btree, EmptyTree) { EXPECT_GT(s.max_size(), 0); } +bool IsEven(int k) { return k % 2 == 0; } + +TEST(Btree, EraseIf) { + // Test that erase_if works with all the container types and supports lambdas. + { + absl::btree_set s = {1, 3, 5, 6, 100}; + erase_if(s, [](int k) { return k > 3; }); + EXPECT_THAT(s, ElementsAre(1, 3)); + } + { + absl::btree_multiset s = {1, 3, 3, 5, 6, 6, 100}; + erase_if(s, [](int k) { return k <= 3; }); + EXPECT_THAT(s, ElementsAre(5, 6, 6, 100)); + } + { + absl::btree_map m = {{1, 1}, {3, 3}, {6, 6}, {100, 100}}; + erase_if(m, [](std::pair kv) { return kv.first > 3; }); + EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3))); + } + { + absl::btree_multimap m = {{1, 1}, {3, 3}, {3, 6}, + {6, 6}, {6, 7}, {100, 6}}; + erase_if(m, [](std::pair kv) { return kv.second == 6; }); + EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3), Pair(6, 7))); + } + // Test that erasing all elements from a large set works and test support for + // function pointers. + { + absl::btree_set s; + for (int i = 0; i < 1000; ++i) s.insert(2 * i); + erase_if(s, IsEven); + EXPECT_THAT(s, IsEmpty()); + } + // Test that erase_if supports other format of function pointers. + { + absl::btree_set s = {1, 3, 5, 6, 100}; + erase_if(s, &IsEven); + EXPECT_THAT(s, ElementsAre(1, 3, 5)); + } +} + } // namespace } // namespace container_internal ABSL_NAMESPACE_END diff --git a/absl/copts/AbseilConfigureCopts.cmake b/absl/copts/AbseilConfigureCopts.cmake index b4426469..52e89ae5 100644 --- a/absl/copts/AbseilConfigureCopts.cmake +++ b/absl/copts/AbseilConfigureCopts.cmake @@ -5,7 +5,7 @@ set(ABSL_LSAN_LINKOPTS "") set(ABSL_HAVE_LSAN OFF) set(ABSL_DEFAULT_LINKOPTS "") -if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") +if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AMD64") if (MSVC) set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_MSVC_X64_FLAGS}") else() diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel index 32cacefd..a0140891 100644 --- a/absl/debugging/BUILD.bazel +++ b/absl/debugging/BUILD.bazel @@ -31,6 +31,14 @@ licenses(["notice"]) # Apache 2.0 cc_library( name = "stacktrace", srcs = [ + "internal/stacktrace_aarch64-inl.inc", + "internal/stacktrace_arm-inl.inc", + "internal/stacktrace_config.h", + "internal/stacktrace_generic-inl.inc", + "internal/stacktrace_powerpc-inl.inc", + "internal/stacktrace_unimplemented-inl.inc", + "internal/stacktrace_win32-inl.inc", + "internal/stacktrace_x86-inl.inc", "stacktrace.cc", ], hdrs = ["stacktrace.h"], @@ -158,14 +166,6 @@ cc_library( hdrs = [ "internal/address_is_readable.h", "internal/elf_mem_image.h", - "internal/stacktrace_aarch64-inl.inc", - "internal/stacktrace_arm-inl.inc", - "internal/stacktrace_config.h", - "internal/stacktrace_generic-inl.inc", - "internal/stacktrace_powerpc-inl.inc", - "internal/stacktrace_unimplemented-inl.inc", - "internal/stacktrace_win32-inl.inc", - "internal/stacktrace_x86-inl.inc", "internal/vdso_support.h", ], copts = ABSL_DEFAULT_COPTS, diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt index ef9e71fc..66886c7a 100644 --- a/absl/debugging/CMakeLists.txt +++ b/absl/debugging/CMakeLists.txt @@ -19,6 +19,14 @@ absl_cc_library( stacktrace HDRS "stacktrace.h" + "internal/stacktrace_aarch64-inl.inc" + "internal/stacktrace_arm-inl.inc" + "internal/stacktrace_config.h" + "internal/stacktrace_generic-inl.inc" + "internal/stacktrace_powerpc-inl.inc" + "internal/stacktrace_unimplemented-inl.inc" + "internal/stacktrace_win32-inl.inc" + "internal/stacktrace_x86-inl.inc" SRCS "stacktrace.cc" COPTS @@ -137,14 +145,6 @@ absl_cc_library( HDRS "internal/address_is_readable.h" "internal/elf_mem_image.h" - "internal/stacktrace_aarch64-inl.inc" - "internal/stacktrace_arm-inl.inc" - "internal/stacktrace_config.h" - "internal/stacktrace_generic-inl.inc" - "internal/stacktrace_powerpc-inl.inc" - "internal/stacktrace_unimplemented-inl.inc" - "internal/stacktrace_win32-inl.inc" - "internal/stacktrace_x86-inl.inc" "internal/vdso_support.h" SRCS "internal/address_is_readable.cc" diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc index 5a56a356..2f07725f 100644 --- a/absl/flags/parse.cc +++ b/absl/flags/parse.cc @@ -525,7 +525,7 @@ std::tuple DeduceFlagValue(const CommandLineFlag& flag, // --my_string_var --foo=bar // We look for a flag of std::string type, whose value begins with a // dash and corresponds to known flag or standalone --. - if (value[0] == '-' && flag.IsOfType()) { + if (!value.empty() && value[0] == '-' && flag.IsOfType()) { auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1))); if (maybe_flag_name.empty() || diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc index 875bd99c..d3904124 100644 --- a/absl/strings/internal/str_format/arg.cc +++ b/absl/strings/internal/str_format/arg.cc @@ -282,7 +282,7 @@ ConvertResult FormatConvertImpl(const char *v, } else if (conv.precision() < 0) { len = std::strlen(v); } else { - // If precision is set, we look for the null terminator on the valid range. + // If precision is set, we look for the NUL-terminator on the valid range. len = std::find(v, v + conv.precision(), '\0') - v; } return {ConvertStringArg(string_view(v, len), conv, sink)}; diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index ca994346..cbcd7caf 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -154,7 +154,7 @@ TEST_F(FormatConvertTest, StringPrecision) { UntypedFormatSpecImpl format("%.1s"); EXPECT_EQ("a", FormatPack(format, {FormatArgImpl(p)})); - // We cap at the nul terminator. + // We cap at the NUL-terminator. p = "ABC"; UntypedFormatSpecImpl format2("%.10s"); EXPECT_EQ("ABC", FormatPack(format2, {FormatArgImpl(p)})); diff --git a/absl/strings/str_format.h b/absl/strings/str_format.h index fbbfe43d..2f9b4b27 100644 --- a/absl/strings/str_format.h +++ b/absl/strings/str_format.h @@ -402,7 +402,7 @@ int FPrintF(std::FILE* output, const FormatSpec& format, // type-safe); prefer `absl::SNPrintF()` over `std::snprintf()`. // // In particular, a successful call to `absl::SNPrintF()` writes at most `size` -// bytes of the formatted output to `output`, including a null terminator, and +// bytes of the formatted output to `output`, including a NUL-terminator, and // returns the number of bytes that would have been written if truncation did // not occur. In the event of an error, a negative value is returned and `errno` // is set. diff --git a/absl/time/internal/cctz/BUILD.bazel b/absl/time/internal/cctz/BUILD.bazel index 5ad0f036..7a53c815 100644 --- a/absl/time/internal/cctz/BUILD.bazel +++ b/absl/time/internal/cctz/BUILD.bazel @@ -18,6 +18,11 @@ package(features = ["-parse_headers"]) licenses(["notice"]) # Apache License +filegroup( + name = "zoneinfo", + srcs = glob(["testdata/zoneinfo/**"]), +) + config_setting( name = "osx", constraint_values = [ @@ -159,8 +164,3 @@ cc_test( ### examples ### binaries - -filegroup( - name = "zoneinfo", - srcs = glob(["testdata/zoneinfo/**"]), -) -- cgit v1.2.3 From d85783fd0b1bb32b3d3e04d18367cec8d96c9e9a Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 5 May 2020 07:54:14 -0700 Subject: Export of internal Abseil changes -- f34cd235a12ad0ee1fea3a1ee5a427272dc2b285 by Abseil Team : Migrates uses of deprecated map types to recommended types. PiperOrigin-RevId: 309945156 -- e3410a47ad32c0775b6911610bc47b22938decad by Matthew Brown : Internal Change PiperOrigin-RevId: 309856021 -- a58cfa25e0bb59e7fa9647ac1aae65eaccff0086 by Greg Falcon : Internal change. PiperOrigin-RevId: 309804612 -- cdc5ec310035fbe25f496bda283fe655d94d7769 by Mark Barolak : Standardize the header comments for friend functions in cord.h PiperOrigin-RevId: 309779073 -- fe61602701be795e54477b0fdbf5ffc1df12a6b7 by Samuel Benzaquen : Implement %f natively for any input. It evaluates the input at runtime and allocates stack space accordingly. This removes a potential fallback into snprintf, improves performance, and removes all memory allocations in this formatting path. PiperOrigin-RevId: 309752501 -- 79e2a24f3f959e8b06ddf1d440bbabbd5f89b5b7 by Greg Falcon : Add a Cord::swap() method. Many other Abseil types already provide this, but it was missing here. We already provided a two-argument free function form of `swap()`, but that API is better suited for generic code. The swap member function is a better API when the types are known. PiperOrigin-RevId: 309751740 -- 85cdf60024f153fb4fcb7fe68ed2b14b9faf119d by Derek Mauro : Cleanup uses of "linker initialized" SpinLocks PiperOrigin-RevId: 309581867 -- 9e5443bfcec4b94056b13c75326576e987ab88fb by Matt Kulukundis : Clarify intended mixing properties of `absl::Hash` PiperOrigin-RevId: 309520174 -- a0630f0827b67f217aaeae68a448fe4c1101e17d by Greg Falcon : Comment out a test in Emscripten to sidestep `long double` issues. PiperOrigin-RevId: 309482953 GitOrigin-RevId: f34cd235a12ad0ee1fea3a1ee5a427272dc2b285 Change-Id: Icce0c9d547117374d596b9d684e4054ddd118669 --- absl/base/BUILD.bazel | 5 +- absl/base/CMakeLists.txt | 1 + absl/base/internal/low_level_alloc_test.cc | 4 +- absl/debugging/symbolize_elf.inc | 6 +- absl/hash/hash.h | 7 +- absl/random/gaussian_distribution_test.cc | 5 +- absl/random/internal/wide_multiply_test.cc | 2 +- absl/strings/BUILD.bazel | 5 +- absl/strings/CMakeLists.txt | 1 + absl/strings/cord.h | 21 +- absl/strings/cord_test.cc | 3 + absl/strings/internal/str_format/arg.cc | 112 ++-- absl/strings/internal/str_format/arg.h | 78 ++- absl/strings/internal/str_format/arg_test.cc | 5 +- absl/strings/internal/str_format/bind.h | 7 +- absl/strings/internal/str_format/checker_test.cc | 2 +- absl/strings/internal/str_format/convert_test.cc | 245 +++++++- absl/strings/internal/str_format/extension.h | 5 - .../internal/str_format/float_conversion.cc | 694 ++++++++++++++++++++- .../strings/internal/str_format/float_conversion.h | 6 +- absl/strings/internal/str_format/parser.h | 8 +- absl/strings/internal/str_format/parser_test.cc | 6 +- absl/strings/str_format_test.cc | 69 +- absl/strings/substitute.h | 2 +- 24 files changed, 1107 insertions(+), 192 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 1af9e45e..1664a351 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -541,7 +541,10 @@ cc_test( copts = ABSL_TEST_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, tags = ["no_test_ios_x86_64"], - deps = [":malloc_internal"], + deps = [ + ":malloc_internal", + "//absl/container:node_hash_map", + ], ) cc_test( diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index a63b591c..2df2e971 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -497,6 +497,7 @@ absl_cc_test( ${ABSL_TEST_COPTS} DEPS absl::malloc_internal + absl::node_hash_map Threads::Threads ) diff --git a/absl/base/internal/low_level_alloc_test.cc b/absl/base/internal/low_level_alloc_test.cc index 7abbbf9c..2f2eaffa 100644 --- a/absl/base/internal/low_level_alloc_test.cc +++ b/absl/base/internal/low_level_alloc_test.cc @@ -21,6 +21,8 @@ #include #include +#include "absl/container/node_hash_map.h" + namespace absl { ABSL_NAMESPACE_BEGIN namespace base_internal { @@ -75,7 +77,7 @@ static bool using_low_level_alloc = false; // allocations and deallocations are reported via the MallocHook // interface. static void Test(bool use_new_arena, bool call_malloc_hook, int n) { - typedef std::unordered_map AllocMap; + typedef absl::node_hash_map AllocMap; AllocMap allocated; AllocMap::iterator it; BlockDesc block_desc; diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc index fe1d36ee..ec86f9a9 100644 --- a/absl/debugging/symbolize_elf.inc +++ b/absl/debugging/symbolize_elf.inc @@ -149,13 +149,15 @@ struct FileMappingHint { // Moreover, we are using only TryLock(), if the decorator list // is being modified (is busy), we skip all decorators, and possibly // loose some info. Sorry, that's the best we could do. -base_internal::SpinLock g_decorators_mu(base_internal::kLinkerInitialized); +ABSL_CONST_INIT absl::base_internal::SpinLock g_decorators_mu( + absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY); const int kMaxFileMappingHints = 8; int g_num_file_mapping_hints; FileMappingHint g_file_mapping_hints[kMaxFileMappingHints]; // Protects g_file_mapping_hints. -base_internal::SpinLock g_file_mapping_mu(base_internal::kLinkerInitialized); +ABSL_CONST_INIT absl::base_internal::SpinLock g_file_mapping_mu( + absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY); // Async-signal-safe function to zero a buffer. // memset() is not guaranteed to be async-signal-safe. diff --git a/absl/hash/hash.h b/absl/hash/hash.h index 3dbeab69..d7386f6c 100644 --- a/absl/hash/hash.h +++ b/absl/hash/hash.h @@ -37,8 +37,11 @@ // types. Hashing of that combined state is separately done by `absl::Hash`. // // One should assume that a hash algorithm is chosen randomly at the start of -// each process. E.g., absl::Hash()(9) in one process and -// absl::Hash()(9) in another process are likely to differ. +// each process. E.g., `absl::Hash{}(9)` in one process and +// `absl::Hash{}(9)` in another process are likely to differ. +// +// `absl::Hash` is intended to strongly mix input bits with a target of passing +// an [Avalanche Test](https://en.wikipedia.org/wiki/Avalanche_effect). // // Example: // diff --git a/absl/random/gaussian_distribution_test.cc b/absl/random/gaussian_distribution_test.cc index 49c07513..398f0131 100644 --- a/absl/random/gaussian_distribution_test.cc +++ b/absl/random/gaussian_distribution_test.cc @@ -130,12 +130,15 @@ TYPED_TEST(GaussianDistributionInterfaceTest, SerializeTest) { ss >> after; #if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \ - defined(__ppc__) || defined(__PPC__) + defined(__ppc__) || defined(__PPC__) || defined(__EMSCRIPTEN__) if (std::is_same::value) { // Roundtripping floating point values requires sufficient precision // to reconstruct the exact value. It turns out that long double // has some errors doing this on ppc, particularly for values // near {1.0 +/- epsilon}. + // + // Emscripten is even worse, implementing long double as a 128-bit + // type, but shipping with a strtold() that doesn't support that. if (mean <= std::numeric_limits::max() && mean >= std::numeric_limits::lowest()) { EXPECT_EQ(static_cast(before.mean()), diff --git a/absl/random/internal/wide_multiply_test.cc b/absl/random/internal/wide_multiply_test.cc index 922603f2..ca8ce923 100644 --- a/absl/random/internal/wide_multiply_test.cc +++ b/absl/random/internal/wide_multiply_test.cc @@ -28,7 +28,7 @@ TEST(WideMultiplyTest, MultiplyU64ToU128Test) { EXPECT_EQ(absl::uint128(0), MultiplyU64ToU128(0, 0)); - // Max uint64 + // Max uint64_t EXPECT_EQ(MultiplyU64ToU128(kMax, kMax), absl::MakeUint128(0xfffffffffffffffe, 0x0000000000000001)); EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(kMax, 1)); diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 8aecbe59..8220896d 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -638,10 +638,13 @@ cc_library( visibility = ["//visibility:private"], deps = [ ":strings", + "//absl/base:bits", "//absl/base:config", "//absl/base:core_headers", + "//absl/functional:function_ref", "//absl/meta:type_traits", "//absl/numeric:int128", + "//absl/types:optional", "//absl/types:span", ], ) @@ -718,7 +721,7 @@ cc_test( deps = [ ":str_format_internal", "//absl/base:raw_logging_internal", - "//absl/numeric:int128", + "//absl/types:optional", "@com_google_googletest//:gtest_main", ], ) diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index 003794f9..c0ea0c8e 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -392,6 +392,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::bits absl::strings absl::config absl::core_headers diff --git a/absl/strings/cord.h b/absl/strings/cord.h index ae3d2e71..86ae76fd 100644 --- a/absl/strings/cord.h +++ b/absl/strings/cord.h @@ -162,7 +162,7 @@ class Cord { if (contents_.is_tree()) DestroyCordSlow(); } - // Cord::MakeCordFromExternal(data, callable) + // MakeCordFromExternal() // // Creates a Cord that takes ownership of external string memory. The // contents of `data` are not copied to the Cord; instead, the external @@ -246,10 +246,17 @@ class Cord { // (pos + new_size) >= size(), the result is the subrange [pos, size()). Cord Subcord(size_t pos, size_t new_size) const; + // Cord::swap() + // + // Swaps the contents of the Cord with `other`. + void swap(Cord& other) noexcept; + // swap() // - // Swaps the data of Cord `x` with Cord `y`. - friend void swap(Cord& x, Cord& y) noexcept; + // Swaps the contents of two Cords. + friend void swap(Cord& x, Cord& y) noexcept { + x.swap(y); + } // Cord::size() // @@ -1032,6 +1039,10 @@ inline Cord& Cord::operator=(const Cord& x) { inline Cord::Cord(Cord&& src) noexcept : contents_(std::move(src.contents_)) {} +inline void Cord::swap(Cord& other) noexcept { + contents_.Swap(&other.contents_); +} + inline Cord& Cord::operator=(Cord&& x) noexcept { contents_ = std::move(x.contents_); return *this; @@ -1308,10 +1319,6 @@ inline bool operator<=(absl::string_view x, const Cord& y) { return !(y < x); } inline bool operator>=(const Cord& x, absl::string_view y) { return !(x < y); } inline bool operator>=(absl::string_view x, const Cord& y) { return !(x < y); } -// Overload of swap for Cord. The use of non-const references is -// required. :( -inline void swap(Cord& x, Cord& y) noexcept { y.contents_.Swap(&x.contents_); } - // Some internals exposed to test code. namespace strings_internal { class CordTestAccess { diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc index 336cedde..4443c828 100644 --- a/absl/strings/cord_test.cc +++ b/absl/strings/cord_test.cc @@ -396,6 +396,9 @@ TEST(Cord, Swap) { swap(x, y); ASSERT_EQ(x, absl::Cord(b)); ASSERT_EQ(y, absl::Cord(a)); + x.swap(y); + ASSERT_EQ(x, absl::Cord(a)); + ASSERT_EQ(y, absl::Cord(b)); } static void VerifyCopyToString(const absl::Cord& cord) { diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc index a112071c..964f25f7 100644 --- a/absl/strings/internal/str_format/arg.cc +++ b/absl/strings/internal/str_format/arg.cc @@ -167,24 +167,26 @@ class IntDigits { // 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 IntDigits &as_digits, - const ConversionSpec conv) { + const FormatConversionSpecImpl conv) { // always show 0x for %p. - bool alt = conv.has_alt_flag() || conv.conversion_char() == ConversionChar::p; - bool hex = (conv.conversion_char() == FormatConversionChar::x || - conv.conversion_char() == FormatConversionChar::X || - conv.conversion_char() == FormatConversionChar::p); + bool alt = conv.has_alt_flag() || + conv.conversion_char() == FormatConversionCharInternal::p; + bool hex = (conv.conversion_char() == FormatConversionCharInternal::x || + conv.conversion_char() == FormatConversionCharInternal::X || + conv.conversion_char() == FormatConversionCharInternal::p); // From the POSIX description of '#' flag: // "For x or X conversion specifiers, a non-zero result shall have // 0x (or 0X) prefixed to it." if (alt && hex && !as_digits.without_neg_or_zero().empty()) { - return conv.conversion_char() == FormatConversionChar::X ? "0X" : "0x"; + return conv.conversion_char() == FormatConversionCharInternal::X ? "0X" + : "0x"; } return {}; } -string_view SignColumn(bool neg, const ConversionSpec conv) { - if (conv.conversion_char() == FormatConversionChar::d || - conv.conversion_char() == FormatConversionChar::i) { +string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) { + if (conv.conversion_char() == FormatConversionCharInternal::d || + conv.conversion_char() == FormatConversionCharInternal::i) { if (neg) return "-"; if (conv.has_show_pos_flag()) return "+"; if (conv.has_sign_col_flag()) return " "; @@ -192,7 +194,7 @@ string_view SignColumn(bool neg, const ConversionSpec conv) { return {}; } -bool ConvertCharImpl(unsigned char v, const ConversionSpec conv, +bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { size_t fill = 0; if (conv.width() >= 0) fill = conv.width(); @@ -204,7 +206,8 @@ bool ConvertCharImpl(unsigned char v, const ConversionSpec conv, } bool ConvertIntImplInnerSlow(const IntDigits &as_digits, - const ConversionSpec conv, FormatSinkImpl *sink) { + const FormatConversionSpecImpl conv, + FormatSinkImpl *sink) { // Print as a sequence of Substrings: // [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces] size_t fill = 0; @@ -224,7 +227,8 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits, if (!precision_specified) precision = 1; - if (conv.has_alt_flag() && conv.conversion_char() == ConversionChar::o) { + if (conv.has_alt_flag() && + conv.conversion_char() == FormatConversionCharInternal::o) { // From POSIX description of the '#' (alt) flag: // "For o conversion, it increases the precision (if necessary) to // force the first digit of the result to be zero." @@ -258,42 +262,43 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits, } template -bool ConvertIntArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) { +bool ConvertIntArg(T v, const FormatConversionSpecImpl conv, + FormatSinkImpl *sink) { using U = typename MakeUnsigned::type; IntDigits as_digits; switch (conv.conversion_char()) { - case FormatConversionChar::c: + case FormatConversionCharInternal::c: return ConvertCharImpl(static_cast(v), conv, sink); - case FormatConversionChar::o: + case FormatConversionCharInternal::o: as_digits.PrintAsOct(static_cast(v)); break; - case FormatConversionChar::x: + case FormatConversionCharInternal::x: as_digits.PrintAsHexLower(static_cast(v)); break; - case FormatConversionChar::X: + case FormatConversionCharInternal::X: as_digits.PrintAsHexUpper(static_cast(v)); break; - case FormatConversionChar::u: + case FormatConversionCharInternal::u: as_digits.PrintAsDec(static_cast(v)); break; - case FormatConversionChar::d: - case FormatConversionChar::i: + case FormatConversionCharInternal::d: + case FormatConversionCharInternal::i: as_digits.PrintAsDec(v); break; - case FormatConversionChar::a: - case FormatConversionChar::e: - case FormatConversionChar::f: - case FormatConversionChar::g: - case FormatConversionChar::A: - case FormatConversionChar::E: - case FormatConversionChar::F: - case FormatConversionChar::G: + case FormatConversionCharInternal::a: + case FormatConversionCharInternal::e: + case FormatConversionCharInternal::f: + case FormatConversionCharInternal::g: + case FormatConversionCharInternal::A: + case FormatConversionCharInternal::E: + case FormatConversionCharInternal::F: + case FormatConversionCharInternal::G: return ConvertFloatImpl(static_cast(v), conv, sink); default: @@ -308,12 +313,13 @@ bool ConvertIntArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) { } template -bool ConvertFloatArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) { +bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv, + FormatSinkImpl *sink) { return FormatConversionCharIsFloat(conv.conversion_char()) && ConvertFloatImpl(v, conv, sink); } -inline bool ConvertStringArg(string_view v, const ConversionSpec conv, +inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { if (conv.conversion_char() != FormatConversionCharInternal::s) return false; if (conv.is_basic()) { @@ -328,19 +334,20 @@ inline bool ConvertStringArg(string_view v, const ConversionSpec conv, // ==================== Strings ==================== StringConvertResult FormatConvertImpl(const std::string &v, - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertStringArg(v, conv, sink)}; } -StringConvertResult FormatConvertImpl(string_view v, const ConversionSpec conv, +StringConvertResult FormatConvertImpl(string_view v, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertStringArg(v, conv, sink)}; } ArgConvertResult -FormatConvertImpl(const char *v, const ConversionSpec conv, +FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { if (conv.conversion_char() == FormatConversionCharInternal::p) return {FormatConvertImpl(VoidPtr(v), conv, sink).value}; @@ -358,7 +365,7 @@ FormatConvertImpl(const char *v, const ConversionSpec conv, // ==================== Raw pointers ==================== ArgConvertResult FormatConvertImpl( - VoidPtr v, const ConversionSpec conv, FormatSinkImpl *sink) { + VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { if (conv.conversion_char() != FormatConversionCharInternal::p) return {false}; if (!v.value) { sink->Append("(nil)"); @@ -370,82 +377,87 @@ ArgConvertResult FormatConvertImpl( } // ==================== Floats ==================== -FloatingConvertResult FormatConvertImpl(float v, const ConversionSpec conv, +FloatingConvertResult FormatConvertImpl(float v, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertFloatArg(v, conv, sink)}; } -FloatingConvertResult FormatConvertImpl(double v, const ConversionSpec conv, +FloatingConvertResult FormatConvertImpl(double v, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertFloatArg(v, conv, sink)}; } FloatingConvertResult FormatConvertImpl(long double v, - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertFloatArg(v, conv, sink)}; } // ==================== Chars ==================== -IntegralConvertResult FormatConvertImpl(char v, const ConversionSpec conv, +IntegralConvertResult FormatConvertImpl(char v, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(signed char v, - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(unsigned char v, - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } // ==================== Ints ==================== IntegralConvertResult FormatConvertImpl(short v, // NOLINT - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } -IntegralConvertResult FormatConvertImpl(int v, const ConversionSpec conv, +IntegralConvertResult FormatConvertImpl(int v, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } -IntegralConvertResult FormatConvertImpl(unsigned v, const ConversionSpec conv, +IntegralConvertResult FormatConvertImpl(unsigned v, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(long v, // NOLINT - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(long long v, // NOLINT - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(absl::int128 v, - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } IntegralConvertResult FormatConvertImpl(absl::uint128 v, - const ConversionSpec conv, + const FormatConversionSpecImpl conv, FormatSinkImpl *sink) { return {ConvertIntArg(v, conv, sink)}; } diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index f4ac940a..9a1e5ef2 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -67,20 +67,24 @@ constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult) { using StringConvertResult = ArgConvertResult; ArgConvertResult FormatConvertImpl( - VoidPtr v, ConversionSpec conv, FormatSinkImpl* sink); + VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); // Strings. -StringConvertResult FormatConvertImpl(const std::string& v, ConversionSpec conv, +StringConvertResult FormatConvertImpl(const std::string& v, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); -StringConvertResult FormatConvertImpl(string_view v, ConversionSpec conv, +StringConvertResult FormatConvertImpl(string_view v, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); ArgConvertResult -FormatConvertImpl(const char* v, ConversionSpec conv, FormatSinkImpl* sink); +FormatConvertImpl(const char* v, const FormatConversionSpecImpl conv, + FormatSinkImpl* sink); + template ::value>::type* = nullptr> StringConvertResult FormatConvertImpl(const AbslCord& value, - ConversionSpec conv, + FormatConversionSpecImpl conv, FormatSinkImpl* sink) { if (conv.conversion_char() != FormatConversionCharInternal::s) { return {false}; @@ -127,50 +131,55 @@ using FloatingConvertResult = ArgConvertResult; // Floats. -FloatingConvertResult FormatConvertImpl(float v, ConversionSpec conv, +FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); -FloatingConvertResult FormatConvertImpl(double v, ConversionSpec conv, +FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); -FloatingConvertResult FormatConvertImpl(long double v, ConversionSpec conv, +FloatingConvertResult FormatConvertImpl(long double v, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); // Chars. -IntegralConvertResult FormatConvertImpl(char v, ConversionSpec conv, +IntegralConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(signed char v, ConversionSpec conv, +IntegralConvertResult FormatConvertImpl(signed char v, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(unsigned char v, ConversionSpec conv, +IntegralConvertResult FormatConvertImpl(unsigned char v, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); // Ints. IntegralConvertResult FormatConvertImpl(short v, // NOLINT - ConversionSpec conv, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT - ConversionSpec conv, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(int v, ConversionSpec conv, +IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(unsigned v, ConversionSpec conv, +IntegralConvertResult FormatConvertImpl(unsigned v, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(long v, // NOLINT - ConversionSpec conv, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT - ConversionSpec conv, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(long long v, // NOLINT - ConversionSpec conv, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT - ConversionSpec conv, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(int128 v, ConversionSpec conv, +IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); -IntegralConvertResult FormatConvertImpl(uint128 v, ConversionSpec conv, +IntegralConvertResult FormatConvertImpl(uint128 v, + FormatConversionSpecImpl conv, FormatSinkImpl* sink); template ::value, int> = 0> -IntegralConvertResult FormatConvertImpl(T v, ConversionSpec conv, +IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink) { return FormatConvertImpl(static_cast(v), conv, sink); } @@ -181,11 +190,11 @@ template typename std::enable_if::value && !HasUserDefinedConvert::value, IntegralConvertResult>::type -FormatConvertImpl(T v, ConversionSpec conv, FormatSinkImpl* sink); +FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); template StringConvertResult FormatConvertImpl(const StreamedWrapper& v, - ConversionSpec conv, + FormatConversionSpecImpl conv, FormatSinkImpl* out) { std::ostringstream oss; oss << v.v_; @@ -198,7 +207,8 @@ StringConvertResult FormatConvertImpl(const StreamedWrapper& v, struct FormatCountCaptureHelper { template static ArgConvertResult ConvertHelper( - const FormatCountCapture& v, ConversionSpec conv, FormatSinkImpl* sink) { + const FormatCountCapture& v, FormatConversionSpecImpl conv, + FormatSinkImpl* sink) { const absl::enable_if_t& v2 = v; if (conv.conversion_char() != @@ -212,7 +222,8 @@ struct FormatCountCaptureHelper { template ArgConvertResult FormatConvertImpl( - const FormatCountCapture& v, ConversionSpec conv, FormatSinkImpl* sink) { + const FormatCountCapture& v, FormatConversionSpecImpl conv, + FormatSinkImpl* sink) { return FormatCountCaptureHelper::ConvertHelper(v, conv, sink); } @@ -221,13 +232,13 @@ ArgConvertResult FormatConvertImpl( struct FormatArgImplFriend { template static bool ToInt(Arg arg, int* out) { - // A value initialized ConversionSpec has a `none` conv, which tells the - // dispatcher to run the `int` conversion. + // A value initialized FormatConversionSpecImpl 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, str_format_internal::ConversionSpec conv, + static bool Convert(Arg arg, FormatConversionSpecImpl conv, FormatSinkImpl* out) { return arg.dispatcher_(arg.data_, conv, out); } @@ -251,7 +262,7 @@ class FormatArgImpl { char buf[kInlinedSpace]; }; - using Dispatcher = bool (*)(Data, ConversionSpec, void* out); + using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out); template struct store_by_value @@ -393,7 +404,7 @@ class FormatArgImpl { } template - static bool Dispatch(Data arg, ConversionSpec spec, void* out) { + static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) { // A `none` conv indicates that we want the `int` conversion. if (ABSL_PREDICT_FALSE(spec.conversion_char() == FormatConversionCharInternal::kNone)) { @@ -410,8 +421,9 @@ class FormatArgImpl { Dispatcher dispatcher_; }; -#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \ - E template bool FormatArgImpl::Dispatch(Data, ConversionSpec, void*) +#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \ + E template bool FormatArgImpl::Dispatch(Data, FormatConversionSpecImpl, \ + void*) #define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \ diff --git a/absl/strings/internal/str_format/arg_test.cc b/absl/strings/internal/str_format/arg_test.cc index 8d30d8b8..37e5b754 100644 --- a/absl/strings/internal/str_format/arg_test.cc +++ b/absl/strings/internal/str_format/arg_test.cc @@ -95,8 +95,9 @@ TEST_F(FormatArgImplTest, OtherPtrDecayToVoidPtr) { TEST_F(FormatArgImplTest, WorksWithCharArraysOfUnknownSize) { std::string s; FormatSinkImpl sink(&s); - ConversionSpec conv; - FormatConversionSpecImplFriend::SetConversionChar(ConversionChar::s, &conv); + FormatConversionSpecImpl conv; + FormatConversionSpecImplFriend::SetConversionChar(FormatConversionChar::s, + &conv); FormatConversionSpecImplFriend::SetFlags(Flags(), &conv); FormatConversionSpecImplFriend::SetWidth(-1, &conv); FormatConversionSpecImplFriend::SetPrecision(-1, &conv); diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h index 05105d8d..585246e7 100644 --- a/absl/strings/internal/str_format/bind.h +++ b/absl/strings/internal/str_format/bind.h @@ -19,7 +19,7 @@ class UntypedFormatSpec; namespace str_format_internal { -class BoundConversion : public ConversionSpec { +class BoundConversion : public FormatConversionSpecImpl { public: const FormatArgImpl* arg() const { return arg_; } void set_arg(const FormatArgImpl* a) { arg_ = a; } @@ -119,7 +119,7 @@ class FormatSpecTemplate #endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER - template ::type> @@ -190,7 +190,8 @@ class StreamedWrapper { private: template friend ArgConvertResult FormatConvertImpl( - const StreamedWrapper& v, ConversionSpec conv, FormatSinkImpl* out); + const StreamedWrapper& v, FormatConversionSpecImpl conv, + FormatSinkImpl* out); const T& v_; }; diff --git a/absl/strings/internal/str_format/checker_test.cc b/absl/strings/internal/str_format/checker_test.cc index 49a24b40..23348174 100644 --- a/absl/strings/internal/str_format/checker_test.cc +++ b/absl/strings/internal/str_format/checker_test.cc @@ -24,7 +24,7 @@ std::string ConvToString(FormatConversionCharSet conv) { } TEST(StrFormatChecker, ArgumentToConv) { - Conv conv = ArgumentToConv(); + FormatConversionCharSet conv = ArgumentToConv(); EXPECT_EQ(ConvToString(conv), "s"); conv = ArgumentToConv(); diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index cbcd7caf..dd167f76 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -1,14 +1,18 @@ #include #include #include + #include #include +#include #include +#include // NOLINT #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/internal/raw_logging.h" #include "absl/strings/internal/str_format/bind.h" +#include "absl/types/optional.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -57,7 +61,7 @@ std::string Esc(const T &v) { return oss.str(); } -void StrAppend(std::string *dst, const char *format, va_list ap) { +void StrAppendV(std::string *dst, const char *format, va_list ap) { // First try with a small fixed size buffer static const int kSpaceLength = 1024; char space[kSpaceLength]; @@ -98,11 +102,18 @@ void StrAppend(std::string *dst, const char *format, va_list ap) { delete[] buf; } +void StrAppend(std::string *out, const char *format, ...) { + va_list ap; + va_start(ap, format); + StrAppendV(out, format, ap); + va_end(ap); +} + std::string StrPrint(const char *format, ...) { va_list ap; va_start(ap, format); std::string result; - StrAppend(&result, format, ap); + StrAppendV(&result, format, ap); va_end(ap); return result; } @@ -471,8 +482,8 @@ TEST_F(FormatConvertTest, Float) { #endif // _MSC_VER const char *const kFormats[] = { - "%", "%.3", "%8.5", "%9", "%.60", "%.30", "%03", "%+", - "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; + "%", "%.3", "%8.5", "%500", "%.5000", "%.60", "%.30", "%03", + "%+", "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; std::vector doubles = {0.0, -0.0, @@ -489,11 +500,6 @@ TEST_F(FormatConvertTest, Float) { std::numeric_limits::infinity(), -std::numeric_limits::infinity()}; -#ifndef __APPLE__ - // Apple formats NaN differently (+nan) vs. (nan) - doubles.push_back(std::nan("")); -#endif - // Some regression tests. doubles.push_back(0.99999999999999989); @@ -512,43 +518,204 @@ TEST_F(FormatConvertTest, Float) { } } + // Workaround libc bug. + // https://sourceware.org/bugzilla/show_bug.cgi?id=22142 + const bool gcc_bug_22142 = + StrPrint("%f", std::numeric_limits::max()) != + "1797693134862315708145274237317043567980705675258449965989174768031" + "5726078002853876058955863276687817154045895351438246423432132688946" + "4182768467546703537516986049910576551282076245490090389328944075868" + "5084551339423045832369032229481658085593321233482747978262041447231" + "68738177180919299881250404026184124858368.000000"; + + if (!gcc_bug_22142) { + for (int exp = -300; exp <= 300; ++exp) { + const double all_ones_mantissa = 0x1fffffffffffff; + doubles.push_back(std::ldexp(all_ones_mantissa, exp)); + } + } + + if (gcc_bug_22142) { + for (auto &d : doubles) { + using L = std::numeric_limits; + double d2 = std::abs(d); + if (d2 == L::max() || d2 == L::min() || d2 == L::denorm_min()) { + d = 0; + } + } + } + + // Remove duplicates to speed up the logic below. + std::sort(doubles.begin(), doubles.end()); + doubles.erase(std::unique(doubles.begin(), doubles.end()), doubles.end()); + +#ifndef __APPLE__ + // Apple formats NaN differently (+nan) vs. (nan) + doubles.push_back(std::nan("")); +#endif + + // Reserve the space to ensure we don't allocate memory in the output itself. + std::string str_format_result; + str_format_result.reserve(1 << 20); + std::string string_printf_result; + string_printf_result.reserve(1 << 20); + for (const char *fmt : kFormats) { for (char f : {'f', 'F', // 'g', 'G', // 'a', 'A', // 'e', 'E'}) { std::string fmt_str = std::string(fmt) + f; + + if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { + // This particular test takes way too long with snprintf. + // Disable for the case we are not implementing natively. + continue; + } + for (double d : doubles) { int i = -10; FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)}; UntypedFormatSpecImpl format(fmt_str); - // We use ASSERT_EQ here because failures are usually correlated and a - // bug would print way too many failed expectations causing the test to - // time out. - ASSERT_EQ(StrPrint(fmt_str.c_str(), d, i), - FormatPack(format, absl::MakeSpan(args))) - << fmt_str << " " << StrPrint("%.18g", d) << " " - << StrPrint("%.999f", d); + + string_printf_result.clear(); + StrAppend(&string_printf_result, fmt_str.c_str(), d, i); + str_format_result.clear(); + + { + AppendPack(&str_format_result, format, absl::MakeSpan(args)); + } + + if (string_printf_result != str_format_result) { + // We use ASSERT_EQ here because failures are usually correlated and a + // bug would print way too many failed expectations causing the test + // to time out. + ASSERT_EQ(string_printf_result, str_format_result) + << fmt_str << " " << StrPrint("%.18g", d) << " " + << StrPrint("%a", d) << " " << StrPrint("%.1080f", d); + } } } } } +TEST_F(FormatConvertTest, FloatRound) { + std::string s; + const auto format = [&](const char *fmt, double d) -> std::string & { + s.clear(); + FormatArgImpl args[1] = {FormatArgImpl(d)}; + AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); +#if !defined(_MSC_VER) + // MSVC has a different rounding policy than us so we can't test our + // implementation against the native one there. + EXPECT_EQ(StrPrint(fmt, d), s); +#endif // _MSC_VER + + return s; + }; + // All of these values have to be exactly represented. + // Otherwise we might not be testing what we think we are testing. + + // These values can fit in a 64bit "fast" representation. + const double exact_value = 0.00000000000005684341886080801486968994140625; + assert(exact_value == std::pow(2, -44)); + // Round up at a 5xx. + EXPECT_EQ(format("%.13f", exact_value), "0.0000000000001"); + // Round up at a >5 + EXPECT_EQ(format("%.14f", exact_value), "0.00000000000006"); + // Round down at a <5 + EXPECT_EQ(format("%.16f", exact_value), "0.0000000000000568"); + // Nine handling + EXPECT_EQ(format("%.35f", exact_value), + "0.00000000000005684341886080801486969"); + EXPECT_EQ(format("%.36f", exact_value), + "0.000000000000056843418860808014869690"); + // Round down the last nine. + EXPECT_EQ(format("%.37f", exact_value), + "0.0000000000000568434188608080148696899"); + EXPECT_EQ(format("%.10f", 0.000003814697265625), "0.0000038147"); + // Round up the last nine + EXPECT_EQ(format("%.11f", 0.000003814697265625), "0.00000381470"); + EXPECT_EQ(format("%.12f", 0.000003814697265625), "0.000003814697"); + + // Round to even (down) + EXPECT_EQ(format("%.43f", exact_value), + "0.0000000000000568434188608080148696899414062"); + // Exact + EXPECT_EQ(format("%.44f", exact_value), + "0.00000000000005684341886080801486968994140625"); + // Round to even (up), let make the last digits 75 instead of 25 + EXPECT_EQ(format("%.43f", exact_value + std::pow(2, -43)), + "0.0000000000001705302565824240446090698242188"); + // Exact, just to check. + EXPECT_EQ(format("%.44f", exact_value + std::pow(2, -43)), + "0.00000000000017053025658242404460906982421875"); + + // This value has to be small enough that it won't fit in the uint128 + // representation for printing. + const double small_exact_value = + 0.000000000000000000000000000000000000752316384526264005099991383822237233803945956334136013765601092018187046051025390625; // NOLINT + assert(small_exact_value == std::pow(2, -120)); + // Round up at a 5xx. + EXPECT_EQ(format("%.37f", small_exact_value), + "0.0000000000000000000000000000000000008"); + // Round down at a <5 + EXPECT_EQ(format("%.38f", small_exact_value), + "0.00000000000000000000000000000000000075"); + // Round up at a >5 + EXPECT_EQ(format("%.41f", small_exact_value), + "0.00000000000000000000000000000000000075232"); + // Nine handling + EXPECT_EQ(format("%.55f", small_exact_value), + "0.0000000000000000000000000000000000007523163845262640051"); + EXPECT_EQ(format("%.56f", small_exact_value), + "0.00000000000000000000000000000000000075231638452626400510"); + EXPECT_EQ(format("%.57f", small_exact_value), + "0.000000000000000000000000000000000000752316384526264005100"); + EXPECT_EQ(format("%.58f", small_exact_value), + "0.0000000000000000000000000000000000007523163845262640051000"); + // Round down the last nine + EXPECT_EQ(format("%.59f", small_exact_value), + "0.00000000000000000000000000000000000075231638452626400509999"); + // Round up the last nine + EXPECT_EQ(format("%.79f", small_exact_value), + "0.000000000000000000000000000000000000" + "7523163845262640050999913838222372338039460"); + + // Round to even (down) + EXPECT_EQ(format("%.119f", small_exact_value), + "0.000000000000000000000000000000000000" + "75231638452626400509999138382223723380" + "394595633413601376560109201818704605102539062"); + // Exact + EXPECT_EQ(format("%.120f", small_exact_value), + "0.000000000000000000000000000000000000" + "75231638452626400509999138382223723380" + "3945956334136013765601092018187046051025390625"); + // Round to even (up), let make the last digits 75 instead of 25 + EXPECT_EQ(format("%.119f", small_exact_value + std::pow(2, -119)), + "0.000000000000000000000000000000000002" + "25694915357879201529997415146671170141" + "183786900240804129680327605456113815307617188"); + // Exact, just to check. + EXPECT_EQ(format("%.120f", small_exact_value + std::pow(2, -119)), + "0.000000000000000000000000000000000002" + "25694915357879201529997415146671170141" + "1837869002408041296803276054561138153076171875"); +} + TEST_F(FormatConvertTest, LongDouble) { - const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", +#ifdef _MSC_VER + // MSVC has a different rounding policy than us so we can't test our + // implementation against the native one there. + return; +#endif // _MSC_VER + const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000", "%.60", "%+", "% ", "%-10"}; - // This value is not representable in double, but it is in long double that - // uses the extended format. - // This is to verify that we are not truncating the value mistakenly through a - // double. - long double very_precise = 10000000000000000.25L; - std::vector doubles = { 0.0, -0.0, - very_precise, - 1 / very_precise, std::numeric_limits::max(), -std::numeric_limits::max(), std::numeric_limits::min(), @@ -556,22 +723,44 @@ TEST_F(FormatConvertTest, LongDouble) { std::numeric_limits::infinity(), -std::numeric_limits::infinity()}; + for (long double base : {1.L, 12.L, 123.L, 1234.L, 12345.L, 123456.L, + 1234567.L, 12345678.L, 123456789.L, 1234567890.L, + 12345678901.L, 123456789012.L, 1234567890123.L, + // This value is not representable in double, but it + // is in long double that uses the extended format. + // This is to verify that we are not truncating the + // value mistakenly through a double. + 10000000000000000.25L}) { + for (int exp : {-1000, -500, 0, 500, 1000}) { + for (int sign : {1, -1}) { + doubles.push_back(sign * std::ldexp(base, exp)); + doubles.push_back(sign / std::ldexp(base, exp)); + } + } + } + for (const char *fmt : kFormats) { for (char f : {'f', 'F', // 'g', 'G', // 'a', 'A', // 'e', 'E'}) { std::string fmt_str = std::string(fmt) + 'L' + f; + + if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { + // This particular test takes way too long with snprintf. + // Disable for the case we are not implementing natively. + continue; + } + for (auto d : doubles) { FormatArgImpl arg(d); UntypedFormatSpecImpl format(fmt_str); // We use ASSERT_EQ here because failures are usually correlated and a // bug would print way too many failed expectations causing the test to // time out. - ASSERT_EQ(StrPrint(fmt_str.c_str(), d), - FormatPack(format, {&arg, 1})) + ASSERT_EQ(StrPrint(fmt_str.c_str(), d), FormatPack(format, {&arg, 1})) << fmt_str << " " << StrPrint("%.18Lg", d) << " " - << StrPrint("%.999Lf", d); + << StrPrint("%La", d) << " " << StrPrint("%.1080Lf", d); } } } diff --git a/absl/strings/internal/str_format/extension.h b/absl/strings/internal/str_format/extension.h index f0cffe1e..33903df0 100644 --- a/absl/strings/internal/str_format/extension.h +++ b/absl/strings/internal/str_format/extension.h @@ -411,11 +411,6 @@ inline size_t Excess(size_t used, size_t capacity) { return used < capacity ? capacity - used : 0; } -// Type alias for use during migration. -using ConversionChar = FormatConversionChar; -using ConversionSpec = FormatConversionSpecImpl; -using Conv = FormatConversionCharSet; - class FormatConversionSpec { public: // Width and precison are not specified, no flags are set. diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index d6858cff..cdccc86f 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -1,12 +1,22 @@ #include "absl/strings/internal/str_format/float_conversion.h" #include + #include #include #include +#include #include +#include "absl/base/attributes.h" #include "absl/base/config.h" +#include "absl/base/internal/bits.h" +#include "absl/base/optimization.h" +#include "absl/functional/function_ref.h" +#include "absl/meta/type_traits.h" +#include "absl/numeric/int128.h" +#include "absl/types/optional.h" +#include "absl/types/span.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -14,13 +24,640 @@ namespace str_format_internal { namespace { -char *CopyStringTo(string_view v, char *out) { +// The code below wants to avoid heap allocations. +// To do so it needs to allocate memory on the stack. +// `StackArray` will allocate memory on the stack in the form of a uint32_t +// array and call the provided callback with said memory. +// It will allocate memory in increments of 512 bytes. We could allocate the +// largest needed unconditionally, but that is more than we need in most of +// cases. This way we use less stack in the common cases. +class StackArray { + using Func = absl::FunctionRef)>; + static constexpr size_t kStep = 512 / sizeof(uint32_t); + // 5 steps is 2560 bytes, which is enough to hold a long double with the + // largest/smallest exponents. + // The operations below will static_assert their particular maximum. + static constexpr size_t kNumSteps = 5; + + // We do not want this function to be inlined. + // Otherwise the caller will allocate the stack space unnecessarily for all + // the variants even though it only calls one. + template + ABSL_ATTRIBUTE_NOINLINE static void RunWithCapacityImpl(Func f) { + uint32_t values[steps * kStep]{}; + f(absl::MakeSpan(values)); + } + + public: + static constexpr size_t kMaxCapacity = kStep * kNumSteps; + + static void RunWithCapacity(size_t capacity, Func f) { + assert(capacity <= kMaxCapacity); + const size_t step = (capacity + kStep - 1) / kStep; + assert(step <= kNumSteps); + switch (step) { + case 1: + return RunWithCapacityImpl<1>(f); + case 2: + return RunWithCapacityImpl<2>(f); + case 3: + return RunWithCapacityImpl<3>(f); + case 4: + return RunWithCapacityImpl<4>(f); + case 5: + return RunWithCapacityImpl<5>(f); + } + + assert(false && "Invalid capacity"); + } +}; + +// Calculates `10 * (*v) + carry` and stores the result in `*v` and returns +// the carry. +template +inline Int MultiplyBy10WithCarry(Int *v, Int carry) { + using BiggerInt = absl::conditional_t; + BiggerInt tmp = 10 * static_cast(*v) + carry; + *v = static_cast(tmp); + return static_cast(tmp >> (sizeof(Int) * 8)); +} + +// Calculates `(2^64 * carry + *v) / 10`. +// Stores the quotient in `*v` and returns the remainder. +// Requires: `0 <= carry <= 9` +inline uint64_t DivideBy10WithCarry(uint64_t *v, uint64_t carry) { + constexpr uint64_t divisor = 10; + // 2^64 / divisor = chunk_quotient + chunk_remainder / divisor + constexpr uint64_t chunk_quotient = (uint64_t{1} << 63) / (divisor / 2); + constexpr uint64_t chunk_remainder = uint64_t{} - chunk_quotient * divisor; + + const uint64_t mod = *v % divisor; + const uint64_t next_carry = chunk_remainder * carry + mod; + *v = *v / divisor + carry * chunk_quotient + next_carry / divisor; + return next_carry % divisor; +} + +// Generates the decimal representation for an integer of the form `v * 2^exp`, +// where `v` and `exp` are both positive integers. +// It generates the digits from the left (ie the most significant digit first) +// to allow for direct printing into the sink. +// +// Requires `0 <= exp` and `exp <= numeric_limits::max_exponent`. +class BinaryToDecimal { + static constexpr int ChunksNeeded(int exp) { + // We will left shift a uint128 by `exp` bits, so we need `128+exp` total + // bits. Round up to 32. + // See constructor for details about adding `10%` to the value. + return (128 + exp + 31) / 32 * 11 / 10; + } + + public: + // Run the conversion for `v * 2^exp` and call `f(binary_to_decimal)`. + // This function will allocate enough stack space to perform the conversion. + static void RunConversion(uint128 v, int exp, + absl::FunctionRef f) { + assert(exp > 0); + assert(exp <= std::numeric_limits::max_exponent); + static_assert( + StackArray::kMaxCapacity >= + ChunksNeeded(std::numeric_limits::max_exponent), + ""); + + StackArray::RunWithCapacity( + ChunksNeeded(exp), + [=](absl::Span input) { f(BinaryToDecimal(input, v, exp)); }); + } + + int TotalDigits() const { + return static_cast((decimal_end_ - decimal_start_) * kDigitsPerChunk + + CurrentDigits().size()); + } + + // See the current block of digits. + absl::string_view CurrentDigits() const { + return absl::string_view(digits_ + kDigitsPerChunk - size_, size_); + } + + // Advance the current view of digits. + // Returns `false` when no more digits are available. + bool AdvanceDigits() { + if (decimal_start_ >= decimal_end_) return false; + + uint32_t w = data_[decimal_start_++]; + for (size_ = 0; size_ < kDigitsPerChunk; w /= 10) { + digits_[kDigitsPerChunk - ++size_] = w % 10 + '0'; + } + return true; + } + + private: + BinaryToDecimal(absl::Span data, uint128 v, int exp) : data_(data) { + // We need to print the digits directly into the sink object without + // buffering them all first. To do this we need two things: + // - to know the total number of digits to do padding when necessary + // - to generate the decimal digits from the left. + // + // In order to do this, we do a two pass conversion. + // On the first pass we convert the binary representation of the value into + // a decimal representation in which each uint32_t chunk holds up to 9 + // decimal digits. In the second pass we take each decimal-holding-uint32_t + // value and generate the ascii decimal digits into `digits_`. + // + // The binary and decimal representations actually share the same memory + // region. As we go converting the chunks from binary to decimal we free + // them up and reuse them for the decimal representation. One caveat is that + // the decimal representation is around 7% less efficient in space than the + // binary one. We allocate an extra 10% memory to account for this. See + // ChunksNeeded for this calculation. + int chunk_index = exp / 32; + decimal_start_ = decimal_end_ = ChunksNeeded(exp); + const int offset = exp % 32; + // Left shift v by exp bits. + data_[chunk_index] = static_cast(v << offset); + for (v >>= (32 - offset); v; v >>= 32) + data_[++chunk_index] = static_cast(v); + + while (chunk_index >= 0) { + // While we have more than one chunk available, go in steps of 1e9. + // `data_[chunk_index]` holds the highest non-zero binary chunk, so keep + // the variable updated. + uint32_t carry = 0; + for (int i = chunk_index; i >= 0; --i) { + uint64_t tmp = uint64_t{data_[i]} + (uint64_t{carry} << 32); + data_[i] = static_cast(tmp / uint64_t{1000000000}); + carry = static_cast(tmp % uint64_t{1000000000}); + } + + // If the highest chunk is now empty, remove it from view. + if (data_[chunk_index] == 0) --chunk_index; + + --decimal_start_; + assert(decimal_start_ != chunk_index); + data_[decimal_start_] = carry; + } + + // Fill the first set of digits. The first chunk might not be complete, so + // handle differently. + for (uint32_t first = data_[decimal_start_++]; first != 0; first /= 10) { + digits_[kDigitsPerChunk - ++size_] = first % 10 + '0'; + } + } + + private: + static constexpr size_t kDigitsPerChunk = 9; + + int decimal_start_; + int decimal_end_; + + char digits_[kDigitsPerChunk]; + int size_ = 0; + + absl::Span data_; +}; + +// Converts a value of the form `x * 2^-exp` into a sequence of decimal digits. +// Requires `-exp < 0` and +// `-exp >= limits::min_exponent - limits::digits`. +class FractionalDigitGenerator { + public: + // Run the conversion for `v * 2^exp` and call `f(generator)`. + // This function will allocate enough stack space to perform the conversion. + static void RunConversion( + uint128 v, int exp, absl::FunctionRef f) { + assert(-exp < 0); + assert(-exp >= std::numeric_limits::min_exponent - 128); + static_assert( + StackArray::kMaxCapacity >= + (128 - std::numeric_limits::min_exponent + 31) / 32, + ""); + StackArray::RunWithCapacity((exp + 31) / 32, + [=](absl::Span input) { + f(FractionalDigitGenerator(input, v, exp)); + }); + } + + // Returns true if there are any more non-zero digits left. + bool HasMoreDigits() const { return next_digit_ != 0 || chunk_index_ >= 0; } + + // Returns true if the remainder digits are greater than 5000... + bool IsGreaterThanHalf() const { + return next_digit_ > 5 || (next_digit_ == 5 && chunk_index_ >= 0); + } + // Returns true if the remainder digits are exactly 5000... + bool IsExactlyHalf() const { return next_digit_ == 5 && chunk_index_ < 0; } + + struct Digits { + int digit_before_nine; + int num_nines; + }; + + // Get the next set of digits. + // They are composed by a non-9 digit followed by a runs of zero or more 9s. + Digits GetDigits() { + Digits digits{next_digit_, 0}; + + next_digit_ = GetOneDigit(); + while (next_digit_ == 9) { + ++digits.num_nines; + next_digit_ = GetOneDigit(); + } + + return digits; + } + + private: + // Return the next digit. + int GetOneDigit() { + if (chunk_index_ < 0) return 0; + + uint32_t carry = 0; + for (int i = chunk_index_; i >= 0; --i) { + carry = MultiplyBy10WithCarry(&data_[i], carry); + } + // If the lowest chunk is now empty, remove it from view. + if (data_[chunk_index_] == 0) --chunk_index_; + return carry; + } + + FractionalDigitGenerator(absl::Span data, uint128 v, int exp) + : chunk_index_(exp / 32), data_(data) { + const int offset = exp % 32; + // Right shift `v` by `exp` bits. + data_[chunk_index_] = static_cast(v << (32 - offset)); + v >>= offset; + // Make sure we don't overflow the data. We already calculated that + // non-zero bits fit, so we might not have space for leading zero bits. + for (int pos = chunk_index_; v; v >>= 32) + data_[--pos] = static_cast(v); + + // Fill next_digit_, as GetDigits expects it to be populated always. + next_digit_ = GetOneDigit(); + } + + int next_digit_; + int chunk_index_; + absl::Span data_; +}; + +// Count the number of leading zero bits. +int LeadingZeros(uint64_t v) { return base_internal::CountLeadingZeros64(v); } +int LeadingZeros(uint128 v) { + auto high = static_cast(v >> 64); + auto low = static_cast(v); + return high != 0 ? base_internal::CountLeadingZeros64(high) + : 64 + base_internal::CountLeadingZeros64(low); +} + +// Round up the text digits starting at `p`. +// The buffer must have an extra digit that is known to not need rounding. +// This is done below by having an extra '0' digit on the left. +void RoundUp(char *p) { + while (*p == '9' || *p == '.') { + if (*p == '9') *p = '0'; + --p; + } + ++*p; +} + +// Check the previous digit and round up or down to follow the round-to-even +// policy. +void RoundToEven(char *p) { + if (*p == '.') --p; + if (*p % 2 == 1) RoundUp(p); +} + +// Simple integral decimal digit printing for values that fit in 64-bits. +// Returns the pointer to the last written digit. +char *PrintIntegralDigitsFromRightFast(uint64_t v, char *p) { + do { + *--p = DivideBy10WithCarry(&v, 0) + '0'; + } while (v != 0); + return p; +} + +// Simple integral decimal digit printing for values that fit in 128-bits. +// Returns the pointer to the last written digit. +char *PrintIntegralDigitsFromRightFast(uint128 v, char *p) { + auto high = static_cast(v >> 64); + auto low = static_cast(v); + + while (high != 0) { + uint64_t carry = DivideBy10WithCarry(&high, 0); + carry = DivideBy10WithCarry(&low, carry); + *--p = carry + '0'; + } + return PrintIntegralDigitsFromRightFast(low, p); +} + +// Simple fractional decimal digit printing for values that fir in 64-bits after +// shifting. +// Performs rounding if necessary to fit within `precision`. +// Returns the pointer to one after the last character written. +char *PrintFractionalDigitsFast(uint64_t v, char *start, int exp, + int precision) { + char *p = start; + v <<= (64 - exp); + while (precision > 0) { + if (!v) return p; + *p++ = MultiplyBy10WithCarry(&v, uint64_t{0}) + '0'; + --precision; + } + + // We need to round. + if (v < 0x8000000000000000) { + // We round down, so nothing to do. + } else if (v > 0x8000000000000000) { + // We round up. + RoundUp(p - 1); + } else { + RoundToEven(p - 1); + } + + assert(precision == 0); + // Precision can only be zero here. + return p; +} + +// Simple fractional decimal digit printing for values that fir in 128-bits +// after shifting. +// Performs rounding if necessary to fit within `precision`. +// Returns the pointer to one after the last character written. +char *PrintFractionalDigitsFast(uint128 v, char *start, int exp, + int precision) { + char *p = start; + v <<= (128 - exp); + auto high = static_cast(v >> 64); + auto low = static_cast(v); + + // While we have digits to print and `low` is not empty, do the long + // multiplication. + while (precision > 0 && low != 0) { + uint64_t carry = MultiplyBy10WithCarry(&low, uint64_t{0}); + carry = MultiplyBy10WithCarry(&high, carry); + + *p++ = carry + '0'; + --precision; + } + + // Now `low` is empty, so use a faster approach for the rest of the digits. + // This block is pretty much the same as the main loop for the 64-bit case + // above. + while (precision > 0) { + if (!high) return p; + *p++ = MultiplyBy10WithCarry(&high, uint64_t{0}) + '0'; + --precision; + } + + // We need to round. + if (high < 0x8000000000000000) { + // We round down, so nothing to do. + } else if (high > 0x8000000000000000 || low != 0) { + // We round up. + RoundUp(p - 1); + } else { + RoundToEven(p - 1); + } + + assert(precision == 0); + // Precision can only be zero here. + return p; +} + +struct FormatState { + char sign_char; + int precision; + const FormatConversionSpecImpl &conv; + FormatSinkImpl *sink; + + // In `alt` mode (flag #) we keep the `.` even if there are no fractional + // digits. In non-alt mode, we strip it. + bool ShouldPrintDot() const { return precision != 0 || conv.has_alt_flag(); } +}; + +struct Padding { + int left_spaces; + int zeros; + int right_spaces; +}; + +Padding ExtraWidthToPadding(int total_size, const FormatState &state) { + int missing_chars = std::max(state.conv.width() - total_size, 0); + if (state.conv.has_left_flag()) { + return {0, 0, missing_chars}; + } else if (state.conv.has_zero_flag()) { + return {0, missing_chars, 0}; + } else { + return {missing_chars, 0, 0}; + } +} + +void FinalPrint(absl::string_view data, int trailing_zeros, + const FormatState &state) { + if (state.conv.width() < 0) { + // No width specified. Fast-path. + if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); + state.sink->Append(data); + state.sink->Append(trailing_zeros, '0'); + return; + } + + auto padding = + ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + + static_cast(data.size()) + trailing_zeros, + state); + + state.sink->Append(padding.left_spaces, ' '); + if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); + state.sink->Append(padding.zeros, '0'); + state.sink->Append(data); + state.sink->Append(trailing_zeros, '0'); + state.sink->Append(padding.right_spaces, ' '); +} + +// Fastpath %f formatter for when the shifted value fits in a simple integral +// type. +// Prints `v*2^exp` with the options from `state`. +template +void FormatFFast(Int v, int exp, const FormatState &state) { + constexpr int input_bits = sizeof(Int) * 8; + + static constexpr size_t integral_size = + /* in case we need to round up an extra digit */ 1 + + /* decimal digits for uint128 */ 40 + 1; + char buffer[integral_size + /* . */ 1 + /* max digits uint128 */ 128]; + buffer[integral_size] = '.'; + char *const integral_digits_end = buffer + integral_size; + char *integral_digits_start; + char *const fractional_digits_start = buffer + integral_size + 1; + char *fractional_digits_end = fractional_digits_start; + + if (exp >= 0) { + const int total_bits = input_bits - LeadingZeros(v) + exp; + integral_digits_start = + total_bits <= 64 + ? PrintIntegralDigitsFromRightFast(static_cast(v) << exp, + integral_digits_end) + : PrintIntegralDigitsFromRightFast(static_cast(v) << exp, + integral_digits_end); + } else { + exp = -exp; + + integral_digits_start = PrintIntegralDigitsFromRightFast( + exp < input_bits ? v >> exp : 0, integral_digits_end); + // PrintFractionalDigits may pull a carried 1 all the way up through the + // integral portion. + integral_digits_start[-1] = '0'; + + fractional_digits_end = + exp <= 64 ? PrintFractionalDigitsFast(v, fractional_digits_start, exp, + state.precision) + : PrintFractionalDigitsFast(static_cast(v), + fractional_digits_start, exp, + state.precision); + // There was a carry, so include the first digit too. + if (integral_digits_start[-1] != '0') --integral_digits_start; + } + + size_t size = fractional_digits_end - integral_digits_start; + + // In `alt` mode (flag #) we keep the `.` even if there are no fractional + // digits. In non-alt mode, we strip it. + if (!state.ShouldPrintDot()) --size; + FinalPrint(absl::string_view(integral_digits_start, size), + static_cast(state.precision - (fractional_digits_end - + fractional_digits_start)), + state); +} + +// Slow %f formatter for when the shifted value does not fit in a uint128, and +// `exp > 0`. +// Prints `v*2^exp` with the options from `state`. +// This one is guaranteed to not have fractional digits, so we don't have to +// worry about anything after the `.`. +void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) { + BinaryToDecimal::RunConversion(v, exp, [&](BinaryToDecimal btd) { + const int total_digits = + btd.TotalDigits() + (state.ShouldPrintDot() ? state.precision + 1 : 0); + + const auto padding = ExtraWidthToPadding( + total_digits + (state.sign_char != '\0' ? 1 : 0), state); + + state.sink->Append(padding.left_spaces, ' '); + if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); + state.sink->Append(padding.zeros, '0'); + + do { + state.sink->Append(btd.CurrentDigits()); + } while (btd.AdvanceDigits()); + + if (state.ShouldPrintDot()) state.sink->Append(1, '.'); + state.sink->Append(state.precision, '0'); + state.sink->Append(padding.right_spaces, ' '); + }); +} + +// Slow %f formatter for when the shifted value does not fit in a uint128, and +// `exp < 0`. +// Prints `v*2^exp` with the options from `state`. +// This one is guaranteed to be < 1.0, so we don't have to worry about integral +// digits. +void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) { + const int total_digits = + /* 0 */ 1 + (state.ShouldPrintDot() ? state.precision + 1 : 0); + auto padding = + ExtraWidthToPadding(total_digits + (state.sign_char ? 1 : 0), state); + padding.zeros += 1; + state.sink->Append(padding.left_spaces, ' '); + if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); + state.sink->Append(padding.zeros, '0'); + + if (state.ShouldPrintDot()) state.sink->Append(1, '.'); + + // Print digits + int digits_to_go = state.precision; + + FractionalDigitGenerator::RunConversion( + v, exp, [&](FractionalDigitGenerator digit_gen) { + // There are no digits to print here. + if (state.precision == 0) return; + + // We go one digit at a time, while keeping track of runs of nines. + // The runs of nines are used to perform rounding when necessary. + + while (digits_to_go > 0 && digit_gen.HasMoreDigits()) { + auto digits = digit_gen.GetDigits(); + + // Now we have a digit and a run of nines. + // See if we can print them all. + if (digits.num_nines + 1 < digits_to_go) { + // We don't have to round yet, so print them. + state.sink->Append(1, digits.digit_before_nine + '0'); + state.sink->Append(digits.num_nines, '9'); + digits_to_go -= digits.num_nines + 1; + + } else { + // We can't print all the nines, see where we have to truncate. + + bool round_up = false; + if (digits.num_nines + 1 > digits_to_go) { + // We round up at a nine. No need to print them. + round_up = true; + } else { + // We can fit all the nines, but truncate just after it. + if (digit_gen.IsGreaterThanHalf()) { + round_up = true; + } else if (digit_gen.IsExactlyHalf()) { + // Round to even + round_up = + digits.num_nines != 0 || digits.digit_before_nine % 2 == 1; + } + } + + if (round_up) { + state.sink->Append(1, digits.digit_before_nine + '1'); + --digits_to_go; + // The rest will be zeros. + } else { + state.sink->Append(1, digits.digit_before_nine + '0'); + state.sink->Append(digits_to_go - 1, '9'); + digits_to_go = 0; + } + return; + } + } + }); + + state.sink->Append(digits_to_go, '0'); + state.sink->Append(padding.right_spaces, ' '); +} + +template +void FormatF(Int mantissa, int exp, const FormatState &state) { + if (exp >= 0) { + const int total_bits = sizeof(Int) * 8 - LeadingZeros(mantissa) + exp; + + // Fallback to the slow stack-based approach if we can't do it in a 64 or + // 128 bit state. + if (ABSL_PREDICT_FALSE(total_bits > 128)) { + return FormatFPositiveExpSlow(mantissa, exp, state); + } + } else { + // Fallback to the slow stack-based approach if we can't do it in a 64 or + // 128 bit state. + if (ABSL_PREDICT_FALSE(exp < -128)) { + return FormatFNegativeExpSlow(mantissa, -exp, state); + } + } + return FormatFFast(mantissa, exp, state); +} + +char *CopyStringTo(absl::string_view v, char *out) { std::memcpy(out, v.data(), v.size()); return out + v.size(); } template -bool FallbackToSnprintf(const Float v, const ConversionSpec &conv, +bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink) { int w = conv.width() >= 0 ? conv.width() : 0; int p = conv.precision() >= 0 ? conv.precision() : -1; @@ -38,12 +675,12 @@ bool FallbackToSnprintf(const Float v, const ConversionSpec &conv, assert(fp < fmt + sizeof(fmt)); } std::string space(512, '\0'); - string_view result; + absl::string_view result; while (true) { int n = snprintf(&space[0], space.size(), fmt, w, p, v); if (n < 0) return false; if (static_cast(n) < space.size()) { - result = string_view(space.data(), n); + result = absl::string_view(space.data(), n); break; } space.resize(n + 1); @@ -96,9 +733,10 @@ enum class FormatStyle { Fixed, Precision }; // Otherwise, return false. template bool ConvertNonNumericFloats(char sign_char, Float v, - const ConversionSpec &conv, FormatSinkImpl *sink) { + const FormatConversionSpecImpl &conv, + FormatSinkImpl *sink) { char text[4], *ptr = text; - if (sign_char) *ptr++ = sign_char; + if (sign_char != '\0') *ptr++ = sign_char; if (std::isnan(v)) { ptr = std::copy_n( FormatConversionCharIsUpper(conv.conversion_char()) ? "NAN" : "nan", 3, @@ -172,7 +810,12 @@ constexpr bool CanFitMantissa() { template struct Decomposed { - Float mantissa; + using MantissaType = + absl::conditional_t::value, uint128, + uint64_t>; + static_assert(std::numeric_limits::digits <= sizeof(MantissaType) * 8, + ""); + MantissaType mantissa; int exponent; }; @@ -183,7 +826,8 @@ Decomposed Decompose(Float v) { Float m = std::frexp(v, &exp); m = std::ldexp(m, std::numeric_limits::digits); exp -= std::numeric_limits::digits; - return {m, exp}; + + return {static_cast::MantissaType>(m), exp}; } // Print 'digits' as decimal. @@ -352,8 +996,9 @@ bool FloatToBuffer(Decomposed decomposed, int precision, Buffer *out, return false; } -void WriteBufferToSink(char sign_char, string_view str, - const ConversionSpec &conv, FormatSinkImpl *sink) { +void WriteBufferToSink(char sign_char, absl::string_view str, + const FormatConversionSpecImpl &conv, + FormatSinkImpl *sink) { int left_spaces = 0, zeros = 0, right_spaces = 0; int missing_chars = conv.width() >= 0 ? std::max(conv.width() - static_cast(str.size()) - @@ -369,14 +1014,14 @@ void WriteBufferToSink(char sign_char, string_view str, } sink->Append(left_spaces, ' '); - if (sign_char) sink->Append(1, sign_char); + if (sign_char != '\0') sink->Append(1, sign_char); sink->Append(zeros, '0'); sink->Append(str); sink->Append(right_spaces, ' '); } template -bool FloatToSink(const Float v, const ConversionSpec &conv, +bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink) { // Print the sign or the sign column. Float abs_v = v; @@ -407,11 +1052,9 @@ bool FloatToSink(const Float v, const ConversionSpec &conv, if (c == FormatConversionCharInternal::f || c == FormatConversionCharInternal::F) { - if (!FloatToBuffer(decomposed, precision, &buffer, - nullptr)) { - return FallbackToSnprintf(v, conv, sink); - } - if (!conv.has_alt_flag() && buffer.back() == '.') buffer.pop_back(); + FormatF(decomposed.mantissa, decomposed.exponent, + {sign_char, precision, conv, sink}); + return true; } else if (c == FormatConversionCharInternal::e || c == FormatConversionCharInternal::E) { if (!FloatToBuffer(decomposed, precision, &buffer, @@ -462,25 +1105,32 @@ bool FloatToSink(const Float v, const ConversionSpec &conv, } WriteBufferToSink(sign_char, - string_view(buffer.begin, buffer.end - buffer.begin), conv, - sink); + absl::string_view(buffer.begin, buffer.end - buffer.begin), + conv, sink); return true; } } // namespace -bool ConvertFloatImpl(long double v, const ConversionSpec &conv, +bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink) { + if (std::numeric_limits::digits == + 2 * std::numeric_limits::digits) { + // This is the `double-double` representation of `long double`. + // We do not handle it natively. Fallback to snprintf. + return FallbackToSnprintf(v, conv, sink); + } + return FloatToSink(v, conv, sink); } -bool ConvertFloatImpl(float v, const ConversionSpec &conv, +bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink) { return FloatToSink(v, conv, sink); } -bool ConvertFloatImpl(double v, const ConversionSpec &conv, +bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink) { return FloatToSink(v, conv, sink); } diff --git a/absl/strings/internal/str_format/float_conversion.h b/absl/strings/internal/str_format/float_conversion.h index 49a6a636..e78bc191 100644 --- a/absl/strings/internal/str_format/float_conversion.h +++ b/absl/strings/internal/str_format/float_conversion.h @@ -7,13 +7,13 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace str_format_internal { -bool ConvertFloatImpl(float v, const ConversionSpec &conv, +bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink); -bool ConvertFloatImpl(double v, const ConversionSpec &conv, +bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink); -bool ConvertFloatImpl(long double v, const ConversionSpec &conv, +bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink); } // namespace str_format_internal diff --git a/absl/strings/internal/str_format/parser.h b/absl/strings/internal/str_format/parser.h index fd2dc970..fffed04f 100644 --- a/absl/strings/internal/str_format/parser.h +++ b/absl/strings/internal/str_format/parser.h @@ -83,7 +83,7 @@ const char* ConsumeUnboundConversion(const char* p, const char* end, // conversions. class ConvTag { public: - constexpr ConvTag(ConversionChar conversion_char) // NOLINT + constexpr ConvTag(FormatConversionChar conversion_char) // NOLINT : tag_(static_cast(conversion_char)) {} // We invert the length modifiers to make them negative so that we can easily // test for them. @@ -94,9 +94,9 @@ class ConvTag { bool is_conv() const { return tag_ >= 0; } bool is_length() const { return tag_ < 0 && tag_ != -128; } - ConversionChar as_conv() const { + FormatConversionChar as_conv() const { assert(is_conv()); - return static_cast(tag_); + return static_cast(tag_); } LengthMod as_length() const { assert(is_length()); @@ -282,7 +282,7 @@ class ParsedFormatBase { // This is the only API that allows the user to pass a runtime specified format // string. These factory functions will return NULL if the format does not match // the conversions requested by the user. -template +template class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase { public: explicit ExtendedParsedFormat(string_view format) diff --git a/absl/strings/internal/str_format/parser_test.cc b/absl/strings/internal/str_format/parser_test.cc index 26f5bec6..dae2d20f 100644 --- a/absl/strings/internal/str_format/parser_test.cc +++ b/absl/strings/internal/str_format/parser_test.cc @@ -41,7 +41,7 @@ TEST(LengthModTest, Names) { TEST(ConversionCharTest, Names) { struct Expectation { - ConversionChar id; + FormatConversionChar id; char name; }; // clang-format off @@ -57,7 +57,7 @@ TEST(ConversionCharTest, Names) { // clang-format on for (auto e : kExpect) { SCOPED_TRACE(e.name); - ConversionChar v = e.id; + FormatConversionChar v = e.id; EXPECT_EQ(e.name, FormatConversionCharToChar(v)); } } @@ -368,7 +368,7 @@ TEST_F(ParsedFormatTest, ValueSemantics) { struct ExpectParse { const char* in; - std::initializer_list conv_set; + std::initializer_list conv_set; const char* out; }; diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc index 160f4c61..3f14dba3 100644 --- a/absl/strings/str_format_test.cc +++ b/absl/strings/str_format_test.cc @@ -532,76 +532,103 @@ TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) { EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format))); } -using str_format_internal::Conv; +using absl::str_format_internal::FormatConversionCharSet; TEST_F(ParsedFormatTest, UncheckedCorrect) { - auto f = ExtendedParsedFormat::New("ABC%dDEF"); + auto f = ExtendedParsedFormat::New("ABC%dDEF"); ASSERT_TRUE(f); EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f)); std::string format = "%sFFF%dZZZ%f"; - auto f2 = ExtendedParsedFormat::New( - format); + auto f2 = + ExtendedParsedFormat::New(format); ASSERT_TRUE(f2); EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2)); - f2 = ExtendedParsedFormat::New( - "%s %d %f"); + f2 = + ExtendedParsedFormat::New("%s %d %f"); ASSERT_TRUE(f2); EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2)); - auto star = ExtendedParsedFormat::New("%*d"); + auto star = ExtendedParsedFormat::New("%*d"); ASSERT_TRUE(star); EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star)); - auto dollar = ExtendedParsedFormat::New("%2$s %1$d"); + auto dollar = + ExtendedParsedFormat::New("%2$s %1$d"); ASSERT_TRUE(dollar); EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar)); // with reuse - dollar = ExtendedParsedFormat::New("%2$s %1$d %1$d"); + dollar = + ExtendedParsedFormat::New("%2$s %1$d %1$d"); ASSERT_TRUE(dollar); EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar)); } TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) { - EXPECT_FALSE((ExtendedParsedFormat::New("ABC"))); - EXPECT_FALSE((ExtendedParsedFormat::New("%dABC"))); - EXPECT_FALSE((ExtendedParsedFormat::New("ABC%2$s"))); - auto f = ExtendedParsedFormat::NewAllowIgnored("ABC"); + EXPECT_FALSE((ExtendedParsedFormat::New("ABC"))); + EXPECT_FALSE( + (ExtendedParsedFormat::New("%dABC"))); + EXPECT_FALSE( + (ExtendedParsedFormat::New("ABC%2$s"))); + auto f = + ExtendedParsedFormat::NewAllowIgnored("ABC"); ASSERT_TRUE(f); EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f)); - f = ExtendedParsedFormat::NewAllowIgnored("%dABC"); + f = ExtendedParsedFormat< + FormatConversionCharSet::d, + FormatConversionCharSet::s>::NewAllowIgnored("%dABC"); ASSERT_TRUE(f); EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f)); - f = ExtendedParsedFormat::NewAllowIgnored("ABC%2$s"); + f = ExtendedParsedFormat< + FormatConversionCharSet::d, + FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s"); ASSERT_TRUE(f); EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f)); } TEST_F(ParsedFormatTest, UncheckedMultipleTypes) { - auto dx = ExtendedParsedFormat::New("%1$d %1$x"); + auto dx = ExtendedParsedFormat::New("%1$d %1$x"); EXPECT_TRUE(dx); EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx)); - dx = ExtendedParsedFormat::New("%1$d"); + dx = ExtendedParsedFormat::New("%1$d"); EXPECT_TRUE(dx); EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx)); } TEST_F(ParsedFormatTest, UncheckedIncorrect) { - EXPECT_FALSE(ExtendedParsedFormat::New("")); + EXPECT_FALSE(ExtendedParsedFormat::New("")); - EXPECT_FALSE(ExtendedParsedFormat::New("ABC%dDEF%d")); + EXPECT_FALSE( + ExtendedParsedFormat::New("ABC%dDEF%d")); std::string format = "%sFFF%dZZZ%f"; - EXPECT_FALSE((ExtendedParsedFormat::New(format))); + EXPECT_FALSE((ExtendedParsedFormat::New(format))); } TEST_F(ParsedFormatTest, RegressionMixPositional) { - EXPECT_FALSE((ExtendedParsedFormat::New("%1$d %o"))); + EXPECT_FALSE( + (ExtendedParsedFormat::New("%1$d %o"))); } using FormatWrapperTest = ::testing::Test; diff --git a/absl/strings/substitute.h b/absl/strings/substitute.h index e7b4c1e6..92c47236 100644 --- a/absl/strings/substitute.h +++ b/absl/strings/substitute.h @@ -50,7 +50,7 @@ // // Supported types: // * absl::string_view, std::string, const char* (null is equivalent to "") -// * int32_t, int64_t, uint32_t, uint64 +// * int32_t, int64_t, uint32_t, uint64_t // * float, double // * bool (Printed as "true" or "false") // * pointer types other than char* (Printed as "0x", -- cgit v1.2.3 From a35ef8a62ce7cded2f131ccbd2b5c4a81d622507 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 7 May 2020 10:42:26 -0700 Subject: Export of internal Abseil changes -- 034c30a00c64d93b9fcbc9d99a0a33801544d741 by Gennadiy Rozental : Split private handle interfaces accessor into a separate target with private visibility. PiperOrigin-RevId: 310391488 -- 6f6ca869309b17900b90849e08488ce7f7b0193a by Derek Mauro : Remove __CLANG_SUPPORT_DYN_ANNOTATION__, which is a symbol defined by us to be true in all builds PiperOrigin-RevId: 310385325 -- ed5c1880c86973c000e826a3006b38e53ab3ed52 by Samuel Benzaquen : Add tests to exercise extreme width and precision, and fix the overflows from it. PiperOrigin-RevId: 310224957 GitOrigin-RevId: 034c30a00c64d93b9fcbc9d99a0a33801544d741 Change-Id: I6c89a3c89ae92fa617c696044148ce9a79bcdda8 --- absl/base/BUILD.bazel | 1 - absl/base/CMakeLists.txt | 2 - absl/base/dynamic_annotations.h | 5 +-- absl/flags/BUILD.bazel | 23 +++++++++- absl/flags/CMakeLists.txt | 23 +++++++++- absl/flags/internal/commandlineflag.cc | 27 ----------- absl/flags/internal/commandlineflag.h | 31 +------------ absl/flags/internal/commandlineflag_test.cc | 31 ++++++------- absl/flags/internal/flag.h | 1 + absl/flags/internal/private_handle_accessor.cc | 52 ++++++++++++++++++++++ absl/flags/internal/private_handle_accessor.h | 52 ++++++++++++++++++++++ absl/flags/internal/registry.cc | 7 +-- absl/flags/internal/type_erased.cc | 7 +-- absl/flags/internal/usage.cc | 1 + absl/flags/parse.cc | 5 ++- absl/strings/internal/str_format/convert_test.cc | 25 +++++++++++ .../internal/str_format/float_conversion.cc | 20 +++++---- 17 files changed, 214 insertions(+), 99 deletions(-) create mode 100644 absl/flags/internal/private_handle_accessor.cc create mode 100644 absl/flags/internal/private_handle_accessor.h (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 1664a351..816e592b 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -118,7 +118,6 @@ cc_library( srcs = ["dynamic_annotations.cc"], hdrs = ["dynamic_annotations.h"], copts = ABSL_DEFAULT_COPTS, - defines = ["__CLANG_SUPPORT_DYN_ANNOTATION__"], linkopts = ABSL_DEFAULT_LINKOPTS, ) diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 2df2e971..292998b3 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -108,8 +108,6 @@ absl_cc_library( "dynamic_annotations.cc" COPTS ${ABSL_DEFAULT_COPTS} - DEFINES - "__CLANG_SUPPORT_DYN_ANNOTATION__" PUBLIC ) diff --git a/absl/base/dynamic_annotations.h b/absl/base/dynamic_annotations.h index 65a54b44..2d985260 100644 --- a/absl/base/dynamic_annotations.h +++ b/absl/base/dynamic_annotations.h @@ -140,10 +140,7 @@ #define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) /* empty */ #endif /* DYNAMIC_ANNOTATIONS_ENABLED || MEMORY_SANITIZER */ -/* TODO(delesley) -- Replace __CLANG_SUPPORT_DYN_ANNOTATION__ with the - appropriate feature ID. */ -#if defined(__clang__) && (!defined(SWIG)) \ - && defined(__CLANG_SUPPORT_DYN_ANNOTATION__) +#if defined(__clang__) && !defined(SWIG) #if DYNAMIC_ANNOTATIONS_ENABLED == 0 #define ANNOTALYSIS_ENABLED diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index 685e3954..36810825 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -40,6 +40,7 @@ cc_library( deps = [ ":config", ":handle", + ":marshalling", ":registry", "//absl/base", "//absl/base:config", @@ -143,8 +144,6 @@ cc_library( "//absl/flags:__pkg__", ], deps = [ - ":config", - ":marshalling", "//absl/base:config", "//absl/base:core_headers", "//absl/base:fast_type_id", @@ -153,6 +152,22 @@ cc_library( ], ) +cc_library( + name = "private_handle_accessor", + srcs = [ + "internal/private_handle_accessor.cc", + ], + hdrs = [ + "internal/private_handle_accessor.h", + ], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl/flags:__pkg__", + ], + deps = [":handle"], +) + cc_library( name = "registry", srcs = [ @@ -171,6 +186,7 @@ cc_library( deps = [ ":config", ":handle", + ":private_handle_accessor", "//absl/base:config", "//absl/base:core_headers", "//absl/base:raw_logging_internal", @@ -222,6 +238,7 @@ cc_library( ":flag_internal", ":handle", ":path_util", + ":private_handle_accessor", ":program_name", ":registry", "//absl/base:config", @@ -263,6 +280,7 @@ cc_library( ":flag", ":flag_internal", ":handle", + ":private_handle_accessor", ":program_name", ":registry", ":usage", @@ -289,6 +307,7 @@ cc_test( ":config", ":flag", ":handle", + ":private_handle_accessor", ":registry", "//absl/memory", "//absl/strings", diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt index ec82ee1e..e6b17c9b 100644 --- a/absl/flags/CMakeLists.txt +++ b/absl/flags/CMakeLists.txt @@ -31,6 +31,7 @@ absl_cc_library( absl::config absl::flags_config absl::flags_handle + absl::flags_marshalling absl::flags_registry absl::synchronization absl::meta @@ -129,8 +130,6 @@ absl_cc_library( DEPS absl::config absl::fast_type_id - absl::flags_config - absl::flags_marshalling absl::core_headers absl::optional absl::raw_logging_internal @@ -138,6 +137,22 @@ absl_cc_library( absl::synchronization ) +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + flags_private_handle_accessor + SRCS + "internal/private_handle_accessor.cc" + HDRS + "internal/private_handle_accessor.h" + COPTS + ${ABSL_DEFAULT_COPTS} + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::flags_handle +) + # Internal-only target, do not depend on directly. absl_cc_library( NAME @@ -156,6 +171,7 @@ absl_cc_library( absl::config absl::flags_config absl::flags_handle + absl::flags_private_handle_accessor absl::core_headers absl::raw_logging_internal absl::strings @@ -203,6 +219,7 @@ absl_cc_library( absl::flags_config absl::flags absl::flags_handle + absl::flags_private_handle_accessor absl::flags_internal absl::flags_path_util absl::flags_program_name @@ -248,6 +265,7 @@ absl_cc_library( absl::flags_config absl::flags absl::flags_handle + absl::flags_private_handle_accessor absl::flags_internal absl::flags_program_name absl::flags_registry @@ -270,6 +288,7 @@ absl_cc_test( absl::flags absl::flags_config absl::flags_handle + absl::flags_private_handle_accessor absl::flags_registry absl::memory absl::strings diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc index c919fa1b..84112437 100644 --- a/absl/flags/internal/commandlineflag.cc +++ b/absl/flags/internal/commandlineflag.cc @@ -28,33 +28,6 @@ bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) { flags_internal::kProgrammaticChange, error); } -FlagFastTypeId PrivateHandleInterface::TypeId(const CommandLineFlag& flag) { - return flag.TypeId(); -} - -std::unique_ptr PrivateHandleInterface::SaveState( - CommandLineFlag* flag) { - return flag->SaveState(); -} - -bool PrivateHandleInterface::ValidateInputValue(const CommandLineFlag& flag, - absl::string_view value) { - return flag.ValidateInputValue(value); -} - -void PrivateHandleInterface::CheckDefaultValueParsingRoundtrip( - const CommandLineFlag& flag) { - flag.CheckDefaultValueParsingRoundtrip(); -} - -bool PrivateHandleInterface::ParseFrom(CommandLineFlag* flag, - absl::string_view value, - flags_internal::FlagSettingMode set_mode, - flags_internal::ValueSource source, - std::string* error) { - return flag->ParseFrom(value, set_mode, source, error); -} - } // namespace flags_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/commandlineflag.h b/absl/flags/internal/commandlineflag.h index af5e05d5..2d3b794d 100644 --- a/absl/flags/internal/commandlineflag.h +++ b/absl/flags/internal/commandlineflag.h @@ -16,18 +16,12 @@ #ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ #define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_ -#include -#include - #include #include -#include #include "absl/base/config.h" #include "absl/base/internal/fast_type_id.h" #include "absl/base/macros.h" -#include "absl/flags/config.h" -#include "absl/flags/marshalling.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" @@ -147,7 +141,7 @@ class CommandLineFlag { ~CommandLineFlag() = default; private: - friend class PrivateHandleInterface; + friend class PrivateHandleAccessor; // Sets the value of the flag based on specified string `value`. If the flag // was successfully set to new value, it returns true. Otherwise, sets `error` @@ -181,29 +175,6 @@ class CommandLineFlag { virtual void CheckDefaultValueParsingRoundtrip() const = 0; }; -// This class serves as a trampoline to access private methods of -// CommandLineFlag. This class is intended for use exclusively internally inside -// of the Abseil Flags implementation -class PrivateHandleInterface { - public: - // Access to CommandLineFlag::TypeId. - static FlagFastTypeId TypeId(const CommandLineFlag& flag); - - // Access to CommandLineFlag::SaveState. - static std::unique_ptr SaveState(CommandLineFlag* flag); - - // Access to CommandLineFlag::ValidateInputValue. - static bool ValidateInputValue(const CommandLineFlag& flag, - absl::string_view value); - - // Access to CommandLineFlag::CheckDefaultValueParsingRoundtrip. - static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag); - - static bool ParseFrom(CommandLineFlag* flag, absl::string_view value, - flags_internal::FlagSettingMode set_mode, - flags_internal::ValueSource source, std::string* error); -}; - // This macro is the "source of truth" for the list of supported flag built-in // types. #define ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \ diff --git a/absl/flags/internal/commandlineflag_test.cc b/absl/flags/internal/commandlineflag_test.cc index 4aeb3bf4..54d50fff 100644 --- a/absl/flags/internal/commandlineflag_test.cc +++ b/absl/flags/internal/commandlineflag_test.cc @@ -20,6 +20,7 @@ #include "gtest/gtest.h" #include "absl/flags/flag.h" +#include "absl/flags/internal/private_handle_accessor.h" #include "absl/flags/internal/registry.h" #include "absl/flags/usage_config.h" #include "absl/memory/memory.h" @@ -122,52 +123,52 @@ TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) { auto* flag_01 = flags::FindCommandLineFlag("int_flag"); EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine()); - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_01, "11", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11); EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine()); - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_01, "-123", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123); EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine()); - EXPECT_TRUE(!flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom( flag_01, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123); EXPECT_EQ(err, "Illegal value 'xyz' specified for flag 'int_flag'"); EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine()); - EXPECT_TRUE(!flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom( flag_01, "A1", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123); EXPECT_EQ(err, "Illegal value 'A1' specified for flag 'int_flag'"); EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine()); - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_01, "0x10", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16); EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine()); - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_01, "011", flags::SET_FLAGS_VALUE, flags::kCommandLine, &err)); EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11); EXPECT_TRUE(flag_01->IsSpecifiedOnCommandLine()); - EXPECT_TRUE(!flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom( flag_01, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'"); auto* flag_02 = flags::FindCommandLineFlag("string_flag"); - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_02, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz"); - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_02, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), ""); } @@ -179,14 +180,14 @@ TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) { auto* flag_01 = flags::FindCommandLineFlag("int_flag"); - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange, &err)); EXPECT_EQ(flag_01->DefaultValue(), "111"); auto* flag_02 = flags::FindCommandLineFlag("string_flag"); - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange, &err)); EXPECT_EQ(flag_02->DefaultValue(), "abc"); @@ -199,24 +200,24 @@ TEST_F(CommandLineFlagTest, TestParseFromIfDefault) { auto* flag_01 = flags::FindCommandLineFlag("int_flag"); - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_01, "22", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange, &err)) << err; EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22); - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange, &err)); EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22); // EXPECT_EQ(err, "ERROR: int_flag is already set to 22"); // Reset back to default value - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_01, "201", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, &err)); - EXPECT_TRUE(flags::PrivateHandleInterface::ParseFrom( + EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom( flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange, &err)); EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201); diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index b2208824..f53f484f 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -31,6 +31,7 @@ #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" #include "absl/meta/type_traits.h" #include "absl/strings/str_cat.h" diff --git a/absl/flags/internal/private_handle_accessor.cc b/absl/flags/internal/private_handle_accessor.cc new file mode 100644 index 00000000..ec5776bb --- /dev/null +++ b/absl/flags/internal/private_handle_accessor.cc @@ -0,0 +1,52 @@ +// +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/flags/internal/private_handle_accessor.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace flags_internal { + +FlagFastTypeId PrivateHandleAccessor::TypeId(const CommandLineFlag& flag) { + return flag.TypeId(); +} + +std::unique_ptr PrivateHandleAccessor::SaveState( + CommandLineFlag* flag) { + return flag->SaveState(); +} + +bool PrivateHandleAccessor::ValidateInputValue(const CommandLineFlag& flag, + absl::string_view value) { + return flag.ValidateInputValue(value); +} + +void PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip( + const CommandLineFlag& flag) { + flag.CheckDefaultValueParsingRoundtrip(); +} + +bool PrivateHandleAccessor::ParseFrom(CommandLineFlag* flag, + absl::string_view value, + flags_internal::FlagSettingMode set_mode, + flags_internal::ValueSource source, + std::string* error) { + return flag->ParseFrom(value, set_mode, source, error); +} + +} // namespace flags_internal +ABSL_NAMESPACE_END +} // namespace absl + diff --git a/absl/flags/internal/private_handle_accessor.h b/absl/flags/internal/private_handle_accessor.h new file mode 100644 index 00000000..fbb4409c --- /dev/null +++ b/absl/flags/internal/private_handle_accessor.h @@ -0,0 +1,52 @@ +// +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_ +#define ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_ + +#include "absl/flags/internal/commandlineflag.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace flags_internal { + +// This class serves as a trampoline to access private methods of +// CommandLineFlag. This class is intended for use exclusively internally inside +// of the Abseil Flags implementation. +class PrivateHandleAccessor { + public: + // Access to CommandLineFlag::TypeId. + static FlagFastTypeId TypeId(const CommandLineFlag& flag); + + // Access to CommandLineFlag::SaveState. + static std::unique_ptr SaveState(CommandLineFlag* flag); + + // Access to CommandLineFlag::ValidateInputValue. + static bool ValidateInputValue(const CommandLineFlag& flag, + absl::string_view value); + + // Access to CommandLineFlag::CheckDefaultValueParsingRoundtrip. + static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag); + + static bool ParseFrom(CommandLineFlag* flag, absl::string_view value, + flags_internal::FlagSettingMode set_mode, + flags_internal::ValueSource source, std::string* error); +}; + +} // namespace flags_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_ diff --git a/absl/flags/internal/registry.cc b/absl/flags/internal/registry.cc index 62b5b40d..3b941f04 100644 --- a/absl/flags/internal/registry.cc +++ b/absl/flags/internal/registry.cc @@ -29,6 +29,7 @@ #include "absl/base/internal/raw_logging.h" #include "absl/base/thread_annotations.h" #include "absl/flags/internal/commandlineflag.h" +#include "absl/flags/internal/private_handle_accessor.h" #include "absl/flags/usage_config.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" @@ -127,8 +128,8 @@ void FlagRegistry::RegisterFlag(CommandLineFlag* flag) { (flag->IsRetired() ? old_flag->Filename() : flag->Filename()), "'."), true); - } else if (flags_internal::PrivateHandleInterface::TypeId(*flag) != - flags_internal::PrivateHandleInterface::TypeId(*old_flag)) { + } else if (flags_internal::PrivateHandleAccessor::TypeId(*flag) != + flags_internal::PrivateHandleAccessor::TypeId(*old_flag)) { flags_internal::ReportUsageError( absl::StrCat("Flag '", flag->Name(), "' was defined more than once but with " @@ -206,7 +207,7 @@ class FlagSaverImpl { assert(backup_registry_.empty()); // call only once! flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) { if (auto flag_state = - flags_internal::PrivateHandleInterface::SaveState(flag)) { + flags_internal::PrivateHandleAccessor::SaveState(flag)) { backup_registry_.emplace_back(std::move(flag_state)); } }); diff --git a/absl/flags/internal/type_erased.cc b/absl/flags/internal/type_erased.cc index adeb7a15..3cfc9b2d 100644 --- a/absl/flags/internal/type_erased.cc +++ b/absl/flags/internal/type_erased.cc @@ -22,6 +22,7 @@ #include "absl/base/config.h" #include "absl/base/internal/raw_logging.h" #include "absl/flags/internal/commandlineflag.h" +#include "absl/flags/internal/private_handle_accessor.h" #include "absl/flags/internal/registry.h" #include "absl/flags/usage_config.h" #include "absl/strings/string_view.h" @@ -56,7 +57,7 @@ bool SetCommandLineOptionWithMode(absl::string_view name, if (!flag || flag->IsRetired()) return false; std::string error; - if (!flags_internal::PrivateHandleInterface::ParseFrom( + if (!flags_internal::PrivateHandleAccessor::ParseFrom( flag, value, set_mode, kProgrammaticChange, &error)) { // Errors here are all of the form: the provided name was a recognized // flag, but the value was invalid (bad type, or validation failed). @@ -74,8 +75,8 @@ bool IsValidFlagValue(absl::string_view name, absl::string_view value) { return flag != nullptr && (flag->IsRetired() || - flags_internal::PrivateHandleInterface::ValidateInputValue(*flag, - value)); + flags_internal::PrivateHandleAccessor::ValidateInputValue(*flag, + value)); } // -------------------------------------------------------------------- diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc index 9d856c87..10accc46 100644 --- a/absl/flags/internal/usage.cc +++ b/absl/flags/internal/usage.cc @@ -27,6 +27,7 @@ #include "absl/flags/internal/commandlineflag.h" #include "absl/flags/internal/flag.h" #include "absl/flags/internal/path_util.h" +#include "absl/flags/internal/private_handle_accessor.h" #include "absl/flags/internal/program_name.h" #include "absl/flags/internal/registry.h" #include "absl/flags/usage_config.h" diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc index cc134909..66a28a93 100644 --- a/absl/flags/parse.cc +++ b/absl/flags/parse.cc @@ -39,6 +39,7 @@ #include "absl/flags/internal/commandlineflag.h" #include "absl/flags/internal/flag.h" #include "absl/flags/internal/parse.h" +#include "absl/flags/internal/private_handle_accessor.h" #include "absl/flags/internal/program_name.h" #include "absl/flags/internal/registry.h" #include "absl/flags/internal/usage.h" @@ -298,7 +299,7 @@ void CheckDefaultValuesParsingRoundtrip() { ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(IGNORE_TYPE) #undef IGNORE_TYPE - flags_internal::PrivateHandleInterface::CheckDefaultValueParsingRoundtrip( + flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip( *flag); }); #endif @@ -697,7 +698,7 @@ std::vector ParseCommandLineImpl(int argc, char* argv[], if (flag->IsRetired()) continue; std::string error; - if (!flags_internal::PrivateHandleInterface::ParseFrom( + if (!flags_internal::PrivateHandleAccessor::ParseFrom( flag, value, SET_FLAGS_VALUE, kCommandLine, &error)) { flags_internal::ReportUsageError(error, true); success = false; diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index dd167f76..20c6229f 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -704,6 +704,31 @@ TEST_F(FormatConvertTest, FloatRound) { "1837869002408041296803276054561138153076171875"); } +// We don't actually store the results. This is just to exercise the rest of the +// machinery. +struct NullSink { + friend void AbslFormatFlush(NullSink *sink, string_view str) {} +}; + +template +bool FormatWithNullSink(absl::string_view fmt, const T &... a) { + NullSink sink; + FormatArgImpl args[] = {FormatArgImpl(a)...}; + return FormatUntyped(&sink, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); +} + +TEST_F(FormatConvertTest, ExtremeWidthPrecision) { + for (const char *fmt : {"f"}) { + for (double d : {1e-100, 1.0, 1e100}) { + constexpr int max = std::numeric_limits::max(); + EXPECT_TRUE(FormatWithNullSink(std::string("%.*") + fmt, max, d)); + EXPECT_TRUE(FormatWithNullSink(std::string("%1.*") + fmt, max, d)); + EXPECT_TRUE(FormatWithNullSink(std::string("%*") + fmt, max, d)); + EXPECT_TRUE(FormatWithNullSink(std::string("%*.*") + fmt, max, max, d)); + } + } +} + TEST_F(FormatConvertTest, LongDouble) { #ifdef _MSC_VER // MSVC has a different rounding policy than us so we can't test our diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index cdccc86f..a761a5a5 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -440,8 +440,10 @@ struct Padding { int right_spaces; }; -Padding ExtraWidthToPadding(int total_size, const FormatState &state) { - int missing_chars = std::max(state.conv.width() - total_size, 0); +Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) { + if (state.conv.width() < 0 || state.conv.width() <= total_size) + return {0, 0, 0}; + int missing_chars = state.conv.width() - total_size; if (state.conv.has_left_flag()) { return {0, 0, missing_chars}; } else if (state.conv.has_zero_flag()) { @@ -462,8 +464,8 @@ void FinalPrint(absl::string_view data, int trailing_zeros, } auto padding = - ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + - static_cast(data.size()) + trailing_zeros, + ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + data.size() + + static_cast(trailing_zeros), state); state.sink->Append(padding.left_spaces, ' '); @@ -536,8 +538,9 @@ void FormatFFast(Int v, int exp, const FormatState &state) { // worry about anything after the `.`. void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) { BinaryToDecimal::RunConversion(v, exp, [&](BinaryToDecimal btd) { - const int total_digits = - btd.TotalDigits() + (state.ShouldPrintDot() ? state.precision + 1 : 0); + const size_t total_digits = + btd.TotalDigits() + + (state.ShouldPrintDot() ? static_cast(state.precision) + 1 : 0); const auto padding = ExtraWidthToPadding( total_digits + (state.sign_char != '\0' ? 1 : 0), state); @@ -562,8 +565,9 @@ void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) { // This one is guaranteed to be < 1.0, so we don't have to worry about integral // digits. void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) { - const int total_digits = - /* 0 */ 1 + (state.ShouldPrintDot() ? state.precision + 1 : 0); + const size_t total_digits = + /* 0 */ 1 + + (state.ShouldPrintDot() ? static_cast(state.precision) + 1 : 0); auto padding = ExtraWidthToPadding(total_digits + (state.sign_char ? 1 : 0), state); padding.zeros += 1; -- cgit v1.2.3 From a8b03d90e0afe03fefa16d4a871ece344a5d52ad Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 4 Jun 2020 14:05:55 -0700 Subject: Export of internal Abseil changes -- 5b9d5ce21074c0541432555d383d1b9c5898b553 by Gennadiy Rozental : Convert FlagSaver into public API PiperOrigin-RevId: 314799739 -- 5f796c9862b1177f161f4b10fe1a84698ebbb5cf by Abseil Team : Google-internal changes only. PiperOrigin-RevId: 314786474 -- 67f2ae0ac5ae73bcd9d57a058ac4fea8fc1243ba by Gennadiy Rozental : Makes sure stacktrace_generic is only used with glibc. Fixes #701 PiperOrigin-RevId: 314726944 -- efb1ef3636b0698b79d3ee3590f12c4dff32a3cb by Samuel Benzaquen : Take the bits into account when reserving the space for the operation, not just the exponent. PiperOrigin-RevId: 314622744 GitOrigin-RevId: 5b9d5ce21074c0541432555d383d1b9c5898b553 Change-Id: I080a5e333e2dc1545b5aa0417882f7ac7116a20c --- absl/base/internal/low_level_scheduling.h | 5 +++ absl/debugging/internal/stacktrace_config.h | 2 +- absl/flags/commandlineflag_test.cc | 4 +-- absl/flags/flag_test.cc | 2 +- absl/flags/internal/registry.h | 25 -------------- absl/flags/internal/usage_test.cc | 2 +- absl/flags/parse_test.cc | 2 +- absl/flags/reflection.cc | 21 +++--------- absl/flags/reflection.h | 38 ++++++++++++++++++++++ absl/flags/reflection_test.cc | 4 +-- absl/strings/internal/str_format/convert_test.cc | 6 ++++ .../internal/str_format/float_conversion.cc | 12 +++---- absl/synchronization/mutex.cc | 7 ++++ 13 files changed, 75 insertions(+), 55 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 961cc981..7c52d48c 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -29,6 +29,9 @@ extern "C" void __google_enable_rescheduling(bool disable_result); namespace absl { ABSL_NAMESPACE_BEGIN +class CondVar; +class Mutex; + namespace base_internal { class SchedulingHelper; // To allow use of SchedulingGuard. @@ -77,6 +80,8 @@ class SchedulingGuard { }; // Access to SchedulingGuard is explicitly white-listed. + friend class absl::CondVar; + friend class absl::Mutex; friend class SchedulingHelper; friend class SpinLock; diff --git a/absl/debugging/internal/stacktrace_config.h b/absl/debugging/internal/stacktrace_config.h index 8caa97c0..d5cc1740 100644 --- a/absl/debugging/internal/stacktrace_config.h +++ b/absl/debugging/internal/stacktrace_config.h @@ -61,7 +61,7 @@ # elif defined(__aarch64__) #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_aarch64-inl.inc" -# elif defined(__arm__) +#elif defined(__arm__) && defined(__GLIBC__) // Note: When using glibc this may require -funwind-tables to function properly. #define ABSL_STACKTRACE_INL_HEADER \ "absl/debugging/internal/stacktrace_generic-inl.inc" diff --git a/absl/flags/commandlineflag_test.cc b/absl/flags/commandlineflag_test.cc index cc8eae91..c5afff61 100644 --- a/absl/flags/commandlineflag_test.cc +++ b/absl/flags/commandlineflag_test.cc @@ -47,7 +47,7 @@ class CommandLineFlagTest : public testing::Test { absl::SetFlagsUsageConfig(default_config); } - void SetUp() override { flag_saver_ = absl::make_unique(); } + void SetUp() override { flag_saver_ = absl::make_unique(); } void TearDown() override { flag_saver_.reset(); } private: @@ -60,7 +60,7 @@ class CommandLineFlagTest : public testing::Test { return std::string(fname); } - std::unique_ptr flag_saver_; + std::unique_ptr flag_saver_; }; TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) { diff --git a/absl/flags/flag_test.cc b/absl/flags/flag_test.cc index 0c88e24a..2eb2ba71 100644 --- a/absl/flags/flag_test.cc +++ b/absl/flags/flag_test.cc @@ -81,7 +81,7 @@ class FlagTest : public testing::Test { #endif return std::string(fname); } - flags::FlagSaver flag_saver_; + absl::FlagSaver flag_saver_; }; struct S1 { diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h index 1e655a3e..c72eebe2 100644 --- a/absl/flags/internal/registry.h +++ b/absl/flags/internal/registry.h @@ -89,31 +89,6 @@ inline bool RetiredFlag(const char* flag_name) { return flags_internal::Retire(flag_name, base_internal::FastTypeId()); } -//----------------------------------------------------------------------------- -// Saves the states (value, default value, whether the user has set -// the flag, registered validators, etc) of all flags, and restores -// them when the FlagSaver is destroyed. -// -// This class is thread-safe. However, its destructor writes to -// exactly the set of flags that have changed value during its -// lifetime, so concurrent _direct_ access to those flags -// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe. - -class FlagSaver { - public: - FlagSaver(); - ~FlagSaver(); - - FlagSaver(const FlagSaver&) = delete; - void operator=(const FlagSaver&) = delete; - - // Prevents saver from restoring the saved state of flags. - void Ignore(); - - private: - class FlagSaverImpl* impl_; // we use pimpl here to keep API steady -}; - } // namespace flags_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/flags/internal/usage_test.cc b/absl/flags/internal/usage_test.cc index 46f85b55..6e583fbe 100644 --- a/absl/flags/internal/usage_test.cc +++ b/absl/flags/internal/usage_test.cc @@ -89,7 +89,7 @@ class UsageReportingTest : public testing::Test { } private: - flags::FlagSaver flag_saver_; + absl::FlagSaver flag_saver_; }; // -------------------------------------------------------------------- diff --git a/absl/flags/parse_test.cc b/absl/flags/parse_test.cc index 1ab87690..67ae8aad 100644 --- a/absl/flags/parse_test.cc +++ b/absl/flags/parse_test.cc @@ -208,7 +208,7 @@ using testing::ElementsAreArray; class ParseTest : public testing::Test { private: - flags::FlagSaver flag_saver_; + absl::FlagSaver flag_saver_; }; // -------------------------------------------------------------------- diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc index 02bb6c2e..5fc945f2 100644 --- a/absl/flags/reflection.cc +++ b/absl/flags/reflection.cc @@ -65,7 +65,8 @@ class FlagRegistry { static FlagRegistry& GlobalRegistry(); // returns a singleton registry private: - friend class FlagSaverImpl; // reads all the flags in order to copy them + friend class flags_internal::FlagSaverImpl; // reads all the flags in order + // to copy them friend void ForEachFlagUnlocked( std::function visitor); @@ -249,15 +250,6 @@ bool Retire(const char* name, FlagFastTypeId type_id) { // -------------------------------------------------------------------- -// FlagSaver -// FlagSaverImpl -// This class stores the states of all flags at construct time, -// and restores all flags to that state at destruct time. -// Its major implementation challenge is that it never modifies -// pointers in the 'main' registry, so global FLAG_* vars always -// point to the right place. -// -------------------------------------------------------------------- - class FlagSaverImpl { public: FlagSaverImpl() = default; @@ -288,11 +280,10 @@ class FlagSaverImpl { backup_registry_; }; -FlagSaver::FlagSaver() : impl_(new FlagSaverImpl) { impl_->SaveFromRegistry(); } +} // namespace flags_internal -void FlagSaver::Ignore() { - delete impl_; - impl_ = nullptr; +FlagSaver::FlagSaver() : impl_(new flags_internal::FlagSaverImpl) { + impl_->SaveFromRegistry(); } FlagSaver::~FlagSaver() { @@ -304,8 +295,6 @@ FlagSaver::~FlagSaver() { // -------------------------------------------------------------------- -} // namespace flags_internal - CommandLineFlag* FindCommandLineFlag(absl::string_view name) { if (name.empty()) return nullptr; flags_internal::FlagRegistry& registry = diff --git a/absl/flags/reflection.h b/absl/flags/reflection.h index e8e24f68..045f9784 100644 --- a/absl/flags/reflection.h +++ b/absl/flags/reflection.h @@ -31,6 +31,9 @@ namespace absl { ABSL_NAMESPACE_BEGIN +namespace flags_internal { +class FlagSaverImpl; +} // namespace flags_internal // FindCommandLineFlag() // @@ -39,6 +42,41 @@ ABSL_NAMESPACE_BEGIN // 'retired' flag is specified. CommandLineFlag* FindCommandLineFlag(absl::string_view name); +//------------------------------------------------------------------------------ +// FlagSaver +//------------------------------------------------------------------------------ +// +// A FlagSaver object stores the state of flags in the scope where the FlagSaver +// is defined, allowing modification of those flags within that scope and +// automatic restoration of the flags to their previous state upon leaving the +// scope. +// +// A FlagSaver can be used within tests to temporarily change the test +// environment and restore the test case to its previous state. +// +// Example: +// +// void MyFunc() { +// absl::FlagSaver fs; +// ... +// absl::SetFlag(FLAGS_myFlag, otherValue); +// ... +// } // scope of FlagSaver left, flags return to previous state +// +// This class is thread-safe. + +class FlagSaver { + public: + FlagSaver(); + ~FlagSaver(); + + FlagSaver(const FlagSaver&) = delete; + void operator=(const FlagSaver&) = delete; + + private: + flags_internal::FlagSaverImpl* impl_; +}; + //----------------------------------------------------------------------------- ABSL_NAMESPACE_END diff --git a/absl/flags/reflection_test.cc b/absl/flags/reflection_test.cc index 2a137bf7..9781e597 100644 --- a/absl/flags/reflection_test.cc +++ b/absl/flags/reflection_test.cc @@ -34,11 +34,11 @@ namespace flags = absl::flags_internal; class ReflectionTest : public testing::Test { protected: - void SetUp() override { flag_saver_ = absl::make_unique(); } + void SetUp() override { flag_saver_ = absl::make_unique(); } void TearDown() override { flag_saver_.reset(); } private: - std::unique_ptr flag_saver_; + std::unique_ptr flag_saver_; }; // -------------------------------------------------------------------- diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 20c6229f..0e8535c2 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -764,6 +764,12 @@ TEST_F(FormatConvertTest, LongDouble) { } } + // Regression tests + // + // Using a string literal because not all platforms support hex literals or it + // might be out of range. + doubles.push_back(std::strtold("-0xf.ffffffb5feafffbp-16324L", nullptr)); + for (const char *fmt : kFormats) { for (char f : {'f', 'F', // 'g', 'G', // diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index a761a5a5..10e46954 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -224,13 +224,13 @@ class FractionalDigitGenerator { // This function will allocate enough stack space to perform the conversion. static void RunConversion( uint128 v, int exp, absl::FunctionRef f) { + using Limits = std::numeric_limits; assert(-exp < 0); - assert(-exp >= std::numeric_limits::min_exponent - 128); - static_assert( - StackArray::kMaxCapacity >= - (128 - std::numeric_limits::min_exponent + 31) / 32, - ""); - StackArray::RunWithCapacity((exp + 31) / 32, + assert(-exp >= Limits::min_exponent - 128); + static_assert(StackArray::kMaxCapacity >= + (Limits::digits + 128 - Limits::min_exponent + 31) / 32, + ""); + StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32, [=](absl::Span input) { f(FractionalDigitGenerator(input, v, exp)); }); diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index 1f8a696e..36c93d5f 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -58,6 +58,7 @@ using absl::base_internal::CurrentThreadIdentityIfPresent; using absl::base_internal::PerThreadSynch; +using absl::base_internal::SchedulingGuard; using absl::base_internal::ThreadIdentity; using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity; using absl::synchronization_internal::GraphCycles; @@ -1108,6 +1109,7 @@ void Mutex::TryRemove(PerThreadSynch *s) { // on the mutex queue. In this case, remove "s" from the queue and return // true, otherwise return false. ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) { if (!DecrementSynchSem(this, s, s->waitp->timeout)) { // After a timeout, we go into a spin loop until we remove ourselves @@ -1897,6 +1899,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) { } void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; intptr_t v = mu_.load(std::memory_order_relaxed); if ((v & kMuEvent) != 0) { @@ -2016,6 +2019,7 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { // or it is in the process of blocking on a condition variable; it must requeue // itself on the mutex/condvar to wait for its condition to become true. ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); this->AssertReaderHeld(); CheckForMutexCorruption(v, "Unlock"); @@ -2331,6 +2335,7 @@ void Mutex::Trans(MuHow how) { // It will later acquire the mutex with high probability. Otherwise, we // enqueue thread w on this mutex. void Mutex::Fer(PerThreadSynch *w) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; ABSL_RAW_CHECK(w->waitp->cond == nullptr, "Mutex::Fer while waiting on Condition"); @@ -2429,6 +2434,7 @@ CondVar::~CondVar() { // Remove thread s from the list of waiters on this condition variable. void CondVar::Remove(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v; int c = 0; for (v = cv_.load(std::memory_order_relaxed);; @@ -2589,6 +2595,7 @@ void CondVar::Wakeup(PerThreadSynch *w) { } void CondVar::Signal() { + SchedulingGuard::ScopedDisable disable_rescheduling; ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); intptr_t v; int c = 0; -- cgit v1.2.3 From b86fff162e15ad8ee534c25e58bf522330e8376d Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 24 Jun 2020 12:46:11 -0700 Subject: Export of internal Abseil changes -- 517dc7eba9878290fc93c6523dc6d6e2c49b8c1e by Abseil Team : Handle 'nan' in HumanReadableInt::ToInt64. PiperOrigin-RevId: 318121226 -- 4fa6103b46dbc1375d416810dba591ab4f4898d1 by Abseil Team : Promote `float`s to `double`s before formatting. This will bring StrFormat behavior more in line with that of sprintf. PiperOrigin-RevId: 318091841 -- e4083a4b64b077d8520ccd8e0ca90da24f4ea24d by Abseil Team : Google-internal changes only. PiperOrigin-RevId: 318069900 -- ab24f60127db089bccaf5fb7d2d1967c76f34768 by Greg Falcon : Inclusive language fix: Stop using blacklist/whitelist terminology in Abseil. PiperOrigin-RevId: 317925379 -- 52b56a27a773ea7c10ea8fd456ed606b9d778947 by Abseil Team : Add test for floats and label tests for double properly. PiperOrigin-RevId: 317916380 -- 0f405960ab5b34d673244fda8bb9141c8f5c1a4f by Abseil Team : Remove the static initialization of global variables used by absl::Mutex as requested by Chromium PiperOrigin-RevId: 317911430 -- ce8cb49d8f4f68950fd111682657ba57d5a09ca0 by Abseil Team : Internal Change PiperOrigin-RevId: 317864956 -- a781948e09fb8406d21a494b2fa4f78edaf9c2ea by Abseil Team : Swap ABSL_DLL / ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES order to fix clang-cl builds. PiperOrigin-RevId: 317858053 -- 4ba197f0dd2cbf8f9b96cebffd878c8847d6ce8d by Gennadiy Rozental : Migrate use of annotation macros to ABSL namespaced names PiperOrigin-RevId: 317792057 GitOrigin-RevId: 517dc7eba9878290fc93c6523dc6d6e2c49b8c1e Change-Id: I1a0c04d01adbdc5106b68fd69c97c31f822e11dc --- absl/base/internal/low_level_alloc.cc | 2 +- absl/base/internal/low_level_scheduling.h | 7 +- absl/base/internal/raw_logging.cc | 4 +- absl/base/internal/raw_logging.h | 2 +- absl/base/internal/unscaledcycleclock.h | 6 +- absl/container/fixed_array.h | 16 ++- absl/debugging/symbolize_elf.inc | 4 +- absl/strings/internal/str_format/convert_test.cc | 158 ++++++++++++++------- .../internal/str_format/float_conversion.cc | 2 +- absl/strings/numbers_test.cc | 6 + absl/synchronization/internal/per_thread_sem.h | 2 +- absl/synchronization/mutex.cc | 68 +++++---- absl/types/BUILD.bazel | 1 - 13 files changed, 182 insertions(+), 96 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/base/internal/low_level_alloc.cc b/absl/base/internal/low_level_alloc.cc index 1bf94438..229ab916 100644 --- a/absl/base/internal/low_level_alloc.cc +++ b/absl/base/internal/low_level_alloc.cc @@ -598,7 +598,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) { section.Leave(); result = &s->levels; } - ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request); + ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request); return result; } diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 961cc981..31261298 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -29,6 +29,9 @@ extern "C" void __google_enable_rescheduling(bool disable_result); namespace absl { ABSL_NAMESPACE_BEGIN +class CondVar; +class Mutex; + namespace base_internal { class SchedulingHelper; // To allow use of SchedulingGuard. @@ -76,7 +79,9 @@ class SchedulingGuard { bool disabled; }; - // Access to SchedulingGuard is explicitly white-listed. + // Access to SchedulingGuard is explicitly permitted. + friend class absl::CondVar; + friend class absl::Mutex; friend class SchedulingHelper; friend class SpinLock; diff --git a/absl/base/internal/raw_logging.cc b/absl/base/internal/raw_logging.cc index 40cea550..ae8754c6 100644 --- a/absl/base/internal/raw_logging.cc +++ b/absl/base/internal/raw_logging.cc @@ -69,7 +69,7 @@ // TODO(gfalcon): We want raw-logging to work on as many platforms as possible. // Explicitly #error out when not ABSL_LOW_LEVEL_WRITE_SUPPORTED, except for a -// whitelisted set of platforms for which we expect not to be able to raw log. +// selected set of platforms for which we expect not to be able to raw log. ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook< absl::raw_logging_internal::LogPrefixHook> @@ -227,7 +227,7 @@ bool RawLoggingFullySupported() { #endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED } -ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES +ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL absl::base_internal::AtomicHook internal_log_function(DefaultInternalLog); diff --git a/absl/base/internal/raw_logging.h b/absl/base/internal/raw_logging.h index 418d6c85..51551baf 100644 --- a/absl/base/internal/raw_logging.h +++ b/absl/base/internal/raw_logging.h @@ -170,7 +170,7 @@ using InternalLogFunction = void (*)(absl::LogSeverity severity, const char* file, int line, const std::string& message); -ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES extern base_internal::AtomicHook< +ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL extern base_internal::AtomicHook< InternalLogFunction> internal_log_function; diff --git a/absl/base/internal/unscaledcycleclock.h b/absl/base/internal/unscaledcycleclock.h index cdce9bf8..82f2c87a 100644 --- a/absl/base/internal/unscaledcycleclock.h +++ b/absl/base/internal/unscaledcycleclock.h @@ -15,8 +15,8 @@ // UnscaledCycleClock // An UnscaledCycleClock yields the value and frequency of a cycle counter // that increments at a rate that is approximately constant. -// This class is for internal / whitelisted use only, you should consider -// using CycleClock instead. +// This class is for internal use only, you should consider using CycleClock +// instead. // // Notes: // The cycle counter frequency is not necessarily the core clock frequency. @@ -109,7 +109,7 @@ class UnscaledCycleClock { // value. static double Frequency(); - // Whitelisted friends. + // Allowed users friend class base_internal::CycleClock; friend class time_internal::UnscaledCycleClockWrapperForGetCurrentTime; friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency; diff --git a/absl/container/fixed_array.h b/absl/container/fixed_array.h index adf0dc80..e74802a4 100644 --- a/absl/container/fixed_array.h +++ b/absl/container/fixed_array.h @@ -428,9 +428,9 @@ class FixedArray { #endif // ADDRESS_SANITIZER private: - ADDRESS_SANITIZER_REDZONE(redzone_begin_); + ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_); alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])]; - ADDRESS_SANITIZER_REDZONE(redzone_end_); + ABSL_ADDRESS_SANITIZER_REDZONE(redzone_end_); }; class EmptyInlinedStorage { @@ -505,8 +505,10 @@ void FixedArray::NonEmptyInlinedStorage::AnnotateConstruct( typename FixedArray::size_type n) { #ifdef ADDRESS_SANITIZER if (!n) return; - ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), data() + n); - ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(), RedzoneBegin()); + ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), + data() + n); + ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(), + RedzoneBegin()); #endif // ADDRESS_SANITIZER static_cast(n); // Mark used when not in asan mode } @@ -516,8 +518,10 @@ void FixedArray::NonEmptyInlinedStorage::AnnotateDestruct( typename FixedArray::size_type n) { #ifdef ADDRESS_SANITIZER if (!n) return; - ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, RedzoneEnd()); - ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(), data()); + ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, + RedzoneEnd()); + ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(), + data()); #endif // ADDRESS_SANITIZER static_cast(n); // Mark used when not in asan mode } diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc index c05424e0..ed77159e 100644 --- a/absl/debugging/symbolize_elf.inc +++ b/absl/debugging/symbolize_elf.inc @@ -1455,7 +1455,7 @@ bool GetFileMappingHint(const void **start, const void **end, uint64_t *offset, bool Symbolize(const void *pc, char *out, int out_size) { // Symbolization is very slow under tsan. - ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); + ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); SAFE_ASSERT(out_size >= 0); debugging_internal::Symbolizer *s = debugging_internal::AllocateSymbolizer(); const char *name = s->GetSymbol(pc); @@ -1474,7 +1474,7 @@ bool Symbolize(const void *pc, char *out, int out_size) { } } debugging_internal::FreeSymbolizer(s); - ANNOTATE_IGNORE_READS_AND_WRITES_END(); + ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END(); return ok; } diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 0e8535c2..e37d0546 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -474,6 +474,57 @@ TEST_F(FormatConvertTest, Uint128) { } } +template +void TestWithMultipleFormatsHelper(const std::vector &floats) { + // Reserve the space to ensure we don't allocate memory in the output itself. + std::string str_format_result; + str_format_result.reserve(1 << 20); + std::string string_printf_result; + string_printf_result.reserve(1 << 20); + + const char *const kFormats[] = { + "%", "%.3", "%8.5", "%500", "%.5000", "%.60", "%.30", "%03", + "%+", "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; + + for (const char *fmt : kFormats) { + for (char f : {'f', 'F', // + 'g', 'G', // + 'a', 'A', // + 'e', 'E'}) { + std::string fmt_str = std::string(fmt) + f; + + if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { + // This particular test takes way too long with snprintf. + // Disable for the case we are not implementing natively. + continue; + } + + for (Floating d : floats) { + int i = -10; + FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)}; + UntypedFormatSpecImpl format(fmt_str); + + string_printf_result.clear(); + StrAppend(&string_printf_result, fmt_str.c_str(), d, i); + str_format_result.clear(); + + { + AppendPack(&str_format_result, format, absl::MakeSpan(args)); + } + + if (string_printf_result != str_format_result) { + // We use ASSERT_EQ here because failures are usually correlated and a + // bug would print way too many failed expectations causing the test + // to time out. + ASSERT_EQ(string_printf_result, str_format_result) + << fmt_str << " " << StrPrint("%.18g", d) << " " + << StrPrint("%a", d) << " " << StrPrint("%.50f", d); + } + } + } + } +} + TEST_F(FormatConvertTest, Float) { #ifdef _MSC_VER // MSVC has a different rounding policy than us so we can't test our @@ -481,9 +532,62 @@ TEST_F(FormatConvertTest, Float) { return; #endif // _MSC_VER - const char *const kFormats[] = { - "%", "%.3", "%8.5", "%500", "%.5000", "%.60", "%.30", "%03", - "%+", "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"}; + std::vector floats = {0.0f, + -0.0f, + .9999999f, + 9999999.f, + std::numeric_limits::max(), + -std::numeric_limits::max(), + std::numeric_limits::min(), + -std::numeric_limits::min(), + std::numeric_limits::lowest(), + -std::numeric_limits::lowest(), + std::numeric_limits::epsilon(), + std::numeric_limits::epsilon() + 1.0f, + std::numeric_limits::infinity(), + -std::numeric_limits::infinity()}; + + // Some regression tests. + floats.push_back(0.999999989f); + + if (std::numeric_limits::has_denorm != std::denorm_absent) { + floats.push_back(std::numeric_limits::denorm_min()); + floats.push_back(-std::numeric_limits::denorm_min()); + } + + for (float base : + {1.f, 12.f, 123.f, 1234.f, 12345.f, 123456.f, 1234567.f, 12345678.f, + 123456789.f, 1234567890.f, 12345678901.f, 12345678.f, 12345678.f}) { + for (int exp = -123; exp <= 123; ++exp) { + for (int sign : {1, -1}) { + floats.push_back(sign * std::ldexp(base, exp)); + } + } + } + + for (int exp = -300; exp <= 300; ++exp) { + const float all_ones_mantissa = 0xffffff; + floats.push_back(std::ldexp(all_ones_mantissa, exp)); + } + + // Remove duplicates to speed up the logic below. + std::sort(floats.begin(), floats.end()); + floats.erase(std::unique(floats.begin(), floats.end()), floats.end()); + +#ifndef __APPLE__ + // Apple formats NaN differently (+nan) vs. (nan) + floats.push_back(std::nan("")); +#endif + + TestWithMultipleFormatsHelper(floats); +} + +TEST_F(FormatConvertTest, Double) { +#ifdef _MSC_VER + // MSVC has a different rounding policy than us so we can't test our + // implementation against the native one there. + return; +#endif // _MSC_VER std::vector doubles = {0.0, -0.0, @@ -554,52 +658,10 @@ TEST_F(FormatConvertTest, Float) { doubles.push_back(std::nan("")); #endif - // Reserve the space to ensure we don't allocate memory in the output itself. - std::string str_format_result; - str_format_result.reserve(1 << 20); - std::string string_printf_result; - string_printf_result.reserve(1 << 20); - - for (const char *fmt : kFormats) { - for (char f : {'f', 'F', // - 'g', 'G', // - 'a', 'A', // - 'e', 'E'}) { - std::string fmt_str = std::string(fmt) + f; - - if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { - // This particular test takes way too long with snprintf. - // Disable for the case we are not implementing natively. - continue; - } - - for (double d : doubles) { - int i = -10; - FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)}; - UntypedFormatSpecImpl format(fmt_str); - - string_printf_result.clear(); - StrAppend(&string_printf_result, fmt_str.c_str(), d, i); - str_format_result.clear(); - - { - AppendPack(&str_format_result, format, absl::MakeSpan(args)); - } - - if (string_printf_result != str_format_result) { - // We use ASSERT_EQ here because failures are usually correlated and a - // bug would print way too many failed expectations causing the test - // to time out. - ASSERT_EQ(string_printf_result, str_format_result) - << fmt_str << " " << StrPrint("%.18g", d) << " " - << StrPrint("%a", d) << " " << StrPrint("%.1080f", d); - } - } - } - } + TestWithMultipleFormatsHelper(doubles); } -TEST_F(FormatConvertTest, FloatRound) { +TEST_F(FormatConvertTest, DoubleRound) { std::string s; const auto format = [&](const char *fmt, double d) -> std::string & { s.clear(); @@ -797,7 +859,7 @@ TEST_F(FormatConvertTest, LongDouble) { } } -TEST_F(FormatConvertTest, IntAsFloat) { +TEST_F(FormatConvertTest, IntAsDouble) { const int kMin = std::numeric_limits::min(); const int kMax = std::numeric_limits::max(); const int ia[] = { diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index 10e46954..39fc5f60 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -1131,7 +1131,7 @@ bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv, bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink) { - return FloatToSink(v, conv, sink); + return FloatToSink(static_cast(v), conv, sink); } bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv, diff --git a/absl/strings/numbers_test.cc b/absl/strings/numbers_test.cc index 7db85e75..c2f03b63 100644 --- a/absl/strings/numbers_test.cc +++ b/absl/strings/numbers_test.cc @@ -359,6 +359,12 @@ TEST(NumbersTest, Atoi) { VerifySimpleAtoiGood(42, 42); } +TEST(NumbersTest, Atod) { + double d; + EXPECT_TRUE(absl::SimpleAtod("nan", &d)); + EXPECT_TRUE(std::isnan(d)); +} + TEST(NumbersTest, Atoenum) { enum E01 { E01_zero = 0, diff --git a/absl/synchronization/internal/per_thread_sem.h b/absl/synchronization/internal/per_thread_sem.h index 8ab43915..2228b6e8 100644 --- a/absl/synchronization/internal/per_thread_sem.h +++ b/absl/synchronization/internal/per_thread_sem.h @@ -78,7 +78,7 @@ class PerThreadSem { // !t.has_timeout() => Wait(t) will return true. static inline bool Wait(KernelTimeout t); - // White-listed callers. + // Permitted callers. friend class PerThreadSemTest; friend class absl::Mutex; friend absl::base_internal::ThreadIdentity* CreateThreadIdentity(); diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index 62fa8e9c..05f5c041 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -39,7 +39,6 @@ #include // NOLINT(build/c++11) #include "absl/base/attributes.h" -#include "absl/base/call_once.h" #include "absl/base/config.h" #include "absl/base/dynamic_annotations.h" #include "absl/base/internal/atomic_hook.h" @@ -59,6 +58,7 @@ using absl::base_internal::CurrentThreadIdentityIfPresent; using absl::base_internal::PerThreadSynch; +using absl::base_internal::SchedulingGuard; using absl::base_internal::ThreadIdentity; using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity; using absl::synchronization_internal::GraphCycles; @@ -86,6 +86,28 @@ ABSL_CONST_INIT std::atomic synch_deadlock_detection( kDeadlockDetectionDefault); ABSL_CONST_INIT std::atomic synch_check_invariants(false); +// ------------------------------------------ spinlock support + +// Make sure read-only globals used in the Mutex code are contained on the +// same cacheline and cacheline aligned to eliminate any false sharing with +// other globals from this and other modules. +static struct MutexGlobals { + MutexGlobals() { + // Find machine-specific data needed for Delay() and + // TryAcquireWithSpinning(). This runs in the global constructor + // sequence, and before that zeros are safe values. + num_cpus = absl::base_internal::NumCPUs(); + spinloop_iterations = num_cpus > 1 ? 1500 : 0; + } + int num_cpus; + int spinloop_iterations; + // Pad this struct to a full cacheline to prevent false sharing. + char padding[ABSL_CACHELINE_SIZE - 2 * sizeof(int)]; +} ABSL_CACHELINE_ALIGNED mutex_globals; +static_assert( + sizeof(MutexGlobals) == ABSL_CACHELINE_SIZE, + "MutexGlobals must occupy an entire cacheline to prevent false sharing"); + ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook submit_profile_data; @@ -122,22 +144,7 @@ void RegisterSymbolizer(bool (*fn)(const void *pc, char *out, int out_size)) { symbolizer.Store(fn); } -struct ABSL_CACHELINE_ALIGNED MutexGlobals { - absl::once_flag once; - int num_cpus = 0; - int spinloop_iterations = 0; -}; - -static const MutexGlobals& GetMutexGlobals() { - ABSL_CONST_INIT static MutexGlobals data; - absl::base_internal::LowLevelCallOnce(&data.once, [&]() { - data.num_cpus = absl::base_internal::NumCPUs(); - data.spinloop_iterations = data.num_cpus > 1 ? 1500 : 0; - }); - return data; -} - -// Spinlock delay on iteration c. Returns new c. +// spinlock delay on iteration c. Returns new c. namespace { enum DelayMode { AGGRESSIVE, GENTLE }; }; @@ -147,25 +154,22 @@ static int Delay(int32_t c, DelayMode mode) { // gentle then spin only a few times before yielding. Aggressive spinning is // used to ensure that an Unlock() call, which must get the spin lock for // any thread to make progress gets it without undue delay. - const int32_t limit = - GetMutexGlobals().num_cpus > 1 ? (mode == AGGRESSIVE ? 5000 : 250) : 0; + int32_t limit = (mutex_globals.num_cpus > 1) ? + ((mode == AGGRESSIVE) ? 5000 : 250) : 0; if (c < limit) { - // Spin. - c++; + c++; // spin } else { ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0); - if (c == limit) { - // Yield once. + if (c == limit) { // yield once AbslInternalMutexYield(); c++; - } else { - // Then wait. + } else { // then wait absl::SleepFor(absl::Microseconds(10)); c = 0; } ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0); } - return c; + return (c); } // --------------------------Generic atomic ops @@ -1051,6 +1055,7 @@ static PerThreadSynch *DequeueAllWakeable(PerThreadSynch *head, // Try to remove thread s from the list of waiters on this mutex. // Does nothing if s is not on the waiter list. void Mutex::TryRemove(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); // acquire spinlock & lock if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait && @@ -1434,7 +1439,7 @@ void Mutex::AssertNotHeld() const { // Attempt to acquire *mu, and return whether successful. The implementation // may spin for a short while if the lock cannot be acquired immediately. static bool TryAcquireWithSpinning(std::atomic* mu) { - int c = GetMutexGlobals().spinloop_iterations; + int c = mutex_globals.spinloop_iterations; do { // do/while somewhat faster on AMD intptr_t v = mu->load(std::memory_order_relaxed); if ((v & (kMuReader|kMuEvent)) != 0) { @@ -1811,9 +1816,9 @@ static inline bool EvalConditionIgnored(Mutex *mu, const Condition *cond) { // So we "divert" (which un-ignores both memory accesses and synchronization) // and then separately turn on ignores of memory accesses. ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0); - ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); + ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); bool res = cond->Eval(); - ANNOTATE_IGNORE_READS_AND_WRITES_END(); + ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END(); ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0); static_cast(mu); // Prevent unused param warning in non-TSAN builds. return res; @@ -1894,6 +1899,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) { } void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; intptr_t v = mu_.load(std::memory_order_relaxed); if ((v & kMuEvent) != 0) { @@ -2013,6 +2019,7 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { // or it is in the process of blocking on a condition variable; it must requeue // itself on the mutex/condvar to wait for its condition to become true. ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); this->AssertReaderHeld(); CheckForMutexCorruption(v, "Unlock"); @@ -2328,6 +2335,7 @@ void Mutex::Trans(MuHow how) { // It will later acquire the mutex with high probability. Otherwise, we // enqueue thread w on this mutex. void Mutex::Fer(PerThreadSynch *w) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; ABSL_RAW_CHECK(w->waitp->cond == nullptr, "Mutex::Fer while waiting on Condition"); @@ -2426,6 +2434,7 @@ CondVar::~CondVar() { // Remove thread s from the list of waiters on this condition variable. void CondVar::Remove(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v; int c = 0; for (v = cv_.load(std::memory_order_relaxed);; @@ -2586,6 +2595,7 @@ void CondVar::Wakeup(PerThreadSynch *w) { } void CondVar::Signal() { + SchedulingGuard::ScopedDisable disable_rescheduling; ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); intptr_t v; int c = 0; diff --git a/absl/types/BUILD.bazel b/absl/types/BUILD.bazel index de71c734..102affaf 100644 --- a/absl/types/BUILD.bazel +++ b/absl/types/BUILD.bazel @@ -12,7 +12,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -# load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") load( -- cgit v1.2.3 From 81f34df8347a73c617f244f49cb916238857dc34 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Tue, 30 Jun 2020 13:08:50 -0700 Subject: Export of internal Abseil changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -- 739f9fb80212c21c015fec473e9e29803a156ef9 by Derek Mauro : Define FlagStateInterface::~FlagStateInterface() in the translation unit in which it is actually declared Fixes #717 PiperOrigin-RevId: 319083605 -- 913ef1f23113268b22d636d3ae3b992862efdb1a by Derek Mauro : Fix ABSL_LOCK_RETURNED statement PiperOrigin-RevId: 319078667 -- a43b1413da1770d638147c73e7e1693cfaf869c7 by Derek Mauro : Fix redeclaration ‘absl::Cord::InlineRep::kMaxInline’, which differs in ‘constexpr’ Fixes #725 PiperOrigin-RevId: 319060910 -- 1ad7d491a80f6c9de78a6fc20f09b7765d224503 by Abseil Team : Make absl SpinLock trivially destructible when possible PiperOrigin-RevId: 319049456 -- 659ecad3578dfa669854a82279fa590002bdb37f by Derek Mauro : Remove the static initialization of global variables used by absl::Mutex as requested by Chromium PiperOrigin-RevId: 319031204 -- 609c491d8bb4f8bb3b44c5a4c0bee51c583df24c by Abseil Team : Add implementation of %a and %A to absl::StrFormat. Prior to this it just fell back to sprintf. PiperOrigin-RevId: 318888039 -- 5e8ae6392bcd135248aac14c4b9f2a5116868678 by Abseil Team : Google-internal changes only. PiperOrigin-RevId: 318857077 -- 4a2578e33e8442954e29e5f0380ddfcf0f033f0d by Greg Falcon : Change of enum constants to accommodate internal change. PiperOrigin-RevId: 318844716 -- 4b578b102816260c213675759f4c15911735578a by Abseil Team : Internal change PiperOrigin-RevId: 318704453 -- 0ee82fd24d548b260c9229fa1f54571dae1dfa24 by Gennadiy Rozental : Allow lookup of retired flags. At the moment we issue warning on attempt to find a retired flag. This way we can't even check if flag is retired without issuing the warning. With this change we will only issue the warning if one tries to access any functionality of retired flag but it's name "is retired" status, and type. PiperOrigin-RevId: 318605017 -- 3e35fe9b4c79f636fa328c59e2aabb93e29b7c99 by Abseil Team : Fix error return from InstallSymbolDecorator(). PiperOrigin-RevId: 318490405 -- ae46063f3eb2998cb961f62a359d932e5908a4bc by Abseil Team : Do not make copies of iterated collection elements into the loop variable. PiperOrigin-RevId: 318423139 -- d06a075a12aab5f6ab98474677ce50d588b21de3 by Abseil Team : add missing word making the error code better English PiperOrigin-RevId: 318335052 GitOrigin-RevId: 739f9fb80212c21c015fec473e9e29803a156ef9 Change-Id: Id77a0a4b1959036b00555deef40e82d51884fbc1 --- absl/base/internal/low_level_scheduling.h | 5 - absl/base/internal/spinlock.h | 7 + absl/base/spinlock_test_common.cc | 5 + .../internal/hash_function_defaults_test.cc | 4 +- absl/debugging/symbolize_elf.inc | 2 +- absl/flags/BUILD.bazel | 3 + absl/flags/CMakeLists.txt | 2 + absl/flags/commandlineflag.cc | 4 - absl/flags/commandlineflag.h | 4 + absl/flags/internal/commandlineflag.cc | 26 ++ absl/flags/internal/flag.h | 3 +- absl/flags/internal/usage.cc | 4 +- absl/flags/parse.cc | 7 +- absl/flags/reflection.cc | 48 ++-- absl/random/BUILD.bazel | 1 + absl/strings/BUILD.bazel | 1 + absl/strings/CMakeLists.txt | 1 + absl/strings/cord.cc | 2 +- absl/strings/internal/str_format/convert_test.cc | 230 ++++++++++++++++- .../internal/str_format/float_conversion.cc | 281 ++++++++++++++++++++- absl/strings/str_cat.cc | 8 +- absl/synchronization/mutex.cc | 64 ++--- 22 files changed, 618 insertions(+), 94 deletions(-) create mode 100644 absl/flags/internal/commandlineflag.cc (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index 31261298..ed0b4bfa 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -29,9 +29,6 @@ extern "C" void __google_enable_rescheduling(bool disable_result); namespace absl { ABSL_NAMESPACE_BEGIN -class CondVar; -class Mutex; - namespace base_internal { class SchedulingHelper; // To allow use of SchedulingGuard. @@ -80,8 +77,6 @@ class SchedulingGuard { }; // Access to SchedulingGuard is explicitly permitted. - friend class absl::CondVar; - friend class absl::Mutex; friend class SchedulingHelper; friend class SpinLock; diff --git a/absl/base/internal/spinlock.h b/absl/base/internal/spinlock.h index 2222398b..e6ac9e64 100644 --- a/absl/base/internal/spinlock.h +++ b/absl/base/internal/spinlock.h @@ -64,7 +64,14 @@ class ABSL_LOCKABLE SpinLock { constexpr SpinLock(absl::ConstInitType, base_internal::SchedulingMode mode) : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {} + // For global SpinLock instances prefer trivial destructor when possible. + // Default but non-trivial destructor in some build configurations causes an + // extra static initializer. +#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE ~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); } +#else + ~SpinLock() = default; +#endif // Acquire this SpinLock. inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { diff --git a/absl/base/spinlock_test_common.cc b/absl/base/spinlock_test_common.cc index b68c51a1..b33c54ba 100644 --- a/absl/base/spinlock_test_common.cc +++ b/absl/base/spinlock_test_common.cc @@ -20,6 +20,7 @@ #include #include #include // NOLINT(build/c++11) +#include #include #include "gtest/gtest.h" @@ -103,6 +104,10 @@ static void ThreadedTest(SpinLock* spinlock) { } } +#ifndef THREAD_SANITIZER +static_assert(std::is_trivially_destructible(), ""); +#endif + TEST(SpinLock, StackNonCooperativeDisablesScheduling) { SpinLock spinlock(base_internal::SCHEDULE_KERNEL_ONLY); spinlock.Lock(); diff --git a/absl/container/internal/hash_function_defaults_test.cc b/absl/container/internal/hash_function_defaults_test.cc index 2d05a0b7..59576b8e 100644 --- a/absl/container/internal/hash_function_defaults_test.cc +++ b/absl/container/internal/hash_function_defaults_test.cc @@ -337,11 +337,11 @@ ABSL_NAMESPACE_END } // namespace absl enum Hash : size_t { - kStd = 0x2, // std::hash + kStd = 0x1, // std::hash #ifdef _MSC_VER kExtension = kStd, // In MSVC, std::hash == ::hash #else // _MSC_VER - kExtension = 0x4, // ::hash (GCC extension) + kExtension = 0x2, // ::hash (GCC extension) #endif // _MSC_VER }; diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc index ed77159e..328869f1 100644 --- a/absl/debugging/symbolize_elf.inc +++ b/absl/debugging/symbolize_elf.inc @@ -1376,7 +1376,7 @@ int InstallSymbolDecorator(SymbolDecorator decorator, void *arg) { if (!g_decorators_mu.TryLock()) { // Someone else is using decorators. Get out. - return false; + return -2; } int ret = ticket; if (g_num_decorators >= kMaxDecorators) { diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index 006911fd..524e7027 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -106,6 +106,9 @@ cc_library( cc_library( name = "commandlineflag_internal", + srcs = [ + "internal/commandlineflag.cc", + ], hdrs = [ "internal/commandlineflag.h", ], diff --git a/absl/flags/CMakeLists.txt b/absl/flags/CMakeLists.txt index ef75db8e..343774de 100644 --- a/absl/flags/CMakeLists.txt +++ b/absl/flags/CMakeLists.txt @@ -95,6 +95,8 @@ absl_cc_library( absl_cc_library( NAME flags_commandlineflag_internal + SRCS + "internal/commandlineflag.cc" HDRS "internal/commandlineflag.h" COPTS diff --git a/absl/flags/commandlineflag.cc b/absl/flags/commandlineflag.cc index 217b2d87..9f3b4a5a 100644 --- a/absl/flags/commandlineflag.cc +++ b/absl/flags/commandlineflag.cc @@ -30,9 +30,5 @@ bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) { flags_internal::kProgrammaticChange, *error); } -namespace flags_internal { -FlagStateInterface::~FlagStateInterface() {} -} // namespace flags_internal ABSL_NAMESPACE_END } // namespace absl - diff --git a/absl/flags/commandlineflag.h b/absl/flags/commandlineflag.h index 7e21d05d..f2fa0897 100644 --- a/absl/flags/commandlineflag.h +++ b/absl/flags/commandlineflag.h @@ -108,6 +108,10 @@ class CommandLineFlag { U u; Read(&u.value); + // allow retired flags to be "read", so we can report invalid access. + if (IsRetired()) { + return absl::nullopt; + } return std::move(u.value); } diff --git a/absl/flags/internal/commandlineflag.cc b/absl/flags/internal/commandlineflag.cc new file mode 100644 index 00000000..4482955c --- /dev/null +++ b/absl/flags/internal/commandlineflag.cc @@ -0,0 +1,26 @@ +// +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "absl/flags/internal/commandlineflag.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace flags_internal { + +FlagStateInterface::~FlagStateInterface() {} + +} // namespace flags_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index 2cc44e00..89e43ad7 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -482,7 +482,8 @@ class FlagImpl final : public CommandLineFlag { friend class FlagState; // Ensures that `data_guard_` is initialized and returns it. - absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED((absl::Mutex*)&data_guard_); + absl::Mutex* DataGuard() const + ABSL_LOCK_RETURNED(reinterpret_cast(data_guard_)); // Returns heap allocated value of type T initialized with default value. std::unique_ptr MakeInitValue() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()); diff --git a/absl/flags/internal/usage.cc b/absl/flags/internal/usage.cc index 35b6427b..0805df31 100644 --- a/absl/flags/internal/usage.cc +++ b/absl/flags/internal/usage.cc @@ -250,14 +250,14 @@ void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb, matching_flags; flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) { - std::string flag_filename = flag.Filename(); - // Ignore retired flags. if (flag.IsRetired()) return; // If the flag has been stripped, pretend that it doesn't exist. if (flag.Help() == flags_internal::kStrippedFlagHelp) return; + std::string flag_filename = flag.Filename(); + // Make sure flag satisfies the filter if (!filter_cb || !filter_cb(flag_filename)) return; diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc index e2c88ff8..4f4bb3d5 100644 --- a/absl/flags/parse.cc +++ b/absl/flags/parse.cc @@ -729,12 +729,13 @@ std::vector ParseCommandLineImpl(int argc, char* argv[], } // 100. Set the located flag to a new new value, unless it is retired. - // Setting retired flag fails, but we ignoring it here. - if (flag->IsRetired()) continue; - + // Setting retired flag fails, but we ignoring it here while also reporting + // access to retired flag. std::string error; if (!flags_internal::PrivateHandleAccessor::ParseFrom( *flag, value, SET_FLAGS_VALUE, kCommandLine, error)) { + if (flag->IsRetired()) continue; + flags_internal::ReportUsageError(error, true); success = false; } else { diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc index 5fc945f2..02b7c06a 100644 --- a/absl/flags/reflection.cc +++ b/absl/flags/reflection.cc @@ -88,12 +88,6 @@ CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) { if (i == flags_.end()) { return nullptr; } - - if (i->second->IsRetired()) { - flags_internal::ReportUsageError( - absl::StrCat("Accessing retired flag '", name, "'"), false); - } - return i->second; } @@ -155,7 +149,7 @@ void FlagRegistry::RegisterFlag(CommandLineFlag& flag) { } else { flags_internal::ReportUsageError( absl::StrCat( - "Something wrong with flag '", flag.Name(), "' in file '", + "Something is wrong with flag '", flag.Name(), "' in file '", flag.Filename(), "'. One possibility: file '", flag.Filename(), "' is being linked both statically and dynamically into this " "executable. e.g. some files listed as srcs to a test and also " @@ -206,16 +200,34 @@ class RetiredFlagObj final : public CommandLineFlag { private: absl::string_view Name() const override { return name_; } - std::string Filename() const override { return "RETIRED"; } + std::string Filename() const override { + OnAccess(); + return "RETIRED"; + } FlagFastTypeId TypeId() const override { return type_id_; } - std::string Help() const override { return ""; } + std::string Help() const override { + OnAccess(); + return ""; + } bool IsRetired() const override { return true; } - bool IsSpecifiedOnCommandLine() const override { return false; } - std::string DefaultValue() const override { return ""; } - std::string CurrentValue() const override { return ""; } + bool IsSpecifiedOnCommandLine() const override { + OnAccess(); + return false; + } + std::string DefaultValue() const override { + OnAccess(); + return ""; + } + std::string CurrentValue() const override { + OnAccess(); + return ""; + } // Any input is valid - bool ValidateInputValue(absl::string_view) const override { return true; } + bool ValidateInputValue(absl::string_view) const override { + OnAccess(); + return true; + } std::unique_ptr SaveState() override { return nullptr; @@ -223,12 +235,18 @@ class RetiredFlagObj final : public CommandLineFlag { bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode, flags_internal::ValueSource, std::string&) override { + OnAccess(); return false; } - void CheckDefaultValueParsingRoundtrip() const override {} + void CheckDefaultValueParsingRoundtrip() const override { OnAccess(); } - void Read(void*) const override {} + void Read(void*) const override { OnAccess(); } + + void OnAccess() const { + flags_internal::ReportUsageError( + absl::StrCat("Accessing retired flag '", name_, "'"), false); + } // Data members const char* const name_; diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel index 694331c2..81e150e6 100644 --- a/absl/random/BUILD.bazel +++ b/absl/random/BUILD.bazel @@ -199,6 +199,7 @@ cc_test( cc_test( name = "distributions_test", size = "small", + timeout = "moderate", srcs = [ "distributions_test.cc", ], diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 8220896d..ef412639 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -720,6 +720,7 @@ cc_test( visibility = ["//visibility:private"], deps = [ ":str_format_internal", + ":strings", "//absl/base:raw_logging_internal", "//absl/types:optional", "@com_google_googletest//:gtest_main", diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index c0ea0c8e..d7237231 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -475,6 +475,7 @@ absl_cc_test( COPTS ${ABSL_TEST_COPTS} DEPS + absl::strings absl::str_format_internal absl::raw_logging_internal absl::int128 diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc index 68f53987..8ecffc4b 100644 --- a/absl/strings/cord.cc +++ b/absl/strings/cord.cc @@ -495,7 +495,7 @@ static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) { // This will trigger LNK2005 in MSVC. #ifndef COMPILER_MSVC -const unsigned char Cord::InlineRep::kMaxInline; +constexpr unsigned char Cord::InlineRep::kMaxInline; #endif // COMPILER_MSVC inline void Cord::InlineRep::set_data(const char* data, size_t n, diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index e37d0546..488d4cd4 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -12,6 +12,7 @@ #include "gtest/gtest.h" #include "absl/base/internal/raw_logging.h" #include "absl/strings/internal/str_format/bind.h" +#include "absl/strings/match.h" #include "absl/types/optional.h" namespace absl { @@ -19,6 +20,13 @@ ABSL_NAMESPACE_BEGIN namespace str_format_internal { namespace { +struct NativePrintfTraits { + bool hex_float_has_glibc_rounding; + bool hex_float_prefers_denormal_repr; + bool hex_float_uses_minimal_precision_when_not_specified; + bool hex_float_optimizes_leading_digit_bit_count; +}; + template size_t ArraySize(T (&)[N]) { return N; @@ -118,6 +126,63 @@ std::string StrPrint(const char *format, ...) { return result; } +NativePrintfTraits VerifyNativeImplementationImpl() { + NativePrintfTraits result; + + // >>> hex_float_has_glibc_rounding. To have glibc's rounding behavior we need + // to meet three requirements: + // + // - The threshold for rounding up is 8 (for e.g. MSVC uses 9). + // - If the digits lower than than the 8 are non-zero then we round up. + // - If the digits lower than the 8 are all zero then we round toward even. + // + // The numbers below represent all the cases covering {below,at,above} the + // threshold (8) with both {zero,non-zero} lower bits and both {even,odd} + // preceding digits. + const double d0079 = 65657.0; // 0x1.0079p+16 + const double d0179 = 65913.0; // 0x1.0179p+16 + const double d0080 = 65664.0; // 0x1.0080p+16 + const double d0180 = 65920.0; // 0x1.0180p+16 + const double d0081 = 65665.0; // 0x1.0081p+16 + const double d0181 = 65921.0; // 0x1.0181p+16 + result.hex_float_has_glibc_rounding = + StartsWith(StrPrint("%.2a", d0079), "0x1.00") && + StartsWith(StrPrint("%.2a", d0179), "0x1.01") && + StartsWith(StrPrint("%.2a", d0080), "0x1.00") && + StartsWith(StrPrint("%.2a", d0180), "0x1.02") && + StartsWith(StrPrint("%.2a", d0081), "0x1.01") && + StartsWith(StrPrint("%.2a", d0181), "0x1.02"); + + // >>> hex_float_prefers_denormal_repr. Formatting `denormal` on glibc yields + // "0x0.0000000000001p-1022", whereas on std libs that don't use denormal + // representation it would either be 0x1p-1074 or 0x1.0000000000000-1074. + const double denormal = std::numeric_limits::denorm_min(); + result.hex_float_prefers_denormal_repr = + StartsWith(StrPrint("%a", denormal), "0x0.0000000000001"); + + // >>> hex_float_uses_minimal_precision_when_not_specified. Some (non-glibc) + // libs will format the following as "0x1.0079000000000p+16". + result.hex_float_uses_minimal_precision_when_not_specified = + (StrPrint("%a", d0079) == "0x1.0079p+16"); + + // >>> hex_float_optimizes_leading_digit_bit_count. The number 1.5, when + // formatted by glibc should yield "0x1.8p+0" for `double` and "0xcp-3" for + // `long double`, i.e., number of bits in the leading digit is adapted to the + // number of bits in the mantissa. + const double d_15 = 1.5; + const long double ld_15 = 1.5; + result.hex_float_optimizes_leading_digit_bit_count = + StartsWith(StrPrint("%a", d_15), "0x1.8") && + StartsWith(StrPrint("%La", ld_15), "0xc"); + + return result; +} + +const NativePrintfTraits &VerifyNativeImplementation() { + static NativePrintfTraits native_traits = VerifyNativeImplementationImpl(); + return native_traits; +} + class FormatConvertTest : public ::testing::Test { }; template @@ -476,6 +541,7 @@ TEST_F(FormatConvertTest, Uint128) { template void TestWithMultipleFormatsHelper(const std::vector &floats) { + const NativePrintfTraits &native_traits = VerifyNativeImplementation(); // Reserve the space to ensure we don't allocate memory in the output itself. std::string str_format_result; str_format_result.reserve(1 << 20); @@ -493,13 +559,23 @@ void TestWithMultipleFormatsHelper(const std::vector &floats) { 'e', 'E'}) { std::string fmt_str = std::string(fmt) + f; - if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { + if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F' && + f != 'a' && f != 'A') { // This particular test takes way too long with snprintf. // Disable for the case we are not implementing natively. continue; } + if ((f == 'a' || f == 'A') && + !native_traits.hex_float_has_glibc_rounding) { + continue; + } + for (Floating d : floats) { + if (!native_traits.hex_float_prefers_denormal_repr && + (f == 'a' || f == 'A') && std::fpclassify(d) == FP_SUBNORMAL) { + continue; + } int i = -10; FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)}; UntypedFormatSpecImpl format(fmt_str); @@ -766,6 +842,111 @@ TEST_F(FormatConvertTest, DoubleRound) { "1837869002408041296803276054561138153076171875"); } +TEST_F(FormatConvertTest, DoubleRoundA) { + const NativePrintfTraits &native_traits = VerifyNativeImplementation(); + std::string s; + const auto format = [&](const char *fmt, double d) -> std::string & { + s.clear(); + FormatArgImpl args[1] = {FormatArgImpl(d)}; + AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); + if (native_traits.hex_float_has_glibc_rounding) { + EXPECT_EQ(StrPrint(fmt, d), s); + } + return s; + }; + + // 0x1.00018000p+100 + const double on_boundary_odd = 1267679614447900152596896153600.0; + EXPECT_EQ(format("%.0a", on_boundary_odd), "0x1p+100"); + EXPECT_EQ(format("%.1a", on_boundary_odd), "0x1.0p+100"); + EXPECT_EQ(format("%.2a", on_boundary_odd), "0x1.00p+100"); + EXPECT_EQ(format("%.3a", on_boundary_odd), "0x1.000p+100"); + EXPECT_EQ(format("%.4a", on_boundary_odd), "0x1.0002p+100"); // round + EXPECT_EQ(format("%.5a", on_boundary_odd), "0x1.00018p+100"); + EXPECT_EQ(format("%.6a", on_boundary_odd), "0x1.000180p+100"); + + // 0x1.00028000p-2 + const double on_boundary_even = 0.250009536743164062500; + EXPECT_EQ(format("%.0a", on_boundary_even), "0x1p-2"); + EXPECT_EQ(format("%.1a", on_boundary_even), "0x1.0p-2"); + EXPECT_EQ(format("%.2a", on_boundary_even), "0x1.00p-2"); + EXPECT_EQ(format("%.3a", on_boundary_even), "0x1.000p-2"); + EXPECT_EQ(format("%.4a", on_boundary_even), "0x1.0002p-2"); // no round + EXPECT_EQ(format("%.5a", on_boundary_even), "0x1.00028p-2"); + EXPECT_EQ(format("%.6a", on_boundary_even), "0x1.000280p-2"); + + // 0x1.00018001p+1 + const double slightly_over = 2.00004577683284878730773925781250; + EXPECT_EQ(format("%.0a", slightly_over), "0x1p+1"); + EXPECT_EQ(format("%.1a", slightly_over), "0x1.0p+1"); + EXPECT_EQ(format("%.2a", slightly_over), "0x1.00p+1"); + EXPECT_EQ(format("%.3a", slightly_over), "0x1.000p+1"); + EXPECT_EQ(format("%.4a", slightly_over), "0x1.0002p+1"); + EXPECT_EQ(format("%.5a", slightly_over), "0x1.00018p+1"); + EXPECT_EQ(format("%.6a", slightly_over), "0x1.000180p+1"); + + // 0x1.00017fffp+0 + const double slightly_under = 1.000022887950763106346130371093750; + EXPECT_EQ(format("%.0a", slightly_under), "0x1p+0"); + EXPECT_EQ(format("%.1a", slightly_under), "0x1.0p+0"); + EXPECT_EQ(format("%.2a", slightly_under), "0x1.00p+0"); + EXPECT_EQ(format("%.3a", slightly_under), "0x1.000p+0"); + EXPECT_EQ(format("%.4a", slightly_under), "0x1.0001p+0"); + EXPECT_EQ(format("%.5a", slightly_under), "0x1.00018p+0"); + EXPECT_EQ(format("%.6a", slightly_under), "0x1.000180p+0"); + EXPECT_EQ(format("%.7a", slightly_under), "0x1.0001800p+0"); + + // 0x1.1b3829ac28058p+3 + const double hex_value = 8.85060580848964661981881363317370414733886718750; + EXPECT_EQ(format("%.0a", hex_value), "0x1p+3"); + EXPECT_EQ(format("%.1a", hex_value), "0x1.2p+3"); + EXPECT_EQ(format("%.2a", hex_value), "0x1.1bp+3"); + EXPECT_EQ(format("%.3a", hex_value), "0x1.1b4p+3"); + EXPECT_EQ(format("%.4a", hex_value), "0x1.1b38p+3"); + EXPECT_EQ(format("%.5a", hex_value), "0x1.1b383p+3"); + EXPECT_EQ(format("%.6a", hex_value), "0x1.1b382ap+3"); + EXPECT_EQ(format("%.7a", hex_value), "0x1.1b3829bp+3"); + EXPECT_EQ(format("%.8a", hex_value), "0x1.1b3829acp+3"); + EXPECT_EQ(format("%.9a", hex_value), "0x1.1b3829ac3p+3"); + EXPECT_EQ(format("%.10a", hex_value), "0x1.1b3829ac28p+3"); + EXPECT_EQ(format("%.11a", hex_value), "0x1.1b3829ac280p+3"); + EXPECT_EQ(format("%.12a", hex_value), "0x1.1b3829ac2806p+3"); + EXPECT_EQ(format("%.13a", hex_value), "0x1.1b3829ac28058p+3"); + EXPECT_EQ(format("%.14a", hex_value), "0x1.1b3829ac280580p+3"); + EXPECT_EQ(format("%.15a", hex_value), "0x1.1b3829ac2805800p+3"); + EXPECT_EQ(format("%.16a", hex_value), "0x1.1b3829ac28058000p+3"); + EXPECT_EQ(format("%.17a", hex_value), "0x1.1b3829ac280580000p+3"); + EXPECT_EQ(format("%.18a", hex_value), "0x1.1b3829ac2805800000p+3"); + EXPECT_EQ(format("%.19a", hex_value), "0x1.1b3829ac28058000000p+3"); + EXPECT_EQ(format("%.20a", hex_value), "0x1.1b3829ac280580000000p+3"); + EXPECT_EQ(format("%.21a", hex_value), "0x1.1b3829ac2805800000000p+3"); + + // 0x1.0818283848586p+3 + const double hex_value2 = 8.2529488658208371987257123691961169242858886718750; + EXPECT_EQ(format("%.0a", hex_value2), "0x1p+3"); + EXPECT_EQ(format("%.1a", hex_value2), "0x1.1p+3"); + EXPECT_EQ(format("%.2a", hex_value2), "0x1.08p+3"); + EXPECT_EQ(format("%.3a", hex_value2), "0x1.082p+3"); + EXPECT_EQ(format("%.4a", hex_value2), "0x1.0818p+3"); + EXPECT_EQ(format("%.5a", hex_value2), "0x1.08183p+3"); + EXPECT_EQ(format("%.6a", hex_value2), "0x1.081828p+3"); + EXPECT_EQ(format("%.7a", hex_value2), "0x1.0818284p+3"); + EXPECT_EQ(format("%.8a", hex_value2), "0x1.08182838p+3"); + EXPECT_EQ(format("%.9a", hex_value2), "0x1.081828385p+3"); + EXPECT_EQ(format("%.10a", hex_value2), "0x1.0818283848p+3"); + EXPECT_EQ(format("%.11a", hex_value2), "0x1.08182838486p+3"); + EXPECT_EQ(format("%.12a", hex_value2), "0x1.081828384858p+3"); + EXPECT_EQ(format("%.13a", hex_value2), "0x1.0818283848586p+3"); + EXPECT_EQ(format("%.14a", hex_value2), "0x1.08182838485860p+3"); + EXPECT_EQ(format("%.15a", hex_value2), "0x1.081828384858600p+3"); + EXPECT_EQ(format("%.16a", hex_value2), "0x1.0818283848586000p+3"); + EXPECT_EQ(format("%.17a", hex_value2), "0x1.08182838485860000p+3"); + EXPECT_EQ(format("%.18a", hex_value2), "0x1.081828384858600000p+3"); + EXPECT_EQ(format("%.19a", hex_value2), "0x1.0818283848586000000p+3"); + EXPECT_EQ(format("%.20a", hex_value2), "0x1.08182838485860000000p+3"); + EXPECT_EQ(format("%.21a", hex_value2), "0x1.081828384858600000000p+3"); +} + // We don't actually store the results. This is just to exercise the rest of the // machinery. struct NullSink { @@ -797,6 +978,7 @@ TEST_F(FormatConvertTest, LongDouble) { // implementation against the native one there. return; #endif // _MSC_VER + const NativePrintfTraits &native_traits = VerifyNativeImplementation(); const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000", "%.60", "%+", "% ", "%-10"}; @@ -839,12 +1021,20 @@ TEST_F(FormatConvertTest, LongDouble) { 'e', 'E'}) { std::string fmt_str = std::string(fmt) + 'L' + f; - if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') { + if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F' && + f != 'a' && f != 'A') { // This particular test takes way too long with snprintf. // Disable for the case we are not implementing natively. continue; } + if (f == 'a' || f == 'A') { + if (!native_traits.hex_float_has_glibc_rounding || + !native_traits.hex_float_optimizes_leading_digit_bit_count) { + continue; + } + } + for (auto d : doubles) { FormatArgImpl arg(d); UntypedFormatSpecImpl format(fmt_str); @@ -860,6 +1050,7 @@ TEST_F(FormatConvertTest, LongDouble) { } TEST_F(FormatConvertTest, IntAsDouble) { + const NativePrintfTraits &native_traits = VerifyNativeImplementation(); const int kMin = std::numeric_limits::min(); const int kMax = std::numeric_limits::max(); const int ia[] = { @@ -875,14 +1066,16 @@ TEST_F(FormatConvertTest, IntAsDouble) { const char *fmt; }; const double dx = static_cast(fx); - const Expectation kExpect[] = { - { __LINE__, StrPrint("%f", dx), "%f" }, - { __LINE__, StrPrint("%12f", dx), "%12f" }, - { __LINE__, StrPrint("%.12f", dx), "%.12f" }, - { __LINE__, StrPrint("%12a", dx), "%12a" }, - { __LINE__, StrPrint("%.12a", dx), "%.12a" }, + std::vector expect = { + {__LINE__, StrPrint("%f", dx), "%f"}, + {__LINE__, StrPrint("%12f", dx), "%12f"}, + {__LINE__, StrPrint("%.12f", dx), "%.12f"}, + {__LINE__, StrPrint("%.12a", dx), "%.12a"}, }; - for (const Expectation &e : kExpect) { + if (native_traits.hex_float_uses_minimal_precision_when_not_specified) { + expect.push_back({__LINE__, StrPrint("%12a", dx), "%12a"}); + } + for (const Expectation &e : expect) { SCOPED_TRACE(e.line); SCOPED_TRACE(e.fmt); UntypedFormatSpecImpl format(e.fmt); @@ -927,6 +1120,25 @@ TEST_F(FormatConvertTest, ExpectedFailures) { EXPECT_TRUE(FormatFails("%*d", "")); } +// Sanity check to make sure that we are testing what we think we're testing on +// e.g. the x86_64+glibc platform. +TEST_F(FormatConvertTest, GlibcHasCorrectTraits) { +#if !defined(__GLIBC__) || !defined(__x86_64__) + return; +#endif + const NativePrintfTraits &native_traits = VerifyNativeImplementation(); + // If one of the following tests break then it is either because the above PP + // macro guards failed to exclude a new platform (likely) or because something + // has changed in the implemention of glibc sprintf float formatting behavior. + // If the latter, then the code that computes these flags needs to be + // revisited and/or possibly the StrFormat implementation. + EXPECT_TRUE(native_traits.hex_float_has_glibc_rounding); + EXPECT_TRUE(native_traits.hex_float_prefers_denormal_repr); + EXPECT_TRUE( + native_traits.hex_float_uses_minimal_precision_when_not_specified); + EXPECT_TRUE(native_traits.hex_float_optimizes_leading_digit_bit_count); +} + } // namespace } // namespace str_format_internal ABSL_NAMESPACE_END diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index 39fc5f60..6eb7b9fc 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -15,6 +15,7 @@ #include "absl/functional/function_ref.h" #include "absl/meta/type_traits.h" #include "absl/numeric/int128.h" +#include "absl/strings/numbers.h" #include "absl/types/optional.h" #include "absl/types/span.h" @@ -453,26 +454,31 @@ Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) { } } -void FinalPrint(absl::string_view data, int trailing_zeros, - const FormatState &state) { +void FinalPrint(const FormatState &state, absl::string_view data, + int padding_offset, int trailing_zeros, + absl::string_view data_postfix) { if (state.conv.width() < 0) { // No width specified. Fast-path. if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); state.sink->Append(data); state.sink->Append(trailing_zeros, '0'); + state.sink->Append(data_postfix); return; } - auto padding = - ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + data.size() + - static_cast(trailing_zeros), - state); + auto padding = ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + + data.size() + data_postfix.size() + + static_cast(trailing_zeros), + state); state.sink->Append(padding.left_spaces, ' '); if (state.sign_char != '\0') state.sink->Append(1, state.sign_char); + // Padding in general needs to be inserted somewhere in the middle of `data`. + state.sink->Append(data.substr(0, padding_offset)); state.sink->Append(padding.zeros, '0'); - state.sink->Append(data); + state.sink->Append(data.substr(padding_offset)); state.sink->Append(trailing_zeros, '0'); + state.sink->Append(data_postfix); state.sink->Append(padding.right_spaces, ' '); } @@ -525,10 +531,11 @@ void FormatFFast(Int v, int exp, const FormatState &state) { // In `alt` mode (flag #) we keep the `.` even if there are no fractional // digits. In non-alt mode, we strip it. if (!state.ShouldPrintDot()) --size; - FinalPrint(absl::string_view(integral_digits_start, size), + FinalPrint(state, absl::string_view(integral_digits_start, size), + /*padding_offset=*/0, static_cast(state.precision - (fractional_digits_end - fractional_digits_start)), - state); + /*data_postfix=*/""); } // Slow %f formatter for when the shifted value does not fit in a uint128, and @@ -655,6 +662,257 @@ void FormatF(Int mantissa, int exp, const FormatState &state) { return FormatFFast(mantissa, exp, state); } +// Grab the group of four bits (nibble) from `n`. E.g., nibble 1 corresponds to +// bits 4-7. +template +uint8_t GetNibble(Int n, int nibble_index) { + constexpr Int mask_low_nibble = Int{0xf}; + int shift = nibble_index * 4; + n &= mask_low_nibble << shift; + return static_cast((n >> shift) & 0xf); +} + +// Add one to the given nibble, applying carry to higher nibbles. Returns true +// if overflow, false otherwise. +template +bool IncrementNibble(int nibble_index, Int *n) { + constexpr int kShift = sizeof(Int) * 8 - 1; + constexpr int kNumNibbles = sizeof(Int) * 8 / 4; + Int before = *n >> kShift; + // Here we essentially want to take the number 1 and move it into the requsted + // nibble, then add it to *n to effectively increment the nibble. However, + // ASan will complain if we try to shift the 1 beyond the limits of the Int, + // i.e., if the nibble_index is out of range. So therefore we check for this + // and if we are out of range we just add 0 which leaves *n unchanged, which + // seems like the reasonable thing to do in that case. + *n += + ((nibble_index * 4 >= sizeof(Int) * 8) ? 0 + : (Int{1} << (nibble_index * 4))); + Int after = *n >> kShift; + return (before && !after) || (nibble_index >= kNumNibbles); +} + +// Return a mask with 1's in the given nibble and all lower nibbles. +template +Int MaskUpToNibbleInclusive(int nibble_index) { + constexpr int kNumNibbles = sizeof(Int) * 8 / 4; + static const Int ones = ~Int{0}; + return ones >> std::max(0, 4 * (kNumNibbles - nibble_index - 1)); +} + +// Return a mask with 1's below the given nibble. +template +Int MaskUpToNibbleExclusive(int nibble_index) { + return nibble_index <= 0 ? 0 : MaskUpToNibbleInclusive(nibble_index - 1); +} + +template +Int MoveToNibble(uint8_t nibble, int nibble_index) { + return Int{nibble} << (4 * nibble_index); +} + +// Given mantissa size, find optimal # of mantissa bits to put in initial digit. +// +// In the hex representation we keep a single hex digit to the left of the dot. +// However, the question as to how many bits of the mantissa should be put into +// that hex digit in theory is arbitrary, but in practice it is optimal to +// choose based on the size of the mantissa. E.g., for a `double`, there are 53 +// mantissa bits, so that means that we should put 1 bit to the left of the dot, +// thereby leaving 52 bits to the right, which is evenly divisible by four and +// thus all fractional digits represent actual precision. For a `long double`, +// on the other hand, there are 64 bits of mantissa, thus we can use all four +// bits for the initial hex digit and still have a number left over (60) that is +// a multiple of four. Once again, the goal is to have all fractional digits +// represent real precision. +template +constexpr int HexFloatLeadingDigitSizeInBits() { + return std::numeric_limits::digits % 4 > 0 + ? std::numeric_limits::digits % 4 + : 4; +} + +// This function captures the rounding behavior of glibc for hex float +// representations. E.g. when rounding 0x1.ab800000 to a precision of .2 +// ("%.2a") glibc will round up because it rounds toward the even number (since +// 0xb is an odd number, it will round up to 0xc). However, when rounding at a +// point that is not followed by 800000..., it disregards the parity and rounds +// up if > 8 and rounds down if < 8. +template +bool HexFloatNeedsRoundUp(Int mantissa, int final_nibble_displayed) { + // If the last nibble (hex digit) to be displayed is the lowest on in the + // mantissa then that means that we don't have any further nibbles to inform + // rounding, so don't round. + if (final_nibble_displayed <= 0) { + return false; + } + int rounding_nibble_idx = final_nibble_displayed - 1; + constexpr int kTotalNibbles = sizeof(Int) * 8 / 4; + assert(final_nibble_displayed <= kTotalNibbles); + Int mantissa_up_to_rounding_nibble_inclusive = + mantissa & MaskUpToNibbleInclusive(rounding_nibble_idx); + Int eight = MoveToNibble(8, rounding_nibble_idx); + if (mantissa_up_to_rounding_nibble_inclusive != eight) { + return mantissa_up_to_rounding_nibble_inclusive > eight; + } + // Nibble in question == 8. + uint8_t should_round_at_8 = + (final_nibble_displayed >= kTotalNibbles) + ? true + : (GetNibble(mantissa, final_nibble_displayed) % 2 == 1); + return should_round_at_8; +} + +// Stores values associated with a Float type needed by the FormatA +// implementation in order to avoid templatizing that function by the Float +// type. +struct HexFloatTypeParams { + template + explicit HexFloatTypeParams(Float) + : min_exponent(std::numeric_limits::min_exponent - 1), + leading_digit_size_bits(HexFloatLeadingDigitSizeInBits()) { + assert(leading_digit_size_bits >= 1 && leading_digit_size_bits <= 4); + } + + int min_exponent; + int leading_digit_size_bits; +}; + +// Hex Float Rounding. First check if we need to round; if so, then we do that +// by manipulating (incrementing) the mantissa, that way we can later print the +// mantissa digits by iterating through them in the same way regardless of +// whether a rounding happened. +template +void FormatARound(bool precision_specified, const FormatState &state, + uint8_t *leading, Int *mantissa, int *exp) { + constexpr int kTotalNibbles = sizeof(Int) * 8 / 4; + // Index of the last nibble that we could display given precision. + int final_nibble_displayed = + precision_specified ? std::max(0, (kTotalNibbles - state.precision)) : 0; + if (HexFloatNeedsRoundUp(*mantissa, final_nibble_displayed)) { + // Need to round up. + bool overflow = IncrementNibble(final_nibble_displayed, mantissa); + *leading += (overflow ? 1 : 0); + if (ABSL_PREDICT_FALSE(*leading > 15)) { + // We have overflowed the leading digit. This would mean that we would + // need two hex digits to the left of the dot, which is not allowed. So + // adjust the mantissa and exponent so that the result is always 1.0eXXX. + *leading = 1; + *mantissa = 0; + *exp += 4; + } + } + // Now that we have handled a possible round-up we can go ahead and zero out + // all the nibbles of the mantissa that we won't need. + if (precision_specified) { + *mantissa &= ~MaskUpToNibbleExclusive(final_nibble_displayed); + } +} + +template +void FormatANormalize(const HexFloatTypeParams float_traits, uint8_t *leading, + Int *mantissa, int *exp) { + constexpr int kIntBits = sizeof(Int) * 8; + static const Int kHighIntBit = Int{1} << (kIntBits - 1); + const int kLeadDigitBitsCount = float_traits.leading_digit_size_bits; + // Normalize mantissa so that highest bit set is in MSB position, unless we + // get interrupted by the exponent threshold. + while (*mantissa && !(*mantissa & kHighIntBit)) { + if (ABSL_PREDICT_FALSE(*exp - 1 < float_traits.min_exponent)) { + *mantissa >>= (float_traits.min_exponent - *exp); + *exp = float_traits.min_exponent; + return; + } + *mantissa <<= 1; + --*exp; + } + // Extract bits for leading digit then shift them away leaving the + // fractional part. + *leading = + static_cast(*mantissa >> (kIntBits - kLeadDigitBitsCount)); + *exp -= (*mantissa != 0) ? kLeadDigitBitsCount : *exp; + *mantissa <<= kLeadDigitBitsCount; +} + +template +void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp, + bool uppercase, const FormatState &state) { + // Int properties. + constexpr int kIntBits = sizeof(Int) * 8; + constexpr int kTotalNibbles = sizeof(Int) * 8 / 4; + // Did the user specify a precision explicitly? + const bool precision_specified = state.conv.precision() >= 0; + + // ========== Normalize/Denormalize ========== + exp += kIntBits; // make all digits fractional digits. + // This holds the (up to four) bits of leading digit, i.e., the '1' in the + // number 0x1.e6fp+2. It's always > 0 unless number is zero or denormal. + uint8_t leading = 0; + FormatANormalize(float_traits, &leading, &mantissa, &exp); + + // =============== Rounding ================== + // Check if we need to round; if so, then we do that by manipulating + // (incrementing) the mantissa before beginning to print characters. + FormatARound(precision_specified, state, &leading, &mantissa, &exp); + + // ============= Format Result =============== + // This buffer holds the "0x1.ab1de3" portion of "0x1.ab1de3pe+2". Compute the + // size with long double which is the largest of the floats. + constexpr size_t kBufSizeForHexFloatRepr = + 2 // 0x + + std::numeric_limits::digits / 4 // number of hex digits + + 1 // round up + + 1; // "." (dot) + char digits_buffer[kBufSizeForHexFloatRepr]; + char *digits_iter = digits_buffer; + const char *const digits = + static_cast("0123456789ABCDEF0123456789abcdef") + + (uppercase ? 0 : 16); + + // =============== Hex Prefix ================ + *digits_iter++ = '0'; + *digits_iter++ = uppercase ? 'X' : 'x'; + + // ========== Non-Fractional Digit =========== + *digits_iter++ = digits[leading]; + + // ================== Dot ==================== + // There are three reasons we might need a dot. Keep in mind that, at this + // point, the mantissa holds only the fractional part. + if ((precision_specified && state.precision > 0) || + (!precision_specified && mantissa > 0) || state.conv.has_alt_flag()) { + *digits_iter++ = '.'; + } + + // ============ Fractional Digits ============ + int digits_emitted = 0; + while (mantissa > 0) { + *digits_iter++ = digits[GetNibble(mantissa, kTotalNibbles - 1)]; + mantissa <<= 4; + ++digits_emitted; + } + int trailing_zeros = + precision_specified ? state.precision - digits_emitted : 0; + assert(trailing_zeros >= 0); + auto digits_result = string_view(digits_buffer, digits_iter - digits_buffer); + + // =============== Exponent ================== + constexpr size_t kBufSizeForExpDecRepr = + numbers_internal::kFastToBufferSize // requred for FastIntToBuffer + + 1 // 'p' or 'P' + + 1; // '+' or '-' + char exp_buffer[kBufSizeForExpDecRepr]; + exp_buffer[0] = uppercase ? 'P' : 'p'; + exp_buffer[1] = exp >= 0 ? '+' : '-'; + numbers_internal::FastIntToBuffer(exp < 0 ? -exp : exp, exp_buffer + 2); + + // ============ Assemble Result ============== + FinalPrint(state, // + digits_result, // 0xN.NNN... + 2, // offset in `data` to start padding if needed. + trailing_zeros, // num remaining mantissa padding zeros + exp_buffer); // exponent +} + char *CopyStringTo(absl::string_view v, char *out) { std::memcpy(out, v.data(), v.size()); return out + v.size(); @@ -1103,7 +1361,10 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv, } } else if (c == FormatConversionCharInternal::a || c == FormatConversionCharInternal::A) { - return FallbackToSnprintf(v, conv, sink); + bool uppercase = (c == FormatConversionCharInternal::A); + FormatA(HexFloatTypeParams(Float{}), decomposed.mantissa, + decomposed.exponent, uppercase, {sign_char, precision, conv, sink}); + return true; } else { return false; } diff --git a/absl/strings/str_cat.cc b/absl/strings/str_cat.cc index d9afe2f3..dd5d25b0 100644 --- a/absl/strings/str_cat.cc +++ b/absl/strings/str_cat.cc @@ -141,12 +141,12 @@ namespace strings_internal { std::string CatPieces(std::initializer_list pieces) { std::string result; size_t total_size = 0; - for (const absl::string_view piece : pieces) total_size += piece.size(); + for (const absl::string_view& piece : pieces) total_size += piece.size(); strings_internal::STLStringResizeUninitialized(&result, total_size); char* const begin = &result[0]; char* out = begin; - for (const absl::string_view piece : pieces) { + for (const absl::string_view& piece : pieces) { const size_t this_size = piece.size(); if (this_size != 0) { memcpy(out, piece.data(), this_size); @@ -170,7 +170,7 @@ void AppendPieces(std::string* dest, std::initializer_list pieces) { size_t old_size = dest->size(); size_t total_size = old_size; - for (const absl::string_view piece : pieces) { + for (const absl::string_view& piece : pieces) { ASSERT_NO_OVERLAP(*dest, piece); total_size += piece.size(); } @@ -178,7 +178,7 @@ void AppendPieces(std::string* dest, char* const begin = &(*dest)[0]; char* out = begin + old_size; - for (const absl::string_view piece : pieces) { + for (const absl::string_view& piece : pieces) { const size_t this_size = piece.size(); if (this_size != 0) { memcpy(out, piece.data(), this_size); diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index 05f5c041..c7968f06 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -39,6 +39,7 @@ #include // NOLINT(build/c++11) #include "absl/base/attributes.h" +#include "absl/base/call_once.h" #include "absl/base/config.h" #include "absl/base/dynamic_annotations.h" #include "absl/base/internal/atomic_hook.h" @@ -58,7 +59,6 @@ using absl::base_internal::CurrentThreadIdentityIfPresent; using absl::base_internal::PerThreadSynch; -using absl::base_internal::SchedulingGuard; using absl::base_internal::ThreadIdentity; using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity; using absl::synchronization_internal::GraphCycles; @@ -86,28 +86,6 @@ ABSL_CONST_INIT std::atomic synch_deadlock_detection( kDeadlockDetectionDefault); ABSL_CONST_INIT std::atomic synch_check_invariants(false); -// ------------------------------------------ spinlock support - -// Make sure read-only globals used in the Mutex code are contained on the -// same cacheline and cacheline aligned to eliminate any false sharing with -// other globals from this and other modules. -static struct MutexGlobals { - MutexGlobals() { - // Find machine-specific data needed for Delay() and - // TryAcquireWithSpinning(). This runs in the global constructor - // sequence, and before that zeros are safe values. - num_cpus = absl::base_internal::NumCPUs(); - spinloop_iterations = num_cpus > 1 ? 1500 : 0; - } - int num_cpus; - int spinloop_iterations; - // Pad this struct to a full cacheline to prevent false sharing. - char padding[ABSL_CACHELINE_SIZE - 2 * sizeof(int)]; -} ABSL_CACHELINE_ALIGNED mutex_globals; -static_assert( - sizeof(MutexGlobals) == ABSL_CACHELINE_SIZE, - "MutexGlobals must occupy an entire cacheline to prevent false sharing"); - ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook submit_profile_data; @@ -144,7 +122,22 @@ void RegisterSymbolizer(bool (*fn)(const void *pc, char *out, int out_size)) { symbolizer.Store(fn); } -// spinlock delay on iteration c. Returns new c. +struct ABSL_CACHELINE_ALIGNED MutexGlobals { + absl::once_flag once; + int num_cpus = 0; + int spinloop_iterations = 0; +}; + +static const MutexGlobals& GetMutexGlobals() { + ABSL_CONST_INIT static MutexGlobals data; + absl::base_internal::LowLevelCallOnce(&data.once, [&]() { + data.num_cpus = absl::base_internal::NumCPUs(); + data.spinloop_iterations = data.num_cpus > 1 ? 1500 : 0; + }); + return data; +} + +// Spinlock delay on iteration c. Returns new c. namespace { enum DelayMode { AGGRESSIVE, GENTLE }; }; @@ -154,22 +147,25 @@ static int Delay(int32_t c, DelayMode mode) { // gentle then spin only a few times before yielding. Aggressive spinning is // used to ensure that an Unlock() call, which must get the spin lock for // any thread to make progress gets it without undue delay. - int32_t limit = (mutex_globals.num_cpus > 1) ? - ((mode == AGGRESSIVE) ? 5000 : 250) : 0; + const int32_t limit = + GetMutexGlobals().num_cpus > 1 ? (mode == AGGRESSIVE ? 5000 : 250) : 0; if (c < limit) { - c++; // spin + // Spin. + c++; } else { ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0); - if (c == limit) { // yield once + if (c == limit) { + // Yield once. AbslInternalMutexYield(); c++; - } else { // then wait + } else { + // Then wait. absl::SleepFor(absl::Microseconds(10)); c = 0; } ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0); } - return (c); + return c; } // --------------------------Generic atomic ops @@ -1055,7 +1051,6 @@ static PerThreadSynch *DequeueAllWakeable(PerThreadSynch *head, // Try to remove thread s from the list of waiters on this mutex. // Does nothing if s is not on the waiter list. void Mutex::TryRemove(PerThreadSynch *s) { - SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); // acquire spinlock & lock if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait && @@ -1439,7 +1434,7 @@ void Mutex::AssertNotHeld() const { // Attempt to acquire *mu, and return whether successful. The implementation // may spin for a short while if the lock cannot be acquired immediately. static bool TryAcquireWithSpinning(std::atomic* mu) { - int c = mutex_globals.spinloop_iterations; + int c = GetMutexGlobals().spinloop_iterations; do { // do/while somewhat faster on AMD intptr_t v = mu->load(std::memory_order_relaxed); if ((v & (kMuReader|kMuEvent)) != 0) { @@ -1899,7 +1894,6 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) { } void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { - SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; intptr_t v = mu_.load(std::memory_order_relaxed); if ((v & kMuEvent) != 0) { @@ -2019,7 +2013,6 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { // or it is in the process of blocking on a condition variable; it must requeue // itself on the mutex/condvar to wait for its condition to become true. ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { - SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); this->AssertReaderHeld(); CheckForMutexCorruption(v, "Unlock"); @@ -2335,7 +2328,6 @@ void Mutex::Trans(MuHow how) { // It will later acquire the mutex with high probability. Otherwise, we // enqueue thread w on this mutex. void Mutex::Fer(PerThreadSynch *w) { - SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; ABSL_RAW_CHECK(w->waitp->cond == nullptr, "Mutex::Fer while waiting on Condition"); @@ -2434,7 +2426,6 @@ CondVar::~CondVar() { // Remove thread s from the list of waiters on this condition variable. void CondVar::Remove(PerThreadSynch *s) { - SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v; int c = 0; for (v = cv_.load(std::memory_order_relaxed);; @@ -2595,7 +2586,6 @@ void CondVar::Wakeup(PerThreadSynch *w) { } void CondVar::Signal() { - SchedulingGuard::ScopedDisable disable_rescheduling; ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); intptr_t v; int c = 0; -- cgit v1.2.3 From 38db52adb2eabc0969195b33b30763e0a1285ef9 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 1 Jul 2020 12:27:47 -0700 Subject: Export of internal Abseil changes -- 510cd0bc2ff9cf21e1e960264d179fa333a88612 by Derek Mauro : Removes the static initializer for VDSOSupport as requested by Chromium. The call is moved to InitializeSymbolizer(). PiperOrigin-RevId: 319275021 -- 0c91944889ad2bd10bc8080f4cd8083ca1d5de46 by Derek Mauro : Check for the lock_returned attribute before using it PiperOrigin-RevId: 319273193 -- 1001fa71bfb850f00502777f787aeff6e80654ca by Derek Mauro : Remove a no longer relevant MSVC code guard PiperOrigin-RevId: 319266085 -- a80caee79eb3f377c6bf97bec6b692c55169fe53 by Abseil Team : Bug fix to StrFormat %a rounding behavior for `long double`. PiperOrigin-RevId: 319238900 -- fdec318c449f1ca586145397099b03d973b738c4 by Abseil Team : Add test cases for absl::Time +/- absl::InfiniteDuration() == absl::Infinite{Future|Past}. PiperOrigin-RevId: 319223053 GitOrigin-RevId: 510cd0bc2ff9cf21e1e960264d179fa333a88612 Change-Id: I4b8932fb0ec6ab9c868450faf4ed837092a7c0c0 --- absl/base/thread_annotations.h | 5 ++ absl/debugging/internal/vdso_support.cc | 12 ---- absl/debugging/symbolize_elf.inc | 6 ++ absl/strings/cord.cc | 3 - absl/strings/internal/str_format/convert_test.cc | 82 ++++++++++++++++++++++ .../internal/str_format/float_conversion.cc | 14 ++-- absl/time/time_test.cc | 44 ++++++------ 7 files changed, 123 insertions(+), 43 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h index 5f51c0c2..6a7112df 100644 --- a/absl/base/thread_annotations.h +++ b/absl/base/thread_annotations.h @@ -34,6 +34,7 @@ #ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_ #define ABSL_BASE_THREAD_ANNOTATIONS_H_ +#include "absl/base/attributes.h" #include "absl/base/config.h" // TODO(mbonadei): Remove after the backward compatibility period. #include "absl/base/internal/thread_annotations.h" // IWYU pragma: export @@ -151,8 +152,12 @@ // Documents a function that returns a mutex without acquiring it. For example, // a public getter method that returns a pointer to a private mutex should // be annotated with ABSL_LOCK_RETURNED. +#if ABSL_HAVE_ATTRIBUTE(lock_returned) #define ABSL_LOCK_RETURNED(x) \ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lock_returned(x)) +#else +#define ABSL_LOCK_RETURNED(x) +#endif // ABSL_LOCKABLE // diff --git a/absl/debugging/internal/vdso_support.cc b/absl/debugging/internal/vdso_support.cc index 1e8a78ac..19deb3cf 100644 --- a/absl/debugging/internal/vdso_support.cc +++ b/absl/debugging/internal/vdso_support.cc @@ -175,18 +175,6 @@ int GetCPU() { return ret_code == 0 ? cpu : ret_code; } -// We need to make sure VDSOSupport::Init() is called before -// InitGoogle() does any setuid or chroot calls. If VDSOSupport -// is used in any global constructor, this will happen, since -// VDSOSupport's constructor calls Init. But if not, we need to -// ensure it here, with a global constructor of our own. This -// is an allowed exception to the normal rule against non-trivial -// global constructors. -static class VDSOInitHelper { - public: - VDSOInitHelper() { VDSOSupport::Init(); } -} vdso_init_helper; - } // namespace debugging_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/debugging/symbolize_elf.inc b/absl/debugging/symbolize_elf.inc index 328869f1..b7f8663c 100644 --- a/absl/debugging/symbolize_elf.inc +++ b/absl/debugging/symbolize_elf.inc @@ -83,6 +83,12 @@ ABSL_NAMESPACE_BEGIN static char *argv0_value = nullptr; void InitializeSymbolizer(const char *argv0) { +#ifdef ABSL_HAVE_VDSO_SUPPORT + // We need to make sure VDSOSupport::Init() is called before any setuid or + // chroot calls, so InitializeSymbolizer() should be called very early in the + // life of a program. + absl::debugging_internal::VDSOSupport::Init(); +#endif if (argv0_value != nullptr) { free(argv0_value); argv0_value = nullptr; diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc index 8ecffc4b..70c399c1 100644 --- a/absl/strings/cord.cc +++ b/absl/strings/cord.cc @@ -493,10 +493,7 @@ static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) { // -------------------------------------------------------------------- // Cord::InlineRep functions -// This will trigger LNK2005 in MSVC. -#ifndef COMPILER_MSVC constexpr unsigned char Cord::InlineRep::kMaxInline; -#endif // COMPILER_MSVC inline void Cord::InlineRep::set_data(const char* data, size_t n, bool nullify_tail) { diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 488d4cd4..5ee5fbc9 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -947,6 +947,88 @@ TEST_F(FormatConvertTest, DoubleRoundA) { EXPECT_EQ(format("%.21a", hex_value2), "0x1.081828384858600000000p+3"); } +TEST_F(FormatConvertTest, LongDoubleRoundA) { + if (std::numeric_limits::digits % 4 != 0) { + // This test doesn't really make sense to run on platforms where a long + // double has a different mantissa size (mod 4) than Prod, since then the + // leading digit will be formatted differently. + return; + } + const NativePrintfTraits &native_traits = VerifyNativeImplementation(); + std::string s; + const auto format = [&](const char *fmt, long double d) -> std::string & { + s.clear(); + FormatArgImpl args[1] = {FormatArgImpl(d)}; + AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args)); + if (native_traits.hex_float_has_glibc_rounding && + native_traits.hex_float_optimizes_leading_digit_bit_count) { + EXPECT_EQ(StrPrint(fmt, d), s); + } + return s; + }; + + // 0x8.8p+4 + const long double on_boundary_even = 136.0; + EXPECT_EQ(format("%.0La", on_boundary_even), "0x8p+4"); + EXPECT_EQ(format("%.1La", on_boundary_even), "0x8.8p+4"); + EXPECT_EQ(format("%.2La", on_boundary_even), "0x8.80p+4"); + EXPECT_EQ(format("%.3La", on_boundary_even), "0x8.800p+4"); + EXPECT_EQ(format("%.4La", on_boundary_even), "0x8.8000p+4"); + EXPECT_EQ(format("%.5La", on_boundary_even), "0x8.80000p+4"); + EXPECT_EQ(format("%.6La", on_boundary_even), "0x8.800000p+4"); + + // 0x9.8p+4 + const long double on_boundary_odd = 152.0; + EXPECT_EQ(format("%.0La", on_boundary_odd), "0xap+4"); + EXPECT_EQ(format("%.1La", on_boundary_odd), "0x9.8p+4"); + EXPECT_EQ(format("%.2La", on_boundary_odd), "0x9.80p+4"); + EXPECT_EQ(format("%.3La", on_boundary_odd), "0x9.800p+4"); + EXPECT_EQ(format("%.4La", on_boundary_odd), "0x9.8000p+4"); + EXPECT_EQ(format("%.5La", on_boundary_odd), "0x9.80000p+4"); + EXPECT_EQ(format("%.6La", on_boundary_odd), "0x9.800000p+4"); + + // 0x8.80001p+24 + const long double slightly_over = 142606352.0; + EXPECT_EQ(format("%.0La", slightly_over), "0x9p+24"); + EXPECT_EQ(format("%.1La", slightly_over), "0x8.8p+24"); + EXPECT_EQ(format("%.2La", slightly_over), "0x8.80p+24"); + EXPECT_EQ(format("%.3La", slightly_over), "0x8.800p+24"); + EXPECT_EQ(format("%.4La", slightly_over), "0x8.8000p+24"); + EXPECT_EQ(format("%.5La", slightly_over), "0x8.80001p+24"); + EXPECT_EQ(format("%.6La", slightly_over), "0x8.800010p+24"); + + // 0x8.7ffffp+24 + const long double slightly_under = 142606320.0; + EXPECT_EQ(format("%.0La", slightly_under), "0x8p+24"); + EXPECT_EQ(format("%.1La", slightly_under), "0x8.8p+24"); + EXPECT_EQ(format("%.2La", slightly_under), "0x8.80p+24"); + EXPECT_EQ(format("%.3La", slightly_under), "0x8.800p+24"); + EXPECT_EQ(format("%.4La", slightly_under), "0x8.8000p+24"); + EXPECT_EQ(format("%.5La", slightly_under), "0x8.7ffffp+24"); + EXPECT_EQ(format("%.6La", slightly_under), "0x8.7ffff0p+24"); + EXPECT_EQ(format("%.7La", slightly_under), "0x8.7ffff00p+24"); + + // 0xc.0828384858688000p+128 + const long double eights = 4094231060438608800781871108094404067328.0; + EXPECT_EQ(format("%.0La", eights), "0xcp+128"); + EXPECT_EQ(format("%.1La", eights), "0xc.1p+128"); + EXPECT_EQ(format("%.2La", eights), "0xc.08p+128"); + EXPECT_EQ(format("%.3La", eights), "0xc.083p+128"); + EXPECT_EQ(format("%.4La", eights), "0xc.0828p+128"); + EXPECT_EQ(format("%.5La", eights), "0xc.08284p+128"); + EXPECT_EQ(format("%.6La", eights), "0xc.082838p+128"); + EXPECT_EQ(format("%.7La", eights), "0xc.0828385p+128"); + EXPECT_EQ(format("%.8La", eights), "0xc.08283848p+128"); + EXPECT_EQ(format("%.9La", eights), "0xc.082838486p+128"); + EXPECT_EQ(format("%.10La", eights), "0xc.0828384858p+128"); + EXPECT_EQ(format("%.11La", eights), "0xc.08283848587p+128"); + EXPECT_EQ(format("%.12La", eights), "0xc.082838485868p+128"); + EXPECT_EQ(format("%.13La", eights), "0xc.0828384858688p+128"); + EXPECT_EQ(format("%.14La", eights), "0xc.08283848586880p+128"); + EXPECT_EQ(format("%.15La", eights), "0xc.082838485868800p+128"); + EXPECT_EQ(format("%.16La", eights), "0xc.0828384858688000p+128"); +} + // We don't actually store the results. This is just to exercise the rest of the // machinery. struct NullSink { diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index 6eb7b9fc..cafa479b 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -738,7 +738,8 @@ constexpr int HexFloatLeadingDigitSizeInBits() { // point that is not followed by 800000..., it disregards the parity and rounds // up if > 8 and rounds down if < 8. template -bool HexFloatNeedsRoundUp(Int mantissa, int final_nibble_displayed) { +bool HexFloatNeedsRoundUp(Int mantissa, int final_nibble_displayed, + uint8_t leading) { // If the last nibble (hex digit) to be displayed is the lowest on in the // mantissa then that means that we don't have any further nibbles to inform // rounding, so don't round. @@ -755,11 +756,10 @@ bool HexFloatNeedsRoundUp(Int mantissa, int final_nibble_displayed) { return mantissa_up_to_rounding_nibble_inclusive > eight; } // Nibble in question == 8. - uint8_t should_round_at_8 = - (final_nibble_displayed >= kTotalNibbles) - ? true - : (GetNibble(mantissa, final_nibble_displayed) % 2 == 1); - return should_round_at_8; + uint8_t round_if_odd = (final_nibble_displayed == kTotalNibbles) + ? leading + : GetNibble(mantissa, final_nibble_displayed); + return round_if_odd % 2 == 1; } // Stores values associated with a Float type needed by the FormatA @@ -788,7 +788,7 @@ void FormatARound(bool precision_specified, const FormatState &state, // Index of the last nibble that we could display given precision. int final_nibble_displayed = precision_specified ? std::max(0, (kTotalNibbles - state.precision)) : 0; - if (HexFloatNeedsRoundUp(*mantissa, final_nibble_displayed)) { + if (HexFloatNeedsRoundUp(*mantissa, final_nibble_displayed, *leading)) { // Need to round up. bool overflow = IncrementNibble(final_nibble_displayed, mantissa); *leading += (overflow ? 1 : 0); diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc index 6f89672c..b28a99fb 100644 --- a/absl/time/time_test.cc +++ b/absl/time/time_test.cc @@ -58,8 +58,7 @@ const char kZoneAbbrRE[] = "[A-Za-z]{3,4}|[-+][0-9]{2}([0-9]{2})?"; // timespec ts1, ts2; // EXPECT_THAT(ts1, TimespecMatcher(ts2)); MATCHER_P(TimespecMatcher, ts, "") { - if (ts.tv_sec == arg.tv_sec && ts.tv_nsec == arg.tv_nsec) - return true; + if (ts.tv_sec == arg.tv_sec && ts.tv_nsec == arg.tv_nsec) return true; *result_listener << "expected: {" << ts.tv_sec << ", " << ts.tv_nsec << "} "; *result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_nsec << "}"; return false; @@ -69,8 +68,7 @@ MATCHER_P(TimespecMatcher, ts, "") { // timeval tv1, tv2; // EXPECT_THAT(tv1, TimevalMatcher(tv2)); MATCHER_P(TimevalMatcher, tv, "") { - if (tv.tv_sec == arg.tv_sec && tv.tv_usec == arg.tv_usec) - return true; + if (tv.tv_sec == arg.tv_sec && tv.tv_usec == arg.tv_usec) return true; *result_listener << "expected: {" << tv.tv_sec << ", " << tv.tv_usec << "} "; *result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_usec << "}"; return false; @@ -103,7 +101,7 @@ TEST(Time, ValueSemantics) { EXPECT_EQ(a, b); EXPECT_EQ(a, c); EXPECT_EQ(b, c); - b = c; // Assignment + b = c; // Assignment EXPECT_EQ(a, b); EXPECT_EQ(a, c); EXPECT_EQ(b, c); @@ -228,6 +226,9 @@ TEST(Time, Infinity) { constexpr absl::Time t = absl::UnixEpoch(); // Any finite time. static_assert(t < ifuture, ""); static_assert(t > ipast, ""); + + EXPECT_EQ(ifuture, t + absl::InfiniteDuration()); + EXPECT_EQ(ipast, t - absl::InfiniteDuration()); } TEST(Time, FloorConversion) { @@ -358,19 +359,21 @@ TEST(Time, FloorConversion) { const int64_t min_plus_1 = std::numeric_limits::min() + 1; EXPECT_EQ(min_plus_1, absl::ToUnixSeconds(absl::FromUnixSeconds(min_plus_1))); EXPECT_EQ(std::numeric_limits::min(), - absl::ToUnixSeconds( - absl::FromUnixSeconds(min_plus_1) - absl::Nanoseconds(1) / 2)); + absl::ToUnixSeconds(absl::FromUnixSeconds(min_plus_1) - + absl::Nanoseconds(1) / 2)); // Tests flooring near positive infinity. EXPECT_EQ(std::numeric_limits::max(), - absl::ToUnixSeconds(absl::FromUnixSeconds( - std::numeric_limits::max()) + absl::Nanoseconds(1) / 2)); + absl::ToUnixSeconds( + absl::FromUnixSeconds(std::numeric_limits::max()) + + absl::Nanoseconds(1) / 2)); EXPECT_EQ(std::numeric_limits::max(), absl::ToUnixSeconds( absl::FromUnixSeconds(std::numeric_limits::max()))); EXPECT_EQ(std::numeric_limits::max() - 1, - absl::ToUnixSeconds(absl::FromUnixSeconds( - std::numeric_limits::max()) - absl::Nanoseconds(1) / 2)); + absl::ToUnixSeconds( + absl::FromUnixSeconds(std::numeric_limits::max()) - + absl::Nanoseconds(1) / 2)); } TEST(Time, RoundtripConversion) { @@ -1045,15 +1048,15 @@ TEST(Time, ConversionSaturation) { // Checks how TimeZone::At() saturates on infinities. auto ci = utc.At(absl::InfiniteFuture()); - EXPECT_CIVIL_INFO(ci, std::numeric_limits::max(), 12, 31, 23, - 59, 59, 0, false); + EXPECT_CIVIL_INFO(ci, std::numeric_limits::max(), 12, 31, 23, 59, 59, + 0, false); EXPECT_EQ(absl::InfiniteDuration(), ci.subsecond); EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(ci.cs)); EXPECT_EQ(365, absl::GetYearDay(ci.cs)); EXPECT_STREQ("-00", ci.zone_abbr); // artifact of TimeZone::At() ci = utc.At(absl::InfinitePast()); - EXPECT_CIVIL_INFO(ci, std::numeric_limits::min(), 1, 1, 0, 0, - 0, 0, false); + EXPECT_CIVIL_INFO(ci, std::numeric_limits::min(), 1, 1, 0, 0, 0, 0, + false); EXPECT_EQ(-absl::InfiniteDuration(), ci.subsecond); EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(ci.cs)); EXPECT_EQ(1, absl::GetYearDay(ci.cs)); @@ -1171,14 +1174,13 @@ TEST(Time, LegacyDateTime) { const int kMin = std::numeric_limits::min(); absl::Time t; - t = absl::FromDateTime(std::numeric_limits::max(), - kMax, kMax, kMax, kMax, kMax, utc); + t = absl::FromDateTime(std::numeric_limits::max(), kMax, + kMax, kMax, kMax, kMax, utc); EXPECT_EQ("infinite-future", absl::FormatTime(ymdhms, t, utc)); // no overflow - t = absl::FromDateTime(std::numeric_limits::min(), - kMin, kMin, kMin, kMin, kMin, utc); - EXPECT_EQ("infinite-past", - absl::FormatTime(ymdhms, t, utc)); // no overflow + t = absl::FromDateTime(std::numeric_limits::min(), kMin, + kMin, kMin, kMin, kMin, utc); + EXPECT_EQ("infinite-past", absl::FormatTime(ymdhms, t, utc)); // no overflow // Check normalization. EXPECT_TRUE(absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, utc).normalized); -- cgit v1.2.3 From 55c04eb9203a93db1c0816adddf3182b45da5384 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 13 Jul 2020 12:10:09 -0700 Subject: Export of internal Abseil changes -- 69b3ab092ee0fef3d27f589e709280c341f006c6 by Greg Falcon : Import of CCTZ from GitHub. PiperOrigin-RevId: 321005878 -- 3a4038cd0cea6455453a7ae82f2de7e91d7e2bc1 by Abseil Team : Google-internal changes only. PiperOrigin-RevId: 320994821 -- f9d9a93782924df6ffc351a271c239ca4bdff3c8 by Derek Mauro : Update Linux latest toolchains, most notably to GCC 10.1 This create a new "hybrid" docker image that includes the latest versions of both GCC and LLVM. Since the LLVM build targets Debian 10, but Debian 10 uses an older version of libstdc++ that doesn't have full C++20 support, the easiest solution is to use the GCC/Debian 10 base image from DockerHub and copy LLVM into it. This also includes fixes to get the build working with the new toolchains. PiperOrigin-RevId: 320991795 -- 43129cd66dc4439b36d85030800a3929f20d9f86 by Abseil Team : Rollback import of CCTZ from GitHub (breaks MSAN tests) - e87b391f0d10ae9c3d2e70e4a3633337d2c5e643 handle "slim" TZif files in TimeZoneInfo::ExtendTransitio... by Bradley White <14679271+devbww@users.noreply.github.com> PiperOrigin-RevId: 320978767 -- 2a343a55f297d433c1521920f0bd20ddd2dc71e8 by Derek Mauro : Use ABSL_HAVE_ATTRIBUTE in thread_annotations.h PiperOrigin-RevId: 320956378 -- f6f3e8333c9ef6e6441586be6587bbfb1c8c8127 by Gennadiy Rozental : Import of CCTZ from GitHub. PiperOrigin-RevId: 320952592 -- 3cc2bcce3533ac1233c0536232b07eea45fe8ed0 by Derek Mauro : Internal change PiperOrigin-RevId: 320862698 -- 4e22066476744609e42c475b55e3cbd874f04c39 by Gennadiy Rozental : Internal change PiperOrigin-RevId: 320461277 GitOrigin-RevId: 69b3ab092ee0fef3d27f589e709280c341f006c6 Change-Id: I36f547711e7078d52f2e0a1ff3f4c903056a2b9e --- WORKSPACE | 6 +- absl/BUILD.bazel | 5 +- absl/base/internal/low_level_scheduling.h | 28 +++ absl/base/thread_annotations.h | 128 ++++++---- .../container/fixed_array_exception_safety_test.cc | 3 +- absl/strings/internal/str_format/convert_test.cc | 3 +- absl/synchronization/mutex.cc | 33 ++- absl/time/internal/cctz/src/time_zone_info.cc | 257 +++++++++++---------- absl/time/internal/cctz/src/time_zone_info.h | 9 +- ci/linux_clang-latest_libstdcxx_bazel.sh | 3 +- ci/linux_docker_containers.sh | 4 +- 11 files changed, 291 insertions(+), 188 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/WORKSPACE b/WORKSPACE index 1a1da6c5..96338199 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -20,9 +20,9 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # GoogleTest/GoogleMock framework. Used by most unit-tests. http_archive( name = "com_google_googletest", - urls = ["https://github.com/google/googletest/archive/011959aafddcd30611003de96cfd8d7a7685c700.zip"], # 2020-05-14T00:36:05Z - strip_prefix = "googletest-011959aafddcd30611003de96cfd8d7a7685c700", - sha256 = "6a5d7d63cd6e0ad2a7130471105a3b83799a7a2b14ef7ec8d742b54f01a4833c", + urls = ["https://github.com/google/googletest/archive/8567b09290fe402cf01923e2131c5635b8ed851b.zip"], # 2020-06-12T22:24:28Z + strip_prefix = "googletest-8567b09290fe402cf01923e2131c5635b8ed851b", + sha256 = "9a8a166eb6a56c7b3d7b19dc2c946fe4778fd6f21c7a12368ad3b836d8f1be48", ) # Google benchmark. diff --git a/absl/BUILD.bazel b/absl/BUILD.bazel index e45d15a5..1019ab5e 100644 --- a/absl/BUILD.bazel +++ b/absl/BUILD.bazel @@ -61,5 +61,8 @@ config_setting( config_setting( name = "wasm", - values = {"cpu": "wasm32"}, + values = { + "cpu": "wasm32", + }, + visibility = [":__subpackages__"], ) diff --git a/absl/base/internal/low_level_scheduling.h b/absl/base/internal/low_level_scheduling.h index ed0b4bfa..6ef79fbf 100644 --- a/absl/base/internal/low_level_scheduling.h +++ b/absl/base/internal/low_level_scheduling.h @@ -18,6 +18,7 @@ #ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_ #define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_ +#include "absl/base/internal/raw_logging.h" #include "absl/base/internal/scheduling_mode.h" #include "absl/base/macros.h" @@ -29,6 +30,13 @@ extern "C" void __google_enable_rescheduling(bool disable_result); namespace absl { ABSL_NAMESPACE_BEGIN +class CondVar; +class Mutex; + +namespace synchronization_internal { +int MutexDelay(int32_t c, int mode); +} // namespace synchronization_internal + namespace base_internal { class SchedulingHelper; // To allow use of SchedulingGuard. @@ -76,9 +84,23 @@ class SchedulingGuard { bool disabled; }; + // A scoped helper to enable rescheduling temporarily. + // REQUIRES: destructor must run in same thread as constructor. + class ScopedEnable { + public: + ScopedEnable(); + ~ScopedEnable(); + + private: + int scheduling_disabled_depth_; + }; + // Access to SchedulingGuard is explicitly permitted. + friend class absl::CondVar; + friend class absl::Mutex; friend class SchedulingHelper; friend class SpinLock; + friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode); SchedulingGuard(const SchedulingGuard&) = delete; SchedulingGuard& operator=(const SchedulingGuard&) = delete; @@ -100,6 +122,12 @@ inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) { return; } +inline SchedulingGuard::ScopedEnable::ScopedEnable() + : scheduling_disabled_depth_(0) {} +inline SchedulingGuard::ScopedEnable::~ScopedEnable() { + ABSL_RAW_CHECK(scheduling_disabled_depth_ == 0, "disable unused warning"); +} + } // namespace base_internal ABSL_NAMESPACE_END } // namespace absl diff --git a/absl/base/thread_annotations.h b/absl/base/thread_annotations.h index 6a7112df..e23fff1d 100644 --- a/absl/base/thread_annotations.h +++ b/absl/base/thread_annotations.h @@ -39,12 +39,6 @@ // TODO(mbonadei): Remove after the backward compatibility period. #include "absl/base/internal/thread_annotations.h" // IWYU pragma: export -#if defined(__clang__) -#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) __attribute__((x)) -#else -#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) // no-op -#endif - // ABSL_GUARDED_BY() // // Documents if a shared field or global variable needs to be protected by a @@ -62,8 +56,11 @@ // int p1_ ABSL_GUARDED_BY(mu_); // ... // }; -#define ABSL_GUARDED_BY(x) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(guarded_by(x)) +#if ABSL_HAVE_ATTRIBUTE(guarded_by) +#define ABSL_GUARDED_BY(x) __attribute__((guarded_by(x))) +#else +#define ABSL_GUARDED_BY(x) +#endif // ABSL_PT_GUARDED_BY() // @@ -85,8 +82,11 @@ // // `q_`, guarded by `mu1_`, points to a shared memory location that is // // guarded by `mu2_`: // int *q_ ABSL_GUARDED_BY(mu1_) ABSL_PT_GUARDED_BY(mu2_); -#define ABSL_PT_GUARDED_BY(x) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(pt_guarded_by(x)) +#if ABSL_HAVE_ATTRIBUTE(pt_guarded_by) +#define ABSL_PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x))) +#else +#define ABSL_PT_GUARDED_BY(x) +#endif // ABSL_ACQUIRED_AFTER() / ABSL_ACQUIRED_BEFORE() // @@ -103,11 +103,17 @@ // // Mutex m1_; // Mutex m2_ ABSL_ACQUIRED_AFTER(m1_); -#define ABSL_ACQUIRED_AFTER(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_after(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(acquired_after) +#define ABSL_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) +#else +#define ABSL_ACQUIRED_AFTER(...) +#endif -#define ABSL_ACQUIRED_BEFORE(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_before(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(acquired_before) +#define ABSL_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) +#else +#define ABSL_ACQUIRED_BEFORE(...) +#endif // ABSL_EXCLUSIVE_LOCKS_REQUIRED() / ABSL_SHARED_LOCKS_REQUIRED() // @@ -132,20 +138,30 @@ // // void foo() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... } // void bar() const ABSL_SHARED_LOCKS_REQUIRED(mu1, mu2) { ... } -#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \ - exclusive_locks_required(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(exclusive_locks_required) +#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \ + __attribute__((exclusive_locks_required(__VA_ARGS__))) +#else +#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) +#endif +#if ABSL_HAVE_ATTRIBUTE(shared_locks_required) #define ABSL_SHARED_LOCKS_REQUIRED(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_locks_required(__VA_ARGS__)) + __attribute__((shared_locks_required(__VA_ARGS__))) +#else +#define ABSL_SHARED_LOCKS_REQUIRED(...) +#endif // ABSL_LOCKS_EXCLUDED() // // Documents the locks acquired in the body of the function. These locks // cannot be held when calling this function (as Abseil's `Mutex` locks are // non-reentrant). -#define ABSL_LOCKS_EXCLUDED(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(locks_excluded(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(locks_excluded) +#define ABSL_LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) +#else +#define ABSL_LOCKS_EXCLUDED(...) +#endif // ABSL_LOCK_RETURNED() // @@ -153,8 +169,7 @@ // a public getter method that returns a pointer to a private mutex should // be annotated with ABSL_LOCK_RETURNED. #if ABSL_HAVE_ATTRIBUTE(lock_returned) -#define ABSL_LOCK_RETURNED(x) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lock_returned(x)) +#define ABSL_LOCK_RETURNED(x) __attribute__((lock_returned(x))) #else #define ABSL_LOCK_RETURNED(x) #endif @@ -162,7 +177,11 @@ // ABSL_LOCKABLE // // Documents if a class/type is a lockable type (such as the `Mutex` class). -#define ABSL_LOCKABLE ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lockable) +#if ABSL_HAVE_ATTRIBUTE(lockable) +#define ABSL_LOCKABLE __attribute__((lockable)) +#else +#define ABSL_LOCKABLE +#endif // ABSL_SCOPED_LOCKABLE // @@ -171,30 +190,43 @@ // acquired, and the destructor should use `UNLOCK_FUNCTION()` with no // arguments; the analysis will assume that the destructor unlocks whatever the // constructor locked. -#define ABSL_SCOPED_LOCKABLE \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(scoped_lockable) +#if ABSL_HAVE_ATTRIBUTE(scoped_lockable) +#define ABSL_SCOPED_LOCKABLE __attribute__((scoped_lockable)) +#else +#define ABSL_SCOPED_LOCKABLE +#endif // ABSL_EXCLUSIVE_LOCK_FUNCTION() // // Documents functions that acquire a lock in the body of a function, and do // not release it. -#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \ - exclusive_lock_function(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(exclusive_lock_function) +#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \ + __attribute__((exclusive_lock_function(__VA_ARGS__))) +#else +#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) +#endif // ABSL_SHARED_LOCK_FUNCTION() // // Documents functions that acquire a shared (reader) lock in the body of a // function, and do not release it. +#if ABSL_HAVE_ATTRIBUTE(shared_lock_function) #define ABSL_SHARED_LOCK_FUNCTION(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_lock_function(__VA_ARGS__)) + __attribute__((shared_lock_function(__VA_ARGS__))) +#else +#define ABSL_SHARED_LOCK_FUNCTION(...) +#endif // ABSL_UNLOCK_FUNCTION() // // Documents functions that expect a lock to be held on entry to the function, // and release it in the body of the function. -#define ABSL_UNLOCK_FUNCTION(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(unlock_function(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(unlock_function) +#define ABSL_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) +#else +#define ABSL_UNLOCK_FUNCTION(...) +#endif // ABSL_EXCLUSIVE_TRYLOCK_FUNCTION() / ABSL_SHARED_TRYLOCK_FUNCTION() // @@ -204,31 +236,49 @@ // success, or `false` for functions that return `false` on success. The second // argument specifies the mutex that is locked on success. If unspecified, this // mutex is assumed to be `this`. +#if ABSL_HAVE_ATTRIBUTE(exclusive_trylock_function) #define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \ - exclusive_trylock_function(__VA_ARGS__)) + __attribute__((exclusive_trylock_function(__VA_ARGS__))) +#else +#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...) +#endif -#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \ - shared_trylock_function(__VA_ARGS__)) +#if ABSL_HAVE_ATTRIBUTE(shared_trylock_function) +#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \ + __attribute__((shared_trylock_function(__VA_ARGS__))) +#else +#define ABSL_SHARED_TRYLOCK_FUNCTION(...) +#endif // ABSL_ASSERT_EXCLUSIVE_LOCK() / ABSL_ASSERT_SHARED_LOCK() // // Documents functions that dynamically check to see if a lock is held, and fail // if it is not held. +#if ABSL_HAVE_ATTRIBUTE(assert_exclusive_lock) #define ABSL_ASSERT_EXCLUSIVE_LOCK(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_exclusive_lock(__VA_ARGS__)) + __attribute__((assert_exclusive_lock(__VA_ARGS__))) +#else +#define ABSL_ASSERT_EXCLUSIVE_LOCK(...) +#endif +#if ABSL_HAVE_ATTRIBUTE(assert_shared_lock) #define ABSL_ASSERT_SHARED_LOCK(...) \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_shared_lock(__VA_ARGS__)) + __attribute__((assert_shared_lock(__VA_ARGS__))) +#else +#define ABSL_ASSERT_SHARED_LOCK(...) +#endif // ABSL_NO_THREAD_SAFETY_ANALYSIS // // Turns off thread safety checking within the body of a particular function. // This annotation is used to mark functions that are known to be correct, but // the locking behavior is more complicated than the analyzer can handle. +#if ABSL_HAVE_ATTRIBUTE(no_thread_safety_analysis) #define ABSL_NO_THREAD_SAFETY_ANALYSIS \ - ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(no_thread_safety_analysis) + __attribute__((no_thread_safety_analysis)) +#else +#define ABSL_NO_THREAD_SAFETY_ANALYSIS +#endif //------------------------------------------------------------------------------ // Tool-Supplied Annotations diff --git a/absl/container/fixed_array_exception_safety_test.cc b/absl/container/fixed_array_exception_safety_test.cc index a5bb009d..e5f59299 100644 --- a/absl/container/fixed_array_exception_safety_test.cc +++ b/absl/container/fixed_array_exception_safety_test.cc @@ -150,8 +150,7 @@ TEST(FixedArrayExceptionSafety, InitListConstructorWithAlloc) { template testing::AssertionResult ReadMemory(FixedArrT* fixed_arr) { - // Marked volatile to prevent optimization. Used for running asan tests. - volatile int sum = 0; + int sum = 0; for (const auto& thrower : *fixed_arr) { sum += thrower.Get(); } diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 5ee5fbc9..634ee78b 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -1155,7 +1155,8 @@ TEST_F(FormatConvertTest, IntAsDouble) { {__LINE__, StrPrint("%.12a", dx), "%.12a"}, }; if (native_traits.hex_float_uses_minimal_precision_when_not_specified) { - expect.push_back({__LINE__, StrPrint("%12a", dx), "%12a"}); + Expectation ex = {__LINE__, StrPrint("%12a", dx), "%12a"}; + expect.push_back(ex); } for (const Expectation &e : expect) { SCOPED_TRACE(e.line); diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index c7968f06..aafeb674 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -59,6 +59,7 @@ using absl::base_internal::CurrentThreadIdentityIfPresent; using absl::base_internal::PerThreadSynch; +using absl::base_internal::SchedulingGuard; using absl::base_internal::ThreadIdentity; using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity; using absl::synchronization_internal::GraphCycles; @@ -141,7 +142,9 @@ static const MutexGlobals& GetMutexGlobals() { namespace { enum DelayMode { AGGRESSIVE, GENTLE }; }; -static int Delay(int32_t c, DelayMode mode) { + +namespace synchronization_internal { +int MutexDelay(int32_t c, int mode) { // If this a uniprocessor, only yield/sleep. Otherwise, if the mode is // aggressive then spin many times before yielding. If the mode is // gentle then spin only a few times before yielding. Aggressive spinning is @@ -153,6 +156,7 @@ static int Delay(int32_t c, DelayMode mode) { // Spin. c++; } else { + SchedulingGuard::ScopedEnable enable_rescheduling; ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0); if (c == limit) { // Yield once. @@ -167,6 +171,7 @@ static int Delay(int32_t c, DelayMode mode) { } return c; } +} // namespace synchronization_internal // --------------------------Generic atomic ops // Ensure that "(*pv & bits) == bits" by doing an atomic update of "*pv" to @@ -1051,6 +1056,7 @@ static PerThreadSynch *DequeueAllWakeable(PerThreadSynch *head, // Try to remove thread s from the list of waiters on this mutex. // Does nothing if s is not on the waiter list. void Mutex::TryRemove(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); // acquire spinlock & lock if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait && @@ -1115,7 +1121,7 @@ ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) { this->TryRemove(s); int c = 0; while (s->next != nullptr) { - c = Delay(c, GENTLE); + c = synchronization_internal::MutexDelay(c, GENTLE); this->TryRemove(s); } if (kDebugMode) { @@ -1894,6 +1900,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) { } void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; intptr_t v = mu_.load(std::memory_order_relaxed); if ((v & kMuEvent) != 0) { @@ -1995,7 +2002,8 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { ABSL_RAW_CHECK( waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors, "detected illegal recursion into Mutex code"); - c = Delay(c, GENTLE); // delay, then try again + // delay, then try again + c = synchronization_internal::MutexDelay(c, GENTLE); } ABSL_RAW_CHECK( waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors, @@ -2013,6 +2021,7 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) { // or it is in the process of blocking on a condition variable; it must requeue // itself on the mutex/condvar to wait for its condition to become true. ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v = mu_.load(std::memory_order_relaxed); this->AssertReaderHeld(); CheckForMutexCorruption(v, "Unlock"); @@ -2289,7 +2298,8 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { mu_.store(nv, std::memory_order_release); break; // out of for(;;)-loop } - c = Delay(c, AGGRESSIVE); // aggressive here; no one can proceed till we do + // aggressive here; no one can proceed till we do + c = synchronization_internal::MutexDelay(c, AGGRESSIVE); } // end of for(;;)-loop if (wake_list != kPerThreadSynchNull) { @@ -2328,6 +2338,7 @@ void Mutex::Trans(MuHow how) { // It will later acquire the mutex with high probability. Otherwise, we // enqueue thread w on this mutex. void Mutex::Fer(PerThreadSynch *w) { + SchedulingGuard::ScopedDisable disable_rescheduling; int c = 0; ABSL_RAW_CHECK(w->waitp->cond == nullptr, "Mutex::Fer while waiting on Condition"); @@ -2377,7 +2388,7 @@ void Mutex::Fer(PerThreadSynch *w) { return; } } - c = Delay(c, GENTLE); + c = synchronization_internal::MutexDelay(c, GENTLE); } } @@ -2426,6 +2437,7 @@ CondVar::~CondVar() { // Remove thread s from the list of waiters on this condition variable. void CondVar::Remove(PerThreadSynch *s) { + SchedulingGuard::ScopedDisable disable_rescheduling; intptr_t v; int c = 0; for (v = cv_.load(std::memory_order_relaxed);; @@ -2454,7 +2466,8 @@ void CondVar::Remove(PerThreadSynch *s) { std::memory_order_release); return; } else { - c = Delay(c, GENTLE); // try again after a delay + // try again after a delay + c = synchronization_internal::MutexDelay(c, GENTLE); } } } @@ -2487,7 +2500,7 @@ static void CondVarEnqueue(SynchWaitParams *waitp) { !cv_word->compare_exchange_weak(v, v | kCvSpin, std::memory_order_acquire, std::memory_order_relaxed)) { - c = Delay(c, GENTLE); + c = synchronization_internal::MutexDelay(c, GENTLE); v = cv_word->load(std::memory_order_relaxed); } ABSL_RAW_CHECK(waitp->thread->waitp == nullptr, "waiting when shouldn't be"); @@ -2586,6 +2599,7 @@ void CondVar::Wakeup(PerThreadSynch *w) { } void CondVar::Signal() { + SchedulingGuard::ScopedDisable disable_rescheduling; ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0); intptr_t v; int c = 0; @@ -2618,7 +2632,7 @@ void CondVar::Signal() { ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); return; } else { - c = Delay(c, GENTLE); + c = synchronization_internal::MutexDelay(c, GENTLE); } } ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); @@ -2655,7 +2669,8 @@ void CondVar::SignalAll () { ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); return; } else { - c = Delay(c, GENTLE); // try again after a delay + // try again after a delay + c = synchronization_internal::MutexDelay(c, GENTLE); } } ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0); diff --git a/absl/time/internal/cctz/src/time_zone_info.cc b/absl/time/internal/cctz/src/time_zone_info.cc index 665fb424..7ccda113 100644 --- a/absl/time/internal/cctz/src/time_zone_info.cc +++ b/absl/time/internal/cctz/src/time_zone_info.cc @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -83,6 +82,27 @@ const std::int_least32_t kSecsPerYear[2] = { 366 * kSecsPerDay, }; +// Convert a cctz::weekday to a POSIX TZ weekday number (0==Sun, ..., 6=Sat). +inline int ToPosixWeekday(weekday wd) { + switch (wd) { + case weekday::sunday: + return 0; + case weekday::monday: + return 1; + case weekday::tuesday: + return 2; + case weekday::wednesday: + return 3; + case weekday::thursday: + return 4; + case weekday::friday: + return 5; + case weekday::saturday: + return 6; + } + return 0; /*NOTREACHED*/ +} + // Single-byte, unsigned numeric values are encoded directly. inline std::uint_fast8_t Decode8(const char* cp) { return static_cast(*cp) & 0xff; @@ -188,15 +208,13 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { tt.is_dst = false; tt.abbr_index = 0; - // We temporarily add some redundant, contemporary (2013 through 2023) + // We temporarily add some redundant, contemporary (2015 through 2025) // transitions for performance reasons. See TimeZoneInfo::LocalTime(). // TODO: Fix the performance issue and remove the extra transitions. transitions_.clear(); transitions_.reserve(12); for (const std::int_fast64_t unix_time : { - -(1LL << 59), // BIG_BANG - 1356998400LL, // 2013-01-01T00:00:00+00:00 - 1388534400LL, // 2014-01-01T00:00:00+00:00 + -(1LL << 59), // a "first half" transition 1420070400LL, // 2015-01-01T00:00:00+00:00 1451606400LL, // 2016-01-01T00:00:00+00:00 1483228800LL, // 2017-01-01T00:00:00+00:00 @@ -206,7 +224,8 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { 1609459200LL, // 2021-01-01T00:00:00+00:00 1640995200LL, // 2022-01-01T00:00:00+00:00 1672531200LL, // 2023-01-01T00:00:00+00:00 - 2147483647LL, // 2^31 - 1 + 1704067200LL, // 2024-01-01T00:00:00+00:00 + 1735689600LL, // 2025-01-01T00:00:00+00:00 }) { Transition& tr(*transitions_.emplace(transitions_.end())); tr.unix_time = unix_time; @@ -217,8 +236,8 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) { default_transition_type_ = 0; abbreviations_ = FixedOffsetToAbbr(offset); - abbreviations_.append(1, '\0'); // add NUL - future_spec_.clear(); // never needed for a fixed-offset zone + abbreviations_.append(1, '\0'); + future_spec_.clear(); // never needed for a fixed-offset zone extended_ = false; tt.civil_max = LocalTime(seconds::max().count(), tt).cs; @@ -259,21 +278,6 @@ std::size_t TimeZoneInfo::Header::DataLength(std::size_t time_len) const { return len; } -// Check that the TransitionType has the expected offset/is_dst/abbreviation. -void TimeZoneInfo::CheckTransition(const std::string& name, - const TransitionType& tt, - std::int_fast32_t offset, bool is_dst, - const std::string& abbr) const { - if (tt.utc_offset != offset || tt.is_dst != is_dst || - &abbreviations_[tt.abbr_index] != abbr) { - std::clog << name << ": Transition" - << " offset=" << tt.utc_offset << "/" - << (tt.is_dst ? "DST" : "STD") - << "/abbr=" << &abbreviations_[tt.abbr_index] - << " does not match POSIX spec '" << future_spec_ << "'\n"; - } -} - // zic(8) can generate no-op transitions when a zone changes rules at an // instant when there is actually no discontinuity. So we check whether // two transitions have equivalent types (same offset/is_dst/abbr). @@ -282,117 +286,108 @@ bool TimeZoneInfo::EquivTransitions(std::uint_fast8_t tt1_index, if (tt1_index == tt2_index) return true; const TransitionType& tt1(transition_types_[tt1_index]); const TransitionType& tt2(transition_types_[tt2_index]); - if (tt1.is_dst != tt2.is_dst) return false; if (tt1.utc_offset != tt2.utc_offset) return false; + if (tt1.is_dst != tt2.is_dst) return false; if (tt1.abbr_index != tt2.abbr_index) return false; return true; } +// Find/make a transition type with these attributes. +bool TimeZoneInfo::GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, + const std::string& abbr, + std::uint_fast8_t* index) { + std::size_t type_index = 0; + std::size_t abbr_index = abbreviations_.size(); + for (; type_index != transition_types_.size(); ++type_index) { + const TransitionType& tt(transition_types_[type_index]); + const char* tt_abbr = &abbreviations_[tt.abbr_index]; + if (tt_abbr == abbr) abbr_index = tt.abbr_index; + if (tt.utc_offset == utc_offset && tt.is_dst == is_dst) { + if (abbr_index == tt.abbr_index) break; // reuse + } + } + if (type_index > 255 || abbr_index > 255) { + // No index space (8 bits) available for a new type or abbreviation. + return false; + } + if (type_index == transition_types_.size()) { + TransitionType& tt(*transition_types_.emplace(transition_types_.end())); + tt.utc_offset = static_cast(utc_offset); + tt.is_dst = is_dst; + if (abbr_index == abbreviations_.size()) { + abbreviations_.append(abbr); + abbreviations_.append(1, '\0'); + } + tt.abbr_index = static_cast(abbr_index); + } + *index = static_cast(type_index); + return true; +} + // Use the POSIX-TZ-environment-variable-style string to handle times // in years after the last transition stored in the zoneinfo data. -void TimeZoneInfo::ExtendTransitions(const std::string& name, - const Header& hdr) { +bool TimeZoneInfo::ExtendTransitions() { extended_ = false; - bool extending = !future_spec_.empty(); + if (future_spec_.empty()) return true; // last transition prevails PosixTimeZone posix; - if (extending && !ParsePosixSpec(future_spec_, &posix)) { - std::clog << name << ": Failed to parse '" << future_spec_ << "'\n"; - extending = false; - } - - if (extending && posix.dst_abbr.empty()) { // std only - // The future specification should match the last/default transition, - // and that means that handling the future will fall out naturally. - std::uint_fast8_t index = default_transition_type_; - if (hdr.timecnt != 0) index = transitions_[hdr.timecnt - 1].type_index; - const TransitionType& tt(transition_types_[index]); - CheckTransition(name, tt, posix.std_offset, false, posix.std_abbr); - extending = false; - } - - if (extending && hdr.timecnt < 2) { - std::clog << name << ": Too few transitions for POSIX spec\n"; - extending = false; - } - - if (!extending) { - // Ensure that there is always a transition in the second half of the - // time line (the BIG_BANG transition is in the first half) so that the - // signed difference between a civil_second and the civil_second of its - // previous transition is always representable, without overflow. - const Transition& last(transitions_.back()); - if (last.unix_time < 0) { - const std::uint_fast8_t type_index = last.type_index; - Transition& tr(*transitions_.emplace(transitions_.end())); - tr.unix_time = 2147483647; // 2038-01-19T03:14:07+00:00 - tr.type_index = type_index; - } - return; // last transition wins + if (!ParsePosixSpec(future_spec_, &posix)) return false; + + // Find transition type for the future std specification. + std::uint_fast8_t std_ti; + if (!GetTransitionType(posix.std_offset, false, posix.std_abbr, &std_ti)) + return false; + + if (posix.dst_abbr.empty()) { // std only + // The future specification should match the last transition, and + // that means that handling the future will fall out naturally. + return EquivTransitions(transitions_.back().type_index, std_ti); } + // Find transition type for the future dst specification. + std::uint_fast8_t dst_ti; + if (!GetTransitionType(posix.dst_offset, true, posix.dst_abbr, &dst_ti)) + return false; + // Extend the transitions for an additional 400 years using the // future specification. Years beyond those can be handled by // mapping back to a cycle-equivalent year within that range. - // zic(8) should probably do this so that we don't have to. - // TODO: Reduce the extension by the number of compatible - // transitions already in place. - transitions_.reserve(hdr.timecnt + 400 * 2 + 1); - transitions_.resize(hdr.timecnt + 400 * 2); + // We may need two additional transitions for the current year. + transitions_.reserve(transitions_.size() + 400 * 2 + 2); extended_ = true; - // The future specification should match the last two transitions, - // and those transitions should have different is_dst flags. Note - // that nothing says the UTC offset used by the is_dst transition - // must be greater than that used by the !is_dst transition. (See - // Europe/Dublin, for example.) - const Transition* tr0 = &transitions_[hdr.timecnt - 1]; - const Transition* tr1 = &transitions_[hdr.timecnt - 2]; - const TransitionType* tt0 = &transition_types_[tr0->type_index]; - const TransitionType* tt1 = &transition_types_[tr1->type_index]; - const TransitionType& dst(tt0->is_dst ? *tt0 : *tt1); - const TransitionType& std(tt0->is_dst ? *tt1 : *tt0); - CheckTransition(name, dst, posix.dst_offset, true, posix.dst_abbr); - CheckTransition(name, std, posix.std_offset, false, posix.std_abbr); - - // Add the transitions to tr1 and back to tr0 for each extra year. - last_year_ = LocalTime(tr0->unix_time, *tt0).cs.year(); + const Transition& last(transitions_.back()); + const std::int_fast64_t last_time = last.unix_time; + const TransitionType& last_tt(transition_types_[last.type_index]); + last_year_ = LocalTime(last_time, last_tt).cs.year(); bool leap_year = IsLeap(last_year_); - const civil_day jan1(last_year_, 1, 1); - std::int_fast64_t jan1_time = civil_second(jan1) - civil_second(); - int jan1_weekday = (static_cast(get_weekday(jan1)) + 1) % 7; - Transition* tr = &transitions_[hdr.timecnt]; // next trans to fill - if (LocalTime(tr1->unix_time, *tt1).cs.year() != last_year_) { - // Add a single extra transition to align to a calendar year. - transitions_.resize(transitions_.size() + 1); - assert(tr == &transitions_[hdr.timecnt]); // no reallocation - const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start); - std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1); - tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset; - tr++->type_index = tr1->type_index; - tr0 = &transitions_[hdr.timecnt]; - tr1 = &transitions_[hdr.timecnt - 1]; - tt0 = &transition_types_[tr0->type_index]; - tt1 = &transition_types_[tr1->type_index]; - } - const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start); - const PosixTransition& pt0(tt0->is_dst ? posix.dst_start : posix.dst_end); - for (const year_t limit = last_year_ + 400; last_year_ < limit;) { - last_year_ += 1; // an additional year of generated transitions + const civil_second jan1(last_year_); + std::int_fast64_t jan1_time = jan1 - civil_second(); + int jan1_weekday = ToPosixWeekday(get_weekday(jan1)); + + Transition dst = {0, dst_ti, civil_second(), civil_second()}; + Transition std = {0, std_ti, civil_second(), civil_second()}; + for (const year_t limit = last_year_ + 400;; ++last_year_) { + auto dst_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_start); + auto std_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_end); + dst.unix_time = jan1_time + dst_trans_off - posix.std_offset; + std.unix_time = jan1_time + std_trans_off - posix.dst_offset; + const auto* ta = dst.unix_time < std.unix_time ? &dst : &std; + const auto* tb = dst.unix_time < std.unix_time ? &std : &dst; + if (last_time < tb->unix_time) { + if (last_time < ta->unix_time) transitions_.push_back(*ta); + transitions_.push_back(*tb); + } + if (last_year_ == limit) break; jan1_time += kSecsPerYear[leap_year]; jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7; - leap_year = !leap_year && IsLeap(last_year_); - std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1); - tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset; - tr++->type_index = tr1->type_index; - std::int_fast64_t tr0_offset = TransOffset(leap_year, jan1_weekday, pt0); - tr->unix_time = jan1_time + tr0_offset - tt1->utc_offset; - tr++->type_index = tr0->type_index; - } - assert(tr == &transitions_[0] + transitions_.size()); + leap_year = !leap_year && IsLeap(last_year_ + 1); + } + + return true; } -bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { +bool TimeZoneInfo::Load(ZoneInfoSource* zip) { // Read and validate the header. tzhead tzh; if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false; @@ -430,7 +425,7 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { const char* bp = tbuf.data(); // Decode and validate the transitions. - transitions_.reserve(hdr.timecnt + 2); // We might add a couple. + transitions_.reserve(hdr.timecnt + 2); transitions_.resize(hdr.timecnt); for (std::size_t i = 0; i != hdr.timecnt; ++i) { transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp); @@ -449,6 +444,7 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { } // Decode and validate the transition types. + transition_types_.reserve(hdr.typecnt + 2); transition_types_.resize(hdr.typecnt); for (std::size_t i = 0; i != hdr.typecnt; ++i) { transition_types_[i].utc_offset = @@ -475,6 +471,7 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { } // Copy all the abbreviations. + abbreviations_.reserve(hdr.charcnt + 10); abbreviations_.assign(bp, hdr.charcnt); bp += hdr.charcnt; @@ -525,19 +522,29 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) { transitions_.resize(hdr.timecnt); // Ensure that there is always a transition in the first half of the - // time line (the second half is handled in ExtendTransitions()) so that - // the signed difference between a civil_second and the civil_second of - // its previous transition is always representable, without overflow. - // A contemporary zic will usually have already done this for us. + // time line (the second half is handled below) so that the signed + // difference between a civil_second and the civil_second of its + // previous transition is always representable, without overflow. if (transitions_.empty() || transitions_.front().unix_time >= 0) { Transition& tr(*transitions_.emplace(transitions_.begin())); - tr.unix_time = -(1LL << 59); // see tz/zic.c "BIG_BANG" + tr.unix_time = -(1LL << 59); // -18267312070-10-26T17:01:52+00:00 tr.type_index = default_transition_type_; - hdr.timecnt += 1; } // Extend the transitions using the future specification. - ExtendTransitions(name, hdr); + if (!ExtendTransitions()) return false; + + // Ensure that there is always a transition in the second half of the + // time line (the first half is handled above) so that the signed + // difference between a civil_second and the civil_second of its + // previous transition is always representable, without overflow. + const Transition& last(transitions_.back()); + if (last.unix_time < 0) { + const std::uint_fast8_t type_index = last.type_index; + Transition& tr(*transitions_.emplace(transitions_.end())); + tr.unix_time = 2147483647; // 2038-01-19T03:14:07+00:00 + tr.type_index = type_index; + } // Compute the local civil time for each transition and the preceding // second. These will be used for reverse conversions in MakeTime(). @@ -723,7 +730,7 @@ bool TimeZoneInfo::Load(const std::string& name) { if (auto zip = AndroidZoneInfoSource::Open(name)) return zip; return nullptr; }); - return zip != nullptr && Load(name, zip.get()); + return zip != nullptr && Load(zip.get()); } // BreakTime() translation for a particular transition type. @@ -897,8 +904,8 @@ bool TimeZoneInfo::NextTransition(const time_point& tp, const Transition* begin = &transitions_[0]; const Transition* end = begin + transitions_.size(); if (begin->unix_time <= -(1LL << 59)) { - // Do not report the BIG_BANG found in recent zoneinfo data as it is - // really a sentinel, not a transition. See tz/zic.c. + // Do not report the BIG_BANG found in some zoneinfo data as it is + // really a sentinel, not a transition. See pre-2018f tz/zic.c. ++begin; } std::int_fast64_t unix_time = ToUnixSeconds(tp); @@ -923,8 +930,8 @@ bool TimeZoneInfo::PrevTransition(const time_point& tp, const Transition* begin = &transitions_[0]; const Transition* end = begin + transitions_.size(); if (begin->unix_time <= -(1LL << 59)) { - // Do not report the BIG_BANG found in recent zoneinfo data as it is - // really a sentinel, not a transition. See tz/zic.c. + // Do not report the BIG_BANG found in some zoneinfo data as it is + // really a sentinel, not a transition. See pre-2018f tz/zic.c. ++begin; } std::int_fast64_t unix_time = ToUnixSeconds(tp); diff --git a/absl/time/internal/cctz/src/time_zone_info.h b/absl/time/internal/cctz/src/time_zone_info.h index 2a10c06c..068e34be 100644 --- a/absl/time/internal/cctz/src/time_zone_info.h +++ b/absl/time/internal/cctz/src/time_zone_info.h @@ -95,15 +95,14 @@ class TimeZoneInfo : public TimeZoneIf { std::size_t DataLength(std::size_t time_len) const; }; - void CheckTransition(const std::string& name, const TransitionType& tt, - std::int_fast32_t offset, bool is_dst, - const std::string& abbr) const; + bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst, + const std::string& abbr, std::uint_fast8_t* index); bool EquivTransitions(std::uint_fast8_t tt1_index, std::uint_fast8_t tt2_index) const; - void ExtendTransitions(const std::string& name, const Header& hdr); + bool ExtendTransitions(); bool ResetToBuiltinUTC(const seconds& offset); - bool Load(const std::string& name, ZoneInfoSource* zip); + bool Load(ZoneInfoSource* zip); // Helpers for BreakTime() and MakeTime(). time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time, diff --git a/ci/linux_clang-latest_libstdcxx_bazel.sh b/ci/linux_clang-latest_libstdcxx_bazel.sh index 0192ee49..4e490676 100755 --- a/ci/linux_clang-latest_libstdcxx_bazel.sh +++ b/ci/linux_clang-latest_libstdcxx_bazel.sh @@ -71,15 +71,16 @@ for std in ${STD}; do -e CC="/opt/llvm/clang/bin/clang" \ -e BAZEL_COMPILER="llvm" \ -e BAZEL_CXXOPTS="-std=${std}" \ - -e CPLUS_INCLUDE_PATH="/usr/include/c++/8" \ ${DOCKER_EXTRA_ARGS:-} \ ${DOCKER_CONTAINER} \ /usr/local/bin/bazel test ... \ --compilation_mode="${compilation_mode}" \ + --copt="--gcc-toolchain=/usr/local" \ --copt="${exceptions_mode}" \ --copt=-Werror \ --define="absl=1" \ --keep_going \ + --linkopt="--gcc-toolchain=/usr/local" \ --show_timestamps \ --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \ --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \ diff --git a/ci/linux_docker_containers.sh b/ci/linux_docker_containers.sh index b652071f..483ce2a2 100644 --- a/ci/linux_docker_containers.sh +++ b/ci/linux_docker_containers.sh @@ -16,6 +16,6 @@ # Test scripts should source this file to get the identifiers. readonly LINUX_ALPINE_CONTAINER="gcr.io/google.com/absl-177019/alpine:20191016" -readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200706" -readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20200319" +readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20200710" +readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20200710" readonly LINUX_GCC_49_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20191018" -- cgit v1.2.3 From 4b2fbb4adba905eede6c61b4494acfdb660a3bb7 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Mon, 12 Oct 2020 10:33:47 -0700 Subject: Export of internal Abseil changes -- a5af5874c1c5cc02bd2a748d455321f82b6f2a93 by Andy Getzendanner : fix compile fails with asan and -Wredundant-decls Import of https://github.com/abseil/abseil-cpp/pull/801 PiperOrigin-RevId: 336693223 -- ed9df42ab2b742386c6692c2bed015374c919d9c by Derek Mauro : Fix integer conversion warning Fixes #814 PiperOrigin-RevId: 336651814 -- 0ab4c23884e72dce17b67c1eb520f9dbb802565d by Derek Mauro : Internal change PiperOrigin-RevId: 336585378 -- eba0e3dccd52a6e91bcff84075bef0affc650b74 by Matt Kulukundis : Add bitset operations to Futex helper. PiperOrigin-RevId: 336409368 -- 8b0709a8b4500bf5f0af4b602d76a298d81645e8 by Abseil Team : Fix code indentation in a comment. PiperOrigin-RevId: 336368167 -- bc3961c87a7e7760c10319a5b0349c279f7ae3ad by Samuel Benzaquen : Improve performance of the registry: - Reduce contention - Reduce memory usage for each flag by `6*sizeof(void*)`. - Replace one immortal allocation per-flag with a single one for all the flags - Slightly improve single-threaded performance by avoiding the std::map indirections. PiperOrigin-RevId: 336365904 -- 264ad9f28f935aad8b6b1437f8bf804fa9104346 by Abseil Team : Fix typo in comment on absl::Condition. PiperOrigin-RevId: 336311680 -- b5b808a8c75ca0df7b09eff9a423ec171d80f771 by Derek Mauro : Add missing Apache license headers PiperOrigin-RevId: 336294980 -- 89446c3a4793df8b95060385cf3e219357c3db1d by Andy Soffer : Internal changes PiperOrigin-RevId: 336287465 -- 57c8be4e294881bc79a6a44b8e4bf7ecbb19b9b9 by Matt Kulukundis : Extract Futex from an implementation detail of Wait to a private interface. PiperOrigin-RevId: 336123209 GitOrigin-RevId: a5af5874c1c5cc02bd2a748d455321f82b6f2a93 Change-Id: Ie5a0ebe28e571814e3e11d4c05ca308523ccf311 --- CMake/AbseilDll.cmake | 1 + absl/algorithm/container.h | 2 +- absl/base/internal/unscaledcycleclock.cc | 4 +- absl/container/internal/layout_test.cc | 560 ++++++++++++--------- absl/container/internal/raw_hash_set_test.cc | 7 +- absl/debugging/internal/symbolize.h | 8 +- absl/flags/BUILD.bazel | 2 + absl/flags/flag_benchmark.cc | 33 ++ absl/flags/internal/registry.h | 5 +- absl/flags/parse.cc | 5 + absl/flags/reflection.cc | 68 ++- absl/hash/hash_test.cc | 8 +- absl/hash/internal/city.cc | 18 +- absl/hash/internal/city.h | 2 +- absl/random/internal/generate_real_test.cc | 4 +- absl/strings/cord_test.cc | 14 + absl/strings/internal/str_format/arg.cc | 14 + absl/strings/internal/str_format/arg.h | 14 + absl/strings/internal/str_format/bind.cc | 14 + absl/strings/internal/str_format/bind.h | 14 + absl/strings/internal/str_format/bind_test.cc | 14 + absl/strings/internal/str_format/checker.h | 14 + absl/strings/internal/str_format/checker_test.cc | 14 + absl/strings/internal/str_format/convert_test.cc | 14 + .../internal/str_format/float_conversion.cc | 14 + .../strings/internal/str_format/float_conversion.h | 14 + absl/strings/internal/str_format/parser.cc | 14 + absl/strings/internal/str_format/parser.h | 14 + absl/strings/internal/str_format/parser_test.cc | 14 + absl/strings/str_format_test.cc | 13 + absl/synchronization/BUILD.bazel | 1 + absl/synchronization/CMakeLists.txt | 1 + absl/synchronization/internal/futex.h | 139 +++++ absl/synchronization/internal/kernel_timeout.h | 3 +- absl/synchronization/internal/waiter.cc | 70 +-- absl/synchronization/mutex.cc | 9 +- absl/synchronization/mutex.h | 10 +- absl/time/clock.cc | 4 +- absl/time/duration.cc | 2 +- absl/time/time.cc | 7 +- absl/time/time.h | 12 +- absl/time/time_test.cc | 12 +- absl/types/internal/variant.h | 2 +- absl/types/variant_test.cc | 6 +- 44 files changed, 817 insertions(+), 397 deletions(-) create mode 100644 absl/synchronization/internal/futex.h (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake index cf6a8c9a..d67c4399 100644 --- a/CMake/AbseilDll.cmake +++ b/CMake/AbseilDll.cmake @@ -250,6 +250,7 @@ set(ABSL_INTERNAL_DLL_FILES "synchronization/notification.h" "synchronization/internal/create_thread_identity.cc" "synchronization/internal/create_thread_identity.h" + "synchronization/internal/futex.h" "synchronization/internal/graphcycles.cc" "synchronization/internal/graphcycles.h" "synchronization/internal/kernel_timeout.h" diff --git a/absl/algorithm/container.h b/absl/algorithm/container.h index bb3d1c7c..09b91f74 100644 --- a/absl/algorithm/container.h +++ b/absl/algorithm/container.h @@ -93,7 +93,7 @@ using ContainerPointerType = // std::foo(begin(c), end(c)); // becomes // std::foo(container_algorithm_internal::begin(c), -// container_algorithm_internal::end(c)); +// container_algorithm_internal::end(c)); // These are meant for internal use only. template diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc index f1e7bbef..1545288c 100644 --- a/absl/base/internal/unscaledcycleclock.cc +++ b/absl/base/internal/unscaledcycleclock.cc @@ -123,9 +123,7 @@ double UnscaledCycleClock::Frequency() { #pragma intrinsic(__rdtsc) -int64_t UnscaledCycleClock::Now() { - return __rdtsc(); -} +int64_t UnscaledCycleClock::Now() { return __rdtsc(); } double UnscaledCycleClock::Frequency() { return base_internal::NominalCPUFrequency(); diff --git a/absl/container/internal/layout_test.cc b/absl/container/internal/layout_test.cc index 757272f1..1d7158ff 100644 --- a/absl/container/internal/layout_test.cc +++ b/absl/container/internal/layout_test.cc @@ -128,8 +128,10 @@ TEST(Layout, ElementTypes) { { using L = Layout; SameType, L::ElementTypes>(); - SameType, decltype(L::Partial())::ElementTypes>(); - SameType, decltype(L::Partial(0))::ElementTypes>(); + SameType, + decltype(L::Partial())::ElementTypes>(); + SameType, + decltype(L::Partial(0))::ElementTypes>(); } { using L = Layout; @@ -368,18 +370,21 @@ TEST(Layout, PointerByIndex) { { using L = Layout; EXPECT_EQ(0, Distance(p, Type(L::Partial().Pointer<0>(p)))); - EXPECT_EQ(0, Distance(p, Type(L::Partial(3).Pointer<0>(p)))); + EXPECT_EQ(0, + Distance(p, Type(L::Partial(3).Pointer<0>(p)))); EXPECT_EQ(0, Distance(p, Type(L(3).Pointer<0>(p)))); } { using L = Layout; EXPECT_EQ(0, Distance(p, Type(L::Partial().Pointer<0>(p)))); - EXPECT_EQ(0, Distance(p, Type(L::Partial(3).Pointer<0>(p)))); - EXPECT_EQ(12, Distance(p, Type(L::Partial(3).Pointer<1>(p)))); EXPECT_EQ(0, - Distance(p, Type(L::Partial(3, 5).Pointer<0>(p)))); + Distance(p, Type(L::Partial(3).Pointer<0>(p)))); EXPECT_EQ(12, - Distance(p, Type(L::Partial(3, 5).Pointer<1>(p)))); + Distance(p, Type(L::Partial(3).Pointer<1>(p)))); + EXPECT_EQ( + 0, Distance(p, Type(L::Partial(3, 5).Pointer<0>(p)))); + EXPECT_EQ( + 12, Distance(p, Type(L::Partial(3, 5).Pointer<1>(p)))); EXPECT_EQ(0, Distance(p, Type(L(3, 5).Pointer<0>(p)))); EXPECT_EQ(12, Distance(p, Type(L(3, 5).Pointer<1>(p)))); } @@ -387,39 +392,44 @@ TEST(Layout, PointerByIndex) { using L = Layout; EXPECT_EQ(0, Distance(p, Type(L::Partial().Pointer<0>(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(0).Pointer<0>(p)))); - EXPECT_EQ(0, Distance(p, Type(L::Partial(0).Pointer<1>(p)))); + EXPECT_EQ(0, + Distance(p, Type(L::Partial(0).Pointer<1>(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(1).Pointer<0>(p)))); - EXPECT_EQ(4, Distance(p, Type(L::Partial(1).Pointer<1>(p)))); + EXPECT_EQ(4, + Distance(p, Type(L::Partial(1).Pointer<1>(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(5).Pointer<0>(p)))); - EXPECT_EQ(8, Distance(p, Type(L::Partial(5).Pointer<1>(p)))); + EXPECT_EQ(8, + Distance(p, Type(L::Partial(5).Pointer<1>(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(0, 0).Pointer<0>(p)))); - EXPECT_EQ(0, - Distance(p, Type(L::Partial(0, 0).Pointer<1>(p)))); + EXPECT_EQ( + 0, Distance(p, Type(L::Partial(0, 0).Pointer<1>(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(0, 0).Pointer<2>(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(1, 0).Pointer<0>(p)))); - EXPECT_EQ(4, - Distance(p, Type(L::Partial(1, 0).Pointer<1>(p)))); + EXPECT_EQ( + 4, Distance(p, Type(L::Partial(1, 0).Pointer<1>(p)))); EXPECT_EQ(8, Distance(p, Type(L::Partial(1, 0).Pointer<2>(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(5, 3).Pointer<0>(p)))); - EXPECT_EQ(8, - Distance(p, Type(L::Partial(5, 3).Pointer<1>(p)))); + EXPECT_EQ( + 8, Distance(p, Type(L::Partial(5, 3).Pointer<1>(p)))); EXPECT_EQ(24, Distance(p, Type(L::Partial(5, 3).Pointer<2>(p)))); EXPECT_EQ( 0, Distance(p, Type(L::Partial(0, 0, 0).Pointer<0>(p)))); EXPECT_EQ( - 0, Distance(p, Type(L::Partial(0, 0, 0).Pointer<1>(p)))); + 0, + Distance(p, Type(L::Partial(0, 0, 0).Pointer<1>(p)))); EXPECT_EQ( 0, Distance(p, Type(L::Partial(0, 0, 0).Pointer<2>(p)))); EXPECT_EQ( 0, Distance(p, Type(L::Partial(1, 0, 0).Pointer<0>(p)))); EXPECT_EQ( - 4, Distance(p, Type(L::Partial(1, 0, 0).Pointer<1>(p)))); + 4, + Distance(p, Type(L::Partial(1, 0, 0).Pointer<1>(p)))); EXPECT_EQ( 8, Distance(p, Type(L::Partial(1, 0, 0).Pointer<2>(p)))); EXPECT_EQ( @@ -428,7 +438,8 @@ TEST(Layout, PointerByIndex) { 24, Distance(p, Type(L::Partial(5, 3, 1).Pointer<2>(p)))); EXPECT_EQ( - 8, Distance(p, Type(L::Partial(5, 3, 1).Pointer<1>(p)))); + 8, + Distance(p, Type(L::Partial(5, 3, 1).Pointer<1>(p)))); EXPECT_EQ(0, Distance(p, Type(L(5, 3, 1).Pointer<0>(p)))); EXPECT_EQ(24, Distance(p, Type(L(5, 3, 1).Pointer<2>(p)))); EXPECT_EQ(8, Distance(p, Type(L(5, 3, 1).Pointer<1>(p)))); @@ -439,75 +450,78 @@ TEST(Layout, PointerByType) { alignas(max_align_t) const unsigned char p[100] = {}; { using L = Layout; - EXPECT_EQ(0, - Distance(p, Type(L::Partial().Pointer(p)))); - EXPECT_EQ(0, - Distance(p, Type(L::Partial(3).Pointer(p)))); + EXPECT_EQ( + 0, Distance(p, Type(L::Partial().Pointer(p)))); + EXPECT_EQ( + 0, + Distance(p, Type(L::Partial(3).Pointer(p)))); EXPECT_EQ(0, Distance(p, Type(L(3).Pointer(p)))); } { using L = Layout; - EXPECT_EQ(0, Distance(p, Type(L::Partial().Pointer(p)))); - EXPECT_EQ(0, - Distance(p, Type(L::Partial(0).Pointer(p)))); - EXPECT_EQ(0, - Distance(p, Type(L::Partial(0).Pointer(p)))); - EXPECT_EQ(0, - Distance(p, Type(L::Partial(1).Pointer(p)))); - EXPECT_EQ(4, - Distance(p, Type(L::Partial(1).Pointer(p)))); - EXPECT_EQ(0, - Distance(p, Type(L::Partial(5).Pointer(p)))); - EXPECT_EQ(8, - Distance(p, Type(L::Partial(5).Pointer(p)))); EXPECT_EQ( - 0, Distance(p, Type(L::Partial(0, 0).Pointer(p)))); + 0, Distance(p, Type(L::Partial().Pointer(p)))); EXPECT_EQ( - 0, Distance(p, Type(L::Partial(0, 0).Pointer(p)))); + 0, Distance(p, Type(L::Partial(0).Pointer(p)))); EXPECT_EQ( 0, - Distance(p, Type(L::Partial(0, 0).Pointer(p)))); - EXPECT_EQ( - 0, Distance(p, Type(L::Partial(1, 0).Pointer(p)))); + Distance(p, Type(L::Partial(0).Pointer(p)))); EXPECT_EQ( - 4, Distance(p, Type(L::Partial(1, 0).Pointer(p)))); + 0, Distance(p, Type(L::Partial(1).Pointer(p)))); EXPECT_EQ( - 8, - Distance(p, Type(L::Partial(1, 0).Pointer(p)))); + 4, + Distance(p, Type(L::Partial(1).Pointer(p)))); EXPECT_EQ( - 0, Distance(p, Type(L::Partial(5, 3).Pointer(p)))); + 0, Distance(p, Type(L::Partial(5).Pointer(p)))); EXPECT_EQ( - 8, Distance(p, Type(L::Partial(5, 3).Pointer(p)))); + 8, + Distance(p, Type(L::Partial(5).Pointer(p)))); EXPECT_EQ( - 24, - Distance(p, Type(L::Partial(5, 3).Pointer(p)))); + 0, + Distance(p, Type(L::Partial(0, 0).Pointer(p)))); + EXPECT_EQ(0, Distance(p, Type( + L::Partial(0, 0).Pointer(p)))); EXPECT_EQ( 0, - Distance(p, Type(L::Partial(0, 0, 0).Pointer(p)))); + Distance(p, Type(L::Partial(0, 0).Pointer(p)))); EXPECT_EQ( 0, - Distance(p, Type(L::Partial(0, 0, 0).Pointer(p)))); - EXPECT_EQ(0, Distance(p, Type( - L::Partial(0, 0, 0).Pointer(p)))); + Distance(p, Type(L::Partial(1, 0).Pointer(p)))); + EXPECT_EQ(4, Distance(p, Type( + L::Partial(1, 0).Pointer(p)))); + EXPECT_EQ( + 8, + Distance(p, Type(L::Partial(1, 0).Pointer(p)))); EXPECT_EQ( 0, - Distance(p, Type(L::Partial(1, 0, 0).Pointer(p)))); + Distance(p, Type(L::Partial(5, 3).Pointer(p)))); + EXPECT_EQ(8, Distance(p, Type( + L::Partial(5, 3).Pointer(p)))); EXPECT_EQ( - 4, - Distance(p, Type(L::Partial(1, 0, 0).Pointer(p)))); + 24, + Distance(p, Type(L::Partial(5, 3).Pointer(p)))); + EXPECT_EQ(0, Distance(p, Type( + L::Partial(0, 0, 0).Pointer(p)))); + EXPECT_EQ(0, Distance(p, Type( + L::Partial(0, 0, 0).Pointer(p)))); + EXPECT_EQ(0, Distance(p, Type( + L::Partial(0, 0, 0).Pointer(p)))); + EXPECT_EQ(0, Distance(p, Type( + L::Partial(1, 0, 0).Pointer(p)))); + EXPECT_EQ(4, Distance(p, Type( + L::Partial(1, 0, 0).Pointer(p)))); EXPECT_EQ(8, Distance(p, Type( L::Partial(1, 0, 0).Pointer(p)))); - EXPECT_EQ( - 0, - Distance(p, Type(L::Partial(5, 3, 1).Pointer(p)))); + EXPECT_EQ(0, Distance(p, Type( + L::Partial(5, 3, 1).Pointer(p)))); EXPECT_EQ(24, Distance(p, Type( L::Partial(5, 3, 1).Pointer(p)))); - EXPECT_EQ( - 8, - Distance(p, Type(L::Partial(5, 3, 1).Pointer(p)))); + EXPECT_EQ(8, Distance(p, Type( + L::Partial(5, 3, 1).Pointer(p)))); EXPECT_EQ(24, Distance(p, Type(L(5, 3, 1).Pointer(p)))); - EXPECT_EQ(8, Distance(p, Type(L(5, 3, 1).Pointer(p)))); + EXPECT_EQ( + 8, Distance(p, Type(L(5, 3, 1).Pointer(p)))); } } @@ -548,15 +562,18 @@ TEST(Layout, MutablePointerByIndex) { EXPECT_EQ(8, Distance(p, Type(L::Partial(5, 3).Pointer<1>(p)))); EXPECT_EQ(24, Distance(p, Type(L::Partial(5, 3).Pointer<2>(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(0, 0, 0).Pointer<0>(p)))); - EXPECT_EQ(0, Distance(p, Type(L::Partial(0, 0, 0).Pointer<1>(p)))); + EXPECT_EQ(0, + Distance(p, Type(L::Partial(0, 0, 0).Pointer<1>(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(0, 0, 0).Pointer<2>(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(1, 0, 0).Pointer<0>(p)))); - EXPECT_EQ(4, Distance(p, Type(L::Partial(1, 0, 0).Pointer<1>(p)))); + EXPECT_EQ(4, + Distance(p, Type(L::Partial(1, 0, 0).Pointer<1>(p)))); EXPECT_EQ(8, Distance(p, Type(L::Partial(1, 0, 0).Pointer<2>(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(5, 3, 1).Pointer<0>(p)))); EXPECT_EQ(24, Distance(p, Type(L::Partial(5, 3, 1).Pointer<2>(p)))); - EXPECT_EQ(8, Distance(p, Type(L::Partial(5, 3, 1).Pointer<1>(p)))); + EXPECT_EQ(8, + Distance(p, Type(L::Partial(5, 3, 1).Pointer<1>(p)))); EXPECT_EQ(0, Distance(p, Type(L(5, 3, 1).Pointer<0>(p)))); EXPECT_EQ(24, Distance(p, Type(L(5, 3, 1).Pointer<2>(p)))); EXPECT_EQ(8, Distance(p, Type(L(5, 3, 1).Pointer<1>(p)))); @@ -568,48 +585,61 @@ TEST(Layout, MutablePointerByType) { { using L = Layout; EXPECT_EQ(0, Distance(p, Type(L::Partial().Pointer(p)))); - EXPECT_EQ(0, Distance(p, Type(L::Partial(3).Pointer(p)))); + EXPECT_EQ(0, + Distance(p, Type(L::Partial(3).Pointer(p)))); EXPECT_EQ(0, Distance(p, Type(L(3).Pointer(p)))); } { using L = Layout; EXPECT_EQ(0, Distance(p, Type(L::Partial().Pointer(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(0).Pointer(p)))); - EXPECT_EQ(0, Distance(p, Type(L::Partial(0).Pointer(p)))); + EXPECT_EQ(0, + Distance(p, Type(L::Partial(0).Pointer(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(1).Pointer(p)))); - EXPECT_EQ(4, Distance(p, Type(L::Partial(1).Pointer(p)))); + EXPECT_EQ(4, + Distance(p, Type(L::Partial(1).Pointer(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(5).Pointer(p)))); - EXPECT_EQ(8, Distance(p, Type(L::Partial(5).Pointer(p)))); - EXPECT_EQ(0, Distance(p, Type(L::Partial(0, 0).Pointer(p)))); - EXPECT_EQ(0, Distance(p, Type(L::Partial(0, 0).Pointer(p)))); + EXPECT_EQ(8, + Distance(p, Type(L::Partial(5).Pointer(p)))); + EXPECT_EQ(0, + Distance(p, Type(L::Partial(0, 0).Pointer(p)))); + EXPECT_EQ( + 0, Distance(p, Type(L::Partial(0, 0).Pointer(p)))); EXPECT_EQ(0, Distance(p, Type(L::Partial(0, 0).Pointer(p)))); - EXPECT_EQ(0, Distance(p, Type(L::Partial(1, 0).Pointer(p)))); - EXPECT_EQ(4, Distance(p, Type(L::Partial(1, 0).Pointer(p)))); + EXPECT_EQ(0, + Distance(p, Type(L::Partial(1, 0).Pointer(p)))); + EXPECT_EQ( + 4, Distance(p, Type(L::Partial(1, 0).Pointer(p)))); EXPECT_EQ(8, Distance(p, Type(L::Partial(1, 0).Pointer(p)))); - EXPECT_EQ(0, Distance(p, Type(L::Partial(5, 3).Pointer(p)))); - EXPECT_EQ(8, Distance(p, Type(L::Partial(5, 3).Pointer(p)))); + EXPECT_EQ(0, + Distance(p, Type(L::Partial(5, 3).Pointer(p)))); + EXPECT_EQ( + 8, Distance(p, Type(L::Partial(5, 3).Pointer(p)))); EXPECT_EQ(24, Distance(p, Type(L::Partial(5, 3).Pointer(p)))); - EXPECT_EQ(0, - Distance(p, Type(L::Partial(0, 0, 0).Pointer(p)))); - EXPECT_EQ(0, - Distance(p, Type(L::Partial(0, 0, 0).Pointer(p)))); + EXPECT_EQ( + 0, Distance(p, Type(L::Partial(0, 0, 0).Pointer(p)))); + EXPECT_EQ( + 0, + Distance(p, Type(L::Partial(0, 0, 0).Pointer(p)))); EXPECT_EQ( 0, Distance(p, Type(L::Partial(0, 0, 0).Pointer(p)))); - EXPECT_EQ(0, - Distance(p, Type(L::Partial(1, 0, 0).Pointer(p)))); - EXPECT_EQ(4, - Distance(p, Type(L::Partial(1, 0, 0).Pointer(p)))); + EXPECT_EQ( + 0, Distance(p, Type(L::Partial(1, 0, 0).Pointer(p)))); + EXPECT_EQ( + 4, + Distance(p, Type(L::Partial(1, 0, 0).Pointer(p)))); EXPECT_EQ( 8, Distance(p, Type(L::Partial(1, 0, 0).Pointer(p)))); - EXPECT_EQ(0, - Distance(p, Type(L::Partial(5, 3, 1).Pointer(p)))); + EXPECT_EQ( + 0, Distance(p, Type(L::Partial(5, 3, 1).Pointer(p)))); EXPECT_EQ( 24, Distance(p, Type(L::Partial(5, 3, 1).Pointer(p)))); - EXPECT_EQ(8, - Distance(p, Type(L::Partial(5, 3, 1).Pointer(p)))); + EXPECT_EQ( + 8, + Distance(p, Type(L::Partial(5, 3, 1).Pointer(p)))); EXPECT_EQ(0, Distance(p, Type(L(5, 3, 1).Pointer(p)))); EXPECT_EQ(24, Distance(p, Type(L(5, 3, 1).Pointer(p)))); EXPECT_EQ(8, Distance(p, Type(L(5, 3, 1).Pointer(p)))); @@ -790,67 +820,72 @@ TEST(Layout, SliceByIndexData) { { using L = Layout; EXPECT_EQ( - 0, - Distance(p, Type>(L::Partial(0).Slice<0>(p)).data())); + 0, Distance( + p, Type>(L::Partial(0).Slice<0>(p)).data())); EXPECT_EQ( - 0, - Distance(p, Type>(L::Partial(3).Slice<0>(p)).data())); - EXPECT_EQ(0, Distance(p, Type>(L(3).Slice<0>(p)).data())); + 0, Distance( + p, Type>(L::Partial(3).Slice<0>(p)).data())); + EXPECT_EQ(0, + Distance(p, Type>(L(3).Slice<0>(p)).data())); } { using L = Layout; EXPECT_EQ( - 0, - Distance(p, Type>(L::Partial(3).Slice<0>(p)).data())); + 0, Distance( + p, Type>(L::Partial(3).Slice<0>(p)).data())); EXPECT_EQ( 0, - Distance(p, - Type>(L::Partial(3, 5).Slice<0>(p)).data())); + Distance( + p, Type>(L::Partial(3, 5).Slice<0>(p)).data())); EXPECT_EQ( 12, - Distance(p, - Type>(L::Partial(3, 5).Slice<1>(p)).data())); - EXPECT_EQ(0, - Distance(p, Type>(L(3, 5).Slice<0>(p)).data())); - EXPECT_EQ(12, - Distance(p, Type>(L(3, 5).Slice<1>(p)).data())); + Distance( + p, Type>(L::Partial(3, 5).Slice<1>(p)).data())); + EXPECT_EQ( + 0, Distance(p, Type>(L(3, 5).Slice<0>(p)).data())); + EXPECT_EQ( + 12, Distance(p, Type>(L(3, 5).Slice<1>(p)).data())); } { using L = Layout; EXPECT_EQ( - 0, - Distance(p, Type>(L::Partial(0).Slice<0>(p)).data())); - EXPECT_EQ( - 0, - Distance(p, Type>(L::Partial(1).Slice<0>(p)).data())); + 0, Distance( + p, Type>(L::Partial(0).Slice<0>(p)).data())); EXPECT_EQ( - 0, - Distance(p, Type>(L::Partial(5).Slice<0>(p)).data())); + 0, Distance( + p, Type>(L::Partial(1).Slice<0>(p)).data())); EXPECT_EQ( 0, Distance( - p, Type>(L::Partial(0, 0).Slice<0>(p)).data())); + p, Type>(L::Partial(5).Slice<0>(p)).data())); EXPECT_EQ( 0, - Distance(p, - Type>(L::Partial(0, 0).Slice<1>(p)).data())); + Distance( + p, Type>(L::Partial(0, 0).Slice<0>(p)).data())); EXPECT_EQ( - 0, Distance( - p, Type>(L::Partial(1, 0).Slice<0>(p)).data())); + 0, + Distance( + p, Type>(L::Partial(0, 0).Slice<1>(p)).data())); + EXPECT_EQ( + 0, + Distance( + p, Type>(L::Partial(1, 0).Slice<0>(p)).data())); EXPECT_EQ( 4, - Distance(p, - Type>(L::Partial(1, 0).Slice<1>(p)).data())); + Distance( + p, Type>(L::Partial(1, 0).Slice<1>(p)).data())); EXPECT_EQ( - 0, Distance( - p, Type>(L::Partial(5, 3).Slice<0>(p)).data())); + 0, + Distance( + p, Type>(L::Partial(5, 3).Slice<0>(p)).data())); EXPECT_EQ( 8, - Distance(p, - Type>(L::Partial(5, 3).Slice<1>(p)).data())); + Distance( + p, Type>(L::Partial(5, 3).Slice<1>(p)).data())); EXPECT_EQ( 0, Distance( - p, Type>(L::Partial(0, 0, 0).Slice<0>(p)).data())); + p, + Type>(L::Partial(0, 0, 0).Slice<0>(p)).data())); EXPECT_EQ( 0, Distance( @@ -864,7 +899,8 @@ TEST(Layout, SliceByIndexData) { EXPECT_EQ( 0, Distance( - p, Type>(L::Partial(1, 0, 0).Slice<0>(p)).data())); + p, + Type>(L::Partial(1, 0, 0).Slice<0>(p)).data())); EXPECT_EQ( 4, Distance( @@ -878,7 +914,8 @@ TEST(Layout, SliceByIndexData) { EXPECT_EQ( 0, Distance( - p, Type>(L::Partial(5, 3, 1).Slice<0>(p)).data())); + p, + Type>(L::Partial(5, 3, 1).Slice<0>(p)).data())); EXPECT_EQ( 24, Distance( @@ -890,12 +927,14 @@ TEST(Layout, SliceByIndexData) { p, Type>(L::Partial(5, 3, 1).Slice<1>(p)).data())); EXPECT_EQ( - 0, Distance(p, Type>(L(5, 3, 1).Slice<0>(p)).data())); + 0, + Distance(p, Type>(L(5, 3, 1).Slice<0>(p)).data())); EXPECT_EQ( 24, Distance(p, Type>(L(5, 3, 1).Slice<2>(p)).data())); EXPECT_EQ( - 8, Distance(p, Type>(L(5, 3, 1).Slice<1>(p)).data())); + 8, + Distance(p, Type>(L(5, 3, 1).Slice<1>(p)).data())); } } @@ -906,98 +945,94 @@ TEST(Layout, SliceByTypeData) { EXPECT_EQ( 0, Distance( - p, Type>(L::Partial(0).Slice(p)).data())); + p, + Type>(L::Partial(0).Slice(p)).data())); EXPECT_EQ( 0, Distance( - p, Type>(L::Partial(3).Slice(p)).data())); + p, + Type>(L::Partial(3).Slice(p)).data())); EXPECT_EQ( - 0, Distance(p, Type>(L(3).Slice(p)).data())); + 0, + Distance(p, Type>(L(3).Slice(p)).data())); } { using L = Layout; - EXPECT_EQ( - 0, Distance( - p, Type>(L::Partial(0).Slice(p)).data())); - EXPECT_EQ( - 0, Distance( - p, Type>(L::Partial(1).Slice(p)).data())); - EXPECT_EQ( - 0, Distance( - p, Type>(L::Partial(5).Slice(p)).data())); - EXPECT_EQ( - 0, - Distance( - p, Type>(L::Partial(0, 0).Slice(p)).data())); EXPECT_EQ( 0, Distance( p, - Type>(L::Partial(0, 0).Slice(p)).data())); + Type>(L::Partial(0).Slice(p)).data())); EXPECT_EQ( 0, - Distance( - p, Type>(L::Partial(1, 0).Slice(p)).data())); - EXPECT_EQ( - 4, Distance( p, - Type>(L::Partial(1, 0).Slice(p)).data())); + Type>(L::Partial(1).Slice(p)).data())); EXPECT_EQ( 0, - Distance( - p, Type>(L::Partial(5, 3).Slice(p)).data())); - EXPECT_EQ( - 8, Distance( p, - Type>(L::Partial(5, 3).Slice(p)).data())); + Type>(L::Partial(5).Slice(p)).data())); EXPECT_EQ( 0, - Distance( - p, - Type>(L::Partial(0, 0, 0).Slice(p)).data())); + Distance(p, Type>(L::Partial(0, 0).Slice(p)) + .data())); + EXPECT_EQ(0, Distance(p, Type>( + L::Partial(0, 0).Slice(p)) + .data())); EXPECT_EQ( 0, - Distance(p, Type>(L::Partial(0, 0, 0).Slice(p)) + Distance(p, Type>(L::Partial(1, 0).Slice(p)) .data())); - EXPECT_EQ(0, Distance(p, Type>( - L::Partial(0, 0, 0).Slice(p)) + EXPECT_EQ(4, Distance(p, Type>( + L::Partial(1, 0).Slice(p)) .data())); EXPECT_EQ( 0, - Distance( - p, - Type>(L::Partial(1, 0, 0).Slice(p)).data())); - EXPECT_EQ( - 4, - Distance(p, Type>(L::Partial(1, 0, 0).Slice(p)) + Distance(p, Type>(L::Partial(5, 3).Slice(p)) .data())); + EXPECT_EQ(8, Distance(p, Type>( + L::Partial(5, 3).Slice(p)) + .data())); + EXPECT_EQ(0, Distance(p, Type>( + L::Partial(0, 0, 0).Slice(p)) + .data())); + EXPECT_EQ(0, Distance(p, Type>( + L::Partial(0, 0, 0).Slice(p)) + .data())); + EXPECT_EQ(0, Distance(p, Type>( + L::Partial(0, 0, 0).Slice(p)) + .data())); + EXPECT_EQ(0, Distance(p, Type>( + L::Partial(1, 0, 0).Slice(p)) + .data())); + EXPECT_EQ(4, Distance(p, Type>( + L::Partial(1, 0, 0).Slice(p)) + .data())); EXPECT_EQ(8, Distance(p, Type>( L::Partial(1, 0, 0).Slice(p)) .data())); - EXPECT_EQ( - 0, - Distance( - p, - Type>(L::Partial(5, 3, 1).Slice(p)).data())); + EXPECT_EQ(0, Distance(p, Type>( + L::Partial(5, 3, 1).Slice(p)) + .data())); EXPECT_EQ(24, Distance(p, Type>( L::Partial(5, 3, 1).Slice(p)) .data())); - EXPECT_EQ( - 8, - Distance(p, Type>(L::Partial(5, 3, 1).Slice(p)) - .data())); + EXPECT_EQ(8, Distance(p, Type>( + L::Partial(5, 3, 1).Slice(p)) + .data())); EXPECT_EQ( 0, - Distance(p, Type>(L(5, 3, 1).Slice(p)).data())); + Distance(p, + Type>(L(5, 3, 1).Slice(p)).data())); EXPECT_EQ( 24, Distance(p, Type>(L(5, 3, 1).Slice(p)).data())); EXPECT_EQ( - 8, Distance( - p, Type>(L(5, 3, 1).Slice(p)).data())); + 8, + Distance( + p, Type>(L(5, 3, 1).Slice(p)).data())); } } @@ -1005,18 +1040,19 @@ TEST(Layout, MutableSliceByIndexData) { alignas(max_align_t) unsigned char p[100]; { using L = Layout; - EXPECT_EQ(0, - Distance(p, Type>(L::Partial(0).Slice<0>(p)).data())); - EXPECT_EQ(0, - Distance(p, Type>(L::Partial(3).Slice<0>(p)).data())); + EXPECT_EQ( + 0, Distance(p, Type>(L::Partial(0).Slice<0>(p)).data())); + EXPECT_EQ( + 0, Distance(p, Type>(L::Partial(3).Slice<0>(p)).data())); EXPECT_EQ(0, Distance(p, Type>(L(3).Slice<0>(p)).data())); } { using L = Layout; - EXPECT_EQ(0, - Distance(p, Type>(L::Partial(3).Slice<0>(p)).data())); EXPECT_EQ( - 0, Distance(p, Type>(L::Partial(3, 5).Slice<0>(p)).data())); + 0, Distance(p, Type>(L::Partial(3).Slice<0>(p)).data())); + EXPECT_EQ( + 0, + Distance(p, Type>(L::Partial(3, 5).Slice<0>(p)).data())); EXPECT_EQ( 12, Distance(p, Type>(L::Partial(3, 5).Slice<1>(p)).data())); @@ -1025,55 +1061,63 @@ TEST(Layout, MutableSliceByIndexData) { } { using L = Layout; - EXPECT_EQ(0, - Distance(p, Type>(L::Partial(0).Slice<0>(p)).data())); - EXPECT_EQ(0, - Distance(p, Type>(L::Partial(1).Slice<0>(p)).data())); - EXPECT_EQ(0, - Distance(p, Type>(L::Partial(5).Slice<0>(p)).data())); - EXPECT_EQ( - 0, Distance(p, Type>(L::Partial(0, 0).Slice<0>(p)).data())); EXPECT_EQ( - 0, Distance(p, Type>(L::Partial(0, 0).Slice<1>(p)).data())); + 0, Distance(p, Type>(L::Partial(0).Slice<0>(p)).data())); EXPECT_EQ( - 0, Distance(p, Type>(L::Partial(1, 0).Slice<0>(p)).data())); + 0, Distance(p, Type>(L::Partial(1).Slice<0>(p)).data())); EXPECT_EQ( - 4, Distance(p, Type>(L::Partial(1, 0).Slice<1>(p)).data())); + 0, Distance(p, Type>(L::Partial(5).Slice<0>(p)).data())); EXPECT_EQ( - 0, Distance(p, Type>(L::Partial(5, 3).Slice<0>(p)).data())); + 0, + Distance(p, Type>(L::Partial(0, 0).Slice<0>(p)).data())); EXPECT_EQ( - 8, Distance(p, Type>(L::Partial(5, 3).Slice<1>(p)).data())); + 0, + Distance(p, Type>(L::Partial(0, 0).Slice<1>(p)).data())); EXPECT_EQ( 0, - Distance(p, Type>(L::Partial(0, 0, 0).Slice<0>(p)).data())); + Distance(p, Type>(L::Partial(1, 0).Slice<0>(p)).data())); + EXPECT_EQ( + 4, + Distance(p, Type>(L::Partial(1, 0).Slice<1>(p)).data())); EXPECT_EQ( 0, - Distance(p, Type>(L::Partial(0, 0, 0).Slice<1>(p)).data())); + Distance(p, Type>(L::Partial(5, 3).Slice<0>(p)).data())); + EXPECT_EQ( + 8, + Distance(p, Type>(L::Partial(5, 3).Slice<1>(p)).data())); + EXPECT_EQ( + 0, Distance( + p, Type>(L::Partial(0, 0, 0).Slice<0>(p)).data())); + EXPECT_EQ( + 0, Distance( + p, Type>(L::Partial(0, 0, 0).Slice<1>(p)).data())); EXPECT_EQ( 0, Distance( p, Type>(L::Partial(0, 0, 0).Slice<2>(p)).data())); EXPECT_EQ( - 0, - Distance(p, Type>(L::Partial(1, 0, 0).Slice<0>(p)).data())); + 0, Distance( + p, Type>(L::Partial(1, 0, 0).Slice<0>(p)).data())); EXPECT_EQ( - 4, - Distance(p, Type>(L::Partial(1, 0, 0).Slice<1>(p)).data())); + 4, Distance( + p, Type>(L::Partial(1, 0, 0).Slice<1>(p)).data())); EXPECT_EQ( 8, Distance( p, Type>(L::Partial(1, 0, 0).Slice<2>(p)).data())); EXPECT_EQ( - 0, - Distance(p, Type>(L::Partial(5, 3, 1).Slice<0>(p)).data())); + 0, Distance( + p, Type>(L::Partial(5, 3, 1).Slice<0>(p)).data())); EXPECT_EQ( 24, Distance( p, Type>(L::Partial(5, 3, 1).Slice<2>(p)).data())); EXPECT_EQ( - 8, - Distance(p, Type>(L::Partial(5, 3, 1).Slice<1>(p)).data())); - EXPECT_EQ(0, Distance(p, Type>(L(5, 3, 1).Slice<0>(p)).data())); + 8, Distance( + p, Type>(L::Partial(5, 3, 1).Slice<1>(p)).data())); + EXPECT_EQ(0, + Distance(p, Type>(L(5, 3, 1).Slice<0>(p)).data())); EXPECT_EQ(24, Distance(p, Type>(L(5, 3, 1).Slice<2>(p)).data())); - EXPECT_EQ(8, Distance(p, Type>(L(5, 3, 1).Slice<1>(p)).data())); + EXPECT_EQ(8, + Distance(p, Type>(L(5, 3, 1).Slice<1>(p)).data())); } } @@ -1082,66 +1126,84 @@ TEST(Layout, MutableSliceByTypeData) { { using L = Layout; EXPECT_EQ( - 0, - Distance(p, Type>(L::Partial(0).Slice(p)).data())); + 0, Distance( + p, Type>(L::Partial(0).Slice(p)).data())); EXPECT_EQ( - 0, - Distance(p, Type>(L::Partial(3).Slice(p)).data())); - EXPECT_EQ(0, Distance(p, Type>(L(3).Slice(p)).data())); + 0, Distance( + p, Type>(L::Partial(3).Slice(p)).data())); + EXPECT_EQ(0, + Distance(p, Type>(L(3).Slice(p)).data())); } { using L = Layout; EXPECT_EQ( - 0, Distance(p, Type>(L::Partial(0).Slice(p)).data())); + 0, + Distance(p, Type>(L::Partial(0).Slice(p)).data())); EXPECT_EQ( - 0, Distance(p, Type>(L::Partial(1).Slice(p)).data())); + 0, + Distance(p, Type>(L::Partial(1).Slice(p)).data())); EXPECT_EQ( - 0, Distance(p, Type>(L::Partial(5).Slice(p)).data())); + 0, + Distance(p, Type>(L::Partial(5).Slice(p)).data())); EXPECT_EQ( 0, - Distance(p, Type>(L::Partial(0, 0).Slice(p)).data())); + Distance(p, + Type>(L::Partial(0, 0).Slice(p)).data())); EXPECT_EQ( - 0, Distance( - p, Type>(L::Partial(0, 0).Slice(p)).data())); + 0, + Distance( + p, Type>(L::Partial(0, 0).Slice(p)).data())); EXPECT_EQ( 0, - Distance(p, Type>(L::Partial(1, 0).Slice(p)).data())); + Distance(p, + Type>(L::Partial(1, 0).Slice(p)).data())); EXPECT_EQ( - 4, Distance( - p, Type>(L::Partial(1, 0).Slice(p)).data())); + 4, + Distance( + p, Type>(L::Partial(1, 0).Slice(p)).data())); EXPECT_EQ( 0, - Distance(p, Type>(L::Partial(5, 3).Slice(p)).data())); + Distance(p, + Type>(L::Partial(5, 3).Slice(p)).data())); EXPECT_EQ( - 8, Distance( - p, Type>(L::Partial(5, 3).Slice(p)).data())); + 8, + Distance( + p, Type>(L::Partial(5, 3).Slice(p)).data())); EXPECT_EQ( - 0, Distance( - p, Type>(L::Partial(0, 0, 0).Slice(p)).data())); + 0, + Distance( + p, + Type>(L::Partial(0, 0, 0).Slice(p)).data())); EXPECT_EQ( 0, Distance( - p, Type>(L::Partial(0, 0, 0).Slice(p)).data())); + p, + Type>(L::Partial(0, 0, 0).Slice(p)).data())); EXPECT_EQ( 0, Distance( p, Type>(L::Partial(0, 0, 0).Slice(p)).data())); EXPECT_EQ( - 0, Distance( - p, Type>(L::Partial(1, 0, 0).Slice(p)).data())); + 0, + Distance( + p, + Type>(L::Partial(1, 0, 0).Slice(p)).data())); EXPECT_EQ( 4, Distance( - p, Type>(L::Partial(1, 0, 0).Slice(p)).data())); + p, + Type>(L::Partial(1, 0, 0).Slice(p)).data())); EXPECT_EQ( 8, Distance( p, Type>(L::Partial(1, 0, 0).Slice(p)).data())); EXPECT_EQ( - 0, Distance( - p, Type>(L::Partial(5, 3, 1).Slice(p)).data())); + 0, + Distance( + p, + Type>(L::Partial(5, 3, 1).Slice(p)).data())); EXPECT_EQ( 24, Distance( @@ -1150,14 +1212,16 @@ TEST(Layout, MutableSliceByTypeData) { EXPECT_EQ( 8, Distance( - p, Type>(L::Partial(5, 3, 1).Slice(p)).data())); - EXPECT_EQ(0, - Distance(p, Type>(L(5, 3, 1).Slice(p)).data())); + p, + Type>(L::Partial(5, 3, 1).Slice(p)).data())); + EXPECT_EQ( + 0, Distance(p, Type>(L(5, 3, 1).Slice(p)).data())); EXPECT_EQ( 24, Distance(p, Type>(L(5, 3, 1).Slice(p)).data())); EXPECT_EQ( - 8, Distance(p, Type>(L(5, 3, 1).Slice(p)).data())); + 8, + Distance(p, Type>(L(5, 3, 1).Slice(p)).data())); } } @@ -1256,17 +1320,17 @@ TEST(Layout, MutableSlices) { } { const auto x = L::Partial(1, 2, 3); - EXPECT_THAT( - (Type, Span, Span>>(x.Slices(p))), - Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)), - IsSameSlice(x.Slice<2>(p)))); + EXPECT_THAT((Type, Span, Span>>( + x.Slices(p))), + Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)), + IsSameSlice(x.Slice<2>(p)))); } { const L x(1, 2, 3); - EXPECT_THAT( - (Type, Span, Span>>(x.Slices(p))), - Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)), - IsSameSlice(x.Slice<2>(p)))); + EXPECT_THAT((Type, Span, Span>>( + x.Slices(p))), + Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)), + IsSameSlice(x.Slice<2>(p)))); } } @@ -1398,7 +1462,8 @@ TEST(Layout, DebugString) { x.DebugString()); } { - constexpr auto x = Layout::Partial(1, 2, 3); + constexpr auto x = + Layout::Partial(1, 2, 3); EXPECT_EQ( "@0(1)[1]; @4(4)[2]; @12(1)[3]; " "@16" + @@ -1406,7 +1471,8 @@ TEST(Layout, DebugString) { x.DebugString()); } { - constexpr auto x = Layout::Partial(1, 2, 3, 4); + constexpr auto x = + Layout::Partial(1, 2, 3, 4); EXPECT_EQ( "@0(1)[1]; @4(4)[2]; @12(1)[3]; " "@16" + diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index f5ae83c4..6210eb64 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -847,7 +847,8 @@ TEST(Table, EraseMaintainsValidIterator) { std::vector CollectBadMergeKeys(size_t N) { static constexpr int kGroupSize = Group::kWidth - 1; - auto topk_range = [](size_t b, size_t e, IntTable* t) -> std::vector { + auto topk_range = [](size_t b, size_t e, + IntTable* t) -> std::vector { for (size_t i = b; i != e; ++i) { t->emplace(i); } @@ -1001,8 +1002,8 @@ using ProbeStatsPerSize = std::map; // 1. Create new table and reserve it to keys.size() * 2 // 2. Insert all keys xored with seed // 3. Collect ProbeStats from final table. -ProbeStats CollectProbeStatsOnKeysXoredWithSeed(const std::vector& keys, - size_t num_iters) { +ProbeStats CollectProbeStatsOnKeysXoredWithSeed( + const std::vector& keys, size_t num_iters) { const size_t reserve_size = keys.size() * 2; ProbeStats stats; diff --git a/absl/debugging/internal/symbolize.h b/absl/debugging/internal/symbolize.h index b3729af7..4f26130f 100644 --- a/absl/debugging/internal/symbolize.h +++ b/absl/debugging/internal/symbolize.h @@ -118,16 +118,14 @@ bool RemoveAllSymbolDecorators(void); // filename != nullptr // // Returns true if the file was successfully registered. -bool RegisterFileMappingHint( - const void* start, const void* end, uint64_t offset, const char* filename); +bool RegisterFileMappingHint(const void* start, const void* end, + uint64_t offset, const char* filename); // Looks up the file mapping registered by RegisterFileMappingHint for an // address range. If there is one, the file name is stored in *filename and // *start and *end are modified to reflect the registered mapping. Returns // whether any hint was found. -bool GetFileMappingHint(const void** start, - const void** end, - uint64_t * offset, +bool GetFileMappingHint(const void** start, const void** end, uint64_t* offset, const char** filename); } // namespace debugging_internal diff --git a/absl/flags/BUILD.bazel b/absl/flags/BUILD.bazel index 9de9e223..2bd94780 100644 --- a/absl/flags/BUILD.bazel +++ b/absl/flags/BUILD.bazel @@ -381,6 +381,8 @@ cc_binary( deps = [ ":flag", ":marshalling", + ":parse", + ":reflection", "//absl/strings", "//absl/time", "//absl/types:optional", diff --git a/absl/flags/flag_benchmark.cc b/absl/flags/flag_benchmark.cc index 7b52c9bc..9982b604 100644 --- a/absl/flags/flag_benchmark.cc +++ b/absl/flags/flag_benchmark.cc @@ -20,6 +20,8 @@ #include "absl/flags/flag.h" #include "absl/flags/marshalling.h" +#include "absl/flags/parse.h" +#include "absl/flags/reflection.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" #include "absl/types/optional.h" @@ -103,6 +105,23 @@ std::string AbslUnparseFlag(const UDT&) { return ""; } BENCHMARKED_TYPES(FLAG_DEF) +// Register thousands of flags to bloat up the size of the registry. +// This mimics real life production binaries. +#define DEFINE_FLAG_0(name) ABSL_FLAG(int, name, 0, ""); +#define DEFINE_FLAG_1(name) DEFINE_FLAG_0(name##0) DEFINE_FLAG_0(name##1) +#define DEFINE_FLAG_2(name) DEFINE_FLAG_1(name##0) DEFINE_FLAG_1(name##1) +#define DEFINE_FLAG_3(name) DEFINE_FLAG_2(name##0) DEFINE_FLAG_2(name##1) +#define DEFINE_FLAG_4(name) DEFINE_FLAG_3(name##0) DEFINE_FLAG_3(name##1) +#define DEFINE_FLAG_5(name) DEFINE_FLAG_4(name##0) DEFINE_FLAG_4(name##1) +#define DEFINE_FLAG_6(name) DEFINE_FLAG_5(name##0) DEFINE_FLAG_5(name##1) +#define DEFINE_FLAG_7(name) DEFINE_FLAG_6(name##0) DEFINE_FLAG_6(name##1) +#define DEFINE_FLAG_8(name) DEFINE_FLAG_7(name##0) DEFINE_FLAG_7(name##1) +#define DEFINE_FLAG_9(name) DEFINE_FLAG_8(name##0) DEFINE_FLAG_8(name##1) +#define DEFINE_FLAG_10(name) DEFINE_FLAG_9(name##0) DEFINE_FLAG_9(name##1) +#define DEFINE_FLAG_11(name) DEFINE_FLAG_10(name##0) DEFINE_FLAG_10(name##1) +#define DEFINE_FLAG_12(name) DEFINE_FLAG_11(name##0) DEFINE_FLAG_11(name##1) +DEFINE_FLAG_12(bloat_flag_); + namespace { #define BM_GetFlag(T) \ @@ -115,6 +134,20 @@ namespace { BENCHMARKED_TYPES(BM_GetFlag) +void BM_ThreadedFindCommandLineFlag(benchmark::State& state) { + char dummy[] = "dummy"; + char* argv[] = {dummy}; + // We need to ensure that flags have been parsed. That is where the registry + // is finalized. + absl::ParseCommandLine(1, argv); + + for (auto s : state) { + benchmark::DoNotOptimize( + absl::FindCommandLineFlag("bloat_flag_010101010101")); + } +} +BENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16); + } // namespace #define InvokeGetFlag(T) \ diff --git a/absl/flags/internal/registry.h b/absl/flags/internal/registry.h index 1df2db79..a8d9eb9c 100644 --- a/absl/flags/internal/registry.h +++ b/absl/flags/internal/registry.h @@ -30,9 +30,6 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace flags_internal { -// Executes specified visitor for each non-retired flag in the registry. -// Requires the caller hold the registry lock. -void ForEachFlagUnlocked(std::function visitor); // Executes specified visitor for each non-retired flag in the registry. While // callback are executed, the registry is locked and can't be changed. void ForEachFlag(std::function visitor); @@ -41,6 +38,8 @@ void ForEachFlag(std::function visitor); bool RegisterCommandLineFlag(CommandLineFlag&); +void FinalizeRegistry(); + //----------------------------------------------------------------------------- // Retired registrations: // diff --git a/absl/flags/parse.cc b/absl/flags/parse.cc index 4f4bb3d5..1835a837 100644 --- a/absl/flags/parse.cc +++ b/absl/flags/parse.cc @@ -611,6 +611,11 @@ std::vector ParseCommandLineImpl(int argc, char* argv[], OnUndefinedFlag on_undef_flag) { ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]"); + // Once parsing has started we will not have more flag registrations. + // If we did, they would be missing during parsing, which is a problem on + // itself. + flags_internal::FinalizeRegistry(); + // This routine does not return anything since we abort on failure. CheckDefaultValuesParsingRoundtrip(); diff --git a/absl/flags/reflection.cc b/absl/flags/reflection.cc index d7060221..c6bf8aab 100644 --- a/absl/flags/reflection.cc +++ b/absl/flags/reflection.cc @@ -17,6 +17,7 @@ #include +#include #include #include @@ -56,21 +57,23 @@ class FlagRegistry { // Returns the flag object for the specified name, or nullptr if not found. // Will emit a warning if a 'retired' flag is specified. - CommandLineFlag* FindFlagLocked(absl::string_view name); + CommandLineFlag* FindFlag(absl::string_view name); static FlagRegistry& GlobalRegistry(); // returns a singleton registry private: friend class flags_internal::FlagSaverImpl; // reads all the flags in order // to copy them - friend void ForEachFlagUnlocked( - std::function visitor); + friend void ForEachFlag(std::function visitor); + friend void FinalizeRegistry(); - // The map from name to flag, for FindFlagLocked(). + // The map from name to flag, for FindFlag(). using FlagMap = std::map; using FlagIterator = FlagMap::iterator; using FlagConstIterator = FlagMap::const_iterator; FlagMap flags_; + std::vector flat_flags_; + std::atomic finalized_flags_{false}; absl::Mutex lock_; @@ -79,15 +82,6 @@ class FlagRegistry { FlagRegistry& operator=(const FlagRegistry&); }; -CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) { - FlagConstIterator i = flags_.find(name); - if (i == flags_.end()) { - return nullptr; - } - - return i->second; -} - namespace { class FlagRegistryLock { @@ -101,8 +95,24 @@ class FlagRegistryLock { } // namespace +CommandLineFlag* FlagRegistry::FindFlag(absl::string_view name) { + if (finalized_flags_.load(std::memory_order_acquire)) { + // We could save some gcus here if we make `Name()` be non-virtual. + // We could move the `const char*` name to the base class. + auto it = std::partition_point( + flat_flags_.begin(), flat_flags_.end(), + [=](CommandLineFlag* f) { return f->Name() < name; }); + if (it != flat_flags_.end() && (*it)->Name() == name) return *it; + } + + FlagRegistryLock frl(*this); + auto it = flags_.find(name); + return it != flags_.end() ? it->second : nullptr; +} + void FlagRegistry::RegisterFlag(CommandLineFlag& flag) { FlagRegistryLock registry_lock(*this); + std::pair ins = flags_.insert(FlagMap::value_type(flag.Name(), &flag)); if (ins.second == false) { // means the name was already in the map @@ -152,18 +162,15 @@ FlagRegistry& FlagRegistry::GlobalRegistry() { // -------------------------------------------------------------------- -void ForEachFlagUnlocked(std::function visitor) { +void ForEachFlag(std::function visitor) { FlagRegistry& registry = FlagRegistry::GlobalRegistry(); - for (FlagRegistry::FlagConstIterator i = registry.flags_.begin(); - i != registry.flags_.end(); ++i) { - visitor(*i->second); + + if (registry.finalized_flags_.load(std::memory_order_acquire)) { + for (const auto& i : registry.flat_flags_) visitor(*i); } -} -void ForEachFlag(std::function visitor) { - FlagRegistry& registry = FlagRegistry::GlobalRegistry(); FlagRegistryLock frl(registry); - ForEachFlagUnlocked(visitor); + for (const auto& i : registry.flags_) visitor(*i.second); } // -------------------------------------------------------------------- @@ -173,6 +180,21 @@ bool RegisterCommandLineFlag(CommandLineFlag& flag) { return true; } +void FinalizeRegistry() { + auto& registry = FlagRegistry::GlobalRegistry(); + FlagRegistryLock frl(registry); + if (registry.finalized_flags_.load(std::memory_order_relaxed)) { + // Was already finalized. Ignore the second time. + return; + } + registry.flat_flags_.reserve(registry.flags_.size()); + for (const auto& f : registry.flags_) { + registry.flat_flags_.push_back(f.second); + } + registry.flags_.clear(); + registry.finalized_flags_.store(true, std::memory_order_release); +} + // -------------------------------------------------------------------- namespace { @@ -298,9 +320,7 @@ CommandLineFlag* FindCommandLineFlag(absl::string_view name) { if (name.empty()) return nullptr; flags_internal::FlagRegistry& registry = flags_internal::FlagRegistry::GlobalRegistry(); - flags_internal::FlagRegistryLock frl(registry); - - return registry.FindFlagLocked(name); + return registry.FindFlag(name); } // -------------------------------------------------------------------- diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc index 39ba24a8..1d2e6cf0 100644 --- a/absl/hash/hash_test.cc +++ b/absl/hash/hash_test.cc @@ -82,8 +82,8 @@ TYPED_TEST_P(HashValueIntTest, FastPath) { } REGISTER_TYPED_TEST_CASE_P(HashValueIntTest, BasicUsage, FastPath); -using IntTypes = testing::Types; +using IntTypes = testing::Types; INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueIntTest, IntTypes); enum LegacyEnum { kValue1, kValue2, kValue3 }; @@ -819,8 +819,8 @@ TYPED_TEST_P(HashIntTest, BasicUsage) { } REGISTER_TYPED_TEST_CASE_P(HashIntTest, BasicUsage); -using IntTypes = testing::Types; +using IntTypes = testing::Types; INSTANTIATE_TYPED_TEST_CASE_P(My, HashIntTest, IntTypes); struct StructWithPadding { diff --git a/absl/hash/internal/city.cc b/absl/hash/internal/city.cc index e122c184..58d4bcb1 100644 --- a/absl/hash/internal/city.cc +++ b/absl/hash/internal/city.cc @@ -253,9 +253,8 @@ static uint64_t HashLen17to32(const char *s, size_t len) { // Return a 16-byte hash for 48 bytes. Quick and dirty. // Callers do best to use "random-looking" values for a and b. -static std::pair WeakHashLen32WithSeeds(uint64_t w, uint64_t x, - uint64_t y, uint64_t z, - uint64_t a, uint64_t b) { +static std::pair WeakHashLen32WithSeeds( + uint64_t w, uint64_t x, uint64_t y, uint64_t z, uint64_t a, uint64_t b) { a += w; b = Rotate(b + a + z, 21); uint64_t c = a; @@ -266,8 +265,9 @@ static std::pair WeakHashLen32WithSeeds(uint64_t w, uint64_t } // Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. -static std::pair WeakHashLen32WithSeeds(const char *s, uint64_t a, - uint64_t b) { +static std::pair WeakHashLen32WithSeeds(const char *s, + uint64_t a, + uint64_t b) { return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a, b); } @@ -310,8 +310,10 @@ uint64_t CityHash64(const char *s, size_t len) { uint64_t x = Fetch64(s + len - 40); uint64_t y = Fetch64(s + len - 16) + Fetch64(s + len - 56); uint64_t z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); - std::pair v = WeakHashLen32WithSeeds(s + len - 64, len, z); - std::pair w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x); + std::pair v = + WeakHashLen32WithSeeds(s + len - 64, len, z); + std::pair w = + WeakHashLen32WithSeeds(s + len - 32, y + k1, x); x = x * k1 + Fetch64(s); // Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. @@ -337,7 +339,7 @@ uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed) { } uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0, - uint64_t seed1) { + uint64_t seed1) { return HashLen16(CityHash64(s, len) - seed0, seed1); } diff --git a/absl/hash/internal/city.h b/absl/hash/internal/city.h index 161c7748..9c1e7a57 100644 --- a/absl/hash/internal/city.h +++ b/absl/hash/internal/city.h @@ -71,7 +71,7 @@ uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed); // Hash function for a byte array. For convenience, two seeds are also // hashed into the result. uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0, - uint64_t seed1); + uint64_t seed1); // Hash function for a byte array. Most useful in 32-bit binaries. uint32_t CityHash32(const char *s, size_t len); diff --git a/absl/random/internal/generate_real_test.cc b/absl/random/internal/generate_real_test.cc index aa02f0c2..4bdc4534 100644 --- a/absl/random/internal/generate_real_test.cc +++ b/absl/random/internal/generate_real_test.cc @@ -419,8 +419,8 @@ TEST(GenerateRealTest, ExhaustiveFloat) { }; // Rely on RandU64ToFloat generating values from greatest to least when - // supplied with uint64_t values from greatest (0xfff...) to least (0x0). Thus, - // this algorithm stores the previous value, and if the new value is at + // supplied with uint64_t values from greatest (0xfff...) to least (0x0). + // Thus, this algorithm stores the previous value, and if the new value is at // greater than or equal to the previous value, then there is a collision in // the generation algorithm. // diff --git a/absl/strings/cord_test.cc b/absl/strings/cord_test.cc index 4443c828..dbed3e9a 100644 --- a/absl/strings/cord_test.cc +++ b/absl/strings/cord_test.cc @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "absl/strings/cord.h" #include diff --git a/absl/strings/internal/str_format/arg.cc b/absl/strings/internal/str_format/arg.cc index 9feb2248..e28a29b1 100644 --- a/absl/strings/internal/str_format/arg.cc +++ b/absl/strings/internal/str_format/arg.cc @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + // // POSIX spec: // http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html diff --git a/absl/strings/internal/str_format/arg.h b/absl/strings/internal/str_format/arg.h index 3dbc1526..7040c866 100644 --- a/absl/strings/internal/str_format/arg.h +++ b/absl/strings/internal/str_format/arg.h @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_ #define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_ diff --git a/absl/strings/internal/str_format/bind.cc b/absl/strings/internal/str_format/bind.cc index 6980ed1d..194e21af 100644 --- a/absl/strings/internal/str_format/bind.cc +++ b/absl/strings/internal/str_format/bind.cc @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "absl/strings/internal/str_format/bind.h" #include diff --git a/absl/strings/internal/str_format/bind.h b/absl/strings/internal/str_format/bind.h index 585246e7..727b2115 100644 --- a/absl/strings/internal/str_format/bind.h +++ b/absl/strings/internal/str_format/bind.h @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_ #define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_ diff --git a/absl/strings/internal/str_format/bind_test.cc b/absl/strings/internal/str_format/bind_test.cc index 64790a85..1eef9c43 100644 --- a/absl/strings/internal/str_format/bind_test.cc +++ b/absl/strings/internal/str_format/bind_test.cc @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "absl/strings/internal/str_format/bind.h" #include diff --git a/absl/strings/internal/str_format/checker.h b/absl/strings/internal/str_format/checker.h index 424c51f7..2a2601ec 100644 --- a/absl/strings/internal/str_format/checker.h +++ b/absl/strings/internal/str_format/checker.h @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_ #define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_ diff --git a/absl/strings/internal/str_format/checker_test.cc b/absl/strings/internal/str_format/checker_test.cc index a76d70b0..7c70f47d 100644 --- a/absl/strings/internal/str_format/checker_test.cc +++ b/absl/strings/internal/str_format/checker_test.cc @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include #include "gmock/gmock.h" diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 634ee78b..375db0a0 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include #include #include diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index 20aeada5..d3c5f0a7 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "absl/strings/internal/str_format/float_conversion.h" #include diff --git a/absl/strings/internal/str_format/float_conversion.h b/absl/strings/internal/str_format/float_conversion.h index e78bc191..71100e71 100644 --- a/absl/strings/internal/str_format/float_conversion.h +++ b/absl/strings/internal/str_format/float_conversion.h @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_ #define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_ diff --git a/absl/strings/internal/str_format/parser.cc b/absl/strings/internal/str_format/parser.cc index cc55dfa9..f308d023 100644 --- a/absl/strings/internal/str_format/parser.cc +++ b/absl/strings/internal/str_format/parser.cc @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "absl/strings/internal/str_format/parser.h" #include diff --git a/absl/strings/internal/str_format/parser.h b/absl/strings/internal/str_format/parser.h index fffed04f..6504dd3d 100644 --- a/absl/strings/internal/str_format/parser.h +++ b/absl/strings/internal/str_format/parser.h @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_ #define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_ diff --git a/absl/strings/internal/str_format/parser_test.cc b/absl/strings/internal/str_format/parser_test.cc index 5aced987..a5fa1c79 100644 --- a/absl/strings/internal/str_format/parser_test.cc +++ b/absl/strings/internal/str_format/parser_test.cc @@ -1,3 +1,17 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + #include "absl/strings/internal/str_format/parser.h" #include diff --git a/absl/strings/str_format_test.cc b/absl/strings/str_format_test.cc index d9fb25af..c60027ad 100644 --- a/absl/strings/str_format_test.cc +++ b/absl/strings/str_format_test.cc @@ -1,3 +1,16 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. #include "absl/strings/str_format.h" diff --git a/absl/synchronization/BUILD.bazel b/absl/synchronization/BUILD.bazel index b2df4131..cd4009a1 100644 --- a/absl/synchronization/BUILD.bazel +++ b/absl/synchronization/BUILD.bazel @@ -80,6 +80,7 @@ cc_library( "barrier.h", "blocking_counter.h", "internal/create_thread_identity.h", + "internal/futex.h", "internal/per_thread_sem.h", "internal/waiter.h", "mutex.h", diff --git a/absl/synchronization/CMakeLists.txt b/absl/synchronization/CMakeLists.txt index c255b03e..e633d0bf 100644 --- a/absl/synchronization/CMakeLists.txt +++ b/absl/synchronization/CMakeLists.txt @@ -52,6 +52,7 @@ absl_cc_library( "barrier.h" "blocking_counter.h" "internal/create_thread_identity.h" + "internal/futex.h" "internal/per_thread_sem.h" "internal/waiter.h" "mutex.h" diff --git a/absl/synchronization/internal/futex.h b/absl/synchronization/internal/futex.h new file mode 100644 index 00000000..3539f491 --- /dev/null +++ b/absl/synchronization/internal/futex.h @@ -0,0 +1,139 @@ +// Copyright 2020 The Abseil Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_ +#define ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_ + +#include "absl/base/config.h" + +#ifdef _WIN32 +#include +#else +#include +#include +#endif + +#ifdef __linux__ +#include +#include +#endif + +#include +#include +#include + +#include +#include + +#include "absl/base/optimization.h" +#include "absl/synchronization/internal/kernel_timeout.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace synchronization_internal { + +// Some Android headers are missing these definitions even though they +// support these futex operations. +#ifdef __BIONIC__ +#ifndef SYS_futex +#define SYS_futex __NR_futex +#endif +#ifndef FUTEX_WAIT_BITSET +#define FUTEX_WAIT_BITSET 9 +#endif +#ifndef FUTEX_PRIVATE_FLAG +#define FUTEX_PRIVATE_FLAG 128 +#endif +#ifndef FUTEX_CLOCK_REALTIME +#define FUTEX_CLOCK_REALTIME 256 +#endif +#ifndef FUTEX_BITSET_MATCH_ANY +#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF +#endif +#endif + +#if defined(__NR_futex_time64) && !defined(SYS_futex_time64) +#define SYS_futex_time64 __NR_futex_time64 +#endif + +#if defined(SYS_futex_time64) && !defined(SYS_futex) +#define SYS_futex SYS_futex_time64 +#endif + +class FutexImpl { + public: + static int WaitUntil(std::atomic *v, int32_t val, + KernelTimeout t) { + int err = 0; + if (t.has_timeout()) { + // https://locklessinc.com/articles/futex_cheat_sheet/ + // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time. + struct timespec abs_timeout = t.MakeAbsTimespec(); + // Atomically check that the futex value is still 0, and if it + // is, sleep until abs_timeout or until woken by FUTEX_WAKE. + err = syscall( + SYS_futex, reinterpret_cast(v), + FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val, + &abs_timeout, nullptr, FUTEX_BITSET_MATCH_ANY); + } else { + // Atomically check that the futex value is still 0, and if it + // is, sleep until woken by FUTEX_WAKE. + err = syscall(SYS_futex, reinterpret_cast(v), + FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, nullptr); + } + if (ABSL_PREDICT_FALSE(err != 0)) { + err = -errno; + } + return err; + } + + static int WaitBitsetAbsoluteTimeout(std::atomic *v, int32_t val, + int32_t bits, + const struct timespec *abstime) { + int err = syscall(SYS_futex, reinterpret_cast(v), + FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG, val, abstime, + nullptr, bits); + if (ABSL_PREDICT_FALSE(err != 0)) { + err = -errno; + } + return err; + } + + static int Wake(std::atomic *v, int32_t count) { + int err = syscall(SYS_futex, reinterpret_cast(v), + FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count); + if (ABSL_PREDICT_FALSE(err < 0)) { + err = -errno; + } + return err; + } + + // FUTEX_WAKE_BITSET + static int WakeBitset(std::atomic *v, int32_t count, int32_t bits) { + int err = syscall(SYS_futex, reinterpret_cast(v), + FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG, count, nullptr, + nullptr, bits); + if (ABSL_PREDICT_FALSE(err < 0)) { + err = -errno; + } + return err; + } +}; + +class Futex : public FutexImpl {}; + +} // namespace synchronization_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_ diff --git a/absl/synchronization/internal/kernel_timeout.h b/absl/synchronization/internal/kernel_timeout.h index 1084e1e6..bbd4d2d7 100644 --- a/absl/synchronization/internal/kernel_timeout.h +++ b/absl/synchronization/internal/kernel_timeout.h @@ -26,6 +26,7 @@ #define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_ #include + #include #include @@ -142,7 +143,7 @@ inline struct timespec KernelTimeout::MakeAbsTimespec() { struct timespec abstime; int64_t seconds = (std::min)(n / kNanosPerSecond, - int64_t{(std::numeric_limits::max)()}); + int64_t{(std::numeric_limits::max)()}); abstime.tv_sec = static_cast(seconds); abstime.tv_nsec = static_cast(n % kNanosPerSecond); return abstime; diff --git a/absl/synchronization/internal/waiter.cc b/absl/synchronization/internal/waiter.cc index b6150b9b..c51855b0 100644 --- a/absl/synchronization/internal/waiter.cc +++ b/absl/synchronization/internal/waiter.cc @@ -48,6 +48,11 @@ #include "absl/base/optimization.h" #include "absl/synchronization/internal/kernel_timeout.h" +#if ABSL_WAITER_MODE == ABSL_WAITER_MODE_FUTEX +#include "absl/synchronization/internal/futex.h" +#endif + + namespace absl { ABSL_NAMESPACE_BEGIN namespace synchronization_internal { @@ -66,71 +71,6 @@ static void MaybeBecomeIdle() { #if ABSL_WAITER_MODE == ABSL_WAITER_MODE_FUTEX -// Some Android headers are missing these definitions even though they -// support these futex operations. -#ifdef __BIONIC__ -#ifndef SYS_futex -#define SYS_futex __NR_futex -#endif -#ifndef FUTEX_WAIT_BITSET -#define FUTEX_WAIT_BITSET 9 -#endif -#ifndef FUTEX_PRIVATE_FLAG -#define FUTEX_PRIVATE_FLAG 128 -#endif -#ifndef FUTEX_CLOCK_REALTIME -#define FUTEX_CLOCK_REALTIME 256 -#endif -#ifndef FUTEX_BITSET_MATCH_ANY -#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF -#endif -#endif - -#if defined(__NR_futex_time64) && !defined(SYS_futex_time64) -#define SYS_futex_time64 __NR_futex_time64 -#endif - -#if defined(SYS_futex_time64) && !defined(SYS_futex) -#define SYS_futex SYS_futex_time64 -#endif - -class Futex { - public: - static int WaitUntil(std::atomic *v, int32_t val, - KernelTimeout t) { - int err = 0; - if (t.has_timeout()) { - // https://locklessinc.com/articles/futex_cheat_sheet/ - // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time. - struct timespec abs_timeout = t.MakeAbsTimespec(); - // Atomically check that the futex value is still 0, and if it - // is, sleep until abs_timeout or until woken by FUTEX_WAKE. - err = syscall( - SYS_futex, reinterpret_cast(v), - FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val, - &abs_timeout, nullptr, FUTEX_BITSET_MATCH_ANY); - } else { - // Atomically check that the futex value is still 0, and if it - // is, sleep until woken by FUTEX_WAKE. - err = syscall(SYS_futex, reinterpret_cast(v), - FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, nullptr); - } - if (err != 0) { - err = -errno; - } - return err; - } - - static int Wake(std::atomic *v, int32_t count) { - int err = syscall(SYS_futex, reinterpret_cast(v), - FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count); - if (ABSL_PREDICT_FALSE(err < 0)) { - err = -errno; - } - return err; - } -}; - Waiter::Waiter() { futex_.store(0, std::memory_order_relaxed); } diff --git a/absl/synchronization/mutex.cc b/absl/synchronization/mutex.cc index 9b7f088a..63f09408 100644 --- a/absl/synchronization/mutex.cc +++ b/absl/synchronization/mutex.cc @@ -88,8 +88,8 @@ ABSL_CONST_INIT std::atomic synch_deadlock_detection( ABSL_CONST_INIT std::atomic synch_check_invariants(false); ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES - absl::base_internal::AtomicHook - submit_profile_data; +absl::base_internal::AtomicHook + submit_profile_data; ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook mutex_tracer; @@ -491,7 +491,7 @@ struct SynchWaitParams { std::atomic *cv_word; int64_t contention_start_cycles; // Time (in cycles) when this thread started - // to contend for the mutex. + // to contend for the mutex. }; struct SynchLocksHeld { @@ -2311,7 +2311,8 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) { if (!cond_waiter) { // Sample lock contention events only if the (first) waiter was trying to // acquire the lock, not waiting on a condition variable or Condition. - int64_t wait_cycles = base_internal::CycleClock::Now() - enqueue_timestamp; + int64_t wait_cycles = + base_internal::CycleClock::Now() - enqueue_timestamp; mutex_tracer("slow release", this, wait_cycles); ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0); submit_profile_data(enqueue_timestamp); diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h index 6340bd63..f686c4df 100644 --- a/absl/synchronization/mutex.h +++ b/absl/synchronization/mutex.h @@ -667,10 +667,10 @@ class Condition { // }; // mu_.Await(Condition(&reached)); // - // NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReadHeld()" in the - // lambda as it may be called when the mutex is being unlocked from a scope - // holding only a reader lock, which will make the assertion not fulfilled and - // crash the binary. + // NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReaderHeld()" in + // the lambda as it may be called when the mutex is being unlocked from a + // scope holding only a reader lock, which will make the assertion not + // fulfilled and crash the binary. // See class comment for performance advice. In particular, if there // might be more than one waiter for the same condition, make sure @@ -954,7 +954,7 @@ void RegisterMutexProfiler(void (*fn)(int64_t wait_timestamp)); // // This has the same memory ordering concerns as RegisterMutexProfiler() above. void RegisterMutexTracer(void (*fn)(const char *msg, const void *obj, - int64_t wait_cycles)); + int64_t wait_cycles)); // TODO(gfalcon): Combine RegisterMutexProfiler() and RegisterMutexTracer() // into a single interface, since they are only ever called in pairs. diff --git a/absl/time/clock.cc b/absl/time/clock.cc index e5c423c7..6862e011 100644 --- a/absl/time/clock.cc +++ b/absl/time/clock.cc @@ -74,9 +74,7 @@ ABSL_NAMESPACE_END #if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS namespace absl { ABSL_NAMESPACE_BEGIN -int64_t GetCurrentTimeNanos() { - return GET_CURRENT_TIME_NANOS_FROM_SYSTEM(); -} +int64_t GetCurrentTimeNanos() { return GET_CURRENT_TIME_NANOS_FROM_SYSTEM(); } ABSL_NAMESPACE_END } // namespace absl #else // Use the cyclecounter-based implementation below. diff --git a/absl/time/duration.cc b/absl/time/duration.cc index eca1a6d9..4443109a 100644 --- a/absl/time/duration.cc +++ b/absl/time/duration.cc @@ -356,7 +356,7 @@ namespace time_internal { // the remainder. If it does not saturate, the remainder remain accurate, // but the returned quotient will over/underflow int64_t and should not be used. int64_t IDivDuration(bool satq, const Duration num, const Duration den, - Duration* rem) { + Duration* rem) { int64_t q = 0; if (IDivFastPath(num, den, &q, rem)) { return q; diff --git a/absl/time/time.cc b/absl/time/time.cc index 6bb36cb3..1ec2026e 100644 --- a/absl/time/time.cc +++ b/absl/time/time.cc @@ -60,9 +60,10 @@ inline cctz::time_point unix_epoch() { inline int64_t FloorToUnit(absl::Duration d, absl::Duration unit) { absl::Duration rem; int64_t q = absl::IDivDuration(d, unit, &rem); - return (q > 0 || - rem >= ZeroDuration() || - q == std::numeric_limits::min()) ? q : q - 1; + return (q > 0 || rem >= ZeroDuration() || + q == std::numeric_limits::min()) + ? q + : q - 1; } inline absl::Time::Breakdown InfiniteFutureBreakdown() { diff --git a/absl/time/time.h b/absl/time/time.h index 37f6131d..72508031 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -639,7 +639,7 @@ class Time { // Deprecated. Use `absl::TimeZone::CivilInfo`. struct Breakdown { - int64_t year; // year (e.g., 2013) + int64_t year; // year (e.g., 2013) int month; // month of year [1:12] int day; // day of month [1:31] int hour; // hour of day [0:23] @@ -1494,12 +1494,10 @@ constexpr Duration Hours(int64_t n) { constexpr bool operator<(Duration lhs, Duration rhs) { return time_internal::GetRepHi(lhs) != time_internal::GetRepHi(rhs) ? time_internal::GetRepHi(lhs) < time_internal::GetRepHi(rhs) - : time_internal::GetRepHi(lhs) == - (std::numeric_limits::min)() - ? time_internal::GetRepLo(lhs) + 1 < - time_internal::GetRepLo(rhs) + 1 - : time_internal::GetRepLo(lhs) < - time_internal::GetRepLo(rhs); + : time_internal::GetRepHi(lhs) == (std::numeric_limits::min)() + ? time_internal::GetRepLo(lhs) + 1 < + time_internal::GetRepLo(rhs) + 1 + : time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs); } constexpr bool operator==(Duration lhs, Duration rhs) { diff --git a/absl/time/time_test.cc b/absl/time/time_test.cc index b28a99fb..cde9423f 100644 --- a/absl/time/time_test.cc +++ b/absl/time/time_test.cc @@ -1070,7 +1070,8 @@ TEST(Time, ConversionSaturation) { EXPECT_EQ("292277026596-12-04T15:30:07+00:00", absl::FormatTime(absl::RFC3339_full, t, utc)); EXPECT_EQ( - absl::UnixEpoch() + absl::Seconds(std::numeric_limits::max()), t); + absl::UnixEpoch() + absl::Seconds(std::numeric_limits::max()), + t); // Checks that we can also get the maximal Time value for a far-east zone. const absl::TimeZone plus14 = absl::FixedTimeZone(14 * 60 * 60); @@ -1078,7 +1079,8 @@ TEST(Time, ConversionSaturation) { EXPECT_EQ("292277026596-12-05T05:30:07+14:00", absl::FormatTime(absl::RFC3339_full, t, plus14)); EXPECT_EQ( - absl::UnixEpoch() + absl::Seconds(std::numeric_limits::max()), t); + absl::UnixEpoch() + absl::Seconds(std::numeric_limits::max()), + t); // One second later should push us to infinity. t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 8), utc); @@ -1092,7 +1094,8 @@ TEST(Time, ConversionSaturation) { EXPECT_EQ("-292277022657-01-27T08:29:52+00:00", absl::FormatTime(absl::RFC3339_full, t, utc)); EXPECT_EQ( - absl::UnixEpoch() + absl::Seconds(std::numeric_limits::min()), t); + absl::UnixEpoch() + absl::Seconds(std::numeric_limits::min()), + t); // Checks that we can also get the minimal Time value for a far-west zone. const absl::TimeZone minus12 = absl::FixedTimeZone(-12 * 60 * 60); @@ -1101,7 +1104,8 @@ TEST(Time, ConversionSaturation) { EXPECT_EQ("-292277022657-01-26T20:29:52-12:00", absl::FormatTime(absl::RFC3339_full, t, minus12)); EXPECT_EQ( - absl::UnixEpoch() + absl::Seconds(std::numeric_limits::min()), t); + absl::UnixEpoch() + absl::Seconds(std::numeric_limits::min()), + t); // One second before should push us to -infinity. t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 51), utc); diff --git a/absl/types/internal/variant.h b/absl/types/internal/variant.h index d404e80c..772008c7 100644 --- a/absl/types/internal/variant.h +++ b/absl/types/internal/variant.h @@ -45,7 +45,7 @@ ABSL_NAMESPACE_BEGIN template class variant; -ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1); +ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, static_cast(-1)); template struct variant_size; diff --git a/absl/types/variant_test.cc b/absl/types/variant_test.cc index cf8f7f33..cf237334 100644 --- a/absl/types/variant_test.cc +++ b/absl/types/variant_test.cc @@ -2311,7 +2311,8 @@ TEST(VariantTest, TestRvalueConversion) { ASSERT_TRUE(absl::holds_alternative(variant2)); EXPECT_EQ(42, absl::get(variant2)); - variant2 = ConvertVariantTo>(variant(42)); + variant2 = + ConvertVariantTo>(variant(42)); ASSERT_TRUE(absl::holds_alternative(variant2)); EXPECT_EQ(42, absl::get(variant2)); #endif // !ABSL_USES_STD_VARIANT @@ -2453,7 +2454,8 @@ TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) { ConvertVariantTo>(variant(42))); EXPECT_THAT(absl::get_if(&variant2), Pointee(42)); - variant2 = ConvertVariantTo>(variant(42)); + variant2 = + ConvertVariantTo>(variant(42)); EXPECT_THAT(absl::get_if(&variant2), Pointee(42)); #endif -- cgit v1.2.3 From c36d825d9a5443f81d2656685ae021d6326da90c Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Sun, 7 Feb 2021 17:35:10 -0800 Subject: Export of internal Abseil changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -- 756156bf03da050e8b27539a8247d9af7e44c6a2 by Abseil Team : Fix a typo in cord.h: "accomodate" => "accommodate" PiperOrigin-RevId: 356168875 -- 638befdb342b608ec28910ee931ee200fdbe1fef by Samuel Benzaquen : Fix float conversion for PPC. In PPC `long double` is a double-double representation which behaves weirdly wrt numeric_limits. Don't take `long double` into account when we are not handling `long double` natively anyway. Fix the convert test to always run the conversion even if we are not going to compare against libc's printf result. This allows exercising the code itself to make sure we don't trigger assertions or UB found by sanitizers. PiperOrigin-RevId: 355857729 -- ff5f893319fa76b273c7785b76ef6c95b1791076 by Abseil Team : Example usage tweak PiperOrigin-RevId: 355695750 -- 0efc454f90023fa651b226e5e3ba7395a3b60c6d by Benjamin Barenblat : Remove endian-sensitivity from Abseil’s RNG Ensure that the Abseil random number generator produces identical output on both big- and little-endian platforms by byte-swapping appropriately on big-endian systems. PiperOrigin-RevId: 355635051 GitOrigin-RevId: 756156bf03da050e8b27539a8247d9af7e44c6a2 Change-Id: Iaaa69767b8e85d626742b9ba56fefb75f07c69ee --- absl/base/BUILD.bazel | 1 + absl/base/CMakeLists.txt | 1 + absl/base/internal/endian.h | 61 +++++++++++++++ absl/random/CMakeLists.txt | 3 + absl/random/internal/BUILD.bazel | 7 +- absl/random/internal/explicit_seed_seq.h | 3 +- absl/random/internal/randen_engine.h | 8 +- absl/random/internal/randen_slow_test.cc | 3 +- absl/strings/cord.h | 2 +- absl/strings/internal/str_format/convert_test.cc | 88 +++++++++++----------- .../internal/str_format/float_conversion.cc | 33 ++++---- absl/synchronization/mutex.h | 2 +- 12 files changed, 146 insertions(+), 66 deletions(-) (limited to 'absl/strings/internal/str_format/convert_test.cc') diff --git a/absl/base/BUILD.bazel b/absl/base/BUILD.bazel index 5d67a507..7d2ff308 100644 --- a/absl/base/BUILD.bazel +++ b/absl/base/BUILD.bazel @@ -479,6 +479,7 @@ cc_library( copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, deps = [ + ":base", ":config", ":core_headers", ], diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt index 3d930b85..981b8cc0 100644 --- a/absl/base/CMakeLists.txt +++ b/absl/base/CMakeLists.txt @@ -418,6 +418,7 @@ absl_cc_library( COPTS ${ABSL_DEFAULT_COPTS} DEPS + absl::base absl::config absl::core_headers PUBLIC diff --git a/absl/base/internal/endian.h b/absl/base/internal/endian.h index 9677530e..dad0e9ae 100644 --- a/absl/base/internal/endian.h +++ b/absl/base/internal/endian.h @@ -26,6 +26,7 @@ #endif #include +#include "absl/base/casts.h" #include "absl/base/config.h" #include "absl/base/internal/unaligned_access.h" #include "absl/base/port.h" @@ -173,6 +174,36 @@ inline constexpr bool IsLittleEndian() { return false; } #endif /* ENDIAN */ +inline uint8_t FromHost(uint8_t x) { return x; } +inline uint16_t FromHost(uint16_t x) { return FromHost16(x); } +inline uint32_t FromHost(uint32_t x) { return FromHost32(x); } +inline uint64_t FromHost(uint64_t x) { return FromHost64(x); } +inline uint8_t ToHost(uint8_t x) { return x; } +inline uint16_t ToHost(uint16_t x) { return ToHost16(x); } +inline uint32_t ToHost(uint32_t x) { return ToHost32(x); } +inline uint64_t ToHost(uint64_t x) { return ToHost64(x); } + +inline int8_t FromHost(int8_t x) { return x; } +inline int16_t FromHost(int16_t x) { + return bit_cast(FromHost16(bit_cast(x))); +} +inline int32_t FromHost(int32_t x) { + return bit_cast(FromHost32(bit_cast(x))); +} +inline int64_t FromHost(int64_t x) { + return bit_cast(FromHost64(bit_cast(x))); +} +inline int8_t ToHost(int8_t x) { return x; } +inline int16_t ToHost(int16_t x) { + return bit_cast(ToHost16(bit_cast(x))); +} +inline int32_t ToHost(int32_t x) { + return bit_cast(ToHost32(bit_cast(x))); +} +inline int64_t ToHost(int64_t x) { + return bit_cast(ToHost64(bit_cast(x))); +} + // Functions to do unaligned loads and stores in little-endian order. inline uint16_t Load16(const void *p) { return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p)); @@ -233,6 +264,36 @@ inline constexpr bool IsLittleEndian() { return false; } #endif /* ENDIAN */ +inline uint8_t FromHost(uint8_t x) { return x; } +inline uint16_t FromHost(uint16_t x) { return FromHost16(x); } +inline uint32_t FromHost(uint32_t x) { return FromHost32(x); } +inline uint64_t FromHost(uint64_t x) { return FromHost64(x); } +inline uint8_t ToHost(uint8_t x) { return x; } +inline uint16_t ToHost(uint16_t x) { return ToHost16(x); } +inline uint32_t ToHost(uint32_t x) { return ToHost32(x); } +inline uint64_t ToHost(uint64_t x) { return ToHost64(x); } + +inline int8_t FromHost(int8_t x) { return x; } +inline int16_t FromHost(int16_t x) { + return bit_cast(FromHost16(bit_cast(x))); +} +inline int32_t FromHost(int32_t x) { + return bit_cast(FromHost32(bit_cast(x))); +} +inline int64_t FromHost(int64_t x) { + return bit_cast(FromHost64(bit_cast(x))); +} +inline int8_t ToHost(int8_t x) { return x; } +inline int16_t ToHost(int16_t x) { + return bit_cast(ToHost16(bit_cast(x))); +} +inline int32_t ToHost(int32_t x) { + return bit_cast(ToHost32(bit_cast(x))); +} +inline int64_t ToHost(int64_t x) { + return bit_cast(ToHost64(bit_cast(x))); +} + // Functions to do unaligned loads and stores in big-endian order. inline uint16_t Load16(const void *p) { return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p)); diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt index 7d7bec83..13093d6d 100644 --- a/absl/random/CMakeLists.txt +++ b/absl/random/CMakeLists.txt @@ -611,6 +611,7 @@ absl_cc_library( ${ABSL_DEFAULT_LINKOPTS} DEPS absl::config + absl::endian TESTONLY ) @@ -758,6 +759,7 @@ absl_cc_library( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS + absl::endian absl::random_internal_iostream_state_saver absl::random_internal_randen absl::raw_logging_internal @@ -1119,6 +1121,7 @@ absl_cc_test( LINKOPTS ${ABSL_DEFAULT_LINKOPTS} DEPS + absl::endian absl::random_internal_randen_slow gtest_main ) diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel index 2c1a5f4a..4e778aee 100644 --- a/absl/random/internal/BUILD.bazel +++ b/absl/random/internal/BUILD.bazel @@ -124,7 +124,10 @@ cc_library( ], copts = ABSL_DEFAULT_COPTS, linkopts = ABSL_DEFAULT_LINKOPTS, - deps = ["//absl/base:config"], + deps = [ + "//absl/base:config", + "//absl/base:endian", + ], ) cc_library( @@ -242,6 +245,7 @@ cc_library( deps = [ ":iostream_state_saver", ":randen", + "//absl/base:endian", "//absl/meta:type_traits", ], ) @@ -606,6 +610,7 @@ cc_test( deps = [ ":platform", ":randen_slow", + "//absl/base:endian", "@com_google_googletest//:gtest_main", ], ) diff --git a/absl/random/internal/explicit_seed_seq.h b/absl/random/internal/explicit_seed_seq.h index 6a743eaf..e3aa31a1 100644 --- a/absl/random/internal/explicit_seed_seq.h +++ b/absl/random/internal/explicit_seed_seq.h @@ -23,6 +23,7 @@ #include #include "absl/base/config.h" +#include "absl/base/internal/endian.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -73,7 +74,7 @@ class ExplicitSeedSeq { template void generate(OutIterator begin, OutIterator end) { for (size_t index = 0; begin != end; begin++) { - *begin = state_.empty() ? 0 : state_[index++]; + *begin = state_.empty() ? 0 : little_endian::FromHost32(state_[index++]); if (index >= state_.size()) { index = 0; } diff --git a/absl/random/internal/randen_engine.h b/absl/random/internal/randen_engine.h index 6b337313..92bb8905 100644 --- a/absl/random/internal/randen_engine.h +++ b/absl/random/internal/randen_engine.h @@ -23,6 +23,7 @@ #include #include +#include "absl/base/internal/endian.h" #include "absl/meta/type_traits.h" #include "absl/random/internal/iostream_state_saver.h" #include "absl/random/internal/randen.h" @@ -76,7 +77,7 @@ class alignas(16) randen_engine { impl_.Generate(state_); } - return state_[next_++]; + return little_endian::ToHost(state_[next_++]); } template @@ -181,7 +182,8 @@ class alignas(16) randen_engine { // In the case that `elem` is `uint8_t`, it must be cast to something // larger so that it prints as an integer rather than a character. For // simplicity, apply the cast all circumstances. - os << static_cast(elem) << os.fill(); + os << static_cast(little_endian::FromHost(elem)) + << os.fill(); } os << engine.next_; return os; @@ -200,7 +202,7 @@ class alignas(16) randen_engine { // necessary to read a wider type and then cast it to uint8_t. numeric_type value; is >> value; - elem = static_cast(value); + elem = little_endian::ToHost(static_cast(value)); } is >> next; if (is.fail()) { diff --git a/absl/random/internal/randen_slow_test.cc b/absl/random/internal/randen_slow_test.cc index 4a535837..4861ffa4 100644 --- a/absl/random/internal/randen_slow_test.cc +++ b/absl/random/internal/randen_slow_test.cc @@ -17,6 +17,7 @@ #include #include "gtest/gtest.h" +#include "absl/base/internal/endian.h" #include "absl/random/internal/randen_traits.h" namespace { @@ -56,7 +57,7 @@ TEST(RandenSlowTest, Default) { uint64_t* id = d.state; for (const auto& elem : kGolden) { - EXPECT_EQ(elem, *id++); + EXPECT_EQ(absl::little_endian::FromHost64(elem), *id++); } } diff --git a/absl/strings/cord.h b/absl/strings/cord.h index 320226d2..fa9cb913 100644 --- a/absl/strings/cord.h +++ b/absl/strings/cord.h @@ -25,7 +25,7 @@ // // Because a Cord consists of these chunks, data can be added to or removed from // a Cord during its lifetime. Chunks may also be shared between Cords. Unlike a -// `std::string`, a Cord can therefore accomodate data that changes over its +// `std::string`, a Cord can therefore accommodate data that changes over its // lifetime, though it's not quite "mutable"; it can change only in the // attachment, detachment, or rearrangement of chunks of its constituent data. // diff --git a/absl/strings/internal/str_format/convert_test.cc b/absl/strings/internal/str_format/convert_test.cc index 375db0a0..926283cf 100644 --- a/absl/strings/internal/str_format/convert_test.cc +++ b/absl/strings/internal/str_format/convert_test.cc @@ -554,7 +554,8 @@ TEST_F(FormatConvertTest, Uint128) { } template -void TestWithMultipleFormatsHelper(const std::vector &floats) { +void TestWithMultipleFormatsHelper(const std::vector &floats, + const std::set &skip_verify) { const NativePrintfTraits &native_traits = VerifyNativeImplementation(); // Reserve the space to ensure we don't allocate memory in the output itself. std::string str_format_result; @@ -602,7 +603,16 @@ void TestWithMultipleFormatsHelper(const std::vector &floats) { AppendPack(&str_format_result, format, absl::MakeSpan(args)); } - if (string_printf_result != str_format_result) { +#ifdef _MSC_VER + // MSVC has a different rounding policy than us so we can't test our + // implementation against the native one there. + continue; +#elif defined(__APPLE__) + // Apple formats NaN differently (+nan) vs. (nan) + if (std::isnan(d)) continue; +#endif + if (string_printf_result != str_format_result && + skip_verify.find(d) == skip_verify.end()) { // We use ASSERT_EQ here because failures are usually correlated and a // bug would print way too many failed expectations causing the test // to time out. @@ -616,12 +626,6 @@ void TestWithMultipleFormatsHelper(const std::vector &floats) { } TEST_F(FormatConvertTest, Float) { -#ifdef _MSC_VER - // MSVC has a different rounding policy than us so we can't test our - // implementation against the native one there. - return; -#endif // _MSC_VER - std::vector floats = {0.0f, -0.0f, .9999999f, @@ -635,7 +639,8 @@ TEST_F(FormatConvertTest, Float) { std::numeric_limits::epsilon(), std::numeric_limits::epsilon() + 1.0f, std::numeric_limits::infinity(), - -std::numeric_limits::infinity()}; + -std::numeric_limits::infinity(), + std::nanf("")}; // Some regression tests. floats.push_back(0.999999989f); @@ -664,21 +669,14 @@ TEST_F(FormatConvertTest, Float) { std::sort(floats.begin(), floats.end()); floats.erase(std::unique(floats.begin(), floats.end()), floats.end()); -#ifndef __APPLE__ - // Apple formats NaN differently (+nan) vs. (nan) - floats.push_back(std::nan("")); -#endif - - TestWithMultipleFormatsHelper(floats); + TestWithMultipleFormatsHelper(floats, {}); } TEST_F(FormatConvertTest, Double) { -#ifdef _MSC_VER - // MSVC has a different rounding policy than us so we can't test our - // implementation against the native one there. - return; -#endif // _MSC_VER - + // For values that we know won't match the standard library implementation we + // skip verification, but still run the algorithm to catch asserts/sanitizer + // bugs. + std::set skip_verify; std::vector doubles = {0.0, -0.0, .99999999999999, @@ -692,7 +690,8 @@ TEST_F(FormatConvertTest, Double) { std::numeric_limits::epsilon(), std::numeric_limits::epsilon() + 1, std::numeric_limits::infinity(), - -std::numeric_limits::infinity()}; + -std::numeric_limits::infinity(), + std::nan("")}; // Some regression tests. doubles.push_back(0.99999999999999989); @@ -722,33 +721,29 @@ TEST_F(FormatConvertTest, Double) { "5084551339423045832369032229481658085593321233482747978262041447231" "68738177180919299881250404026184124858368.000000"; - if (!gcc_bug_22142) { - for (int exp = -300; exp <= 300; ++exp) { - const double all_ones_mantissa = 0x1fffffffffffff; - doubles.push_back(std::ldexp(all_ones_mantissa, exp)); + for (int exp = -300; exp <= 300; ++exp) { + const double all_ones_mantissa = 0x1fffffffffffff; + doubles.push_back(std::ldexp(all_ones_mantissa, exp)); + if (gcc_bug_22142) { + skip_verify.insert(doubles.back()); } } if (gcc_bug_22142) { - for (auto &d : doubles) { - using L = std::numeric_limits; - double d2 = std::abs(d); - if (d2 == L::max() || d2 == L::min() || d2 == L::denorm_min()) { - d = 0; - } - } + using L = std::numeric_limits; + skip_verify.insert(L::max()); + skip_verify.insert(L::min()); // NOLINT + skip_verify.insert(L::denorm_min()); + skip_verify.insert(-L::max()); + skip_verify.insert(-L::min()); // NOLINT + skip_verify.insert(-L::denorm_min()); } // Remove duplicates to speed up the logic below. std::sort(doubles.begin(), doubles.end()); doubles.erase(std::unique(doubles.begin(), doubles.end()), doubles.end()); -#ifndef __APPLE__ - // Apple formats NaN differently (+nan) vs. (nan) - doubles.push_back(std::nan("")); -#endif - - TestWithMultipleFormatsHelper(doubles); + TestWithMultipleFormatsHelper(doubles, skip_verify); } TEST_F(FormatConvertTest, DoubleRound) { @@ -1069,11 +1064,6 @@ TEST_F(FormatConvertTest, ExtremeWidthPrecision) { } TEST_F(FormatConvertTest, LongDouble) { -#ifdef _MSC_VER - // MSVC has a different rounding policy than us so we can't test our - // implementation against the native one there. - return; -#endif // _MSC_VER const NativePrintfTraits &native_traits = VerifyNativeImplementation(); const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000", "%.60", "%+", "% ", "%-10"}; @@ -1134,10 +1124,18 @@ TEST_F(FormatConvertTest, LongDouble) { for (auto d : doubles) { FormatArgImpl arg(d); UntypedFormatSpecImpl format(fmt_str); + std::string result = FormatPack(format, {&arg, 1}); + +#ifdef _MSC_VER + // MSVC has a different rounding policy than us so we can't test our + // implementation against the native one there. + continue; +#endif // _MSC_VER + // We use ASSERT_EQ here because failures are usually correlated and a // bug would print way too many failed expectations causing the test to // time out. - ASSERT_EQ(StrPrint(fmt_str.c_str(), d), FormatPack(format, {&arg, 1})) + ASSERT_EQ(StrPrint(fmt_str.c_str(), d), result) << fmt_str << " " << StrPrint("%.18Lg", d) << " " << StrPrint("%La", d) << " " << StrPrint("%.1080Lf", d); } diff --git a/absl/strings/internal/str_format/float_conversion.cc b/absl/strings/internal/str_format/float_conversion.cc index 2aa41aa7..2b1fd8cb 100644 --- a/absl/strings/internal/str_format/float_conversion.cc +++ b/absl/strings/internal/str_format/float_conversion.cc @@ -112,12 +112,22 @@ inline uint64_t DivideBy10WithCarry(uint64_t *v, uint64_t carry) { return next_carry % divisor; } +constexpr bool IsDoubleDouble() { + // This is the `double-double` representation of `long double`. + // We do not handle it natively. Fallback to snprintf. + return std::numeric_limits::digits == + 2 * std::numeric_limits::digits; +} + +using MaxFloatType = + typename std::conditional::type; + // Generates the decimal representation for an integer of the form `v * 2^exp`, // where `v` and `exp` are both positive integers. // It generates the digits from the left (ie the most significant digit first) // to allow for direct printing into the sink. // -// Requires `0 <= exp` and `exp <= numeric_limits::max_exponent`. +// Requires `0 <= exp` and `exp <= numeric_limits::max_exponent`. class BinaryToDecimal { static constexpr int ChunksNeeded(int exp) { // We will left shift a uint128 by `exp` bits, so we need `128+exp` total @@ -132,10 +142,10 @@ class BinaryToDecimal { static void RunConversion(uint128 v, int exp, absl::FunctionRef f) { assert(exp > 0); - assert(exp <= std::numeric_limits::max_exponent); + assert(exp <= std::numeric_limits::max_exponent); static_assert( static_cast(StackArray::kMaxCapacity) >= - ChunksNeeded(std::numeric_limits::max_exponent), + ChunksNeeded(std::numeric_limits::max_exponent), ""); StackArray::RunWithCapacity( @@ -232,14 +242,14 @@ class BinaryToDecimal { // Converts a value of the form `x * 2^-exp` into a sequence of decimal digits. // Requires `-exp < 0` and -// `-exp >= limits::min_exponent - limits::digits`. +// `-exp >= limits::min_exponent - limits::digits`. class FractionalDigitGenerator { public: // Run the conversion for `v * 2^exp` and call `f(generator)`. // This function will allocate enough stack space to perform the conversion. static void RunConversion( uint128 v, int exp, absl::FunctionRef f) { - using Limits = std::numeric_limits; + using Limits = std::numeric_limits; assert(-exp < 0); assert(-exp >= Limits::min_exponent - 128); static_assert(StackArray::kMaxCapacity >= @@ -871,10 +881,10 @@ void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp, // This buffer holds the "0x1.ab1de3" portion of "0x1.ab1de3pe+2". Compute the // size with long double which is the largest of the floats. constexpr size_t kBufSizeForHexFloatRepr = - 2 // 0x - + std::numeric_limits::digits / 4 // number of hex digits - + 1 // round up - + 1; // "." (dot) + 2 // 0x + + std::numeric_limits::digits / 4 // number of hex digits + + 1 // round up + + 1; // "." (dot) char digits_buffer[kBufSizeForHexFloatRepr]; char *digits_iter = digits_buffer; const char *const digits = @@ -1393,10 +1403,7 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv, bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv, FormatSinkImpl *sink) { - if (std::numeric_limits::digits == - 2 * std::numeric_limits::digits) { - // This is the `double-double` representation of `long double`. - // We do not handle it natively. Fallback to snprintf. + if (IsDoubleDouble()) { return FallbackToSnprintf(v, conv, sink); } diff --git a/absl/synchronization/mutex.h b/absl/synchronization/mutex.h index 4dd51fec..8c6d573d 100644 --- a/absl/synchronization/mutex.h +++ b/absl/synchronization/mutex.h @@ -147,7 +147,7 @@ class ABSL_LOCKABLE Mutex { // // Example usage: // namespace foo { - // ABSL_CONST_INIT Mutex mu(absl::kConstInit); + // ABSL_CONST_INIT absl::Mutex mu(absl::kConstInit); // } explicit constexpr Mutex(absl::ConstInitType); -- cgit v1.2.3