[clang] [Clang] Yet more consistent Unicode diagnostics (PR #211002)
Corentin Jabot via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 21 06:51:32 PDT 2026
https://github.com/cor3ntin created https://github.com/llvm/llvm-project/pull/211002
This PR
- Use the recently introduced `EscapeSingleCodepointForDiagnostic` in more places
- Fix a bug where U+FEFF was incorrectly treated as a BOM and therefore did not render at all in diagnostics
>From 9fcfe8d24c592ae2d065438da0a069cd5c90c1e5 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Tue, 21 Jul 2026 15:47:24 +0200
Subject: [PATCH] [Clang] Yet more consistent Unicode diagnostics.
This PR
- Use the recently introduced `EscapeSingleCodepointForDiagnostic`
in more places
- Fix a bug where U+FEFF was incorrectly treated as a BOM and therefore
did not render at all in diagnostics
---
clang/docs/ReleaseNotes.md | 2 +
.../include/clang/Basic/DiagnosticLexKinds.td | 10 ++--
clang/lib/Basic/Diagnostic.cpp | 9 ++--
clang/lib/Lex/Lexer.cpp | 19 +++----
clang/test/C/C11/n1518.c | 6 +--
clang/test/C/C23/n2836_n2939.c | 50 +++++++++----------
clang/test/CXX/drs/cwg26xx.cpp | 2 +-
clang/test/FixIt/fixit-unicode.c | 2 +-
clang/test/Lexer/escape_newline_unicode.c | 2 +-
clang/test/Lexer/unicode.c | 36 ++++++-------
.../Parser/cxx11-user-defined-literals.cpp | 6 +--
clang/test/ParserHLSL/semantic_parsing.hlsl | 4 +-
clang/test/Preprocessor/ucn-allowed-chars.c | 10 ++--
clang/test/Preprocessor/ucn-pp-identifier.c | 2 +-
clang/test/Preprocessor/utf8-allowed-chars.c | 8 +--
clang/unittests/Basic/DiagnosticTest.cpp | 1 +
16 files changed, 83 insertions(+), 86 deletions(-)
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 9301745b9628e..882d3e81ab4ef 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -125,6 +125,8 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the
### Improvements to Clang's diagnostics
+- More consistent rendering of Unicode characters in diagnostic messages.
+
- Fixed bug in `-Wdocumentation` so that it correctly handles explicit
function template instantiations (#64087).
diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td b/clang/include/clang/Basic/DiagnosticLexKinds.td
index 79e74a846e3ea..c4c42f2d0fc9e 100644
--- a/clang/include/clang/Basic/DiagnosticLexKinds.td
+++ b/clang/include/clang/Basic/DiagnosticLexKinds.td
@@ -133,20 +133,20 @@ def err_invalid_utf8 : Error<
def warn_invalid_utf8_in_comment : Extension<
"invalid UTF-8 in comment">, InGroup<DiagGroup<"invalid-utf8">>;
def err_character_not_allowed : Error<
- "unexpected character <U+%0>">;
+ "unexpected character %0">;
def err_character_not_allowed_identifier : Error<
- "character <U+%0> not allowed %select{in|at the start of}1 an identifier">;
+ "character %0 not allowed %select{in|at the start of}1 an identifier">;
def ext_unicode_whitespace : ExtWarn<
"treating Unicode character as whitespace">,
InGroup<DiagGroup<"unicode-whitespace">>;
def warn_utf8_symbol_homoglyph : Warning<
- "treating Unicode character <U+%0> as an identifier character rather than "
+ "treating character %0 as an identifier character rather than "
"as '%1' symbol">, InGroup<DiagGroup<"unicode-homoglyph">>;
def warn_utf8_symbol_zero_width : Warning<
- "identifier contains Unicode character <U+%0> that is invisible in "
+ "identifier contains character %0 that is invisible in "
"some environments">, InGroup<DiagGroup<"unicode-zero-width">>;
def ext_mathematical_notation : ExtWarn<
- "mathematical notation character <U+%0> in an identifier is a Clang extension">,
+ "mathematical notation character %0 in an identifier is a Clang extension">,
InGroup<DiagGroup<"mathematical-notation-identifier-extension">>;
def ext_delimited_escape_sequence : Extension<
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index 4c63e54964ed6..48dd9559ab8e6 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -1122,11 +1122,12 @@ SmallString<16> clang::EscapeSingleCodepointForDiagnostic(StringRef Str) {
}
SmallString<16> clang::EscapeSingleCodepointForDiagnostic(llvm::UTF32 CP) {
- std::string Str;
- bool Converted = convertUTF32ToUTF8String(ArrayRef<llvm::UTF32>(&CP, 1), Str);
- if (!Converted)
+ char ResultBuf[UNI_MAX_UTF8_BYTES_PER_CODE_POINT];
+ char *ResultPtr = ResultBuf;
+ if (!llvm::ConvertCodePointToUTF8(CP, ResultPtr))
return SmallString<16>(llvm::formatv("<{0:X+}>", CP).str());
- return EscapeSingleCodepointForDiagnostic(Str);
+ return EscapeSingleCodepointForDiagnostic(
+ StringRef(ResultBuf, ResultPtr - ResultBuf));
}
void Diagnostic::FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index d5085ca6d4c8a..ae4a2c53e1bc6 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -1602,13 +1602,6 @@ static bool isUnicodeWhitespace(uint32_t Codepoint) {
return UnicodeWhitespaceChars.contains(Codepoint);
}
-static llvm::SmallString<5> codepointAsHexString(uint32_t C) {
- llvm::SmallString<5> CharBuf;
- llvm::raw_svector_ostream CharOS(CharBuf);
- llvm::write_hex(CharOS, C, llvm::HexPrintStyle::Upper, 4);
- return CharBuf;
-}
-
// To mitigate https://github.com/llvm/llvm-project/issues/54732,
// we allow "Mathematical Notation Characters" in identifiers.
// This is a proposed profile that extends the XID_Start/XID_continue
@@ -1696,7 +1689,7 @@ static void diagnoseExtensionInIdentifier(DiagnosticsEngine &Diags, uint32_t C,
assert((MathStartChars.contains(C) || MathContinueChars.contains(C)) &&
"Unexpected mathematical notation codepoint");
Diags.Report(Range.getBegin(), diag::ext_mathematical_notation)
- << codepointAsHexString(C) << Range;
+ << EscapeSingleCodepointForDiagnostic(C) << Range;
}
static inline CharSourceRange makeCharRange(Lexer &L, const char *Begin,
@@ -1801,10 +1794,10 @@ static void maybeDiagnoseUTF8Homoglyph(DiagnosticsEngine &Diags, uint32_t C,
if (Homoglyph->LooksLike) {
const char LooksLikeStr[] = {Homoglyph->LooksLike, 0};
Diags.Report(Range.getBegin(), diag::warn_utf8_symbol_homoglyph)
- << Range << codepointAsHexString(C) << LooksLikeStr;
+ << Range << EscapeSingleCodepointForDiagnostic(C) << LooksLikeStr;
} else {
Diags.Report(Range.getBegin(), diag::warn_utf8_symbol_zero_width)
- << Range << codepointAsHexString(C);
+ << Range << EscapeSingleCodepointForDiagnostic(C);
}
}
}
@@ -1832,11 +1825,11 @@ static bool CheckCodepointValidInIdentifier(const Preprocessor *PP,
if (!IsFirst || InvalidOnlyAtStart) {
PP->Diag(Range.getBegin(), diag::err_character_not_allowed_identifier)
- << Range << codepointAsHexString(CodePoint) << int(InvalidOnlyAtStart)
- << FixItHint::CreateRemoval(Range);
+ << Range << EscapeSingleCodepointForDiagnostic(CodePoint)
+ << int(InvalidOnlyAtStart) << FixItHint::CreateRemoval(Range);
} else {
PP->Diag(Range.getBegin(), diag::err_character_not_allowed)
- << Range << codepointAsHexString(CodePoint)
+ << Range << EscapeSingleCodepointForDiagnostic(CodePoint)
<< FixItHint::CreateRemoval(Range);
}
return false;
diff --git a/clang/test/C/C11/n1518.c b/clang/test/C/C11/n1518.c
index e950d22b20cf9..c44a49e2d08ca 100644
--- a/clang/test/C/C11/n1518.c
+++ b/clang/test/C/C11/n1518.c
@@ -12,13 +12,13 @@
// This file contains Unicode characters; please do not "fix" them!
// This was fine in C11, is now an error in C23.
-extern int ٢; // c23-error {{character <U+0662> not allowed at the start of an identifier}} \
+extern int ٢; // c23-error {{character '٢' U+0662 not allowed at the start of an identifier}} \
c23-warning {{declaration does not declare anything}}
// This was an error in C11 but is an extension in C23.
-extern int ∞; // c11-error {{unexpected character <U+221E>}} \
+extern int ∞; // c11-error {{unexpected character '∞' U+221E}} \
c11-warning {{declaration does not declare anything}} \
- c23-warning {{mathematical notation character <U+221E> in an identifier is a Clang extension}}
+ c23-warning {{mathematical notation character '∞' U+221E in an identifier is a Clang extension}}
int \u1DC0; // both-error {{expected identifier or '('}}
int e\u1DC0; // Ok
diff --git a/clang/test/C/C23/n2836_n2939.c b/clang/test/C/C23/n2836_n2939.c
index 13e23c3def80d..84d3d4f21b662 100644
--- a/clang/test/C/C23/n2836_n2939.c
+++ b/clang/test/C/C23/n2836_n2939.c
@@ -33,27 +33,27 @@ COPYRIGHT
// start or continuation characters as of C23. These are taken from section 1
// of N2836.
extern int \N{CONSTRUCTION WORKER}; // expected-error {{expected identifier or '('}}
-extern int X\N{CONSTRUCTION WORKER}; // expected-error {{character <U+1F477> not allowed in an identifier}}
+extern int X\N{CONSTRUCTION WORKER}; // expected-error {{character '👷' U+1F477 not allowed in an identifier}}
extern int \U0001F477; // expected-error {{expected identifier or '('}}
-extern int X\U0001F477; // expected-error {{character <U+1F477> not allowed in an identifier}}
-extern int 👷; // expected-error {{unexpected character <U+1F477>}} \
+extern int X\U0001F477; // expected-error {{character '👷' U+1F477 not allowed in an identifier}}
+extern int 👷; // expected-error {{unexpected character '👷' U+1F477}} \
// expected-warning {{declaration does not declare anything}}
-extern int X👷; // expected-error {{character <U+1F477> not allowed in an identifier}}
-extern int 🕐; // expected-error {{unexpected character <U+1F550>}} \
+extern int X👷; // expected-error {{character '👷' U+1F477 not allowed in an identifier}}
+extern int 🕐; // expected-error {{unexpected character '🕐' U+1F550}} \
// expected-warning {{declaration does not declare anything}}
-extern int X🕐; // expected-error {{character <U+1F550> not allowed in an identifier}}
-extern int 💀; // expected-error {{unexpected character <U+1F480>}} \
+extern int X🕐; // expected-error {{character '🕐' U+1F550 not allowed in an identifier}}
+extern int 💀; // expected-error {{unexpected character '💀' U+1F480}} \
// expected-warning {{declaration does not declare anything}}
-extern int X💀; // expected-error {{character <U+1F480> not allowed in an identifier}}
-extern int 👊; // expected-error {{unexpected character <U+1F44A>}} \
+extern int X💀; // expected-error {{character '💀' U+1F480 not allowed in an identifier}}
+extern int 👊; // expected-error {{unexpected character '👊' U+1F44A}} \
// expected-warning {{declaration does not declare anything}}
-extern int X👊; // expected-error {{character <U+1F44A> not allowed in an identifier}}
-extern int 🚀; // expected-error {{unexpected character <U+1F680>}} \
+extern int X👊; // expected-error {{character '👊' U+1F44A not allowed in an identifier}}
+extern int 🚀; // expected-error {{unexpected character '🚀' U+1F680}} \
// expected-warning {{declaration does not declare anything}}
-extern int X🚀; // expected-error {{character <U+1F680> not allowed in an identifier}}
-extern int 😀; // expected-error {{unexpected character <U+1F600>}} \
+extern int X🚀; // expected-error {{character '🚀' U+1F680 not allowed in an identifier}}
+extern int 😀; // expected-error {{unexpected character '😀' U+1F600}} \
// expected-warning {{declaration does not declare anything}}
-extern int X😀; // expected-error {{character <U+1F600> not allowed in an identifier}}
+extern int X😀; // expected-error {{character '😀' U+1F600 not allowed in an identifier}}
// The characters in the following identifiers are not allowed as start
// characters, but are allowed as continuation characters.
@@ -61,7 +61,7 @@ extern int \N{ARABIC-INDIC DIGIT ZERO}; // expected-error {{expected identifier
extern int X\N{ARABIC-INDIC DIGIT ZERO};
extern int \u0661; // expected-error {{expected identifier or '('}}
extern int X\u0661;
-extern int ٢; // expected-error {{character <U+0662> not allowed at the start of an identifier}} \\
+extern int ٢; // expected-error {{character '٢' U+0662 not allowed at the start of an identifier}} \\
// expected-warning {{declaration does not declare anything}}
extern int X٠;
@@ -69,15 +69,15 @@ extern int X٠;
// continuation characters in the standard, but are accepted as a conforming
// extension.
extern int \N{SUPERSCRIPT ZERO}; // expected-error {{expected identifier or '('}}
-extern int X\N{SUPERSCRIPT ZERO}; // expected-warning {{mathematical notation character <U+2070> in an identifier is a Clang extension}}
+extern int X\N{SUPERSCRIPT ZERO}; // expected-warning {{mathematical notation character '⁰' U+2070 in an identifier is a Clang extension}}
extern int \u00B9; // expected-error {{expected identifier or '('}}
-extern int X\u00B9; // expected-warning {{mathematical notation character <U+00B9> in an identifier is a Clang extension}}
-extern int ²; // expected-error {{character <U+00B2> not allowed at the start of an identifier}} \\
+extern int X\u00B9; // expected-warning {{mathematical notation character '¹' U+00B9 in an identifier is a Clang extension}}
+extern int ²; // expected-error {{character '²' U+00B2 not allowed at the start of an identifier}} \\
// expected-warning {{declaration does not declare anything}}
-extern int X²; // expected-warning {{mathematical notation character <U+00B2> in an identifier is a Clang extension}}
-extern int \N{PARTIAL DIFFERENTIAL}; // expected-warning {{mathematical notation character <U+2202> in an identifier is a Clang extension}}
-extern int X\N{PARTIAL DIFFERENTIAL}; // expected-warning {{mathematical notation character <U+2202> in an identifier is a Clang extension}}
-extern int \u2207; // expected-warning {{mathematical notation character <U+2207> in an identifier is a Clang extension}}
-extern int X\u2207; // expected-warning {{mathematical notation character <U+2207> in an identifier is a Clang extension}}
-extern int ∞; // expected-warning {{mathematical notation character <U+221E> in an identifier is a Clang extension}}
-extern int X∞; // expected-warning {{mathematical notation character <U+221E> in an identifier is a Clang extension}}
+extern int X²; // expected-warning {{mathematical notation character '²' U+00B2 in an identifier is a Clang extension}}
+extern int \N{PARTIAL DIFFERENTIAL}; // expected-warning {{mathematical notation character '∂' U+2202 in an identifier is a Clang extension}}
+extern int X\N{PARTIAL DIFFERENTIAL}; // expected-warning {{mathematical notation character '∂' U+2202 in an identifier is a Clang extension}}
+extern int \u2207; // expected-warning {{mathematical notation character '∇' U+2207 in an identifier is a Clang extension}}
+extern int X\u2207; // expected-warning {{mathematical notation character '∇' U+2207 in an identifier is a Clang extension}}
+extern int ∞; // expected-warning {{mathematical notation character '∞' U+221E in an identifier is a Clang extension}}
+extern int X∞; // expected-warning {{mathematical notation character '∞' U+221E in an identifier is a Clang extension}}
diff --git a/clang/test/CXX/drs/cwg26xx.cpp b/clang/test/CXX/drs/cwg26xx.cpp
index 6a15513879bbd..383ab1c63c6f5 100644
--- a/clang/test/CXX/drs/cwg26xx.cpp
+++ b/clang/test/CXX/drs/cwg26xx.cpp
@@ -221,7 +221,7 @@ const char* emoji = "\N{🤡}";
int x = cwg2640_a\N{abc});
// expected-error at -1 {{'abc' is not a valid Unicode character name}}
int y = cwg2640_a\N{LOTUS});
-// expected-error at -1 {{character <U+1FAB7> not allowed in an identifier}}
+// expected-error at -1 {{character '🪷' U+1FAB7 not allowed in an identifier}}
// expected-error at -2 {{use of undeclared identifier 'cwg2640_a🪷'}}
} // namespace cwg2640
diff --git a/clang/test/FixIt/fixit-unicode.c b/clang/test/FixIt/fixit-unicode.c
index 87819cdfbea17..16c0a4b2f3ebb 100644
--- a/clang/test/FixIt/fixit-unicode.c
+++ b/clang/test/FixIt/fixit-unicode.c
@@ -13,7 +13,7 @@ struct Foo {
void test1() {
struct Foo foo;
foo.bar = 42☃
- // CHECK: error: character <U+2603> not allowed in an identifier
+ // CHECK: error: character '☃' U+2603 not allowed in an identifier
// CHECK: {{^ \^}}
// Make sure we emit the fixit right in front of the snowman.
diff --git a/clang/test/Lexer/escape_newline_unicode.c b/clang/test/Lexer/escape_newline_unicode.c
index 81a6429df4841..9276d7e0e57de 100644
--- a/clang/test/Lexer/escape_newline_unicode.c
+++ b/clang/test/Lexer/escape_newline_unicode.c
@@ -34,5 +34,5 @@ int \
int a\
❌ = 0;
-// expected-error at -1 {{character <U+274C> not allowed in an identifier}}
+// expected-error at -1 {{character '❌' U+274C not allowed in an identifier}}
}
diff --git a/clang/test/Lexer/unicode.c b/clang/test/Lexer/unicode.c
index 5add2e49e4dfb..29be2bb5d270b 100644
--- a/clang/test/Lexer/unicode.c
+++ b/clang/test/Lexer/unicode.c
@@ -52,11 +52,11 @@ extern int a\N{TANGSALETTERGA}; // expected-error {{'TANGSALETTERGA' is not a va
// expected-error {{expected ';' after top level declarator}} \
// expected-note {{character names in Unicode escape sequences are sensitive to case and whitespace}}
-extern int 𝛛; // expected-warning {{mathematical notation character <U+1D6DB> in an identifier is a Clang extension}}
-extern int ₉; // expected-error {{character <U+2089> not allowed at the start of an identifier}} \\
+extern int 𝛛; // expected-warning {{mathematical notation character '𝛛' U+1D6DB in an identifier is a Clang extension}}
+extern int ₉; // expected-error {{character '₉' U+2089 not allowed at the start of an identifier}} \\
expected-warning {{declaration does not declare anything}}
-extern int a\N{PICKLE}; // expected-error {{character <U+1FADD> not allowed in an identifier}}
+extern int a\N{PICKLE}; // expected-error {{character '' U+1FADD not allowed in an identifier}}
int a¹b₍₄₂₎∇; // expected-warning 6{{mathematical notation character}}
@@ -70,20 +70,20 @@ int a\N{SUBSCRIPT EQUALS SIGN} = 1; // expected-warning {{mathematical notation
extern int \U00016AC0; // TANGSA DIGIT ZERO // cxx-error {{expected unqualified-id}} \
// c2x-error {{expected identifier or '('}}
-extern int 🌹; // expected-error {{unexpected character <U+1F339>}} \
+extern int 🌹; // expected-error {{unexpected character '🌹' U+1F339}} \
expected-warning {{declaration does not declare anything}}
extern int 🫎; // MOOSE (Unicode 15) \
- // expected-error {{unexpected character <U+1FACE>}} \
+ // expected-error {{unexpected character '🫎' U+1FACE}} \
expected-warning {{declaration does not declare anything}}
-extern int 👷; // expected-error {{unexpected character <U+1F477>}} \
+extern int 👷; // expected-error {{unexpected character '👷' U+1F477}} \
expected-warning {{declaration does not declare anything}}
extern int 👷♀; // expected-warning {{declaration does not declare anything}} \
- expected-error {{unexpected character <U+1F477>}} \
- expected-error {{character <U+200D> not allowed at the start of an identifier}} \
- expected-error {{unexpected character <U+2640>}}
+ expected-error {{unexpected character '👷' U+1F477}} \
+ expected-error {{character U+200D not allowed at the start of an identifier}} \
+ expected-error {{unexpected character '♀' U+2640}}
#else
// A 🌹 by any other name....
@@ -94,19 +94,19 @@ int main (void) {
return 🌷;
}
-int n; = 3; // expected-warning {{treating Unicode character <U+037E> as an identifier character rather than as ';' symbol}}
-int *n꞉꞉v = &n;; // expected-warning 2{{treating Unicode character <U+A789> as an identifier character rather than as ':' symbol}}
- // expected-warning at -1 {{treating Unicode character <U+037E> as an identifier character rather than as ';' symbol}}
-int v=[=](auto){return~x;}(); // expected-warning 12{{treating Unicode character}}
+int n; = 3; // expected-warning {{treating character ';' U+037E as an identifier character rather than as ';' symbol}}
+int *n꞉꞉v = &n;; // expected-warning 2{{treating character '꞉' U+A789 as an identifier character rather than as ':' symbol}}
+ // expected-warning at -1 {{treating character ';' U+037E as an identifier character rather than as ';' symbol}}
+int v=[=](auto){return~x;}(); // expected-warning 12{{treating character}}
int xx;
-// expected-warning at -1 {{identifier contains Unicode character <U+2060> that is invisible in some environments}}
-// expected-warning at -2 {{identifier contains Unicode character <U+FEFF> that is invisible in some environments}}
-// expected-warning at -3 {{identifier contains Unicode character <U+200D> that is invisible in some environments}}
-int foobar = 0; // expected-warning {{identifier contains Unicode character <U+200B> that is invisible in some environments}}
+// expected-warning at -1 {{identifier contains character U+2060 that is invisible in some environments}}
+// expected-warning at -2 {{identifier contains character U+FEFF that is invisible in some environments}}
+// expected-warning at -3 {{identifier contains character U+200D that is invisible in some environments}}
+int foobar = 0; // expected-warning {{identifier contains character U+200B that is invisible in some environments}}
int x = foobar; // expected-error {{undeclared identifier}}
-int ∣foo; // expected-error {{unexpected character <U+2223>}}
+int ∣foo; // expected-error {{unexpected character '∣' U+2223}}
#ifndef PP_ONLY
#define ∶ x // expected-error {{macro name must be an identifier}}
#endif
diff --git a/clang/test/Parser/cxx11-user-defined-literals.cpp b/clang/test/Parser/cxx11-user-defined-literals.cpp
index 27a7181bc9f91..968868509de19 100644
--- a/clang/test/Parser/cxx11-user-defined-literals.cpp
+++ b/clang/test/Parser/cxx11-user-defined-literals.cpp
@@ -148,6 +148,6 @@ void operator""_℮""_℮(unsigned long long) {} // expected-note {{previous}}
void operator""_\u212e""_\u212e(unsigned long long) {} // expected-error {{redefinition}}
#define ¢ *0.01 // expected-error {{macro name must be an identifier}}
-constexpr int operator""_¢(long double d) { return d * 100; } // expected-error {{character <U+00A2> not allowed in an identifier}}
-constexpr int operator""_¢(unsigned long long n) { return n; } // expected-error {{character <U+00A2> not allowed in an identifier}}
-static_assert(0.02_¢ == 2_¢, ""); // expected-error 2{{character <U+00A2> not allowed in an identifier}}
+constexpr int operator""_¢(long double d) { return d * 100; } // expected-error {{character '¢' U+00A2 not allowed in an identifier}}
+constexpr int operator""_¢(unsigned long long n) { return n; } // expected-error {{character '¢' U+00A2 not allowed in an identifier}}
+static_assert(0.02_¢ == 2_¢, ""); // expected-error 2{{character '¢' U+00A2 not allowed in an identifier}}
diff --git a/clang/test/ParserHLSL/semantic_parsing.hlsl b/clang/test/ParserHLSL/semantic_parsing.hlsl
index 1a914dd853768..232d47a4da7fc 100644
--- a/clang/test/ParserHLSL/semantic_parsing.hlsl
+++ b/clang/test/ParserHLSL/semantic_parsing.hlsl
@@ -36,9 +36,9 @@ void UnicodePony(int GI : ℮) { }
// mentioned in N3337.
// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1949r7.html
-// expected-error at +2 {{unexpected character <U+1F60A>}}
+// expected-error at +2 {{unexpected character '😊' U+1F60A}}
// expected-error at +1 {{expected HLSL Semantic identifier}}
void UTFPony(int GI : 😊) { }
-// expected-error at +1 {{character <U+1F60A> not allowed in an identifier}}
+// expected-error at +1 {{character '😊' U+1F60A not allowed in an identifier}}
void SmilingPony(int GI : PonyWithA😊) { }
diff --git a/clang/test/Preprocessor/ucn-allowed-chars.c b/clang/test/Preprocessor/ucn-allowed-chars.c
index 0409ad07c559a..8a6c40a3ecff5 100644
--- a/clang/test/Preprocessor/ucn-allowed-chars.c
+++ b/clang/test/Preprocessor/ucn-allowed-chars.c
@@ -38,8 +38,8 @@ extern char \u0D61; // C99, C11, C++03, C++11
#if __cplusplus
-// expected-error at 10 {{character <U+0384> not allowed in an identifier}}
-// expected-error at 12 {{character <U+FFFF> not allowed in an identifier}}
+// expected-error at 10 {{character '΄' U+0384 not allowed in an identifier}}
+// expected-error at 12 {{character U+FFFF not allowed in an identifier}}
// expected-error at 18 {{expected unqualified-id}}
# if __cplusplus >= 201103L
// C++11
@@ -56,8 +56,8 @@ extern char \u0D61; // C99, C11, C++03, C++11
# if __STDC_VERSION__ >= 202311L
// C23
// expected-warning at 8 {{using this character in an identifier is incompatible with C99}}
-// expected-error at 10 {{character <U+0384> not allowed in an identifier}}
-// expected-error at 12 {{character <U+FFFF> not allowed in an identifier}}
+// expected-error at 10 {{character '΄' U+0384 not allowed in an identifier}}
+// expected-error at 12 {{character U+FFFF not allowed in an identifier}}
// expected-error at 18 {{expected identifier}}
// expected-error at 19 {{expected identifier}}
// expected-error at 33 {{invalid universal character}}
@@ -65,7 +65,7 @@ extern char \u0D61; // C99, C11, C++03, C++11
// C11
// expected-warning at 8 {{using this character in an identifier is incompatible with C99}}
// expected-warning at 10 {{using this character in an identifier is incompatible with C99}}
-// expected-error at 12 {{character <U+FFFF> not allowed in an identifier}}
+// expected-error at 12 {{character U+FFFF not allowed in an identifier}}
// expected-warning at 18 {{starting an identifier with this character is incompatible with C99}}
// expected-error at 19 {{expected identifier}}
// expected-error at 33 {{invalid universal character}}
diff --git a/clang/test/Preprocessor/ucn-pp-identifier.c b/clang/test/Preprocessor/ucn-pp-identifier.c
index ee008a73eb882..0311d3eb29d1b 100644
--- a/clang/test/Preprocessor/ucn-pp-identifier.c
+++ b/clang/test/Preprocessor/ucn-pp-identifier.c
@@ -161,4 +161,4 @@ int a\N{LATIN CAPITAL LETTER A WITH GRAVE??>;
#endif
// GH64161
-int A\N{LEFT-TO-RIGHT OVERRIDE}; // expected-error {{character <U+202D> not allowed in an identifier}}
+int A\N{LEFT-TO-RIGHT OVERRIDE}; // expected-error {{character U+202D not allowed in an identifier}}
diff --git a/clang/test/Preprocessor/utf8-allowed-chars.c b/clang/test/Preprocessor/utf8-allowed-chars.c
index db8a62e29ff6c..ce670530c9b5b 100644
--- a/clang/test/Preprocessor/utf8-allowed-chars.c
+++ b/clang/test/Preprocessor/utf8-allowed-chars.c
@@ -26,8 +26,8 @@ extern char ̀; // disallowed initially in C11/C++, always in C99
#if __cplusplus
// expected-error at 11 {{not allowed in an identifier}}
// expected-error at 13 {{not allowed in an identifier}}
-// expected-error at 20 {{character <U+0E50> not allowed at the start of an identifier}}
-// expected-error at 21 {{character <U+0300> not allowed at the start of an identifier}}
+// expected-error at 20 {{character '๐' U+0E50 not allowed at the start of an identifier}}
+// expected-error at 21 {{character '̀' U+0300 not allowed at the start of an identifier}}
// expected-warning at 20 {{declaration does not declare anything}}
// expected-warning at 21 {{declaration does not declare anything}}
@@ -48,8 +48,8 @@ extern char ̀; // disallowed initially in C11/C++, always in C99
// expected-error at 11 {{not allowed in an identifier}}
// expected-error at 13 {{not allowed in an identifier}}
// expected-error at 14 {{not allowed in an identifier}}
-// expected-error at 20 {{character <U+0E50> not allowed at the start of an identifier}}
-// expected-error at 21 {{unexpected character <U+0300>}}
+// expected-error at 20 {{character '๐' U+0E50 not allowed at the start of an identifier}}
+// expected-error at 21 {{unexpected character '̀' U+0300}}
// expected-warning at 20 {{declaration does not declare anything}}
// expected-warning at 21 {{declaration does not declare anything}}
diff --git a/clang/unittests/Basic/DiagnosticTest.cpp b/clang/unittests/Basic/DiagnosticTest.cpp
index 13553491397f2..793431bbbe154 100644
--- a/clang/unittests/Basic/DiagnosticTest.cpp
+++ b/clang/unittests/Basic/DiagnosticTest.cpp
@@ -460,6 +460,7 @@ TEST(EscapeSingleCodepointForDiagnosticTest, nonPrintableDisplaysNoQuoted) {
EXPECT_EQ(EscapeSingleCodepointForDiagnostic(U'\n'), "U+000A");
EXPECT_EQ(EscapeSingleCodepointForDiagnostic(U'\0'), "U+0000");
EXPECT_EQ(EscapeSingleCodepointForDiagnostic(U'\x1B'), "U+001B");
+ EXPECT_EQ(EscapeSingleCodepointForDiagnostic(U'\uFEFF'), "U+FEFF");
}
TEST(EscapeSingleCodepointForDiagnosticTest, nonScalarValues) {
More information about the cfe-commits
mailing list