[clang] [clang][Preprocessor] Fix expansion locations for feature-like builtin macros (PR #207130)
Macro Terra via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 9 02:26:32 PDT 2026
https://github.com/hongtaihu updated https://github.com/llvm/llvm-project/pull/207130
>From 30cc618a32fdf8374d9b108f7788cf7e1731bdf1 Mon Sep 17 00:00:00 2001
From: hongtaihu <13541229370 at qq.com>
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 | 19 +++++++++++++++++++
2 files changed, 21 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..5efe52a9cbbb9 100644
--- a/clang/unittests/Tooling/Syntax/TokensTest.cpp
+++ b/clang/unittests/Tooling/Syntax/TokensTest.cpp
@@ -552,6 +552,25 @@ 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)));
+ auto ExpansionRange =
+ SourceMgr->getExpansionRange(findExpanded("1").front().location());
+ auto MacroInvocation =
+ findSpelled("__has_builtin ( __builtin_allow_runtime_check )");
+ EXPECT_EQ(MacroInvocation.front().location(), ExpansionRange.getBegin());
+ EXPECT_EQ(MacroInvocation.back().location(), ExpansionRange.getEnd());
+
+ 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(
More information about the cfe-commits
mailing list