https://github.com/dzbarsky created https://github.com/llvm/llvm-project/pull/203258
This replaces the generated `getDiagnosticCode` switch with one pointer-free character blob and a direct `uint32_t` offset table indexed by diagnostic ID; zero offsets preserve the existing `nullptr` result for unnamed diagnostic IDs. On an arm64 Release build, standalone clangd decreases by 49,480 bytes raw and 49,560 bytes stripped with 7,251 fewer linked fixups; there is no upstream clangd multicall target. Forty-nine clangd diagnostic unit tests pass, normalized `clangd --check` diagnostic codes match, and random successful lookup time measures 2.75 ns versus 2.53 ns for the switch. Work towards #202616 AI tool disclosure: Co-authored with OpenAI Codex. >From 1d4fffc84eba55f6f2f47702fc8efa4e0c7f4292 Mon Sep 17 00:00:00 2001 From: David Zbarsky <[email protected]> Date: Thu, 11 Jun 2026 09:14:09 -0400 Subject: [PATCH] [clangd] Store diagnostic names in a direct offset table Replace the generated getDiagnosticCode switch with one character blob and a direct uint32_t offset table indexed by diagnostic ID. Zero offsets retain the existing nullptr result for diagnostic IDs outside the named categories. On an arm64 Release build, Diagnostics.cpp.o decreases by 291,096 bytes and its relocations decrease by 7,263. clangd decreases by 49,480 bytes raw and 49,560 bytes stripped. Linked __TEXT,__text increases by 32 bytes, __TEXT,__const increases by 279,888 bytes, __TEXT,__cstring decreases by 239,400 bytes, __DATA_CONST,__const decreases by 71,408 bytes, and linked fixups decrease by 7,251. There is no upstream clangd multicall target. Random successful lookups measure 2.75 ns with the offset table and 2.53 ns with the switch. Forty-nine clangd diagnostic unit tests pass, and normalized clangd --check diagnostic codes match the switch implementation. --- .../clangd/DiagnosticNameKinds.inc | 27 +++++++++ clang-tools-extra/clangd/Diagnostics.cpp | 57 +++++++++++++------ 2 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 clang-tools-extra/clangd/DiagnosticNameKinds.inc diff --git a/clang-tools-extra/clangd/DiagnosticNameKinds.inc b/clang-tools-extra/clangd/DiagnosticNameKinds.inc new file mode 100644 index 0000000000000..a7c00d7f817ec --- /dev/null +++ b/clang-tools-extra/clangd/DiagnosticNameKinds.inc @@ -0,0 +1,27 @@ +//===-- DiagnosticNameKinds.inc - clangd diagnostic names -------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Expands the diagnostic categories whose names clangd exposes as LSP +// diagnostic codes. +// +// Diagnostics.cpp includes DiagnosticNameKinds.inc with different DIAG +// definitions, so DiagnosticNameKinds.inc intentionally has no include guard. + +// clang-format off +#include "clang/Basic/DiagnosticCommonKinds.inc" +#include "clang/Basic/DiagnosticDriverKinds.inc" +#include "clang/Basic/DiagnosticFrontendKinds.inc" +#include "clang/Basic/DiagnosticSerializationKinds.inc" +#include "clang/Basic/DiagnosticLexKinds.inc" +#include "clang/Basic/DiagnosticParseKinds.inc" +#include "clang/Basic/DiagnosticASTKinds.inc" +#include "clang/Basic/DiagnosticCommentKinds.inc" +#include "clang/Basic/DiagnosticSemaKinds.inc" +#include "clang/Basic/DiagnosticAnalysisKinds.inc" +#include "clang/Basic/DiagnosticRefactoringKinds.inc" +// clang-format on diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp index d0baf0224a18e..e18864160750d 100644 --- a/clang-tools-extra/clangd/Diagnostics.cpp +++ b/clang-tools-extra/clangd/Diagnostics.cpp @@ -39,7 +39,11 @@ #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <array> #include <cassert> +#include <cstddef> +#include <cstdint> +#include <limits> #include <optional> #include <set> #include <string> @@ -51,28 +55,47 @@ namespace clang { namespace clangd { namespace { -const char *getDiagnosticCode(unsigned ID) { - switch (ID) { +struct DiagnosticNameTable { #define DIAG(ENUM, CLASS, DEFAULT_MAPPING, DESC, GROPU, SFINAE, NOWERROR, \ SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, STABLE_ID, \ LEGACY_STABLE_IDS) \ - case clang::diag::ENUM: \ - return #ENUM; -#include "clang/Basic/DiagnosticASTKinds.inc" -#include "clang/Basic/DiagnosticAnalysisKinds.inc" -#include "clang/Basic/DiagnosticCommentKinds.inc" -#include "clang/Basic/DiagnosticCommonKinds.inc" -#include "clang/Basic/DiagnosticDriverKinds.inc" -#include "clang/Basic/DiagnosticFrontendKinds.inc" -#include "clang/Basic/DiagnosticLexKinds.inc" -#include "clang/Basic/DiagnosticParseKinds.inc" -#include "clang/Basic/DiagnosticRefactoringKinds.inc" -#include "clang/Basic/DiagnosticSemaKinds.inc" -#include "clang/Basic/DiagnosticSerializationKinds.inc" + char ENUM[sizeof(#ENUM)]; +#include "DiagnosticNameKinds.inc" #undef DIAG - default: +}; + +constexpr DiagnosticNameTable DiagnosticNames = { +#define DIAG(ENUM, CLASS, DEFAULT_MAPPING, DESC, GROPU, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, STABLE_ID, \ + LEGACY_STABLE_IDS) \ + #ENUM, +#include "DiagnosticNameKinds.inc" +#undef DIAG +}; + +constexpr std::array<uint32_t, clang::diag::DIAG_UPPER_LIMIT> +makeDiagnosticNameOffsets() { + std::array<uint32_t, clang::diag::DIAG_UPPER_LIMIT> Offsets{}; +#define DIAG(ENUM, CLASS, DEFAULT_MAPPING, DESC, GROPU, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY, STABLE_ID, \ + LEGACY_STABLE_IDS) \ + Offsets[clang::diag::ENUM] = offsetof(DiagnosticNameTable, ENUM) + 1; +#include "DiagnosticNameKinds.inc" +#undef DIAG + return Offsets; +} + +constexpr auto DiagnosticNameOffsets = makeDiagnosticNameOffsets(); +static_assert(sizeof(DiagnosticNames) < std::numeric_limits<uint32_t>::max()); + +const char *getDiagnosticCode(unsigned ID) { + if (ID >= DiagnosticNameOffsets.size()) return nullptr; - } + uint32_t Offset = DiagnosticNameOffsets[ID]; + if (Offset == 0) + return nullptr; + const char *Names = reinterpret_cast<const char *>(&DiagnosticNames); + return Names + Offset - 1; } bool mentionsMainFile(const Diag &D) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
