Author: Yihan Wang Date: 2026-06-23T23:25:02+08:00 New Revision: 83528bad5c9b9722280d284a7c35b06d560003bc
URL: https://github.com/llvm/llvm-project/commit/83528bad5c9b9722280d284a7c35b06d560003bc DIFF: https://github.com/llvm/llvm-project/commit/83528bad5c9b9722280d284a7c35b06d560003bc.diff LOG: [clangd] fix preprocessor caching-lexer state tracking (#203716) Fix `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. Fixes https://github.com/llvm/llvm-project/issues/200677 --------- Signed-off-by: yronglin <[email protected]> Added: Modified: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp clang/docs/ReleaseNotes.rst clang/include/clang/Lex/Preprocessor.h clang/lib/Lex/PPCaching.cpp clang/lib/Lex/PPLexerChange.cpp clang/lib/Lex/Preprocessor.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index 5808b2145965f..dc94af4dddf8c 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1918,6 +1918,23 @@ TEST(SignatureHelpTest, StalePreamble) { EXPECT_EQ(0, Results.activeParameter); } +TEST(SignatureHelpTest, EOFInSkippedFunctionBody) { + Annotations Test(R"cpp( +#ifdef IS_HEADER +void frameSizeBlocksWarning() { + auto fn = []() { + }; + fn(); +} +#else +#define IS_HEADER +#include __FILE__ +#^endif +)cpp"); + auto Results = signatures(Test.code(), Test.point()); + EXPECT_THAT(Results.signatures, IsEmpty()); +} + class IndexRequestCollector : public SymbolIndex { public: IndexRequestCollector(std::vector<Symbol> Syms = {}) : Symbols(Syms) {} diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index e86f1d9602bed..4aa13ce1384ac 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -725,6 +725,9 @@ Bug Fixes in This Version - Fixed a potential stack-use-after-return issue in Clang when copy-initializing an array via an element-at-a-time copy loop (#GH192026) - Fixed an issue where certain designated initializers would be rejected for constexpr variables. (#GH193373) +- 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 a crash when ``#embed`` is used with C++ modules (#GH195350) - Fixed a bug where ``-x cuda`` caused clang to immediately resolve templates that should not be. (#GH200545) - Fixed an issue where ``__typeof_unqual`` and ``__typeof_unqual__`` were rejected as a declaration specifier in block scope in C++. diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 8b684e85eb1c1..fc66bd745a618 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -2819,11 +2819,7 @@ class Preprocessor { // Caching stuff. void CachingLex(Token &Result); - bool InCachingLexMode() const { - // If the Lexer pointers are 0 and IncludeMacroStack is empty, it means - // that we are past EOF, not that we are in CachingLex mode. - return !CurPPLexer && !CurTokenLexer && !IncludeMacroStack.empty(); - } + bool InCachingLexMode() const { return CurLexerCallback == CLK_CachingLexer; } void EnterCachingLexMode(); void EnterCachingLexModeUnchecked(); diff --git a/clang/lib/Lex/PPCaching.cpp b/clang/lib/Lex/PPCaching.cpp index cbacda9d31ae2..3f0ebd8455685 100644 --- a/clang/lib/Lex/PPCaching.cpp +++ b/clang/lib/Lex/PPCaching.cpp @@ -117,16 +117,14 @@ void Preprocessor::EnterCachingLexMode() { assert(LexLevel == 0 && "entered caching lex mode while lexing something else"); - if (InCachingLexMode()) { - assert(CurLexerCallback == CLK_CachingLexer && "Unexpected lexer kind"); + if (InCachingLexMode()) return; - } EnterCachingLexModeUnchecked(); } void Preprocessor::EnterCachingLexModeUnchecked() { - assert(CurLexerCallback != CLK_CachingLexer && "already in caching lex mode"); + assert(!InCachingLexMode() && "already in caching lex mode"); PushIncludeMacroStack(); CurLexerCallback = CLK_CachingLexer; } diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp index 98ff9a9a04e7c..b44bf2cd3c253 100644 --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -172,7 +172,7 @@ void Preprocessor::EnterMacro(Token &Tok, SourceLocation ILEnd, void Preprocessor::EnterTokenStream(const Token *Toks, unsigned NumToks, bool DisableMacroExpansion, bool OwnsTokens, bool IsReinject) { - if (CurLexerCallback == CLK_CachingLexer) { + if (InCachingLexMode()) { if (CachedLexPos < CachedTokens.size()) { assert(IsReinject && "new tokens in the middle of cached stream"); // We're entering tokens into the middle of our cached token stream. We diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 1e21b4a94cea3..c69d084d6514f 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -417,14 +417,16 @@ StringRef Preprocessor::getLastMacroWithSpelling( } void Preprocessor::recomputeCurLexerKind() { - if (CurLexer) + if (InCachingLexMode()) + CurLexerCallback = CLK_CachingLexer; + else if (CurLexer) CurLexerCallback = CurLexer->isDependencyDirectivesLexer() ? CLK_DependencyDirectivesLexer : CLK_Lexer; else if (CurTokenLexer) CurLexerCallback = CLK_TokenLexer; else - CurLexerCallback = CLK_CachingLexer; + CurLexerCallback = CLK_Lexer; } bool Preprocessor::SetCodeCompletionPoint(FileEntryRef File, _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
