Author: Macro Terra Date: 2026-07-10T08:28:57-04:00 New Revision: 235056b9efea87a1a7fa0d36f94e56a44dbd920b
URL: https://github.com/llvm/llvm-project/commit/235056b9efea87a1a7fa0d36f94e56a44dbd920b DIFF: https://github.com/llvm/llvm-project/commit/235056b9efea87a1a7fa0d36f94e56a44dbd920b.diff LOG: [clang][Preprocessor] Fix expansion locations for feature-like builtin macros (#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 Added: Modified: clang/docs/ReleaseNotes.md clang/lib/Lex/PPMacroExpansion.cpp clang/unittests/Tooling/Syntax/TokensTest.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 5a321cdb7e3cd..7f0a28acd2ade 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -790,6 +790,9 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the - Fixed `clang::Preprocessor::recomputeCurLexerKind` to avoid default fallback to `CurLexerCallback = CLK_CachingLexer;`. This prevents code-completion EOF handling from accidentally restoring CLK_CachingLexer while a tentative parse is still active, which could trigger a caching lexer re-entry assertion in clangd signature help. (#GH200677) +- Fixed incorrect expansion source ranges for synthesized tokens produced by + feature-like builtin macros such as `__has_builtin`, which could trigger + assertions in syntax token collection. (#GH196067) - Fixed a crash when `#embed` is used with C++ modules (#GH195350) - Fixed an assertion in constant evaluation when using a defaulted comparison operator in a `union`. (#GH147127) - Fixed a bug where `-x cuda` caused clang to immediately resolve templates that should not be. (#GH200545) 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..6418cc8f87d9d 100644 --- a/clang/unittests/Tooling/Syntax/TokensTest.cpp +++ b/clang/unittests/Tooling/Syntax/TokensTest.cpp @@ -552,6 +552,18 @@ 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()); + EXPECT_EQ(findSpelled("__has_builtin").front().location(), + ExpansionRange.getBegin()); + EXPECT_EQ(findSpelled(")").front().location(), ExpansionRange.getEnd()); +} + 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
