[clang-tools-extra] [clangd] Fix crash on completion with out-of-range position (PR #196112)
Krzysztof Jędruczyk via cfe-commits
cfe-commits at lists.llvm.org
Wed May 6 10:08:50 PDT 2026
https://github.com/kjedruczyk updated https://github.com/llvm/llvm-project/pull/196112
>From 6ce84e65d9ba636e10aa72ac96b057808fc3f4e5 Mon Sep 17 00:00:00 2001
From: Krzysztof Jedruczyk <kjedruczyk at bloomberg.net>
Date: Wed, 6 May 2026 17:04:24 +0100
Subject: [PATCH 1/2] [clangd] Fix crash on completion with out-of-range
position
shouldRunCompletion() checked the Expected<> from positionToOffset() via
operator!() but never consumed the error with takeError(). This caused an
assertion failure when a TriggerCharacter completion request had a position
beyond the document bounds.
---
clang-tools-extra/clangd/ClangdLSPServer.cpp | 3 ++-
.../clangd/unittests/ClangdLSPServerTests.cpp | 20 +++++++++++++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index ebd42abd2dd61..811c3b33d27ca 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -1801,7 +1801,8 @@ bool ClangdLSPServer::shouldRunCompletion(
if (!Offset) {
vlog("could not convert position '{0}' to offset for file '{1}'",
Params.position, Params.textDocument.uri.file());
- return true;
+ llvm::consumeError(Offset.takeError());
+ return true; // completion code will log the error for invalid position.
}
return allowImplicitCompletion(*Code, *Offset);
}
diff --git a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
index 95bf5e54fc792..0aca1433614dc 100644
--- a/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ClangdLSPServerTests.cpp
@@ -492,6 +492,26 @@ TEST_F(LSPTest, DiagModuleTest) {
EXPECT_THAT(Client.diagnostics("foo.cpp"),
llvm::ValueIs(testing::ElementsAre(diagMessage(DiagMsg))));
}
+
+// Regression test for https://github.com/llvm/llvm-project/issues/196072.
+TEST_F(LSPTest, CompletionOutOfRangePosition) {
+ auto &Client = start();
+ Client.didOpen("foo.cpp", "int x;");
+ auto &Reply = Client.call(
+ "textDocument/completion",
+ llvm::json::Object{
+ {"textDocument", Client.documentID("foo.cpp")},
+ {"position", llvm::json::Object{{"line", 97}, {"character", 0}}},
+ {"context",
+ llvm::json::Object{
+ {"triggerKind", 2},
+ {"triggerCharacter", ">"},
+ }},
+ });
+ auto Result = Reply.take();
+ ASSERT_TRUE(!!Result) << "Expected a response, not a server crash";
+}
+
} // namespace
} // namespace clangd
} // namespace clang
>From 635f4212178e23f80ef61cae327ecd5c0acc414d Mon Sep 17 00:00:00 2001
From: Krzysztof Jedruczyk <kjedruczyk at bloomberg.net>
Date: Wed, 6 May 2026 18:06:46 +0100
Subject: [PATCH 2/2] [clangd] log the line out of range error instead of
consuming
---
clang-tools-extra/clangd/ClangdLSPServer.cpp | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index 811c3b33d27ca..7d5367e4d2d41 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -1799,10 +1799,9 @@ bool ClangdLSPServer::shouldRunCompletion(
auto Offset = positionToOffset(*Code, Params.position,
/*AllowColumnsBeyondLineLength=*/false);
if (!Offset) {
- vlog("could not convert position '{0}' to offset for file '{1}'",
- Params.position, Params.textDocument.uri.file());
- llvm::consumeError(Offset.takeError());
- return true; // completion code will log the error for invalid position.
+ vlog("could not convert position '{0}' to offset for file '{1}': {2}",
+ Params.position, Params.textDocument.uri.file(), Offset.takeError());
+ return true;
}
return allowImplicitCompletion(*Code, *Offset);
}
More information about the cfe-commits
mailing list