[clang] [Clang] Supports dollars in UDLs and pp-numbers (PR #208490)
Corentin Jabot via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 10 05:05:42 PDT 2026
https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/208490
>From e5e795a9254cdd19b6bde8e03621186a0b8d4c0e Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Thu, 9 Jul 2026 17:41:30 +0200
Subject: [PATCH] [Clang] Supports dollars in UDLs and pp-numbers
When dollars are supported in identifiers, we should be consistent.
Fixes #173985
Fixes #171190
---
clang/docs/ReleaseNotes.md | 3 +-
clang/lib/Lex/Lexer.cpp | 4 +--
clang/test/Lexer/dollar-idents.cpp | 47 ++++++++++++++++++++++++++++++
3 files changed, 51 insertions(+), 3 deletions(-)
create mode 100644 clang/test/Lexer/dollar-idents.cpp
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index be894701f5ce9..b0d80ebf34cac 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -787,6 +787,7 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the
- Fixed an issue where `__typeof_unqual` and `__typeof_unqual__` were rejected as a declaration specifier in block scope in C++.
- Fixed crash when checking for overflow for unary operator that can't overflow (#GH170072)
- Clang no longer handles a `" q-char-sequence "` header name as a string literal (#GH132643).
+- Under `-fdollars-in-identifiers`, the `$` can now appear in user-defined-literals. (#GH173985)
- Fixed an assertion where we improperly handled implicit conversions to integral types from an atomic-type with a conversion function. (#GH201770)
- Fixed assertion failures involving code completion with delayed default arguments and exception specifications. (#GH200879)
- Fixed a regression where calling a function that takes a class-type parameter by value inside `decltype` of a concept could be incorrectly rejected when used as a non-type template argument. (#GH175831)
@@ -1122,7 +1123,7 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the
- Fixed a crash in code completion when using a C-Style cast with a parenthesized
operand in Objective-C++ mode. (#GH180125)
-- Fixed a crash when code completion is triggered inside an ill-formed lambda's trailing requires-clause. (#GH201632)
+- Fixed a crash when code completion is triggered inside an ill-formed lambda's trailing requires-clause. (#GH201632)
### Static Analyzer
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index f52b84a42ca70..4742fd2073f05 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -2179,7 +2179,7 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr,
char C = getCharAndSize(CurPtr, Size);
bool Consumed = false;
- if (!isAsciiIdentifierStart(C)) {
+ if (!isAsciiIdentifierStart(C, LangOpts.DollarIdents)) {
if (C == '\\' && tryConsumeIdentifierUCN(CurPtr, Size, Result))
Consumed = true;
else if (!isASCII(C) && tryConsumeIdentifierUTF8Char(CurPtr, Result))
@@ -2217,7 +2217,7 @@ const char *Lexer::LexUDSuffix(Token &Result, const char *CurPtr,
while (true) {
auto [Next, NextSize] =
getCharAndSizeNoWarn(CurPtr + Consumed, LangOpts);
- if (!isAsciiIdentifierContinue(Next)) {
+ if (!isAsciiIdentifierContinue(Next, LangOpts.DollarIdents)) {
// End of suffix. Check whether this is on the allowed list.
const StringRef CompleteSuffix(Buffer, Chars);
IsUDSuffix =
diff --git a/clang/test/Lexer/dollar-idents.cpp b/clang/test/Lexer/dollar-idents.cpp
new file mode 100644
index 0000000000000..138451f8a49c6
--- /dev/null
+++ b/clang/test/Lexer/dollar-idents.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -std=c++11 -Wno-user-defined-literals -verify %s
+// RUN: %clang_cc1 -std=c++11 -Wno-user-defined-literals -verify=no_dollar -fno-dollars-in-identifiers %s
+
+int $; // no_dollar-error {{expected unqualified-id}}
+int $$; // no_dollar-error {{expected unqualified-id}}
+int Σ$; // no_dollar-error {{expected ';' after top level declarator}}
+int $Σ; // no_dollar-error {{expected unqualified-id}}
+
+using size_t = decltype(sizeof(void *));
+
+namespace UDL {
+
+int operator"" $(const char *p, size_t n); // no_dollar-error {{expected identifier}}
+int operator"" $$(const char *p, size_t n); // no_dollar-error {{expected identifier}}
+int operator"" Σ$(const char *p, size_t n); // no_dollar-error {{'operator""Σ' cannot be the name of a variable or data member}} \
+ // no_dollar-error {{expected ';' after top level declarator}}
+int operator"" $Σ(const char *p, size_t n); // no_dollar-error {{expected identifier}}
+int operator"" Σ(const char *p, size_t n);
+
+}
+namespace UDL2 {
+
+int operator"" _$(unsigned long long); // expected-warning {{identifier '_$' preceded by whitespace in a literal operator declaration is deprecated}} \
+ // no_dollar-error {{'operator""_' cannot be the name of a variable or data member}} \
+ // no_dollar-error {{expected ';' after top level declarator}} \
+ // no_dollar-warning {{identifier '_' preceded by whitespace in a literal operator declaration is deprecated}}
+int a = 1_$; // no_dollar-error {{no matching literal operator for call}}
+
+int operator"" _a$(unsigned long long); // expected-warning {{identifier '_a$' preceded by whitespace in a literal operator declaration is deprecated}} \
+ // no_dollar-error {{expected ';' after top level declarator}} \
+ // no_dollar-error {{'operator""_a' cannot be the name of a variable or data member}} \
+ // no_dollar-warning {{identifier '_a' preceded by whitespace in a literal operator declaration is deprecated}}
+int b = 1_a$; // no_dollar-error {{no matching literal operator for call}}
+
+
+int operator""_c$(unsigned long long); // no_dollar-error {{'operator""_c' cannot be the name of a variable or data member}} \
+ // no_dollar-error {{expected ';' after top level declarator}}
+int c = 1_c$; // no_dollar-error {{no matching literal operator for call}}
+
+}
+
+#define CAT(X,Y,Z)CAT_(X,Y##Z)
+#define CAT_(X,Y)X##Y
+void GH171190(){
+ int CAT(X,0,$); // no_dollar-error {{pasting formed '0$', an invalid preprocessing token}} \
+ // no_dollar-error {{expected ';' at end of declaration}}
+}
More information about the cfe-commits
mailing list