https://github.com/hongtaihu created 
https://github.com/llvm/llvm-project/pull/207130

Fixes #196067.

This patch fixes the expansion locations of synthesized tokens produced by
feature-like builtin macros such as `__has_builtin(...)`.

Feature-like builtin macros lex past the macro name while evaluating their
arguments. `ExpandBuiltinMacro()` used the final `Tok` location as both the
expansion start and end when creating the synthesized result token, so
`__has_builtin(...)` results were anchored at the closing paren rather than the
builtin macro invocation.

Fix by saving the macro-name location before argument parsing and using it as
the expansion start. The expansion end remains the final `Tok` location.

Add a `syntax::TokenCollector` regression test for a valid `__has_builtin(...)`
expansion and the `__is_identifier;` recovery path.

Tested:
`ninja -C /home/ubuntu2404/build-196067-assert check-clang`

Total Discovered Tests: 52396
Skipped: 6
Unsupported: 5782
Passed: 46582
Expectedly Failed: 26

Assisted-by: OpenAI Codex


>From 4c4f1e3d4869be85b667c94cb446a586a77a2c46 Mon Sep 17 00:00:00 2001
From: hongtaihu <[email protected]>
Date: Thu, 2 Jul 2026 14:43:32 +0800
Subject: [PATCH] [clang][Preprocessor] Fix expansion locations for
 feature-like builtin macros

Fixes #196067.

This patch fixes the expansion locations of synthesized tokens produced by 
feature-like builtin macros such as `__has_builtin(...)`.

Feature-like builtin macros lex past the macro name while evaluating their 
arguments. `ExpandBuiltinMacro()` used the final `Tok` location as both the 
expansion start and end when creating the synthesized result token, so 
`__has_builtin(...)` results were anchored at the closing paren rather than the 
builtin macro invocation.

Fix by saving the macro-name location before argument parsing and using it as 
the expansion start. The expansion end remains the final `Tok` location.

Add a `syntax::TokenCollector` regression test for a valid `__has_builtin(...)` 
expansion and the `__is_identifier;` recovery path.

Assisted-by: OpenAI Codex
---
 clang/lib/Lex/PPMacroExpansion.cpp            |  3 ++-
 clang/unittests/Tooling/Syntax/TokensTest.cpp | 13 +++++++++++++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Lex/PPMacroExpansion.cpp 
b/clang/lib/Lex/PPMacroExpansion.cpp
index 23a21f42b8e3a..e09e80a063c4e 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -1619,6 +1619,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
   // Figure out which token this is.
   IdentifierInfo *II = Tok.getIdentifierInfo();
   assert(II && "Can't be a macro without id info!");
+  SourceLocation MacroNameLoc = Tok.getLocation();
 
   // If this is an _Pragma or Microsoft __pragma directive, expand it,
   // invoke the pragma handler, then lex the token after it.
@@ -2096,7 +2097,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
   } else {
     llvm_unreachable("Unknown identifier!");
   }
-  CreateString(OS.str(), Tok, Tok.getLocation(), Tok.getLocation());
+  CreateString(OS.str(), Tok, MacroNameLoc, Tok.getLocation());
   Tok.setFlagValue(Token::StartOfLine, IsAtStartOfLine);
   Tok.setFlagValue(Token::LeadingSpace, HasLeadingSpace);
   Tok.clearFlag(Token::NeedsCleaning);
diff --git a/clang/unittests/Tooling/Syntax/TokensTest.cpp 
b/clang/unittests/Tooling/Syntax/TokensTest.cpp
index ae5001a2f5645..7c0b0d0d5df7c 100644
--- a/clang/unittests/Tooling/Syntax/TokensTest.cpp
+++ b/clang/unittests/Tooling/Syntax/TokensTest.cpp
@@ -552,6 +552,19 @@ file './input.cpp'
   }
 }
 
+TEST_F(TokenCollectorTest, FeatureLikeBuiltinMacros) {
+  recordTokens("__has_builtin(__builtin_allow_runtime_check)\n");
+  EXPECT_THAT(Buffer.expandedTokens(),
+              ElementsAre(AllOf(Kind(tok::numeric_constant), HasText("1")),
+                          Kind(tok::eof)));
+
+  AllowErrors = true;
+  recordTokens("__is_identifier;\n");
+  EXPECT_THAT(Buffer.expandedTokens(),
+              ElementsAre(AllOf(Kind(tok::numeric_constant), HasText("0")),
+                          Kind(tok::eof)));
+}
+
 TEST_F(TokenCollectorTest, SpecialTokens) {
   // Tokens coming from concatenations.
   recordTokens(R"cpp(

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

Reply via email to