[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 foo​bar = 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 foo​bar = 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