diff --git a/libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp b/libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp deleted file mode 100644 --- a/libcxx/benchmarks/std_format_spec_string_unicode.bench.cpp +++ /dev/null @@ -1,196 +0,0 @@ -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef _LIBCPP_HAS_NO_UNICODE - -#include -#include - -#include "benchmark/benchmark.h" - -#include "test_macros.h" - -template -class tester { - static constexpr size_t size_ = N - 1; - std::array data_; - -public: - explicit constexpr tester(const CharT (&input)[N]) { - auto it = data_.begin(); - for (int i = 0; i < 100; ++i) - it = std::copy_n(input, size_, it); - } - - constexpr size_t size() const noexcept { return data_.size(); } - constexpr const CharT* begin() const noexcept { return data_.begin(); } - constexpr const CharT* end() const noexcept { return data_.end(); } - - void test(benchmark::State& state) const { - for (auto _ : state) - benchmark::DoNotOptimize(std::__format_spec::__get_string_alignment( - begin(), end(), 1'000'000, 1'000'000)); - state.SetItemsProcessed(state.iterations() * size()); - } -}; - -#define TEST(u8) \ - if constexpr (std::same_as) { \ - constexpr auto p = tester{u8}; \ - p.test(state); \ - } else if constexpr (std::same_as) { \ - constexpr auto p = tester{TEST_CONCAT(u, u8)}; \ - p.test(state); \ - } else { \ - constexpr auto p = tester{TEST_CONCAT(U, u8)}; \ - p.test(state); \ - } - -template -static void BM_EstimateLengthNoMultiByte(benchmark::State& state) { - TEST("The quick brown fox jumps over the lazy dog"); -} - -template -static void BM_EstimateLengthTwoByteDE(benchmark::State& state) { - static_assert(sizeof("Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich") == 67); - - // https://en.wikipedia.org/wiki/Pangram - TEST("Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich"); -} - -template -static void BM_EstimateLengthTwoBytePL(benchmark::State& state) { - static_assert(sizeof("Stróż pchnął kość w quiz gędźb vel fax myjń") == 53); - - // https://en.wikipedia.org/wiki/Pangram - TEST("Stróż pchnął kość w quiz gędźb vel fax myjń"); -} - -// All values below are 1100, which is is the first multi column sequence. -template -static void BM_EstimateLengthThreeByteSingleColumnLow(benchmark::State& state) { - static_assert(sizeof("\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807" - "\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f") == - 49); - - TEST("\u0800\u0801\u0802\u0803\u0804\u0805\u0806\u0807" - "\u0808\u0809\u080a\u080b\u080c\u080d\u080e\u080f"); -} - -template -static void -BM_EstimateLengthThreeByteSingleColumnHigh(benchmark::State& state) { - static_assert(sizeof("\u1800\u1801\u1802\u1803\u1804\u1805\u1806\u1807" - "\u1808\u1809\u180a\u180b\u180c\u180d\u180e\u180f") == - 49); - - TEST("\u1800\u1801\u1802\u1803\u1804\u1805\u1806\u1807" - "\u1808\u1809\u180a\u180b\u180c\u180d\u180e\u180f"); -} - -template -static void BM_EstimateLengthThreeByteDoubleColumn(benchmark::State& state) { - static_assert(sizeof("\u1100\u0801\u0802\u0803\u0804\u0805\u0806\u0807" - "\u1108\u0809\u080a\u080b\u080c\u080d\u080e\u080f") == - 49); - - TEST("\u1100\u0801\u0802\u0803\u0804\u0805\u0806\u0807" - "\u1108\u0809\u080a\u080b\u080c\u080d\u080e\u080f"); -} - -template -static void BM_EstimateLengthThreeByte(benchmark::State& state) { - static_assert(sizeof("\u1400\u1501\ubbbb\uff00\u0800\u4099\uabcd\u4000" - "\u8ead\ubeef\u1111\u4987\u4321\uffff\u357a\ud50e") == - 49); - - TEST("\u1400\u1501\ubbbb\uff00\u0800\u4099\uabcd\u4000" - "\u8ead\ubeef\u1111\u4987\u4321\uffff\u357a\ud50e"); -} - -template -static void BM_EstimateLengthFourByteSingleColumn(benchmark::State& state) { - static_assert(sizeof("\U00010000\U00010001\U00010002\U00010003" - "\U00010004\U00010005\U00010006\U00010007" - "\U00010008\U00010009\U0001000a\U0001000b" - "\U0001000c\U0001000d\U0001000e\U0001000f") == 65); - - TEST("\U00010000\U00010001\U00010002\U00010003" - "\U00010004\U00010005\U00010006\U00010007" - "\U00010008\U00010009\U0001000a\U0001000b" - "\U0001000c\U0001000d\U0001000e\U0001000f"); -} - -template -static void BM_EstimateLengthFourByteDoubleColumn(benchmark::State& state) { - static_assert(sizeof("\U00020000\U00020002\U00020002\U00020003" - "\U00020004\U00020005\U00020006\U00020007" - "\U00020008\U00020009\U0002000a\U0002000b" - "\U0002000c\U0002000d\U0002000e\U0002000f") == 65); - - TEST("\U00020000\U00020002\U00020002\U00020003" - "\U00020004\U00020005\U00020006\U00020007" - "\U00020008\U00020009\U0002000a\U0002000b" - "\U0002000c\U0002000d\U0002000e\U0002000f"); -} - -template -static void BM_EstimateLengthFourByte(benchmark::State& state) { - static_assert(sizeof("\U00010000\U00010001\U00010002\U00010003" - "\U00020004\U00020005\U00020006\U00020007" - "\U00010008\U00010009\U0001000a\U0001000b" - "\U0002000c\U0002000d\U0002000e\U0002000f") == 65); - - TEST("\U00010000\U00010001\U00010002\U00010003" - "\U00020004\U00020005\U00020006\U00020007" - "\U00010008\U00010009\U0001000a\U0001000b" - "\U0002000c\U0002000d\U0002000e\U0002000f"); -} - -BENCHMARK_TEMPLATE(BM_EstimateLengthNoMultiByte, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoByteDE, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoBytePL, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnLow, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnHigh, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteDoubleColumn, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByte, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteSingleColumn, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteDoubleColumn, char); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByte, char); - -BENCHMARK_TEMPLATE(BM_EstimateLengthNoMultiByte, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoByteDE, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoBytePL, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnLow, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnHigh, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteDoubleColumn, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByte, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteSingleColumn, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteDoubleColumn, char16_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByte, char16_t); - -BENCHMARK_TEMPLATE(BM_EstimateLengthNoMultiByte, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoByteDE, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthTwoBytePL, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnLow, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteSingleColumnHigh, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByteDoubleColumn, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthThreeByte, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteSingleColumn, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByteDoubleColumn, char32_t); -BENCHMARK_TEMPLATE(BM_EstimateLengthFourByte, char32_t); - -int main(int argc, char** argv) { - benchmark::Initialize(&argc, argv); - if (benchmark::ReportUnrecognizedArguments(argc, argv)) - return 1; - - benchmark::RunSpecifiedBenchmarks(); -} -#else -int main(int, char**) { return 0; } -#endif diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv --- a/libcxx/docs/Status/Cxx20Papers.csv +++ b/libcxx/docs/Status/Cxx20Papers.csv @@ -171,7 +171,7 @@ "`P1460 `__","LWG","Mandating the Standard Library: Clause 20 - Utilities library","Prague","* *","" "`P1739 `__","LWG","Avoid template bloat for safe_ranges in combination with ""subrange-y"" view adaptors","Prague","* *","" "`P1831 `__","LWG","Deprecating volatile: library","Prague","* *","" -"`P1868 `__","LWG","width: clarifying units of width and precision in std::format","Prague","|In Progress|","" +"`P1868 `__","LWG","width: clarifying units of width and precision in std::format","Prague","* *","" "`P1908 `__","CWG","Reserving Attribute Namespaces for Future Use","Prague","* *","" "`P1937 `__","CWG","Fixing inconsistencies between constexpr and consteval functions","Prague","* *","" "`P1956 `__","LWG","On the names of low-level bit manipulation functions","Prague","|Complete|","12.0" diff --git a/libcxx/docs/Status/FormatIssues.csv b/libcxx/docs/Status/FormatIssues.csv --- a/libcxx/docs/Status/FormatIssues.csv +++ b/libcxx/docs/Status/FormatIssues.csv @@ -1,10 +1,10 @@ Number,Name,Assignee,Patch,Status,First released version -`P0645 `_,"Text Formatting",Mark de Wever,,|Partial|, +`P0645 `_,"Text Formatting",Mark de Wever,,|partial|, `P1652 `_,"Printf corner cases in std::format",Mark de Wever,`D103433 `__,|Review|, -`P1892 `_,"Extended locale-specific presentation specifiers for std::format",Mark de Wever,`D103368 `__,|Complete|,Clang 14 -`P1868 `_,"width: clarifying units of width and precision in std::format (Implements the unicode support.)",Mark de Wever,"`D103413 `__ `D103425 `__ `D103670 `__",|Complete|,Clang 14 +`P1892 `_,"Extended locale-specific presentation specifiers for std::format",Mark de Wever,`D103368 `__,|Review|, +`P1868 `_,"width: clarifying units of width and precision in std::format (Implements the unicode support.)",Mark de Wever,"`D103413 `__ `D103425 `__ `D103670 `__",|Review|, `P2216 `_,"std::format improvements",Mark de Wever,,|In Progress|, -`LWG-3242 `_,"std::format: missing rules for arg-id in width and precision",Mark de Wever,`D103368 `__,|Complete|,Clang 14 +`LWG-3242 `_,"std::format: missing rules for arg-id in width and precision",Mark de Wever,`D103368 `__,|Review|, `LWG-3243 `_,"std::format and negative zeroes",,,|Not Started|, `LWG-3246 `_,"What are the constraints on the template parameter of basic_format_arg?",,,|Not Started|, `LWG-3248 `_,"std::format #b, #B, #o, #x, and #X presentation types misformat negative numbers",Mark de Wever,`D103433 `__,|Review|, diff --git a/libcxx/docs/Status/FormatPaper.csv b/libcxx/docs/Status/FormatPaper.csv --- a/libcxx/docs/Status/FormatPaper.csv +++ b/libcxx/docs/Status/FormatPaper.csv @@ -15,10 +15,10 @@ `[format.formatter.spec] `_,"Formatter specializations - integral types",,Mark de Wever,"`D96664 `__ `D103433 `__",|Review|, `[format.formatter.spec] `_,"Formatter specializations - floating-point types",`D70631 `__,Mark de Wever,,|In Progress|, `[format.formatter.spec] `_,"Formatter specializations - pointer types",,Unassigned,,|Not Started|, -`[format.string.std] `_,"Standard format specifiers - character types",,Mark de Wever,`D103368 `__,|Complete|,Clang 14 -`[format.string.std] `_,"Standard format specifiers - string types",`D103379 `__,Mark de Wever,"`D103368 `__ `D103413 `__",|Complete|,Clang 14 -`[format.string.std] `_,"Standard format specifiers - boolean type",`D103379 `__,Mark de Wever,"`D103368 `__ `D103413 `__",|Complete|,Clang 14 -`[format.string.std] `_,"Standard format specifiers - integral types",,Mark de Wever,`D103368 `__,|Complete|,Clang 14 +`[format.string.std] `_,"Standard format specifiers - character types",,Mark de Wever,`D103368 `__,|Review|, +`[format.string.std] `_,"Standard format specifiers - string types",`D103379 `__,Mark de Wever,"`D103368 `__ `D103413 `__",|Review|, +`[format.string.std] `_,"Standard format specifiers - boolean type",`D103379 `__,Mark de Wever,"`D103368 `__ `D103413 `__",|Review|, +`[format.string.std] `_,"Standard format specifiers - integral types",,Mark de Wever,`D103368 `__,|Review|, `[format.string.std] `_,"Standard format specifiers - floating-point types",,Mark de Wever,,|Not Started|, `[format.string.std] `_,"Standard format specifiers - pointer types",,Mark de Wever,,|Not Started|, `[format.functions] `_,"Format functions - format(string_view fmt, const Args&... args);",,Mark de Wever,`D96664 `__,|Complete|,Clang 14 @@ -43,7 +43,6 @@ `[format.functions] `_,"Format functions - formatted_size(wstring_view fmt, const Args&... args);",,Mark de Wever,`D96664 `__,|Complete|,Clang 14 `[format.functions] `_,"Format functions - formatted_size(const locale& loc, string_view fmt, const Args&... args);",,Mark de Wever,`D96664 `__,|Complete|,Clang 14 `[format.functions] `_,"Format functions - formatted_size(const locale& loc, wstring_view fmt, const Args&... args);",,Mark de Wever,`D96664 `__,|Complete|,Clang 14 -`[format.functions] `_,"Format functions - Improve performance format_to_n",,Mark de Wever,`D110499 `__,|Review|, -`[format.functions] `_,"Format functions - Improve performance formatted size",,Mark de Wever,`D110500 `__,|Review|, -`[format.functions] `_,"`P2216 `_ - Compile-time checks",,Mark de Wever,,|In Progress|, -`[format.functions] `_,"`P2216 `_ - Binary size",,Mark de Wever,`D110494 `__,|Review|, +`[format.functions] `_,"Format functions - Implement locale support",,Mark de Wever,,|In Progress|, +`[format.functions] `_,"Format functions - Improve performance format_to_n",,Mark de Wever,,|Not Started|, +`[format.functions] `_,"Format functions - Improve performance formatted size",,Mark de Wever,,|Not Started|, diff --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h --- a/libcxx/include/__format/parser_std_format_spec.h +++ b/libcxx/include/__format/parser_std_format_spec.h @@ -10,15 +10,12 @@ #ifndef _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H #define _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H -#include <__algorithm/find_if.h> -#include <__algorithm/min.h> #include <__config> #include <__debug> #include <__format/format_arg.h> #include <__format/format_error.h> #include <__format/format_string.h> #include <__variant/monostate.h> -#include #include #include #include @@ -27,9 +24,6 @@ # pragma GCC system_header #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER > 17 @@ -717,462 +711,6 @@ // TODO FMT Add a parser for floating-point values. // TODO FMT Add a parser for pointer values. -/** Helper struct returned from @ref __get_string_alignment. */ -template -struct _LIBCPP_TEMPLATE_VIS __string_alignment { - /** Points beyond the last character to write to the output. */ - const _CharT* __last; - /** - * The estimated number of columns in the output or 0. - * - * Only when the output needs to be aligned it's required to know the exact - * number of columns in the output. So if the formatted output has only a - * minimum width the exact size isn't important. It's only important to know - * the minimum has been reached. The minimum width is the width specified in - * the format-spec. - * - * For example in this code @code std::format("{:10}", MyString); @endcode - * the width estimation can stop once the algorithm has determined the output - * width is 10 columns. - * - * So if: - * * @ref __align == @c true the @ref __size is the estimated number of - * columns required. - * * @ref __align == @c false the @ref __size is the estimated number of - * columns required or 0 when the estimation algorithm stopped prematurely. - */ - ptrdiff_t __size; - /** - * Does the output need to be aligned. - * - * When alignment is needed the output algorithm needs to add the proper - * padding. Else the output algorithm just needs to copy the input up to - * @ref __last. - */ - bool __align; -}; - -#ifndef _LIBCPP_HAS_NO_UNICODE -namespace __detail { - -/** - * Unicode column width estimates. - * - * Unicode can be stored in several formats: UTF-8, UTF-16, and UTF-32. - * Depending on format the relation between the number of code units stored and - * the number of output columns differs. The first relation is the number of - * code units forming a code point. (The text assumes the code units are - * unsigned.) - * - UTF-8 The number of code units is between one and four. The first 127 - * Unicode code points match the ASCII character set. When the highest bit is - * set it means the code point has more than one code unit. - * - UTF-16: The number of code units is between 1 and 2. When the first - * code unit is in the range [0xd800,0xdfff) it means the code point uses two - * code units. - * - UTF-32: The number of code units is always one. - * - * The code point to the number of columns isn't well defined. The code uses the - * estimations defined in [format.string.std]/11. This list might change in the - * future. - * - * The algorithm of @ref __get_string_alignment uses two different scanners: - * - The simple scanner @ref __estimate_column_width_fast. This scanner assumes - * 1 code unit is 1 column. This scanner stops when it can't be sure the - * assumption is valid: - * - UTF-8 when the code point is encoded in more than 1 code unit. - * - UTF-16 and UTF-32 when the first multi-column code point is encountered. - * (The code unit's value is lower than 0xd800 so the 2 code unit encoding - * is irrelevant for this scanner.) - * Due to these assumptions the scanner is faster than the full scanner. It - * can process all text only containing ASCII. For UTF-16/32 it can process - * most (all?) European languages. (Note the set it can process might be - * reduced in the future, due to updates in the scanning rules.) - * - The full scanner @ref __estimate_column_width. This scanner, if needed, - * converts multiple code units into one code point then converts the code - * point to a column width. - * - * See also: - * - [format.string.general]/11 - * - https://en.wikipedia.org/wiki/UTF-8#Encoding - * - https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF - */ - -/** - * The first 2 column code point. - * - * This is the point where the fast UTF-16/32 scanner needs to stop processing. - */ -inline constexpr uint32_t __two_column_code_point = 0x1100; - -/** Helper concept for an UTF-8 character type. */ -template -concept __utf8_character = same_as<_CharT, char> || same_as<_CharT, char8_t>; - -/** Helper concept for an UTF-16 character type. */ -template -concept __utf16_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 2) || same_as<_CharT, char16_t>; - -/** Helper concept for an UTF-32 character type. */ -template -concept __utf32_character = (same_as<_CharT, wchar_t> && sizeof(wchar_t) == 4) || same_as<_CharT, char32_t>; - -/** Helper concept for an UTF-16 or UTF-32 character type. */ -template -concept __utf16_or_32_character = __utf16_character<_CharT> || __utf32_character<_CharT>; - -/** - * Converts a code point to the column width. - * - * The estimations are conforming to [format.string.general]/11 - * - * This version expects a value less than 0x1'0000, which is a 3-byte UTF-8 - * character. - */ -_LIBCPP_HIDE_FROM_ABI inline constexpr int __column_width_3(uint32_t __c) noexcept { - _LIBCPP_ASSERT(__c < 0x1'0000, - "Use __column_width_4 or __column_width for larger values"); - - // clang-format off - return 1 + (__c >= 0x1100 && (__c <= 0x115f || - (__c >= 0x2329 && (__c <= 0x232a || - (__c >= 0x2e80 && (__c <= 0x303e || - (__c >= 0x3040 && (__c <= 0xa4cf || - (__c >= 0xac00 && (__c <= 0xd7a3 || - (__c >= 0xf900 && (__c <= 0xfaff || - (__c >= 0xfe10 && (__c <= 0xfe19 || - (__c >= 0xfe30 && (__c <= 0xfe6f || - (__c >= 0xff00 && (__c <= 0xff60 || - (__c >= 0xffe0 && (__c <= 0xffe6 - )))))))))))))))))))); - // clang-format on -} - -/** - * @overload - * - * This version expects a value greater than or equal to 0x1'0000, which is a - * 4-byte UTF-8 character. - */ -_LIBCPP_HIDE_FROM_ABI inline constexpr int __column_width_4(uint32_t __c) noexcept { - _LIBCPP_ASSERT(__c >= 0x1'0000, - "Use __column_width_3 or __column_width for smaller values"); - - // clang-format off - return 1 + (__c >= 0x1'f300 && (__c <= 0x1'f64f || - (__c >= 0x1'f900 && (__c <= 0x1'f9ff || - (__c >= 0x2'0000 && (__c <= 0x2'fffd || - (__c >= 0x3'0000 && (__c <= 0x3'fffd - )))))))); - // clang-format on -} - -/** - * @overload - * - * The general case, accepting all values. - */ -_LIBCPP_HIDE_FROM_ABI inline constexpr int __column_width(uint32_t __c) noexcept { - if (__c < 0x1'0000) - return __column_width_3(__c); - - return __column_width_4(__c); -} - -/** - * Estimate the column width for the UTF-8 sequence using the fast algorithm. - */ -template <__utf8_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* -__estimate_column_width_fast(const _CharT* __first, - const _CharT* __last) noexcept { - return _VSTD::find_if(__first, __last, - [](unsigned char __c) { return __c & 0x80; }); -} - -/** - * @overload - * - * The implementation for UTF-16/32. - */ -template <__utf16_or_32_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr const _CharT* -__estimate_column_width_fast(const _CharT* __first, - const _CharT* __last) noexcept { - return _VSTD::find_if(__first, __last, - [](uint32_t __c) { return __c >= 0x1100; }); -} - -template -struct _LIBCPP_TEMPLATE_VIS __column_width_result { - /** The number of output columns. */ - size_t __width; - /** - * The last parsed element. - * - * This limits the original output to fit in the wanted number of columns. - */ - const _CharT* __ptr; -}; - -/** - * Small helper to determine the width of malformed Unicode. - * - * @note This function's only needed for UTF-8. During scanning UTF-8 there - * are multiple place where it can be detected that the Unicode is malformed. - * UTF-16 only requires 1 test and UTF-32 requires no testing. - */ -template <__utf8_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> -__estimate_column_width_malformed(const _CharT* __first, const _CharT* __last, - size_t __maximum, size_t __result) noexcept { - size_t __size = __last - __first; - size_t __n = _VSTD::min(__size, __maximum); - return {__result + __n, __first + __n}; -} - -/** - * Determines the number of output columns needed to render the input. - * - * @note When the scanner encounters malformed Unicode it acts as-if every code - * unit at the end of the input is one output column. It's expected the output - * terminal will replace these malformed code units with a one column - * replacement characters. - * - * @param __first Points to the first element of the input range. - * @param __last Points beyond the last element of the input range. - * @param __maximum The maximum number of output columns. The returned number - * of estimated output columns will not exceed this value. - */ -template <__utf8_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> -__estimate_column_width(const _CharT* __first, const _CharT* __last, - size_t __maximum) noexcept { - size_t __result = 0; - - while (__first != __last) { - // Based on the number of leading 1 bits the number of code units in the - // code point can be determined. See - // https://en.wikipedia.org/wiki/UTF-8#Encoding - switch (_VSTD::countl_one(static_cast(*__first))) { - case 0: // 1-code unit encoding: all 1 column - ++__result; - ++__first; - break; - - case 2: // 2-code unit encoding: all 1 column - // Malformed Unicode. - if (__last - __first < 2) [[unlikely]] - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - __first += 2; - ++__result; - break; - - case 3: // 3-code unit encoding: either 1 or 2 columns - // Malformed Unicode. - if (__last - __first < 3) [[unlikely]] - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - { - uint32_t __c = static_cast(*__first++) & 0x0f; - __c <<= 6; - __c |= static_cast(*__first++) & 0x3f; - __c <<= 6; - __c |= static_cast(*__first++) & 0x3f; - __result += __column_width_3(__c); - if (__result > __maximum) - return {__result - 2, __first - 3}; - } - break; - case 4: // 4-code unit encoding: either 1 or 2 columns - // Malformed Unicode. - if (__last - __first < 4) [[unlikely]] - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - { - uint32_t __c = static_cast(*__first++) & 0x07; - __c <<= 6; - __c |= static_cast(*__first++) & 0x3f; - __c <<= 6; - __c |= static_cast(*__first++) & 0x3f; - __c <<= 6; - __c |= static_cast(*__first++) & 0x3f; - __result += __column_width_4(__c); - if (__result > __maximum) - return {__result - 2, __first - 4}; - } - break; - default: - // Malformed Unicode. - return __estimate_column_width_malformed(__first, __last, __maximum, - __result); - } - - if (__result >= __maximum) - return {__result, __first}; - } - return {__result, __first}; -} - -template <__utf16_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> -__estimate_column_width(const _CharT* __first, const _CharT* __last, - size_t __maximum) noexcept { - size_t __result = 0; - - while (__first != __last) { - uint32_t __c = *__first; - // Is the code unit part of a surrogate pair? See - // https://en.wikipedia.org/wiki/UTF-16#U+D800_to_U+DFFF - if (__c >= 0xd800 && __c <= 0xDfff) { - // Malformed Unicode. - if (__last - __first < 2) [[unlikely]] - return {__result + 1, __first + 1}; - - __c -= 0xd800; - __c <<= 10; - __c += (*(__first + 1) - 0xdc00); - __c += 0x10'000; - - __result += __column_width_4(__c); - if (__result > __maximum) - return {__result - 2, __first}; - __first += 2; - } else { - __result += __column_width_3(__c); - if (__result > __maximum) - return {__result - 2, __first}; - ++__first; - } - - if (__result >= __maximum) - return {__result, __first}; - } - - return {__result, __first}; -} - -template <__utf32_character _CharT> -_LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> -__estimate_column_width(const _CharT* __first, const _CharT* __last, - size_t __maximum) noexcept { - size_t __result = 0; - - while (__first != __last) { - wchar_t __c = *__first; - __result += __column_width(__c); - - if (__result > __maximum) - return {__result - 2, __first}; - - ++__first; - if (__result >= __maximum) - return {__result, __first}; - } - - return {__result, __first}; -} - -} // namespace __detail - -template -_LIBCPP_HIDE_FROM_ABI constexpr __string_alignment<_CharT> -__get_string_alignment(const _CharT* __first, const _CharT* __last, - ptrdiff_t __width, ptrdiff_t __precision) noexcept { - _LIBCPP_ASSERT(__width != 0 || __precision != -1, - "The function has no effect and shouldn't be used"); - - // TODO FMT There might be more optimizations possible: - // If __precision == __format::__number_max and the encoding is: - // * UTF-8 : 4 * (__last - __first) >= __width - // * UTF-16 : 2 * (__last - __first) >= __width - // * UTF-32 : (__last - __first) >= __width - // In these cases it's certain the output is at least the requested width. - // It's unknown how often this happens in practice. For now the improvement - // isn't implemented. - - /* - * First assume there are no special Unicode code units in the input. - * - Apply the precision (this may reduce the size of the input). When - * __precison == -1 this step is omitted. - * - Scan for special code units in the input. - * If our assumption was correct the __pos will be at the end of the input. - */ - const ptrdiff_t __length = __last - __first; - const _CharT* __limit = - __first + - (__precision == -1 ? __length : _VSTD::min(__length, __precision)); - ptrdiff_t __size = __limit - __first; - const _CharT* __pos = - __detail::__estimate_column_width_fast(__first, __limit); - - if (__pos == __limit) - return {__limit, __size, __size < __width}; - - /* - * Our assumption was wrong, there are special Unicode code units. - * The range [__first, __pos) contains a set of code units with the - * following property: - * Every _CharT in the range will be rendered in 1 column. - * - * If there's no maximum width and the parsed size already exceeds the - * minimum required width. The real size isn't important. So bail out. - */ - if (__precision == -1 && (__pos - __first) >= __width) - return {__last, 0, false}; - - /* If there's a __precision, truncate the output to that width. */ - ptrdiff_t __prefix = __pos - __first; - if (__precision != -1) { - _LIBCPP_ASSERT(__precision > __prefix, "Logic error."); - auto __lengh_info = __detail::__estimate_column_width( - __pos, __last, __precision - __prefix); - __size = __lengh_info.__width + __prefix; - return {__lengh_info.__ptr, __size, __size < __width}; - } - - /* Else use __width to determine the number of required padding characters. */ - _LIBCPP_ASSERT(__width > __prefix, "Logic error."); - /* - * The column width is always one or two columns. For the precision the wanted - * column width is the maximum, for the width it's the minimum. Using the - * width estimation with its truncating behavior will result in the wrong - * result in the following case: - * - The last code unit processed requires two columns and exceeds the - * maximum column width. - * By increasing the __maximum by one avoids this issue. (It means it may - * pass one code point more than required to determine the proper result; - * that however isn't a problem for the algorithm.) - */ - size_t __maximum = 1 + __width - __prefix; - auto __lengh_info = - __detail::__estimate_column_width(__pos, __last, __maximum); - if (__lengh_info.__ptr != __last) { - // Consumed the width number of code units. The exact size of the string - // is unknown. We only know we don't need to align the output. - _LIBCPP_ASSERT(static_cast(__lengh_info.__width + __prefix) >= - __width, - "Logic error"); - return {__last, 0, false}; - } - - __size = __lengh_info.__width + __prefix; - return {__last, __size, __size < __width}; -} -#else // _LIBCPP_HAS_NO_UNICODE -template -_LIBCPP_HIDE_FROM_ABI constexpr __string_alignment<_CharT> -__get_string_alignment(const _CharT* __first, const _CharT* __last, - ptrdiff_t __width, ptrdiff_t __precision) noexcept { - const ptrdiff_t __length = __last - __first; - const _CharT* __limit = - __first + - (__precision == -1 ? __length : _VSTD::min(__length, __precision)); - ptrdiff_t __size = __limit - __first; - return {__limit, __size, __size < __width}; -} -#endif // _LIBCPP_HAS_NO_UNICODE - } // namespace __format_spec # endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) @@ -1181,6 +719,4 @@ _LIBCPP_END_NAMESPACE_STD -_LIBCPP_POP_MACROS - #endif // _LIBCPP___FORMAT_PARSER_STD_FORMAT_SPEC_H diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h --- a/libcxx/include/__ranges/iota_view.h +++ b/libcxx/include/__ranges/iota_view.h @@ -9,16 +9,6 @@ #ifndef _LIBCPP___RANGES_IOTA_VIEW_H #define _LIBCPP___RANGES_IOTA_VIEW_H -#include <__compare/three_way_comparable.h> -#include <__concepts/arithmetic.h> -#include <__concepts/constructible.h> -#include <__concepts/convertible_to.h> -#include <__concepts/copyable.h> -#include <__concepts/equality_comparable.h> -#include <__concepts/invocable.h> -#include <__concepts/same_as.h> -#include <__concepts/semiregular.h> -#include <__concepts/totally_ordered.h> #include <__config> #include <__debug> #include <__functional/ranges_operations.h> @@ -31,6 +21,7 @@ #include <__ranges/view_interface.h> #include <__utility/forward.h> #include <__utility/move.h> +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -221,11 +212,11 @@ return !(__x < __y); } - friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) - requires totally_ordered<_Start> && three_way_comparable<_Start> - { - return __x.__value_ <=> __y.__value_; - } +// friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) +// requires totally_ordered<_Start> && three_way_comparable<_Start> +// { +// return __x.__value_ <=> __y.__value_; +// } _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n) diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h --- a/libcxx/include/__ranges/transform_view.h +++ b/libcxx/include/__ranges/transform_view.h @@ -9,13 +9,6 @@ #ifndef _LIBCPP___RANGES_TRANSFORM_VIEW_H #define _LIBCPP___RANGES_TRANSFORM_VIEW_H -#include <__compare/three_way_comparable.h> -#include <__concepts/constructible.h> -#include <__concepts/convertible_to.h> -#include <__concepts/copyable.h> -#include <__concepts/derived_from.h> -#include <__concepts/equality_comparable.h> -#include <__concepts/invocable.h> #include <__config> #include <__functional/bind_back.h> #include <__functional/invoke.h> @@ -34,6 +27,7 @@ #include <__utility/forward.h> #include <__utility/in_place.h> #include <__utility/move.h> +#include #include #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) @@ -303,14 +297,13 @@ return __x.__current_ >= __y.__current_; } -#if !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) - _LIBCPP_HIDE_FROM_ABI - friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) - requires random_access_range<_Base> && three_way_comparable> - { - return __x.__current_ <=> __y.__current_; - } -#endif // !defined(_LIBCPP_HAS_NO_SPACESHIP_OPERATOR) +// TODO: Fix this as soon as soon as three_way_comparable is implemented. +// _LIBCPP_HIDE_FROM_ABI +// friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) +// requires random_access_range<_Base> && three_way_comparable> +// { +// return __x.__current_ <=> __y.__current_; +// } _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(__iterator __i, difference_type __n) diff --git a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_string_non_unicode.pass.cpp b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_string_non_unicode.pass.cpp deleted file mode 100644 --- a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_string_non_unicode.pass.cpp +++ /dev/null @@ -1,110 +0,0 @@ -//===----------------------------------------------------------------------===// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: libcpp-no-concepts -// UNSUPPORTED: libcpp-has-no-incomplete-format - -// UTF-32 doesn't work properly -// XFAIL: windows - -// - -// Tests the Unicode width support of the standard format specifiers. -// It tests [format.string.std]/8 - 11: -// - Properly determining the estimated with of a unicode string. -// - Properly truncating to the wanted maximum width. - -// This version runs the test when the platform doesn't have Unicode support. -// REQUIRES: libcpp-has-no-unicode - -#include -#include - -#include "test_macros.h" -#include "make_string.h" - -#define CSTR(S) MAKE_CSTRING(CharT, S) - -using namespace std::__format_spec; - -template -constexpr bool operator==(const __string_alignment& lhs, - const __string_alignment& rhs) noexcept { - return lhs.__last == rhs.__last && lhs.__size == rhs.__size && - lhs.__align == rhs.__align; -} - -template -constexpr void get_string_alignment(size_t offset, ptrdiff_t size, bool align, - const CharT* str, size_t width, - size_t precision) { - std::basic_string_view sv{str}; - __string_alignment expected{sv.begin() + offset, size, align}; - __string_alignment traits = - __get_string_alignment(sv.begin(), sv.end(), width, precision); - assert(traits == expected); -} - -template -constexpr void get_string_alignment() { - // Truncate the input. - get_string_alignment(2, 2, false, CSTR("abc"), 0, 2); - - // The 2-column character gets half accepted. - get_string_alignment(2, 2, false, CSTR("a\u115f"), 0, 2); - - // No alignment since the number of characters fits. - get_string_alignment(2, 2, false, CSTR("a\u115f"), 2, 2); - - // Same but for a 2-column 4-byte UTF-8 sequence - get_string_alignment(2, 2, false, CSTR("a\U0001f300"), 0, 2); - get_string_alignment(2, 2, false, CSTR("a\U0001f300"), 2, 2); - - // No alignment required. - get_string_alignment(3, 3, false, CSTR("abc"), 2, -1); - get_string_alignment(3, 3, false, CSTR("abc"), 3, -1); - - get_string_alignment(3 + 2 * (sizeof(CharT) == 1), - 3 + 2 * (sizeof(CharT) == 1), false, CSTR("ab\u1111"), 2, - -1); - - // Doesn't evaluate 'c' so size -> 0 - get_string_alignment(3 + 2 * (sizeof(CharT) == 1), - 3 + 2 * (sizeof(CharT) == 1), false, - CSTR("a\u115fc") /* 2-column character */, 3, -1); - // Extend width - get_string_alignment(3, 3, true, CSTR("abc"), 4, -1); - get_string_alignment(3 + 2 * (sizeof(CharT) == 1), - 3 + 2 * (sizeof(CharT) == 1), true, - CSTR("a\u1160c") /* 1-column character */, 6, -1); -} - -template -constexpr void test() { - get_string_alignment(); -} - -constexpr bool test() { - test(); - test(); -#ifndef _LIBCPP_HAS_NO_CHAR8_T - test(); -#endif -#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS - test(); - test(); -#endif - return true; -} - -int main(int, char**) { - test(); - static_assert(test()); - - return 0; -} diff --git a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_string_unicode.pass.cpp b/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_string_unicode.pass.cpp deleted file mode 100644 --- a/libcxx/test/libcxx/utilities/format/format.string/format.string.std/std_format_spec_string_unicode.pass.cpp +++ /dev/null @@ -1,270 +0,0 @@ -//===----------------------------------------------------------------------===// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// UNSUPPORTED: c++03, c++11, c++14, c++17 -// UNSUPPORTED: libcpp-no-concepts -// UNSUPPORTED: libcpp-has-no-incomplete-format - -// UTF-32 doesn't work properly -// XFAIL: windows - -// - -// Tests the Unicode width support of the standard format specifiers. -// It tests [format.string.std]/8 - 11: -// - Properly determining the estimated with of a unicode string. -// - Properly truncating to the wanted maximum width. - -// This version runs the test when the platform has Unicode support. -// UNSUPPORTED: libcpp-has-no-unicode - -#include -#include - -#include "test_macros.h" -#include "make_string.h" - -#define CSTR(S) MAKE_CSTRING(CharT, S) - -using namespace std::__format_spec; - -template -constexpr bool operator==(const __string_alignment& lhs, - const __string_alignment& rhs) noexcept { - return lhs.__last == rhs.__last && lhs.__size == rhs.__size && - lhs.__align == rhs.__align; -} - -template -constexpr void get_string_alignment(size_t offset, ptrdiff_t size, bool align, - const CharT* str, size_t width, - size_t precision) { - std::basic_string_view sv{str}; - __string_alignment expected{sv.begin() + offset, size, align}; - __string_alignment traits = - __get_string_alignment(sv.begin(), sv.end(), width, precision); - assert(traits == expected); -} - -template -constexpr void estimate_column_width_fast(size_t expected, const CharT* str) { - std::basic_string_view sv{str}; - const CharT* out = - __detail::__estimate_column_width_fast(sv.begin(), sv.end()); - assert(out == sv.begin() + expected); -} - -template -constexpr void estimate_column_width_fast() { - - // No unicode - estimate_column_width_fast(3, CSTR("abc")); - estimate_column_width_fast(3, CSTR("a\u007fc")); - - if constexpr (sizeof(CharT) == 1) { - // UTF-8 stop at the first multi-byte character. - estimate_column_width_fast(0, CSTR("\u0080bc")); - estimate_column_width_fast(1, CSTR("a\u0080c")); - estimate_column_width_fast(2, CSTR("ab\u0080")); - estimate_column_width_fast(1, CSTR("aßc")); - - estimate_column_width_fast(1, CSTR("a\u07ffc")); - estimate_column_width_fast(1, CSTR("a\u0800c")); - - estimate_column_width_fast(1, CSTR("a\u10ffc")); - } else { - // UTF-16/32 stop at the first multi-column character. - estimate_column_width_fast(3, CSTR("\u0080bc")); - estimate_column_width_fast(3, CSTR("a\u0080c")); - estimate_column_width_fast(3, CSTR("ab\u0080")); - estimate_column_width_fast(3, CSTR("aßc")); - - estimate_column_width_fast(3, CSTR("a\u07ffc")); - estimate_column_width_fast(3, CSTR("a\u0800c")); - - estimate_column_width_fast(3, CSTR("a\u10ffc")); - } - // First 2-column character - estimate_column_width_fast(1, CSTR("a\u1100c")); - - estimate_column_width_fast(1, CSTR("a\U0000ffffc")); - estimate_column_width_fast(1, CSTR("a\U00010000c")); - estimate_column_width_fast(1, CSTR("a\U0010FFFFc")); -} - -template -constexpr void estimate_column_width(size_t expected, const CharT* str) { - std::basic_string_view sv{str}; - std::__format_spec::__detail::__column_width_result column_info = - __detail::__estimate_column_width(sv.begin(), sv.end(), -1); - assert(column_info.__width == expected); -} - -template -constexpr void estimate_column_width() { - //*** 1-byte code points *** - estimate_column_width(1, CSTR(" ")); - estimate_column_width(1, CSTR("~")); - - //*** 2-byte code points *** - estimate_column_width(1, CSTR("\u00a1")); // INVERTED EXCLAMATION MARK - estimate_column_width(1, CSTR("\u07ff")); // NKO TAMAN SIGN - - //*** 3-byte code points *** - estimate_column_width(1, CSTR("\u0800")); // SAMARITAN LETTER ALAF - estimate_column_width(1, CSTR("\ufffd")); // REPLACEMENT CHARACTER - - // 2 column ranges - estimate_column_width(2, CSTR("\u1100")); // HANGUL CHOSEONG KIYEOK - estimate_column_width(2, CSTR("\u115f")); // HANGUL CHOSEONG FILLER - - estimate_column_width(2, CSTR("\u2329")); // LEFT-POINTING ANGLE BRACKET - estimate_column_width(2, CSTR("\u232a")); // RIGHT-POINTING ANGLE BRACKET - - estimate_column_width(2, CSTR("\u2e80")); // CJK RADICAL REPEAT - estimate_column_width(2, CSTR("\u303e")); // IDEOGRAPHIC VARIATION INDICATOR - - estimate_column_width(2, CSTR("\u3040")); // U+3041 HIRAGANA LETTER SMALL A - estimate_column_width(2, CSTR("\ua4cf")); // U+A4D0 LISU LETTER BA - - estimate_column_width(2, CSTR("\uac00")); // - estimate_column_width(2, CSTR("\ud7a3")); // Hangul Syllable Hih - - estimate_column_width(2, CSTR("\uf900")); // CJK COMPATIBILITY IDEOGRAPH-F900 - estimate_column_width(2, CSTR("\ufaff")); // U+FB00 LATIN SMALL LIGATURE FF - - estimate_column_width(2, - CSTR("\ufe10")); // PRESENTATION FORM FOR VERTICAL COMMA - estimate_column_width( - 2, CSTR("\ufe19")); // PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS - - estimate_column_width( - 2, CSTR("\ufe30")); // PRESENTATION FORM FOR VERTICAL TWO DOT LEADER - estimate_column_width(2, - CSTR("\ufe6f")); // U+FE70 ARABIC FATHATAN ISOLATED FORM - - estimate_column_width(2, CSTR("\uff00")); // U+FF01 FULLWIDTH EXCLAMATION MARK - estimate_column_width(2, CSTR("\uff60")); // FULLWIDTH RIGHT WHITE PARENTHESIS - - estimate_column_width(2, CSTR("\uffe0")); // FULLWIDTH CENT SIGN - estimate_column_width(2, CSTR("\uffe6")); // FULLWIDTH WON SIGN - - //*** 4-byte code points *** - estimate_column_width(1, CSTR("\U00010000")); // LINEAR B SYLLABLE B008 A - estimate_column_width(1, CSTR("\U0010FFFF")); // Undefined Character - - // 2 column ranges - estimate_column_width(2, CSTR("\U0001f300")); // CYCLONE - estimate_column_width(2, CSTR("\U0001f64f")); // PERSON WITH FOLDED HANDS - estimate_column_width( - 2, CSTR("\U0001f900")); // CIRCLED CROSS FORMEE WITH FOUR DOTS - estimate_column_width(2, CSTR("\U0001f9ff")); // NAZAR AMULET - estimate_column_width( - 2, CSTR("\U00020000")); // - estimate_column_width(2, CSTR("\U0002fffd")); // Undefined Character - estimate_column_width( - 2, CSTR("\U00030000")); // - estimate_column_width(2, CSTR("\U0003fffd")); // Undefined Character -} - -template -constexpr void get_string_alignment() { - // Truncate the input. - get_string_alignment(2, 2, false, CSTR("abc"), 0, 2); - - // The 2-column character gets entirely rejected. - get_string_alignment(1, 1, false, CSTR("a\u115f"), 0, 2); - - // Due to the requested width extra alignment is required. - get_string_alignment(1, 1, true, CSTR("a\u115f"), 2, 2); - - // Same but for a 2-column 4-byte UTF-8 sequence - get_string_alignment(1, 1, false, CSTR("a\U0001f300"), 0, 2); - get_string_alignment(1, 1, true, CSTR("a\U0001f300"), 2, 2); - - // No alignment required. - get_string_alignment(3, 3, false, CSTR("abc"), 2, -1); - get_string_alignment(3, 3, false, CSTR("abc"), 3, -1); - - // Special case, we have a special character already parsed and have enough - // withd to satisfy the minumum required width. - get_string_alignment(3 + 2 * (sizeof(CharT) == 1), 0, false, CSTR("ab\u1111"), - 2, -1); - - // Evaluates all so size ->4 - get_string_alignment(3 + 2 * (sizeof(CharT) == 1), 4, false, - CSTR("a\u115fc") /* 2-column character */, 3, -1); - // Evaluates all so size ->4 - get_string_alignment(3 + 2 * (sizeof(CharT) == 1), 4, false, - CSTR("a\u115fc") /* 2-column character */, 4, -1); - - // Evaluates all so size ->5 - get_string_alignment(4 + 2 * (sizeof(CharT) == 1), 5, false, - CSTR("a\u115fcd") /* 2-column character */, 4, -1); - - // Evaluates all so size ->5 - get_string_alignment(4 + 2 * (sizeof(CharT) == 1), 5, false, - CSTR("a\u115fcd") /* 2-column character */, 5, -1); - - // Extend width - get_string_alignment(3, 3, true, CSTR("abc"), 4, -1); - get_string_alignment(3 + 2 * (sizeof(CharT) == 1), 3, true, - CSTR("a\u1160c") /* 1-column character */, 4, -1); - - // In this case the threshold where the width is still determined. - get_string_alignment(2 + 2 * (sizeof(CharT) == 1), 3, false, CSTR("i\u1110"), - 2, -1); - - // The width is no longer exactly determined. - get_string_alignment(2 + 2 * (sizeof(CharT) == 1), 0, false, CSTR("i\u1110"), - 1, -1); - - // Extend width and truncate input. - get_string_alignment(1, 1, true, CSTR("abc"), 3, 1); - - if constexpr (sizeof(CharT) == 1) { - // Corrupt UTF-8 sequence. - get_string_alignment(2, 2, false, CSTR("a\xc0"), 0, 3); - get_string_alignment(2, 2, false, CSTR("a\xe0"), 0, 3); - get_string_alignment(2, 2, false, CSTR("a\xf0"), 0, 3); - } else if constexpr (sizeof(CharT) == 2) { - // Corrupt UTF-16 sequence. - if constexpr (std::same_as) - get_string_alignment(2, 2, false, u"a\xdddd", 0, 3); - else - // Corrupt UTF-16 wchar_t seqence. - get_string_alignment(2, 2, false, L"a\xdddd", 0, 3); - } - // UTF-32 doesn't combine characters, thus no corruption tests. -} - -template -constexpr void test() { - estimate_column_width_fast(); - estimate_column_width(); - get_string_alignment(); -} - -constexpr bool test() { - test(); - test(); -#ifndef _LIBCPP_HAS_NO_CHAR8_T - test(); -#endif -#ifndef _LIBCPP_HAS_NO_UNICODE_CHARS - test(); - test(); -#endif - return true; -} - -int main(int, char**) { - test(); - static_assert(test()); - - return 0; -} diff --git a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp --- a/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp +++ b/libcxx/test/std/containers/sequences/vector/vector.capacity/shrink_to_fit.pass.cpp @@ -37,7 +37,7 @@ assert(v.size() == 101); assert(is_contiguous_container_asan_correct(v)); } -#ifndef TEST_HAS_NO_EXCEPTIONS +#ifndef _LIBCPP_NO_EXCEPTIONS { std::vector > v(100); v.push_back(1); diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/compare.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/compare.pass.cpp --- a/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/compare.pass.cpp +++ b/libcxx/test/std/ranges/range.adaptors/range.transform/iterator/compare.pass.cpp @@ -10,59 +10,51 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: libcpp-has-no-incomplete-ranges -// transform_view::::operator{<,>,<=,>=,==,!=,<=>} +// transform_view::::operator{<,>,<=,>=} #include #include #include "test_macros.h" -#include "test_iterators.h" #include "../types.h" constexpr bool test() { { - // Test a new-school iterator with operator<=>; the transform iterator should also have operator<=>. - using It = three_way_contiguous_iterator; - static_assert(std::three_way_comparable); - using R = std::ranges::transform_view, PlusOne>; - static_assert(std::three_way_comparable>); + std::ranges::transform_view transformView1; + auto iter1 = std::move(transformView1).begin(); + std::ranges::transform_view transformView2; + auto iter2 = std::move(transformView2).begin(); + assert(iter1 == iter2); + assert(iter1 + 1 != iter2); + assert(iter1 + 1 == iter2 + 1); - int a[] = {1,2,3}; - std::same_as auto r = std::ranges::subrange(It(a), It(a+3)) | std::views::transform(PlusOne()); - auto iter1 = r.begin(); - auto iter2 = iter1 + 1; - - assert(!(iter1 < iter1)); assert(iter1 < iter2); assert(!(iter2 < iter1)); - assert(iter1 <= iter1); assert(iter1 <= iter2); assert(!(iter2 <= iter1)); - assert(!(iter1 > iter1)); assert(!(iter1 > iter2)); assert(iter2 > iter1); - assert(iter1 >= iter1); assert(!(iter1 >= iter2)); assert(iter2 >= iter1); - assert(iter1 == iter1); assert(!(iter1 == iter2)); assert(iter2 == iter2); - assert(!(iter1 != iter1)); assert(iter1 != iter2); assert(!(iter2 != iter2)); - - assert((iter1 <=> iter2) == std::strong_ordering::less); - assert((iter1 <=> iter1) == std::strong_ordering::equal); - assert((iter2 <=> iter1) == std::strong_ordering::greater); + assert(iter1 < iter1 + 1); + assert(iter1 + 1 > iter1); + assert(iter1 <= iter1 + 1); + assert(iter1 <= iter2); + assert(iter1 + 1 >= iter2); + assert(iter1 >= iter2); } - { - // Test an old-school iterator with no operator<=>; the transform iterator shouldn't have operator<=> either. - using It = random_access_iterator; - static_assert(!std::three_way_comparable); - using R = std::ranges::transform_view, PlusOne>; - static_assert(!std::three_way_comparable>); - - int a[] = {1,2,3}; - std::same_as auto r = std::ranges::subrange(It(a), It(a+3)) | std::views::transform(PlusOne()); - auto iter1 = r.begin(); - auto iter2 = iter1 + 1; - - assert(!(iter1 < iter1)); assert(iter1 < iter2); assert(!(iter2 < iter1)); - assert(iter1 <= iter1); assert(iter1 <= iter2); assert(!(iter2 <= iter1)); - assert(!(iter1 > iter1)); assert(!(iter1 > iter2)); assert(iter2 > iter1); - assert(iter1 >= iter1); assert(!(iter1 >= iter2)); assert(iter2 >= iter1); - assert(iter1 == iter1); assert(!(iter1 == iter2)); assert(iter2 == iter2); - assert(!(iter1 != iter1)); assert(iter1 != iter2); assert(!(iter2 != iter2)); - } +// TODO: when three_way_comparable is implemented and std::is_eq is implemented, +// uncomment this. +// { +// std::ranges::transform_view transformView1; +// auto iter1 = transformView1.begin(); +// std::ranges::transform_view transformView2; +// auto iter2 = transformView2.begin(); +// +// assert(std::is_eq(iter1 <=> iter2)); +// assert(std::is_lteq(iter1 <=> iter2)); +// ++iter2; +// assert(std::is_neq(iter1 <=> iter2)); +// assert(std::is_lt(iter1 <=> iter2)); +// assert(std::is_gt(iter2 <=> iter1)); +// assert(std::is_gteq(iter2 <=> iter1)); +// +// static_assert( std::three_way_comparable>>); +// static_assert(!std::three_way_comparable>>); +// } return true; } diff --git a/libcxx/test/std/ranges/range.adaptors/range.transform/types.h b/libcxx/test/std/ranges/range.adaptors/range.transform/types.h --- a/libcxx/test/std/ranges/range.adaptors/range.transform/types.h +++ b/libcxx/test/std/ranges/range.adaptors/range.transform/types.h @@ -129,6 +129,14 @@ constexpr CountedIter end() const { return CountedIter(ForwardIter(globalBuff + 8)); } }; +using ThreeWayCompIter = three_way_contiguous_iterator; +struct ThreeWayCompView : std::ranges::view_base { + constexpr ThreeWayCompIter begin() { return ThreeWayCompIter(globalBuff); } + constexpr ThreeWayCompIter begin() const { return ThreeWayCompIter(globalBuff); } + constexpr ThreeWayCompIter end() { return ThreeWayCompIter(globalBuff + 8); } + constexpr ThreeWayCompIter end() const { return ThreeWayCompIter(globalBuff + 8); } +}; + struct TimesTwo { constexpr int operator()(int x) const { return x * 2; } }; diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/compare.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/compare.pass.cpp --- a/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/compare.pass.cpp +++ b/libcxx/test/std/ranges/range.factories/range.iota.view/iterator/compare.pass.cpp @@ -10,79 +10,69 @@ // UNSUPPORTED: libcpp-no-concepts // UNSUPPORTED: libcpp-has-no-incomplete-ranges -// iota_view::::operator{<,>,<=,>=,==,!=,<=>} +// friend constexpr bool operator<(const iterator& x, const iterator& y) +// requires totally_ordered; +// friend constexpr bool operator>(const iterator& x, const iterator& y) +// requires totally_ordered; +// friend constexpr bool operator<=(const iterator& x, const iterator& y) +// requires totally_ordered; +// friend constexpr bool operator>=(const iterator& x, const iterator& y) +// requires totally_ordered; +// friend constexpr bool operator==(const iterator& x, const iterator& y) +// requires equality_comparable; + +// TODO: test spaceship operator once it's implemented. #include -#include +#include #include "test_macros.h" -#include "test_iterators.h" #include "../types.h" constexpr bool test() { { - // Test `int`, which has operator<=>; the iota iterator should also have operator<=>. - using R = std::ranges::iota_view; - static_assert(std::three_way_comparable>); - - std::same_as auto r = std::views::iota(42); - auto iter1 = r.begin(); - auto iter2 = iter1 + 1; - - assert(!(iter1 < iter1)); assert(iter1 < iter2); assert(!(iter2 < iter1)); - assert(iter1 <= iter1); assert(iter1 <= iter2); assert(!(iter2 <= iter1)); - assert(!(iter1 > iter1)); assert(!(iter1 > iter2)); assert(iter2 > iter1); - assert(iter1 >= iter1); assert(!(iter1 >= iter2)); assert(iter2 >= iter1); - assert(iter1 == iter1); assert(!(iter1 == iter2)); assert(iter2 == iter2); - assert(!(iter1 != iter1)); assert(iter1 != iter2); assert(!(iter2 != iter2)); - - assert((iter1 <=> iter2) == std::strong_ordering::less); - assert((iter1 <=> iter1) == std::strong_ordering::equal); - assert((iter2 <=> iter1) == std::strong_ordering::greater); + const std::ranges::iota_view io(0); + assert( io.begin() == io.begin() ); + assert( io.begin() != std::ranges::next(io.begin())); + assert( io.begin() < std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) > io.begin() ); + assert( io.begin() <= std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) >= io.begin() ); + assert( io.begin() <= io.begin() ); + assert( io.begin() >= io.begin() ); } - { - // Test a new-school iterator with operator<=>; the iota iterator should also have operator<=>. - using It = three_way_contiguous_iterator; - static_assert(std::three_way_comparable); - using R = std::ranges::iota_view; - static_assert(std::three_way_comparable>); - - int a[] = {1,2,3}; - std::same_as auto r = std::views::iota(It(a)); - auto iter1 = r.begin(); - auto iter2 = iter1 + 1; - - assert(!(iter1 < iter1)); assert(iter1 < iter2); assert(!(iter2 < iter1)); - assert(iter1 <= iter1); assert(iter1 <= iter2); assert(!(iter2 <= iter1)); - assert(!(iter1 > iter1)); assert(!(iter1 > iter2)); assert(iter2 > iter1); - assert(iter1 >= iter1); assert(!(iter1 >= iter2)); assert(iter2 >= iter1); - assert(iter1 == iter1); assert(!(iter1 == iter2)); assert(iter2 == iter2); - assert(!(iter1 != iter1)); assert(iter1 != iter2); assert(!(iter2 != iter2)); - - assert((iter1 <=> iter2) == std::strong_ordering::less); - assert((iter1 <=> iter1) == std::strong_ordering::equal); - assert((iter2 <=> iter1) == std::strong_ordering::greater); + std::ranges::iota_view io(0); + assert( io.begin() == io.begin() ); + assert( io.begin() != std::ranges::next(io.begin())); + assert( io.begin() < std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) > io.begin() ); + assert( io.begin() <= std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) >= io.begin() ); + assert( io.begin() <= io.begin() ); + assert( io.begin() >= io.begin() ); } - { - // Test an old-school iterator with no operator<=>; the iota iterator shouldn't have operator<=> either. - using It = random_access_iterator; - static_assert(!std::three_way_comparable); - using R = std::ranges::iota_view; - static_assert(!std::three_way_comparable>); - - int a[] = {1,2,3}; - std::same_as auto r = std::views::iota(It(a)); - auto iter1 = r.begin(); - auto iter2 = iter1 + 1; - - assert(!(iter1 < iter1)); assert(iter1 < iter2); assert(!(iter2 < iter1)); - assert(iter1 <= iter1); assert(iter1 <= iter2); assert(!(iter2 <= iter1)); - assert(!(iter1 > iter1)); assert(!(iter1 > iter2)); assert(iter2 > iter1); - assert(iter1 >= iter1); assert(!(iter1 >= iter2)); assert(iter2 >= iter1); - assert(iter1 == iter1); assert(!(iter1 == iter2)); assert(iter2 == iter2); - assert(!(iter1 != iter1)); assert(iter1 != iter2); assert(!(iter2 != iter2)); + const std::ranges::iota_view io(SomeInt(0)); + assert( io.begin() == io.begin() ); + assert( io.begin() != std::ranges::next(io.begin())); + assert( io.begin() < std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) > io.begin() ); + assert( io.begin() <= std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) >= io.begin() ); + assert( io.begin() <= io.begin() ); + assert( io.begin() >= io.begin() ); + } + { + std::ranges::iota_view io(SomeInt(0)); + assert( io.begin() == io.begin() ); + assert( io.begin() != std::ranges::next(io.begin())); + assert( io.begin() < std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) > io.begin() ); + assert( io.begin() <= std::ranges::next(io.begin())); + assert(std::ranges::next(io.begin()) >= io.begin() ); + assert( io.begin() <= io.begin() ); + assert( io.begin() >= io.begin() ); } return true; diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml --- a/libcxx/utils/ci/buildkite-pipeline.yml +++ b/libcxx/utils/ci/buildkite-pipeline.yml @@ -18,562 +18,6 @@ # steps: - # - # Light pre-commit tests for things like formatting or when people forget - # to update generated files. - # - - label: "Format" - command: "libcxx/utils/ci/run-buildbot check-format" - artifact_paths: - - "**/clang-format.patch" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - soft_fail: - - exit_status: 1 - timeout_in_minutes: 120 - - - label: "Generated output" - command: "libcxx/utils/ci/run-buildbot check-generated-output" - artifact_paths: - - "**/generated_output.patch" - - "**/generated_output.status" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # - # General testing with the default configuration, under all the supported - # Standard modes, with Clang and GCC. This catches most issues upfront. - # The goal of this step is to catch most issues while being very fast. - # - - wait - - - label: "C++2b" - command: "libcxx/utils/ci/run-buildbot generic-cxx2b" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "C++20" - command: "libcxx/utils/ci/run-buildbot generic-cxx20" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "C++17" - command: "libcxx/utils/ci/run-buildbot generic-cxx17" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "C++14" - command: "libcxx/utils/ci/run-buildbot generic-cxx14" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "C++11" - command: "libcxx/utils/ci/run-buildbot generic-cxx11" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "C++03" - command: "libcxx/utils/ci/run-buildbot generic-cxx03" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "GCC 11 / C++latest" - command: "libcxx/utils/ci/run-buildbot generic-gcc" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # - # All other supported configurations of libc++. - # - - wait - - # Tests with the supported compilers. - - label: "GCC 11 / C++11" - command: "libcxx/utils/ci/run-buildbot generic-gcc-cxx11" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Clang 11" - command: "libcxx/utils/ci/run-buildbot generic-clang-11" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Clang 12" - command: "libcxx/utils/ci/run-buildbot generic-clang-12" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Tests with the sanitizers. - - label: "ASAN" - command: "libcxx/utils/ci/run-buildbot generic-asan" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "TSAN" - command: "libcxx/utils/ci/run-buildbot generic-tsan" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "UBSAN" - command: "libcxx/utils/ci/run-buildbot generic-ubsan" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Tests with the various supported ways to build libc++. - - label: "Legacy Lit configuration" - command: "libcxx/utils/ci/run-buildbot legacy-test-config" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Legacy standalone build" - command: "libcxx/utils/ci/run-buildbot legacy-standalone" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Unified standalone build" - command: "libcxx/utils/ci/run-buildbot unified-standalone" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "New standalone runtimes build" - command: "libcxx/utils/ci/run-buildbot new-standalone" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Runtimes build" - command: "libcxx/utils/ci/run-buildbot runtimes-build" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Tests with various build configurations. - - label: "-fno-exceptions" - command: "libcxx/utils/ci/run-buildbot generic-noexceptions" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Modular build" - command: "libcxx/utils/ci/run-buildbot generic-modules" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Static libraries" - command: "libcxx/utils/ci/run-buildbot generic-static" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Assertions enabled" - command: "libcxx/utils/ci/run-buildbot generic-assertions" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Debug iterators" - command: "libcxx/utils/ci/run-buildbot generic-debug-iterators" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "With LLVM's libunwind" - command: "libcxx/utils/ci/run-buildbot generic-with_llvm_unwinder" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "32 bit" - command: "libcxx/utils/ci/run-buildbot generic-32bit" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Single-threaded" - command: "libcxx/utils/ci/run-buildbot generic-singlethreaded" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No debug mode" - command: "libcxx/utils/ci/run-buildbot generic-no-debug" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No filesystem" - command: "libcxx/utils/ci/run-buildbot generic-no-filesystem" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No random device" - command: "libcxx/utils/ci/run-buildbot generic-no-random_device" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No locale" - command: "libcxx/utils/ci/run-buildbot generic-no-localization" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "No Unicode" - command: "libcxx/utils/ci/run-buildbot generic-no-unicode" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Other non-testing CI jobs - - label: "Benchmarks" - command: "libcxx/utils/ci/run-buildbot benchmarks" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Documentation" - command: "libcxx/utils/ci/run-buildbot documentation" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "linux" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Tests on non-Unix platforms - - label: "Windows (DLL)" - command: "bash libcxx/utils/ci/run-buildbot windows-dll" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "windows" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Windows (Static)" - command: "bash libcxx/utils/ci/run-buildbot windows-static" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "windows" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "MacOS x86_64" - command: "libcxx/utils/ci/run-buildbot generic-cxx20" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "macos" - arch: "x86_64" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "MacOS arm64" - command: "libcxx/utils/ci/run-buildbot generic-cxx20" - artifact_paths: - - "**/test-results.xml" - - "**/*.abilist" - agents: - queue: "libcxx-builders" - os: "macos" - arch: "arm64" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - # Build with the configuration we use to generate libc++.dylib on Apple platforms - - label: "Apple system" - command: "libcxx/utils/ci/run-buildbot x86_64-apple-system" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "macos" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - label: "Apple system -fno-exceptions" command: "libcxx/utils/ci/run-buildbot x86_64-apple-system-noexceptions" artifact_paths: @@ -586,110 +30,3 @@ - exit_status: -1 # Agent was lost limit: 2 timeout_in_minutes: 120 - - # Test back-deployment to older Apple platforms - - label: "Apple back-deployment macosx10.9" - command: "libcxx/utils/ci/run-buildbot x86_64-apple-system-backdeployment-10.9" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "macos10.15" # TODO: For now, we're running the back-deployment tests for 10.9 on 10.15, because we don't have proper 10.9 machines - arch: "x86_64" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Apple back-deployment macosx10.15" - command: "libcxx/utils/ci/run-buildbot x86_64-apple-system-backdeployment-10.15" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders" - os: "macos10.15" - arch: "x86_64" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "AArch64" - command: "libcxx/utils/ci/run-buildbot aarch64" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "aarch64" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "AArch64 -fno-exceptions" - command: "libcxx/utils/ci/run-buildbot aarch64-noexceptions" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "aarch64" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Armv8" - command: "libcxx/utils/ci/run-buildbot armv8" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "armv8l" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Armv8 -fno-exceptions" - command: "libcxx/utils/ci/run-buildbot armv8-noexceptions" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "armv8l" - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Armv7" - command: "libcxx/utils/ci/run-buildbot armv7" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "armv8l" # Compiling for v7, running on v8 hardware - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 - - - label: "Armv7 -fno-exceptions" - command: "libcxx/utils/ci/run-buildbot armv7-noexceptions" - artifact_paths: - - "**/test-results.xml" - agents: - queue: "libcxx-builders-linaro-arm" - arch: "armv8l" # Compiling for v7, running on v8 hardware - retry: - automatic: - - exit_status: -1 # Agent was lost - limit: 2 - timeout_in_minutes: 120 diff --git a/libcxxabi/src/demangle/Utility.h b/libcxxabi/src/demangle/Utility.h --- a/libcxxabi/src/demangle/Utility.h +++ b/libcxxabi/src/demangle/Utility.h @@ -126,16 +126,6 @@ return this->operator<<(static_cast(N)); } - void insert(size_t Pos, const char *S, size_t N) { - assert(Pos <= CurrentPosition); - if (N == 0) - return; - grow(N); - std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos); - std::memcpy(Buffer + Pos, S, N); - CurrentPosition += N; - } - size_t getCurrentPosition() const { return CurrentPosition; } void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } diff --git a/llvm/include/llvm/Demangle/Utility.h b/llvm/include/llvm/Demangle/Utility.h --- a/llvm/include/llvm/Demangle/Utility.h +++ b/llvm/include/llvm/Demangle/Utility.h @@ -126,16 +126,6 @@ return this->operator<<(static_cast(N)); } - void insert(size_t Pos, const char *S, size_t N) { - assert(Pos <= CurrentPosition); - if (N == 0) - return; - grow(N); - std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos); - std::memcpy(Buffer + Pos, S, N); - CurrentPosition += N; - } - size_t getCurrentPosition() const { return CurrentPosition; } void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; } diff --git a/llvm/lib/Demangle/RustDemangle.cpp b/llvm/lib/Demangle/RustDemangle.cpp --- a/llvm/lib/Demangle/RustDemangle.cpp +++ b/llvm/lib/Demangle/RustDemangle.cpp @@ -135,7 +135,6 @@ void printDecimalNumber(uint64_t N); void printBasicType(BasicType); void printLifetime(uint64_t Index); - void printIdentifier(Identifier Ident); char look() const; char consume(); @@ -284,7 +283,8 @@ switch (consume()) { case 'C': { parseOptionalBase62Number('s'); - printIdentifier(parseIdentifier()); + Identifier Ident = parseIdentifier(); + print(Ident.Name); break; } case 'M': { @@ -333,7 +333,7 @@ print(NS); if (!Ident.empty()) { print(":"); - printIdentifier(Ident); + print(Ident.Name); } print('#'); printDecimalNumber(Disambiguator); @@ -342,7 +342,7 @@ // Implementation internal namespaces. if (!Ident.empty()) { print("::"); - printIdentifier(Ident); + print(Ident.Name); } } break; @@ -669,8 +669,6 @@ print("C"); } else { Identifier Ident = parseIdentifier(); - if (Ident.Punycode) - Error = true; for (char C : Ident.Name) { // When mangling ABI string, the "-" is replaced with "_". if (C == '_') @@ -1080,172 +1078,6 @@ } } -static inline bool decodePunycodeDigit(char C, size_t &Value) { - if (isLower(C)) { - Value = C - 'a'; - return true; - } - - if (isDigit(C)) { - Value = 26 + (C - '0'); - return true; - } - - return false; -} - -static void removeNullBytes(OutputStream &Output, size_t StartIdx) { - char *Buffer = Output.getBuffer(); - char *Start = Buffer + StartIdx; - char *End = Buffer + Output.getCurrentPosition(); - Output.setCurrentPosition(std::remove(Start, End, '\0') - Buffer); -} - -// Encodes code point as UTF-8 and stores results in Output. Returns false if -// CodePoint is not a valid unicode scalar value. -static inline bool encodeUTF8(size_t CodePoint, char *Output) { - if (0xD800 <= CodePoint && CodePoint <= 0xDFFF) - return false; - - if (CodePoint <= 0x7F) { - Output[0] = CodePoint; - return true; - } - - if (CodePoint <= 0x7FF) { - Output[0] = 0xC0 | ((CodePoint >> 6) & 0x3F); - Output[1] = 0x80 | (CodePoint & 0x3F); - return true; - } - - if (CodePoint <= 0xFFFF) { - Output[0] = 0xE0 | (CodePoint >> 12); - Output[1] = 0x80 | ((CodePoint >> 6) & 0x3F); - Output[2] = 0x80 | (CodePoint & 0x3F); - return true; - } - - if (CodePoint <= 0x10FFFF) { - Output[0] = 0xF0 | (CodePoint >> 18); - Output[1] = 0x80 | ((CodePoint >> 12) & 0x3F); - Output[2] = 0x80 | ((CodePoint >> 6) & 0x3F); - Output[3] = 0x80 | (CodePoint & 0x3F); - return true; - } - - return false; -} - -// Decodes string encoded using punycode and appends results to Output. -// Returns true if decoding was successful. -static bool decodePunycode(StringView Input, OutputStream &Output) { - size_t OutputSize = Output.getCurrentPosition(); - size_t InputIdx = 0; - - // Rust uses an underscore as a delimiter. - size_t DelimiterPos = StringView::npos; - for (size_t I = 0; I != Input.size(); ++I) - if (Input[I] == '_') - DelimiterPos = I; - - if (DelimiterPos != StringView::npos) { - // Copy basic code points before the last delimiter to the output. - for (; InputIdx != DelimiterPos; ++InputIdx) { - char C = Input[InputIdx]; - if (!isValid(C)) - return false; - // Code points are padded with zeros while decoding is in progress. - char UTF8[4] = {C}; - Output += StringView(UTF8, UTF8 + 4); - } - // Skip over the delimiter. - ++InputIdx; - } - - size_t Base = 36; - size_t Skew = 38; - size_t Bias = 72; - size_t N = 0x80; - size_t TMin = 1; - size_t TMax = 26; - size_t Damp = 700; - - auto Adapt = [&](size_t Delta, size_t NumPoints) { - Delta /= Damp; - Delta += Delta / NumPoints; - Damp = 2; - - size_t K = 0; - while (Delta > (Base - TMin) * TMax / 2) { - Delta /= Base - TMin; - K += Base; - } - return K + (((Base - TMin + 1) * Delta) / (Delta + Skew)); - }; - - // Main decoding loop. - for (size_t I = 0; InputIdx != Input.size(); I += 1) { - size_t OldI = I; - size_t W = 1; - size_t Max = std::numeric_limits::max(); - for (size_t K = Base; true; K += Base) { - if (InputIdx == Input.size()) - return false; - char C = Input[InputIdx++]; - size_t Digit = 0; - if (!decodePunycodeDigit(C, Digit)) - return false; - - if (Digit > (Max - I) / W) - return false; - I += Digit * W; - - size_t T; - if (K <= Bias) - T = TMin; - else if (K >= Bias + TMax) - T = TMax; - else - T = K - Bias; - - if (Digit < T) - break; - - if (W > Max / (Base - T)) - return false; - W *= (Base - T); - } - size_t NumPoints = (Output.getCurrentPosition() - OutputSize) / 4 + 1; - Bias = Adapt(I - OldI, NumPoints); - - if (I / NumPoints > Max - N) - return false; - N += I / NumPoints; - I = I % NumPoints; - - // Insert N at position I in the output. - char UTF8[4] = {}; - if (!encodeUTF8(N, UTF8)) - return false; - Output.insert(OutputSize + I * 4, UTF8, 4); - } - - removeNullBytes(Output, OutputSize); - return true; -} - -void Demangler::printIdentifier(Identifier Ident) { - if (Error || !Print) - return; - - if (Ident.Punycode) { - if (!decodePunycode(Ident.Name, Output)) - Error = true; - } else { - print(Ident.Name); - } -} - char Demangler::look() const { if (Error || Position >= Input.size()) return 0; diff --git a/llvm/test/Demangle/rust.test b/llvm/test/Demangle/rust.test --- a/llvm/test/Demangle/rust.test +++ b/llvm/test/Demangle/rust.test @@ -237,11 +237,6 @@ CHECK: function:: _RIC8functionFUK21C_cmse_nonsecure_callEuE -; Invalid ABI with punycode. - -CHECK: _RIC8functionFKu3n3hEuE - _RIC8functionFKu3n3hEuE - ; Trait objects CHECK: trait:: @@ -461,44 +456,6 @@ CHECK: dot (.llvm.6789) _RC3dotC5crate.llvm.6789 -; Punycode - -CHECK: punycode::東京 - _RNvC8punycodeu7_1lqs71d - -CHECK: punycode::zażółć_gęślą_jaźń - _RNvC8punycodeu29za_gl_ja_w3a7psa2tqtgb10airva - -CHECK: punycode::საჭმელად_გემრიელი_სადილი - _RNvC8punycodeu30____7hkackfecea1cbdathfdh9hlq6y - -CHECK: Gödel::Escher::Bach - _RNtNvCu8Gdel_5qa6Escher4Bach - -CHECK: punycode::🦁🐅 - _RNvC8punycodeu7wn8hx1g - -; Punycode - invalid code point - -CHECK: _RCu5r731r - _RCu5r731r - -CHECK: _RCu8b44444yy - _RCu8b44444yy - -CHECK: _RNvC1au25zzzzzzzzzzzzzzzzzzzzzzzzz - _RNvC1au25zzzzzzzzzzzzzzzzzzzzzzzzz - -; Punycode - early EOF - -CHECK: _RCu8_CCCAR_u4 - _RCu8_CCCAR_u4 - -; Punycode - overflow - -CHECK: _RNvC1au21p18888888888888888888 - _RNvC1au21p18888888888888888888 - ; Invalid mangled characters CHECK: _RNvC2a.1c diff --git a/llvm/unittests/Demangle/CMakeLists.txt b/llvm/unittests/Demangle/CMakeLists.txt --- a/llvm/unittests/Demangle/CMakeLists.txt +++ b/llvm/unittests/Demangle/CMakeLists.txt @@ -6,7 +6,6 @@ add_llvm_unittest(DemangleTests DemangleTest.cpp ItaniumDemangleTest.cpp - OutputStreamTest.cpp PartialDemangleTest.cpp RustDemangleTest.cpp StringViewTest.cpp diff --git a/llvm/unittests/Demangle/OutputStreamTest.cpp b/llvm/unittests/Demangle/OutputStreamTest.cpp deleted file mode 100644 --- a/llvm/unittests/Demangle/OutputStreamTest.cpp +++ /dev/null @@ -1,61 +0,0 @@ -//===- llvm/unittest/OutputStreamTest.cpp - OutputStream unit tests -------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/Demangle/Utility.h" -#include "gtest/gtest.h" -#include - -using namespace llvm; -using llvm::itanium_demangle::OutputStream; - -static std::string toString(OutputStream &OS) { - return {OS.getBuffer(), OS.getCurrentPosition()}; -} - -template static std::string printToString(const T &Value) { - OutputStream OS; - OS << Value; - std::string s = toString(OS); - std::free(OS.getBuffer()); - return s; -} - -TEST(OutputStreamTest, Format) { - EXPECT_EQ("0", printToString(0)); - EXPECT_EQ("1", printToString(1)); - EXPECT_EQ("-1", printToString(-1)); - EXPECT_EQ("-90", printToString(-90)); - EXPECT_EQ("109", printToString(109)); - EXPECT_EQ("400", printToString(400)); - - EXPECT_EQ("a", printToString('a')); - EXPECT_EQ("?", printToString('?')); - - EXPECT_EQ("abc", printToString("abc")); -} - -TEST(OutputStreamTest, Insert) { - OutputStream OS; - - OS.insert(0, "", 0); - EXPECT_EQ("", toString(OS)); - - OS.insert(0, "abcd", 4); - EXPECT_EQ("abcd", toString(OS)); - - OS.insert(0, "x", 1); - EXPECT_EQ("xabcd", toString(OS)); - - OS.insert(5, "y", 1); - EXPECT_EQ("xabcdy", toString(OS)); - - OS.insert(3, "defghi", 6); - EXPECT_EQ("xabdefghicdy", toString(OS)); - - std::free(OS.getBuffer()); -}