https://github.com/dzbarsky updated 
https://github.com/llvm/llvm-project/pull/203121

>From a7565f229055522e375f732f8c007f136885c163 Mon Sep 17 00:00:00 2001
From: David Zbarsky <[email protected]>
Date: Wed, 10 Jun 2026 19:15:23 -0400
Subject: [PATCH] [clangd][Support] Outline LSP payload decode errors

Move failed payload handling from clangd::LSPBinder::parse<T> and 
llvm::lsp::MessageHandler::parse<T> into their non-inline handleParseError 
functions. Successful payload conversion remains specialized in each parse<T> 
instantiation.

In a matched Release assertions-off Darwin arm64 build, clangd decreases by 
33,584 bytes unstripped and 32,848 bytes stripped, with 25,180 fewer bytes in 
__TEXT,__text. Linked fixups are unchanged. A 16-pair successful-parse 
benchmark measured -4.4% CPU time with a 95% confidence interval of [-5.2%, 
-3.7%].

ClangdTests --gtest_filter=LSPBinderTest.* passes. 
llvm/lib/Support/LSP/Transport.cpp passes a standalone syntax compile.

Co-authored-by: OpenAI Codex <[email protected]>
---
 clang-tools-extra/clangd/CMakeLists.txt       |  1 +
 clang-tools-extra/clangd/LSPBinder.cpp        | 36 +++++++++++++++++++
 clang-tools-extra/clangd/LSPBinder.h          | 20 ++++-------
 llvm/include/llvm/Support/LSP/Transport.h     | 20 ++++-------
 llvm/lib/Support/LSP/Transport.cpp            | 17 +++++++++
 .../clang-tools-extra/clangd/BUILD.gn         |  1 +
 .../clang-tools-extra/clangd/BUILD.bazel      |  1 +
 7 files changed, 69 insertions(+), 27 deletions(-)
 create mode 100644 clang-tools-extra/clangd/LSPBinder.cpp

diff --git a/clang-tools-extra/clangd/CMakeLists.txt 
b/clang-tools-extra/clangd/CMakeLists.txt
index 890562dde1792..9fa7d92d8374c 100644
--- a/clang-tools-extra/clangd/CMakeLists.txt
+++ b/clang-tools-extra/clangd/CMakeLists.txt
@@ -96,6 +96,7 @@ add_clang_library(clangDaemon STATIC
   IncludeFixer.cpp
   InlayHints.cpp
   JSONTransport.cpp
+  LSPBinder.cpp
   ModulesBuilder.cpp
   PathMapping.cpp
   ProjectModules.cpp
diff --git a/clang-tools-extra/clangd/LSPBinder.cpp 
b/clang-tools-extra/clangd/LSPBinder.cpp
new file mode 100644
index 0000000000000..8e997776f3763
--- /dev/null
+++ b/clang-tools-extra/clangd/LSPBinder.cpp
@@ -0,0 +1,36 @@
+//===--- LSPBinder.cpp - Tables of LSP handlers --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "LSPBinder.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+namespace clangd {
+
+// Keep handleParseError out of every parse<T> instantiation.
+LLVM_ATTRIBUTE_NOINLINE llvm::Error LSPBinder::handleParseError(
+    const llvm::json::Value &Raw, llvm::StringRef PayloadName,
+    llvm::StringRef PayloadKind, const llvm::json::Path::Root &Root) {
+  elog("Failed to decode {0} {1}: {2}", PayloadName, PayloadKind,
+       Root.getError());
+  // Dump the relevant parts of the broken message.
+  std::string Context;
+  llvm::raw_string_ostream OS(Context);
+  Root.printErrorContext(Raw, OS);
+  vlog("{0}", OS.str());
+  // Report the error (e.g. to the client).
+  return llvm::make_error<LSPError>(
+      llvm::formatv("failed to decode {0} {1}: {2}", PayloadName, PayloadKind,
+                    fmt_consume(Root.getError())),
+      ErrorCode::InvalidParams);
+}
+
+} // namespace clangd
+} // namespace clang
diff --git a/clang-tools-extra/clangd/LSPBinder.h 
b/clang-tools-extra/clangd/LSPBinder.h
index 8542112681375..74b4bd0f708ff 100644
--- a/clang-tools-extra/clangd/LSPBinder.h
+++ b/clang-tools-extra/clangd/LSPBinder.h
@@ -101,6 +101,10 @@ class LSPBinder {
   static llvm::Expected<T> parse(const llvm::json::Value &Raw,
                                  llvm::StringRef PayloadName,
                                  llvm::StringRef PayloadKind);
+  static llvm::Error handleParseError(const llvm::json::Value &Raw,
+                                      llvm::StringRef PayloadName,
+                                      llvm::StringRef PayloadKind,
+                                      const llvm::json::Path::Root &Root);
 
   RawHandlers &Raw;
   RawOutgoing &Out;
@@ -112,20 +116,8 @@ llvm::Expected<T> LSPBinder::parse(const llvm::json::Value 
&Raw,
                                    llvm::StringRef PayloadKind) {
   T Result;
   llvm::json::Path::Root Root;
-  if (!fromJSON(Raw, Result, Root)) {
-    elog("Failed to decode {0} {1}: {2}", PayloadName, PayloadKind,
-         Root.getError());
-    // Dump the relevant parts of the broken message.
-    std::string Context;
-    llvm::raw_string_ostream OS(Context);
-    Root.printErrorContext(Raw, OS);
-    vlog("{0}", OS.str());
-    // Report the error (e.g. to the client).
-    return llvm::make_error<LSPError>(
-        llvm::formatv("failed to decode {0} {1}: {2}", PayloadName, 
PayloadKind,
-                      fmt_consume(Root.getError())),
-        ErrorCode::InvalidParams);
-  }
+  if (!fromJSON(Raw, Result, Root))
+    return handleParseError(Raw, PayloadName, PayloadKind, Root);
   return std::move(Result);
 }
 
diff --git a/llvm/include/llvm/Support/LSP/Transport.h 
b/llvm/include/llvm/Support/LSP/Transport.h
index 6a0dd51d946bd..eee4a4e525fde 100644
--- a/llvm/include/llvm/Support/LSP/Transport.h
+++ b/llvm/include/llvm/Support/LSP/Transport.h
@@ -172,19 +172,9 @@ class MessageHandler {
                                  StringRef PayloadName, StringRef PayloadKind) 
{
     T Result;
     llvm::json::Path::Root Root;
-    if (fromJSON(Raw, Result, Root))
-      return std::move(Result);
-
-    // Dump the relevant parts of the broken message.
-    std::string Context;
-    llvm::raw_string_ostream Os(Context);
-    Root.printErrorContext(Raw, Os);
-
-    // Report the error (e.g. to the client).
-    return llvm::make_error<LSPError>(
-        llvm::formatv("failed to decode {0} {1}: {2}", PayloadName, 
PayloadKind,
-                      fmt_consume(Root.getError())),
-        ErrorCode::InvalidParams);
+    if (!fromJSON(Raw, Result, Root))
+      return handleParseError(Raw, PayloadName, PayloadKind, Root);
+    return std::move(Result);
   }
 
   template <typename Param, typename Result, typename ThisT>
@@ -266,6 +256,10 @@ class MessageHandler {
   }
 
 private:
+  LLVM_ABI static llvm::Error
+  handleParseError(const llvm::json::Value &Raw, StringRef PayloadName,
+                   StringRef PayloadKind, const llvm::json::Path::Root &Root);
+
   template <typename HandlerT>
   using HandlerMap = llvm::StringMap<llvm::unique_function<HandlerT>>;
 
diff --git a/llvm/lib/Support/LSP/Transport.cpp 
b/llvm/lib/Support/LSP/Transport.cpp
index 31b5a89f9b5e0..e79ca679878d0 100644
--- a/llvm/lib/Support/LSP/Transport.cpp
+++ b/llvm/lib/Support/LSP/Transport.cpp
@@ -83,6 +83,23 @@ void Reply::operator()(llvm::Expected<llvm::json::Value> 
Reply) {
 // MessageHandler
 
//===----------------------------------------------------------------------===//
 
+// Keep handleParseError out of every parse<T> instantiation.
+LLVM_ATTRIBUTE_NOINLINE llvm::Error
+MessageHandler::handleParseError(const llvm::json::Value &Raw,
+                                 StringRef PayloadName, StringRef PayloadKind,
+                                 const llvm::json::Path::Root &Root) {
+  // Dump the relevant parts of the broken message.
+  std::string Context;
+  llvm::raw_string_ostream Os(Context);
+  Root.printErrorContext(Raw, Os);
+
+  // Report the error (e.g. to the client).
+  return llvm::make_error<LSPError>(
+      llvm::formatv("failed to decode {0} {1}: {2}", PayloadName, PayloadKind,
+                    fmt_consume(Root.getError())),
+      ErrorCode::InvalidParams);
+}
+
 bool MessageHandler::onNotify(llvm::StringRef Method, llvm::json::Value Value) 
{
   Logger::info("--> {0}", Method);
 
diff --git a/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn 
b/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
index 86f959816f958..f30aac6add176 100644
--- a/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn
@@ -112,6 +112,7 @@ static_library("clangd") {
     "IncludeFixer.cpp",
     "InlayHints.cpp",
     "JSONTransport.cpp",
+    "LSPBinder.cpp",
     "ModulesBuilder.cpp",
     "ParsedAST.cpp",
     "PathMapping.cpp",
diff --git 
a/utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel 
b/utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel
index 4151e55a938d9..34d44e8f63512 100644
--- a/utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang-tools-extra/clangd/BUILD.bazel
@@ -36,6 +36,7 @@ cc_library(
         "Feature.cpp",
         "Features.inc",
         "JSONTransport.cpp",
+        "LSPBinder.cpp",
         "Protocol.cpp",
         "URI.cpp",
         "index/SymbolID.cpp",

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

Reply via email to