llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangd

Author: Yihan Wang (yronglin)

<details>
<summary>Changes</summary>

In code-completion mode, `Parser::trySkippingFunctionBody()` uses a 
TentativeParsingAction to decide whether a function body can be skipped. We use 
`SkipUntil(tok::r_brace, StopAtCodeCompletion)`, which consumes the matching 
closing brace while the tentative parse is still active.

Consuming that brace lexes one token past the skipped function body. In clangd, 
when the completion point is reached while unwinding a self-include, this can 
hit the code-completion `EOF` path before the tentative parse has committed. 
That `EOF` path restores the lexer callback to `CLK_CachingLexer`. When control 
returns to CachingLex(), it tries to enter caching lex mode again and 
encounters the assertion (We tried to re-enter CachineLexMode while the 
Preprocessor was already in CachineLexMode.).

We fix this by stopping before the function body's closing brace while the 
tentative parse is active. Once we know the body does not contain the 
code-completion token, commit the tentative parse first, then consume the 
closing brace outside backtracking/caching mode.

Function try blocks conservatively fall back to normal parsing in 
code-completion mode, because determining the end of the full try/catch 
sequence requires lexing across body/catch boundaries while the tentative parse 
is active.

Add a clangd regression test covering a self-include file where signature help 
is requested at the main-file #endif after the included function body.

Fixes https://github.com/llvm/llvm-project/issues/200677

---
Full diff: https://github.com/llvm/llvm-project/pull/203716.diff


2 Files Affected:

- (modified) clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp (+17) 
- (modified) clang/lib/Parse/ParseStmt.cpp (+5-9) 


``````````diff
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/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 37f142e059930..e77d6066847b2 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -2496,8 +2496,10 @@ bool Parser::trySkippingFunctionBody() {
 
   // We're in code-completion mode. Skip parsing for all function bodies unless
   // the body contains the code-completion point.
+  if (Tok.is(tok::kw_try))
+    return false;
+
   TentativeParsingAction PA(*this);
-  bool IsTryCatch = Tok.is(tok::kw_try);
   CachedTokens Toks;
   bool ErrorInPrologue = ConsumeAndStoreFunctionPrologue(Toks);
   if (llvm::any_of(Toks, [](const Token &Tok) {
@@ -2511,18 +2513,12 @@ bool Parser::trySkippingFunctionBody() {
     SkipMalformedDecl();
     return true;
   }
-  if (!SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
+  if (!SkipUntil(tok::r_brace, StopAtCodeCompletion | StopBeforeMatch)) {
     PA.Revert();
     return false;
   }
-  while (IsTryCatch && Tok.is(tok::kw_catch)) {
-    if (!SkipUntil(tok::l_brace, StopAtCodeCompletion) ||
-        !SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
-      PA.Revert();
-      return false;
-    }
-  }
   PA.Commit();
+  ConsumeBrace();
   return true;
 }
 

``````````

</details>


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

Reply via email to