https://github.com/Teemperor created 
https://github.com/llvm/llvm-project/pull/222663

TypeSystemClike needs to store the name of structs, enums, member
variables and similar entities. In the old TypeSystemClang this
information was stored in Clang's IdentifierTable.

This patch introduces an equivalent for TypeSystemClike called
`IdentifierMap`. It turns strings into unique Identifier objects, which
for now directly store the StringRef to the value. The actual storage
of the string contents is either (A) in the IdentifierMap itself
or (B) backed by ConstString/constant memory for strings. Option B
exists mainly because we often already have a ConstString around that
already contains the respective string, and it avoids us having to
save a copy like with TypeSystemClang.

Some design questions where I just picked one option:

(a) Do we really need to deduplicate strings?

There is no functional reason to do it, but it might save some memory
for heavily templated code (where each instantiation is its own time
with the same names for everything). We can benchmark this once the
system is working to see what is the right tradeoff.

(b) Can't we just store some small id in `Identifier` instead of a
StringRef (and the id would be some offset into an IdentifierMap data
structure)?

We could, but then you would need to pass the right IdentifierMap to
resolve the id in `Identifier::getName()`, and that is a bit fragile.
Especially in the context of multiple TypeSystems being used at the
same time, this can easily go wrong. Again, we might want to benchmark
this at the end to see if storing something smaller is worth it in
terms of memory.

>From 7a6e2bfa5920762ab93f58abb6cb0f4783d15151 Mon Sep 17 00:00:00 2001
From: Raphael Isemann <[email protected]>
Date: Thu, 10 Sep 2026 09:34:47 +0100
Subject: [PATCH 1/2] [lldb][TypeSystemClike][NFC] Add the TypeSystemClike
 plugin skeleton

Introduces an empty TypeSystem plugin infrastructure for the new
TypeSystemClike.

For the RFC with more information and background, see
https://discourse.llvm.org/t/rfc-a-faster-more-reliable-type-system-for-c-languages/91459

assisted-by: claude
---
 lldb/source/Plugins/TypeSystem/CMakeLists.txt |   1 +
 .../Plugins/TypeSystem/Clike/CMakeLists.txt   |  10 +
 .../TypeSystem/Clike/TypeSystemClike.cpp      | 479 ++++++++++++++++++
 .../TypeSystem/Clike/TypeSystemClike.h        | 200 ++++++++
 4 files changed, 690 insertions(+)
 create mode 100644 lldb/source/Plugins/TypeSystem/Clike/CMakeLists.txt
 create mode 100644 lldb/source/Plugins/TypeSystem/Clike/TypeSystemClike.cpp
 create mode 100644 lldb/source/Plugins/TypeSystem/Clike/TypeSystemClike.h

diff --git a/lldb/source/Plugins/TypeSystem/CMakeLists.txt 
b/lldb/source/Plugins/TypeSystem/CMakeLists.txt
index 47e32ff176d8c..a87d15f513211 100644
--- a/lldb/source/Plugins/TypeSystem/CMakeLists.txt
+++ b/lldb/source/Plugins/TypeSystem/CMakeLists.txt
@@ -3,3 +3,4 @@ set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND TypeSystem)
 set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES SymbolFile)
 
 add_subdirectory(Clang)
+add_subdirectory(Clike)
diff --git a/lldb/source/Plugins/TypeSystem/Clike/CMakeLists.txt 
b/lldb/source/Plugins/TypeSystem/Clike/CMakeLists.txt
new file mode 100644
index 0000000000000..89e1771177109
--- /dev/null
+++ b/lldb/source/Plugins/TypeSystem/Clike/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_lldb_library(lldbPluginTypeSystemClike PLUGIN
+  TypeSystemClike.cpp
+
+  LINK_COMPONENTS
+    Support
+  LINK_LIBS
+    lldbCore
+    lldbSymbol
+    lldbUtility
+)
diff --git a/lldb/source/Plugins/TypeSystem/Clike/TypeSystemClike.cpp 
b/lldb/source/Plugins/TypeSystem/Clike/TypeSystemClike.cpp
new file mode 100644
index 0000000000000..1a08c1c5db0b5
--- /dev/null
+++ b/lldb/source/Plugins/TypeSystem/Clike/TypeSystemClike.cpp
@@ -0,0 +1,479 @@
+//===-- TypeSystemClike.cpp
+//-------------------------------------------------------------------------===//
+//
+// 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 "TypeSystemClike.h"
+
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/Type.h"
+#include "llvm/ADT/APFloat.h"
+
+#include <optional>
+
+using namespace lldb_private;
+
+LLDB_PLUGIN_DEFINE(TypeSystemClike)
+
+char TypeSystemClike::ID;
+
+TypeSystemClike::TypeSystemClike() = default;
+
+TypeSystemClike::~TypeSystemClike() = default;
+
+lldb::TypeSystemSP TypeSystemClike::CreateInstance(lldb::LanguageType language,
+                                                   Module *module,
+                                                   Target *target) {
+  return lldb::TypeSystemSP();
+}
+
+LanguageSet TypeSystemClike::GetSupportedLanguagesForTypes() {
+  return LanguageSet();
+}
+
+LanguageSet TypeSystemClike::GetSupportedLanguagesForExpressions() {
+  return LanguageSet();
+}
+
+void TypeSystemClike::Initialize() {
+  PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                "C/C++/Objective-C++ TypeSystem plug-in",
+                                CreateInstance, 
GetSupportedLanguagesForTypes(),
+                                GetSupportedLanguagesForExpressions());
+}
+
+void TypeSystemClike::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ConstString TypeSystemClike::DeclGetName(void *opaque_decl) {
+  return ConstString();
+}
+
+CompilerType TypeSystemClike::GetTypeForDecl(void *opaque_decl) {
+  return CompilerType();
+}
+
+ConstString TypeSystemClike::DeclContextGetName(void *opaque_decl_ctx) {
+  return ConstString();
+}
+
+ConstString
+TypeSystemClike::DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) {
+  return ConstString();
+}
+
+bool TypeSystemClike::DeclContextIsClassMethod(void *opaque_decl_ctx) {
+  return false;
+}
+
+bool TypeSystemClike::DeclContextIsContainedInLookup(
+    void *opaque_decl_ctx, void *other_opaque_decl_ctx) {
+  return false;
+}
+
+lldb::LanguageType
+TypeSystemClike::DeclContextGetLanguage(void *opaque_decl_ctx) {
+  return lldb::eLanguageTypeUnknown;
+}
+
+bool TypeSystemClike::Verify(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsArrayType(lldb::opaque_compiler_type_t type,
+                                  CompilerType *element_type, uint64_t *size,
+                                  bool *is_incomplete) {
+  return false;
+}
+
+bool TypeSystemClike::IsAggregateType(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsCharType(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsCompleteType(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsDefined(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsFloatingPointType(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsFunctionType(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+size_t TypeSystemClike::GetNumberOfFunctionArguments(
+    lldb::opaque_compiler_type_t type) {
+  return 0;
+}
+
+CompilerType
+TypeSystemClike::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
+                                            const size_t index) {
+  return CompilerType();
+}
+
+bool TypeSystemClike::IsFunctionPointerType(lldb::opaque_compiler_type_t type) 
{
+  return false;
+}
+
+bool TypeSystemClike::IsMemberFunctionPointerType(
+    lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsMemberDataPointerType(
+    lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsBlockPointerType(
+    lldb::opaque_compiler_type_t type,
+    CompilerType *function_pointer_type_ptr) {
+  return false;
+}
+
+bool TypeSystemClike::IsIntegerType(lldb::opaque_compiler_type_t type,
+                                    bool &is_signed) {
+  return false;
+}
+
+bool TypeSystemClike::IsScopedEnumerationType(
+    lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
+                                            CompilerType *target_type,
+                                            bool check_cplusplus,
+                                            bool check_objc) {
+  return false;
+}
+
+bool TypeSystemClike::IsPointerType(lldb::opaque_compiler_type_t type,
+                                    CompilerType *pointee_type) {
+  return false;
+}
+
+bool TypeSystemClike::IsScalarType(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsVoidType(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::CanPassInRegisters(const CompilerType &type) {
+  return false;
+}
+
+bool TypeSystemClike::SupportsLanguage(lldb::LanguageType language) {
+  return false;
+}
+
+bool TypeSystemClike::GetCompleteType(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+uint32_t TypeSystemClike::GetPointerByteSize() { return 0; }
+
+CompilerType TypeSystemClike::GetPointerDiffType(bool is_signed) {
+  return CompilerType();
+}
+
+CompilerType TypeSystemClike::GetSizeType() { return CompilerType(); }
+
+unsigned TypeSystemClike::GetPtrAuthKey(lldb::opaque_compiler_type_t type) {
+  return 0;
+}
+
+unsigned
+TypeSystemClike::GetPtrAuthDiscriminator(lldb::opaque_compiler_type_t type) {
+  return 0;
+}
+
+bool TypeSystemClike::GetPtrAuthAddressDiversity(
+    lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+ConstString TypeSystemClike::GetTypeName(lldb::opaque_compiler_type_t type,
+                                         bool BaseOnly) {
+  return ConstString();
+}
+
+ConstString
+TypeSystemClike::GetDisplayTypeName(lldb::opaque_compiler_type_t type) {
+  return ConstString();
+}
+
+uint32_t
+TypeSystemClike::GetTypeInfo(lldb::opaque_compiler_type_t type,
+                             CompilerType *pointee_or_element_compiler_type) {
+  return 0;
+}
+
+lldb::LanguageType
+TypeSystemClike::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
+  return lldb::eLanguageTypeUnknown;
+}
+
+lldb::TypeClass
+TypeSystemClike::GetTypeClass(lldb::opaque_compiler_type_t type) {
+  return lldb::eTypeClassInvalid;
+}
+
+CompilerType
+TypeSystemClike::GetArrayElementType(lldb::opaque_compiler_type_t type,
+                                     ExecutionContextScope *exe_scope) {
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClike::GetCanonicalType(lldb::opaque_compiler_type_t type) {
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClike::GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) {
+  return CompilerType();
+}
+
+int TypeSystemClike::GetFunctionArgumentCount(
+    lldb::opaque_compiler_type_t type) {
+  return 0;
+}
+
+CompilerType TypeSystemClike::GetFunctionArgumentTypeAtIndex(
+    lldb::opaque_compiler_type_t type, size_t idx) {
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClike::GetFunctionReturnType(lldb::opaque_compiler_type_t type) {
+  return CompilerType();
+}
+
+size_t
+TypeSystemClike::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
+  return 0;
+}
+
+TypeMemberFunctionImpl
+TypeSystemClike::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
+                                          size_t idx) {
+  return TypeMemberFunctionImpl();
+}
+
+CompilerType
+TypeSystemClike::GetPointeeType(lldb::opaque_compiler_type_t type) {
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClike::GetPointerType(lldb::opaque_compiler_type_t type) {
+  return CompilerType();
+}
+
+const llvm::fltSemantics &
+TypeSystemClike::GetFloatTypeSemantics(size_t byte_size, lldb::Format format) {
+  return llvm::APFloat::Bogus();
+}
+
+llvm::Expected<uint64_t>
+TypeSystemClike::GetBitSize(lldb::opaque_compiler_type_t type,
+                            ExecutionContextScope *exe_scope) {
+  return 0;
+}
+
+lldb::Encoding TypeSystemClike::GetEncoding(lldb::opaque_compiler_type_t type) 
{
+  return lldb::eEncodingInvalid;
+}
+
+lldb::Format TypeSystemClike::GetFormat(lldb::opaque_compiler_type_t type) {
+  return lldb::eFormatDefault;
+}
+
+llvm::Expected<uint32_t>
+TypeSystemClike::GetNumChildren(lldb::opaque_compiler_type_t type,
+                                bool omit_empty_base_classes,
+                                const ExecutionContext *exe_ctx) {
+  return 0;
+}
+
+lldb::BasicType
+TypeSystemClike::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
+  return lldb::eBasicTypeInvalid;
+}
+
+uint32_t TypeSystemClike::GetNumFields(lldb::opaque_compiler_type_t type) {
+  return 0;
+}
+
+CompilerType TypeSystemClike::GetFieldAtIndex(lldb::opaque_compiler_type_t 
type,
+                                              size_t idx, std::string &name,
+                                              uint64_t *bit_offset_ptr,
+                                              uint32_t *bitfield_bit_size_ptr,
+                                              bool *is_bitfield_ptr) {
+  return CompilerType();
+}
+
+uint32_t
+TypeSystemClike::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) {
+  return 0;
+}
+
+uint32_t
+TypeSystemClike::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) {
+  return 0;
+}
+
+CompilerType TypeSystemClike::GetDirectBaseClassAtIndex(
+    lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
+  return CompilerType();
+}
+
+CompilerType TypeSystemClike::GetVirtualBaseClassAtIndex(
+    lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
+  return CompilerType();
+}
+
+llvm::Expected<CompilerType> TypeSystemClike::GetDereferencedType(
+    lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
+    std::string &deref_name, uint32_t &deref_byte_size,
+    int32_t &deref_byte_offset, ValueObject *valobj, uint64_t &language_flags) 
{
+  return CompilerType();
+}
+
+llvm::Expected<CompilerType> TypeSystemClike::GetChildCompilerTypeAtIndex(
+    lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
+    bool transparent_pointers, bool omit_empty_base_classes,
+    bool ignore_array_bounds, std::string &child_name,
+    uint32_t &child_byte_size, int32_t &child_byte_offset,
+    uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
+    bool &child_is_base_class, bool &child_is_deref_of_parent,
+    ValueObject *valobj, uint64_t &language_flags) {
+  return CompilerType();
+}
+
+llvm::Expected<uint32_t>
+TypeSystemClike::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
+                                         llvm::StringRef name,
+                                         bool omit_empty_base_classes) {
+  return 0;
+}
+
+size_t TypeSystemClike::GetIndexOfChildMemberWithName(
+    lldb::opaque_compiler_type_t type, llvm::StringRef name,
+    bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
+  return 0;
+}
+
+bool TypeSystemClike::DumpTypeValue(
+    lldb::opaque_compiler_type_t type, Stream &s, lldb::Format format,
+    const DataExtractor &data, lldb::offset_t data_offset,
+    size_t data_byte_size, uint32_t bitfield_bit_size,
+    uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) {
+  return false;
+}
+
+void TypeSystemClike::DumpTypeDescription(lldb::opaque_compiler_type_t type,
+                                          lldb::DescriptionLevel level) {}
+
+void TypeSystemClike::DumpTypeDescription(lldb::opaque_compiler_type_t type,
+                                          Stream &s,
+                                          lldb::DescriptionLevel level) {}
+
+void TypeSystemClike::Dump(llvm::raw_ostream &output, llvm::StringRef filter,
+                           bool show_color) {}
+
+bool TypeSystemClike::IsRuntimeGeneratedType(
+    lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsPointerOrReferenceType(
+    lldb::opaque_compiler_type_t type, CompilerType *pointee_type) {
+  return false;
+}
+
+unsigned TypeSystemClike::GetTypeQualifiers(lldb::opaque_compiler_type_t type) 
{
+  return 0;
+}
+
+std::optional<size_t>
+TypeSystemClike::GetTypeBitAlign(lldb::opaque_compiler_type_t type,
+                                 ExecutionContextScope *exe_scope) {
+  return std::nullopt;
+}
+
+CompilerType TypeSystemClike::GetBasicTypeFromAST(lldb::BasicType basic_type) {
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClike::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
+                                                     size_t bit_size) {
+  return CompilerType();
+}
+
+bool TypeSystemClike::IsBeingDefined(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsConst(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+uint32_t
+TypeSystemClike::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
+                                        CompilerType *base_type_ptr) {
+  return 0;
+}
+
+bool TypeSystemClike::IsPolymorphicClass(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+bool TypeSystemClike::IsTypedefType(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+CompilerType
+TypeSystemClike::GetTypedefedType(lldb::opaque_compiler_type_t type) {
+  return CompilerType();
+}
+
+bool TypeSystemClike::IsVectorType(lldb::opaque_compiler_type_t type,
+                                   CompilerType *element_type, uint64_t *size) 
{
+  return false;
+}
+
+CompilerType
+TypeSystemClike::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
+  return CompilerType();
+}
+
+CompilerType
+TypeSystemClike::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
+  return CompilerType();
+}
+
+bool TypeSystemClike::IsReferenceType(lldb::opaque_compiler_type_t type,
+                                      CompilerType *pointee_type,
+                                      bool *is_rvalue) {
+  return false;
+}
diff --git a/lldb/source/Plugins/TypeSystem/Clike/TypeSystemClike.h 
b/lldb/source/Plugins/TypeSystem/Clike/TypeSystemClike.h
new file mode 100644
index 0000000000000..06c7ee37a7ee5
--- /dev/null
+++ b/lldb/source/Plugins/TypeSystem/Clike/TypeSystemClike.h
@@ -0,0 +1,200 @@
+//===-- TypeSystemClike.h ---------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLIKE_TYPESYSTEMCLIKE_H
+#define LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLIKE_TYPESYSTEMCLIKE_H
+
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/TypeSystem.h"
+
+namespace lldb_private {
+
+/// A TypeSystem for Clike languages such as C, C++ and Objective-C.
+class TypeSystemClike : public TypeSystem {
+  // LLVM RTTI support
+  static char ID;
+
+public:
+  TypeSystemClike();
+  ~TypeSystemClike() override;
+
+  // PluginInterface
+  static void Initialize();
+  static void Terminate();
+  static llvm::StringRef GetPluginNameStatic() { return "cpp"; }
+  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+
+  static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
+                                           Module *module, Target *target);
+  static LanguageSet GetSupportedLanguagesForTypes();
+  static LanguageSet GetSupportedLanguagesForExpressions();
+
+  // LLVM RTTI support
+  bool isA(const void *ClassID) const override { return ClassID == &ID; }
+  static bool classof(const TypeSystem *ts) { return ts->isA(&ID); }
+
+  ConstString DeclGetName(void *opaque_decl) override;
+  CompilerType GetTypeForDecl(void *opaque_decl) override;
+  ConstString DeclContextGetName(void *opaque_decl_ctx) override;
+  ConstString DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) override;
+  bool DeclContextIsClassMethod(void *opaque_decl_ctx) override;
+  bool DeclContextIsContainedInLookup(void *opaque_decl_ctx,
+                                      void *other_opaque_decl_ctx) override;
+  lldb::LanguageType DeclContextGetLanguage(void *opaque_decl_ctx) override;
+  bool Verify(lldb::opaque_compiler_type_t type) override;
+  bool IsArrayType(lldb::opaque_compiler_type_t type,
+                   CompilerType *element_type, uint64_t *size,
+                   bool *is_incomplete) override;
+  bool IsAggregateType(lldb::opaque_compiler_type_t type) override;
+  bool IsCharType(lldb::opaque_compiler_type_t type) override;
+  bool IsCompleteType(lldb::opaque_compiler_type_t type) override;
+  bool IsDefined(lldb::opaque_compiler_type_t type) override;
+  bool IsFloatingPointType(lldb::opaque_compiler_type_t type) override;
+  bool IsFunctionType(lldb::opaque_compiler_type_t type) override;
+  size_t
+  GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) override;
+  CompilerType GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
+                                          const size_t index) override;
+  bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) override;
+  bool IsMemberFunctionPointerType(lldb::opaque_compiler_type_t type) override;
+  bool IsMemberDataPointerType(lldb::opaque_compiler_type_t type) override;
+  bool IsBlockPointerType(lldb::opaque_compiler_type_t type,
+                          CompilerType *function_pointer_type_ptr) override;
+  bool IsIntegerType(lldb::opaque_compiler_type_t type,
+                     bool &is_signed) override;
+  bool IsScopedEnumerationType(lldb::opaque_compiler_type_t type) override;
+  bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
+                             CompilerType *target_type, bool check_cplusplus,
+                             bool check_objc) override;
+  bool IsPointerType(lldb::opaque_compiler_type_t type,
+                     CompilerType *pointee_type) override;
+  bool IsScalarType(lldb::opaque_compiler_type_t type) override;
+  bool IsVoidType(lldb::opaque_compiler_type_t type) override;
+  bool CanPassInRegisters(const CompilerType &type) override;
+  bool SupportsLanguage(lldb::LanguageType language) override;
+  bool GetCompleteType(lldb::opaque_compiler_type_t type) override;
+  uint32_t GetPointerByteSize() override;
+  CompilerType GetPointerDiffType(bool is_signed) override;
+  CompilerType GetSizeType() override;
+  unsigned GetPtrAuthKey(lldb::opaque_compiler_type_t type) override;
+  unsigned GetPtrAuthDiscriminator(lldb::opaque_compiler_type_t type) override;
+  bool GetPtrAuthAddressDiversity(lldb::opaque_compiler_type_t type) override;
+  ConstString GetTypeName(lldb::opaque_compiler_type_t type,
+                          bool BaseOnly) override;
+  ConstString GetDisplayTypeName(lldb::opaque_compiler_type_t type) override;
+  uint32_t GetTypeInfo(lldb::opaque_compiler_type_t type,
+                       CompilerType *pointee_or_element_compiler_type) 
override;
+  lldb::LanguageType
+  GetMinimumLanguage(lldb::opaque_compiler_type_t type) override;
+  lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) override;
+  CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type,
+                                   ExecutionContextScope *exe_scope) override;
+  CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) override;
+  CompilerType
+  GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) override;
+  int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override;
+  CompilerType GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t 
type,
+                                              size_t idx) override;
+  CompilerType
+  GetFunctionReturnType(lldb::opaque_compiler_type_t type) override;
+  size_t GetNumMemberFunctions(lldb::opaque_compiler_type_t type) override;
+  TypeMemberFunctionImpl
+  GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
+                           size_t idx) override;
+  CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) override;
+  CompilerType GetPointerType(lldb::opaque_compiler_type_t type) override;
+  const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size,
+                                                  lldb::Format format) 
override;
+  llvm::Expected<uint64_t>
+  GetBitSize(lldb::opaque_compiler_type_t type,
+             ExecutionContextScope *exe_scope) override;
+  lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type) override;
+  lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override;
+  llvm::Expected<uint32_t>
+  GetNumChildren(lldb::opaque_compiler_type_t type,
+                 bool omit_empty_base_classes,
+                 const ExecutionContext *exe_ctx) override;
+  lldb::BasicType
+  GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override;
+  uint32_t GetNumFields(lldb::opaque_compiler_type_t type) override;
+  CompilerType GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx,
+                               std::string &name, uint64_t *bit_offset_ptr,
+                               uint32_t *bitfield_bit_size_ptr,
+                               bool *is_bitfield_ptr) override;
+  uint32_t GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) override;
+  uint32_t GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) 
override;
+  CompilerType GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type,
+                                         size_t idx,
+                                         uint32_t *bit_offset_ptr) override;
+  CompilerType GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type,
+                                          size_t idx,
+                                          uint32_t *bit_offset_ptr) override;
+  llvm::Expected<CompilerType>
+  GetDereferencedType(lldb::opaque_compiler_type_t type,
+                      ExecutionContext *exe_ctx, std::string &deref_name,
+                      uint32_t &deref_byte_size, int32_t &deref_byte_offset,
+                      ValueObject *valobj, uint64_t &language_flags) override;
+  llvm::Expected<CompilerType> GetChildCompilerTypeAtIndex(
+      lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
+      bool transparent_pointers, bool omit_empty_base_classes,
+      bool ignore_array_bounds, std::string &child_name,
+      uint32_t &child_byte_size, int32_t &child_byte_offset,
+      uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
+      bool &child_is_base_class, bool &child_is_deref_of_parent,
+      ValueObject *valobj, uint64_t &language_flags) override;
+  llvm::Expected<uint32_t>
+  GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
+                          llvm::StringRef name,
+                          bool omit_empty_base_classes) override;
+  size_t
+  GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type,
+                                llvm::StringRef name,
+                                bool omit_empty_base_classes,
+                                std::vector<uint32_t> &child_indexes) override;
+  bool DumpTypeValue(lldb::opaque_compiler_type_t type, Stream &s,
+                     lldb::Format format, const DataExtractor &data,
+                     lldb::offset_t data_offset, size_t data_byte_size,
+                     uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
+                     ExecutionContextScope *exe_scope) override;
+  void DumpTypeDescription(
+      lldb::opaque_compiler_type_t type,
+      lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) override;
+  void DumpTypeDescription(
+      lldb::opaque_compiler_type_t type, Stream &s,
+      lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) override;
+  void Dump(llvm::raw_ostream &output, llvm::StringRef filter,
+            bool show_color) override;
+  bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) override;
+  bool IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
+                                CompilerType *pointee_type) override;
+  unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) override;
+  std::optional<size_t>
+  GetTypeBitAlign(lldb::opaque_compiler_type_t type,
+                  ExecutionContextScope *exe_scope) override;
+  CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override;
+  CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
+                                                   size_t bit_size) override;
+  bool IsBeingDefined(lldb::opaque_compiler_type_t type) override;
+  bool IsConst(lldb::opaque_compiler_type_t type) override;
+  uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
+                                  CompilerType *base_type_ptr) override;
+  bool IsPolymorphicClass(lldb::opaque_compiler_type_t type) override;
+  bool IsTypedefType(lldb::opaque_compiler_type_t type) override;
+  CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) override;
+  bool IsVectorType(lldb::opaque_compiler_type_t type,
+                    CompilerType *element_type, uint64_t *size) override;
+  CompilerType
+  GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) override;
+  CompilerType GetNonReferenceType(lldb::opaque_compiler_type_t type) override;
+  bool IsReferenceType(lldb::opaque_compiler_type_t type,
+                       CompilerType *pointee_type, bool *is_rvalue) override;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLIKE_TYPESYSTEMCLIKE_H

>From ed632efaa5018a2095e91d01a454d9d5240545cf Mon Sep 17 00:00:00 2001
From: Raphael Isemann <[email protected]>
Date: Tue, 8 Sep 2026 11:59:37 +0100
Subject: [PATCH 2/2] [lldb][Clike] Add IdentifierMap

TypeSystemClike needs to store the name of structs, enums, member
variables and similar entities. In the old TypeSystemClang this
information was stored in Clang's IdentifierTable.

This patch introduces an equivalent for TypeSystemClike called
`IdentifierMap`. It turns strings into unique Identifier objects, which
for now directly store the StringRef to the value. The actual storage
of the string contents is either (A) in the IdentifierMap itself
or (B) backed by ConstString/constant memory for strings. Option B
exists mainly because we often already have a ConstString around that
already contains the respective string, and it avoids us having to
save a copy like with TypeSystemClang.

Some design questions where I just picked one option:

(a) Do we really need to deduplicate strings?

There is no functional reason to do it, but it might save some memory
for heavily templated code (where each instantiation is its own time
with the same names for everything). We can benchmark this once the
system is working to see what is the right tradeoff.

(b) Can't we just store some small id in `Identifier` instead of a
StringRef (and the id would be some offset into an IdentifierMap data
structure)?

We could, but then you would need to pass the right IdentifierMap to
resolve the id in `Identifier::getName()`, and that is a bit fragile.
Especially in the context of multiple TypeSystems being used at the
same time, this can easily go wrong. Again, we might want to benchmark
this at the end to see if storing something smaller is worth it in
terms of memory.
---
 .../Plugins/TypeSystem/Clike/CMakeLists.txt   |  1 +
 .../Plugins/TypeSystem/Clike/Identifier.cpp   | 48 ++++++++++++++
 .../Plugins/TypeSystem/Clike/Identifier.h     | 65 +++++++++++++++++++
 lldb/unittests/CMakeLists.txt                 |  1 +
 lldb/unittests/TypeSystem/CMakeLists.txt      |  1 +
 .../unittests/TypeSystem/Clike/CMakeLists.txt |  6 ++
 .../TypeSystem/Clike/IdentifierTest.cpp       | 64 ++++++++++++++++++
 7 files changed, 186 insertions(+)
 create mode 100644 lldb/source/Plugins/TypeSystem/Clike/Identifier.cpp
 create mode 100644 lldb/source/Plugins/TypeSystem/Clike/Identifier.h
 create mode 100644 lldb/unittests/TypeSystem/CMakeLists.txt
 create mode 100644 lldb/unittests/TypeSystem/Clike/CMakeLists.txt
 create mode 100644 lldb/unittests/TypeSystem/Clike/IdentifierTest.cpp

diff --git a/lldb/source/Plugins/TypeSystem/Clike/CMakeLists.txt 
b/lldb/source/Plugins/TypeSystem/Clike/CMakeLists.txt
index 89e1771177109..3f8e742165cfd 100644
--- a/lldb/source/Plugins/TypeSystem/Clike/CMakeLists.txt
+++ b/lldb/source/Plugins/TypeSystem/Clike/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_lldb_library(lldbPluginTypeSystemClike PLUGIN
+  Identifier.cpp
   TypeSystemClike.cpp
 
   LINK_COMPONENTS
diff --git a/lldb/source/Plugins/TypeSystem/Clike/Identifier.cpp 
b/lldb/source/Plugins/TypeSystem/Clike/Identifier.cpp
new file mode 100644
index 0000000000000..a810af88b34f1
--- /dev/null
+++ b/lldb/source/Plugins/TypeSystem/Clike/Identifier.cpp
@@ -0,0 +1,48 @@
+//===-- Identifier.cpp 
----------------------------------------------------===//
+//
+// 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 "Identifier.h"
+
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+
+#include <cstring>
+
+using namespace lldb_private;
+using namespace lldb_private::clike_typesystem;
+
+Identifier IdentifierMap::get(llvm::StringRef name) {
+  auto it = m_names.find(name);
+  if (it != m_names.end())
+    return Identifier(*it);
+
+  // Copy the string into our own storage.
+  char *storage = m_string_storage.Allocate<char>(name.size());
+  std::memcpy(storage, name.data(), name.size());
+  llvm::StringRef owned(storage, name.size());
+  m_names.insert(owned);
+  return Identifier(owned);
+}
+
+Identifier IdentifierMap::getWithStaticStorageStr(llvm::StringRef name) {
+  // The caller promises the backing storage outlives this map.
+  m_names.insert(name);
+  return Identifier(name);
+}
+
+IdentifierMap::~IdentifierMap() {
+#if LLVM_ADDRESS_SANITIZER_BUILD
+  // Verify every identifier still points at live memory.
+  for (llvm::StringRef name : m_names) {
+    if (!name.empty() &&
+        __asan_region_is_poisoned(const_cast<char *>(name.data()), 
name.size()))
+      llvm::report_fatal_error("IdentifierMap holds a freed string "
+                               "(misuse of getWithStaticStorageStr?)");
+  }
+#endif
+}
diff --git a/lldb/source/Plugins/TypeSystem/Clike/Identifier.h 
b/lldb/source/Plugins/TypeSystem/Clike/Identifier.h
new file mode 100644
index 0000000000000..d16dd09d2b7ba
--- /dev/null
+++ b/lldb/source/Plugins/TypeSystem/Clike/Identifier.h
@@ -0,0 +1,65 @@
+//===-- Identifier.h --------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLIKE_IDENTIFIER_H
+#define LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLIKE_IDENTIFIER_H
+
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Allocator.h"
+
+#include <vector>
+
+namespace lldb_private {
+namespace clike_typesystem {
+
+class IdentifierMap;
+
+/// Represents a name in TypeSystemClike.
+class Identifier {
+public:
+  Identifier() = default;
+
+  llvm::StringRef GetName() const { return m_name; }
+
+private:
+  // Only IdentifierMap may build a non-empty Identifier.
+  friend class IdentifierMap;
+  explicit Identifier(llvm::StringRef name) : m_name(name) {}
+
+  llvm::StringRef m_name;
+};
+
+/// Turns strings into unique Identifier objects.
+class IdentifierMap {
+public:
+  ~IdentifierMap();
+
+  /// Returns an Identifier for \p name.
+  ///
+  /// This copies the string into storage owned by this map.
+  Identifier get(llvm::StringRef name);
+
+  /// Returns an Identifier for \p name.
+  ///
+  /// This does not make a copy of the passed string and the string storage
+  /// needs to outlive this IdentifierMap. This is used if `name` is a string
+  /// literal or backed by ConstString.
+  Identifier getWithStaticStorageStr(llvm::StringRef name);
+
+private:
+  /// Owns the copies made by get().
+  llvm::BumpPtrAllocator m_string_storage;
+  /// Set of all created Identifiers strings.
+  llvm::DenseSet<llvm::StringRef> m_names;
+};
+
+} // namespace clike_typesystem
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TYPESYSTEM_CLIKE_IDENTIFIER_H
diff --git a/lldb/unittests/CMakeLists.txt b/lldb/unittests/CMakeLists.txt
index b0b7f68a7dcd6..6ded2974adfd3 100644
--- a/lldb/unittests/CMakeLists.txt
+++ b/lldb/unittests/CMakeLists.txt
@@ -101,6 +101,7 @@ add_subdirectory(Symbol)
 add_subdirectory(SymbolFile)
 add_subdirectory(Target)
 add_subdirectory(Thread)
+add_subdirectory(TypeSystem)
 add_subdirectory(UnwindAssembly)
 add_subdirectory(Utility)
 add_subdirectory(ValueObject)
diff --git a/lldb/unittests/TypeSystem/CMakeLists.txt 
b/lldb/unittests/TypeSystem/CMakeLists.txt
new file mode 100644
index 0000000000000..61f1669b38ed0
--- /dev/null
+++ b/lldb/unittests/TypeSystem/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(Clike)
diff --git a/lldb/unittests/TypeSystem/Clike/CMakeLists.txt 
b/lldb/unittests/TypeSystem/Clike/CMakeLists.txt
new file mode 100644
index 0000000000000..c74cc7d651de1
--- /dev/null
+++ b/lldb/unittests/TypeSystem/Clike/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_lldb_unittest(TypeSystemClikeUnitTests
+  IdentifierTest.cpp
+
+  LINK_LIBS
+    lldbPluginTypeSystemClike
+  )
diff --git a/lldb/unittests/TypeSystem/Clike/IdentifierTest.cpp 
b/lldb/unittests/TypeSystem/Clike/IdentifierTest.cpp
new file mode 100644
index 0000000000000..6320fd44d4b27
--- /dev/null
+++ b/lldb/unittests/TypeSystem/Clike/IdentifierTest.cpp
@@ -0,0 +1,64 @@
+//===-- IdentifierTest.cpp 
------------------------------------------------===//
+//
+// 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 "Plugins/TypeSystem/Clike/Identifier.h"
+
+#include "gtest/gtest.h"
+
+using namespace lldb_private::clike_typesystem;
+
+TEST(IdentifierTest, DefaultConstructed) {
+  Identifier id;
+  EXPECT_TRUE(id.GetName().empty());
+}
+
+TEST(IdentifierTest, GetInternsEqualStrings) {
+  IdentifierMap map;
+  Identifier a = map.get("foo");
+  Identifier b = map.get("foo");
+  EXPECT_EQ(a.GetName(), "foo");
+  EXPECT_EQ(a.GetName().data(), b.GetName().data());
+}
+
+TEST(IdentifierTest, GetDistinctStringsAreDistinct) {
+  IdentifierMap map;
+  Identifier a = map.get("foo");
+  Identifier b = map.get("bar");
+  EXPECT_NE(a.GetName(), b.GetName());
+}
+
+TEST(IdentifierTest, GetCopiesInput) {
+  IdentifierMap map;
+  Identifier id;
+  {
+    std::string temp = "temporary";
+    id = map.get(temp);
+    temp.clear();
+  }
+  // clear() should not have changed id.
+  EXPECT_EQ(id.GetName(), "temporary");
+}
+
+// getWithStaticStorageStr() does not copy: it hands back an Identifier
+// wrapping the exact same backing storage as the (static-lifetime) input.
+TEST(IdentifierTest, GetWithStaticStorageStrDoesNotCopy) {
+  IdentifierMap map;
+  static const char *kStatic = "int";
+  Identifier id = map.getWithStaticStorageStr(kStatic);
+  EXPECT_EQ(id.GetName().data(), kStatic);
+}
+
+// Interning via get() and via getWithStaticStorageStr() with the same content
+// still uniques to the same underlying storage.
+TEST(IdentifierTest, GetAndStaticShareStorage) {
+  IdentifierMap map;
+  static const char *kStatic = "shared";
+  Identifier a = map.getWithStaticStorageStr(kStatic);
+  Identifier b = map.get("shared");
+  EXPECT_EQ(a.GetName().data(), b.GetName().data());
+}

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

Reply via email to