https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/206990
>From f2f1d661b57c287b9236ebe36ec80a2a95cb5a50 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <[email protected]> Date: Wed, 1 Jul 2026 15:43:48 +0200 Subject: [PATCH] [Clang] Reduce the number of ways we have to print a codepoint. In #206326, we introduced yet another way to format a codepoint, so we try to claw back some consistency. - When we display a single character we do so inside quotes - Non-decodable code units are displayed as <0xYY> - In strings - we render printable and format characters - we print <U+XXXX> for non printable, non-format characters - In characters - we only render non-format print characters - we always print the codepoint as U+XXXX This does not change `WriteCharValueForDiagnostic` which is deeply weird and was contentous a while back. So we still have 2 different formatting utilities. Which is better than 4! I've also added a test for invalid utf-8 in \N{} --- clang/include/clang/Basic/Diagnostic.h | 3 +- .../clang/Basic/DiagnosticSemaKinds.td | 4 +- clang/lib/AST/ASTDiagnostic.cpp | 8 +- clang/lib/Basic/Diagnostic.cpp | 78 ++++++++++++------- clang/lib/Lex/LiteralSupport.cpp | 12 +-- .../char-escapes-delimited-invalid-utf8.c | 5 ++ clang/test/Lexer/char-escapes-delimited.c | 2 +- clang/test/SemaCXX/static-assert-cxx26.cpp | 2 +- clang/test/SemaCXX/static-assert.cpp | 8 +- .../warn-implicit-unicode-conversions.cpp | 28 +++---- clang/unittests/Basic/DiagnosticTest.cpp | 24 +++--- llvm/include/llvm/Support/ConvertUTF.h | 4 + llvm/lib/Support/ConvertUTF.cpp | 5 +- 13 files changed, 103 insertions(+), 80 deletions(-) create mode 100644 clang/test/Lexer/char-escapes-delimited-invalid-utf8.c diff --git a/clang/include/clang/Basic/Diagnostic.h b/clang/include/clang/Basic/Diagnostic.h index c033320687078..66e79e3b4300b 100644 --- a/clang/include/clang/Basic/Diagnostic.h +++ b/clang/include/clang/Basic/Diagnostic.h @@ -1877,7 +1877,8 @@ void ProcessWarningOptions(DiagnosticsEngine &Diags, const DiagnosticOptions &Opts, llvm::vfs::FileSystem &VFS, bool ReportDiags = true); void EscapeStringForDiagnostic(StringRef Str, SmallVectorImpl<char> &OutStr); -llvm::SmallString<16> DisplayCodePointForDiagnostic(llvm::UTF32 CodePoint); +SmallString<16> EscapeSingleCodepointForDiagnostic(StringRef Str); +SmallString<16> EscapeSingleCodepointForDiagnostic(llvm::UTF32 CP); } // namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 86b765fdf1fab..05f49a4dbd1ca 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4664,7 +4664,7 @@ def warn_impcast_unicode_precision InGroup<CharacterConversion>; def warn_impcast_unicode_char_type_constant : Warning<"implicit conversion from %0 to %1 changes the meaning of the " - "%select{code unit|code point}2 '%3'">, + "%select{code unit|code point}2 %3">, InGroup<CharacterConversion>; def warn_comparison_unicode_mixed_types @@ -4674,7 +4674,7 @@ def warn_comparison_unicode_mixed_types def warn_comparison_unicode_mixed_types_constant : Warning<"comparing values of different Unicode code unit types %0 and %1 " - "compares unrelated code units '%2' and '%3'">, + "compares unrelated code units %2 and %3">, InGroup<CharacterConversion>; def warn_xor_used_as_pow : Warning< diff --git a/clang/lib/AST/ASTDiagnostic.cpp b/clang/lib/AST/ASTDiagnostic.cpp index b8023cb6fa10f..f7888f58985db 100644 --- a/clang/lib/AST/ASTDiagnostic.cpp +++ b/clang/lib/AST/ASTDiagnostic.cpp @@ -2212,10 +2212,6 @@ std::string clang::FormatUTFCodeUnitAsCodepoint(unsigned Value, QualType T) { return std::string(Str.begin(), Str.end()); } - char Buffer[UNI_MAX_UTF8_BYTES_PER_CODE_POINT]; - char *Ptr = Buffer; - [[maybe_unused]] bool Converted = llvm::ConvertCodePointToUTF8(Value, Ptr); - assert(Converted && "trying to encode invalid code unit"); - EscapeStringForDiagnostic(StringRef(Buffer, Ptr - Buffer), Str); - return std::string(Str.begin(), Str.end()); + llvm::SmallString<16> Escaped = EscapeSingleCodepointForDiagnostic(Value); + return std::string(Escaped.begin(), Escaped.end()); } diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp index 57fa8a16d3a50..4c63e54964ed6 100644 --- a/clang/lib/Basic/Diagnostic.cpp +++ b/clang/lib/Basic/Diagnostic.cpp @@ -30,6 +30,7 @@ #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/Error.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SpecialCaseList.h" #include "llvm/Support/Unicode.h" @@ -1042,19 +1043,33 @@ void Diagnostic::FormatDiagnostic(SmallVectorImpl<char> &OutStr) const { /// EscapeStringForDiagnostic - Append Str to the diagnostic buffer, /// escaping non-printable characters and ill-formed code unit sequences. -void clang::EscapeStringForDiagnostic(StringRef Str, - SmallVectorImpl<char> &OutStr) { +static void EscapeStringForDiagnostic(StringRef Str, + SmallVectorImpl<char> &OutStr, + bool ForCodepoint) { OutStr.reserve(OutStr.size() + Str.size()); auto *Begin = reinterpret_cast<const unsigned char *>(Str.data()); llvm::raw_svector_ostream OutStream(OutStr); - const unsigned char *End = Begin + Str.size(); + unsigned Size = Str.size(); + const unsigned char *End = Begin + Size; + if (ForCodepoint) { + unsigned Size = llvm::getUTF8SequenceSize(Begin, End); + if (Size == 0) + Size = llvm::findMaximalSubpartOfIllFormedUTF8Sequence(Begin, End); + End = Begin + Size; + } while (Begin != End) { - // ASCII case - if (isPrintable(*Begin) || isWhitespace(*Begin)) { + if (!ForCodepoint && (isPrintable(*Begin) || isWhitespace(*Begin))) { OutStream << *Begin; ++Begin; continue; } + if (ForCodepoint && *Begin < 0x80) { + if (isPrintable(*Begin)) { + OutStream << "'" << *Begin << "'"; + ++Begin; + continue; + } + } if (llvm::isLegalUTF8Sequence(Begin, End)) { llvm::UTF32 CodepointValue; llvm::UTF32 *CpPtr = &CodepointValue; @@ -1069,40 +1084,49 @@ void clang::EscapeStringForDiagnostic(StringRef Str, "the sequence is legal UTF-8 but we couldn't convert it to UTF-32"); assert(Begin == CodepointEnd && "we must be further along in the string now"); + if (llvm::sys::unicode::isPrintable(CodepointValue) || - llvm::sys::unicode::isFormatting(CodepointValue)) { - OutStr.append(CodepointBegin, CodepointEnd); - continue; + (!ForCodepoint && llvm::sys::unicode::isFormatting(CodepointValue))) { + OutStream << (ForCodepoint ? "'" : "") + << StringRef(reinterpret_cast<const char *>(CodepointBegin), + std::distance(CodepointBegin, CodepointEnd)) + << (ForCodepoint ? "' " : ""); + if (!ForCodepoint) + continue; } // Unprintable code point. - OutStream << "<U+" << llvm::format_hex_no_prefix(CodepointValue, 4, true) - << ">"; + OutStream << (ForCodepoint ? "" : "<") << "U+" + << llvm::format_hex_no_prefix(CodepointValue, 4, true) + << (ForCodepoint ? "" : ">"); continue; } // Invalid code unit. - OutStream << "<" << llvm::format_hex_no_prefix(*Begin, 2, true) << ">"; + OutStream << "<0x" << llvm::format_hex_no_prefix(*Begin, 2, true) << ">"; ++Begin; } } +/// EscapeStringForDiagnostic - Append Str to the diagnostic buffer, +/// escaping non-printable characters and ill-formed code unit sequences. +void clang::EscapeStringForDiagnostic(StringRef Str, + SmallVectorImpl<char> &OutStr) { + ::EscapeStringForDiagnostic(Str, OutStr, /*ForCodepoint=*/false); +} + /// Displays a single Unicode codepoint in U+NNNN notation, optionally /// prepending the quoted codepoint itself if printable. -llvm::SmallString<16> -clang::DisplayCodePointForDiagnostic(llvm::UTF32 CodePoint) { - llvm::SmallString<16> Result; - if (llvm::sys::unicode::isPrintable(CodePoint)) { - std::string CharUTF8; - llvm::convertUTF32ToUTF8String(llvm::ArrayRef<llvm::UTF32>(&CodePoint, 1), - CharUTF8); - Result.append("'"); - Result.append(CharUTF8); - Result.append("' U+"); - } else { - Result.append("U+"); - } - llvm::raw_svector_ostream OS(Result); - llvm::write_hex(OS, CodePoint, llvm::HexPrintStyle::Upper, 4); - return Result; +SmallString<16> clang::EscapeSingleCodepointForDiagnostic(StringRef Str) { + SmallString<16> CP; + ::EscapeStringForDiagnostic(Str, CP, /*ForCodepoint=*/true); + return CP; +} + +SmallString<16> clang::EscapeSingleCodepointForDiagnostic(llvm::UTF32 CP) { + std::string Str; + bool Converted = convertUTF32ToUTF8String(ArrayRef<llvm::UTF32>(&CP, 1), Str); + if (!Converted) + return SmallString<16>(llvm::formatv("<{0:X+}>", CP).str()); + return EscapeSingleCodepointForDiagnostic(Str); } void Diagnostic::FormatDiagnostic(const char *DiagStr, const char *DiagEnd, diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index 72a65dd156b19..54db19859d32f 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -561,17 +561,12 @@ static void DiagnoseInvalidUnicodeCharacterName( ++P; continue; } - const auto *Src = reinterpret_cast<const llvm::UTF8 *>(P); - const auto *SrcEnd = reinterpret_cast<const llvm::UTF8 *>(E); - llvm::UTF32 CodePoint = 0; - if (llvm::convertUTF8Sequence(&Src, SrcEnd, &CodePoint, - llvm::strictConversion) != llvm::conversionOK) - break; SourceLocation CharLoc = Lexer::AdvanceToTokenCharacter( Loc, (TokRangeBegin - TokBegin) + (P - Name.begin()), Loc.getManager(), Features); Diags->Report(CharLoc, diag::note_invalid_ucn_name_character) - << DisplayCodePointForDiagnostic(CodePoint); + << EscapeSingleCodepointForDiagnostic( + StringRef(P, std::distance(P, E))); HasIllegalCharacter = true; break; } @@ -607,10 +602,9 @@ static void DiagnoseInvalidUnicodeCharacterName( 3) break; Distance = Match.Distance; - Diag(Diags, Features, Loc, TokBegin, TokRangeBegin, TokRangeEnd, diag::note_invalid_ucn_name_candidate) - << Match.Name << DisplayCodePointForDiagnostic(Match.Value) + << Match.Name << EscapeSingleCodepointForDiagnostic(Match.Value) << FixItHint::CreateReplacement( MakeCharSourceRange(Features, Loc, TokBegin, TokRangeBegin, TokRangeEnd), diff --git a/clang/test/Lexer/char-escapes-delimited-invalid-utf8.c b/clang/test/Lexer/char-escapes-delimited-invalid-utf8.c new file mode 100644 index 0000000000000..301302e1c786a --- /dev/null +++ b/clang/test/Lexer/char-escapes-delimited-invalid-utf8.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -x c++ -std=c++23 + +unsigned h = U'\N{INVALID�}'; \ +//expected-error {{'INVALID<0x80>' is not a valid Unicode character name}} +//expected-note {{character <0x80> cannot appear in a Unicode character name}} diff --git a/clang/test/Lexer/char-escapes-delimited.c b/clang/test/Lexer/char-escapes-delimited.c index 1c20456701d75..d581c9760a364 100644 --- a/clang/test/Lexer/char-escapes-delimited.c +++ b/clang/test/Lexer/char-escapes-delimited.c @@ -83,7 +83,7 @@ void named(void) { char b = '\N{DOLLAR SIGN}'; // ext-warning {{extension}} cxx23-warning {{C++23}} char b_ = '\N{ DOL-LAR _SIGN }'; // expected-error {{' DOL-LAR _SIGN ' is not a valid Unicode character name}} \ // expected-note {{character names in Unicode escape sequences are sensitive to case and whitespaces}} \ - // expected-note {{character '_' U+005F cannot appear in a Unicode character name}} + // expected-note {{character '_' cannot appear in a Unicode character name}} char c = '\N{NOTATHING}'; // expected-error {{'NOTATHING' is not a valid Unicode character name}} \ // expected-note 5{{did you mean}} diff --git a/clang/test/SemaCXX/static-assert-cxx26.cpp b/clang/test/SemaCXX/static-assert-cxx26.cpp index e9eb98dc72e04..644805a9e84c7 100644 --- a/clang/test/SemaCXX/static-assert-cxx26.cpp +++ b/clang/test/SemaCXX/static-assert-cxx26.cpp @@ -309,7 +309,7 @@ namespace EscapeInDiagnostic { static_assert('\u{9}' == (char)1, ""); // expected-error {{failed}} \ // expected-note {{evaluates to ''\t' (0x09, 9) == '<U+0001>' (0x01, 1)'}} static_assert((char8_t)-128 == (char8_t)-123, ""); // expected-error {{failed}} \ - // expected-note {{evaluates to 'u8'<80>' (0x80, 128) == u8'<85>' (0x85, 133)'}} + // expected-note {{evaluates to 'u8'<0x80>' (0x80, 128) == u8'<0x85>' (0x85, 133)'}} static_assert((char16_t)0xFEFF == (char16_t)0xDB93, ""); // expected-error {{failed}} \ // expected-note {{evaluates to 'u'' (0xFEFF, 65279) == u'\xDB93' (0xDB93, 56211)'}} } diff --git a/clang/test/SemaCXX/static-assert.cpp b/clang/test/SemaCXX/static-assert.cpp index 354016db36432..c48791203733b 100644 --- a/clang/test/SemaCXX/static-assert.cpp +++ b/clang/test/SemaCXX/static-assert.cpp @@ -278,13 +278,13 @@ namespace Diagnostics { // The note above is intended to match "evaluates to '\n' (0x0A, 10) == '<U+0000>' (0x00, 0)'", but if we write it as it is, // the "\n" cannot be consumed by the diagnostic consumer. static_assert((signed char)10 == (char)-123, ""); // expected-error {{failed}} \ - // expected-note {{evaluates to '10 == '<85>' (0x85, -123)'}} + // expected-note {{evaluates to '10 == '<0x85>' (0x85, -123)'}} static_assert((char)-4 == (unsigned char)-8, ""); // expected-error {{failed}} \ - // expected-note {{evaluates to ''<FC>' (0xFC, -4) == 248'}} + // expected-note {{evaluates to ''<0xFC>' (0xFC, -4) == 248'}} static_assert((char)-128 == (char)-123, ""); // expected-error {{failed}} \ - // expected-note {{evaluates to ''<80>' (0x80, -128) == '<85>' (0x85, -123)'}} + // expected-note {{evaluates to ''<0x80>' (0x80, -128) == '<0x85>' (0x85, -123)'}} static_assert('\xA0' == (char)'\x20', ""); // expected-error {{failed}} \ - // expected-note {{evaluates to ''<A0>' (0xA0, -96) == ' ' (0x20, 32)'}} + // expected-note {{evaluates to ''<0xA0>' (0xA0, -96) == ' ' (0x20, 32)'}} static_assert((char16_t)L'ゆ' == L"C̵̭̯̠̎͌ͅť̺"[1], ""); // expected-error {{failed}} \ // expected-note {{evaluates to 'u'ゆ' (0x3086, 12422) == L'̵' (0x335, 821)'}} static_assert(L"\/"[1] == u'\xFFFD', ""); // expected-error {{failed}} \ diff --git a/clang/test/SemaCXX/warn-implicit-unicode-conversions.cpp b/clang/test/SemaCXX/warn-implicit-unicode-conversions.cpp index f17f20ca25295..6f9f8f3898625 100644 --- a/clang/test/SemaCXX/warn-implicit-unicode-conversions.cpp +++ b/clang/test/SemaCXX/warn-implicit-unicode-conversions.cpp @@ -19,12 +19,12 @@ void test(char8_t u8, char16_t u16, char32_t u32) { c8(char32_t(0x7f)); - c8(char32_t(0x80)); // expected-warning {{implicit conversion from 'char32_t' to 'char8_t' changes the meaning of the code point '<U+0080>'}} + c8(char32_t(0x80)); // expected-warning {{implicit conversion from 'char32_t' to 'char8_t' changes the meaning of the code point U+0080}} c8(char16_t(0x7f)); - c8(char16_t(0x80)); // expected-warning {{implicit conversion from 'char16_t' to 'char8_t' changes the meaning of the code point '<U+0080>'}} - c8(char16_t(0xD800)); // expected-warning {{implicit conversion from 'char16_t' to 'char8_t' changes the meaning of the code unit '<0xD800>'}} - c8(char16_t(0xE000)); // expected-warning {{implicit conversion from 'char16_t' to 'char8_t' changes the meaning of the code point '<U+E000>'}} + c8(char16_t(0x80)); // expected-warning {{implicit conversion from 'char16_t' to 'char8_t' changes the meaning of the code point U+0080}} + c8(char16_t(0xD800)); // expected-warning {{implicit conversion from 'char16_t' to 'char8_t' changes the meaning of the code unit <0xD800>}} + c8(char16_t(0xE000)); // expected-warning {{implicit conversion from 'char16_t' to 'char8_t' changes the meaning of the code point U+E000}} c16(char32_t(0x7f)); @@ -36,8 +36,8 @@ void test(char8_t u8, char16_t u16, char32_t u32) { c32(char8_t(0x7f)); - c32(char8_t(0x80)); // expected-warning {{implicit conversion from 'char8_t' to 'char32_t' changes the meaning of the code unit '<0x80>'}} - c32(char8_t(0xFF)); // expected-warning {{implicit conversion from 'char8_t' to 'char32_t' changes the meaning of the code unit '<0xFF>'}} + c32(char8_t(0x80)); // expected-warning {{implicit conversion from 'char8_t' to 'char32_t' changes the meaning of the code unit <0x80>}} + c32(char8_t(0xFF)); // expected-warning {{implicit conversion from 'char8_t' to 'char32_t' changes the meaning of the code unit <0xFF>}} c32(char16_t(0x7f)); @@ -90,19 +90,19 @@ void test_comp(char8_t u8, char16_t u16, char32_t u32) { (void)(char8_t(0x7f) == char32_t(0x7f)); (void)(char8_t(0x80) == char8_t(0x80)); - (void)(char8_t(0x80) == char16_t(0x80)); // expected-warning{{comparing values of different Unicode code unit types 'char8_t' and 'char16_t' compares unrelated code units '<0x80>' and '<U+0080>}} - (void)(char8_t(0x80) == char32_t(0x80)); // expected-warning{{comparing values of different Unicode code unit types 'char8_t' and 'char32_t' compares unrelated code units '<0x80>' and '<U+0080>}} + (void)(char8_t(0x80) == char16_t(0x80)); // expected-warning{{comparing values of different Unicode code unit types 'char8_t' and 'char16_t' compares unrelated code units <0x80> and U+0080}} + (void)(char8_t(0x80) == char32_t(0x80)); // expected-warning{{comparing values of different Unicode code unit types 'char8_t' and 'char32_t' compares unrelated code units <0x80> and U+0080}} (void)(char8_t(0x80) == char8_t(0x7f)); - (void)(char8_t(0x80) == char16_t(0x7f)); // expected-warning{{comparing values of different Unicode code unit types 'char8_t' and 'char16_t' compares unrelated code units '<0x80>' and '<U+007F>'}} - (void)(char8_t(0x80) == char32_t(0x7f)); // expected-warning{{comparing values of different Unicode code unit types 'char8_t' and 'char32_t' compares unrelated code units '<0x80>' and '<U+007F>'}} + (void)(char8_t(0x80) == char16_t(0x7f)); // expected-warning{{comparing values of different Unicode code unit types 'char8_t' and 'char16_t' compares unrelated code units <0x80> and U+007F}} + (void)(char8_t(0x80) == char32_t(0x7f)); // expected-warning{{comparing values of different Unicode code unit types 'char8_t' and 'char32_t' compares unrelated code units <0x80> and U+007F}} (void)(char16_t(0x7f) < char8_t(0x7f)); (void)(char16_t(0x7f) < char16_t(0x7f)); (void)(char16_t(0x7f) < char32_t(0x7f)); - (void)(char16_t(0x80) < char8_t(0x80)); // expected-warning{{comparing values of different Unicode code unit types 'char16_t' and 'char8_t' compares unrelated code units '<U+0080>' and '<0x80>'}} + (void)(char16_t(0x80) < char8_t(0x80)); // expected-warning{{comparing values of different Unicode code unit types 'char16_t' and 'char8_t' compares unrelated code units U+0080 and <0x80>}} (void)(char16_t(0x80) < char16_t(0x80)); (void)(char16_t(0x80) < char32_t(0x80)); @@ -115,7 +115,7 @@ void test_comp(char8_t u8, char16_t u16, char32_t u32) { (void)(char32_t(0x7f) < char16_t(0x7f)); (void)(char32_t(0x7f) < char32_t(0x7f)); - (void)(char32_t(0x80) < char8_t(0x80)); // expected-warning{{comparing values of different Unicode code unit types 'char32_t' and 'char8_t' compares unrelated code units '<U+0080>' and '<0x80>'}} + (void)(char32_t(0x80) < char8_t(0x80)); // expected-warning{{comparing values of different Unicode code unit types 'char32_t' and 'char8_t' compares unrelated code units U+0080 and <0x80>}} (void)(char32_t(0x80) < char16_t(0x80)); (void)(char32_t(0x80) < char32_t(0x80)); @@ -124,10 +124,10 @@ void test_comp(char8_t u8, char16_t u16, char32_t u32) { (void)(char32_t(0x80) < char32_t(0x7f)); - (void)(char32_t(U'🐉') <= char16_t(0xD800)); // expected-warning{{comparing values of different Unicode code unit types 'char32_t' and 'char16_t' compares unrelated code units '🐉' and '<0xD800>'}} + (void)(char32_t(U'🐉') <= char16_t(0xD800)); // expected-warning{{comparing values of different Unicode code unit types 'char32_t' and 'char16_t' compares unrelated code units '🐉' U+1F409 and <0xD800>}} (void)(char32_t(U'🐉') <= char16_t(0xD7FF)); - (void)(char16_t(0xD800) >= char32_t(U'🐉')); // expected-warning{{comparing values of different Unicode code unit types 'char16_t' and 'char32_t' compares unrelated code units '<0xD800>' and '🐉'}} + (void)(char16_t(0xD800) >= char32_t(U'🐉')); // expected-warning{{comparing values of different Unicode code unit types 'char16_t' and 'char32_t' compares unrelated code units <0xD800> and '🐉' U+1F409}} (void)(char16_t(0xD7FF) >= char32_t(U'🐉')); } diff --git a/clang/unittests/Basic/DiagnosticTest.cpp b/clang/unittests/Basic/DiagnosticTest.cpp index 5cc0c39e5cb51..e986cbaceaa19 100644 --- a/clang/unittests/Basic/DiagnosticTest.cpp +++ b/clang/unittests/Basic/DiagnosticTest.cpp @@ -449,24 +449,24 @@ TEST_F(SuppressionMappingTest, CanonicalizesSlashesOnWindows) { } #endif -TEST(DisplayCodePointForDiagnosticTest, printableDisplaysQuoted) { - EXPECT_EQ(DisplayCodePointForDiagnostic(U'A'), "'A' U+0041"); - EXPECT_EQ(DisplayCodePointForDiagnostic(U'🤡'), "'🤡' U+1F921"); - EXPECT_EQ(DisplayCodePointForDiagnostic(U' '), "' ' U+0020"); +TEST(EscapeSingleCodepointForDiagnosticTest, printableDisplaysQuoted) { + EXPECT_EQ(EscapeSingleCodepointForDiagnostic(U'A'), "'A'"); + EXPECT_EQ(EscapeSingleCodepointForDiagnostic(U'🤡'), "'🤡' U+1F921"); + EXPECT_EQ(EscapeSingleCodepointForDiagnostic(U' '), "' '"); } -TEST(DisplayCodePointForDiagnosticTest, nonPrintableDisplaysNoQuoted) { - EXPECT_EQ(DisplayCodePointForDiagnostic(U'\n'), "U+000A"); - EXPECT_EQ(DisplayCodePointForDiagnostic(U'\0'), "U+0000"); - EXPECT_EQ(DisplayCodePointForDiagnostic(U'\x1B'), "U+001B"); +TEST(EscapeSingleCodepointForDiagnosticTest, nonPrintableDisplaysNoQuoted) { + EXPECT_EQ(EscapeSingleCodepointForDiagnostic(U'\n'), "U+000A"); + EXPECT_EQ(EscapeSingleCodepointForDiagnostic(U'\0'), "U+0000"); + EXPECT_EQ(EscapeSingleCodepointForDiagnostic(U'\x1B'), "U+001B"); } -TEST(DisplayCodePointForDiagnosticTest, nonScalarValues) { +TEST(EscapeSingleCodepointForDiagnosticTest, nonScalarValues) { // Low and high surrogates: - EXPECT_EQ(DisplayCodePointForDiagnostic(0xD800), "U+D800"); - EXPECT_EQ(DisplayCodePointForDiagnostic(0xDFFF), "U+DFFF"); + EXPECT_EQ(EscapeSingleCodepointForDiagnostic(0xD800), "<0xD800>"); + EXPECT_EQ(EscapeSingleCodepointForDiagnostic(0xDFFF), "<0xDFFF>"); // Overly large values: - EXPECT_EQ(DisplayCodePointForDiagnostic(0x110000), "U+110000"); + EXPECT_EQ(EscapeSingleCodepointForDiagnostic(0x110000), "<0x110000>"); } } // namespace diff --git a/llvm/include/llvm/Support/ConvertUTF.h b/llvm/include/llvm/Support/ConvertUTF.h index 5252336f8aa98..42329b9066dc9 100644 --- a/llvm/include/llvm/Support/ConvertUTF.h +++ b/llvm/include/llvm/Support/ConvertUTF.h @@ -212,6 +212,10 @@ LLVM_ABI Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd); LLVM_ABI unsigned getUTF8SequenceSize(const UTF8 *source, const UTF8 *sourceEnd); +LLVM_ABI unsigned +findMaximalSubpartOfIllFormedUTF8Sequence(const UTF8 *source, + const UTF8 *sourceEnd); + LLVM_ABI unsigned getNumBytesForUTF8(UTF8 firstByte); /*************************************************************************/ diff --git a/llvm/lib/Support/ConvertUTF.cpp b/llvm/lib/Support/ConvertUTF.cpp index 63f92631d5b47..0641e3cc6e53d 100644 --- a/llvm/lib/Support/ConvertUTF.cpp +++ b/llvm/lib/Support/ConvertUTF.cpp @@ -445,9 +445,8 @@ unsigned getUTF8SequenceSize(const UTF8 *source, const UTF8 *sourceEnd) { /* --------------------------------------------------------------------- */ -static unsigned -findMaximalSubpartOfIllFormedUTF8Sequence(const UTF8 *source, - const UTF8 *sourceEnd) { +unsigned findMaximalSubpartOfIllFormedUTF8Sequence(const UTF8 *source, + const UTF8 *sourceEnd) { UTF8 b1, b2, b3; assert(!isLegalUTF8Sequence(source, sourceEnd)); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
