Author: Akash Manna
Date: 2026-08-31T09:56:50Z
New Revision: 5702fda2aed05e98ca2578a9682996ff520df093

URL: 
https://github.com/llvm/llvm-project/commit/5702fda2aed05e98ca2578a9682996ff520df093
DIFF: 
https://github.com/llvm/llvm-project/commit/5702fda2aed05e98ca2578a9682996ff520df093.diff

LOG: [Clang] Fix double revert of a keyword token that was cached before the 
first fallback (#219799)

Fixes #214128

When an undeclared name is followed by `<`, the parser tentatively looks
for a template-argument list and, on invalid input, can skip all the way
to the end of the file. Every token after that point is lexed and cached
while the type-trait keywords still have their keyword kind. The first
`struct __make_unsigned` then reverts the keyword to an identifier, but
the second `struct __make_unsigned` is replayed from the cache with the
stale keyword kind, so `TryKeywordIdentFallback` tries to revert the
same `IdentifierInfo` again and trips the assertion in
`revertTokenIDToIdentifier`. The same thing can happen with any keyword
this hack covers (`__is_pod`, `__is_signed`, the transform traits) and
with any cached token, since a `Token` is just a snapshot of the
classification at lex time.

`TryKeywordIdentFallback` now asks the `IdentifierInfo`, which is the
source of truth, before doing anything: if the keyword has already been
made an identifier for the remainder of the translation unit, the token
kind is simply fixed up and no diagnostic or revert happens a second
time. First encounters behave exactly as before.

LLM tools were used for this contribution. I've reviewed, built, and
tested the change myself before pushing to GitHub.

Added: 
    clang/test/Parser/GH214128.cpp

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/Parse/Parser.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index bdbabf2cd98d0..4056e01f559aa 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -551,6 +551,11 @@ features cannot lower the translation-unit ABI level;
   inside a union caused the union to be treated as a polymorphic class.
   (#GH213854)
 
+- Fixed an assertion when a type-trait keyword that had already been made
+  available as an identifier (e.g. `struct __make_unsigned`) was seen again
+  in a token that was lexed and cached before the first occurrence was parsed.
+  (#GH214128)
+
 #### Bug Fixes to AST Handling
 
 - Fixed a non-deterministic ordering of unused local typedefs that made

diff  --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index bad81ea92cd2d..84059a41238cc 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1849,11 +1849,20 @@ SourceLocation Parser::getEndOfPreviousToken() const {
 
 bool Parser::TryKeywordIdentFallback(bool DisableKeyword) {
   assert(Tok.isNot(tok::identifier));
+  IdentifierInfo *II = Tok.getIdentifierInfo();
+
+  // A token lexed and cached before an earlier fallback reverted this keyword
+  // still carries the stale keyword kind; it is already an identifier.
+  if (II->getTokenID() == tok::identifier) {
+    Tok.setKind(tok::identifier);
+    return true;
+  }
+
   Diag(Tok, diag::ext_keyword_as_ident)
     << PP.getSpelling(Tok)
     << DisableKeyword;
   if (DisableKeyword)
-    Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
+    II->revertTokenIDToIdentifier();
   Tok.setKind(tok::identifier);
   return true;
 }

diff  --git a/clang/test/Parser/GH214128.cpp b/clang/test/Parser/GH214128.cpp
new file mode 100644
index 0000000000000..a6021ce36d781
--- /dev/null
+++ b/clang/test/Parser/GH214128.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+i < 0
+// expected-error@-1 {{no template named 'i'}}
+// expected-error@-2 {{expected '>'}}
+// expected-note@-3 {{to match this '<'}}
+
+void f() {
+  struct __is_pod; // expected-warning {{keyword '__is_pod' will be made 
available as an identifier for the remainder of the translation unit}}
+  struct __is_pod;
+}


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to