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

Reply via email to