https://github.com/cor3ntin created
https://github.com/llvm/llvm-project/pull/206990
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 for non-ascii characters
This does not change `WriteCharValueForDiagnostic` which is deeply weird and
was contentious 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{}
>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