[Lldb-commits] [lldb] [lldb][DWARF] Add support for case-insensitive identifier lookups using DW_AT_identifier_case (PR #213323)

Iasonas Karaprodromidis via lldb-commits lldb-commits at lists.llvm.org
Sat Aug 1 03:35:29 PDT 2026


https://github.com/Iasonaskrpr updated https://github.com/llvm/llvm-project/pull/213323

>From 2188c8cc2476eb130a9f59cd5597484ecc8d3d11 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Sat, 9 May 2026 18:50:07 +0300
Subject: [PATCH 01/44] [lldb] Added boilerplate for new TypeSystem and
 DWARFASTParser

---
 .../Plugins/SymbolFile/DWARF/CMakeLists.txt   |   3 +
 .../Plugins/SymbolFile/DWARF/DWARFASTParser.h |   2 +-
 .../DWARF/DWARFASTParserFortran.cpp           |  39 ++
 .../SymbolFile/DWARF/DWARFASTParserFortran.h  |  75 +++
 lldb/source/Plugins/TypeSystem/CMakeLists.txt |   1 +
 .../Plugins/TypeSystem/Fortran/CMakeLists.txt |  12 +
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  |   0
 .../TypeSystem/Fortran/TypeSystemFortran.h    | 480 ++++++++++++++++++
 8 files changed, 611 insertions(+), 1 deletion(-)
 create mode 100644 lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
 create mode 100644 lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
 create mode 100644 lldb/source/Plugins/TypeSystem/Fortran/CMakeLists.txt
 create mode 100644 lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
 create mode 100644 lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
index 3f7cf023ac21c..b198ec4e99b24 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
+++ b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
@@ -16,6 +16,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
   DIERef.cpp
   DWARFASTParser.cpp
   DWARFASTParserClang.cpp
+  DWARFASTParserFortran.cpp
   DWARFAttribute.cpp
   DWARFBaseDIE.cpp
   DWARFCompileUnit.cpp
@@ -57,7 +58,9 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
     lldbPluginObjCLanguage
     lldbPluginCPlusPlusLanguage
     lldbPluginExpressionParserClang
+    lldbPluginFortranLanguage
     lldbPluginTypeSystemClang
+    lldbPluginTypeSystemFortran
   CLANG_LIBS
     clangAST
     clangBasic
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
index 80f7becc1b24b..8f32874d788af 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -29,7 +29,7 @@ class SymbolFileDWARF;
 
 class DWARFASTParser {
 public:
-  enum class Kind { DWARFASTParserClang };
+  enum class Kind { DWARFASTParserClang, DWARFASTParserFortran };
   DWARFASTParser(Kind kind) : m_kind(kind) {}
 
   virtual ~DWARFASTParser() = default;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
new file mode 100644
index 0000000000000..0973f658f6b04
--- /dev/null
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
@@ -0,0 +1,39 @@
+//===-- DWARFASTParserFortran.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 "DWARFASTParserFortran.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+DWARFASTParserFortran::DWARFASTParserFortran(
+    lldb_private::TypeSystemFortran m_ast)
+    : lldb_private::plugin::dwarf::DWARFASTParser(Kind::DWARFASTParserFortran),
+      m_ast(m_ast) {}
+
+DWARFASTParserFortran::~DWARFASTParserFortran() {}
+
+lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(
+    const lldb_private::SymbolContext &sc,
+    const lldb_private::plugin::dwarf::DWARFDIE &die, bool *type_is_new_ptr) {
+  // TODO
+}
+
+lldb_private::Function *DWARFASTParserFortran::ParseFunctionFromDWARF(
+    lldb_private::CompileUnit &comp_unit,
+    const lldb_private::plugin::dwarf::DWARFDIE &die,
+    lldb_private::AddressRanges ranges) {
+  // TODO
+}
+
+bool DWARFASTParserFortran::CompleteTypeFromDWARF(
+    const lldb_private::plugin::dwarf::DWARFDIE &die, lldb_private::Type *type,
+    const lldb_private::CompilerType &compiler_type) {
+  // TODO
+  return false;
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
new file mode 100644
index 0000000000000..6b26c798d190b
--- /dev/null
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
@@ -0,0 +1,75 @@
+//===-- DWARFASTParserFortran.h -------------------------------------------===//
+//
+// 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_SYMBOLFILE_DWARF_DWARFASTPARSERFORTRAN_H
+#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSERFORTRAN_H
+
+#include "DWARFASTParser.h"
+#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
+#include "Plugins/TypeSystem/Fortran/TypeSystemFortran.h"
+
+namespace lldb_private {
+class CompileUnit;
+class ExecutionContext;
+} // namespace lldb_private
+
+class DWARFASTParserFortran
+    : public lldb_private::plugin::dwarf::DWARFASTParser {
+public:
+  DWARFASTParserFortran(lldb_private::TypeSystemFortran m_ast);
+
+  ~DWARFASTParserFortran() override;
+
+  lldb::TypeSP
+  ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
+                     const lldb_private::plugin::dwarf::DWARFDIE &die,
+                     bool *type_is_new_ptr) override;
+
+  lldb_private::Function *
+  ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit,
+                         const lldb_private::plugin::dwarf::DWARFDIE &die,
+                         lldb_private::AddressRanges ranges) override;
+
+  bool CompleteTypeFromDWARF(
+      const lldb_private::plugin::dwarf::DWARFDIE &die,
+      lldb_private::Type *type,
+      const lldb_private::CompilerType &compiler_type) override;
+
+  lldb_private::ConstString ConstructDemangledNameFromDWARF(
+      const lldb_private::plugin::dwarf::DWARFDIE &die) override {
+    return lldb_private::ConstString();
+  }
+
+  lldb_private::CompilerDecl GetDeclForUIDFromDWARF(
+      const lldb_private::plugin::dwarf::DWARFDIE &die) override {
+    return lldb_private::CompilerDecl();
+  }
+
+  lldb_private::CompilerDeclContext GetDeclContextForUIDFromDWARF(
+      const lldb_private::plugin::dwarf::DWARFDIE &die) override {
+    return lldb_private::CompilerDeclContext();
+  }
+
+  lldb_private::CompilerDeclContext GetDeclContextContainingUIDFromDWARF(
+      const lldb_private::plugin::dwarf::DWARFDIE &die) override {
+    return lldb_private::CompilerDeclContext();
+  }
+
+  void EnsureAllDIEsInDeclContextHaveBeenParsed(
+      lldb_private::CompilerDeclContext decl_context) override {}
+
+  std::string GetDIEClassTemplateParams(
+      lldb_private::plugin::dwarf::DWARFDIE die) override {
+    return {};
+  }
+
+private:
+  lldb_private::TypeSystemFortran &m_ast;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_DWARFASTPARSERFORTRAN_H
diff --git a/lldb/source/Plugins/TypeSystem/CMakeLists.txt b/lldb/source/Plugins/TypeSystem/CMakeLists.txt
index 47e32ff176d8c..24431c14fca61 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(Fortran)
\ No newline at end of file
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/CMakeLists.txt b/lldb/source/Plugins/TypeSystem/Fortran/CMakeLists.txt
new file mode 100644
index 0000000000000..c78b70d48eb31
--- /dev/null
+++ b/lldb/source/Plugins/TypeSystem/Fortran/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_lldb_library(lldbPluginTypeSystemFortran PLUGIN
+  TypeSystemFortran.cpp
+
+  LINK_COMPONENTS
+    Support
+  LINK_LIBS
+    lldbCore
+    lldbSymbol
+    lldbTarget
+    lldbUtility
+    lldbPluginSymbolFileDWARF
+)
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
new file mode 100644
index 0000000000000..be1844a16853c
--- /dev/null
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -0,0 +1,480 @@
+//===-- TypeSystemFortran.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_FORTRAN_TYPESYSTEMFORTRAN_H
+#define LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_TYPESYSTEMFORTRAN_H
+#include "lldb/Symbol/TypeSystem.h"
+#include "llvm/Support/ErrorHandling.h"
+namespace lldb_private {
+
+class TypeSystemFortran : public TypeSystem {
+
+  // llvm casting support
+  bool isA(const void *ClassID) const override { return ClassID == &ID; }
+  static bool classof(const TypeSystem *ts) { return ts->isA(&ID); }
+
+  TypeSystemFortran();
+  ~TypeSystemFortran();
+
+  // CompilerDecl functions
+  ConstString DeclGetName(void *opaque_decl) override { return ConstString(); }
+
+  CompilerType GetTypeForDecl(void *opaque_decl) override {
+    return CompilerType();
+  }
+
+  // CompilerDeclContext functions
+
+  ConstString DeclContextGetName(void *opaque_decl_ctx) override {
+    return ConstString();
+  }
+
+  ConstString DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) override {
+    return ConstString();
+  }
+
+  bool DeclContextIsClassMethod(void *opaque_decl_ctx) override {
+    return false;
+  }
+
+  bool DeclContextIsContainedInLookup(void *opaque_decl_ctx,
+                                      void *other_opaque_decl_ctx) override {
+    return false;
+  }
+
+  lldb::LanguageType DeclContextGetLanguage(void *opaque_decl_ctx) override {
+    return lldb::LanguageType::eLanguageTypeUnknown;
+  }
+
+// Tests
+#ifndef NDEBUG
+  /// Verify the integrity of the type to catch CompilerTypes that mix
+  /// and match invalid TypeSystem/Opaque type pairs.
+  bool Verify(lldb::opaque_compiler_type_t type) { return false; };
+#endif
+
+  bool IsArrayType(lldb::opaque_compiler_type_t type,
+                   CompilerType *element_type, uint64_t *size,
+                   bool *is_incomplete) override {
+    return false;
+  };
+
+  bool IsAggregateType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  bool IsCharType(lldb::opaque_compiler_type_t type) override { return false; }
+
+  bool IsCompleteType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  bool IsDefined(lldb::opaque_compiler_type_t type) override { return false; }
+
+  bool IsFloatingPointType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  bool IsFunctionType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  size_t
+  GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) override {
+    return 0;
+  }
+
+  CompilerType GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
+                                          const size_t index) override {
+    return CompilerType();
+  }
+
+  bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  bool IsMemberFunctionPointerType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  bool IsMemberDataPointerType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  bool IsBlockPointerType(lldb::opaque_compiler_type_t type,
+                          CompilerType *function_pointer_type_ptr) override {
+    return false;
+  }
+
+  bool IsIntegerType(lldb::opaque_compiler_type_t type,
+                     bool &is_signed) override {
+    return false;
+  };
+
+  bool IsScopedEnumerationType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
+                             CompilerType *target_type, // Can pass NULL
+                             bool check_cplusplus, bool check_objc) override {
+    return false;
+  }
+
+  bool IsPointerType(lldb::opaque_compiler_type_t type,
+                     CompilerType *pointee_type) override {
+    return false;
+  }
+
+  bool IsScalarType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  bool IsVoidType(lldb::opaque_compiler_type_t type) override { return false; }
+
+  bool CanPassInRegisters(const CompilerType &type) override { return false; }
+
+  // TypeSystems can support more than one language
+  bool SupportsLanguage(lldb::LanguageType language) override {
+    if (language == lldb::LanguageType::eLanguageTypeFortran77 ||
+        language == lldb::LanguageType::eLanguageTypeFortran90 ||
+        language == lldb::LanguageType::eLanguageTypeFortran95 ||
+        language == lldb::LanguageType::eLanguageTypeFortran03 ||
+        language == lldb::LanguageType::eLanguageTypeFortran08 ||
+        language == lldb::LanguageType::eLanguageTypeFortran18) {
+      return true;
+    }
+    return false;
+  }
+
+  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+
+  static llvm::StringRef GetPluginNameStatic() { return "fortran"; }
+
+  // Type Completion
+
+  bool GetCompleteType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  // AST related queries
+
+  uint32_t GetPointerByteSize() override { return 0; }
+
+  CompilerType GetPointerDiffType(bool is_signed) override {
+    return CompilerType();
+  }
+
+  unsigned GetPtrAuthKey(lldb::opaque_compiler_type_t type) override {
+    return 0;
+  }
+
+  unsigned GetPtrAuthDiscriminator(lldb::opaque_compiler_type_t type) override {
+    return 0;
+  }
+
+  bool GetPtrAuthAddressDiversity(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  // Accessors
+
+  ConstString GetTypeName(lldb::opaque_compiler_type_t type,
+                          bool BaseOnly) override {
+    return ConstString();
+  }
+
+  ConstString GetDisplayTypeName(lldb::opaque_compiler_type_t type) override {
+    return ConstString();
+  }
+
+  uint32_t
+  GetTypeInfo(lldb::opaque_compiler_type_t type,
+              CompilerType *pointee_or_element_compiler_type) override {
+    return 0;
+  }
+
+  lldb::LanguageType
+  GetMinimumLanguage(lldb::opaque_compiler_type_t type) override {
+    return lldb::LanguageType::eLanguageTypeUnknown;
+  }
+
+  lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) override {
+    return lldb::TypeClass::eTypeClassInvalid;
+  }
+
+  // Creating related types
+
+  CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type,
+                                   ExecutionContextScope *exe_scope) override {
+    return CompilerType();
+  }
+
+  CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) override {
+    return CompilerType();
+  }
+
+  CompilerType
+  GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) override {
+    return CompilerType();
+  }
+
+  // Returns -1 if this isn't a function of if the function doesn't have a
+  // prototype Returns a value >= 0 if there is a prototype.
+  int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override {
+    return -1;
+  }
+
+  CompilerType GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type,
+                                              size_t idx) override {
+    return CompilerType();
+  }
+
+  CompilerType
+  GetFunctionReturnType(lldb::opaque_compiler_type_t type) override {
+    return CompilerType();
+  }
+
+  size_t GetNumMemberFunctions(lldb::opaque_compiler_type_t type) override {
+    return 0;
+  }
+
+  TypeMemberFunctionImpl
+  GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
+                           size_t idx) override {
+    return TypeMemberFunctionImpl();
+  }
+
+  CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) override {
+    return CompilerType();
+  }
+
+  CompilerType GetPointerType(lldb::opaque_compiler_type_t type) override {
+    return CompilerType();
+  }
+
+  // Exploring the type
+
+  const llvm::fltSemantics &
+  GetFloatTypeSemantics(size_t byte_size, lldb::Format format) override {
+    return llvm::APFloatBase::Bogus();
+  }
+
+  llvm::Expected<uint64_t>
+  GetBitSize(lldb::opaque_compiler_type_t type,
+             ExecutionContextScope *exe_scope) override {
+    return 0;
+  }
+
+  lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type) override {
+    return lldb::eEncodingInvalid;
+  }
+
+  lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override {
+    return lldb::eFormatDefault;
+  }
+
+  llvm::Expected<uint32_t>
+  GetNumChildren(lldb::opaque_compiler_type_t type,
+                 bool omit_empty_base_classes,
+                 const ExecutionContext *exe_ctx) override {
+    return 0;
+  }
+
+  lldb::BasicType
+  GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override {
+    return lldb::eBasicTypeUnsignedInt;
+  }
+
+  uint32_t GetNumFields(lldb::opaque_compiler_type_t type) override {
+    return 0;
+  }
+
+  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 {
+    return CompilerType();
+  }
+
+  uint32_t GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) override {
+    return 0;
+  }
+
+  uint32_t
+  GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) override {
+    return 0;
+  }
+
+  CompilerType GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type,
+                                         size_t idx,
+                                         uint32_t *bit_offset_ptr) override {
+    return CompilerType();
+  }
+
+  CompilerType GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type,
+                                          size_t idx,
+                                          uint32_t *bit_offset_ptr) override {
+    return CompilerType();
+  }
+
+  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 {
+    return CompilerType();
+  }
+
+  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 {
+    return CompilerType();
+  }
+
+  // Lookup a child given a name. This function will match base class names and
+  // member member names in "clang_type" only, not descendants.
+  llvm::Expected<uint32_t>
+  GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
+                          llvm::StringRef name,
+                          bool omit_empty_base_classes) override {
+    return 0;
+  }
+
+  size_t
+  GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type,
+                                llvm::StringRef name,
+                                bool omit_empty_base_classes,
+                                std::vector<uint32_t> &child_indexes) override {
+    return 0;
+  }
+
+#ifndef NDEBUG
+  /// Convenience LLVM-style dump method for use in the debugger only.
+  LLVM_DUMP_METHOD void dump(lldb::opaque_compiler_type_t type) const override {
+  }
+#endif
+
+  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 {
+    return false;
+  }
+
+  /// Dump the type to stdout.
+  void DumpTypeDescription(
+      lldb::opaque_compiler_type_t type,
+      lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) override {}
+
+  /// Print a description of the type to a stream. The exact implementation
+  /// varies, but the expectation is that eDescriptionLevelFull returns a
+  /// source-like representation of the type, whereas eDescriptionLevelVerbose
+  /// does a dump of the underlying AST if applicable.
+  void DumpTypeDescription(
+      lldb::opaque_compiler_type_t type, Stream &s,
+      lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) override {}
+
+  /// Dump a textual representation of the internal TypeSystem state to the
+  /// given stream.
+  ///
+  /// This should not modify the state of the TypeSystem if possible.
+  ///
+  /// \param[out] output Stream to dup the AST into.
+  /// \param[in] filter If empty, dump whole AST. If non-empty, will only
+  /// dump decls whose names contain \c filter.
+  /// \param[in] show_color If true, prints the AST color-highlighted.
+  void Dump(llvm::raw_ostream &output, llvm::StringRef filter,
+            bool show_color) override {}
+
+  /// This is used by swift.
+  bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  // TODO: Determine if these methods should move to TypeSystemClang.
+
+  bool IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
+                                CompilerType *pointee_type) override {
+    return false;
+  }
+
+  unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) override {
+    return 0;
+  }
+
+  std::optional<size_t>
+  GetTypeBitAlign(lldb::opaque_compiler_type_t type,
+                  ExecutionContextScope *exe_scope) override {
+    return 0;
+  }
+
+  CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override {
+    return CompilerType();
+  }
+
+  CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
+                                                   size_t bit_size) override {
+    return CompilerType();
+  }
+
+  bool IsBeingDefined(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  bool IsConst(lldb::opaque_compiler_type_t type) override { return false; }
+
+  uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
+                                  CompilerType *base_type_ptr) override {
+    return 0;
+  }
+
+  bool IsPolymorphicClass(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  bool IsTypedefType(lldb::opaque_compiler_type_t type) override {
+    return false;
+  }
+
+  // If the current object represents a typedef type, get the underlying type
+  CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) override {
+    return CompilerType();
+  }
+
+  bool IsVectorType(lldb::opaque_compiler_type_t type,
+                    CompilerType *element_type, uint64_t *size) override {
+    return false;
+  }
+
+  CompilerType
+  GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) override {
+    return CompilerType();
+  }
+
+  CompilerType GetNonReferenceType(lldb::opaque_compiler_type_t type) override {
+    return CompilerType();
+  }
+  // TODO
+  bool IsReferenceType(lldb::opaque_compiler_type_t type,
+                       CompilerType *pointee_type, bool *is_rvalue) override {
+    return false;
+  }
+
+private:
+  // LLVM RTTI support
+  static char ID;
+};
+} // namespace lldb_private
+#endif // LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_TYPESYSTEMFORTRAN_H

>From 30a78e27574481c6112121f23c7c6e8b439bc7a9 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Sat, 9 May 2026 20:14:29 +0300
Subject: [PATCH 02/44] [lldb] Added Fortran language Plugin

---
 lldb/include/lldb/Target/Language.h           |  2 +
 lldb/source/Plugins/Language/CMakeLists.txt   |  1 +
 .../Plugins/Language/Fortran/CMakeLists.txt   | 12 ++++
 .../Language/Fortran/FortranLanguage.cpp      | 60 +++++++++++++++++++
 .../Language/Fortran/FortranLanguage.h        | 53 ++++++++++++++++
 lldb/source/Target/Language.cpp               | 14 +++++
 6 files changed, 142 insertions(+)
 create mode 100644 lldb/source/Plugins/Language/Fortran/CMakeLists.txt
 create mode 100644 lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp
 create mode 100644 lldb/source/Plugins/Language/Fortran/FortranLanguage.h

diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h
index 4b8d4eaf262a0..d4f3a7071d9a0 100644
--- a/lldb/include/lldb/Target/Language.h
+++ b/lldb/include/lldb/Target/Language.h
@@ -441,6 +441,8 @@ class Language : public PluginInterface {
   /// Equivalent to \c LanguageIsC||LanguageIsObjC||LanguageIsCPlusPlus.
   static bool LanguageIsCFamily(lldb::LanguageType language);
 
+  static bool LanguageIsFortran(lldb::LanguageType language);
+
   static bool LanguageIsPascal(lldb::LanguageType language);
 
   // return the primary language, so if LanguageIsC(l), return eLanguageTypeC,
diff --git a/lldb/source/Plugins/Language/CMakeLists.txt b/lldb/source/Plugins/Language/CMakeLists.txt
index 6367ab916c8fb..5377734af2f8d 100644
--- a/lldb/source/Plugins/Language/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CMakeLists.txt
@@ -7,3 +7,4 @@ set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES
 add_subdirectory(CPlusPlus)
 add_subdirectory(ObjC)
 add_subdirectory(ObjCPlusPlus)
+add_subdirectory(Fortran)
diff --git a/lldb/source/Plugins/Language/Fortran/CMakeLists.txt b/lldb/source/Plugins/Language/Fortran/CMakeLists.txt
new file mode 100644
index 0000000000000..7c5faa87aeaba
--- /dev/null
+++ b/lldb/source/Plugins/Language/Fortran/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_lldb_library(lldbPluginFortranLanguage PLUGIN
+  FortranLanguage.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbDataFormatters
+    lldbExpression
+    lldbHost
+    lldbSymbol
+    lldbTarget
+    lldbUtility
+)
\ No newline at end of file
diff --git a/lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp b/lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp
new file mode 100644
index 0000000000000..a7040ae337b17
--- /dev/null
+++ b/lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp
@@ -0,0 +1,60 @@
+//===-- FortranLanguage.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 "llvm/ADT/StringRef.h"
+
+#include "FortranLanguage.h"
+
+#include "lldb/Core/PluginManager.h"
+
+#include "Plugins/TypeSystem/Fortran/TypeSystemFortran.h"
+
+using namespace llvm;
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+LLDB_PLUGIN_DEFINE(FortranLanguage)
+
+void FortranLanguage::Initialize() {
+  PluginManager::RegisterPlugin(GetPluginNameStatic(), "Fortran Language",
+                                CreateInstance);
+}
+
+void FortranLanguage::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+StringRef FortranLanguage::GetPluginNameStatic() {
+  static llvm::StringRef g_name("fortran");
+  return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+StringRef FortranLanguage::GetPluginName() { return GetPluginNameStatic(); }
+
+uint32_t FortranLanguage::GetPluginVersion() { return 1; }
+
+Language *FortranLanguage::CreateInstance(LanguageType language) {
+  // FIXME: Should Fortran 77 be supported???
+  if (Language::LanguageIsFortran(language)) {
+    return new FortranLanguage();
+  }
+  return nullptr;
+}
+
+bool FortranLanguage::IsSourceFile(StringRef file_path) const {
+  const auto suffixes = {".f90", ".f"};
+  for (auto suffix : suffixes) {
+    if (file_path.ends_with_insensitive(suffix))
+      return true;
+  }
+  return false;
+}
diff --git a/lldb/source/Plugins/Language/Fortran/FortranLanguage.h b/lldb/source/Plugins/Language/Fortran/FortranLanguage.h
new file mode 100644
index 0000000000000..1116564e96c7a
--- /dev/null
+++ b/lldb/source/Plugins/Language/Fortran/FortranLanguage.h
@@ -0,0 +1,53 @@
+//===-- FortranLanguage.h -------------------------------------------------===//
+//
+// 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_LANGUAGE_FORTRAN_FORTRANLANGUAGE_H
+#define LLDB_SOURCE_PLUGINS_LANGUAGE_FORTRAN_FORTRANLANGUAGE_H
+#include "lldb/Target/Language.h"
+
+#include "llvm/ADT/StringRef.h"
+
+#include "lldb/Target/Language.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+class FortranLanguage : public Language {
+public:
+  FortranLanguage() = default;
+
+  ~FortranLanguage() override = default;
+
+  lldb::LanguageType GetLanguageType() const override {
+    return lldb::eLanguageTypeFortran90;
+  }
+  //------------------------------------------------------------------
+  // Static Functions
+  //------------------------------------------------------------------
+  static void Initialize();
+
+  static void Terminate();
+
+  static lldb_private::Language *CreateInstance(lldb::LanguageType language);
+
+  static llvm::StringRef GetPluginNameStatic();
+
+  //------------------------------------------------------------------
+  // PluginInterface protocol
+  //------------------------------------------------------------------
+  llvm::StringRef GetPluginName() override;
+
+  uint32_t GetPluginVersion();
+
+  bool IsSourceFile(llvm::StringRef file_path) const override;
+};
+
+}; // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_LANGUAGE_FORTRAN_FORTRANLANGUAGE_H
\ No newline at end of file
diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp
index 03754e988faa4..304c07c387d3b 100644
--- a/lldb/source/Target/Language.cpp
+++ b/lldb/source/Target/Language.cpp
@@ -396,6 +396,20 @@ bool Language::LanguageIsCFamily(LanguageType language) {
   }
 }
 
+bool Language::LanguageIsFortran(LanguageType language) {
+  switch (language) {
+  case eLanguageTypeFortran77:
+  case eLanguageTypeFortran90:
+  case eLanguageTypeFortran95:
+  case eLanguageTypeFortran03:
+  case eLanguageTypeFortran08:
+  case eLanguageTypeFortran18:
+    return true;
+  default:
+    return false;
+  }
+}
+
 bool Language::LanguageIsPascal(LanguageType language) {
   switch (language) {
   case eLanguageTypePascal83:

>From 2aa105e7161e264424672547caabbf196899b78d Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Mon, 11 May 2026 15:19:37 +0300
Subject: [PATCH 03/44] [lldb] TypeSystem prototype has been implemented

---
 .../Language/Fortran/FortranLanguage.h        |   1 -
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 242 ++++++++++++++++++
 .../TypeSystem/Fortran/TypeSystemFortran.h    | 108 ++++----
 3 files changed, 307 insertions(+), 44 deletions(-)

diff --git a/lldb/source/Plugins/Language/Fortran/FortranLanguage.h b/lldb/source/Plugins/Language/Fortran/FortranLanguage.h
index 1116564e96c7a..e6313b7377deb 100644
--- a/lldb/source/Plugins/Language/Fortran/FortranLanguage.h
+++ b/lldb/source/Plugins/Language/Fortran/FortranLanguage.h
@@ -8,7 +8,6 @@
 
 #ifndef LLDB_SOURCE_PLUGINS_LANGUAGE_FORTRAN_FORTRANLANGUAGE_H
 #define LLDB_SOURCE_PLUGINS_LANGUAGE_FORTRAN_FORTRANLANGUAGE_H
-#include "lldb/Target/Language.h"
 
 #include "llvm/ADT/StringRef.h"
 
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index e69de29bb2d1d..97315fc55228f 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -0,0 +1,242 @@
+//===-- TypeSystemFortran.cpp -----------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+#include "TypeSystemFortran.h"
+
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/SymbolFile.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+using namespace lldb_private::plugin::dwarf;
+
+LLDB_PLUGIN_DEFINE(TypeSystemFortran)
+
+namespace lldb_private {
+
+// Temporary Type class to represent scalar types for prototype
+class FortranType {
+public:
+  enum TypeKind { KIND_INTEGER, KIND_LOGICAL, KIND_REAL, KIND_UNKNOWN };
+  FortranType(int kind, const lldb_private::ConstString &name, uint64_t bitsize)
+      : m_kind(kind), m_type_name(name), m_bitsize(bitsize) {}
+  int GetKind() { return m_kind; }
+  uint64_t GetBitSize() { return m_bitsize; }
+  lldb_private::ConstString GetName() { return m_type_name; }
+
+private:
+  int m_kind;
+  uint64_t m_bitsize;
+  lldb_private::ConstString m_type_name;
+};
+}; // namespace lldb_private
+
+namespace {
+bool IsLanguageSupported(lldb::LanguageType language) {
+  if (language == lldb::LanguageType::eLanguageTypeFortran77 ||
+      language == lldb::LanguageType::eLanguageTypeFortran90 ||
+      language == lldb::LanguageType::eLanguageTypeFortran95 ||
+      language == lldb::LanguageType::eLanguageTypeFortran03 ||
+      language == lldb::LanguageType::eLanguageTypeFortran08 ||
+      language == lldb::LanguageType::eLanguageTypeFortran18)
+    return true;
+
+  return false;
+}
+} // namespace
+char TypeSystemFortran::ID;
+
+TypeSystemFortran::~TypeSystemFortran() = default;
+TypeSystemFortran::TypeSystemFortran() = default;
+
+void TypeSystemFortran::Initialize() {
+  PluginManager::RegisterPlugin(
+      GetPluginNameStatic(), "fortran AST context plug-in", CreateInstance,
+      GetSupportedLanguagesForTypes(), GetSupportedLanguagesForExpressions());
+}
+
+void TypeSystemFortran::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+LanguageSet TypeSystemFortran::GetSupportedLanguagesForTypes() {
+  LanguageSet languages;
+  languages.Insert(eLanguageTypeFortran77);
+  languages.Insert(eLanguageTypeFortran90);
+  languages.Insert(eLanguageTypeFortran95);
+  languages.Insert(eLanguageTypeFortran03);
+  languages.Insert(eLanguageTypeFortran08);
+  languages.Insert(eLanguageTypeFortran18);
+  return languages;
+}
+
+LanguageSet TypeSystemFortran::GetSupportedLanguagesForExpressions() {
+  LanguageSet languages;
+  languages.Insert(eLanguageTypeFortran77);
+  languages.Insert(eLanguageTypeFortran90);
+  languages.Insert(eLanguageTypeFortran95);
+  languages.Insert(eLanguageTypeFortran03);
+  languages.Insert(eLanguageTypeFortran08);
+  languages.Insert(eLanguageTypeFortran18);
+  return languages;
+}
+
+bool TypeSystemFortran::IsFloatingPointType(lldb::opaque_compiler_type_t type) {
+  int kind = static_cast<FortranType *>(type)->GetKind();
+  if (kind == FortranType::KIND_REAL)
+    return true;
+  return false;
+}
+
+ConstString TypeSystemFortran::GetTypeName(lldb::opaque_compiler_type_t type,
+                                           bool BaseOnly) {
+  if (!type)
+    return ConstString();
+  FortranType *fortran_type = static_cast<FortranType *>(type);
+  uint64_t bytes = fortran_type->GetBitSize() / 8;
+  if (BaseOnly)
+    return fortran_type->GetName();
+  switch (fortran_type->GetKind()) {
+  case FortranType::KIND_INTEGER:
+    if (fortran_type->GetBitSize() != 32)
+      return ConstString(llvm::formatv("INTEGER(KIND={0})", bytes).str());
+    else
+      return fortran_type->GetName();
+    break;
+  case FortranType::KIND_LOGICAL:
+    return fortran_type->GetName();
+  case FortranType::KIND_REAL:
+    if (bytes == 4)
+      return ConstString("REAL");
+    if (bytes == 8)
+      return ConstString("DOUBLE PRECISION");
+    return ConstString(llvm::formatv("REAL(KIND={0})", bytes).str());
+  }
+  return ConstString("Unsupported");
+}
+
+CompilerType TypeSystemFortran::GetOrCreateFortranType(int kind,
+                                                       uint64_t bitsize,
+                                                       ConstString name) {
+  FortranType *type = m_type_map[{kind, bitsize}].get();
+  if (type)
+    return CompilerType(weak_from_this(), (void *)type);
+  auto new_type_up = std::make_unique<FortranType>(kind, name, bitsize);
+  FortranType *raw_ptr = new_type_up.get();
+
+  m_type_map[{kind, bitsize}] = std::move(new_type_up);
+
+  return CompilerType(weak_from_this(), (void *)raw_ptr);
+}
+
+// FIXME: Needs a map to index this
+CompilerType
+TypeSystemFortran::GetBasicTypeFromAST(lldb::BasicType basic_type) {
+  switch (basic_type) {
+  case lldb::eBasicTypeInt:
+    return GetOrCreateFortranType(FortranType::KIND_INTEGER, 32,
+                                  ConstString("INTEGER"));
+  case lldb::eBasicTypeFloat:
+    return GetOrCreateFortranType(FortranType::KIND_REAL, 32,
+                                  ConstString("REAL"));
+  case lldb::eBasicTypeDouble:
+    return GetOrCreateFortranType(FortranType::KIND_REAL, 64,
+                                  ConstString("DOUBLE PRECISION"));
+  case lldb::eBasicTypeBool:
+    return GetOrCreateFortranType(FortranType::KIND_LOGICAL, 32,
+                                  ConstString("LOGICAL"));
+  default:
+    return CompilerType();
+  }
+}
+
+CompilerType
+TypeSystemFortran::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
+                                                       size_t bit_size) {
+  switch (encoding) {
+  case eEncodingSint:
+    return GetOrCreateFortranType(FortranType::KIND_INTEGER, bit_size,
+                                  ConstString("INTEGER"));
+  case eEncodingIEEE754:
+    return GetOrCreateFortranType(FortranType::KIND_REAL, bit_size,
+                                  ConstString("REAL"));
+  default:
+    return CompilerType();
+  }
+}
+
+plugin::dwarf::DWARFASTParser *TypeSystemFortran::GetDWARFParser() {
+  if (!m_dwarf_ast_parser_up)
+    m_dwarf_ast_parser_up = std::make_unique<DWARFASTParserFortran>(*this);
+  return m_dwarf_ast_parser_up.get();
+}
+
+// TODO: Process Target and architecture for pointers and Expression Evaluation,
+// if module and target have different typesystems like clang, we would have to
+// account for that here
+lldb::TypeSystemSP
+TypeSystemFortran::CreateInstance(lldb::LanguageType language, Module *module,
+                                  Target *target) {
+  if (IsLanguageSupported(language)) {
+    return std::make_shared<TypeSystemFortran>();
+  }
+  return TypeSystemSP();
+}
+
+llvm::Expected<uint64_t>
+TypeSystemFortran::GetBitSize(lldb::opaque_compiler_type_t type,
+                              ExecutionContextScope *exe_scope) {
+  if (!type)
+    return 0;
+  FortranType *fortran_type = static_cast<FortranType *>(type);
+  return fortran_type->GetBitSize();
+}
+
+lldb::Encoding
+TypeSystemFortran::GetEncoding(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return lldb::eEncodingInvalid;
+  FortranType *fortran_type = static_cast<FortranType *>(type);
+  switch (fortran_type->GetKind()) {
+  case FortranType::KIND_REAL:
+    return lldb::eEncodingIEEE754;
+  case FortranType::KIND_INTEGER:
+    return lldb::eEncodingSint;
+  case FortranType::KIND_LOGICAL:
+    return lldb::eEncodingUint;
+  default:
+    return lldb::eEncodingInvalid;
+  }
+}
+
+lldb::Format TypeSystemFortran::GetFormat(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return lldb::eFormatDefault;
+  FortranType *fortran_type = static_cast<FortranType *>(type);
+  switch (fortran_type->GetKind()) {
+  case FortranType::KIND_INTEGER:
+    return lldb::eFormatDecimal;
+  case FortranType::KIND_REAL:
+    return lldb::eFormatFloat;
+  case FortranType::KIND_LOGICAL:
+    return lldb::eFormatBoolean;
+  default:
+    return lldb::eFormatDefault;
+  }
+}
+
+bool IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) {
+  if (!type)
+    return false;
+  FortranType *fortran_type = static_cast<FortranType *>(type);
+  if (fortran_type->GetKind() == FortranType::KIND_INTEGER) {
+    is_signed = true;
+    return true;
+  }
+  return false;
+}
\ No newline at end of file
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index be1844a16853c..91beff1745792 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -9,11 +9,17 @@
 #ifndef LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_TYPESYSTEMFORTRAN_H
 #define LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_TYPESYSTEMFORTRAN_H
 #include "lldb/Symbol/TypeSystem.h"
+
+#include "Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/ErrorHandling.h"
+
 namespace lldb_private {
 
-class TypeSystemFortran : public TypeSystem {
+class FortranType;
 
+class TypeSystemFortran : public TypeSystem {
+public:
   // llvm casting support
   bool isA(const void *ClassID) const override { return ClassID == &ID; }
   static bool classof(const TypeSystem *ts) { return ts->isA(&ID); }
@@ -21,6 +27,19 @@ class TypeSystemFortran : public TypeSystem {
   TypeSystemFortran();
   ~TypeSystemFortran();
 
+  static void Initialize();
+
+  static void Terminate();
+
+  plugin::dwarf::DWARFASTParser *GetDWARFParser() override;
+
+  static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
+                                           Module *module, Target *target);
+
+  static LanguageSet GetSupportedLanguagesForTypes();
+
+  static LanguageSet GetSupportedLanguagesForExpressions();
+
   // CompilerDecl functions
   ConstString DeclGetName(void *opaque_decl) override { return ConstString(); }
 
@@ -71,15 +90,15 @@ class TypeSystemFortran : public TypeSystem {
   bool IsCharType(lldb::opaque_compiler_type_t type) override { return false; }
 
   bool IsCompleteType(lldb::opaque_compiler_type_t type) override {
-    return false;
+    return true;
   }
 
-  bool IsDefined(lldb::opaque_compiler_type_t type) override { return false; }
-
-  bool IsFloatingPointType(lldb::opaque_compiler_type_t type) override {
-    return false;
+  bool IsDefined(lldb::opaque_compiler_type_t type) override {
+    return type != nullptr;
   }
 
+  bool IsFloatingPointType(lldb::opaque_compiler_type_t type) override;
+
   bool IsFunctionType(lldb::opaque_compiler_type_t type) override {
     return false;
   }
@@ -112,9 +131,7 @@ class TypeSystemFortran : public TypeSystem {
   }
 
   bool IsIntegerType(lldb::opaque_compiler_type_t type,
-                     bool &is_signed) override {
-    return false;
-  };
+                     bool &is_signed) override;
 
   bool IsScopedEnumerationType(lldb::opaque_compiler_type_t type) override {
     return false;
@@ -131,9 +148,7 @@ class TypeSystemFortran : public TypeSystem {
     return false;
   }
 
-  bool IsScalarType(lldb::opaque_compiler_type_t type) override {
-    return false;
-  }
+  bool IsScalarType(lldb::opaque_compiler_type_t type) override { return true; }
 
   bool IsVoidType(lldb::opaque_compiler_type_t type) override { return false; }
 
@@ -159,7 +174,7 @@ class TypeSystemFortran : public TypeSystem {
   // Type Completion
 
   bool GetCompleteType(lldb::opaque_compiler_type_t type) override {
-    return false;
+    return true;
   }
 
   // AST related queries
@@ -183,14 +198,11 @@ class TypeSystemFortran : public TypeSystem {
   }
 
   // Accessors
-
   ConstString GetTypeName(lldb::opaque_compiler_type_t type,
-                          bool BaseOnly) override {
-    return ConstString();
-  }
+                          bool BaseOnly) override;
 
   ConstString GetDisplayTypeName(lldb::opaque_compiler_type_t type) override {
-    return ConstString();
+    return GetTypeName(type, false);
   }
 
   uint32_t
@@ -201,27 +213,35 @@ class TypeSystemFortran : public TypeSystem {
 
   lldb::LanguageType
   GetMinimumLanguage(lldb::opaque_compiler_type_t type) override {
-    return lldb::LanguageType::eLanguageTypeUnknown;
+    return lldb::LanguageType::eLanguageTypeFortran90;
   }
 
   lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) override {
-    return lldb::TypeClass::eTypeClassInvalid;
+    if (!type)
+      return lldb::eTypeClassInvalid;
+
+    return lldb::eTypeClassBuiltin;
   }
 
+  CompilerType GetOrCreateFortranType(int kind, uint64_t bitsize,
+                                      ConstString name);
+
   // Creating related types
 
   CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type,
                                    ExecutionContextScope *exe_scope) override {
     return CompilerType();
   }
-
+  //
   CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) override {
-    return CompilerType();
+    if (!type)
+      return CompilerType();
+    return CompilerType(weak_from_this(), type);
   }
 
   CompilerType
   GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) override {
-    return CompilerType();
+    return CompilerType(weak_from_this(), type);
   }
 
   // Returns -1 if this isn't a function of if the function doesn't have a
@@ -267,17 +287,11 @@ class TypeSystemFortran : public TypeSystem {
 
   llvm::Expected<uint64_t>
   GetBitSize(lldb::opaque_compiler_type_t type,
-             ExecutionContextScope *exe_scope) override {
-    return 0;
-  }
+             ExecutionContextScope *exe_scope) override;
 
-  lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type) override {
-    return lldb::eEncodingInvalid;
-  }
+  lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type) override;
 
-  lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override {
-    return lldb::eFormatDefault;
-  }
+  lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override;
 
   llvm::Expected<uint32_t>
   GetNumChildren(lldb::opaque_compiler_type_t type,
@@ -285,10 +299,10 @@ class TypeSystemFortran : public TypeSystem {
                  const ExecutionContext *exe_ctx) override {
     return 0;
   }
-
+  // TODO
   lldb::BasicType
   GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override {
-    return lldb::eBasicTypeUnsignedInt;
+    return lldb::eBasicTypeInt;
   }
 
   uint32_t GetNumFields(lldb::opaque_compiler_type_t type) override {
@@ -420,14 +434,10 @@ class TypeSystemFortran : public TypeSystem {
     return 0;
   }
 
-  CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override {
-    return CompilerType();
-  }
+  CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override;
 
   CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
-                                                   size_t bit_size) override {
-    return CompilerType();
-  }
+                                                   size_t bit_size) override;
 
   bool IsBeingDefined(lldb::opaque_compiler_type_t type) override {
     return false;
@@ -460,13 +470,17 @@ class TypeSystemFortran : public TypeSystem {
 
   CompilerType
   GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) override {
-    return CompilerType();
+    if (!type)
+      return CompilerType();
+    return CompilerType(weak_from_this(), type);
   }
 
   CompilerType GetNonReferenceType(lldb::opaque_compiler_type_t type) override {
-    return CompilerType();
+    if (!type)
+      return CompilerType();
+    return CompilerType(weak_from_this(), type);
   }
-  // TODO
+
   bool IsReferenceType(lldb::opaque_compiler_type_t type,
                        CompilerType *pointee_type, bool *is_rvalue) override {
     return false;
@@ -475,6 +489,14 @@ class TypeSystemFortran : public TypeSystem {
 private:
   // LLVM RTTI support
   static char ID;
+  typedef std::pair<int, uint64_t> TypeKey;
+  typedef llvm::DenseMap<TypeKey, std::unique_ptr<FortranType>> TypeMap;
+
+  TypeMap m_type_map;
+  std::unique_ptr<DWARFASTParserFortran> m_dwarf_ast_parser_up;
+
+  TypeSystemFortran(const TypeSystemFortran &) = delete;
+  const TypeSystemFortran &operator=(const TypeSystemFortran &) = delete;
 };
 } // namespace lldb_private
 #endif // LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_TYPESYSTEMFORTRAN_H

>From e7acc87f243ba846eee277af5c53f1e1d40924f0 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Thu, 14 May 2026 23:20:53 +0300
Subject: [PATCH 04/44] [lldb][Fortran] Added TypeSystemFortran to lldb-forward
 declarations

---
 lldb/include/lldb/lldb-forward.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 67888f7d32ed1..9c6a11dd6d9b3 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -282,6 +282,7 @@ class TypeSummaryImpl;
 class TypeSummaryOptions;
 class TypeSystem;
 class TypeSystemClang;
+class TypeSystemFortran;
 class UUID;
 class UnixSignals;
 class Unwind;

>From b9a81a5b9d3f43f38038ac83ecdfd7c6b897bdcf Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Thu, 14 May 2026 23:22:17 +0300
Subject: [PATCH 05/44] [lldb][Fortran] Added function type, added support for
 printing basic variable values and logically grouped functions

---
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 296 +++++++++++++-----
 .../TypeSystem/Fortran/TypeSystemFortran.h    |  78 ++---
 2 files changed, 259 insertions(+), 115 deletions(-)

diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index 97315fc55228f..8431acc8929b1 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -7,8 +7,14 @@
 //===----------------------------------------------------------------------===//
 #include "TypeSystemFortran.h"
 
+#include "lldb/Core/DumpDataExtractor.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Target/Target.h"
+
+#include "llvm/Support/raw_ostream.h"
+
+#include "Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -19,36 +25,57 @@ LLDB_PLUGIN_DEFINE(TypeSystemFortran)
 
 namespace lldb_private {
 
-// Temporary Type class to represent scalar types for prototype
+/// A simplified internal representation of a Fortran type.
+/// In the future, this will likely be replaced by a Flang-backed AST.
 class FortranType {
 public:
-  enum TypeKind { KIND_INTEGER, KIND_LOGICAL, KIND_REAL, KIND_UNKNOWN };
-  FortranType(int kind, const lldb_private::ConstString &name, uint64_t bitsize)
-      : m_kind(kind), m_type_name(name), m_bitsize(bitsize) {}
-  int GetKind() { return m_kind; }
-  uint64_t GetBitSize() { return m_bitsize; }
-  lldb_private::ConstString GetName() { return m_type_name; }
+  enum TypeKind {
+    KIND_INTEGER,
+    KIND_LOGICAL,
+    KIND_REAL,
+    KIND_FUNCTION,
+    KIND_UNKNOWN
+  };
+  FortranType(int kind, const ConstString &name, uint64_t bitsize)
+      : m_kind(kind), m_bitsize(bitsize), m_type_name(name) {}
+  int GetKind() const { return m_kind; }
+  uint64_t GetBitSize() const { return m_bitsize; }
+  ConstString GetName() const { return m_type_name; }
 
 private:
   int m_kind;
   uint64_t m_bitsize;
-  lldb_private::ConstString m_type_name;
+  ConstString m_type_name;
 };
-}; // namespace lldb_private
 
-namespace {
-bool IsLanguageSupported(lldb::LanguageType language) {
-  if (language == lldb::LanguageType::eLanguageTypeFortran77 ||
-      language == lldb::LanguageType::eLanguageTypeFortran90 ||
-      language == lldb::LanguageType::eLanguageTypeFortran95 ||
-      language == lldb::LanguageType::eLanguageTypeFortran03 ||
-      language == lldb::LanguageType::eLanguageTypeFortran08 ||
-      language == lldb::LanguageType::eLanguageTypeFortran18)
+class FortranFunction : public FortranType {
+public:
+  FortranFunction(ConstString func_name,
+                  const SmallVectorImpl<CompilerType> &parameters)
+      : FortranType(FortranType::KIND_FUNCTION, func_name, 0) {
+    m_parameters.assign(parameters.begin(), parameters.end());
+  }
+  ArrayRef<CompilerType> GetParameters() const { return m_parameters; }
+  size_t GetNumberOfParameters() const { return m_parameters.size(); }
+
+private:
+  SmallVector<CompilerType, 4> m_parameters;
+};
+} // namespace lldb_private
+
+/// Used to determine if TypeSystem supports the language passed in CreateInstance
+static bool IsLanguageSupported(LanguageType language) {
+  if (language == LanguageType::eLanguageTypeFortran77 ||
+      language == LanguageType::eLanguageTypeFortran90 ||
+      language == LanguageType::eLanguageTypeFortran95 ||
+      language == LanguageType::eLanguageTypeFortran03 ||
+      language == LanguageType::eLanguageTypeFortran08 ||
+      language == LanguageType::eLanguageTypeFortran18)
     return true;
 
   return false;
 }
-} // namespace
+
 char TypeSystemFortran::ID;
 
 TypeSystemFortran::~TypeSystemFortran() = default;
@@ -64,6 +91,33 @@ void TypeSystemFortran::Terminate() {
   PluginManager::UnregisterPlugin(CreateInstance);
 }
 
+plugin::dwarf::DWARFASTParser *TypeSystemFortran::GetDWARFParser() {
+  if (!m_dwarf_ast_parser_up)
+    m_dwarf_ast_parser_up = std::make_unique<DWARFASTParserFortran>(*this);
+  return m_dwarf_ast_parser_up.get();
+}
+
+// TODO: Process Target and architecture for pointers and Expression Evaluation,
+// if module and target have different typesystems like clang, we would have to
+// account for that here
+TypeSystemSP TypeSystemFortran::CreateInstance(LanguageType language,
+                                               Module *module, Target *target) {
+
+  if (IsLanguageSupported(language)) {
+    auto type_system_sp = std::make_shared<TypeSystemFortran>();
+
+    // Get the byte order from the target or module and store it
+    if (target) {
+      type_system_sp->SetByteOrder(target->GetArchitecture().GetByteOrder());
+    } else if (module) {
+      type_system_sp->SetByteOrder(module->GetArchitecture().GetByteOrder());
+    }
+
+    return type_system_sp;
+  }
+  return TypeSystemSP();
+}
+
 LanguageSet TypeSystemFortran::GetSupportedLanguagesForTypes() {
   LanguageSet languages;
   languages.Insert(eLanguageTypeFortran77);
@@ -75,6 +129,8 @@ LanguageSet TypeSystemFortran::GetSupportedLanguagesForTypes() {
   return languages;
 }
 
+// FIXME: Currently returns all Fortran languages to satisfy plugin requirements,
+// but expression evaluation is not yet implemented.
 LanguageSet TypeSystemFortran::GetSupportedLanguagesForExpressions() {
   LanguageSet languages;
   languages.Insert(eLanguageTypeFortran77);
@@ -86,14 +142,71 @@ LanguageSet TypeSystemFortran::GetSupportedLanguagesForExpressions() {
   return languages;
 }
 
-bool TypeSystemFortran::IsFloatingPointType(lldb::opaque_compiler_type_t type) {
-  int kind = static_cast<FortranType *>(type)->GetKind();
-  if (kind == FortranType::KIND_REAL)
+//FIXME: Is support for all Fortran ISO the goal?
+bool TypeSystemFortran::SupportsLanguage(lldb::LanguageType language) {
+  if (language == lldb::LanguageType::eLanguageTypeFortran77 ||
+      language == lldb::LanguageType::eLanguageTypeFortran90 ||
+      language == lldb::LanguageType::eLanguageTypeFortran95 ||
+      language == lldb::LanguageType::eLanguageTypeFortran03 ||
+      language == lldb::LanguageType::eLanguageTypeFortran08 ||
+      language == lldb::LanguageType::eLanguageTypeFortran18) {
     return true;
+  }
   return false;
 }
 
-ConstString TypeSystemFortran::GetTypeName(lldb::opaque_compiler_type_t type,
+/// Returns the type assosciated with the kind and bitsize, or creates it 
+/// if it is not in the map
+CompilerType TypeSystemFortran::GetOrCreateFortranType(int kind,
+                                                       uint64_t bitsize,
+                                                       ConstString name) {
+  FortranType *type = m_type_map[{kind, bitsize}].get();
+  if (type)
+    return CompilerType(weak_from_this(), (void *)type);
+  auto new_type_up = std::make_unique<FortranType>(kind, name, bitsize);
+  FortranType *raw_ptr = new_type_up.get();
+
+  m_type_map[{kind, bitsize}] = std::move(new_type_up);
+
+  return CompilerType(weak_from_this(), (void *)raw_ptr);
+}
+
+/// Returns the type assosciated with the name, or creates it 
+/// if it is not in the map
+CompilerType TypeSystemFortran::GetOrCreateFortranFunction(
+    ConstString name, const SmallVectorImpl<CompilerType> &parameters) {
+  FortranType *type = m_function_map[name].get();
+  if (type)
+    return CompilerType(weak_from_this(), (void *)type);
+  auto new_type_up = std::make_unique<FortranFunction>(name, parameters);
+  FortranType *raw_ptr = new_type_up.get();
+
+  m_function_map[name] = std::move(new_type_up);
+
+  return CompilerType(weak_from_this(), (void *)raw_ptr);
+}
+
+CompilerType TypeSystemFortran::CreateType(uint32_t kind, uint64_t bitsize,
+                                           ConstString name) {
+  int underlying_kind;
+  switch (kind) {
+  case dwarf::DW_ATE_boolean:
+    underlying_kind = FortranType::KIND_LOGICAL;
+    break;
+  case dwarf::DW_ATE_float:
+    underlying_kind = FortranType::KIND_REAL;
+    break;
+  case dwarf::DW_ATE_signed:
+    underlying_kind = FortranType::KIND_INTEGER;
+    break;
+  default:
+    return CompilerType();
+  }
+  return GetOrCreateFortranType(underlying_kind, bitsize, name);
+}
+
+/// Returns the type name upper-cased to follow Fortran's general style
+ConstString TypeSystemFortran::GetTypeName(opaque_compiler_type_t type,
                                            bool BaseOnly) {
   if (!type)
     return ConstString();
@@ -104,7 +217,7 @@ ConstString TypeSystemFortran::GetTypeName(lldb::opaque_compiler_type_t type,
   switch (fortran_type->GetKind()) {
   case FortranType::KIND_INTEGER:
     if (fortran_type->GetBitSize() != 32)
-      return ConstString(llvm::formatv("INTEGER(KIND={0})", bytes).str());
+      return ConstString(formatv("INTEGER(KIND={0})", bytes).str());
     else
       return fortran_type->GetName();
     break;
@@ -115,39 +228,23 @@ ConstString TypeSystemFortran::GetTypeName(lldb::opaque_compiler_type_t type,
       return ConstString("REAL");
     if (bytes == 8)
       return ConstString("DOUBLE PRECISION");
-    return ConstString(llvm::formatv("REAL(KIND={0})", bytes).str());
+    return ConstString(formatv("REAL(KIND={0})", bytes).str());
   }
   return ConstString("Unsupported");
 }
 
-CompilerType TypeSystemFortran::GetOrCreateFortranType(int kind,
-                                                       uint64_t bitsize,
-                                                       ConstString name) {
-  FortranType *type = m_type_map[{kind, bitsize}].get();
-  if (type)
-    return CompilerType(weak_from_this(), (void *)type);
-  auto new_type_up = std::make_unique<FortranType>(kind, name, bitsize);
-  FortranType *raw_ptr = new_type_up.get();
-
-  m_type_map[{kind, bitsize}] = std::move(new_type_up);
-
-  return CompilerType(weak_from_this(), (void *)raw_ptr);
-}
-
-// FIXME: Needs a map to index this
-CompilerType
-TypeSystemFortran::GetBasicTypeFromAST(lldb::BasicType basic_type) {
+CompilerType TypeSystemFortran::GetBasicTypeFromAST(BasicType basic_type) {
   switch (basic_type) {
-  case lldb::eBasicTypeInt:
+  case eBasicTypeInt:
     return GetOrCreateFortranType(FortranType::KIND_INTEGER, 32,
                                   ConstString("INTEGER"));
-  case lldb::eBasicTypeFloat:
+  case eBasicTypeFloat:
     return GetOrCreateFortranType(FortranType::KIND_REAL, 32,
                                   ConstString("REAL"));
-  case lldb::eBasicTypeDouble:
+  case eBasicTypeDouble:
     return GetOrCreateFortranType(FortranType::KIND_REAL, 64,
                                   ConstString("DOUBLE PRECISION"));
-  case lldb::eBasicTypeBool:
+  case eBasicTypeBool:
     return GetOrCreateFortranType(FortranType::KIND_LOGICAL, 32,
                                   ConstString("LOGICAL"));
   default:
@@ -156,7 +253,7 @@ TypeSystemFortran::GetBasicTypeFromAST(lldb::BasicType basic_type) {
 }
 
 CompilerType
-TypeSystemFortran::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
+TypeSystemFortran::GetBuiltinTypeForEncodingAndBitSize(Encoding encoding,
                                                        size_t bit_size) {
   switch (encoding) {
   case eEncodingSint:
@@ -170,26 +267,32 @@ TypeSystemFortran::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
   }
 }
 
-plugin::dwarf::DWARFASTParser *TypeSystemFortran::GetDWARFParser() {
-  if (!m_dwarf_ast_parser_up)
-    m_dwarf_ast_parser_up = std::make_unique<DWARFASTParserFortran>(*this);
-  return m_dwarf_ast_parser_up.get();
-}
-
-// TODO: Process Target and architecture for pointers and Expression Evaluation,
-// if module and target have different typesystems like clang, we would have to
-// account for that here
-lldb::TypeSystemSP
-TypeSystemFortran::CreateInstance(lldb::LanguageType language, Module *module,
-                                  Target *target) {
-  if (IsLanguageSupported(language)) {
-    return std::make_shared<TypeSystemFortran>();
+uint32_t
+TypeSystemFortran::GetTypeInfo(opaque_compiler_type_t type,
+                               CompilerType *pointee_or_element_compiler_type) {
+  if (!type)
+    return 0;
+  FortranType *fortran_type = static_cast<FortranType *>(type);
+  uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue;
+  int type_kind = fortran_type->GetKind();
+  switch (type_kind) {
+  case FortranType::KIND_REAL:
+  case FortranType::KIND_INTEGER:
+  case FortranType::KIND_LOGICAL:
+    builtin_type_flags |= eTypeIsScalar;
+    if (type_kind == FortranType::KIND_INTEGER)
+      builtin_type_flags |= eTypeIsInteger | eTypeIsSigned;
+    if (type_kind == FortranType::KIND_REAL)
+      builtin_type_flags |= eTypeIsFloat;
+    break;
+  default:
+    break;
   }
-  return TypeSystemSP();
+  return builtin_type_flags;
 }
 
-llvm::Expected<uint64_t>
-TypeSystemFortran::GetBitSize(lldb::opaque_compiler_type_t type,
+Expected<uint64_t>
+TypeSystemFortran::GetBitSize(opaque_compiler_type_t type,
                               ExecutionContextScope *exe_scope) {
   if (!type)
     return 0;
@@ -197,40 +300,40 @@ TypeSystemFortran::GetBitSize(lldb::opaque_compiler_type_t type,
   return fortran_type->GetBitSize();
 }
 
-lldb::Encoding
-TypeSystemFortran::GetEncoding(lldb::opaque_compiler_type_t type) {
+Encoding TypeSystemFortran::GetEncoding(opaque_compiler_type_t type) {
   if (!type)
-    return lldb::eEncodingInvalid;
+    return eEncodingInvalid;
   FortranType *fortran_type = static_cast<FortranType *>(type);
   switch (fortran_type->GetKind()) {
   case FortranType::KIND_REAL:
-    return lldb::eEncodingIEEE754;
+    return eEncodingIEEE754;
   case FortranType::KIND_INTEGER:
-    return lldb::eEncodingSint;
+    return eEncodingSint;
   case FortranType::KIND_LOGICAL:
-    return lldb::eEncodingUint;
+    return eEncodingUint;
   default:
-    return lldb::eEncodingInvalid;
+    return eEncodingInvalid;
   }
 }
 
-lldb::Format TypeSystemFortran::GetFormat(lldb::opaque_compiler_type_t type) {
+Format TypeSystemFortran::GetFormat(opaque_compiler_type_t type) {
   if (!type)
-    return lldb::eFormatDefault;
+    return eFormatDefault;
   FortranType *fortran_type = static_cast<FortranType *>(type);
   switch (fortran_type->GetKind()) {
   case FortranType::KIND_INTEGER:
-    return lldb::eFormatDecimal;
+    return eFormatDecimal;
   case FortranType::KIND_REAL:
-    return lldb::eFormatFloat;
+    return eFormatFloat;
   case FortranType::KIND_LOGICAL:
-    return lldb::eFormatBoolean;
+    return eFormatBoolean;
   default:
-    return lldb::eFormatDefault;
+    return eFormatDefault;
   }
 }
 
-bool IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) {
+bool TypeSystemFortran::IsIntegerType(opaque_compiler_type_t type,
+                                      bool &is_signed) {
   if (!type)
     return false;
   FortranType *fortran_type = static_cast<FortranType *>(type);
@@ -239,4 +342,41 @@ bool IsIntegerType(lldb::opaque_compiler_type_t type, bool &is_signed) {
     return true;
   }
   return false;
-}
\ No newline at end of file
+}
+
+bool TypeSystemFortran::IsFloatingPointType(opaque_compiler_type_t type) {
+  int kind = static_cast<FortranType *>(type)->GetKind();
+  if (kind == FortranType::KIND_REAL)
+    return true;
+  return false;
+}
+
+bool TypeSystemFortran::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) {
+  if (!type)
+    return false;
+
+  FortranType *fortran_type = static_cast<FortranType *>(type);
+  int type_kind = fortran_type->GetKind();
+  DataExtractor format_data;
+  switch (type_kind) {
+  case FortranType::KIND_INTEGER:
+  case FortranType::KIND_REAL:
+  case FortranType::KIND_LOGICAL:
+
+    format_data.SetData(data, 0, data.GetByteSize());
+    format_data.SetAddressByteSize(data.GetAddressByteSize());
+    format_data.SetByteOrder(m_byte_order);
+    return DumpDataExtractor(format_data, &s, data_offset, format,
+                             data_byte_size, 1 /*item_count*/, UINT32_MAX,
+                             LLDB_INVALID_ADDRESS, bitfield_bit_size,
+                             bitfield_bit_offset, exe_scope);
+  default:
+    Host::SystemLog(lldb::eSeverityError,
+                    "Error: DumpTypeValue not handled yet.\n");
+    return false;
+  }
+}
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index 91beff1745792..1cd98d4b417eb 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -10,7 +10,6 @@
 #define LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_TYPESYSTEMFORTRAN_H
 #include "lldb/Symbol/TypeSystem.h"
 
-#include "Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/ErrorHandling.h"
 
@@ -18,7 +17,14 @@ namespace lldb_private {
 
 class FortranType;
 
+/// A TypeSystem implementation for the Fortran language.
+/// 
+/// This plugin provides LLDB with the ability to understand Fortran types
+/// parsed from debug information (DWARF).
 class TypeSystemFortran : public TypeSystem {
+  // LLVM RTTI support
+  static char ID;
+
 public:
   // llvm casting support
   bool isA(const void *ClassID) const override { return ClassID == &ID; }
@@ -36,10 +42,18 @@ class TypeSystemFortran : public TypeSystem {
   static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
                                            Module *module, Target *target);
 
+  CompilerType CreateType(uint32_t kind, uint64_t bitsize, ConstString name);
+
   static LanguageSet GetSupportedLanguagesForTypes();
 
   static LanguageSet GetSupportedLanguagesForExpressions();
 
+  bool SupportsLanguage(lldb::LanguageType language) override;
+
+  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+
+  static llvm::StringRef GetPluginNameStatic() { return "fortran"; }
+
   // CompilerDecl functions
   ConstString DeclGetName(void *opaque_decl) override { return ConstString(); }
 
@@ -77,6 +91,7 @@ class TypeSystemFortran : public TypeSystem {
   bool Verify(lldb::opaque_compiler_type_t type) { return false; };
 #endif
 
+  // Type Classification
   bool IsArrayType(lldb::opaque_compiler_type_t type,
                    CompilerType *element_type, uint64_t *size,
                    bool *is_incomplete) override {
@@ -154,25 +169,7 @@ class TypeSystemFortran : public TypeSystem {
 
   bool CanPassInRegisters(const CompilerType &type) override { return false; }
 
-  // TypeSystems can support more than one language
-  bool SupportsLanguage(lldb::LanguageType language) override {
-    if (language == lldb::LanguageType::eLanguageTypeFortran77 ||
-        language == lldb::LanguageType::eLanguageTypeFortran90 ||
-        language == lldb::LanguageType::eLanguageTypeFortran95 ||
-        language == lldb::LanguageType::eLanguageTypeFortran03 ||
-        language == lldb::LanguageType::eLanguageTypeFortran08 ||
-        language == lldb::LanguageType::eLanguageTypeFortran18) {
-      return true;
-    }
-    return false;
-  }
-
-  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
-
-  static llvm::StringRef GetPluginNameStatic() { return "fortran"; }
-
-  // Type Completion
-
+  // Type Completion, all basic types are complete
   bool GetCompleteType(lldb::opaque_compiler_type_t type) override {
     return true;
   }
@@ -205,11 +202,8 @@ class TypeSystemFortran : public TypeSystem {
     return GetTypeName(type, false);
   }
 
-  uint32_t
-  GetTypeInfo(lldb::opaque_compiler_type_t type,
-              CompilerType *pointee_or_element_compiler_type) override {
-    return 0;
-  }
+  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 {
@@ -226,6 +220,9 @@ class TypeSystemFortran : public TypeSystem {
   CompilerType GetOrCreateFortranType(int kind, uint64_t bitsize,
                                       ConstString name);
 
+  CompilerType GetOrCreateFortranFunction(
+      ConstString name, const llvm::SmallVectorImpl<CompilerType> &parameters);
+
   // Creating related types
 
   CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type,
@@ -278,6 +275,10 @@ class TypeSystemFortran : public TypeSystem {
     return CompilerType();
   }
 
+  void SetByteOrder(lldb::ByteOrder byte_order) { m_byte_order = byte_order; }
+
+  lldb::ByteOrder GetByteOrder() { return m_byte_order; }
+
   // Exploring the type
 
   const llvm::fltSemantics &
@@ -299,7 +300,7 @@ class TypeSystemFortran : public TypeSystem {
                  const ExecutionContext *exe_ctx) override {
     return 0;
   }
-  // TODO
+
   lldb::BasicType
   GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override {
     return lldb::eBasicTypeInt;
@@ -383,10 +384,7 @@ class TypeSystemFortran : public TypeSystem {
                      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 {
-    return false;
-  }
-
+                     ExecutionContextScope *exe_scope) override;
   /// Dump the type to stdout.
   void DumpTypeDescription(
       lldb::opaque_compiler_type_t type,
@@ -412,7 +410,6 @@ class TypeSystemFortran : public TypeSystem {
   void Dump(llvm::raw_ostream &output, llvm::StringRef filter,
             bool show_color) override {}
 
-  /// This is used by swift.
   bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) override {
     return false;
   }
@@ -487,16 +484,23 @@ class TypeSystemFortran : public TypeSystem {
   }
 
 private:
-  // LLVM RTTI support
-  static char ID;
+  
   typedef std::pair<int, uint64_t> TypeKey;
   typedef llvm::DenseMap<TypeKey, std::unique_ptr<FortranType>> TypeMap;
+  typedef llvm::DenseMap<ConstString, std::unique_ptr<FortranType>> FunctionMap;
 
+  // TODO: Types are assosciated by their kind and bitsize, this helps to 
+  // return from their basic type and is enough for basic types but 
+  // will change once more types are supported
   TypeMap m_type_map;
-  std::unique_ptr<DWARFASTParserFortran> m_dwarf_ast_parser_up;
-
-  TypeSystemFortran(const TypeSystemFortran &) = delete;
-  const TypeSystemFortran &operator=(const TypeSystemFortran &) = delete;
+  // Right now we can index functions just by their name, but a more 
+  // effecient solution might replace this
+  FunctionMap m_function_map;
+  std::unique_ptr<plugin::dwarf::DWARFASTParser> m_dwarf_ast_parser_up;
+  /// Store byte order of the system so variables can be printed correctly
+  lldb::ByteOrder m_byte_order;
+  TypeSystemFortran(const TypeSystemFortran &);
+  const TypeSystemFortran &operator=(const TypeSystemFortran &);
 };
 } // namespace lldb_private
 #endif // LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_TYPESYSTEMFORTRAN_H

>From 0317387982b5c1c3a03286ab7803f6bb54b37c07 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Thu, 14 May 2026 23:23:45 +0300
Subject: [PATCH 06/44] [lldb][Fortran] Implemented parsing for basic types and
 functions in DWARFASTParserFortran

---
 .../DWARF/DWARFASTParserFortran.cpp           | 193 ++++++++++++++++--
 .../SymbolFile/DWARF/DWARFASTParserFortran.h  |   6 +-
 2 files changed, 181 insertions(+), 18 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
index 0973f658f6b04..f3bf860b205ce 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
@@ -8,32 +8,193 @@
 
 #include "DWARFASTParserFortran.h"
 
+#include "DWARFDIE.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDeclContext.h"
+#include "DWARFDefines.h"
+#include "LogChannelDWARF.h"
+#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+#include "UniqueDWARFASTType.h"
+
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Utility/Log.h"
+
 using namespace lldb;
 using namespace lldb_private;
+using namespace lldb_private::plugin::dwarf;
+using namespace llvm::dwarf;
 
-DWARFASTParserFortran::DWARFASTParserFortran(
-    lldb_private::TypeSystemFortran m_ast)
-    : lldb_private::plugin::dwarf::DWARFASTParser(Kind::DWARFASTParserFortran),
-      m_ast(m_ast) {}
+DWARFASTParserFortran::DWARFASTParserFortran(TypeSystemFortran &ast)
+    : DWARFASTParser(Kind::DWARFASTParserFortran), m_ast(ast) {}
 
 DWARFASTParserFortran::~DWARFASTParserFortran() {}
 
-lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(
-    const lldb_private::SymbolContext &sc,
-    const lldb_private::plugin::dwarf::DWARFDIE &die, bool *type_is_new_ptr) {
-  // TODO
+//TODO: Add more logging here there is not enough
+lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(const SymbolContext &sc,
+                                                       const DWARFDIE &die,
+                                                       bool *type_is_new_ptr) {
+  TypeSP type_sp;
+  if (type_is_new_ptr)
+    *type_is_new_ptr = false;
+
+  Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups);
+
+  if (die) {
+    SymbolFileDWARF *dwarf = die.GetDWARF();
+    if (log) {
+      dwarf->GetObjectFile()->GetModule()->LogMessage(
+          log,
+          "DWARFASTParserFortran::ParseTypeFromDWARF (die = 0x%8.8x) %s name"
+          "= "
+          "'%s')",
+          die.GetOffset(), plugin::dwarf::DW_TAG_value_to_name(die.Tag()),
+          die.GetName());
+    }
+    Type *type_ptr = dwarf->GetDIEToType().lookup(die.GetDIE());
+    if (!type_ptr) {
+      if (type_is_new_ptr)
+        *type_is_new_ptr = true;
+
+      const dw_tag_t tag = die.Tag();
+      ConstString type_name;
+      const char *type_name_cstr = nullptr;
+      CompilerType compiler_type;
+      DWARFAttributes attributes;
+      DWARFFormValue form_value;
+      Declaration decl;
+      uint32_t encoding = 0;
+      switch (tag) {
+      case DW_TAG_base_type: {
+        dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+        attributes = die.GetAttributes();
+        uint64_t bit_size = 0;
+        for (size_t idx = 0; idx < attributes.Size(); idx++) {
+          if (attributes.ExtractFormValueAtIndex(idx, form_value)) {
+            switch (attributes.AttributeAtIndex(idx)) {
+            case DW_AT_name:
+              type_name_cstr = form_value.AsCString();
+              if (type_name_cstr &&
+                  type_name_cstr[0]) { // Check for null AND empty string
+                type_name.SetString(llvm::StringRef(type_name_cstr).upper());
+              } else {
+                type_name.SetCString("UNKNOWN_FORTRAN_TYPE");
+              }
+              break;
+            case DW_AT_encoding:
+              encoding = form_value.Unsigned();
+              break;
+            case DW_AT_byte_size:
+              bit_size = form_value.Unsigned() * 8;
+              break;
+            case DW_AT_bit_size:
+              bit_size = form_value.Unsigned();
+              break;
+            default:
+              break;
+            }
+          }
+        }
+        compiler_type = m_ast.CreateType(encoding, bit_size, type_name);
+        type_sp =
+            dwarf->MakeType(die.GetID(), type_name, (bit_size + 7) / 8, nullptr,
+                            LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
+                            compiler_type, Type::ResolveState::Full);
+      } break;
+      case DW_TAG_subprogram:
+      case DW_TAG_subroutine_type: {
+        dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+        attributes = die.GetAttributes();
+        size_t num_attr = attributes.Size();
+        for (size_t i = 0; i < num_attr; ++i) {
+          if (attributes.ExtractFormValueAtIndex(i, form_value)) {
+            switch (attributes.AttributeAtIndex(i)) {
+            case DW_AT_name:
+              type_name_cstr = form_value.AsCString();
+              if (type_name_cstr &&
+                  type_name_cstr[0]) { // Check for null AND empty string
+                type_name.SetString(llvm::StringRef(type_name_cstr).upper());
+              } else {
+                type_name.SetCString("UNKNOWN_FORTRAN_FUNCTION");
+              }
+              break;
+            default:
+              break;
+            }
+          }
+        }
+        llvm::SmallVector<CompilerType, 4> function_params_types;
+        // TODO: Parse Parameters here, for now this is not supported
+        compiler_type =
+            m_ast.GetOrCreateFortranFunction(type_name, function_params_types);
+        type_sp = dwarf->MakeType(die.GetID(), type_name, 0, nullptr,
+                                  LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
+                                  compiler_type, Type::ResolveState::Full);
+      } break;
+      default:
+        break;
+      }
+      if (type_sp.get()) {
+        // TODO: Here calculate the variable scope
+        dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
+      }
+    } else if (type_ptr != DIE_IS_BEING_PARSED) {
+      type_sp = type_ptr->shared_from_this();
+    }
+  }
+  return type_sp;
 }
 
 lldb_private::Function *DWARFASTParserFortran::ParseFunctionFromDWARF(
     lldb_private::CompileUnit &comp_unit,
     const lldb_private::plugin::dwarf::DWARFDIE &die,
     lldb_private::AddressRanges ranges) {
-  // TODO
-}
+  if (die.Tag() != DW_TAG_subprogram)
+    return nullptr;
+  llvm::DWARFAddressRangesVector unused_func_ranges;
+  const char *name = nullptr;
+  const char *mangled = nullptr;
+  std::optional<int> decl_file = 0;
+  std::optional<int> decl_line = 0;
+  std::optional<int> decl_column = 0;
+  std::optional<int> call_file = 0;
+  std::optional<int> call_line = 0;
+  std::optional<int> call_column = 0;
+  DWARFExpressionList frame_base;
+  if (die.GetDIENamesAndRanges(name, mangled, unused_func_ranges, decl_file,
+                               decl_line, decl_column, call_file, call_line,
+                               call_column, &frame_base)) {
+    Mangled func_name;
+    // Mangled doesn't know how to demangle fortran names
+    if (mangled)
+      func_name.SetMangledName(ConstString(mangled));
+    if (name)
+      func_name.SetDemangledName(ConstString(name));
 
-bool DWARFASTParserFortran::CompleteTypeFromDWARF(
-    const lldb_private::plugin::dwarf::DWARFDIE &die, lldb_private::Type *type,
-    const lldb_private::CompilerType &compiler_type) {
-  // TODO
-  return false;
-}
+    FunctionSP func_sp;
+
+    SymbolFileDWARF *dwarf = die.GetDWARF();
+    // Supply the type _only_ if it has already been parsed
+    Type *func_type = dwarf->GetDIEToType().lookup(die.GetDIE());
+
+    assert(func_type == nullptr || func_type != DIE_IS_BEING_PARSED);
+
+    const user_id_t func_user_id = die.GetID();
+
+    Address func_addr = ranges[0].GetBaseAddress();
+
+    func_sp =
+        std::make_shared<Function>(&comp_unit,
+                                   func_user_id, // UserID is the DIE offset
+                                   func_user_id, func_name, func_type,
+                                   std::move(func_addr), std::move(ranges));
+
+    if (func_sp.get() != nullptr) {
+      if (frame_base.IsValid())
+        func_sp->GetFrameBaseExpression() = frame_base;
+      comp_unit.AddFunction(func_sp);
+      return func_sp.get();
+    }
+  }
+  return nullptr;
+}
\ No newline at end of file
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
index 6b26c798d190b..61fab284431c4 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
@@ -16,12 +16,13 @@
 namespace lldb_private {
 class CompileUnit;
 class ExecutionContext;
+class TypeSystemFortran;
 } // namespace lldb_private
 
 class DWARFASTParserFortran
     : public lldb_private::plugin::dwarf::DWARFASTParser {
 public:
-  DWARFASTParserFortran(lldb_private::TypeSystemFortran m_ast);
+  DWARFASTParserFortran(lldb_private::TypeSystemFortran &ast);
 
   ~DWARFASTParserFortran() override;
 
@@ -39,7 +40,8 @@ class DWARFASTParserFortran
       const lldb_private::plugin::dwarf::DWARFDIE &die,
       lldb_private::Type *type,
       const lldb_private::CompilerType &compiler_type) override;
-
+  
+  //TODO: The following functions are left intentionally blank and will be populated in a future patch
   lldb_private::ConstString ConstructDemangledNameFromDWARF(
       const lldb_private::plugin::dwarf::DWARFDIE &die) override {
     return lldb_private::ConstString();

>From 8ebb6891bd120964e83151e79db6752f53d16cd5 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Thu, 14 May 2026 23:53:22 +0300
Subject: [PATCH 07/44] [lldb][Fortran] Formatted files correctly

---
 .../SymbolFile/DWARF/DWARFASTParserFortran.cpp      |  2 +-
 .../SymbolFile/DWARF/DWARFASTParserFortran.h        |  5 +++--
 .../TypeSystem/Fortran/TypeSystemFortran.cpp        | 13 +++++++------
 .../Plugins/TypeSystem/Fortran/TypeSystemFortran.h  |  9 ++++-----
 4 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
index f3bf860b205ce..07d3ffbbc9d6c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
@@ -30,7 +30,7 @@ DWARFASTParserFortran::DWARFASTParserFortran(TypeSystemFortran &ast)
 
 DWARFASTParserFortran::~DWARFASTParserFortran() {}
 
-//TODO: Add more logging here there is not enough
+// TODO: Add more logging here there is not enough
 lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(const SymbolContext &sc,
                                                        const DWARFDIE &die,
                                                        bool *type_is_new_ptr) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
index 61fab284431c4..e98903f1c67cc 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
@@ -40,8 +40,9 @@ class DWARFASTParserFortran
       const lldb_private::plugin::dwarf::DWARFDIE &die,
       lldb_private::Type *type,
       const lldb_private::CompilerType &compiler_type) override;
-  
-  //TODO: The following functions are left intentionally blank and will be populated in a future patch
+
+  // TODO: The following functions are left intentionally blank and will be
+  // populated in a future patch
   lldb_private::ConstString ConstructDemangledNameFromDWARF(
       const lldb_private::plugin::dwarf::DWARFDIE &die) override {
     return lldb_private::ConstString();
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index 8431acc8929b1..558f5a34a1c62 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -63,7 +63,8 @@ class FortranFunction : public FortranType {
 };
 } // namespace lldb_private
 
-/// Used to determine if TypeSystem supports the language passed in CreateInstance
+/// Used to determine if TypeSystem supports the language passed in
+/// CreateInstance
 static bool IsLanguageSupported(LanguageType language) {
   if (language == LanguageType::eLanguageTypeFortran77 ||
       language == LanguageType::eLanguageTypeFortran90 ||
@@ -129,8 +130,8 @@ LanguageSet TypeSystemFortran::GetSupportedLanguagesForTypes() {
   return languages;
 }
 
-// FIXME: Currently returns all Fortran languages to satisfy plugin requirements,
-// but expression evaluation is not yet implemented.
+// FIXME: Currently returns all Fortran languages to satisfy plugin
+// requirements, but expression evaluation is not yet implemented.
 LanguageSet TypeSystemFortran::GetSupportedLanguagesForExpressions() {
   LanguageSet languages;
   languages.Insert(eLanguageTypeFortran77);
@@ -142,7 +143,7 @@ LanguageSet TypeSystemFortran::GetSupportedLanguagesForExpressions() {
   return languages;
 }
 
-//FIXME: Is support for all Fortran ISO the goal?
+// FIXME: Is support for all Fortran ISO the goal?
 bool TypeSystemFortran::SupportsLanguage(lldb::LanguageType language) {
   if (language == lldb::LanguageType::eLanguageTypeFortran77 ||
       language == lldb::LanguageType::eLanguageTypeFortran90 ||
@@ -155,7 +156,7 @@ bool TypeSystemFortran::SupportsLanguage(lldb::LanguageType language) {
   return false;
 }
 
-/// Returns the type assosciated with the kind and bitsize, or creates it 
+/// Returns the type assosciated with the kind and bitsize, or creates it
 /// if it is not in the map
 CompilerType TypeSystemFortran::GetOrCreateFortranType(int kind,
                                                        uint64_t bitsize,
@@ -171,7 +172,7 @@ CompilerType TypeSystemFortran::GetOrCreateFortranType(int kind,
   return CompilerType(weak_from_this(), (void *)raw_ptr);
 }
 
-/// Returns the type assosciated with the name, or creates it 
+/// Returns the type assosciated with the name, or creates it
 /// if it is not in the map
 CompilerType TypeSystemFortran::GetOrCreateFortranFunction(
     ConstString name, const SmallVectorImpl<CompilerType> &parameters) {
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index 1cd98d4b417eb..1447198228011 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -18,7 +18,7 @@ namespace lldb_private {
 class FortranType;
 
 /// A TypeSystem implementation for the Fortran language.
-/// 
+///
 /// This plugin provides LLDB with the ability to understand Fortran types
 /// parsed from debug information (DWARF).
 class TypeSystemFortran : public TypeSystem {
@@ -484,16 +484,15 @@ class TypeSystemFortran : public TypeSystem {
   }
 
 private:
-  
   typedef std::pair<int, uint64_t> TypeKey;
   typedef llvm::DenseMap<TypeKey, std::unique_ptr<FortranType>> TypeMap;
   typedef llvm::DenseMap<ConstString, std::unique_ptr<FortranType>> FunctionMap;
 
-  // TODO: Types are assosciated by their kind and bitsize, this helps to 
-  // return from their basic type and is enough for basic types but 
+  // TODO: Types are assosciated by their kind and bitsize, this helps to
+  // return from their basic type and is enough for basic types but
   // will change once more types are supported
   TypeMap m_type_map;
-  // Right now we can index functions just by their name, but a more 
+  // Right now we can index functions just by their name, but a more
   // effecient solution might replace this
   FunctionMap m_function_map;
   std::unique_ptr<plugin::dwarf::DWARFASTParser> m_dwarf_ast_parser_up;

>From e2e31311a1e995681b7d510b7680cfacb74a394c Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 15 May 2026 17:27:49 +0300
Subject: [PATCH 08/44] [lldb][Fortran] Readded missing file which caused
 linker errors

---
 lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
index e98903f1c67cc..ade018b277d8b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h
@@ -39,7 +39,9 @@ class DWARFASTParserFortran
   bool CompleteTypeFromDWARF(
       const lldb_private::plugin::dwarf::DWARFDIE &die,
       lldb_private::Type *type,
-      const lldb_private::CompilerType &compiler_type) override;
+      const lldb_private::CompilerType &compiler_type) override {
+    return false;
+  }
 
   // TODO: The following functions are left intentionally blank and will be
   // populated in a future patch

>From 54702db837eb24651527e62a1b9be2b63b4ae6f5 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 5 Jun 2026 19:23:27 +0300
Subject: [PATCH 09/44] [lldb] Added tests

---
 .../API/lang/fortran/frame-variable/Makefile  |  7 +++
 .../TestFortranFrameVariable.py               | 25 +++++++++++
 .../API/lang/fortran/frame-variable/frame.f90 | 15 +++++++
 lldb/test/API/lang/fortran/integer/Makefile   |  7 +++
 .../fortran/integer/TestFortranIntegers.py    | 45 +++++++++++++++++++
 .../API/lang/fortran/integer/integers.f90     | 16 +++++++
 lldb/test/API/lang/fortran/logical/Makefile   |  7 +++
 .../fortran/logical/TestFortranLogicals.py    | 45 +++++++++++++++++++
 .../test/API/lang/fortran/logical/logical.f90 | 17 +++++++
 lldb/test/API/lang/fortran/real/Makefile      |  7 +++
 .../API/lang/fortran/real/TestFortranReal.py  | 39 ++++++++++++++++
 lldb/test/API/lang/fortran/real/real.f90      | 14 ++++++
 12 files changed, 244 insertions(+)
 create mode 100644 lldb/test/API/lang/fortran/frame-variable/Makefile
 create mode 100644 lldb/test/API/lang/fortran/frame-variable/TestFortranFrameVariable.py
 create mode 100644 lldb/test/API/lang/fortran/frame-variable/frame.f90
 create mode 100644 lldb/test/API/lang/fortran/integer/Makefile
 create mode 100644 lldb/test/API/lang/fortran/integer/TestFortranIntegers.py
 create mode 100644 lldb/test/API/lang/fortran/integer/integers.f90
 create mode 100644 lldb/test/API/lang/fortran/logical/Makefile
 create mode 100644 lldb/test/API/lang/fortran/logical/TestFortranLogicals.py
 create mode 100644 lldb/test/API/lang/fortran/logical/logical.f90
 create mode 100644 lldb/test/API/lang/fortran/real/Makefile
 create mode 100644 lldb/test/API/lang/fortran/real/TestFortranReal.py
 create mode 100644 lldb/test/API/lang/fortran/real/real.f90

diff --git a/lldb/test/API/lang/fortran/frame-variable/Makefile b/lldb/test/API/lang/fortran/frame-variable/Makefile
new file mode 100644
index 0000000000000..15d13e4a001fe
--- /dev/null
+++ b/lldb/test/API/lang/fortran/frame-variable/Makefile
@@ -0,0 +1,7 @@
+FC ?= flang
+FFLAGS ?= -g -O0
+
+a.out: frame.f90
+	$(FC) $(FFLAGS) frame.f90 -o a.out
+
+include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/frame-variable/TestFortranFrameVariable.py b/lldb/test/API/lang/fortran/frame-variable/TestFortranFrameVariable.py
new file mode 100644
index 0000000000000..db8006e7f1e94
--- /dev/null
+++ b/lldb/test/API/lang/fortran/frame-variable/TestFortranFrameVariable.py
@@ -0,0 +1,25 @@
+"""
+Tests that the frame variable command works 
+"""
+
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+
+
+class FortranTestFrameVariable(TestBase):
+
+    def test_fortran_frame_variable(self):
+        """Tests if frame variable outputs the expected results"""
+        self.build()
+        self.main_source_file = lldb.SBFileSpec("frame.f90")
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "! Breakpoint here", self.main_source_file
+        )
+
+        self.expect("frame variable num_int", substrs=["(INTEGER) num_int = 152"])
+
+        self.expect("frame variable num_real", substrs=["(REAL) num_real = 2.718"])
+
+        self.expect("frame variable num_logical", substrs=["(LOGICAL) num_logical = true"])
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/frame-variable/frame.f90 b/lldb/test/API/lang/fortran/frame-variable/frame.f90
new file mode 100644
index 0000000000000..1bfc3974ddaa7
--- /dev/null
+++ b/lldb/test/API/lang/fortran/frame-variable/frame.f90
@@ -0,0 +1,15 @@
+program frameVariable
+  implicit none
+
+  real  :: num_real
+  integer :: num_int
+  logical :: num_logical
+
+
+  num_int    = 152
+  num_real   = 2.718281828459045
+  num_logical = .TRUE.
+
+  print *, "Done" ! Breakpoint here
+
+end program frameVariable
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/integer/Makefile b/lldb/test/API/lang/fortran/integer/Makefile
new file mode 100644
index 0000000000000..3c510456ab82e
--- /dev/null
+++ b/lldb/test/API/lang/fortran/integer/Makefile
@@ -0,0 +1,7 @@
+FC ?= flang
+FFLAGS ?= -g -O0
+
+a.out: integers.f90
+	$(FC) $(FFLAGS) integers.f90 -o a.out
+
+include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/integer/TestFortranIntegers.py b/lldb/test/API/lang/fortran/integer/TestFortranIntegers.py
new file mode 100644
index 0000000000000..1175506f71fe3
--- /dev/null
+++ b/lldb/test/API/lang/fortran/integer/TestFortranIntegers.py
@@ -0,0 +1,45 @@
+"""
+Tests that the integer intrinsic type with different byte sizes works as expected 
+"""
+
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+
+
+class FortranTestIntegers(TestBase):
+
+    def test_fortran_integers(self):
+        """Tests if integers return the correct name, kind and value."""
+        self.build()
+        self.main_source_file = lldb.SBFileSpec("integers.f90")
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "! Breakpoint here", self.main_source_file
+        )
+
+        frame = thread.GetFrameAtIndex(0)
+
+        tiny_int = frame.FindVariable("tiny_int")
+        self.assertSuccess(tiny_int.GetError(), "Failed to fetch tiny_int")
+        self.assertEqual(tiny_int.GetTypeName(), "INTEGER(KIND=1)")
+        self.assertEqual(tiny_int.GetByteSize(), 1)
+        self.assertEqual(tiny_int.GetValueAsSigned(), 127)
+
+        short_int = frame.FindVariable("short_int")
+        self.assertSuccess(short_int.GetError(), "Failed to fetch short_int")
+        self.assertEqual(tiny_int.GetTypeName(), "INTEGER(KIND=2)")
+        self.assertEqual(short_int.GetByteSize(), 2)
+        self.assertEqual(short_int.GetValueAsSigned(), 32767)
+        
+        normal_int = frame.FindVariable("normal_int")
+        self.assertSuccess(normal_int.GetError(), "Failed to fetch normal_int")
+        self.assertEqual(tiny_int.GetTypeName(), "INTEGER")
+        self.assertEqual(normal_int.GetByteSize(), 4)
+        self.assertEqual(normal_int.GetValueAsSigned(), 2147483647)
+
+        huge_int = frame.FindVariable("huge_int")
+        self.assertSuccess(huge_int.GetError(), "Failed to fetch huge_int")
+        self.assertEqual(tiny_int.GetTypeName(), "INTEGER(KIND=8)")
+        self.assertEqual(huge_int.GetByteSize(), 8)
+        self.assertEqual(huge_int.GetValueAsSigned(), 9223372036854775807)
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/integer/integers.f90 b/lldb/test/API/lang/fortran/integer/integers.f90
new file mode 100644
index 0000000000000..bf03c529160a3
--- /dev/null
+++ b/lldb/test/API/lang/fortran/integer/integers.f90
@@ -0,0 +1,16 @@
+program integer_kinds
+    implicit none
+
+    integer(1) :: tiny_int
+    integer(2) :: short_int
+    integer(4) :: normal_int
+    integer(8) :: huge_int
+
+    tiny_int   = 127
+    short_int  = 32767
+    normal_int = 2147483647
+    huge_int   = 9223372036854775807_8 
+
+    print *, "Done" ! Breakpoint here
+
+end program integer_kinds
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/logical/Makefile b/lldb/test/API/lang/fortran/logical/Makefile
new file mode 100644
index 0000000000000..0179c41bc5203
--- /dev/null
+++ b/lldb/test/API/lang/fortran/logical/Makefile
@@ -0,0 +1,7 @@
+FC ?= flang
+FFLAGS ?= -g -O0
+
+a.out: logical.f90
+	$(FC) $(FFLAGS) logical.f90 -o a.out
+
+include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/logical/TestFortranLogicals.py b/lldb/test/API/lang/fortran/logical/TestFortranLogicals.py
new file mode 100644
index 0000000000000..0389abf241298
--- /dev/null
+++ b/lldb/test/API/lang/fortran/logical/TestFortranLogicals.py
@@ -0,0 +1,45 @@
+"""
+Tests that the logical intrinsic type with different byte sizes works as expected 
+"""
+
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+
+
+class FortranTestLogicals(TestBase):
+
+    def test_fortran_logicals(self):
+        """Tests if logicals return the correct name, kind and value."""
+        self.build()
+        self.main_source_file = lldb.SBFileSpec("logical.f90")
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "! Breakpoint here", self.main_source_file
+        )
+
+        frame = thread.GetFrameAtIndex(0)
+
+        bool_one = frame.FindVariable("bool_one")
+        self.assertSuccess(bool_one.GetError(), "Failed to fetch bool_one")
+        self.assertEqual(bool_one.GetTypeName(), "LOGICAL")
+        self.assertEqual(bool_one.GetByteSize(), 1)
+        self.assertEqual(bool_one.GetValue(), "true")
+
+        bool_two = frame.FindVariable("bool_two")
+        self.assertSuccess(bool_two.GetError(), "Failed to fetch bool_two")
+        self.assertEqual(bool_two.GetTypeName(), "LOGICAL")
+        self.assertEqual(bool_two.GetByteSize(), 2)
+        self.assertEqual(bool_two.GetValue(), "false")
+        
+        bool_four = frame.FindVariable("bool_four")
+        self.assertSuccess(bool_four.GetError(), "Failed to fetch bool_four")
+        self.assertEqual(bool_four.GetTypeName(), "LOGICAL")
+        self.assertEqual(bool_four.GetByteSize(), 4)
+        self.assertEqual(bool_four.GetValue(), "true")
+
+        bool_eight = frame.FindVariable("bool_eight")
+        self.assertSuccess(bool_eight.GetError(), "Failed to fetch bool_eight")
+        self.assertEqual(bool_eight.GetTypeName(), "LOGICAL")
+        self.assertEqual(bool_eight.GetByteSize(), 8)
+        self.assertEqual(bool_eight.GetValue(), "false")
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/logical/logical.f90 b/lldb/test/API/lang/fortran/logical/logical.f90
new file mode 100644
index 0000000000000..3ad72b03bfc94
--- /dev/null
+++ b/lldb/test/API/lang/fortran/logical/logical.f90
@@ -0,0 +1,17 @@
+program logical_kinds
+    implicit none
+
+    logical(1) :: bool_one
+    logical(2) :: bool_two
+    logical(4) :: bool_four
+    logical(8) :: bool_eight
+
+
+    bool_one   = .true.
+    bool_two   = .false.
+    bool_four  = .true.
+    bool_eight = .false.
+
+    print *, "Done" ! Breakpoint here
+
+end program logical_kinds
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/real/Makefile b/lldb/test/API/lang/fortran/real/Makefile
new file mode 100644
index 0000000000000..d800f0d663d30
--- /dev/null
+++ b/lldb/test/API/lang/fortran/real/Makefile
@@ -0,0 +1,7 @@
+FC ?= flang
+FFLAGS ?= -g -O0
+
+a.out: real.f90
+	$(FC) $(FFLAGS) real.f90 -o a.out
+
+include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/real/TestFortranReal.py b/lldb/test/API/lang/fortran/real/TestFortranReal.py
new file mode 100644
index 0000000000000..58198f2c4e9d6
--- /dev/null
+++ b/lldb/test/API/lang/fortran/real/TestFortranReal.py
@@ -0,0 +1,39 @@
+"""
+Tests that the real intrinsic type with different byte sizes works as expected 
+"""
+
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+
+
+class FortranTestReal(TestBase):
+
+    def test_fortran_real(self):
+        """Tests if Real type return the correct name, kind and value."""
+        self.build()
+        self.main_source_file = lldb.SBFileSpec("real.f90")
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "! Breakpoint here", self.main_source_file
+        )
+
+        frame = thread.GetFrameAtIndex(0)
+        
+        float_four = frame.FindVariable("float_four")
+        self.assertSuccess(float_four.GetError(), "Failed to fetch float_four")
+        self.assertEqual(float_four.GetTypeName(), "REAL")
+        self.assertEqual(float_four.GetByteSize(), 4)
+        self.assertTrue(float_four.GetValue().startswith("3.14"), "float_four value is correct")
+
+        float_eight = frame.FindVariable("float_eight")
+        self.assertSuccess(float_eight.GetError(), "Failed to fetch float_eight")
+        self.assertEqual(float_four.GetTypeName(), "DOUBLE PRECISION")
+        self.assertEqual(float_eight.GetByteSize(), 8)
+        self.assertTrue(float_eight.GetValue().startswith("2.718"), "float_eight value is correct")
+
+        float_sixteen = frame.FindVariable("float_sixteen")
+        self.assertSuccess(float_sixteen.GetError(), "Failed to fetch float_sixteen")
+        self.assertEqual(float_four.GetTypeName(), "REAL(KIND=16)")
+        self.assertEqual(float_sixteen.GetByteSize(), 16)
+        self.assertTrue(float_sixteen.GetValue().startswith("1.618"), "float_sixteen value is correct")
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/real/real.f90 b/lldb/test/API/lang/fortran/real/real.f90
new file mode 100644
index 0000000000000..bea21d4bb984a
--- /dev/null
+++ b/lldb/test/API/lang/fortran/real/real.f90
@@ -0,0 +1,14 @@
+program real_kinds
+    implicit none
+
+    real(4)  :: float_four
+    real(8)  :: float_eight
+    real(16) :: float_sixteen
+
+    float_four    = 3.1415926_4
+    float_eight   = 2.718281828459045_8
+    float_sixteen = 1.618033988749894848204586834365638_16
+
+    print *, "Done" ! Breakpoint here
+
+end program real_kinds
\ No newline at end of file

>From 29afc77ea7bd802ec6214161808b74006fcb812e Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Mon, 8 Jun 2026 23:58:20 +0300
Subject: [PATCH 10/44] [lldb][Fortran] Fixed Type name to be consistent across
 gfortran and Flang

---
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 26 +++++++------------
 .../TypeSystem/Fortran/TypeSystemFortran.h    |  2 +-
 2 files changed, 11 insertions(+), 17 deletions(-)

diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index 558f5a34a1c62..5c2cc36bac648 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -192,12 +192,18 @@ CompilerType TypeSystemFortran::CreateType(uint32_t kind, uint64_t bitsize,
   int underlying_kind;
   switch (kind) {
   case dwarf::DW_ATE_boolean:
+    if (bitsize == 32)
+      name.SetCString("LOGICAL");
     underlying_kind = FortranType::KIND_LOGICAL;
     break;
   case dwarf::DW_ATE_float:
+    if (bitsize == 32)
+      name.SetCString("REAL");
     underlying_kind = FortranType::KIND_REAL;
     break;
   case dwarf::DW_ATE_signed:
+    if (bitsize == 32)
+      name.SetCString("INTEGER");
     underlying_kind = FortranType::KIND_INTEGER;
     break;
   default:
@@ -212,26 +218,14 @@ ConstString TypeSystemFortran::GetTypeName(opaque_compiler_type_t type,
   if (!type)
     return ConstString();
   FortranType *fortran_type = static_cast<FortranType *>(type);
-  uint64_t bytes = fortran_type->GetBitSize() / 8;
-  if (BaseOnly)
-    return fortran_type->GetName();
   switch (fortran_type->GetKind()) {
   case FortranType::KIND_INTEGER:
-    if (fortran_type->GetBitSize() != 32)
-      return ConstString(formatv("INTEGER(KIND={0})", bytes).str());
-    else
-      return fortran_type->GetName();
-    break;
   case FortranType::KIND_LOGICAL:
-    return fortran_type->GetName();
   case FortranType::KIND_REAL:
-    if (bytes == 4)
-      return ConstString("REAL");
-    if (bytes == 8)
-      return ConstString("DOUBLE PRECISION");
-    return ConstString(formatv("REAL(KIND={0})", bytes).str());
+    return fortran_type->GetName();
+  default:
+    return ConstString("Unsupported");
   }
-  return ConstString("Unsupported");
 }
 
 CompilerType TypeSystemFortran::GetBasicTypeFromAST(BasicType basic_type) {
@@ -244,7 +238,7 @@ CompilerType TypeSystemFortran::GetBasicTypeFromAST(BasicType basic_type) {
                                   ConstString("REAL"));
   case eBasicTypeDouble:
     return GetOrCreateFortranType(FortranType::KIND_REAL, 64,
-                                  ConstString("DOUBLE PRECISION"));
+                                  ConstString("REAL(KIND=8)"));
   case eBasicTypeBool:
     return GetOrCreateFortranType(FortranType::KIND_LOGICAL, 32,
                                   ConstString("LOGICAL"));
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index 1447198228011..3350a0bb52e87 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -88,7 +88,7 @@ class TypeSystemFortran : public TypeSystem {
 #ifndef NDEBUG
   /// Verify the integrity of the type to catch CompilerTypes that mix
   /// and match invalid TypeSystem/Opaque type pairs.
-  bool Verify(lldb::opaque_compiler_type_t type) { return false; };
+  bool Verify(lldb::opaque_compiler_type_t type) override { return true; }
 #endif
 
   // Type Classification

>From a86017fc7344f3e05183b1a9725c2a7b8c46d417 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Tue, 9 Jun 2026 00:01:07 +0300
Subject: [PATCH 11/44] [lldb][Fortran] Bug fixes in API tests

---
 lldb/test/API/lang/fortran/frame-variable/Makefile     |  4 ++--
 lldb/test/API/lang/fortran/integer/Makefile            |  4 ++--
 .../API/lang/fortran/integer/TestFortranIntegers.py    |  6 +++---
 lldb/test/API/lang/fortran/logical/Makefile            |  2 +-
 .../API/lang/fortran/logical/TestFortranLogicals.py    |  6 +++---
 lldb/test/API/lang/fortran/real/Makefile               |  2 +-
 lldb/test/API/lang/fortran/real/TestFortranReal.py     | 10 ++--------
 lldb/test/API/lang/fortran/real/real.f90               |  2 --
 8 files changed, 14 insertions(+), 22 deletions(-)

diff --git a/lldb/test/API/lang/fortran/frame-variable/Makefile b/lldb/test/API/lang/fortran/frame-variable/Makefile
index 15d13e4a001fe..811ee301696fe 100644
--- a/lldb/test/API/lang/fortran/frame-variable/Makefile
+++ b/lldb/test/API/lang/fortran/frame-variable/Makefile
@@ -2,6 +2,6 @@ FC ?= flang
 FFLAGS ?= -g -O0
 
 a.out: frame.f90
-	$(FC) $(FFLAGS) frame.f90 -o a.out
-
+	$(FC) $(FFLAGS) $< -o a.out
+	
 include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/integer/Makefile b/lldb/test/API/lang/fortran/integer/Makefile
index 3c510456ab82e..c99e38286265d 100644
--- a/lldb/test/API/lang/fortran/integer/Makefile
+++ b/lldb/test/API/lang/fortran/integer/Makefile
@@ -2,6 +2,6 @@ FC ?= flang
 FFLAGS ?= -g -O0
 
 a.out: integers.f90
-	$(FC) $(FFLAGS) integers.f90 -o a.out
-
+	$(FC) $(FFLAGS) $< -o a.out
+	
 include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/integer/TestFortranIntegers.py b/lldb/test/API/lang/fortran/integer/TestFortranIntegers.py
index 1175506f71fe3..6506b400f3fb2 100644
--- a/lldb/test/API/lang/fortran/integer/TestFortranIntegers.py
+++ b/lldb/test/API/lang/fortran/integer/TestFortranIntegers.py
@@ -28,18 +28,18 @@ def test_fortran_integers(self):
 
         short_int = frame.FindVariable("short_int")
         self.assertSuccess(short_int.GetError(), "Failed to fetch short_int")
-        self.assertEqual(tiny_int.GetTypeName(), "INTEGER(KIND=2)")
+        self.assertEqual(short_int.GetTypeName(), "INTEGER(KIND=2)")
         self.assertEqual(short_int.GetByteSize(), 2)
         self.assertEqual(short_int.GetValueAsSigned(), 32767)
         
         normal_int = frame.FindVariable("normal_int")
         self.assertSuccess(normal_int.GetError(), "Failed to fetch normal_int")
-        self.assertEqual(tiny_int.GetTypeName(), "INTEGER")
+        self.assertEqual(normal_int.GetTypeName(), "INTEGER")
         self.assertEqual(normal_int.GetByteSize(), 4)
         self.assertEqual(normal_int.GetValueAsSigned(), 2147483647)
 
         huge_int = frame.FindVariable("huge_int")
         self.assertSuccess(huge_int.GetError(), "Failed to fetch huge_int")
-        self.assertEqual(tiny_int.GetTypeName(), "INTEGER(KIND=8)")
+        self.assertEqual(huge_int.GetTypeName(), "INTEGER(KIND=8)")
         self.assertEqual(huge_int.GetByteSize(), 8)
         self.assertEqual(huge_int.GetValueAsSigned(), 9223372036854775807)
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/logical/Makefile b/lldb/test/API/lang/fortran/logical/Makefile
index 0179c41bc5203..700aeafeceb10 100644
--- a/lldb/test/API/lang/fortran/logical/Makefile
+++ b/lldb/test/API/lang/fortran/logical/Makefile
@@ -2,6 +2,6 @@ FC ?= flang
 FFLAGS ?= -g -O0
 
 a.out: logical.f90
-	$(FC) $(FFLAGS) logical.f90 -o a.out
+	$(FC) $(FFLAGS) $< -o a.out
 
 include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/logical/TestFortranLogicals.py b/lldb/test/API/lang/fortran/logical/TestFortranLogicals.py
index 0389abf241298..fa46b919fa99b 100644
--- a/lldb/test/API/lang/fortran/logical/TestFortranLogicals.py
+++ b/lldb/test/API/lang/fortran/logical/TestFortranLogicals.py
@@ -22,13 +22,13 @@ def test_fortran_logicals(self):
 
         bool_one = frame.FindVariable("bool_one")
         self.assertSuccess(bool_one.GetError(), "Failed to fetch bool_one")
-        self.assertEqual(bool_one.GetTypeName(), "LOGICAL")
+        self.assertEqual(bool_one.GetTypeName(), "LOGICAL(KIND=1)")
         self.assertEqual(bool_one.GetByteSize(), 1)
         self.assertEqual(bool_one.GetValue(), "true")
 
         bool_two = frame.FindVariable("bool_two")
         self.assertSuccess(bool_two.GetError(), "Failed to fetch bool_two")
-        self.assertEqual(bool_two.GetTypeName(), "LOGICAL")
+        self.assertEqual(bool_two.GetTypeName(), "LOGICAL(KIND=2)")
         self.assertEqual(bool_two.GetByteSize(), 2)
         self.assertEqual(bool_two.GetValue(), "false")
         
@@ -40,6 +40,6 @@ def test_fortran_logicals(self):
 
         bool_eight = frame.FindVariable("bool_eight")
         self.assertSuccess(bool_eight.GetError(), "Failed to fetch bool_eight")
-        self.assertEqual(bool_eight.GetTypeName(), "LOGICAL")
+        self.assertEqual(bool_eight.GetTypeName(), "LOGICAL(KIND=8)")
         self.assertEqual(bool_eight.GetByteSize(), 8)
         self.assertEqual(bool_eight.GetValue(), "false")
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/real/Makefile b/lldb/test/API/lang/fortran/real/Makefile
index d800f0d663d30..1ec2629dc2841 100644
--- a/lldb/test/API/lang/fortran/real/Makefile
+++ b/lldb/test/API/lang/fortran/real/Makefile
@@ -2,6 +2,6 @@ FC ?= flang
 FFLAGS ?= -g -O0
 
 a.out: real.f90
-	$(FC) $(FFLAGS) real.f90 -o a.out
+	$(FC) $(FFLAGS) $< -o a.out
 
 include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/real/TestFortranReal.py b/lldb/test/API/lang/fortran/real/TestFortranReal.py
index 58198f2c4e9d6..11ab2e70e5eb6 100644
--- a/lldb/test/API/lang/fortran/real/TestFortranReal.py
+++ b/lldb/test/API/lang/fortran/real/TestFortranReal.py
@@ -28,12 +28,6 @@ def test_fortran_real(self):
 
         float_eight = frame.FindVariable("float_eight")
         self.assertSuccess(float_eight.GetError(), "Failed to fetch float_eight")
-        self.assertEqual(float_four.GetTypeName(), "DOUBLE PRECISION")
+        self.assertEqual(float_eight.GetTypeName(), "REAL(KIND=8)")
         self.assertEqual(float_eight.GetByteSize(), 8)
-        self.assertTrue(float_eight.GetValue().startswith("2.718"), "float_eight value is correct")
-
-        float_sixteen = frame.FindVariable("float_sixteen")
-        self.assertSuccess(float_sixteen.GetError(), "Failed to fetch float_sixteen")
-        self.assertEqual(float_four.GetTypeName(), "REAL(KIND=16)")
-        self.assertEqual(float_sixteen.GetByteSize(), 16)
-        self.assertTrue(float_sixteen.GetValue().startswith("1.618"), "float_sixteen value is correct")
\ No newline at end of file
+        self.assertTrue(float_eight.GetValue().startswith("2.718"), "float_eight value is correct")
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/real/real.f90 b/lldb/test/API/lang/fortran/real/real.f90
index bea21d4bb984a..87b279a4f5777 100644
--- a/lldb/test/API/lang/fortran/real/real.f90
+++ b/lldb/test/API/lang/fortran/real/real.f90
@@ -3,11 +3,9 @@ program real_kinds
 
     real(4)  :: float_four
     real(8)  :: float_eight
-    real(16) :: float_sixteen
 
     float_four    = 3.1415926_4
     float_eight   = 2.718281828459045_8
-    float_sixteen = 1.618033988749894848204586834365638_16
 
     print *, "Done" ! Breakpoint here
 

>From 069b8b7869a471c7284ad9cb5a8d8ae22d85212c Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Tue, 9 Jun 2026 15:11:19 +0300
Subject: [PATCH 12/44] [lldb][Fortran] Added plugin registration tests for
 Fortran

---
 lldb/unittests/Language/CMakeLists.txt        |  1 +
 .../unittests/Language/Fortran/CMakeLists.txt |  6 ++++
 .../Language/Fortran/FortranLanguageTest.cpp  | 36 +++++++++++++++++++
 3 files changed, 43 insertions(+)
 create mode 100644 lldb/unittests/Language/Fortran/CMakeLists.txt
 create mode 100644 lldb/unittests/Language/Fortran/FortranLanguageTest.cpp

diff --git a/lldb/unittests/Language/CMakeLists.txt b/lldb/unittests/Language/CMakeLists.txt
index a0bdc62af98c6..26710ff8896e2 100644
--- a/lldb/unittests/Language/CMakeLists.txt
+++ b/lldb/unittests/Language/CMakeLists.txt
@@ -1,3 +1,4 @@
 add_subdirectory(CPlusPlus)
 add_subdirectory(CLanguages)
 add_subdirectory(ObjC)
+add_subdirectory(Fortran)
diff --git a/lldb/unittests/Language/Fortran/CMakeLists.txt b/lldb/unittests/Language/Fortran/CMakeLists.txt
new file mode 100644
index 0000000000000..661b12ebf8950
--- /dev/null
+++ b/lldb/unittests/Language/Fortran/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_lldb_unittest(LanguageFortranLanguageTests
+  FortranLanguageTest.cpp
+
+  LINK_LIBS
+    lldbPluginFortranLanguage
+)
diff --git a/lldb/unittests/Language/Fortran/FortranLanguageTest.cpp b/lldb/unittests/Language/Fortran/FortranLanguageTest.cpp
new file mode 100644
index 0000000000000..0b5e9b9e43818
--- /dev/null
+++ b/lldb/unittests/Language/Fortran/FortranLanguageTest.cpp
@@ -0,0 +1,36 @@
+//===-- FortranLanguagesTest.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/Language/Fortran/FortranLanguage.h"
+#include "TestingSupport/SubsystemRAII.h"
+#include "lldb/lldb-enumerations.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+
+/// Returns the name of the LLDB plugin for the given language or an empty
+/// string if there is no fitting plugin.
+static llvm::StringRef GetPluginName(lldb::LanguageType language) {
+  Language *language_plugin = Language::FindPlugin(language);
+  if (language_plugin)
+    return language_plugin->GetPluginName();
+  return "";
+}
+
+TEST(FortranLanguage, LookupFortranLanguageByLanguageType) {
+  SubsystemRAII<FortranLanguage> langs;
+
+  EXPECT_EQ(GetPluginName(lldb::eLanguageTypeFortran77), "fortran");
+  EXPECT_EQ(GetPluginName(lldb::eLanguageTypeFortran90), "fortran");
+  EXPECT_EQ(GetPluginName(lldb::eLanguageTypeFortran95), "fortran");
+  EXPECT_EQ(GetPluginName(lldb::eLanguageTypeFortran03), "fortran");
+  EXPECT_EQ(GetPluginName(lldb::eLanguageTypeFortran08), "fortran");
+  EXPECT_EQ(GetPluginName(lldb::eLanguageTypeFortran18), "fortran");
+}

>From 5cb0b7327750e29971dc8e3b9a76e4809c49f158 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Tue, 9 Jun 2026 16:52:03 +0300
Subject: [PATCH 13/44] [lldb][Fortran] Added lit cfg file to check for
 available fortran compiler

---
 .../API/lang/fortran/frame-variable/Makefile  |  1 -
 lldb/test/API/lang/fortran/integer/Makefile   |  1 -
 lldb/test/API/lang/fortran/lit.local.cfg      | 27 +++++++++++++++++++
 lldb/test/API/lang/fortran/logical/Makefile   |  1 -
 lldb/test/API/lang/fortran/real/Makefile      |  1 -
 5 files changed, 27 insertions(+), 4 deletions(-)
 create mode 100644 lldb/test/API/lang/fortran/lit.local.cfg

diff --git a/lldb/test/API/lang/fortran/frame-variable/Makefile b/lldb/test/API/lang/fortran/frame-variable/Makefile
index 811ee301696fe..076fb85bca4cb 100644
--- a/lldb/test/API/lang/fortran/frame-variable/Makefile
+++ b/lldb/test/API/lang/fortran/frame-variable/Makefile
@@ -1,4 +1,3 @@
-FC ?= flang
 FFLAGS ?= -g -O0
 
 a.out: frame.f90
diff --git a/lldb/test/API/lang/fortran/integer/Makefile b/lldb/test/API/lang/fortran/integer/Makefile
index c99e38286265d..21f67078a1557 100644
--- a/lldb/test/API/lang/fortran/integer/Makefile
+++ b/lldb/test/API/lang/fortran/integer/Makefile
@@ -1,4 +1,3 @@
-FC ?= flang
 FFLAGS ?= -g -O0
 
 a.out: integers.f90
diff --git a/lldb/test/API/lang/fortran/lit.local.cfg b/lldb/test/API/lang/fortran/lit.local.cfg
new file mode 100644
index 0000000000000..1fd3d154c5e05
--- /dev/null
+++ b/lldb/test/API/lang/fortran/lit.local.cfg
@@ -0,0 +1,27 @@
+import lit.util
+
+fc_executable = config.environment.get('FC')
+
+fallback_compilers = [ 
+    'flang-new',
+    'flang', 
+    'gfortran'
+]
+
+if not fc_executable:
+    for compiler in fallback_compilers:
+        fc_executable = lit.util.which(compiler, config.llvm_tools_dir)
+        if fc_executable:
+            break
+                
+        fc_executable = lit.util.which(compiler, config.environment.get('PATH'))
+        if fc_executable:
+            break
+
+if fc_executable:
+    config.environment['FC'] = fc_executable
+    config.substitutions.append(('%FC', fc_executable))
+    config.available_features.add('fortran')
+
+else:
+    config.unsupported = True
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/logical/Makefile b/lldb/test/API/lang/fortran/logical/Makefile
index 700aeafeceb10..126ce47d0d772 100644
--- a/lldb/test/API/lang/fortran/logical/Makefile
+++ b/lldb/test/API/lang/fortran/logical/Makefile
@@ -1,4 +1,3 @@
-FC ?= flang
 FFLAGS ?= -g -O0
 
 a.out: logical.f90
diff --git a/lldb/test/API/lang/fortran/real/Makefile b/lldb/test/API/lang/fortran/real/Makefile
index 1ec2629dc2841..8cbb245f95cfc 100644
--- a/lldb/test/API/lang/fortran/real/Makefile
+++ b/lldb/test/API/lang/fortran/real/Makefile
@@ -1,4 +1,3 @@
-FC ?= flang
 FFLAGS ?= -g -O0
 
 a.out: real.f90

>From 020f20e84a0ebcd77a5c4d1af7800a8cc29ba85e Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 26 Jun 2026 20:01:29 +0300
Subject: [PATCH 14/44] [lldb]Added case-insensitive support

---
 lldb/include/lldb/Symbol/CompileUnit.h        | 10 +++++
 lldb/include/lldb/lldb-enumerations.h         | 15 +++++++
 .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp    | 32 ++++++++++++++
 .../Plugins/SymbolFile/DWARF/DWARFUnit.h      |  3 ++
 .../SymbolFile/DWARF/ManualDWARFIndex.cpp     |  5 +++
 .../SymbolFile/DWARF/ManualDWARFIndex.h       | 11 +++++
 .../Plugins/SymbolFile/DWARF/NameToDIE.cpp    | 14 +++++++
 .../Plugins/SymbolFile/DWARF/NameToDIE.h      |  3 ++
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      |  9 ++--
 lldb/source/ValueObject/DILEval.cpp           | 42 +++++++++++++++----
 10 files changed, 134 insertions(+), 10 deletions(-)

diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h
index bb9594699df33..7d99bd16ae02d 100644
--- a/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/lldb/include/lldb/Symbol/CompileUnit.h
@@ -152,6 +152,14 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
     m_language = language;
   }
 
+  lldb::IdentifierCaseType GetCasing() {
+    return m_identifier_case;
+  }
+
+  void SetCasing(lldb::IdentifierCaseType identifier_case){
+    m_identifier_case = identifier_case;
+  }
+
   void GetDescription(Stream *s, lldb::DescriptionLevel level) const;
 
   /// Apply a lambda to each function in this compile unit.
@@ -422,6 +430,8 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
   void *m_user_data;
   /// The programming language enumeration value.
   lldb::LanguageType m_language;
+  /// Used to determine if lookups should be case-insensitive
+  lldb::IdentifierCaseType m_identifier_case = lldb::eCaseSensitive;
   /// Compile unit flags that help with partial parsing.
   Flags m_flags;
   /// Maps UIDs to functions.
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 32a341b354d9f..4c0d2c27a8745 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -631,6 +631,21 @@ enum LanguageType {
   eNumLanguageTypes
 };
 
+//----------------------------------------------------------------------
+/// Identifier Case type
+///
+/// this enumeration indetifies the treatment of identifiers within
+/// compilation unit. the default is case sensitive in case it is absent
+/// in compilation unit.
+//----------------------------------------------------------------------
+enum IdentifierCaseType {
+  eCaseSensitive = 0,
+  eUpperCase = 1,
+  eLowerCase = 2,
+  eCaseInsensitive = 3,
+  eCaseUnknown = 4,
+};
+
 enum InstrumentationRuntimeType {
   eInstrumentationRuntimeTypeAddressSanitizer = 0x0000,
   eInstrumentationRuntimeTypeThreadSanitizer = 0x0001,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 4b02124e987e8..7fbef4a831ff1 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -888,6 +888,38 @@ llvm::VersionTuple DWARFUnit::GetProducerVersion() {
   return m_producer_version;
 }
 
+lldb::IdentifierCaseType DWARFUnit::GetIdentifierCase() {
+  if(m_identifier_case != eCaseUnknown)
+    return m_identifier_case;
+
+  const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
+
+  if(!die) 
+    m_identifier_case = eCaseSensitive;
+    
+  else {
+    uint64_t identifier_case = die->GetAttributeValueAsUnsigned(this, DW_AT_identifier_case, llvm::dwarf::DW_ID_case_sensitive);
+
+    switch (identifier_case) {
+      case llvm::dwarf::DW_ID_up_case:
+        m_identifier_case = eUpperCase;
+        break;
+      case llvm::dwarf::DW_ID_down_case:
+        m_identifier_case = eLowerCase;
+        break;
+      case llvm::dwarf::DW_ID_case_insensitive:
+        m_identifier_case = eCaseInsensitive;
+        break;
+      case llvm::dwarf::DW_ID_case_sensitive:
+      default:
+        m_identifier_case = eCaseSensitive;
+        break;
+    }
+  }
+
+  return m_identifier_case;
+}
+
 uint64_t DWARFUnit::GetDWARFLanguageType() {
   if (m_language_type)
     return *m_language_type;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 6fde9af57fa8b..51bafa75ca1cf 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -204,6 +204,8 @@ class DWARFUnit : public DWARFExpression::Delegate, public UserID {
 
   llvm::VersionTuple GetProducerVersion();
 
+  lldb::IdentifierCaseType GetIdentifierCase();
+
   uint64_t GetDWARFLanguageType();
 
   bool GetIsOptimized();
@@ -352,6 +354,7 @@ class DWARFUnit : public DWARFExpression::Delegate, public UserID {
   DWARFProducer m_producer = eProducerInvalid;
   llvm::VersionTuple m_producer_version;
   std::optional<uint64_t> m_language_type;
+  lldb::IdentifierCaseType m_identifier_case = lldb::eCaseUnknown;
   LazyBool m_is_optimized = eLazyBoolCalculate;
   std::optional<FileSpec> m_comp_dir;
   std::optional<FileSpec> m_file_spec;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index 0971e66df86ae..15efee15fd713 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -158,6 +158,11 @@ void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp,
 
   const LanguageType cu_language = SymbolFileDWARF::GetLanguage(unit);
 
+  lldb::IdentifierCaseType cu_identifier_case = unit.GetIdentifierCase();
+
+  if(cu_identifier_case != eCaseSensitive)
+    SetNameCaseInsensitive();
+
   // First check if the unit has a DWO ID. If it does then we only want to index
   // the .dwo file or nothing at all. If we have a compile unit where we can't
   // locate the .dwo/.dwp file we don't want to index anything from the skeleton
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
index 41e0e620a4896..40da3ea82ab0c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -169,6 +169,17 @@ class ManualDWARFIndex : public DWARFIndex {
   ///   True if this index is a partial index, false otherwise.
   bool IsPartial() const;
 
+	void SetNameCaseInsensitive() {
+		m_set.function_basenames.SetNameCaseInsensitive();
+		m_set.function_fullnames.SetNameCaseInsensitive();
+		m_set.function_methods.SetNameCaseInsensitive();
+		m_set.function_selectors.SetNameCaseInsensitive();
+		m_set.objc_class_selectors.SetNameCaseInsensitive();
+		m_set.globals.SetNameCaseInsensitive();
+		m_set.types.SetNameCaseInsensitive();
+		m_set.namespaces.SetNameCaseInsensitive();
+	}
+
   /// The DWARF file which we are indexing.
   SymbolFileDWARF *m_dwarf;
   /// Which dwarf units should we skip while building the index.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
index b34fda5740924..d6636195e2bbb 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -38,6 +38,20 @@ bool NameToDIE::Find(
   for (const auto &entry : m_map.equal_range(name))
     if (callback(entry.value) == IterationAction::Stop)
       return false;
+  
+  if(!NameCaseInsensitive){
+    for (const auto &entry : m_map.equal_range(name))
+      if (callback(entry.value) == IterationAction::Stop)
+        return false;
+    return true;
+  }
+  
+  for (const auto &entry : m_map){
+    if(ConstString::Equals(ConstString(entry.cstring.GetCString()), name, false))
+      if (callback(entry.value) == IterationAction::Stop)
+        return false;
+  }
+
   return true;
 }
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
index 9f9b631f178ee..6040de1f09b27 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -86,8 +86,11 @@ class NameToDIE {
 
   void Clear() { m_map.Clear(); }
 
+  void SetNameCaseInsensitive() { NameCaseInsensitive = true; }
+
 protected:
   UniqueCStringMap<DIERef> m_map;
+  bool NameCaseInsensitive = false;
 };
 } // namespace dwarf
 } // namespace lldb_private::plugin
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 56fbf3fd771b5..881a009553df2 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -792,6 +792,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
       if (module_sp) {
         auto initialize_cu = [&](SupportFileNSP support_file_nsp,
                                  LanguageType cu_language,
+                                 IdentifierCaseType cu_casing,
                                  SupportFileList &&support_files = {}) {
           BuildCuTranslationTable();
           cu_sp = std::make_shared<CompileUnit>(
@@ -799,8 +800,10 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
               *GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language,
               eLazyBoolCalculate, std::move(support_files));
 
-          dwarf_cu.SetLLDBCompUnit(cu_sp.get());
+          cu_sp->SetCasing(cu_casing);
 
+          dwarf_cu.SetLLDBCompUnit(cu_sp.get());
+          
           SetCompileUnitAtIndex(dwarf_cu.GetID(), cu_sp);
         };
 
@@ -829,7 +832,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
           if (support_files.GetSize() == 0)
             return false;
           initialize_cu(support_files.GetSupportFileAtIndex(0),
-                        eLanguageTypeUnknown, std::move(support_files));
+                        eLanguageTypeUnknown, dwarf_cu.GetIdentifierCase(), std::move(support_files));
           return true;
         };
 
@@ -848,7 +851,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
             MakeAbsoluteAndRemap(cu_file_spec, dwarf_cu, module_sp);
 
             initialize_cu(std::make_shared<SupportFile>(cu_file_spec),
-                          cu_language);
+                          cu_language, dwarf_cu.GetIdentifierCase());
           }
         }
       }
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index 5fc2376be0e75..b358948bee093 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -289,14 +289,28 @@ lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref,
   SymbolContext symbol_context =
       stack_frame.GetSymbolContext(lldb::eSymbolContextCompUnit);
   lldb::VariableListSP variable_list;
-  if (symbol_context.comp_unit)
+  lldb::IdentifierCaseType identifier_case = lldb::eCaseSensitive;
+
+  if (symbol_context.comp_unit){
     variable_list = symbol_context.comp_unit->GetVariableList(true);
+    identifier_case = symbol_context.comp_unit->GetCasing();
+  }
+    
 
   name_ref.consume_front("::");
+
+  std::string search_string;
+  if(identifier_case == lldb::eLowerCase)
+    search_string = name_ref.lower();
+  else if(identifier_case == lldb::eUpperCase)
+    search_string = name_ref.upper();
+  else 
+    search_string = name_ref.str();
+
   lldb::ValueObjectSP value_sp;
   if (variable_list) {
     lldb::VariableSP var_sp =
-        DILFindVariable(ConstString(name_ref), *variable_list);
+        DILFindVariable(ConstString(search_string), *variable_list);
     if (var_sp)
       value_sp =
           stack_frame.GetValueObjectForFrameVariable(var_sp, use_dynamic);
@@ -308,12 +322,12 @@ lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref,
   // Check for match in modules global variables.
   VariableList modules_var_list;
   target_sp->GetImages().FindGlobalVariables(
-      ConstString(name_ref), std::numeric_limits<uint32_t>::max(),
+      ConstString(search_string), std::numeric_limits<uint32_t>::max(),
       modules_var_list);
 
   if (!modules_var_list.Empty()) {
     lldb::VariableSP var_sp =
-        DILFindVariable(ConstString(name_ref), modules_var_list);
+        DILFindVariable(ConstString(search_string), modules_var_list);
     if (var_sp)
       value_sp = ValueObjectVariable::Create(&stack_frame, var_sp);
 
@@ -345,10 +359,24 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
     lldb::VariableListSP variable_list(
         stack_frame.GetInScopeVariableList(false));
 
+    SymbolContext sc = stack_frame.GetSymbolContext(lldb::eSymbolContextCompUnit);
+
+    lldb::IdentifierCaseType identifier_case = lldb::eCaseSensitive;
+    if(sc.comp_unit)
+      identifier_case = sc.comp_unit->GetCasing();
+
+    std::string search_string;
+    if(identifier_case == lldb::eLowerCase)
+      search_string = name_ref.lower();
+    else if(identifier_case == lldb::eUpperCase)
+      search_string = name_ref.upper();
+    else 
+      search_string = name_ref.str();
+
     lldb::ValueObjectSP value_sp;
     if (variable_list) {
       lldb::VariableSP var_sp =
-          variable_list->FindVariable(ConstString(name_ref));
+          variable_list->FindVariable(ConstString(search_string));
       if (var_sp)
         value_sp =
             stack_frame.GetValueObjectForFrameVariable(var_sp, use_dynamic);
@@ -358,12 +386,12 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
       return value_sp;
 
     // Try looking for an instance variable (class member).
-    SymbolContext sc = stack_frame.GetSymbolContext(
+    sc = stack_frame.GetSymbolContext(
         lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
     llvm::StringRef instance_name = sc.GetInstanceName();
     value_sp = stack_frame.FindVariable(ConstString(instance_name));
     if (value_sp)
-      value_sp = value_sp->GetChildMemberWithName(name_ref);
+      value_sp = value_sp->GetChildMemberWithName(search_string);
 
     if (value_sp)
       return value_sp;

>From 1a0f25c968265398debed05e919d1053ee74f03a Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 26 Jun 2026 20:01:29 +0300
Subject: [PATCH 15/44] [lldb]Added case-insensitive support

---
 lldb/include/lldb/Symbol/CompileUnit.h        | 10 +++++
 lldb/include/lldb/lldb-enumerations.h         | 15 +++++++
 .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp    | 32 ++++++++++++++
 .../Plugins/SymbolFile/DWARF/DWARFUnit.h      |  3 ++
 .../SymbolFile/DWARF/ManualDWARFIndex.cpp     |  5 +++
 .../SymbolFile/DWARF/ManualDWARFIndex.h       | 11 +++++
 .../Plugins/SymbolFile/DWARF/NameToDIE.cpp    | 14 +++++++
 .../Plugins/SymbolFile/DWARF/NameToDIE.h      |  3 ++
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      |  9 ++--
 lldb/source/ValueObject/DILEval.cpp           | 42 +++++++++++++++----
 10 files changed, 134 insertions(+), 10 deletions(-)

diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h
index bb9594699df33..7d99bd16ae02d 100644
--- a/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/lldb/include/lldb/Symbol/CompileUnit.h
@@ -152,6 +152,14 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
     m_language = language;
   }
 
+  lldb::IdentifierCaseType GetCasing() {
+    return m_identifier_case;
+  }
+
+  void SetCasing(lldb::IdentifierCaseType identifier_case){
+    m_identifier_case = identifier_case;
+  }
+
   void GetDescription(Stream *s, lldb::DescriptionLevel level) const;
 
   /// Apply a lambda to each function in this compile unit.
@@ -422,6 +430,8 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
   void *m_user_data;
   /// The programming language enumeration value.
   lldb::LanguageType m_language;
+  /// Used to determine if lookups should be case-insensitive
+  lldb::IdentifierCaseType m_identifier_case = lldb::eCaseSensitive;
   /// Compile unit flags that help with partial parsing.
   Flags m_flags;
   /// Maps UIDs to functions.
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 32a341b354d9f..4c0d2c27a8745 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -631,6 +631,21 @@ enum LanguageType {
   eNumLanguageTypes
 };
 
+//----------------------------------------------------------------------
+/// Identifier Case type
+///
+/// this enumeration indetifies the treatment of identifiers within
+/// compilation unit. the default is case sensitive in case it is absent
+/// in compilation unit.
+//----------------------------------------------------------------------
+enum IdentifierCaseType {
+  eCaseSensitive = 0,
+  eUpperCase = 1,
+  eLowerCase = 2,
+  eCaseInsensitive = 3,
+  eCaseUnknown = 4,
+};
+
 enum InstrumentationRuntimeType {
   eInstrumentationRuntimeTypeAddressSanitizer = 0x0000,
   eInstrumentationRuntimeTypeThreadSanitizer = 0x0001,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 4b02124e987e8..7fbef4a831ff1 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -888,6 +888,38 @@ llvm::VersionTuple DWARFUnit::GetProducerVersion() {
   return m_producer_version;
 }
 
+lldb::IdentifierCaseType DWARFUnit::GetIdentifierCase() {
+  if(m_identifier_case != eCaseUnknown)
+    return m_identifier_case;
+
+  const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
+
+  if(!die) 
+    m_identifier_case = eCaseSensitive;
+    
+  else {
+    uint64_t identifier_case = die->GetAttributeValueAsUnsigned(this, DW_AT_identifier_case, llvm::dwarf::DW_ID_case_sensitive);
+
+    switch (identifier_case) {
+      case llvm::dwarf::DW_ID_up_case:
+        m_identifier_case = eUpperCase;
+        break;
+      case llvm::dwarf::DW_ID_down_case:
+        m_identifier_case = eLowerCase;
+        break;
+      case llvm::dwarf::DW_ID_case_insensitive:
+        m_identifier_case = eCaseInsensitive;
+        break;
+      case llvm::dwarf::DW_ID_case_sensitive:
+      default:
+        m_identifier_case = eCaseSensitive;
+        break;
+    }
+  }
+
+  return m_identifier_case;
+}
+
 uint64_t DWARFUnit::GetDWARFLanguageType() {
   if (m_language_type)
     return *m_language_type;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 6fde9af57fa8b..51bafa75ca1cf 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -204,6 +204,8 @@ class DWARFUnit : public DWARFExpression::Delegate, public UserID {
 
   llvm::VersionTuple GetProducerVersion();
 
+  lldb::IdentifierCaseType GetIdentifierCase();
+
   uint64_t GetDWARFLanguageType();
 
   bool GetIsOptimized();
@@ -352,6 +354,7 @@ class DWARFUnit : public DWARFExpression::Delegate, public UserID {
   DWARFProducer m_producer = eProducerInvalid;
   llvm::VersionTuple m_producer_version;
   std::optional<uint64_t> m_language_type;
+  lldb::IdentifierCaseType m_identifier_case = lldb::eCaseUnknown;
   LazyBool m_is_optimized = eLazyBoolCalculate;
   std::optional<FileSpec> m_comp_dir;
   std::optional<FileSpec> m_file_spec;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index 0971e66df86ae..15efee15fd713 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -158,6 +158,11 @@ void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp,
 
   const LanguageType cu_language = SymbolFileDWARF::GetLanguage(unit);
 
+  lldb::IdentifierCaseType cu_identifier_case = unit.GetIdentifierCase();
+
+  if(cu_identifier_case != eCaseSensitive)
+    SetNameCaseInsensitive();
+
   // First check if the unit has a DWO ID. If it does then we only want to index
   // the .dwo file or nothing at all. If we have a compile unit where we can't
   // locate the .dwo/.dwp file we don't want to index anything from the skeleton
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
index 41e0e620a4896..40da3ea82ab0c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -169,6 +169,17 @@ class ManualDWARFIndex : public DWARFIndex {
   ///   True if this index is a partial index, false otherwise.
   bool IsPartial() const;
 
+	void SetNameCaseInsensitive() {
+		m_set.function_basenames.SetNameCaseInsensitive();
+		m_set.function_fullnames.SetNameCaseInsensitive();
+		m_set.function_methods.SetNameCaseInsensitive();
+		m_set.function_selectors.SetNameCaseInsensitive();
+		m_set.objc_class_selectors.SetNameCaseInsensitive();
+		m_set.globals.SetNameCaseInsensitive();
+		m_set.types.SetNameCaseInsensitive();
+		m_set.namespaces.SetNameCaseInsensitive();
+	}
+
   /// The DWARF file which we are indexing.
   SymbolFileDWARF *m_dwarf;
   /// Which dwarf units should we skip while building the index.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
index b34fda5740924..d6636195e2bbb 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -38,6 +38,20 @@ bool NameToDIE::Find(
   for (const auto &entry : m_map.equal_range(name))
     if (callback(entry.value) == IterationAction::Stop)
       return false;
+  
+  if(!NameCaseInsensitive){
+    for (const auto &entry : m_map.equal_range(name))
+      if (callback(entry.value) == IterationAction::Stop)
+        return false;
+    return true;
+  }
+  
+  for (const auto &entry : m_map){
+    if(ConstString::Equals(ConstString(entry.cstring.GetCString()), name, false))
+      if (callback(entry.value) == IterationAction::Stop)
+        return false;
+  }
+
   return true;
 }
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
index 9f9b631f178ee..6040de1f09b27 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -86,8 +86,11 @@ class NameToDIE {
 
   void Clear() { m_map.Clear(); }
 
+  void SetNameCaseInsensitive() { NameCaseInsensitive = true; }
+
 protected:
   UniqueCStringMap<DIERef> m_map;
+  bool NameCaseInsensitive = false;
 };
 } // namespace dwarf
 } // namespace lldb_private::plugin
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 56fbf3fd771b5..881a009553df2 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -792,6 +792,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
       if (module_sp) {
         auto initialize_cu = [&](SupportFileNSP support_file_nsp,
                                  LanguageType cu_language,
+                                 IdentifierCaseType cu_casing,
                                  SupportFileList &&support_files = {}) {
           BuildCuTranslationTable();
           cu_sp = std::make_shared<CompileUnit>(
@@ -799,8 +800,10 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
               *GetDWARFUnitIndex(dwarf_cu.GetID()), cu_language,
               eLazyBoolCalculate, std::move(support_files));
 
-          dwarf_cu.SetLLDBCompUnit(cu_sp.get());
+          cu_sp->SetCasing(cu_casing);
 
+          dwarf_cu.SetLLDBCompUnit(cu_sp.get());
+          
           SetCompileUnitAtIndex(dwarf_cu.GetID(), cu_sp);
         };
 
@@ -829,7 +832,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
           if (support_files.GetSize() == 0)
             return false;
           initialize_cu(support_files.GetSupportFileAtIndex(0),
-                        eLanguageTypeUnknown, std::move(support_files));
+                        eLanguageTypeUnknown, dwarf_cu.GetIdentifierCase(), std::move(support_files));
           return true;
         };
 
@@ -848,7 +851,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
             MakeAbsoluteAndRemap(cu_file_spec, dwarf_cu, module_sp);
 
             initialize_cu(std::make_shared<SupportFile>(cu_file_spec),
-                          cu_language);
+                          cu_language, dwarf_cu.GetIdentifierCase());
           }
         }
       }
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index 5fc2376be0e75..b358948bee093 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -289,14 +289,28 @@ lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref,
   SymbolContext symbol_context =
       stack_frame.GetSymbolContext(lldb::eSymbolContextCompUnit);
   lldb::VariableListSP variable_list;
-  if (symbol_context.comp_unit)
+  lldb::IdentifierCaseType identifier_case = lldb::eCaseSensitive;
+
+  if (symbol_context.comp_unit){
     variable_list = symbol_context.comp_unit->GetVariableList(true);
+    identifier_case = symbol_context.comp_unit->GetCasing();
+  }
+    
 
   name_ref.consume_front("::");
+
+  std::string search_string;
+  if(identifier_case == lldb::eLowerCase)
+    search_string = name_ref.lower();
+  else if(identifier_case == lldb::eUpperCase)
+    search_string = name_ref.upper();
+  else 
+    search_string = name_ref.str();
+
   lldb::ValueObjectSP value_sp;
   if (variable_list) {
     lldb::VariableSP var_sp =
-        DILFindVariable(ConstString(name_ref), *variable_list);
+        DILFindVariable(ConstString(search_string), *variable_list);
     if (var_sp)
       value_sp =
           stack_frame.GetValueObjectForFrameVariable(var_sp, use_dynamic);
@@ -308,12 +322,12 @@ lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref,
   // Check for match in modules global variables.
   VariableList modules_var_list;
   target_sp->GetImages().FindGlobalVariables(
-      ConstString(name_ref), std::numeric_limits<uint32_t>::max(),
+      ConstString(search_string), std::numeric_limits<uint32_t>::max(),
       modules_var_list);
 
   if (!modules_var_list.Empty()) {
     lldb::VariableSP var_sp =
-        DILFindVariable(ConstString(name_ref), modules_var_list);
+        DILFindVariable(ConstString(search_string), modules_var_list);
     if (var_sp)
       value_sp = ValueObjectVariable::Create(&stack_frame, var_sp);
 
@@ -345,10 +359,24 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
     lldb::VariableListSP variable_list(
         stack_frame.GetInScopeVariableList(false));
 
+    SymbolContext sc = stack_frame.GetSymbolContext(lldb::eSymbolContextCompUnit);
+
+    lldb::IdentifierCaseType identifier_case = lldb::eCaseSensitive;
+    if(sc.comp_unit)
+      identifier_case = sc.comp_unit->GetCasing();
+
+    std::string search_string;
+    if(identifier_case == lldb::eLowerCase)
+      search_string = name_ref.lower();
+    else if(identifier_case == lldb::eUpperCase)
+      search_string = name_ref.upper();
+    else 
+      search_string = name_ref.str();
+
     lldb::ValueObjectSP value_sp;
     if (variable_list) {
       lldb::VariableSP var_sp =
-          variable_list->FindVariable(ConstString(name_ref));
+          variable_list->FindVariable(ConstString(search_string));
       if (var_sp)
         value_sp =
             stack_frame.GetValueObjectForFrameVariable(var_sp, use_dynamic);
@@ -358,12 +386,12 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
       return value_sp;
 
     // Try looking for an instance variable (class member).
-    SymbolContext sc = stack_frame.GetSymbolContext(
+    sc = stack_frame.GetSymbolContext(
         lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
     llvm::StringRef instance_name = sc.GetInstanceName();
     value_sp = stack_frame.FindVariable(ConstString(instance_name));
     if (value_sp)
-      value_sp = value_sp->GetChildMemberWithName(name_ref);
+      value_sp = value_sp->GetChildMemberWithName(search_string);
 
     if (value_sp)
       return value_sp;

>From be1e2f4da7f050328fa0ea363ff57d45d506ce47 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Sat, 27 Jun 2026 21:22:57 +0300
Subject: [PATCH 16/44] [lldb][Fortran] Removed duplicate loop in
 NameToDIE::Find

---
 lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
index d6636195e2bbb..fc62f726783d6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -35,10 +35,6 @@ void NameToDIE::Insert(ConstString name, const DIERef &die_ref) {
 bool NameToDIE::Find(
     ConstString name,
     llvm::function_ref<IterationAction(DIERef ref)> callback) const {
-  for (const auto &entry : m_map.equal_range(name))
-    if (callback(entry.value) == IterationAction::Stop)
-      return false;
-  
   if(!NameCaseInsensitive){
     for (const auto &entry : m_map.equal_range(name))
       if (callback(entry.value) == IterationAction::Stop)

>From fac18d88edd30488eff3b36ea2f8d8aabd1fe286 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Sun, 28 Jun 2026 19:36:56 +0300
Subject: [PATCH 17/44] [lldb] Case sensitivity now defaults to case sensitive
 if at least one CU is case sensitive

---
 .../Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp     |  4 ++++
 .../Plugins/SymbolFile/DWARF/ManualDWARFIndex.h       | 11 +++++++++++
 lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h      |  8 +++++++-
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index 15efee15fd713..43f53ea34163b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -160,8 +160,12 @@ void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp,
 
   lldb::IdentifierCaseType cu_identifier_case = unit.GetIdentifierCase();
 
+  // If at least one of the Compile Units is case sensitive, then all compile  
+  // units will be case sensitive
   if(cu_identifier_case != eCaseSensitive)
     SetNameCaseInsensitive();
+  else
+    SetStrictlyCaseSensitive();
 
   // First check if the unit has a DWO ID. If it does then we only want to index
   // the .dwo file or nothing at all. If we have a compile unit where we can't
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
index 40da3ea82ab0c..5e137c0f930d8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -180,6 +180,17 @@ class ManualDWARFIndex : public DWARFIndex {
 		m_set.namespaces.SetNameCaseInsensitive();
 	}
 
+	void SetStrictlyCaseSensitive() {
+		m_set.function_basenames.SetStrictlyCaseSensitive();
+		m_set.function_fullnames.SetStrictlyCaseSensitive();
+		m_set.function_methods.SetStrictlyCaseSensitive();
+		m_set.function_selectors.SetStrictlyCaseSensitive();
+		m_set.objc_class_selectors.SetStrictlyCaseSensitive();
+		m_set.globals.SetStrictlyCaseSensitive();
+		m_set.types.SetStrictlyCaseSensitive();
+		m_set.namespaces.SetStrictlyCaseSensitive();
+	}
+
   /// The DWARF file which we are indexing.
   SymbolFileDWARF *m_dwarf;
   /// Which dwarf units should we skip while building the index.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
index 6040de1f09b27..a85c6a2cda846 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -86,11 +86,17 @@ class NameToDIE {
 
   void Clear() { m_map.Clear(); }
 
-  void SetNameCaseInsensitive() { NameCaseInsensitive = true; }
+  void SetNameCaseInsensitive() { if(!StrictlyCaseSensitive) NameCaseInsensitive = true; }
+  
+  void SetStrictlyCaseSensitive() {
+    NameCaseInsensitive = false;
+    StrictlyCaseSensitive = true;
+  }
 
 protected:
   UniqueCStringMap<DIERef> m_map;
   bool NameCaseInsensitive = false;
+  bool StrictlyCaseSensitive = false;
 };
 } // namespace dwarf
 } // namespace lldb_private::plugin

>From d637347227beee5dbe9a34f51700c93ecc0444ac Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Sat, 27 Jun 2026 15:50:19 +0300
Subject: [PATCH 18/44] [lldb][Fortran] Added variable guard to Fortran Plugin

---
 lldb/source/Plugins/Language/CMakeLists.txt      |  4 +++-
 .../Plugins/SymbolFile/DWARF/CMakeLists.txt      | 16 +++++++++++++---
 lldb/source/Plugins/TypeSystem/CMakeLists.txt    |  5 ++++-
 lldb/unittests/Language/CMakeLists.txt           |  4 +++-
 4 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/lldb/source/Plugins/Language/CMakeLists.txt b/lldb/source/Plugins/Language/CMakeLists.txt
index 5377734af2f8d..bdecd0bf2a6a3 100644
--- a/lldb/source/Plugins/Language/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CMakeLists.txt
@@ -7,4 +7,6 @@ set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES
 add_subdirectory(CPlusPlus)
 add_subdirectory(ObjC)
 add_subdirectory(ObjCPlusPlus)
-add_subdirectory(Fortran)
+if("flang" IN_LIST LLVM_ENABLE_PROJECTS OR "all" IN_LIST LLVM_ENABLE_PROJECTS)
+  add_subdirectory(Fortran)
+endif()
\ No newline at end of file
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
index b198ec4e99b24..027cad4cbdd6f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
+++ b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
@@ -16,7 +16,6 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
   DIERef.cpp
   DWARFASTParser.cpp
   DWARFASTParserClang.cpp
-  DWARFASTParserFortran.cpp
   DWARFAttribute.cpp
   DWARFBaseDIE.cpp
   DWARFCompileUnit.cpp
@@ -58,9 +57,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
     lldbPluginObjCLanguage
     lldbPluginCPlusPlusLanguage
     lldbPluginExpressionParserClang
-    lldbPluginFortranLanguage
     lldbPluginTypeSystemClang
-    lldbPluginTypeSystemFortran
   CLANG_LIBS
     clangAST
     clangBasic
@@ -69,3 +66,16 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
 add_dependencies(lldbPluginSymbolFileDWARF
   LLDBPluginSymbolFileDWARFPropertiesGen
   LLDBPluginSymbolFileDWARFPropertiesEnumGen)
+
+if("flang" IN_LIST LLVM_ENABLE_PROJECTS OR "all" IN_LIST LLVM_ENABLE_PROJECTS)
+
+  target_sources(lldbPluginSymbolFileDWARF PRIVATE 
+    DWARFASTParserFortran.cpp
+  )
+
+  target_link_libraries(lldbPluginSymbolFileDWARF PRIVATE 
+    lldbPluginFortranLanguage 
+    lldbPluginTypeSystemFortran
+  )
+
+endif()
diff --git a/lldb/source/Plugins/TypeSystem/CMakeLists.txt b/lldb/source/Plugins/TypeSystem/CMakeLists.txt
index 24431c14fca61..3128f207eaee3 100644
--- a/lldb/source/Plugins/TypeSystem/CMakeLists.txt
+++ b/lldb/source/Plugins/TypeSystem/CMakeLists.txt
@@ -3,4 +3,7 @@ set_property(DIRECTORY PROPERTY LLDB_PLUGIN_KIND TypeSystem)
 set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES SymbolFile)
 
 add_subdirectory(Clang)
-add_subdirectory(Fortran)
\ No newline at end of file
+
+if("flang" IN_LIST LLVM_ENABLE_PROJECTS OR "all" IN_LIST LLVM_ENABLE_PROJECTS)
+  add_subdirectory(Fortran)
+endif()
\ No newline at end of file
diff --git a/lldb/unittests/Language/CMakeLists.txt b/lldb/unittests/Language/CMakeLists.txt
index 26710ff8896e2..d23dec58328be 100644
--- a/lldb/unittests/Language/CMakeLists.txt
+++ b/lldb/unittests/Language/CMakeLists.txt
@@ -1,4 +1,6 @@
 add_subdirectory(CPlusPlus)
 add_subdirectory(CLanguages)
 add_subdirectory(ObjC)
-add_subdirectory(Fortran)
+if("flang" IN_LIST LLVM_ENABLE_PROJECTS OR "all" IN_LIST LLVM_ENABLE_PROJECTS)  
+  add_subdirectory(Fortran)
+endif()
\ No newline at end of file

>From 8f4415d13ede7e29e5b1008aa1330697e71f6796 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Sun, 28 Jun 2026 19:02:22 +0300
Subject: [PATCH 19/44] [lldb][Fortran] Added FindFlang module and updated
 CMAKE flag guarding for Fortran support in lldb

---
 lldb/cmake/modules/FindFlang.cmake              | 17 +++++++++++++++++
 lldb/cmake/modules/LLDBConfig.cmake             |  1 +
 lldb/source/Plugins/Language/CMakeLists.txt     |  2 +-
 .../Plugins/SymbolFile/DWARF/CMakeLists.txt     | 16 +++++++++-------
 lldb/source/Plugins/TypeSystem/CMakeLists.txt   |  2 +-
 lldb/unittests/Language/CMakeLists.txt          |  2 +-
 6 files changed, 30 insertions(+), 10 deletions(-)
 create mode 100644 lldb/cmake/modules/FindFlang.cmake

diff --git a/lldb/cmake/modules/FindFlang.cmake b/lldb/cmake/modules/FindFlang.cmake
new file mode 100644
index 0000000000000..f71d42c5fb586
--- /dev/null
+++ b/lldb/cmake/modules/FindFlang.cmake
@@ -0,0 +1,17 @@
+# FindFlang.cmake
+
+include(FindPackageHandleStandardArgs)
+
+# If Flang and lldb are in-tree then the libraries will already be available, otherwise look for specific directories
+if(TARGET flangFrontEnd)
+  set(Flang_FOUND TRUE)
+else()
+  find_package(Flang QUIET CONFIG HINTS ${Flang_DIR} ${LLVM_DIR}/../flang)
+endif()
+
+find_package_handle_standard_args(Flang
+  FOUND_VAR
+    Flang_FOUND
+  REQUIRED_VARS
+    Flang_FOUND
+)
\ No newline at end of file
diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake
index e086aaf5d3632..82ad8b19ebb79 100644
--- a/lldb/cmake/modules/LLDBConfig.cmake
+++ b/lldb/cmake/modules/LLDBConfig.cmake
@@ -64,6 +64,7 @@ add_optional_dependency(LLDB_ENABLE_LUA "Enable Lua scripting support in LLDB" L
 add_optional_dependency(LLDB_ENABLE_PYTHON "Enable Python scripting support in LLDB" PythonAndSwig PYTHONANDSWIG_FOUND)
 add_optional_dependency(LLDB_ENABLE_LIBXML2 "Enable Libxml 2 support in LLDB" LibXml2 LIBXML2_FOUND VERSION ${LLDB_LIBXML2_VERSION})
 add_optional_dependency(LLDB_ENABLE_TREESITTER "Enable Tree-sitter syntax highlighting" TreeSitter TREESITTER_FOUND)
+add_optional_dependency(LLDB_ENABLE_FORTRAN "Enable Fortran support in lldb" Flang Flang_FOUND)
 
 option(LLDB_USE_ENTITLEMENTS "When codesigning, use entitlements if available" ON)
 option(LLDB_BUILD_FRAMEWORK "Build LLDB.framework (Darwin only)" OFF)
diff --git a/lldb/source/Plugins/Language/CMakeLists.txt b/lldb/source/Plugins/Language/CMakeLists.txt
index bdecd0bf2a6a3..2dd89b5207a57 100644
--- a/lldb/source/Plugins/Language/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CMakeLists.txt
@@ -7,6 +7,6 @@ set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES
 add_subdirectory(CPlusPlus)
 add_subdirectory(ObjC)
 add_subdirectory(ObjCPlusPlus)
-if("flang" IN_LIST LLVM_ENABLE_PROJECTS OR "all" IN_LIST LLVM_ENABLE_PROJECTS)
+if(LLDB_ENABLE_FORTRAN)
   add_subdirectory(Fortran)
 endif()
\ No newline at end of file
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
index 027cad4cbdd6f..dcaf1c2df2b19 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
+++ b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
@@ -10,6 +10,13 @@ lldb_tablegen(SymbolFileDWARFProperties.json -dump-json
   SOURCE SymbolFileDWARFProperties.td
   TARGET LLDBPluginSymbolFileDWARFPropertiesJsonGen)
 
+set(LLVM_OPTIONAL_SOURCES DWARFASTParserFortran.cpp)
+
+set(FORTRAN_DWARF_SOURCES "")
+if(LLDB_ENABLE_FORTRAN)
+  set(FORTRAN_DWARF_SOURCES DWARFASTParserFortran.cpp)
+endif()
+
 add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
   AppleDWARFIndex.cpp
   DebugNamesDWARFIndex.cpp
@@ -41,6 +48,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
   SymbolFileDWARFDebugMap.cpp
   SymbolFileWasm.cpp
   UniqueDWARFASTType.cpp
+  ${FORTRAN_DWARF_SOURCES}
 
   LINK_COMPONENTS
     DebugInfoDWARF
@@ -67,15 +75,9 @@ add_dependencies(lldbPluginSymbolFileDWARF
   LLDBPluginSymbolFileDWARFPropertiesGen
   LLDBPluginSymbolFileDWARFPropertiesEnumGen)
 
-if("flang" IN_LIST LLVM_ENABLE_PROJECTS OR "all" IN_LIST LLVM_ENABLE_PROJECTS)
-
-  target_sources(lldbPluginSymbolFileDWARF PRIVATE 
-    DWARFASTParserFortran.cpp
-  )
-
+if(LLDB_ENABLE_FORTRAN)
   target_link_libraries(lldbPluginSymbolFileDWARF PRIVATE 
     lldbPluginFortranLanguage 
     lldbPluginTypeSystemFortran
   )
-
 endif()
diff --git a/lldb/source/Plugins/TypeSystem/CMakeLists.txt b/lldb/source/Plugins/TypeSystem/CMakeLists.txt
index 3128f207eaee3..7342c5a8af639 100644
--- a/lldb/source/Plugins/TypeSystem/CMakeLists.txt
+++ b/lldb/source/Plugins/TypeSystem/CMakeLists.txt
@@ -4,6 +4,6 @@ set_property(DIRECTORY PROPERTY LLDB_TOLERATED_PLUGIN_DEPENDENCIES SymbolFile)
 
 add_subdirectory(Clang)
 
-if("flang" IN_LIST LLVM_ENABLE_PROJECTS OR "all" IN_LIST LLVM_ENABLE_PROJECTS)
+if(LLDB_ENABLE_FORTRAN)
   add_subdirectory(Fortran)
 endif()
\ No newline at end of file
diff --git a/lldb/unittests/Language/CMakeLists.txt b/lldb/unittests/Language/CMakeLists.txt
index d23dec58328be..db43874757bc3 100644
--- a/lldb/unittests/Language/CMakeLists.txt
+++ b/lldb/unittests/Language/CMakeLists.txt
@@ -1,6 +1,6 @@
 add_subdirectory(CPlusPlus)
 add_subdirectory(CLanguages)
 add_subdirectory(ObjC)
-if("flang" IN_LIST LLVM_ENABLE_PROJECTS OR "all" IN_LIST LLVM_ENABLE_PROJECTS)  
+if(LLDB_ENABLE_FORTRAN)  
   add_subdirectory(Fortran)
 endif()
\ No newline at end of file

>From c97bcbd26219459a9094b0eabb85aa8ae00c8e99 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Sun, 28 Jun 2026 19:59:25 +0300
Subject: [PATCH 20/44] [lldb] Default to case-sensitive in NameToDIE when at
 least one CU is case sensitive

---
 .../Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp     |  4 ++++
 .../Plugins/SymbolFile/DWARF/ManualDWARFIndex.h       | 11 +++++++++++
 lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h      |  8 +++++++-
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index 15efee15fd713..43f53ea34163b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -160,8 +160,12 @@ void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp,
 
   lldb::IdentifierCaseType cu_identifier_case = unit.GetIdentifierCase();
 
+  // If at least one of the Compile Units is case sensitive, then all compile  
+  // units will be case sensitive
   if(cu_identifier_case != eCaseSensitive)
     SetNameCaseInsensitive();
+  else
+    SetStrictlyCaseSensitive();
 
   // First check if the unit has a DWO ID. If it does then we only want to index
   // the .dwo file or nothing at all. If we have a compile unit where we can't
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
index 40da3ea82ab0c..5e137c0f930d8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -180,6 +180,17 @@ class ManualDWARFIndex : public DWARFIndex {
 		m_set.namespaces.SetNameCaseInsensitive();
 	}
 
+	void SetStrictlyCaseSensitive() {
+		m_set.function_basenames.SetStrictlyCaseSensitive();
+		m_set.function_fullnames.SetStrictlyCaseSensitive();
+		m_set.function_methods.SetStrictlyCaseSensitive();
+		m_set.function_selectors.SetStrictlyCaseSensitive();
+		m_set.objc_class_selectors.SetStrictlyCaseSensitive();
+		m_set.globals.SetStrictlyCaseSensitive();
+		m_set.types.SetStrictlyCaseSensitive();
+		m_set.namespaces.SetStrictlyCaseSensitive();
+	}
+
   /// The DWARF file which we are indexing.
   SymbolFileDWARF *m_dwarf;
   /// Which dwarf units should we skip while building the index.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
index 6040de1f09b27..a85c6a2cda846 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -86,11 +86,17 @@ class NameToDIE {
 
   void Clear() { m_map.Clear(); }
 
-  void SetNameCaseInsensitive() { NameCaseInsensitive = true; }
+  void SetNameCaseInsensitive() { if(!StrictlyCaseSensitive) NameCaseInsensitive = true; }
+  
+  void SetStrictlyCaseSensitive() {
+    NameCaseInsensitive = false;
+    StrictlyCaseSensitive = true;
+  }
 
 protected:
   UniqueCStringMap<DIERef> m_map;
   bool NameCaseInsensitive = false;
+  bool StrictlyCaseSensitive = false;
 };
 } // namespace dwarf
 } // namespace lldb_private::plugin

>From eecceca9a14a1183158c6c83d418b0d47b950cd6 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Sun, 28 Jun 2026 23:10:45 +0300
Subject: [PATCH 21/44] [lldb][Fortran] Pass Fortran compiler to the API test
 suite

---
 .../Python/lldbsuite/test/builders/builder.py | 10 ++++---
 lldb/packages/Python/lldbsuite/test/dotest.py | 17 ++++++++++++
 .../Python/lldbsuite/test/make/Makefile.rules | 13 +++++++++
 lldb/test/API/CMakeLists.txt                  | 14 ++++++++++
 .../API/lang/fortran/frame-variable/Makefile  |  5 +---
 lldb/test/API/lang/fortran/integer/Makefile   |  5 +---
 lldb/test/API/lang/fortran/lit.local.cfg      | 27 +------------------
 lldb/test/API/lang/fortran/logical/Makefile   |  5 +---
 lldb/test/API/lang/fortran/real/Makefile      |  5 +---
 lldb/test/API/lit.cfg.py                      |  3 +++
 lldb/test/API/lit.site.cfg.py.in              |  2 ++
 11 files changed, 61 insertions(+), 45 deletions(-)

diff --git a/lldb/packages/Python/lldbsuite/test/builders/builder.py b/lldb/packages/Python/lldbsuite/test/builders/builder.py
index 93ce4cc732bd3..bbff968df6077 100644
--- a/lldb/packages/Python/lldbsuite/test/builders/builder.py
+++ b/lldb/packages/Python/lldbsuite/test/builders/builder.py
@@ -202,12 +202,16 @@ def getToolchainUtil(util_name):
 
         if lldbplatformutil.platformIsDarwin():
             utils.extend(["AR=%slibtool" % os.getenv("CROSS_COMPILE", "")])
-
-        return [
+        build_cmd = [
             "CC=%s" % cc,
             "CC_TYPE=%s" % cc_type,
             "CXX=%s" % cxx,
-        ] + utils
+        ]
+        
+        fc = configuration.fortran_compiler
+        if fc:
+            build_cmd.append("FC=%s" % fc)  
+        return build_cmd + utils
 
     def getSDKRootSpec(self):
         """
diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py
index b1145f8f96078..9159b256a71d2 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest.py
@@ -266,6 +266,23 @@ def parseOptionsAndInitTestdirs():
                 if which(candidate):
                     configuration.compiler = candidate
                     break
+    
+    if args.fortran_compiler:
+        configuration.fortran_compiler = os.path.abspath(args.fortran_compiler)
+        if not is_exe(configuration.fortran_compiler):
+            configuration.fortran_compiler = which(args.fortran_compiler)
+        if not is_exe(configuration.fortran_compiler):
+            logging.error(
+                '"%s" is not a valid Fortran compiler executable; aborting...', args.fortran_compiler
+            )
+            sys.exit(-1)
+    else:
+        # If no Fortran compiler was explicitly specified, search for local fallbacks.
+        candidateFortranCompilers = ["flang-new", "flang", "gfortran"]
+        for candidate in candidateFortranCompilers:
+            if which(candidate):
+                configuration.fortran_compiler = candidate
+                break
 
     if args.make:
         configuration.make_path = args.make
diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
index 51729959fdf62..5fc38dcafed09 100644
--- a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
+++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
@@ -536,6 +536,16 @@ ifneq "$(strip $(OBJCXX_SOURCES))" ""
 	endif
 endif
 
+#----------------------------------------------------------------------
+# Check if we have any Fortran source files
+#----------------------------------------------------------------------
+ifneq "$(strip $(F_SOURCES))" ""
+	ifeq "$(FC)" ""
+    $(error "No Fortran compiler found for fortran tests")
+  endif
+  OBJECTS +=$(strip $(F_SOURCES:.f90=.o))
+endif
+
 ifeq ($(CC_TYPE), clang)
 	CXXFLAGS += --driver-mode=g++
 endif
@@ -673,6 +683,9 @@ endif
 %.o: %.mm %.d
 	$(CXX) $(CXXFLAGS) -MT $@ -MD -MP -MF $*.d -c -o $@ $<
 
+%.o: %.f90
+	$(FC) $(CFLAGS) -c -o $@ $<
+
 #----------------------------------------------------------------------
 # Automatic variables based on items already entered. Below we create
 # an object's lists from the list of sources by replacing all entries
diff --git a/lldb/test/API/CMakeLists.txt b/lldb/test/API/CMakeLists.txt
index bff3bac438d6b..ad093dd6e3ccb 100644
--- a/lldb/test/API/CMakeLists.txt
+++ b/lldb/test/API/CMakeLists.txt
@@ -88,6 +88,20 @@ else()
   set(LLDB_DEFAULT_TEST_COMPILER "")
 endif()
 
+if(LLDB_ENABLE_FORTRAN)
+  # Prefer the in-tree built target if available.
+  if(TARGET flang)
+    set(LLDB_DEFAULT_TEST_FORTRAN_COMPILER "${LLVM_TOOLS_BINARY_DIR}/flang${CMAKE_EXECUTABLE_SUFFIX}")
+  # Fall back to the out-of-tree installation prefix if configured via find_package.
+  elif(FLANG_INSTALL_PREFIX)
+    set(LLDB_DEFAULT_TEST_FORTRAN_COMPILER "${FLANG_INSTALL_PREFIX}/bin/flang${CMAKE_EXECUTABLE_SUFFIX}")
+  else()
+    set(LLDB_DEFAULT_TEST_FORTRAN_COMPILER "")
+  endif()
+
+  set(LLDB_TEST_FORTRAN_COMPILER "${LLDB_DEFAULT_TEST_FORTRAN_COMPILER}" CACHE PATH "Fortran Compiler to use for building LLDB test inferiors")
+endif()
+
 set(LLDB_TEST_EXECUTABLE "${LLDB_DEFAULT_TEST_EXECUTABLE}" CACHE PATH "lldb executable used for testing")
 set(LLDB_TEST_COMPILER "${LLDB_DEFAULT_TEST_COMPILER}" CACHE PATH "C Compiler to use for building LLDB test inferiors")
 set(LLDB_TEST_DSYMUTIL "${LLDB_DEFAULT_TEST_DSYMUTIL}" CACHE PATH "dsymutil used for generating dSYM bundles")
diff --git a/lldb/test/API/lang/fortran/frame-variable/Makefile b/lldb/test/API/lang/fortran/frame-variable/Makefile
index 076fb85bca4cb..f2c57e164eae4 100644
--- a/lldb/test/API/lang/fortran/frame-variable/Makefile
+++ b/lldb/test/API/lang/fortran/frame-variable/Makefile
@@ -1,6 +1,3 @@
-FFLAGS ?= -g -O0
-
-a.out: frame.f90
-	$(FC) $(FFLAGS) $< -o a.out
+F_SOURCES := frame.f90
 	
 include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/integer/Makefile b/lldb/test/API/lang/fortran/integer/Makefile
index 21f67078a1557..0339201b206d6 100644
--- a/lldb/test/API/lang/fortran/integer/Makefile
+++ b/lldb/test/API/lang/fortran/integer/Makefile
@@ -1,6 +1,3 @@
-FFLAGS ?= -g -O0
+F_SOURCES := integers.f90
 
-a.out: integers.f90
-	$(FC) $(FFLAGS) $< -o a.out
-	
 include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/lit.local.cfg b/lldb/test/API/lang/fortran/lit.local.cfg
index 1fd3d154c5e05..3ec4e0da998d9 100644
--- a/lldb/test/API/lang/fortran/lit.local.cfg
+++ b/lldb/test/API/lang/fortran/lit.local.cfg
@@ -1,27 +1,2 @@
-import lit.util
-
-fc_executable = config.environment.get('FC')
-
-fallback_compilers = [ 
-    'flang-new',
-    'flang', 
-    'gfortran'
-]
-
-if not fc_executable:
-    for compiler in fallback_compilers:
-        fc_executable = lit.util.which(compiler, config.llvm_tools_dir)
-        if fc_executable:
-            break
-                
-        fc_executable = lit.util.which(compiler, config.environment.get('PATH'))
-        if fc_executable:
-            break
-
-if fc_executable:
-    config.environment['FC'] = fc_executable
-    config.substitutions.append(('%FC', fc_executable))
-    config.available_features.add('fortran')
-
-else:
+if not getattr(config, 'lldb_enable_fortran', False):
     config.unsupported = True
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/logical/Makefile b/lldb/test/API/lang/fortran/logical/Makefile
index 126ce47d0d772..848e5361dd976 100644
--- a/lldb/test/API/lang/fortran/logical/Makefile
+++ b/lldb/test/API/lang/fortran/logical/Makefile
@@ -1,6 +1,3 @@
-FFLAGS ?= -g -O0
-
-a.out: logical.f90
-	$(FC) $(FFLAGS) $< -o a.out
+F_SOURCES := logical.f90
 
 include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/real/Makefile b/lldb/test/API/lang/fortran/real/Makefile
index 8cbb245f95cfc..1564dfff256eb 100644
--- a/lldb/test/API/lang/fortran/real/Makefile
+++ b/lldb/test/API/lang/fortran/real/Makefile
@@ -1,6 +1,3 @@
-FFLAGS ?= -g -O0
-
-a.out: real.f90
-	$(FC) $(FFLAGS) $< -o a.out
+F_SOURCES := real.f90
 
 include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lit.cfg.py b/lldb/test/API/lit.cfg.py
index 7d6b43f07287d..3d27aa6f7d3bc 100644
--- a/lldb/test/API/lit.cfg.py
+++ b/lldb/test/API/lit.cfg.py
@@ -297,6 +297,9 @@ def delete_module_cache(path):
 if is_configured("test_compiler"):
     dotest_cmd += ["--compiler", config.test_compiler]
 
+if is_configured("fortran_test_compiler"):
+    dotest_cmd += ["--fortran-compiler", config.fortran_test_compiler]
+
 if is_configured("dsymutil"):
     dotest_cmd += ["--dsymutil", config.dsymutil]
 
diff --git a/lldb/test/API/lit.site.cfg.py.in b/lldb/test/API/lit.site.cfg.py.in
index 44c62414f8bdd..c655f9b1dfd96 100644
--- a/lldb/test/API/lit.site.cfg.py.in
+++ b/lldb/test/API/lit.site.cfg.py.in
@@ -24,6 +24,7 @@ config.python_root_dir = "@Python3_ROOT_DIR@"
 config.lua_executable = "@LUA_EXECUTABLE@"
 config.lldb_lua_cpath = "@LLDB_LUA_CPATH@"
 config.lua_test_entry = "TestLuaAPI.py"
+config.lldb_enable_fortran = "@LLDB_ENABLE_FORTRAN@"
 config.dotest_common_args_str = lit_config.substitute("@LLDB_TEST_COMMON_ARGS@")
 config.dotest_user_args_str = lit_config.substitute("@LLDB_TEST_USER_ARGS@")
 config.lldb_platform_url = lit_config.substitute("@LLDB_TEST_PLATFORM_URL@")
@@ -36,6 +37,7 @@ config.enabled_plugins = []
 config.lldb_executable = lit_config.substitute('@LLDB_TEST_EXECUTABLE@')
 config.test_triple = '@LLDB_TEST_TRIPLE@'
 config.test_compiler = lit_config.substitute('@LLDB_TEST_COMPILER@')
+config.fortran_test_compiler = lit_config.substitute('@LLDB_TEST_FORTRAN_COMPILER@')
 config.dsymutil = lit_config.substitute('@LLDB_TEST_DSYMUTIL@')
 config.make = lit_config.substitute('@LLDB_TEST_MAKE@')
 config.has_libcxx = @LLDB_HAS_LIBCXX@

>From b5f8702d19e013fe615fd99ddebf578ab44725a9 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Sun, 28 Jun 2026 23:13:56 +0300
Subject: [PATCH 22/44] [lldb] Added some spacing to builder.py

---
 lldb/packages/Python/lldbsuite/test/builders/builder.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lldb/packages/Python/lldbsuite/test/builders/builder.py b/lldb/packages/Python/lldbsuite/test/builders/builder.py
index bbff968df6077..73c5b65c9addb 100644
--- a/lldb/packages/Python/lldbsuite/test/builders/builder.py
+++ b/lldb/packages/Python/lldbsuite/test/builders/builder.py
@@ -202,15 +202,17 @@ def getToolchainUtil(util_name):
 
         if lldbplatformutil.platformIsDarwin():
             utils.extend(["AR=%slibtool" % os.getenv("CROSS_COMPILE", "")])
+
         build_cmd = [
             "CC=%s" % cc,
             "CC_TYPE=%s" % cc_type,
             "CXX=%s" % cxx,
         ]
-        
+
         fc = configuration.fortran_compiler
         if fc:
             build_cmd.append("FC=%s" % fc)  
+            
         return build_cmd + utils
 
     def getSDKRootSpec(self):

>From 4d84e1b171370654d5d4f5edcdba047bac09a519 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Sun, 28 Jun 2026 23:16:31 +0300
Subject: [PATCH 23/44] [lldb] Moved SetNameCaseInsensitive and
 SetStrictlyCaseSensitive to ManualDWARFIndex.cpp

---
 .../SymbolFile/DWARF/ManualDWARFIndex.cpp     | 24 ++++++++++++++++++-
 .../SymbolFile/DWARF/ManualDWARFIndex.h       | 23 ++----------------
 .../Plugins/SymbolFile/DWARF/NameToDIE.h      |  7 ++++--
 3 files changed, 30 insertions(+), 24 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index 43f53ea34163b..4c881d0ac41e8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -160,7 +160,7 @@ void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp,
 
   lldb::IdentifierCaseType cu_identifier_case = unit.GetIdentifierCase();
 
-  // If at least one of the Compile Units is case sensitive, then all compile  
+  // If at least one of the Compile Units is case sensitive, then all compile
   // units will be case sensitive
   if(cu_identifier_case != eCaseSensitive)
     SetNameCaseInsensitive();
@@ -663,3 +663,25 @@ void ManualDWARFIndex::SaveToCache() {
       m_dwarf->SetDebugInfoIndexWasSavedToCache();
   }
 }
+
+void ManualDWARFIndex::SetNameCaseInsensitive() {
+		m_set.function_basenames.SetNameCaseInsensitive();
+		m_set.function_fullnames.SetNameCaseInsensitive();
+		m_set.function_methods.SetNameCaseInsensitive();
+		m_set.function_selectors.SetNameCaseInsensitive();
+		m_set.objc_class_selectors.SetNameCaseInsensitive();
+		m_set.globals.SetNameCaseInsensitive();
+		m_set.types.SetNameCaseInsensitive();
+		m_set.namespaces.SetNameCaseInsensitive();
+}
+
+void ManualDWARFIndex::SetStrictlyCaseSensitive() {
+  m_set.function_basenames.SetStrictlyCaseSensitive();
+  m_set.function_fullnames.SetStrictlyCaseSensitive();
+  m_set.function_methods.SetStrictlyCaseSensitive();
+  m_set.function_selectors.SetStrictlyCaseSensitive();
+  m_set.objc_class_selectors.SetStrictlyCaseSensitive();
+  m_set.globals.SetStrictlyCaseSensitive();
+  m_set.types.SetStrictlyCaseSensitive();
+  m_set.namespaces.SetStrictlyCaseSensitive();
+}
\ No newline at end of file
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
index 5e137c0f930d8..c85e1543fc921 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -169,28 +169,9 @@ class ManualDWARFIndex : public DWARFIndex {
   ///   True if this index is a partial index, false otherwise.
   bool IsPartial() const;
 
-	void SetNameCaseInsensitive() {
-		m_set.function_basenames.SetNameCaseInsensitive();
-		m_set.function_fullnames.SetNameCaseInsensitive();
-		m_set.function_methods.SetNameCaseInsensitive();
-		m_set.function_selectors.SetNameCaseInsensitive();
-		m_set.objc_class_selectors.SetNameCaseInsensitive();
-		m_set.globals.SetNameCaseInsensitive();
-		m_set.types.SetNameCaseInsensitive();
-		m_set.namespaces.SetNameCaseInsensitive();
-	}
-
-	void SetStrictlyCaseSensitive() {
-		m_set.function_basenames.SetStrictlyCaseSensitive();
-		m_set.function_fullnames.SetStrictlyCaseSensitive();
-		m_set.function_methods.SetStrictlyCaseSensitive();
-		m_set.function_selectors.SetStrictlyCaseSensitive();
-		m_set.objc_class_selectors.SetStrictlyCaseSensitive();
-		m_set.globals.SetStrictlyCaseSensitive();
-		m_set.types.SetStrictlyCaseSensitive();
-		m_set.namespaces.SetStrictlyCaseSensitive();
-	}
+	void SetNameCaseInsensitive();
 
+  void SetStrictlyCaseSensitive();
   /// The DWARF file which we are indexing.
   SymbolFileDWARF *m_dwarf;
   /// Which dwarf units should we skip while building the index.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
index a85c6a2cda846..01cdffb5bb2db 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -86,8 +86,11 @@ class NameToDIE {
 
   void Clear() { m_map.Clear(); }
 
-  void SetNameCaseInsensitive() { if(!StrictlyCaseSensitive) NameCaseInsensitive = true; }
-  
+  void SetNameCaseInsensitive() {
+    if (!StrictlyCaseSensitive)
+      NameCaseInsensitive = true;
+  }
+
   void SetStrictlyCaseSensitive() {
     NameCaseInsensitive = false;
     StrictlyCaseSensitive = true;

>From 7f7f7c528c16091de2c754e87d74233c7a63f1dc Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 3 Jul 2026 17:44:51 +0300
Subject: [PATCH 24/44] [lldb][Fortran] Added initial support for complex types

---
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index 5c2cc36bac648..c8ef97d74489b 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -33,6 +33,7 @@ class FortranType {
     KIND_INTEGER,
     KIND_LOGICAL,
     KIND_REAL,
+    KIND_COMPLEX,
     KIND_FUNCTION,
     KIND_UNKNOWN
   };
@@ -206,6 +207,11 @@ CompilerType TypeSystemFortran::CreateType(uint32_t kind, uint64_t bitsize,
       name.SetCString("INTEGER");
     underlying_kind = FortranType::KIND_INTEGER;
     break;
+  case dwarf::DW_ATE_complex_float:
+    if (bitsize == 64)
+      name.SetCString("COMPLEX");
+    underlying_kind = FortranType::KIND_COMPLEX;
+    break;
   default:
     return CompilerType();
   }
@@ -222,6 +228,7 @@ ConstString TypeSystemFortran::GetTypeName(opaque_compiler_type_t type,
   case FortranType::KIND_INTEGER:
   case FortranType::KIND_LOGICAL:
   case FortranType::KIND_REAL:
+  case FortranType::KIND_COMPLEX:
     return fortran_type->GetName();
   default:
     return ConstString("Unsupported");
@@ -242,6 +249,15 @@ CompilerType TypeSystemFortran::GetBasicTypeFromAST(BasicType basic_type) {
   case eBasicTypeBool:
     return GetOrCreateFortranType(FortranType::KIND_LOGICAL, 32,
                                   ConstString("LOGICAL"));
+  case eBasicTypeFloatComplex:
+    return GetOrCreateFortranType(FortranType::KIND_COMPLEX, 64,
+                                  ConstString("COMPLEX"));
+  case eBasicTypeDoubleComplex:
+    return GetOrCreateFortranType(FortranType::KIND_COMPLEX, 128,
+                                  ConstString("COMPLEX(KIND=8)"));
+  case eBasicTypeLongDoubleComplex:
+    return GetOrCreateFortranType(FortranType::KIND_COMPLEX, 256,
+                                  ConstString("COMPLEX(KIND=16)"));
   default:
     return CompilerType();
   }
@@ -280,6 +296,9 @@ TypeSystemFortran::GetTypeInfo(opaque_compiler_type_t type,
     if (type_kind == FortranType::KIND_REAL)
       builtin_type_flags |= eTypeIsFloat;
     break;
+  case FortranType::KIND_COMPLEX:
+    builtin_type_flags |= eTypeIsComplex;
+    break;
   default:
     break;
   }
@@ -300,6 +319,7 @@ Encoding TypeSystemFortran::GetEncoding(opaque_compiler_type_t type) {
     return eEncodingInvalid;
   FortranType *fortran_type = static_cast<FortranType *>(type);
   switch (fortran_type->GetKind()) {
+  case FortranType::KIND_COMPLEX:
   case FortranType::KIND_REAL:
     return eEncodingIEEE754;
   case FortranType::KIND_INTEGER:
@@ -322,6 +342,8 @@ Format TypeSystemFortran::GetFormat(opaque_compiler_type_t type) {
     return eFormatFloat;
   case FortranType::KIND_LOGICAL:
     return eFormatBoolean;
+  case FortranType::KIND_COMPLEX:
+    return eFormatComplex;
   default:
     return eFormatDefault;
   }
@@ -362,6 +384,14 @@ bool TypeSystemFortran::DumpTypeValue(
   case FortranType::KIND_REAL:
   case FortranType::KIND_LOGICAL:
 
+    format_data.SetData(data, 0, data.GetByteSize());
+    format_data.SetAddressByteSize(data.GetAddressByteSize());
+    format_data.SetByteOrder(m_byte_order);
+    return DumpDataExtractor(format_data, &s, data_offset, format,
+                             data_byte_size, 1 /*item_count*/, UINT32_MAX,
+                             LLDB_INVALID_ADDRESS, bitfield_bit_size,
+                             bitfield_bit_offset, exe_scope);
+  case FortranType::KIND_COMPLEX:
     format_data.SetData(data, 0, data.GetByteSize());
     format_data.SetAddressByteSize(data.GetAddressByteSize());
     format_data.SetByteOrder(m_byte_order);

>From 9e7b3216a8719e9d7622d727062d763382cbc4a2 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 3 Jul 2026 20:42:02 +0300
Subject: [PATCH 25/44] [lldb] Fixed Makefile.rules to correctly handle Fortran
 and added --fortran-compiler to dotest_args.py

---
 .../Python/lldbsuite/test/dotest_args.py      |  9 ++++++++
 .../Python/lldbsuite/test/make/Makefile.rules | 23 +++++++++++++++++--
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/lldb/packages/Python/lldbsuite/test/dotest_args.py b/lldb/packages/Python/lldbsuite/test/dotest_args.py
index 13b3d85628dc2..7f2151e7d0758 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest_args.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest_args.py
@@ -48,6 +48,15 @@ def create_parser():
             """Specify the compiler(s) used to build the inferior executables. The compiler path can be an executable basename or a full path to a compiler executable. This option can be specified multiple times."""
         ),
     )
+    group.add_argument(
+        '--fortran-compiler',
+        metavar="fortran_compiler",
+        dest='fortran_compiler',
+        default="",
+        help=textwrap.dedent(
+            """The fortran compiler used to build the test programs."""
+        ),
+    )   
     group.add_argument(
         "--sysroot",
         metavar="sysroot",
diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
index 5fc38dcafed09..eb6d6a439ee81 100644
--- a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
+++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
@@ -255,14 +255,17 @@ endif
 DEBUG_INFO_FLAG ?= -g
 
 CFLAGS ?= $(DEBUG_INFO_FLAG) -O0
+FFLAGS ?= $(DEBUG_INFO_FLAG) -O0
 
 # Some tests require no debug information. When lldb-dotest specifies a DWARF version,
 # it adds `-gdwarf-{version}` to the CFLAGS environment variable which causes those tests
 # to fail. Strip any existing debug flags from CFLAGS and force -g0 to prevent this.
 ifeq "$(MAKE_NO_DEBUG_INFO)" "YES"
     CFLAGS := $(filter-out -g%,$(CFLAGS)) -g0
+		FFLAGS := $(filter-out -g%,$(FFLAGS)) -g0
 endif
 CFLAGS += $(SYSROOT_FLAGS)
+FFLAGS += $(SYSROOT_FLAGS)
 
 ifeq "$(OS)" "Darwin"
 	CFLAGS += $(FRAMEWORK_INCLUDES)
@@ -270,22 +273,27 @@ endif
 
 CFLAGS += -I$(LLDB_BASE_DIR)/include -I$(LLDB_OBJ_ROOT)/include
 CFLAGS += -I$(SRCDIR) -I$(THIS_FILE_DIR)
+FFLAGS += -I$(LLDB_BASE_DIR)/include -I$(LLDB_OBJ_ROOT)/include
+FFLAGS += -I$(SRCDIR) -I$(THIS_FILE_DIR)
 
 ifndef NO_TEST_COMMON_H
   CFLAGS += -include $(THIS_FILE_DIR)/test_common.h
 endif
 
 CFLAGS += $(NO_LIMIT_DEBUG_INFO_FLAGS) $(ARCH_CFLAGS)
+FFLAGS += $(ARCH_CFLAGS)
 
 # Use this one if you want to build one part of the result without debug information:
 CFLAGS_NO_DEBUG = -O0 $(FRAMEWORK_INCLUDES) $(ARCH_CFLAGS) $(CFLAGS_EXTRAS) $(SYSROOT_FLAGS)
 
 ifeq "$(MAKE_DWO)" "YES"
 	CFLAGS += -gsplit-dwarf
+	FFLAGS += -gsplit-dwarf
 endif
 
 ifeq "$(MAKE_DEBUG_NAMES)" "YES"
 	CFLAGS += -gpubnames
+	FFLAGS += -gpubnames
 endif
 
 # Enable GNU POSIX extensions (e.g. kill(), usleep(), getpgid(), ...)
@@ -324,10 +332,19 @@ ifeq ($(CC_TYPE), clang)
 endif
 
 CFLAGS += $(CFLAGS_EXTRAS)
+FFLAGS += $(FFLAGS_EXTRAS)
 CXXFLAGS += -std=c++11 $(CFLAGS) $(ARCH_CXXFLAGS)
+
 # Copy common options to the linker flags (dwarf, arch. & etc).
 # Note: we get some 'garbage' options for linker here (such as -I, --isystem & etc).
-LDFLAGS += $(CFLAGS)
+ifneq "$(strip $(F_SOURCES))" ""
+    # We are building Fortran. Use FFLAGS flags.
+    LDFLAGS += $(FFLAGS)
+else
+    # We are building C/C++. Use CFLAGS.
+    LDFLAGS += $(CFLAGS)
+endif
+
 LDFLAGS += $(LD_EXTRAS) $(ARCH_LDFLAGS)
 ifeq (,$(filter $(OS), Windows_NT Android Darwin Wasm))
 	ifneq (,$(filter YES,$(ENABLE_THREADS)))
@@ -544,6 +561,8 @@ ifneq "$(strip $(F_SOURCES))" ""
     $(error "No Fortran compiler found for fortran tests")
   endif
   OBJECTS +=$(strip $(F_SOURCES:.f90=.o))
+	override LD := $(FC)
+	override LDC := any
 endif
 
 ifeq ($(CC_TYPE), clang)
@@ -684,7 +703,7 @@ endif
 	$(CXX) $(CXXFLAGS) -MT $@ -MD -MP -MF $*.d -c -o $@ $<
 
 %.o: %.f90
-	$(FC) $(CFLAGS) -c -o $@ $<
+	$(FC) $(FFLAGS) -c -o $@ $<
 
 #----------------------------------------------------------------------
 # Automatic variables based on items already entered. Below we create

>From 20deee87356385cf6944e2260827a506e814a166 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 3 Jul 2026 20:42:35 +0300
Subject: [PATCH 26/44] [lldb][Fortran] Added Fortran Complex type tests

---
 lldb/test/API/lang/fortran/complex/Makefile   |  3 ++
 .../fortran/complex/TestFortranComplex.py     | 33 +++++++++++++++++++
 .../test/API/lang/fortran/complex/complex.f90 | 13 ++++++++
 3 files changed, 49 insertions(+)
 create mode 100644 lldb/test/API/lang/fortran/complex/Makefile
 create mode 100644 lldb/test/API/lang/fortran/complex/TestFortranComplex.py
 create mode 100644 lldb/test/API/lang/fortran/complex/complex.f90

diff --git a/lldb/test/API/lang/fortran/complex/Makefile b/lldb/test/API/lang/fortran/complex/Makefile
new file mode 100644
index 0000000000000..38f38c1339e5f
--- /dev/null
+++ b/lldb/test/API/lang/fortran/complex/Makefile
@@ -0,0 +1,3 @@
+F_SOURCES := complex.f90
+
+include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/complex/TestFortranComplex.py b/lldb/test/API/lang/fortran/complex/TestFortranComplex.py
new file mode 100644
index 0000000000000..ca665dadaffa3
--- /dev/null
+++ b/lldb/test/API/lang/fortran/complex/TestFortranComplex.py
@@ -0,0 +1,33 @@
+"""
+Tests that the complex intrinsic type with different byte sizes works as expected 
+"""
+
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+
+
+class FortranTestComplex(TestBase):
+
+    def test_fortran_complex(self):
+        """Tests if complex return the correct name, kind and value."""
+        self.build()
+        self.main_source_file = lldb.SBFileSpec("complex.f90")
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+            self, "! Breakpoint here", self.main_source_file
+        )
+
+        frame = thread.GetFrameAtIndex(0)
+
+        complex_four = frame.FindVariable("complex_four")
+        self.assertSuccess(complex_four.GetError(), "Failed to fetch complex_four.")
+        self.assertEqual(complex_four.GetTypeName(), "COMPLEX")
+        self.assertEqual(complex_four.GetByteSize(), 8)
+        self.assertEqual(complex_four.GetValue(), "2 + 3i")
+
+        complex_eight = frame.FindVariable("complex_eight")
+        self.assertSuccess(complex_eight.GetError(), "Failed to fetch complex_eight.")
+        self.assertEqual(complex_eight.GetTypeName(), "COMPLEX(KIND=8)")
+        self.assertEqual(complex_eight.GetByteSize(), 16)
+        self.assertEqual(complex_eight.GetValue(), "1 + 4i")
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/complex/complex.f90 b/lldb/test/API/lang/fortran/complex/complex.f90
new file mode 100644
index 0000000000000..968014ab37a1a
--- /dev/null
+++ b/lldb/test/API/lang/fortran/complex/complex.f90
@@ -0,0 +1,13 @@
+program Complex
+  implicit none
+
+  complex(4) :: complex_four
+  complex(8) :: complex_eight
+
+  complex_four = (2.0, 3.0)
+
+  complex_eight = (1.0, 4.0)
+
+  print *, "Done" ! Breakpoint here
+
+end program Complex
\ No newline at end of file

>From 753929706c97bef3b7585e703f0baea5f3ebc7fd Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 3 Jul 2026 21:46:49 +0300
Subject: [PATCH 27/44] [lldb][Fortran] Updated Complex type printing and tests
 to accomodate changes

---
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 34 ++++++++++++++++---
 .../fortran/complex/TestFortranComplex.py     |  4 +--
 .../TestFortranFrameVariable.py               |  4 ++-
 .../API/lang/fortran/frame-variable/frame.f90 |  2 ++
 4 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index c8ef97d74489b..a568766119c01 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -78,6 +78,33 @@ static bool IsLanguageSupported(LanguageType language) {
   return false;
 }
 
+static bool DumpComplex(Stream &s, const lldb_private::DataExtractor &data,
+                        lldb::offset_t &offset, size_t data_byte_size) {
+  if (sizeof(float) * 2 == data_byte_size) {
+    float f32_1 = data.GetFloat(&offset);
+    float f32_2 = data.GetFloat(&offset);
+
+    s.Printf("(%g, %g)", f32_1, f32_2);
+    return true;
+  } else if (sizeof(double) * 2 == data_byte_size) {
+    double d64_1 = data.GetDouble(&offset);
+    double d64_2 = data.GetDouble(&offset);
+
+    s.Printf("(%lg, %lg)", d64_1, d64_2);
+    return true;
+  } else if (sizeof(long double) * 2 == data_byte_size) {
+    long double ld64_1 = data.GetLongDouble(&offset);
+    long double ld64_2 = data.GetLongDouble(&offset);
+    s.Printf("(%Lg, %Lg)", ld64_1, ld64_2);
+    return true;
+  } else {
+    s.Printf("error: unsupported byte size (%" PRIu64
+             ") for complex float format",
+             (uint64_t)data_byte_size);
+    return false;
+  }
+}
+
 char TypeSystemFortran::ID;
 
 TypeSystemFortran::~TypeSystemFortran() = default;
@@ -383,7 +410,6 @@ bool TypeSystemFortran::DumpTypeValue(
   case FortranType::KIND_INTEGER:
   case FortranType::KIND_REAL:
   case FortranType::KIND_LOGICAL:
-
     format_data.SetData(data, 0, data.GetByteSize());
     format_data.SetAddressByteSize(data.GetAddressByteSize());
     format_data.SetByteOrder(m_byte_order);
@@ -392,13 +418,11 @@ bool TypeSystemFortran::DumpTypeValue(
                              LLDB_INVALID_ADDRESS, bitfield_bit_size,
                              bitfield_bit_offset, exe_scope);
   case FortranType::KIND_COMPLEX:
+    // For Complex we print the value exactly how Fortran prints it
     format_data.SetData(data, 0, data.GetByteSize());
     format_data.SetAddressByteSize(data.GetAddressByteSize());
     format_data.SetByteOrder(m_byte_order);
-    return DumpDataExtractor(format_data, &s, data_offset, format,
-                             data_byte_size, 1 /*item_count*/, UINT32_MAX,
-                             LLDB_INVALID_ADDRESS, bitfield_bit_size,
-                             bitfield_bit_offset, exe_scope);
+    return DumpComplex(s, data, data_offset, data_byte_size);
   default:
     Host::SystemLog(lldb::eSeverityError,
                     "Error: DumpTypeValue not handled yet.\n");
diff --git a/lldb/test/API/lang/fortran/complex/TestFortranComplex.py b/lldb/test/API/lang/fortran/complex/TestFortranComplex.py
index ca665dadaffa3..a824adbdc9629 100644
--- a/lldb/test/API/lang/fortran/complex/TestFortranComplex.py
+++ b/lldb/test/API/lang/fortran/complex/TestFortranComplex.py
@@ -24,10 +24,10 @@ def test_fortran_complex(self):
         self.assertSuccess(complex_four.GetError(), "Failed to fetch complex_four.")
         self.assertEqual(complex_four.GetTypeName(), "COMPLEX")
         self.assertEqual(complex_four.GetByteSize(), 8)
-        self.assertEqual(complex_four.GetValue(), "2 + 3i")
+        self.assertEqual(complex_four.GetValue(), "(2, 3)")
 
         complex_eight = frame.FindVariable("complex_eight")
         self.assertSuccess(complex_eight.GetError(), "Failed to fetch complex_eight.")
         self.assertEqual(complex_eight.GetTypeName(), "COMPLEX(KIND=8)")
         self.assertEqual(complex_eight.GetByteSize(), 16)
-        self.assertEqual(complex_eight.GetValue(), "1 + 4i")
\ No newline at end of file
+        self.assertEqual(complex_eight.GetValue(), "(1, 4)")
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/frame-variable/TestFortranFrameVariable.py b/lldb/test/API/lang/fortran/frame-variable/TestFortranFrameVariable.py
index db8006e7f1e94..d323980e9a6e6 100644
--- a/lldb/test/API/lang/fortran/frame-variable/TestFortranFrameVariable.py
+++ b/lldb/test/API/lang/fortran/frame-variable/TestFortranFrameVariable.py
@@ -22,4 +22,6 @@ def test_fortran_frame_variable(self):
 
         self.expect("frame variable num_real", substrs=["(REAL) num_real = 2.718"])
 
-        self.expect("frame variable num_logical", substrs=["(LOGICAL) num_logical = true"])
\ No newline at end of file
+        self.expect("frame variable num_logical", substrs=["(LOGICAL) num_logical = true"])
+
+        self.expect("frame variable num_complex", substrs=["(COMPLEX) num_complex = (1.3, 2.6)"])
\ No newline at end of file
diff --git a/lldb/test/API/lang/fortran/frame-variable/frame.f90 b/lldb/test/API/lang/fortran/frame-variable/frame.f90
index 1bfc3974ddaa7..2e6b066afb1d3 100644
--- a/lldb/test/API/lang/fortran/frame-variable/frame.f90
+++ b/lldb/test/API/lang/fortran/frame-variable/frame.f90
@@ -4,11 +4,13 @@ program frameVariable
   real  :: num_real
   integer :: num_int
   logical :: num_logical
+  complex :: num_complex
 
 
   num_int    = 152
   num_real   = 2.718281828459045
   num_logical = .TRUE.
+  num_complex = (1.3, 2.6)
 
   print *, "Done" ! Breakpoint here
 

>From 1bac1cffa74259cba539253644249bc5ccd87318 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Mon, 6 Jul 2026 20:20:47 +0300
Subject: [PATCH 28/44] [lldb] Removed broken elseif statement in CMake

---
 lldb/test/API/CMakeLists.txt | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/lldb/test/API/CMakeLists.txt b/lldb/test/API/CMakeLists.txt
index ad093dd6e3ccb..540a1280ad04a 100644
--- a/lldb/test/API/CMakeLists.txt
+++ b/lldb/test/API/CMakeLists.txt
@@ -92,9 +92,6 @@ if(LLDB_ENABLE_FORTRAN)
   # Prefer the in-tree built target if available.
   if(TARGET flang)
     set(LLDB_DEFAULT_TEST_FORTRAN_COMPILER "${LLVM_TOOLS_BINARY_DIR}/flang${CMAKE_EXECUTABLE_SUFFIX}")
-  # Fall back to the out-of-tree installation prefix if configured via find_package.
-  elif(FLANG_INSTALL_PREFIX)
-    set(LLDB_DEFAULT_TEST_FORTRAN_COMPILER "${FLANG_INSTALL_PREFIX}/bin/flang${CMAKE_EXECUTABLE_SUFFIX}")
   else()
     set(LLDB_DEFAULT_TEST_FORTRAN_COMPILER "")
   endif()

>From fa9ed19fad7f1894a940decf84278e2903c4b898 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Mon, 6 Jul 2026 22:14:20 +0300
Subject: [PATCH 29/44] [lldb] Removed support for out-of-tree flang builds

---
 lldb/cmake/modules/FindFlang.cmake  | 17 -----------------
 lldb/cmake/modules/LLDBConfig.cmake |  9 ++++++++-
 2 files changed, 8 insertions(+), 18 deletions(-)
 delete mode 100644 lldb/cmake/modules/FindFlang.cmake

diff --git a/lldb/cmake/modules/FindFlang.cmake b/lldb/cmake/modules/FindFlang.cmake
deleted file mode 100644
index f71d42c5fb586..0000000000000
--- a/lldb/cmake/modules/FindFlang.cmake
+++ /dev/null
@@ -1,17 +0,0 @@
-# FindFlang.cmake
-
-include(FindPackageHandleStandardArgs)
-
-# If Flang and lldb are in-tree then the libraries will already be available, otherwise look for specific directories
-if(TARGET flangFrontEnd)
-  set(Flang_FOUND TRUE)
-else()
-  find_package(Flang QUIET CONFIG HINTS ${Flang_DIR} ${LLVM_DIR}/../flang)
-endif()
-
-find_package_handle_standard_args(Flang
-  FOUND_VAR
-    Flang_FOUND
-  REQUIRED_VARS
-    Flang_FOUND
-)
\ No newline at end of file
diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake
index 82ad8b19ebb79..ffb01342531dc 100644
--- a/lldb/cmake/modules/LLDBConfig.cmake
+++ b/lldb/cmake/modules/LLDBConfig.cmake
@@ -56,6 +56,14 @@ set(LLDB_LIBXML2_VERSION "2.8" CACHE STRING
   static builds of libxml 2. Use at your own risk.")
 mark_as_advanced(LLDB_LIBXML2_VERSION)
 
+set(LLDB_DEFAULT_ENABLE_FORTRAN OFF)
+
+if("flang" IN_LIST LLVM_ENABLE_PROJECTS)
+  set(LLDB_DEFAULT_ENABLE_FORTRAN ON)
+endif()
+
+option(LLDB_ENABLE_FORTRAN "Enable Fortran support in LLDB" ${LLDB_DEFAULT_ENABLE_FORTRAN})
+
 add_optional_dependency(LLDB_ENABLE_SWIG "Enable SWIG to generate LLDB bindings" SWIG SWIG_FOUND VERSION 4)
 add_optional_dependency(LLDB_ENABLE_LIBEDIT "Enable editline support in LLDB" LibEdit LibEdit_FOUND)
 add_optional_dependency(LLDB_ENABLE_CURSES "Enable curses support in LLDB" CursesAndPanel CURSESANDPANEL_FOUND)
@@ -64,7 +72,6 @@ add_optional_dependency(LLDB_ENABLE_LUA "Enable Lua scripting support in LLDB" L
 add_optional_dependency(LLDB_ENABLE_PYTHON "Enable Python scripting support in LLDB" PythonAndSwig PYTHONANDSWIG_FOUND)
 add_optional_dependency(LLDB_ENABLE_LIBXML2 "Enable Libxml 2 support in LLDB" LibXml2 LIBXML2_FOUND VERSION ${LLDB_LIBXML2_VERSION})
 add_optional_dependency(LLDB_ENABLE_TREESITTER "Enable Tree-sitter syntax highlighting" TreeSitter TREESITTER_FOUND)
-add_optional_dependency(LLDB_ENABLE_FORTRAN "Enable Fortran support in lldb" Flang Flang_FOUND)
 
 option(LLDB_USE_ENTITLEMENTS "When codesigning, use entitlements if available" ON)
 option(LLDB_BUILD_FRAMEWORK "Build LLDB.framework (Darwin only)" OFF)

>From 978ec5be96ad9af60051d2db5da29d6332917db8 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Wed, 10 Jun 2026 21:04:46 +0300
Subject: [PATCH 30/44] [lldb][Fortran] Added handling for arrays in
 DWARFASTParser, DWARFExpressions not yet stored or handled

---
 .../DWARF/DWARFASTParserFortran.cpp           | 175 ++++++++++++++++++
 1 file changed, 175 insertions(+)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
index 07d3ffbbc9d6c..95c33c66e6fef 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
@@ -19,6 +19,7 @@
 
 #include "lldb/Symbol/CompileUnit.h"
 #include "lldb/Utility/Log.h"
+#include "lldb/ValueObject/ValueObject.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -30,6 +31,125 @@ DWARFASTParserFortran::DWARFASTParserFortran(TypeSystemFortran &ast)
 
 DWARFASTParserFortran::~DWARFASTParserFortran() {}
 
+// Struct holding extra info needed to characterize Fortran Arrays
+// TODO: Add comments explaining each one
+struct FortranArrayInfo {
+
+  bool is_star = false;
+  bool is_allocatable = false;
+  bool size_known = true;
+
+  llvm::SmallVector<std::optional<uint64_t>, 1> elements_per_dimension;
+  llvm::SmallVector<std::optional<uint64_t>, 1> byte_stride;
+  llvm::SmallVector<int64_t, 1> lower_bounds;
+};
+
+FortranArrayInfo ParseArray(const DWARFDIE &parent_die,
+                            const ExecutionContext *exe_ctx) {
+  FortranArrayInfo array_info;
+  for (DWARFDIE die : parent_die.children()) {
+    const dw_tag_t tag = die.Tag();
+    if (tag != DW_TAG_subrange_type)
+      continue;
+    // If a subrange of an array is a star meaning we can't infer how many
+    // elements it has it is always the last dimension and is identified by not
+    // having a DW_AT_count attribute, if this at the end is true then it is a
+    // star and needs to be treated as such
+    array_info.is_star = true;
+    DWARFAttributes attributes = die.GetAttributes();
+    if (attributes.Size() == 0)
+      continue;
+
+    std::optional<uint64_t> num_elements;
+    std::optional<uint64_t> byte_stride;
+    int64_t lower_bound = 1;
+    int64_t upper_bound = 0;
+    bool upper_bound_valid = false;
+    for (size_t i = 0; i < attributes.Size(); ++i) {
+      const dw_attr_t attr = attributes.AttributeAtIndex(i);
+      DWARFFormValue form_value;
+      if (attributes.ExtractFormValueAtIndex(i, form_value)) {
+        switch (attr) {
+        case DW_AT_name:
+          break;
+
+        case DW_AT_count:
+          array_info.is_star = false;
+          if (DWARFDIE var_die = die.GetReferencedDIE(DW_AT_count)) {
+            if (var_die.Tag() == DW_TAG_variable)
+              if (exe_ctx) {
+                if (auto frame = exe_ctx->GetFrameSP()) {
+                  Status error;
+                  lldb::VariableSP var_sp;
+                  auto valobj_sp = frame->GetValueForVariableExpressionPath(
+                      var_die.GetName(), eNoDynamicValues, 0, var_sp, error);
+                  if (valobj_sp) {
+                    num_elements = valobj_sp->GetValueAsUnsigned(0);
+                    break;
+                  }
+                }
+              }
+          } else if (DWARFFormValue::IsBlockForm(form_value.Form())) {
+            // TODO: Handle cases where we have to read the dope vector
+            array_info.size_known = false;
+          } else
+            num_elements = form_value.Unsigned();
+          break;
+
+        case DW_AT_byte_stride:
+          if (DWARFFormValue::IsBlockForm(form_value.Form())) {
+            // TODO: Handle cases where we have to read the dope vector
+            byte_stride = 0;
+            array_info.size_known = false;
+          } else
+            byte_stride = form_value.Unsigned();
+          break;
+
+        case DW_AT_lower_bound:
+          // TODO: Handle cases where we have to read the dope vector
+          if (DWARFFormValue::IsBlockForm(form_value.Form())) {
+            lower_bound = 1;
+            array_info.size_known = false;
+          }
+
+          else
+            lower_bound = form_value.Signed();
+          break;
+
+        case DW_AT_upper_bound:
+          upper_bound_valid = true;
+          // TODO: Handle cases where we have to read the dope vector
+          if (DWARFFormValue::IsBlockForm(form_value.Form())) {
+            array_info.size_known = false;
+            upper_bound = 1;
+          } else
+            upper_bound = form_value.Signed();
+          break;
+
+        case DW_AT_allocated:
+          array_info.is_allocatable = true;
+          array_info.size_known = false;
+          // TODO: Save the DWARFExpression so we can query the dope vector
+          // every time
+
+        default:
+          break;
+        }
+      }
+    }
+
+    if (!num_elements || *num_elements == 0) {
+      if (upper_bound_valid && upper_bound >= lower_bound)
+        num_elements = upper_bound - lower_bound + 1;
+    }
+
+    array_info.elements_per_dimension.push_back(num_elements);
+    array_info.byte_stride.push_back(byte_stride);
+    array_info.lower_bounds.push_back(lower_bound);
+  }
+  return array_info;
+}
+
 // TODO: Add more logging here there is not enough
 lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(const SymbolContext &sc,
                                                        const DWARFDIE &die,
@@ -101,6 +221,61 @@ lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(const SymbolContext &sc,
                             LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
                             compiler_type, Type::ResolveState::Full);
       } break;
+      case DW_TAG_array_type: {
+        dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
+
+        uint32_t byte_stride = 0;
+        uint32_t bit_stride = 0;
+
+        DWARFDIE element_die = die.GetAttributeValueAsReferenceDIE(DW_AT_type);
+
+        Type *element_type = dwarf->ResolveTypeUID(element_die, true);
+        if (element_type) {
+
+          CompilerType array_element_type =
+              element_type->GetForwardCompilerType();
+          uint64_t total_array_size = 0;
+          uint64_t total_elements = 0;
+          if (array_element_type.GetCompleteType()) {
+            FortranArrayInfo array_info = ParseArray(die, nullptr);
+            // We need to calculate the total array size, if it is known
+            // at compile time
+            if (array_info.size_known) {
+              for (int idx = 0; idx < array_info.byte_stride.size(); idx++) {
+                total_elements += *array_info.elements_per_dimension[idx];
+                if (array_info.byte_stride[idx])
+                  total_array_size +=
+                      (*array_info.elements_per_dimension[idx]) *
+                      (*array_info.byte_stride[idx]);
+                else
+                  total_array_size +=
+                      (*array_info.elements_per_dimension[idx]) *
+                      *array_element_type.GetByteSize(nullptr);
+              }
+            }
+
+            compiler_type = m_ast.CreateArrayType(
+                array_info.elements_per_dimension, array_info.byte_stride,
+                array_info.lower_bounds, array_element_type,
+                array_info.is_allocatable, array_info.is_star,
+                total_array_size * 8, total_elements);
+
+            type_sp = dwarf->MakeType(
+                die.GetID(), compiler_type.GetTypeName(), total_array_size,
+                nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
+                compiler_type, Type::ResolveState::Full);
+            type_sp->SetEncodingType(element_type);
+          } else {
+            dwarf->GetObjectFile()->GetModule()->LogMessage(
+                log,
+                "DWARFASTParserFortran::ParseTypeFromDWARF (die = 0x%8.8x) %s "
+                "name "
+                "= '%s'), incomplete type array element not supported, yet!.",
+                die.GetOffset(), plugin::dwarf::DW_TAG_value_to_name(die.Tag()),
+                die.GetName());
+          }
+        }
+      } break;
       case DW_TAG_subprogram:
       case DW_TAG_subroutine_type: {
         dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;

>From 4f0c71a933d637a9f8f0adedeb94a7b6f4563551 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Wed, 10 Jun 2026 21:03:35 +0300
Subject: [PATCH 31/44] [lldb] [Fortran] Added initial array type
 representation in TypeSystem

---
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 203 +++++++++++++++++-
 .../TypeSystem/Fortran/TypeSystemFortran.h    |  15 +-
 2 files changed, 210 insertions(+), 8 deletions(-)

diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index a568766119c01..6abb36da4ab6d 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -11,6 +11,7 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Symbol/SymbolFile.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Utility/LLDBLog.h"
 
 #include "llvm/Support/raw_ostream.h"
 
@@ -35,6 +36,7 @@ class FortranType {
     KIND_REAL,
     KIND_COMPLEX,
     KIND_FUNCTION,
+    KIND_ARRAY,
     KIND_UNKNOWN
   };
   FortranType(int kind, const ConstString &name, uint64_t bitsize)
@@ -45,8 +47,8 @@ class FortranType {
 
 private:
   int m_kind;
-  uint64_t m_bitsize;
   ConstString m_type_name;
+  uint64_t m_bitsize;
 };
 
 class FortranFunction : public FortranType {
@@ -62,6 +64,81 @@ class FortranFunction : public FortranType {
 private:
   SmallVector<CompilerType, 4> m_parameters;
 };
+
+class ArrayBound {
+public:
+  enum class Category { Explicit, Star, Colon };
+  ArrayBound() = default;
+  ArrayBound(Category category) : m_category{category} {}
+  ArrayBound(Category category, int64_t bound)
+      : m_category{category}, m_bound(bound), m_is_bound_known(true) {}
+
+  bool IsExplicit() const { return m_category == Category::Explicit; }
+
+  bool IsStar() const { return m_category == Category::Star; }
+
+  bool IsColon() const { return m_category == Category::Colon; }
+
+  void SetCategory(Category c) { m_category = c; }
+
+  int64_t GetBound() const {
+    assert(m_is_bound_known && "Can't get the bound if it is not explicit");
+    return m_bound;
+  }
+
+  void SetBound(int64_t bound) {
+    m_is_bound_known = true;
+    m_bound = bound;
+  }
+
+private:
+  int64_t m_bound;
+  bool m_is_bound_known = false;
+  Category m_category{Category::Explicit};
+};
+
+class ArrayShape {
+public:
+  ArrayShape(ArrayBound lb, ArrayBound ub, uint64_t byte_stride)
+      : m_lb(lb), m_ub(ub), m_byte_stride(byte_stride) {}
+
+  const ArrayBound &GetLowerBound() const { return m_lb; }
+  const ArrayBound &GetUpperBound() const { return m_ub; }
+  const uint64_t GetByteStride() const { return m_byte_stride; }
+
+private:
+  ArrayBound m_lb;
+  ArrayBound m_ub;
+  uint64_t m_byte_stride;
+};
+
+class FortranArray : public FortranType {
+public:
+  FortranArray(CompilerType element_type,
+               const SmallVectorImpl<ArrayShape> &dimensions,
+               ConstString array_type_name, uint64_t total_array_size,
+               bool is_allocatable, bool is_array_explicit,
+               uint64_t total_elements)
+      : m_element_type(element_type),
+        m_dimensions(dimensions.begin(), dimensions.end()),
+        m_is_allocatable(is_allocatable), m_total_elements(total_elements),
+        FortranType(TypeKind::KIND_ARRAY, array_type_name, total_array_size) {}
+  // TODO: Add necessary methods here
+  CompilerType GetElementType() const { return m_element_type; }
+  uint64_t GetTotalElements() const { return m_total_elements; }
+  bool IsAllocatable() const { return m_is_allocatable; }
+  bool IsSizeKnown() const { return m_is_explicit; }
+
+private:
+  CompilerType m_element_type;
+  llvm::SmallVector<ArrayShape, 2> m_dimensions;
+  uint64_t m_total_elements;
+  bool m_is_allocatable;
+  // To know if the array is fully explicit without looping through the shapes
+  // every time
+  bool m_is_explicit;
+};
+
 } // namespace lldb_private
 
 /// Used to determine if TypeSystem supports the language passed in
@@ -105,6 +182,46 @@ static bool DumpComplex(Stream &s, const lldb_private::DataExtractor &data,
   }
 }
 
+ConstString
+CreateArrayTypeName(const CompilerType &element_type,
+                    const llvm::SmallVectorImpl<std::optional<uint64_t>>
+                        &elements_per_dimension,
+                    const llvm::SmallVectorImpl<int64_t> &lower_bounds,
+                    bool is_allocatable, bool is_star) {
+
+  std::string name_buffer;
+  llvm::raw_string_ostream name_stream(name_buffer);
+
+  name_stream << element_type.GetTypeName().AsCString(nullptr) << "(";
+  size_t rank = elements_per_dimension.size();
+
+  for (size_t idx = 0; idx < rank; ++idx) {
+    if (idx > 0)
+      name_stream << ", ";
+
+    if (!elements_per_dimension[idx]) {
+      if (is_star && idx == rank - 1) {
+        name_stream << lower_bounds[idx] << ":*";
+      } else {
+        name_stream << ":";
+      }
+    } else {
+      int64_t upper_bound =
+          lower_bounds[idx] + *elements_per_dimension[idx] - 1;
+      name_stream << lower_bounds[idx] << ":" << upper_bound;
+    }
+  }
+
+  name_stream << ")";
+
+  if (is_allocatable) {
+    name_stream << ", allocatable";
+  }
+
+  name_stream.flush();
+  return ConstString(name_buffer.c_str());
+}
+
 char TypeSystemFortran::ID;
 
 TypeSystemFortran::~TypeSystemFortran() = default;
@@ -189,13 +306,13 @@ bool TypeSystemFortran::SupportsLanguage(lldb::LanguageType language) {
 CompilerType TypeSystemFortran::GetOrCreateFortranType(int kind,
                                                        uint64_t bitsize,
                                                        ConstString name) {
-  FortranType *type = m_type_map[{kind, bitsize}].get();
+  FortranType *type = m_basic_type_map[{kind, bitsize}].get();
   if (type)
     return CompilerType(weak_from_this(), (void *)type);
   auto new_type_up = std::make_unique<FortranType>(kind, name, bitsize);
   FortranType *raw_ptr = new_type_up.get();
 
-  m_type_map[{kind, bitsize}] = std::move(new_type_up);
+  m_basic_type_map[{kind, bitsize}] = std::move(new_type_up);
 
   return CompilerType(weak_from_this(), (void *)raw_ptr);
 }
@@ -245,6 +362,58 @@ CompilerType TypeSystemFortran::CreateType(uint32_t kind, uint64_t bitsize,
   return GetOrCreateFortranType(underlying_kind, bitsize, name);
 }
 
+CompilerType TypeSystemFortran::CreateArrayType(
+    llvm::SmallVectorImpl<std::optional<uint64_t>> &elements_per_dimension,
+    llvm::SmallVectorImpl<std::optional<uint64_t>> &byte_strides,
+    llvm::SmallVectorImpl<int64_t> &lower_bounds, CompilerType element_type,
+    bool is_allocatable, bool is_star, uint64_t total_array_size,
+    uint64_t total_elements) {
+
+  size_t rank = elements_per_dimension.size();
+  llvm::SmallVector<ArrayShape, 2> array_shapes;
+  ConstString type_name;
+  bool is_size_known = true;
+  if (total_array_size == 0)
+    is_size_known = false;
+  for (int idx = 0; idx < rank; ++idx) {
+    ArrayBound lb;
+    ArrayBound ub;
+    ArrayBound::Category bound_category;
+    uint64_t byte_stride;
+    auto byte_stride_or_err = element_type.GetByteSize(nullptr);
+    if (!byte_stride_or_err) {
+      LLDB_LOG_ERROR(GetLog(LLDBLog::Types), byte_stride_or_err.takeError(),
+                     "{0}");
+      return CompilerType();
+    }
+    byte_stride = *byte_stride_or_err;
+    // If the elements for this dimension are unknown it is either colon or star
+    // Star can only appear as the last bound
+    if (!elements_per_dimension[idx]) {
+      bound_category = ArrayBound::Category::Colon;
+
+      if (is_star && idx == rank - 1)
+        bound_category = ArrayBound::Category::Star;
+    } else {
+      bound_category = ArrayBound::Category::Explicit;
+      ub.SetBound(lower_bounds[idx] + *elements_per_dimension[idx]);
+    }
+    lb.SetCategory(bound_category);
+    lb.SetBound(lower_bounds[idx]);
+    ub.SetCategory(bound_category);
+    array_shapes.emplace_back(lb, ub, byte_stride);
+  }
+  ConstString array_type_name =
+      CreateArrayTypeName(element_type, elements_per_dimension, lower_bounds,
+                          is_allocatable, is_star);
+
+  FortranArray *array_type = new FortranArray(
+      element_type, array_shapes, array_type_name, total_array_size,
+      is_allocatable, is_size_known, total_elements);
+
+  return CompilerType(weak_from_this(), (void *)array_type);
+}
+
 /// Returns the type name upper-cased to follow Fortran's general style
 ConstString TypeSystemFortran::GetTypeName(opaque_compiler_type_t type,
                                            bool BaseOnly) {
@@ -395,6 +564,34 @@ bool TypeSystemFortran::IsFloatingPointType(opaque_compiler_type_t type) {
   return false;
 }
 
+bool TypeSystemFortran::IsArrayType(lldb::opaque_compiler_type_t type,
+                                    CompilerType *element_type, uint64_t *size,
+                                    bool *is_incomplete) {
+  if (element_type)
+    element_type->Clear();
+  if (size)
+    *size = 0;
+  if (is_incomplete)
+    *is_incomplete = false;
+
+  FortranType *super_type = static_cast<FortranType *>(type);
+  if (!super_type)
+    return false;
+
+  FortranArray *array_type = static_cast<FortranArray *>(super_type);
+
+  if (!array_type)
+    return false;
+
+  if (element_type)
+    *element_type = array_type->GetElementType();
+  // TODO: If it isn't we have to evaluate the DWARFExpressionList
+  if (array_type->IsSizeKnown())
+    *size = array_type->GetTotalElements();
+
+  return true;
+}
+
 bool TypeSystemFortran::DumpTypeValue(
     lldb::opaque_compiler_type_t type, Stream &s, lldb::Format format,
     const DataExtractor &data, lldb::offset_t data_offset,
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index 3350a0bb52e87..97aac13763354 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -44,6 +44,13 @@ class TypeSystemFortran : public TypeSystem {
 
   CompilerType CreateType(uint32_t kind, uint64_t bitsize, ConstString name);
 
+  CompilerType CreateArrayType(
+      llvm::SmallVectorImpl<std::optional<uint64_t>> &elements_per_dimension,
+      llvm::SmallVectorImpl<std::optional<uint64_t>> &byte_strides,
+      llvm::SmallVectorImpl<int64_t> &lower_bounds, CompilerType element_type,
+      bool is_allocatable, bool is_star, uint64_t total_array_size,
+      uint64_t total_elements);
+
   static LanguageSet GetSupportedLanguagesForTypes();
 
   static LanguageSet GetSupportedLanguagesForExpressions();
@@ -94,9 +101,7 @@ class TypeSystemFortran : public TypeSystem {
   // Type Classification
   bool IsArrayType(lldb::opaque_compiler_type_t type,
                    CompilerType *element_type, uint64_t *size,
-                   bool *is_incomplete) override {
-    return false;
-  };
+                   bool *is_incomplete) override;
 
   bool IsAggregateType(lldb::opaque_compiler_type_t type) override {
     return false;
@@ -485,13 +490,13 @@ class TypeSystemFortran : public TypeSystem {
 
 private:
   typedef std::pair<int, uint64_t> TypeKey;
-  typedef llvm::DenseMap<TypeKey, std::unique_ptr<FortranType>> TypeMap;
+  typedef llvm::DenseMap<TypeKey, std::unique_ptr<FortranType>> BasicTypeMap;
   typedef llvm::DenseMap<ConstString, std::unique_ptr<FortranType>> FunctionMap;
 
   // TODO: Types are assosciated by their kind and bitsize, this helps to
   // return from their basic type and is enough for basic types but
   // will change once more types are supported
-  TypeMap m_type_map;
+  BasicTypeMap m_basic_type_map;
   // Right now we can index functions just by their name, but a more
   // effecient solution might replace this
   FunctionMap m_function_map;

>From 299bd0d6a73fefd3731c8da09b8b3f08c1b12583 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 10 Jul 2026 22:33:34 +0300
Subject: [PATCH 32/44] [lldb] Addressed code quality comments

---
 lldb/packages/Python/lldbsuite/test/dotest_args.py      | 2 +-
 lldb/packages/Python/lldbsuite/test/make/Makefile.rules | 8 +++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/lldb/packages/Python/lldbsuite/test/dotest_args.py b/lldb/packages/Python/lldbsuite/test/dotest_args.py
index 7f2151e7d0758..f3be12205c4ed 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest_args.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest_args.py
@@ -54,7 +54,7 @@ def create_parser():
         dest='fortran_compiler',
         default="",
         help=textwrap.dedent(
-            """The fortran compiler used to build the test programs."""
+            """The Fortran compiler used to build the test programs."""
         ),
     )   
     group.add_argument(
diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
index eb6d6a439ee81..ed4608be6484a 100644
--- a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
+++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules
@@ -261,8 +261,8 @@ FFLAGS ?= $(DEBUG_INFO_FLAG) -O0
 # it adds `-gdwarf-{version}` to the CFLAGS environment variable which causes those tests
 # to fail. Strip any existing debug flags from CFLAGS and force -g0 to prevent this.
 ifeq "$(MAKE_NO_DEBUG_INFO)" "YES"
-    CFLAGS := $(filter-out -g%,$(CFLAGS)) -g0
-		FFLAGS := $(filter-out -g%,$(FFLAGS)) -g0
+  CFLAGS := $(filter-out -g%,$(CFLAGS)) -g0
+  FFLAGS := $(filter-out -g%,$(FFLAGS)) -g0
 endif
 CFLAGS += $(SYSROOT_FLAGS)
 FFLAGS += $(SYSROOT_FLAGS)
@@ -557,10 +557,12 @@ endif
 # Check if we have any Fortran source files
 #----------------------------------------------------------------------
 ifneq "$(strip $(F_SOURCES))" ""
-	ifeq "$(FC)" ""
+  ifeq "$(FC)" ""
     $(error "No Fortran compiler found for fortran tests")
   endif
   OBJECTS +=$(strip $(F_SOURCES:.f90=.o))
+	# Override the linker with the Fortran compiler, LDC is not needed 
+	# currently so it is set to any.
 	override LD := $(FC)
 	override LDC := any
 endif

>From 91ee22167931b2f896cc96b0be44b0f8344fbba9 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Tue, 14 Jul 2026 00:02:57 +0300
Subject: [PATCH 33/44] [lldb][Fortran] Started adding support for printing
 explicit array types

---
 .../DWARF/DWARFASTParserFortran.cpp           | 20 ++--
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 95 ++++++++++++++++++-
 .../TypeSystem/Fortran/TypeSystemFortran.h    |  6 +-
 3 files changed, 104 insertions(+), 17 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
index 95c33c66e6fef..d4bbe0da5ab9b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
@@ -235,22 +235,22 @@ lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(const SymbolContext &sc,
           CompilerType array_element_type =
               element_type->GetForwardCompilerType();
           uint64_t total_array_size = 0;
-          uint64_t total_elements = 0;
+          uint64_t total_elements = 1;
           if (array_element_type.GetCompleteType()) {
             FortranArrayInfo array_info = ParseArray(die, nullptr);
             // We need to calculate the total array size, if it is known
             // at compile time
             if (array_info.size_known) {
               for (int idx = 0; idx < array_info.byte_stride.size(); idx++) {
-                total_elements += *array_info.elements_per_dimension[idx];
-                if (array_info.byte_stride[idx])
-                  total_array_size +=
-                      (*array_info.elements_per_dimension[idx]) *
-                      (*array_info.byte_stride[idx]);
-                else
-                  total_array_size +=
-                      (*array_info.elements_per_dimension[idx]) *
-                      *array_element_type.GetByteSize(nullptr);
+                total_elements *= *array_info.elements_per_dimension[idx];
+              }
+
+              // Total size is just total elements * the size of one element
+              auto byte_size_or_err = array_element_type.GetByteSize(nullptr);
+              if (byte_size_or_err) {
+                total_array_size = total_elements * (*byte_size_or_err);
+              } else {
+                total_array_size = 0;
               }
             }
 
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index 6abb36da4ab6d..377105430d2b5 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -104,8 +104,13 @@ class ArrayShape {
 
   const ArrayBound &GetLowerBound() const { return m_lb; }
   const ArrayBound &GetUpperBound() const { return m_ub; }
+  const int64_t GetNumberOfElements() const {
+    return m_ub.GetBound() - m_lb.GetBound() + 1;
+  }
   const uint64_t GetByteStride() const { return m_byte_stride; }
 
+  void SetByteStride(uint64_t byte_stride) { m_byte_stride = byte_stride; }
+
 private:
   ArrayBound m_lb;
   ArrayBound m_ub;
@@ -128,10 +133,21 @@ class FortranArray : public FortranType {
   uint64_t GetTotalElements() const { return m_total_elements; }
   bool IsAllocatable() const { return m_is_allocatable; }
   bool IsSizeKnown() const { return m_is_explicit; }
+  uint64_t GetElementByteSize() const {
+    auto byte_size_or_err = m_element_type.GetByteSize(nullptr);
+    // TODO: Change this to returning an error, and change return type to
+    // expected<uint64_t>
+    if (!byte_size_or_err)
+      return 0;
+    return *byte_size_or_err;
+  }
+
+  size_t GetRank() const { return m_dimensions.size(); }
+  ArrayRef<ArrayShape> GetDimensions() { return m_dimensions; }
 
 private:
   CompilerType m_element_type;
-  llvm::SmallVector<ArrayShape, 2> m_dimensions;
+  SmallVector<ArrayShape, 2> m_dimensions;
   uint64_t m_total_elements;
   bool m_is_allocatable;
   // To know if the array is fully explicit without looping through the shapes
@@ -396,7 +412,7 @@ CompilerType TypeSystemFortran::CreateArrayType(
         bound_category = ArrayBound::Category::Star;
     } else {
       bound_category = ArrayBound::Category::Explicit;
-      ub.SetBound(lower_bounds[idx] + *elements_per_dimension[idx]);
+      ub.SetBound(lower_bounds[idx] + *elements_per_dimension[idx] - 1);
     }
     lb.SetCategory(bound_category);
     lb.SetBound(lower_bounds[idx]);
@@ -545,6 +561,79 @@ Format TypeSystemFortran::GetFormat(opaque_compiler_type_t type) {
   }
 }
 
+Expected<CompilerType> TypeSystemFortran::GetChildCompilerTypeAtIndex(
+    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) {
+  if (!type)
+    return createStringError(
+        inconvertibleErrorCode(),
+        "Failed to craft intermediate Fortran array type: type is null.");
+  FortranType *super_type = static_cast<FortranType *>(type);
+
+  if (super_type->GetKind() != FortranType::KIND_ARRAY)
+    return CompilerType();
+
+  FortranArray *fortran_type = static_cast<FortranArray *>(super_type);
+
+  if (!fortran_type)
+    return CompilerType();
+
+  ArrayRef<ArrayShape> old_dimensions = fortran_type->GetDimensions();
+  if (old_dimensions.size() > 1) {
+
+    SmallVector<ArrayShape, 2> new_dimensions(old_dimensions.begin() + 1,
+                                              old_dimensions.end());
+
+    ArrayShape old_first_dimension = old_dimensions.front();
+    uint64_t new_byte_stride;
+
+    if (old_first_dimension.GetByteStride() != 0)
+      new_byte_stride = old_first_dimension.GetNumberOfElements() *
+                        old_first_dimension.GetByteStride();
+    else
+      new_byte_stride = old_first_dimension.GetNumberOfElements() *
+                        fortran_type->GetElementByteSize();
+
+    new_dimensions.front().SetByteStride(new_byte_stride);
+    bool is_star = new_dimensions.back().GetLowerBound().IsStar();
+    bool is_allocatable = fortran_type->IsAllocatable();
+    uint64_t new_total_elements = fortran_type->GetTotalElements() /
+                                  old_first_dimension.GetNumberOfElements();
+    // Fortran is 1-base indexed, and the offset of element array(1) is 0
+    if (old_dimensions.front().GetByteStride() != 0)
+      child_byte_offset = (idx - 1) * old_dimensions.front().GetByteStride();
+    else
+      child_byte_offset = (idx - 1) * fortran_type->GetElementByteSize();
+
+    uint64_t last_dim_stride = new_dimensions.back().GetByteStride();
+
+    if (last_dim_stride != 0) {
+      child_byte_size =
+          new_dimensions.back().GetNumberOfElements() * last_dim_stride;
+    } else {
+      child_byte_size = new_total_elements * fortran_type->GetElementByteSize();
+    }
+
+    // TODO: Change this to calculate new array name and not reuse old one, same
+    // for total array size.
+    FortranArray *array_type = new FortranArray(
+        fortran_type->GetElementType(), new_dimensions, fortran_type->GetName(),
+        child_byte_size, is_allocatable, fortran_type->IsSizeKnown(),
+        new_total_elements);
+
+    return CompilerType(weak_from_this(), (void *)array_type);
+  } else {
+    child_byte_offset = (idx - 1) * old_dimensions.front().GetByteStride();
+    child_byte_size = fortran_type->GetElementByteSize();
+    return fortran_type->GetElementType();
+  }
+}
+
 bool TypeSystemFortran::IsIntegerType(opaque_compiler_type_t type,
                                       bool &is_signed) {
   if (!type)
@@ -586,7 +675,7 @@ bool TypeSystemFortran::IsArrayType(lldb::opaque_compiler_type_t type,
   if (element_type)
     *element_type = array_type->GetElementType();
   // TODO: If it isn't we have to evaluate the DWARFExpressionList
-  if (array_type->IsSizeKnown())
+  if (array_type->IsSizeKnown() && size)
     *size = array_type->GetTotalElements();
 
   return true;
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index 97aac13763354..80951a6d45c99 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -181,7 +181,7 @@ class TypeSystemFortran : public TypeSystem {
 
   // AST related queries
 
-  uint32_t GetPointerByteSize() override { return 0; }
+  uint32_t GetPointerByteSize() override { return 4; }
 
   CompilerType GetPointerDiffType(bool is_signed) override {
     return CompilerType();
@@ -358,9 +358,7 @@ class TypeSystemFortran : public TypeSystem {
       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 {
-    return CompilerType();
-  }
+      ValueObject *valobj, uint64_t &language_flags) override;
 
   // Lookup a child given a name. This function will match base class names and
   // member member names in "clang_type" only, not descendants.

>From 8d38b1473de9c72af2558c1e05a0d437cccefa72 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Tue, 14 Jul 2026 18:39:45 +0300
Subject: [PATCH 34/44] [lldb][Fortran] Completed explicit array support, yet
 to make tests

---
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 100 +++++++++++++-----
 .../TypeSystem/Fortran/TypeSystemFortran.h    |   8 +-
 2 files changed, 76 insertions(+), 32 deletions(-)

diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index 377105430d2b5..96e2c645d2589 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -47,8 +47,8 @@ class FortranType {
 
 private:
   int m_kind;
-  ConstString m_type_name;
   uint64_t m_bitsize;
+  ConstString m_type_name;
 };
 
 class FortranFunction : public FortranType {
@@ -92,9 +92,9 @@ class ArrayBound {
   }
 
 private:
+  Category m_category{Category::Explicit};
   int64_t m_bound;
   bool m_is_bound_known = false;
-  Category m_category{Category::Explicit};
 };
 
 class ArrayShape {
@@ -198,33 +198,35 @@ static bool DumpComplex(Stream &s, const lldb_private::DataExtractor &data,
   }
 }
 
-ConstString
-CreateArrayTypeName(const CompilerType &element_type,
-                    const llvm::SmallVectorImpl<std::optional<uint64_t>>
-                        &elements_per_dimension,
-                    const llvm::SmallVectorImpl<int64_t> &lower_bounds,
-                    bool is_allocatable, bool is_star) {
+ConstString CreateArrayTypeName(const CompilerType &element_type,
+                                const llvm::ArrayRef<ArrayShape> shapes,
+                                bool is_allocatable, bool is_star) {
 
   std::string name_buffer;
   llvm::raw_string_ostream name_stream(name_buffer);
 
   name_stream << element_type.GetTypeName().AsCString(nullptr) << "(";
-  size_t rank = elements_per_dimension.size();
+  size_t rank = shapes.size();
 
   for (size_t idx = 0; idx < rank; ++idx) {
     if (idx > 0)
       name_stream << ", ";
 
-    if (!elements_per_dimension[idx]) {
-      if (is_star && idx == rank - 1) {
-        name_stream << lower_bounds[idx] << ":*";
-      } else {
-        name_stream << ":";
+    const ArrayBound &lb = shapes[idx].GetLowerBound();
+    const ArrayBound &ub = shapes[idx].GetUpperBound();
+
+    if (ub.IsStar()) {
+      // Assuming you want standard Fortran syntax (e.g., "1:*")
+      name_stream << lb.GetBound() << ":*";
+    } else if (ub.IsColon()) {
+      // Unknown bound elements
+      name_stream << ":";
+    } else if (ub.IsExplicit()) {
+      // Explicit bounds
+      if (lb.GetBound() != 1) {
+        name_stream << lb.GetBound() << ":";
       }
-    } else {
-      int64_t upper_bound =
-          lower_bounds[idx] + *elements_per_dimension[idx] - 1;
-      name_stream << lower_bounds[idx] << ":" << upper_bound;
+      name_stream << ub.GetBound();
     }
   }
 
@@ -420,8 +422,7 @@ CompilerType TypeSystemFortran::CreateArrayType(
     array_shapes.emplace_back(lb, ub, byte_stride);
   }
   ConstString array_type_name =
-      CreateArrayTypeName(element_type, elements_per_dimension, lower_bounds,
-                          is_allocatable, is_star);
+      CreateArrayTypeName(element_type, array_shapes, is_allocatable, is_star);
 
   FortranArray *array_type = new FortranArray(
       element_type, array_shapes, array_type_name, total_array_size,
@@ -441,6 +442,7 @@ ConstString TypeSystemFortran::GetTypeName(opaque_compiler_type_t type,
   case FortranType::KIND_LOGICAL:
   case FortranType::KIND_REAL:
   case FortranType::KIND_COMPLEX:
+  case FortranType::KIND_ARRAY:
     return fortran_type->GetName();
   default:
     return ConstString("Unsupported");
@@ -561,6 +563,33 @@ Format TypeSystemFortran::GetFormat(opaque_compiler_type_t type) {
   }
 }
 
+Expected<uint32_t>
+TypeSystemFortran::GetNumChildren(opaque_compiler_type_t type,
+                                  bool omit_empty_base_classes,
+                                  const ExecutionContext *exe_ctx) {
+  if (!type)
+    return createStringError(
+        inconvertibleErrorCode(),
+        "Couldn't get number of children, bad Fortran type.");
+  FortranType *super_type = static_cast<FortranType *>(type);
+
+  switch (super_type->GetKind()) {
+  case FortranType::KIND_ARRAY: {
+    FortranArray *fortran_array = static_cast<FortranArray *>(super_type);
+
+    if (!fortran_array)
+      return createStringError(
+          inconvertibleErrorCode(),
+          "Couldn't get number of children, bad Fortran type.");
+
+    // Fetch the number of elements
+    return fortran_array->GetDimensions().front().GetNumberOfElements();
+  }
+  default:
+    return 0;
+  }
+}
+
 Expected<CompilerType> TypeSystemFortran::GetChildCompilerTypeAtIndex(
     opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
     bool transparent_pointers, bool omit_empty_base_classes,
@@ -584,6 +613,16 @@ Expected<CompilerType> TypeSystemFortran::GetChildCompilerTypeAtIndex(
     return CompilerType();
 
   ArrayRef<ArrayShape> old_dimensions = fortran_type->GetDimensions();
+  int64_t ub = old_dimensions.front().GetUpperBound().GetBound();
+  int64_t lb = old_dimensions.front().GetLowerBound().GetBound();
+  if ((idx + 1) < lb || (idx + 1) > ub)
+    return createStringError(
+        inconvertibleErrorCode(),
+        llvm::formatv(
+            "Failed to craft intermediate Fortran array type: physical index "
+            "{0} is out of bounds (array only has {1} elements)",
+            idx, fortran_type->GetTotalElements()));
+
   if (old_dimensions.size() > 1) {
 
     SmallVector<ArrayShape, 2> new_dimensions(old_dimensions.begin() + 1,
@@ -606,9 +645,9 @@ Expected<CompilerType> TypeSystemFortran::GetChildCompilerTypeAtIndex(
                                   old_first_dimension.GetNumberOfElements();
     // Fortran is 1-base indexed, and the offset of element array(1) is 0
     if (old_dimensions.front().GetByteStride() != 0)
-      child_byte_offset = (idx - 1) * old_dimensions.front().GetByteStride();
+      child_byte_offset = idx * old_dimensions.front().GetByteStride();
     else
-      child_byte_offset = (idx - 1) * fortran_type->GetElementByteSize();
+      child_byte_offset = idx * fortran_type->GetElementByteSize();
 
     uint64_t last_dim_stride = new_dimensions.back().GetByteStride();
 
@@ -619,16 +658,23 @@ Expected<CompilerType> TypeSystemFortran::GetChildCompilerTypeAtIndex(
       child_byte_size = new_total_elements * fortran_type->GetElementByteSize();
     }
 
+    child_name = llvm::formatv("[{0}]", idx);
     // TODO: Change this to calculate new array name and not reuse old one, same
     // for total array size.
-    FortranArray *array_type = new FortranArray(
-        fortran_type->GetElementType(), new_dimensions, fortran_type->GetName(),
-        child_byte_size, is_allocatable, fortran_type->IsSizeKnown(),
-        new_total_elements);
+    ConstString type_name =
+        CreateArrayTypeName(fortran_type->GetElementType(), new_dimensions,
+                            is_allocatable, is_star);
+    FortranArray *array_type =
+        new FortranArray(fortran_type->GetElementType(), new_dimensions,
+                         type_name, child_byte_size, is_allocatable,
+                         fortran_type->IsSizeKnown(), new_total_elements);
 
     return CompilerType(weak_from_this(), (void *)array_type);
   } else {
-    child_byte_offset = (idx - 1) * old_dimensions.front().GetByteStride();
+    if (old_dimensions.front().GetByteStride() != 0)
+      child_byte_offset = idx * old_dimensions.front().GetByteStride();
+    else
+      child_byte_offset = idx * fortran_type->GetElementByteSize();
     child_byte_size = fortran_type->GetElementByteSize();
     return fortran_type->GetElementType();
   }
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index 80951a6d45c99..f5fcc7b2e76d5 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -181,7 +181,8 @@ class TypeSystemFortran : public TypeSystem {
 
   // AST related queries
 
-  uint32_t GetPointerByteSize() override { return 4; }
+  // FIXME: This is temporary for now
+  uint32_t GetPointerByteSize() override { return 8; }
 
   CompilerType GetPointerDiffType(bool is_signed) override {
     return CompilerType();
@@ -302,10 +303,7 @@ class TypeSystemFortran : public TypeSystem {
   llvm::Expected<uint32_t>
   GetNumChildren(lldb::opaque_compiler_type_t type,
                  bool omit_empty_base_classes,
-                 const ExecutionContext *exe_ctx) override {
-    return 0;
-  }
-
+                 const ExecutionContext *exe_ctx) override;
   lldb::BasicType
   GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override {
     return lldb::eBasicTypeInt;

>From eacec557fb25b980d8a3c4d7e51445735967fc21 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 17 Jul 2026 18:36:33 +0300
Subject: [PATCH 35/44] Addressed compiler warnings

---
 .../Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp      | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index 96e2c645d2589..1dbba12e3e072 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -104,10 +104,10 @@ class ArrayShape {
 
   const ArrayBound &GetLowerBound() const { return m_lb; }
   const ArrayBound &GetUpperBound() const { return m_ub; }
-  const int64_t GetNumberOfElements() const {
+  int64_t GetNumberOfElements() const {
     return m_ub.GetBound() - m_lb.GetBound() + 1;
   }
-  const uint64_t GetByteStride() const { return m_byte_stride; }
+  uint64_t GetByteStride() const { return m_byte_stride; }
 
   void SetByteStride(uint64_t byte_stride) { m_byte_stride = byte_stride; }
 
@@ -126,7 +126,7 @@ class FortranArray : public FortranType {
                uint64_t total_elements)
       : m_element_type(element_type),
         m_dimensions(dimensions.begin(), dimensions.end()),
-        m_is_allocatable(is_allocatable), m_total_elements(total_elements),
+        m_total_elements(total_elements), m_is_allocatable(is_allocatable), 
         FortranType(TypeKind::KIND_ARRAY, array_type_name, total_array_size) {}
   // TODO: Add necessary methods here
   CompilerType GetElementType() const { return m_element_type; }
@@ -393,7 +393,7 @@ CompilerType TypeSystemFortran::CreateArrayType(
   bool is_size_known = true;
   if (total_array_size == 0)
     is_size_known = false;
-  for (int idx = 0; idx < rank; ++idx) {
+  for (size_t idx = 0; idx < rank; ++idx) {
     ArrayBound lb;
     ArrayBound ub;
     ArrayBound::Category bound_category;

>From 7c6e4891c125640615a392e48c28bf0feb66603f Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Tue, 21 Jul 2026 20:09:34 +0300
Subject: [PATCH 36/44] [lldb][Fortran] Switching to handling arrays through
 synthetic children

---
 .../Plugins/Language/Fortran/DynamicArray.cpp | 147 +++++++++++++
 .../Plugins/Language/Fortran/DynamicArray.h   |  27 +++
 .../Plugins/TypeSystem/Fortran/FortranTypes.h | 193 ++++++++++++++++++
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 179 +---------------
 .../TypeSystem/Fortran/TypeSystemFortran.h    |  17 ++
 5 files changed, 386 insertions(+), 177 deletions(-)
 create mode 100644 lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
 create mode 100644 lldb/source/Plugins/Language/Fortran/DynamicArray.h
 create mode 100644 lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h

diff --git a/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp b/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
new file mode 100644
index 0000000000000..43bbad9fc3054
--- /dev/null
+++ b/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
@@ -0,0 +1,147 @@
+//===-- DynamicArray.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 "DynamicArray.h"
+
+#include "lldb/Expression/DWARFExpressionList.h"
+
+#include "Plugins/TypeSystem/Fortran/FortranTypes.h"
+#include "Plugins/TypeSystem/Fortran/TypeSystemFortran.h"
+
+#include "llvm/Support/Error.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+namespace lldb_private {
+namespace formatters {
+
+class DynamicArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+  DynamicArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+  ~DynamicArraySyntheticFrontEnd();
+
+  llvm::Expected<uint32_t> CalculateNumChildren() override;
+
+  lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
+
+  lldb::ChildCacheState Update() override;
+
+  llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
+
+private:
+  CompilerType m_element_type;
+  CompilerType m_array_type;
+  llvm::DenseMap<FortranArray *, FortranType *> m_children_map;
+};
+
+DynamicArraySyntheticFrontEnd::DynamicArraySyntheticFrontEnd(
+    lldb::ValueObjectSP valobj_sp)
+    : SyntheticChildrenFrontEnd(*valobj_sp), m_element_type() {
+  if (valobj_sp)
+    Update();
+}
+
+llvm::Expected<uint32_t> DynamicArraySyntheticFrontEnd::CalculateNumChildren() {
+  lldb::opaque_compiler_type_t raw_type = m_array_type.GetOpaqueQualType();
+  if (!raw_type)
+    return 0;
+  FortranArray *array_type = static_cast<FortranArray *>(raw_type);
+  if (!array_type)
+    return 0;
+
+  ArrayShape first_dimension = array_type->GetDimensions().front();
+  return first_dimension.GetNumberOfElements();
+}
+
+lldb::ValueObjectSP
+DynamicArraySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
+  lldb::opaque_compiler_type_t raw_type = m_array_type.GetOpaqueQualType();
+
+  if (!raw_type)
+    return ValueObjectSP();
+
+  FortranType *super_type = static_cast<FortranType *>(raw_type);
+
+  if (super_type->GetKind() != FortranType::KIND_ARRAY)
+    return ValueObjectSP();
+
+  FortranArray *fortran_type = static_cast<FortranArray *>(super_type);
+
+  if (!fortran_type)
+    return ValueObjectSP();
+  uint32_t child_byte_size;
+  int32_t child_byte_offset;
+  std::string child_name;
+  llvm::ArrayRef<ArrayShape> old_dimensions = fortran_type->GetDimensions();
+  int64_t ub = old_dimensions.front().GetUpperBound().GetBound();
+  int64_t lb = old_dimensions.front().GetLowerBound().GetBound();
+  if ((idx + 1) < lb || (idx + 1) > ub)
+    return ValueObjectSP();
+
+  if (old_dimensions.size() > 1) {
+
+    llvm::SmallVector<ArrayShape, 2> new_dimensions(old_dimensions.begin() + 1,
+                                                    old_dimensions.end());
+
+    ArrayShape old_first_dimension = old_dimensions.front();
+    uint64_t new_byte_stride;
+
+    if (old_first_dimension.GetByteStride() != 0)
+      new_byte_stride = old_first_dimension.GetNumberOfElements() *
+                        old_first_dimension.GetByteStride();
+    else
+      new_byte_stride = old_first_dimension.GetNumberOfElements() *
+                        fortran_type->GetElementByteSize();
+
+    new_dimensions.front().SetByteStride(new_byte_stride);
+    bool is_star = new_dimensions.back().GetLowerBound().IsStar();
+    bool is_allocatable = fortran_type->IsAllocatable();
+    uint64_t new_total_elements = fortran_type->GetTotalElements() /
+                                  old_first_dimension.GetNumberOfElements();
+    // Fortran is 1-base indexed, and the offset of element array(1) is 0
+    if (old_dimensions.front().GetByteStride() != 0)
+      child_byte_offset = idx * old_dimensions.front().GetByteStride();
+    else
+      child_byte_offset = idx * fortran_type->GetElementByteSize();
+
+    uint64_t last_dim_stride = new_dimensions.back().GetByteStride();
+
+    if (last_dim_stride != 0) {
+      child_byte_size =
+          new_dimensions.back().GetNumberOfElements() * last_dim_stride;
+    } else {
+      child_byte_size = new_total_elements * fortran_type->GetElementByteSize();
+    }
+
+    child_name = llvm::formatv("[{0}]", idx);
+    ConstString type_name =
+        CreateArrayTypeName(fortran_type->GetElementType(), new_dimensions,
+                            is_allocatable, is_star);
+    FortranArray *array_type =
+        new FortranArray(fortran_type->GetElementType(), new_dimensions,
+                         type_name, child_byte_size, is_allocatable,
+                         fortran_type->IsSizeKnown(), new_total_elements);
+    CompilerType array_compiler_type(
+        TypeSystemWP(m_array_type.GetTypeSystem().GetSharedPointer()),
+        (void *)array_type);
+    
+  } else {
+    if (old_dimensions.front().GetByteStride() != 0)
+      child_byte_offset = idx * old_dimensions.front().GetByteStride();
+    else
+      child_byte_offset = idx * fortran_type->GetElementByteSize();
+    child_byte_size = fortran_type->GetElementByteSize();
+    return fortran_type->GetElementType();
+  }
+}
+
+} // namespace formatters
+} // namespace lldb_private
\ No newline at end of file
diff --git a/lldb/source/Plugins/Language/Fortran/DynamicArray.h b/lldb/source/Plugins/Language/Fortran/DynamicArray.h
new file mode 100644
index 0000000000000..6eb2e183f0acd
--- /dev/null
+++ b/lldb/source/Plugins/Language/Fortran/DynamicArray.h
@@ -0,0 +1,27 @@
+//===-- DynamicArray.h ----------------------------------------------------===//
+//
+// 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_LANGUAGE_FORTRAN_DYNAMICARRAY_H
+#define LLDB_SOURCE_PLUGINS_LANGUAGE_FORTRAN_DYNAMICARRAY_H
+
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/ValueObject/ValueObject.h"
+
+namespace lldb_private {
+namespace formatters {
+
+SyntheticChildrenFrontEnd *
+FortranDynamicArraySyntheticFrontEndCreator(CXXSyntheticChildren *,
+                                            lldb::ValueObjectSP);
+
+} // namespace formatters
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_LANGUAGE_FORTRAN_DYNAMICARRAY_H
\ No newline at end of file
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h b/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h
new file mode 100644
index 0000000000000..be933b7c7e8be
--- /dev/null
+++ b/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h
@@ -0,0 +1,193 @@
+//===-- FortranTypes.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_FORTRAN_FORTRANTYPES_H
+#define LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_FORTRANTYPES_H
+
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+
+namespace lldb_private {
+
+/// A simplified internal representation of a Fortran type.
+/// In the future, this will likely be replaced by a Flang-backed AST.
+class FortranType {
+public:
+  enum TypeKind {
+    KIND_INTEGER,
+    KIND_LOGICAL,
+    KIND_REAL,
+    KIND_COMPLEX,
+    KIND_FUNCTION,
+    KIND_ARRAY,
+    KIND_UNKNOWN
+  };
+  FortranType(int kind, const ConstString &name, uint64_t bitsize)
+      : m_kind(kind), m_bitsize(bitsize), m_type_name(name) {}
+  int GetKind() const { return m_kind; }
+  uint64_t GetBitSize() const { return m_bitsize; }
+  ConstString GetName() const { return m_type_name; }
+
+private:
+  int m_kind;
+  uint64_t m_bitsize;
+  ConstString m_type_name;
+};
+
+class FortranFunction : public FortranType {
+public:
+  FortranFunction(ConstString func_name,
+                  const llvm::SmallVectorImpl<CompilerType> &parameters)
+      : FortranType(FortranType::KIND_FUNCTION, func_name, 0) {
+    m_parameters.assign(parameters.begin(), parameters.end());
+  }
+  llvm::ArrayRef<CompilerType> GetParameters() const { return m_parameters; }
+  size_t GetNumberOfParameters() const { return m_parameters.size(); }
+
+private:
+  llvm::SmallVector<CompilerType, 4> m_parameters;
+};
+
+class ArrayBound {
+public:
+  enum class Category { Explicit, Star, Colon };
+  ArrayBound() = default;
+  ArrayBound(Category category) : m_category{category} {}
+  ArrayBound(Category category, int64_t bound)
+      : m_category{category}, m_bound(bound), m_is_bound_known(true) {}
+
+  bool IsExplicit() const { return m_category == Category::Explicit; }
+
+  bool IsStar() const { return m_category == Category::Star; }
+
+  bool IsColon() const { return m_category == Category::Colon; }
+
+  void SetCategory(Category c) { m_category = c; }
+
+  int64_t GetBound() const {
+    assert(m_is_bound_known && "Can't get the bound if it is not explicit");
+    return m_bound;
+  }
+
+  void SetBound(int64_t bound) {
+    m_is_bound_known = true;
+    m_bound = bound;
+  }
+
+private:
+  Category m_category{Category::Explicit};
+  int64_t m_bound;
+  bool m_is_bound_known = false;
+};
+
+class ArrayShape {
+public:
+  ArrayShape(ArrayBound lb, ArrayBound ub, uint64_t byte_stride)
+      : m_lb(lb), m_ub(ub), m_byte_stride(byte_stride) {}
+
+  const ArrayBound &GetLowerBound() const { return m_lb; }
+  const ArrayBound &GetUpperBound() const { return m_ub; }
+  int64_t GetNumberOfElements() const {
+    return m_ub.GetBound() - m_lb.GetBound() + 1;
+  }
+  uint64_t GetByteStride() const { return m_byte_stride; }
+
+  void SetByteStride(uint64_t byte_stride) { m_byte_stride = byte_stride; }
+
+private:
+  ArrayBound m_lb;
+  ArrayBound m_ub;
+  uint64_t m_byte_stride;
+};
+
+class FortranArray : public FortranType {
+public:
+  FortranArray(CompilerType element_type,
+               const llvm::SmallVectorImpl<ArrayShape> &dimensions,
+               ConstString array_type_name, uint64_t total_array_size,
+               bool is_allocatable, bool is_array_explicit,
+               uint64_t total_elements)
+      : m_element_type(element_type),
+        m_dimensions(dimensions.begin(), dimensions.end()),
+        m_total_elements(total_elements), m_is_allocatable(is_allocatable),
+        FortranType(TypeKind::KIND_ARRAY, array_type_name, total_array_size) {}
+  // TODO: Add necessary methods here
+  CompilerType GetElementType() const { return m_element_type; }
+  uint64_t GetTotalElements() const { return m_total_elements; }
+  bool IsAllocatable() const { return m_is_allocatable; }
+  bool IsSizeKnown() const { return m_is_explicit; }
+  uint64_t GetElementByteSize() const {
+    auto byte_size_or_err = m_element_type.GetByteSize(nullptr);
+    // TODO: Change this to returning an error, and change return type to
+    // expected<uint64_t>
+    if (!byte_size_or_err)
+      return 0;
+    return *byte_size_or_err;
+  }
+
+  size_t GetRank() const { return m_dimensions.size(); }
+  llvm::ArrayRef<ArrayShape> GetDimensions() { return m_dimensions; }
+
+private:
+  CompilerType m_element_type;
+  llvm::SmallVector<ArrayShape, 2> m_dimensions;
+  uint64_t m_total_elements;
+  bool m_is_allocatable;
+  // To know if the array is fully explicit without looping through the shapes
+  // every time
+  bool m_is_explicit;
+};
+
+ConstString CreateArrayTypeName(const CompilerType &element_type,
+                                const llvm::ArrayRef<ArrayShape> shapes,
+                                bool is_allocatable, bool is_star) {
+
+  std::string name_buffer;
+  llvm::raw_string_ostream name_stream(name_buffer);
+
+  name_stream << element_type.GetTypeName().AsCString(nullptr) << "(";
+  size_t rank = shapes.size();
+
+  for (size_t idx = 0; idx < rank; ++idx) {
+    if (idx > 0)
+      name_stream << ", ";
+
+    const ArrayBound &lb = shapes[idx].GetLowerBound();
+    const ArrayBound &ub = shapes[idx].GetUpperBound();
+
+    if (ub.IsStar()) {
+      // Assuming you want standard Fortran syntax (e.g., "1:*")
+      name_stream << lb.GetBound() << ":*";
+    } else if (ub.IsColon()) {
+      // Unknown bound elements
+      name_stream << ":";
+    } else if (ub.IsExplicit()) {
+      // Explicit bounds
+      if (lb.GetBound() != 1) {
+        name_stream << lb.GetBound() << ":";
+      }
+      name_stream << ub.GetBound();
+    }
+  }
+
+  name_stream << ")";
+
+  if (is_allocatable) {
+    name_stream << ", allocatable";
+  }
+
+  name_stream.flush();
+  return ConstString(name_buffer.c_str());
+}
+
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_FORTRANTYPES_H
\ No newline at end of file
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index 1dbba12e3e072..325fcdd558ba8 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include "TypeSystemFortran.h"
+#include "FortranTypes.h"
 
 #include "lldb/Core/DumpDataExtractor.h"
 #include "lldb/Core/PluginManager.h"
@@ -24,139 +25,6 @@ using namespace lldb_private::plugin::dwarf;
 
 LLDB_PLUGIN_DEFINE(TypeSystemFortran)
 
-namespace lldb_private {
-
-/// A simplified internal representation of a Fortran type.
-/// In the future, this will likely be replaced by a Flang-backed AST.
-class FortranType {
-public:
-  enum TypeKind {
-    KIND_INTEGER,
-    KIND_LOGICAL,
-    KIND_REAL,
-    KIND_COMPLEX,
-    KIND_FUNCTION,
-    KIND_ARRAY,
-    KIND_UNKNOWN
-  };
-  FortranType(int kind, const ConstString &name, uint64_t bitsize)
-      : m_kind(kind), m_bitsize(bitsize), m_type_name(name) {}
-  int GetKind() const { return m_kind; }
-  uint64_t GetBitSize() const { return m_bitsize; }
-  ConstString GetName() const { return m_type_name; }
-
-private:
-  int m_kind;
-  uint64_t m_bitsize;
-  ConstString m_type_name;
-};
-
-class FortranFunction : public FortranType {
-public:
-  FortranFunction(ConstString func_name,
-                  const SmallVectorImpl<CompilerType> &parameters)
-      : FortranType(FortranType::KIND_FUNCTION, func_name, 0) {
-    m_parameters.assign(parameters.begin(), parameters.end());
-  }
-  ArrayRef<CompilerType> GetParameters() const { return m_parameters; }
-  size_t GetNumberOfParameters() const { return m_parameters.size(); }
-
-private:
-  SmallVector<CompilerType, 4> m_parameters;
-};
-
-class ArrayBound {
-public:
-  enum class Category { Explicit, Star, Colon };
-  ArrayBound() = default;
-  ArrayBound(Category category) : m_category{category} {}
-  ArrayBound(Category category, int64_t bound)
-      : m_category{category}, m_bound(bound), m_is_bound_known(true) {}
-
-  bool IsExplicit() const { return m_category == Category::Explicit; }
-
-  bool IsStar() const { return m_category == Category::Star; }
-
-  bool IsColon() const { return m_category == Category::Colon; }
-
-  void SetCategory(Category c) { m_category = c; }
-
-  int64_t GetBound() const {
-    assert(m_is_bound_known && "Can't get the bound if it is not explicit");
-    return m_bound;
-  }
-
-  void SetBound(int64_t bound) {
-    m_is_bound_known = true;
-    m_bound = bound;
-  }
-
-private:
-  Category m_category{Category::Explicit};
-  int64_t m_bound;
-  bool m_is_bound_known = false;
-};
-
-class ArrayShape {
-public:
-  ArrayShape(ArrayBound lb, ArrayBound ub, uint64_t byte_stride)
-      : m_lb(lb), m_ub(ub), m_byte_stride(byte_stride) {}
-
-  const ArrayBound &GetLowerBound() const { return m_lb; }
-  const ArrayBound &GetUpperBound() const { return m_ub; }
-  int64_t GetNumberOfElements() const {
-    return m_ub.GetBound() - m_lb.GetBound() + 1;
-  }
-  uint64_t GetByteStride() const { return m_byte_stride; }
-
-  void SetByteStride(uint64_t byte_stride) { m_byte_stride = byte_stride; }
-
-private:
-  ArrayBound m_lb;
-  ArrayBound m_ub;
-  uint64_t m_byte_stride;
-};
-
-class FortranArray : public FortranType {
-public:
-  FortranArray(CompilerType element_type,
-               const SmallVectorImpl<ArrayShape> &dimensions,
-               ConstString array_type_name, uint64_t total_array_size,
-               bool is_allocatable, bool is_array_explicit,
-               uint64_t total_elements)
-      : m_element_type(element_type),
-        m_dimensions(dimensions.begin(), dimensions.end()),
-        m_total_elements(total_elements), m_is_allocatable(is_allocatable), 
-        FortranType(TypeKind::KIND_ARRAY, array_type_name, total_array_size) {}
-  // TODO: Add necessary methods here
-  CompilerType GetElementType() const { return m_element_type; }
-  uint64_t GetTotalElements() const { return m_total_elements; }
-  bool IsAllocatable() const { return m_is_allocatable; }
-  bool IsSizeKnown() const { return m_is_explicit; }
-  uint64_t GetElementByteSize() const {
-    auto byte_size_or_err = m_element_type.GetByteSize(nullptr);
-    // TODO: Change this to returning an error, and change return type to
-    // expected<uint64_t>
-    if (!byte_size_or_err)
-      return 0;
-    return *byte_size_or_err;
-  }
-
-  size_t GetRank() const { return m_dimensions.size(); }
-  ArrayRef<ArrayShape> GetDimensions() { return m_dimensions; }
-
-private:
-  CompilerType m_element_type;
-  SmallVector<ArrayShape, 2> m_dimensions;
-  uint64_t m_total_elements;
-  bool m_is_allocatable;
-  // To know if the array is fully explicit without looping through the shapes
-  // every time
-  bool m_is_explicit;
-};
-
-} // namespace lldb_private
-
 /// Used to determine if TypeSystem supports the language passed in
 /// CreateInstance
 static bool IsLanguageSupported(LanguageType language) {
@@ -171,6 +39,7 @@ static bool IsLanguageSupported(LanguageType language) {
   return false;
 }
 
+// TODO: Should this be a lambda?
 static bool DumpComplex(Stream &s, const lldb_private::DataExtractor &data,
                         lldb::offset_t &offset, size_t data_byte_size) {
   if (sizeof(float) * 2 == data_byte_size) {
@@ -198,48 +67,6 @@ static bool DumpComplex(Stream &s, const lldb_private::DataExtractor &data,
   }
 }
 
-ConstString CreateArrayTypeName(const CompilerType &element_type,
-                                const llvm::ArrayRef<ArrayShape> shapes,
-                                bool is_allocatable, bool is_star) {
-
-  std::string name_buffer;
-  llvm::raw_string_ostream name_stream(name_buffer);
-
-  name_stream << element_type.GetTypeName().AsCString(nullptr) << "(";
-  size_t rank = shapes.size();
-
-  for (size_t idx = 0; idx < rank; ++idx) {
-    if (idx > 0)
-      name_stream << ", ";
-
-    const ArrayBound &lb = shapes[idx].GetLowerBound();
-    const ArrayBound &ub = shapes[idx].GetUpperBound();
-
-    if (ub.IsStar()) {
-      // Assuming you want standard Fortran syntax (e.g., "1:*")
-      name_stream << lb.GetBound() << ":*";
-    } else if (ub.IsColon()) {
-      // Unknown bound elements
-      name_stream << ":";
-    } else if (ub.IsExplicit()) {
-      // Explicit bounds
-      if (lb.GetBound() != 1) {
-        name_stream << lb.GetBound() << ":";
-      }
-      name_stream << ub.GetBound();
-    }
-  }
-
-  name_stream << ")";
-
-  if (is_allocatable) {
-    name_stream << ", allocatable";
-  }
-
-  name_stream.flush();
-  return ConstString(name_buffer.c_str());
-}
-
 char TypeSystemFortran::ID;
 
 TypeSystemFortran::~TypeSystemFortran() = default;
@@ -659,8 +486,6 @@ Expected<CompilerType> TypeSystemFortran::GetChildCompilerTypeAtIndex(
     }
 
     child_name = llvm::formatv("[{0}]", idx);
-    // TODO: Change this to calculate new array name and not reuse old one, same
-    // for total array size.
     ConstString type_name =
         CreateArrayTypeName(fortran_type->GetElementType(), new_dimensions,
                             is_allocatable, is_star);
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index f5fcc7b2e76d5..c6a3b42698eb7 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -375,6 +375,23 @@ class TypeSystemFortran : public TypeSystem {
     return 0;
   }
 
+  DWARFExpressionList
+  GetDataLocationExpression(lldb::opaque_compiler_type_t type);
+
+  DWARFExpressionList
+  GetUpperBoundExpression(lldb::opaque_compiler_type_t type);
+
+  DWARFExpressionList
+  GetLowerBoundExpression(lldb::opaque_compiler_type_t type);
+
+  DWARFExpressionList
+  GetElementCountExpression(lldb::opaque_compiler_type_t type);
+
+  DWARFExpressionList GetAllocatedExpression(lldb::opaque_compiler_type_t type);
+
+  DWARFExpressionList
+  GetByteStrideExpression(lldb::opaque_compiler_type_t type);
+
 #ifndef NDEBUG
   /// Convenience LLVM-style dump method for use in the debugger only.
   LLVM_DUMP_METHOD void dump(lldb::opaque_compiler_type_t type) const override {

>From 627ef93bdcd7b39bfaf5533da8b0580bf7bc7e34 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Wed, 22 Jul 2026 22:57:02 +0300
Subject: [PATCH 37/44] [lldb][Fortran] Implemented support for dynamic array
 types, not tested yet

---
 .../Plugins/Language/Fortran/CMakeLists.txt   |   1 +
 .../Plugins/Language/Fortran/DynamicArray.cpp | 194 ++++++++++++++-
 .../DWARF/DWARFASTParserFortran.cpp           | 222 ++++++++++--------
 .../Plugins/TypeSystem/Fortran/FortranTypes.h | 100 +++++++-
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 197 +++++++---------
 .../TypeSystem/Fortran/TypeSystemFortran.h    |  43 ++--
 6 files changed, 494 insertions(+), 263 deletions(-)

diff --git a/lldb/source/Plugins/Language/Fortran/CMakeLists.txt b/lldb/source/Plugins/Language/Fortran/CMakeLists.txt
index 7c5faa87aeaba..02326a976139b 100644
--- a/lldb/source/Plugins/Language/Fortran/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/Fortran/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_lldb_library(lldbPluginFortranLanguage PLUGIN
   FortranLanguage.cpp
+  DynamicArray.cpp
 
   LINK_LIBS
     lldbCore
diff --git a/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp b/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
index 43bbad9fc3054..789bf53764f58 100644
--- a/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
+++ b/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
@@ -6,9 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+// TODO: Clean this up, fix names, add comments
 #include "DynamicArray.h"
 
 #include "lldb/Expression/DWARFExpressionList.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/SymbolContext.h"
 
 #include "Plugins/TypeSystem/Fortran/FortranTypes.h"
 #include "Plugins/TypeSystem/Fortran/TypeSystemFortran.h"
@@ -18,6 +21,7 @@
 using namespace lldb;
 using namespace lldb_private;
 using namespace lldb_private::formatters;
+using namespace lldb_private::plugin::fortran;
 
 namespace lldb_private {
 namespace formatters {
@@ -39,6 +43,8 @@ class DynamicArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
 private:
   CompilerType m_element_type;
   CompilerType m_array_type;
+  lldb::addr_t m_array_addr;
+  bool m_allocated;
   llvm::DenseMap<FortranArray *, FortranType *> m_children_map;
 };
 
@@ -48,6 +54,165 @@ DynamicArraySyntheticFrontEnd::DynamicArraySyntheticFrontEnd(
   if (valobj_sp)
     Update();
 }
+// TODO: Handle star arrays
+lldb::ChildCacheState DynamicArraySyntheticFrontEnd::Update() {
+  m_children_map.clear();
+  m_allocated = false;
+
+  lldb::opaque_compiler_type_t raw_type =
+      m_backend.GetCompilerType().GetOpaqueQualType();
+  if (!raw_type)
+    return lldb::ChildCacheState::eRefetch;
+  auto ast_sp = m_backend.GetCompilerType().GetTypeSystem<TypeSystemFortran>();
+  if (!ast_sp)
+    return lldb::ChildCacheState::eRefetch;
+  FortranArray *array_type = static_cast<FortranArray *>(raw_type);
+  m_element_type = array_type->GetElementType();
+  if (!array_type->IsDynamic())
+    return lldb::ChildCacheState::eReuse;
+  lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
+  ExecutionContext exe_ctx(m_backend.GetExecutionContextRef());
+  Target *target = exe_ctx.GetTargetPtr();
+  StackFrame *frame = exe_ctx.GetFramePtr();
+
+  if (!target || !frame)
+    return lldb::ChildCacheState::eRefetch;
+  SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction);
+
+  if (!sc.function)
+    return lldb::ChildCacheState::eRefetch;
+
+  loclist_base_load_addr = sc.function->GetAddress().GetLoadAddress(target);
+
+  DWARFExpressionList allocated_exp = array_type->GetAllocatedExpression();
+  DWARFExpressionList data_location_exp =
+      array_type->GetDataLocationExpression();
+
+  llvm::Expected<Value> allocated_val_or_err = allocated_exp.Evaluate(
+      &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
+  if (!allocated_val_or_err)
+    return lldb::ChildCacheState::eRefetch;
+
+  Value allocated_val = *allocated_val_or_err;
+  if (allocated_val.ResolveValue(&exe_ctx).IsZero())
+    return lldb::ChildCacheState::eRefetch;
+
+  m_allocated = true;
+
+  llvm::Expected<Value> array_addr_or_err = data_location_exp.Evaluate(
+      &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
+  if (!array_addr_or_err)
+    return lldb::ChildCacheState::eRefetch;
+
+  Value array_addr = *array_addr_or_err;
+
+  m_array_addr =
+      array_addr.ResolveValue(&exe_ctx).ULongLong(LLDB_INVALID_ADDRESS);
+
+  llvm::ArrayRef<ArrayShape> dimensions = array_type->GetDimensions();
+  FortranArrayMetadata array_info;
+  array_info.element_type = m_element_type;
+  array_info.is_allocatable = array_type->IsAllocatable();
+  array_info.is_dynamic = false;
+  array_info.is_star = false;
+  for (ArrayShape dimension : dimensions) {
+    FortranDimension dimension_info;
+    DWARFExpressionList lower_bound_exp = dimension.GetLowerBoundExpression();
+    DWARFExpressionList upper_bound_exp = dimension.GetUpperBoundExpression();
+    DWARFExpressionList element_count_exp =
+        dimension.GetElementCountExpression();
+    DWARFExpressionList byte_stride_exp = dimension.GetByteStrideExpression();
+    if (lower_bound_exp.IsValid()) {
+      llvm::Expected<Value> lower_bound_or_err = lower_bound_exp.Evaluate(
+          &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
+      if (!lower_bound_or_err)
+        return lldb::ChildCacheState::eRefetch;
+
+      Value lower_bound = *lower_bound_or_err;
+
+      dimension_info.lower_bound =
+          lower_bound.ResolveValue(&exe_ctx).SLongLong(0);
+    } else
+      dimension_info.lower_bound = dimension.GetLowerBound().GetBound();
+
+    if (upper_bound_exp.IsValid()) {
+      llvm::Expected<Value> upper_bound_or_err = upper_bound_exp.Evaluate(
+          &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
+      if (!upper_bound_or_err)
+        return lldb::ChildCacheState::eRefetch;
+
+      Value upper_bound = *upper_bound_or_err;
+      dimension_info.upper_bound =
+          upper_bound.ResolveValue(&exe_ctx).SLongLong(0);
+    } else
+      dimension_info.upper_bound = dimension.GetUpperBound().GetBound();
+    // TODO: Handle cases where we only upper and lower bound
+    if (element_count_exp.IsValid()) {
+      llvm::Expected<Value> element_count_or_err = element_count_exp.Evaluate(
+          &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
+      if (!element_count_or_err)
+        return lldb::ChildCacheState::eRefetch;
+
+      Value element_count = *element_count_or_err;
+      dimension_info.element_count =
+          element_count.ResolveValue(&exe_ctx).ULongLong(0);
+    } else
+      dimension_info.element_count = dimension.GetElementCount();
+
+    if (byte_stride_exp.IsValid()) {
+      llvm::Expected<Value> byte_stride_or_err = byte_stride_exp.Evaluate(
+          &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
+      if (!byte_stride_or_err)
+        return lldb::ChildCacheState::eRefetch;
+
+      Value byte_stride = *byte_stride_or_err;
+      dimension_info.byte_stride =
+          byte_stride.ResolveValue(&exe_ctx).SLongLong(0);
+    } else
+      dimension_info.byte_stride = dimension.GetByteStride();
+
+    array_info.dimensions.push_back(dimension_info);
+  }
+  uint64_t total_elements = 1;
+  uint64_t total_array_size = 0;
+
+  for (auto &dim : array_info.dimensions) {
+    uint64_t count = std::get<uint64_t>(dim.element_count);
+
+    int64_t lb = 0;
+    int64_t ub = 0;
+    if (const auto *l_val = std::get_if<int64_t>(&dim.lower_bound))
+      lb = *l_val;
+    if (const auto *u_val = std::get_if<int64_t>(&dim.upper_bound))
+      ub = *u_val;
+
+    if (count == 0) {
+      if (ub >= lb) {
+        count = ub - lb + 1;
+      } else if (array_info.is_star && &dim == &array_info.dimensions.back()) {
+        count = 0;
+      }
+    }
+
+    // Update the struct so it's correct for later indexing math
+    dim.element_count = count;
+    total_elements *= count;
+  }
+
+  // Calculate total byte size of the array
+  llvm::Expected<uint64_t> elem_byte_size_or_err =
+      m_element_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
+
+  if (elem_byte_size_or_err) {
+    total_array_size = total_elements * (*elem_byte_size_or_err);
+  } else {
+    // Fallback if the element type is incomplete
+    total_array_size = 0;
+  }
+  m_array_type =
+      ast_sp->CreateArrayType(array_info, total_array_size, total_elements);
+  return lldb::ChildCacheState::eRefetch;
+}
 
 llvm::Expected<uint32_t> DynamicArraySyntheticFrontEnd::CalculateNumChildren() {
   lldb::opaque_compiler_type_t raw_type = m_array_type.GetOpaqueQualType();
@@ -63,6 +228,8 @@ llvm::Expected<uint32_t> DynamicArraySyntheticFrontEnd::CalculateNumChildren() {
 
 lldb::ValueObjectSP
 DynamicArraySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
+  if (!m_allocated)
+    return ValueObjectSP();
   lldb::opaque_compiler_type_t raw_type = m_array_type.GetOpaqueQualType();
 
   if (!raw_type)
@@ -83,7 +250,8 @@ DynamicArraySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
   llvm::ArrayRef<ArrayShape> old_dimensions = fortran_type->GetDimensions();
   int64_t ub = old_dimensions.front().GetUpperBound().GetBound();
   int64_t lb = old_dimensions.front().GetLowerBound().GetBound();
-  if ((idx + 1) < lb || (idx + 1) > ub)
+  uint64_t num_elements = old_dimensions.front().GetNumberOfElements();
+  if (idx >= num_elements)
     return ValueObjectSP();
 
   if (old_dimensions.size() > 1) {
@@ -106,7 +274,6 @@ DynamicArraySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
     bool is_allocatable = fortran_type->IsAllocatable();
     uint64_t new_total_elements = fortran_type->GetTotalElements() /
                                   old_first_dimension.GetNumberOfElements();
-    // Fortran is 1-base indexed, and the offset of element array(1) is 0
     if (old_dimensions.front().GetByteStride() != 0)
       child_byte_offset = idx * old_dimensions.front().GetByteStride();
     else
@@ -121,25 +288,34 @@ DynamicArraySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
       child_byte_size = new_total_elements * fortran_type->GetElementByteSize();
     }
 
-    child_name = llvm::formatv("[{0}]", idx);
+    child_name = llvm::formatv("[{0}]", lb + idx);
     ConstString type_name =
         CreateArrayTypeName(fortran_type->GetElementType(), new_dimensions,
                             is_allocatable, is_star);
-    FortranArray *array_type =
-        new FortranArray(fortran_type->GetElementType(), new_dimensions,
-                         type_name, child_byte_size, is_allocatable,
-                         fortran_type->IsSizeKnown(), new_total_elements);
+    FortranArray *array_type = new FortranArray(
+        fortran_type->GetElementType(), new_dimensions, type_name,
+        child_byte_size, is_allocatable, fortran_type->IsDynamic(),
+        new_total_elements, fortran_type->GetAllocatedExpression(),
+        fortran_type->GetDataLocationExpression());
     CompilerType array_compiler_type(
         TypeSystemWP(m_array_type.GetTypeSystem().GetSharedPointer()),
         (void *)array_type);
-    
+    m_children_map[fortran_type] = array_type;
+    uint64_t array_address = m_array_addr + child_byte_offset;
+    return CreateChildValueObjectFromAddress(child_name, array_address,
+                                             m_backend.GetExecutionContextRef(),
+                                             array_compiler_type);
   } else {
     if (old_dimensions.front().GetByteStride() != 0)
       child_byte_offset = idx * old_dimensions.front().GetByteStride();
     else
       child_byte_offset = idx * fortran_type->GetElementByteSize();
     child_byte_size = fortran_type->GetElementByteSize();
-    return fortran_type->GetElementType();
+    StreamString name;
+    name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+    return CreateChildValueObjectFromAddress(
+        name.GetString(), m_array_addr + child_byte_offset,
+        m_backend.GetExecutionContextRef(), m_element_type);
   }
 }
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
index d4bbe0da5ab9b..c165caf67d2ca 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
@@ -13,6 +13,7 @@
 #include "DWARFDeclContext.h"
 #include "DWARFDefines.h"
 #include "LogChannelDWARF.h"
+#include "Plugins/TypeSystem/Fortran/FortranTypes.h"
 #include "SymbolFileDWARF.h"
 #include "SymbolFileDWARFDebugMap.h"
 #include "UniqueDWARFASTType.h"
@@ -25,30 +26,55 @@ using namespace lldb;
 using namespace lldb_private;
 using namespace lldb_private::plugin::dwarf;
 using namespace llvm::dwarf;
+using namespace lldb_private::plugin::fortran;
 
 DWARFASTParserFortran::DWARFASTParserFortran(TypeSystemFortran &ast)
     : DWARFASTParser(Kind::DWARFASTParserFortran), m_ast(ast) {}
 
 DWARFASTParserFortran::~DWARFASTParserFortran() {}
 
-// Struct holding extra info needed to characterize Fortran Arrays
-// TODO: Add comments explaining each one
-struct FortranArrayInfo {
-
-  bool is_star = false;
-  bool is_allocatable = false;
-  bool size_known = true;
-
-  llvm::SmallVector<std::optional<uint64_t>, 1> elements_per_dimension;
-  llvm::SmallVector<std::optional<uint64_t>, 1> byte_stride;
-  llvm::SmallVector<int64_t, 1> lower_bounds;
-};
+DWARFExpressionList GetDWARFExpression(const DWARFDIE &die,
+                                       const DWARFFormValue &form_value,
+                                       ModuleSP module) {
+  auto data = die.GetData();
+  uint32_t offset = form_value.BlockData() - data.GetDataStart();
+  uint32_t length = form_value.Unsigned();
+  return DWARFExpressionList(module, DataExtractor(data, offset, length),
+                             die.GetCU());
+}
 
-FortranArrayInfo ParseArray(const DWARFDIE &parent_die,
-                            const ExecutionContext *exe_ctx) {
-  FortranArrayInfo array_info;
+FortranArrayMetadata ParseArray(const DWARFDIE &parent_die,
+                                const ExecutionContext *exe_ctx) {
+  // We first process the array type attributes and then each individual
+  // subrange
+  FortranArrayMetadata array_info;
+  DWARFAttributes parent_attributes = parent_die.GetAttributes();
+  ModuleSP parent_module(parent_die.GetModule());
+  for (int idx = 0; idx < parent_attributes.Size(); idx++) {
+    const dw_attr_t attr = parent_attributes.AttributeAtIndex(idx);
+    DWARFFormValue form_value;
+    if (!parent_attributes.ExtractFormValueAtIndex(idx, form_value))
+      continue;
+    switch (attr) {
+    case DW_AT_data_location:
+      array_info.is_dynamic = true;
+      array_info.data_location_exp =
+          GetDWARFExpression(parent_die, form_value, parent_module);
+      break;
+    case DW_AT_allocated:
+      array_info.is_allocatable = true;
+      array_info.is_dynamic = true;
+      array_info.allocated_exp =
+          GetDWARFExpression(parent_die, form_value, parent_module);
+      break;
+    default:
+      break;
+    }
+  }
   for (DWARFDIE die : parent_die.children()) {
     const dw_tag_t tag = die.Tag();
+    ModuleSP module(die.GetModule());
+
     if (tag != DW_TAG_subrange_type)
       continue;
     // If a subrange of an array is a star meaning we can't infer how many
@@ -60,92 +86,87 @@ FortranArrayInfo ParseArray(const DWARFDIE &parent_die,
     if (attributes.Size() == 0)
       continue;
 
-    std::optional<uint64_t> num_elements;
-    std::optional<uint64_t> byte_stride;
-    int64_t lower_bound = 1;
-    int64_t upper_bound = 0;
+    DWARFValue num_elements;
+    DWARFValue byte_stride;
+    DWARFValue lower_bound;
+    DWARFValue upper_bound;
     bool upper_bound_valid = false;
     for (size_t i = 0; i < attributes.Size(); ++i) {
       const dw_attr_t attr = attributes.AttributeAtIndex(i);
       DWARFFormValue form_value;
-      if (attributes.ExtractFormValueAtIndex(i, form_value)) {
-        switch (attr) {
-        case DW_AT_name:
-          break;
-
-        case DW_AT_count:
-          array_info.is_star = false;
-          if (DWARFDIE var_die = die.GetReferencedDIE(DW_AT_count)) {
-            if (var_die.Tag() == DW_TAG_variable)
-              if (exe_ctx) {
-                if (auto frame = exe_ctx->GetFrameSP()) {
-                  Status error;
-                  lldb::VariableSP var_sp;
-                  auto valobj_sp = frame->GetValueForVariableExpressionPath(
-                      var_die.GetName(), eNoDynamicValues, 0, var_sp, error);
-                  if (valobj_sp) {
-                    num_elements = valobj_sp->GetValueAsUnsigned(0);
-                    break;
-                  }
+      if (!attributes.ExtractFormValueAtIndex(i, form_value))
+        continue;
+      switch (attr) {
+      case DW_AT_name:
+        break;
+
+      case DW_AT_count:
+        array_info.is_star = false;
+        if (DWARFDIE var_die = die.GetReferencedDIE(DW_AT_count)) {
+          if (var_die.Tag() == DW_TAG_variable)
+            if (exe_ctx) {
+              if (auto frame = exe_ctx->GetFrameSP()) {
+                Status error;
+                lldb::VariableSP var_sp;
+                auto valobj_sp = frame->GetValueForVariableExpressionPath(
+                    var_die.GetName(), eNoDynamicValues, 0, var_sp, error);
+                if (valobj_sp) {
+                  num_elements = valobj_sp->GetValueAsUnsigned(0);
+                  break;
                 }
               }
-          } else if (DWARFFormValue::IsBlockForm(form_value.Form())) {
-            // TODO: Handle cases where we have to read the dope vector
-            array_info.size_known = false;
-          } else
-            num_elements = form_value.Unsigned();
-          break;
-
-        case DW_AT_byte_stride:
-          if (DWARFFormValue::IsBlockForm(form_value.Form())) {
-            // TODO: Handle cases where we have to read the dope vector
-            byte_stride = 0;
-            array_info.size_known = false;
-          } else
-            byte_stride = form_value.Unsigned();
-          break;
-
-        case DW_AT_lower_bound:
-          // TODO: Handle cases where we have to read the dope vector
-          if (DWARFFormValue::IsBlockForm(form_value.Form())) {
-            lower_bound = 1;
-            array_info.size_known = false;
-          }
+            }
+        } else if (DWARFFormValue::IsBlockForm(form_value.Form())) {
+          num_elements = GetDWARFExpression(die, form_value, module);
+          array_info.is_dynamic = true;
+        } else
+          num_elements = form_value.Unsigned();
+        break;
 
-          else
-            lower_bound = form_value.Signed();
-          break;
-
-        case DW_AT_upper_bound:
-          upper_bound_valid = true;
-          // TODO: Handle cases where we have to read the dope vector
-          if (DWARFFormValue::IsBlockForm(form_value.Form())) {
-            array_info.size_known = false;
-            upper_bound = 1;
-          } else
-            upper_bound = form_value.Signed();
-          break;
-
-        case DW_AT_allocated:
-          array_info.is_allocatable = true;
-          array_info.size_known = false;
-          // TODO: Save the DWARFExpression so we can query the dope vector
-          // every time
-
-        default:
-          break;
-        }
+      case DW_AT_byte_stride:
+        if (DWARFFormValue::IsBlockForm(form_value.Form())) {
+          byte_stride = GetDWARFExpression(die, form_value, module);
+          array_info.is_dynamic = false;
+        } else
+          byte_stride = form_value.Unsigned();
+        break;
+
+      case DW_AT_lower_bound:
+        if (DWARFFormValue::IsBlockForm(form_value.Form())) {
+          lower_bound = GetDWARFExpression(die, form_value, module);
+          array_info.is_dynamic = false;
+        } else
+          lower_bound = form_value.Signed();
+        break;
+
+      case DW_AT_upper_bound:
+        upper_bound_valid = true;
+        // TODO: Handle cases where we have to read the dope vector
+        if (DWARFFormValue::IsBlockForm(form_value.Form())) {
+          array_info.is_dynamic = false;
+          upper_bound = GetDWARFExpression(die, form_value, module);
+        } else
+          upper_bound = form_value.Signed();
+        break;
+
+      default:
+        break;
       }
     }
 
-    if (!num_elements || *num_elements == 0) {
-      if (upper_bound_valid && upper_bound >= lower_bound)
-        num_elements = upper_bound - lower_bound + 1;
+    if (std::holds_alternative<std::monostate>(num_elements)) {
+      if (std::holds_alternative<std::int64_t>(upper_bound) &&
+          std::holds_alternative<std::int64_t>(lower_bound))
+        num_elements =
+            static_cast<uint64_t>(std::get<int64_t>(upper_bound) -
+                                  std::get<int64_t>(lower_bound) + 1);
     }
-
-    array_info.elements_per_dimension.push_back(num_elements);
-    array_info.byte_stride.push_back(byte_stride);
-    array_info.lower_bounds.push_back(lower_bound);
+    FortranDimension dimension;
+    dimension.element_count = num_elements;
+    dimension.lower_bound = lower_bound;
+    dimension.upper_bound = upper_bound;
+    dimension.byte_stride = byte_stride;
+    array_info.dimensions.push_back(dimension);
   }
   return array_info;
 }
@@ -237,28 +258,25 @@ lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(const SymbolContext &sc,
           uint64_t total_array_size = 0;
           uint64_t total_elements = 1;
           if (array_element_type.GetCompleteType()) {
-            FortranArrayInfo array_info = ParseArray(die, nullptr);
+            FortranArrayMetadata array_info = ParseArray(die, nullptr);
             // We need to calculate the total array size, if it is known
             // at compile time
-            if (array_info.size_known) {
-              for (int idx = 0; idx < array_info.byte_stride.size(); idx++) {
-                total_elements *= *array_info.elements_per_dimension[idx];
+            if (!array_info.is_dynamic) {
+              for (int idx = 0; idx < array_info.dimensions.size(); idx++) {
+                total_elements *= std::get<uint64_t>(
+                    array_info.dimensions[idx].element_count);
               }
 
               // Total size is just total elements * the size of one element
               auto byte_size_or_err = array_element_type.GetByteSize(nullptr);
-              if (byte_size_or_err) {
+              if (byte_size_or_err)
                 total_array_size = total_elements * (*byte_size_or_err);
-              } else {
+              else
                 total_array_size = 0;
-              }
             }
 
-            compiler_type = m_ast.CreateArrayType(
-                array_info.elements_per_dimension, array_info.byte_stride,
-                array_info.lower_bounds, array_element_type,
-                array_info.is_allocatable, array_info.is_star,
-                total_array_size * 8, total_elements);
+            compiler_type = m_ast.CreateArrayType(array_info, total_array_size,
+                                                  total_elements);
 
             type_sp = dwarf->MakeType(
                 die.GetID(), compiler_type.GetTypeName(), total_array_size,
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h b/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h
index be933b7c7e8be..f1c5cdb3a8345 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h
@@ -9,6 +9,7 @@
 #ifndef LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_FORTRANTYPES_H
 #define LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_FORTRANTYPES_H
 
+#include "lldb/Expression/DWARFExpressionList.h"
 #include "lldb/Symbol/CompilerType.h"
 #include "lldb/Utility/ConstString.h"
 
@@ -16,6 +17,32 @@
 #include "llvm/ADT/SmallVector.h"
 
 namespace lldb_private {
+namespace plugin {
+namespace fortran {
+using DWARFValue =
+    std::variant<std::monostate, // Represents "Default" or "Not Present"
+                 uint64_t,       // Constant value (e.g., constant byte stride)
+                 int64_t,
+                 DWARFExpressionList // Dynamic expression (e.g.,
+                                     // variable/runtime stride)
+                 >;
+
+struct FortranDimension {
+  DWARFValue lower_bound;
+  DWARFValue upper_bound;
+  DWARFValue element_count;
+  DWARFValue byte_stride;
+};
+
+struct FortranArrayMetadata {
+  CompilerType element_type;
+  llvm::SmallVector<FortranDimension, 4> dimensions;
+  bool is_allocatable = false;
+  bool is_dynamic = false;
+  bool is_star = false;
+  std::optional<DWARFExpressionList> allocated_exp;
+  std::optional<DWARFExpressionList> data_location_exp;
+};
 
 /// A simplified internal representation of a Fortran type.
 /// In the future, this will likely be replaced by a Flang-backed AST.
@@ -90,22 +117,62 @@ class ArrayBound {
 
 class ArrayShape {
 public:
+  ArrayShape() = default;
   ArrayShape(ArrayBound lb, ArrayBound ub, uint64_t byte_stride)
       : m_lb(lb), m_ub(ub), m_byte_stride(byte_stride) {}
 
   const ArrayBound &GetLowerBound() const { return m_lb; }
   const ArrayBound &GetUpperBound() const { return m_ub; }
+  const uint64_t GetByteStride() const { return m_byte_stride; }
+  const uint64_t GetElementCount() const { return m_element_count; }
+
   int64_t GetNumberOfElements() const {
     return m_ub.GetBound() - m_lb.GetBound() + 1;
   }
-  uint64_t GetByteStride() const { return m_byte_stride; }
 
+  const DWARFExpressionList &GetElementCountExpression() const {
+    return m_element_count_exp;
+  }
+  const DWARFExpressionList &GetUpperBoundExpression() const {
+    return m_upper_bound_exp;
+  }
+  const DWARFExpressionList &GetLowerBoundExpression() const {
+    return m_lower_bound_exp;
+  }
+  const DWARFExpressionList &GetByteStrideExpression() const {
+    return m_byte_stride_exp;
+  }
+
+  void SetLowerBound(const ArrayBound &lb) { m_lb = lb; }
+  void SetUpperBound(const ArrayBound &ub) { m_ub = ub; }
   void SetByteStride(uint64_t byte_stride) { m_byte_stride = byte_stride; }
+  void SetElementCount(uint64_t element_count) {
+    m_element_count = element_count;
+  }
+
+  void SetElementCountExpression(DWARFExpressionList expr) {
+    m_element_count_exp = std::move(expr);
+  }
+  void SetUpperBoundExpression(DWARFExpressionList expr) {
+    m_upper_bound_exp = std::move(expr);
+  }
+  void SetLowerBoundExpression(DWARFExpressionList expr) {
+    m_lower_bound_exp = std::move(expr);
+  }
+  void SetByteStrideExpression(DWARFExpressionList expr) {
+    m_byte_stride_exp = std::move(expr);
+  }
 
 private:
   ArrayBound m_lb;
   ArrayBound m_ub;
   uint64_t m_byte_stride;
+  uint64_t m_element_count;
+
+  DWARFExpressionList m_element_count_exp;
+  DWARFExpressionList m_upper_bound_exp;
+  DWARFExpressionList m_lower_bound_exp;
+  DWARFExpressionList m_byte_stride_exp;
 };
 
 class FortranArray : public FortranType {
@@ -113,17 +180,20 @@ class FortranArray : public FortranType {
   FortranArray(CompilerType element_type,
                const llvm::SmallVectorImpl<ArrayShape> &dimensions,
                ConstString array_type_name, uint64_t total_array_size,
-               bool is_allocatable, bool is_array_explicit,
-               uint64_t total_elements)
+               bool is_allocatable, bool is_dynamic, uint64_t total_elements,
+               DWARFExpressionList allocated_exp,
+               DWARFExpressionList data_location_exp)
       : m_element_type(element_type),
         m_dimensions(dimensions.begin(), dimensions.end()),
-        m_total_elements(total_elements), m_is_allocatable(is_allocatable),
+        m_is_allocatable(is_allocatable), m_is_dynamic(is_dynamic),
+        m_total_elements(total_elements), m_allocated_exp(allocated_exp),
+        m_data_location_exp(data_location_exp),
         FortranType(TypeKind::KIND_ARRAY, array_type_name, total_array_size) {}
   // TODO: Add necessary methods here
   CompilerType GetElementType() const { return m_element_type; }
   uint64_t GetTotalElements() const { return m_total_elements; }
   bool IsAllocatable() const { return m_is_allocatable; }
-  bool IsSizeKnown() const { return m_is_explicit; }
+  bool IsDynamic() const { return m_is_dynamic; }
   uint64_t GetElementByteSize() const {
     auto byte_size_or_err = m_element_type.GetByteSize(nullptr);
     // TODO: Change this to returning an error, and change return type to
@@ -134,7 +204,12 @@ class FortranArray : public FortranType {
   }
 
   size_t GetRank() const { return m_dimensions.size(); }
-  llvm::ArrayRef<ArrayShape> GetDimensions() { return m_dimensions; }
+  llvm::ArrayRef<ArrayShape> GetDimensions() const { return m_dimensions; }
+
+  DWARFExpressionList GetAllocatedExpression() const { return m_allocated_exp; }
+  DWARFExpressionList GetDataLocationExpression() const {
+    return m_data_location_exp;
+  }
 
 private:
   CompilerType m_element_type;
@@ -143,12 +218,14 @@ class FortranArray : public FortranType {
   bool m_is_allocatable;
   // To know if the array is fully explicit without looping through the shapes
   // every time
-  bool m_is_explicit;
+  bool m_is_dynamic;
+  DWARFExpressionList m_allocated_exp;
+  DWARFExpressionList m_data_location_exp;
 };
 
-ConstString CreateArrayTypeName(const CompilerType &element_type,
-                                const llvm::ArrayRef<ArrayShape> shapes,
-                                bool is_allocatable, bool is_star) {
+inline ConstString CreateArrayTypeName(const CompilerType &element_type,
+                                       const llvm::ArrayRef<ArrayShape> shapes,
+                                       bool is_allocatable, bool is_star) {
 
   std::string name_buffer;
   llvm::raw_string_ostream name_stream(name_buffer);
@@ -187,7 +264,8 @@ ConstString CreateArrayTypeName(const CompilerType &element_type,
   name_stream.flush();
   return ConstString(name_buffer.c_str());
 }
-
+} // namespace fortran
+} // namespace plugin
 } // namespace lldb_private
 
 #endif // LLDB_SOURCE_PLUGINS_TYPESYSTEM_FORTRAN_FORTRANTYPES_H
\ No newline at end of file
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index 325fcdd558ba8..ecbb185e6694f 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -21,6 +21,7 @@
 using namespace lldb;
 using namespace lldb_private;
 using namespace llvm;
+using namespace lldb_private::plugin::fortran;
 using namespace lldb_private::plugin::dwarf;
 
 LLDB_PLUGIN_DEFINE(TypeSystemFortran)
@@ -207,53 +208,107 @@ CompilerType TypeSystemFortran::CreateType(uint32_t kind, uint64_t bitsize,
   return GetOrCreateFortranType(underlying_kind, bitsize, name);
 }
 
-CompilerType TypeSystemFortran::CreateArrayType(
-    llvm::SmallVectorImpl<std::optional<uint64_t>> &elements_per_dimension,
-    llvm::SmallVectorImpl<std::optional<uint64_t>> &byte_strides,
-    llvm::SmallVectorImpl<int64_t> &lower_bounds, CompilerType element_type,
-    bool is_allocatable, bool is_star, uint64_t total_array_size,
-    uint64_t total_elements) {
+CompilerType TypeSystemFortran::CreateArrayType(FortranArrayMetadata array_info,
+                                                uint64_t total_array_size,
+                                                uint64_t total_elements) {
 
-  size_t rank = elements_per_dimension.size();
+  size_t rank = array_info.dimensions.size();
   llvm::SmallVector<ArrayShape, 2> array_shapes;
   ConstString type_name;
-  bool is_size_known = true;
-  if (total_array_size == 0)
-    is_size_known = false;
-  for (size_t idx = 0; idx < rank; ++idx) {
+  for (int idx = 0; idx < rank; ++idx) {
+    ArrayShape shape;
     ArrayBound lb;
     ArrayBound ub;
     ArrayBound::Category bound_category;
     uint64_t byte_stride;
-    auto byte_stride_or_err = element_type.GetByteSize(nullptr);
-    if (!byte_stride_or_err) {
-      LLDB_LOG_ERROR(GetLog(LLDBLog::Types), byte_stride_or_err.takeError(),
-                     "{0}");
-      return CompilerType();
+    int64_t dim_elements = -1;
+
+    if (std::holds_alternative<std::monostate>(
+            array_info.dimensions[idx].byte_stride)) {
+      auto byte_stride_or_err = array_info.element_type.GetByteSize(nullptr);
+      if (!byte_stride_or_err) {
+        LLDB_LOG_ERROR(GetLog(LLDBLog::Types), byte_stride_or_err.takeError(),
+                       "{0}");
+        return CompilerType();
+      }
+      shape.SetByteStride(*byte_stride_or_err);
     }
-    byte_stride = *byte_stride_or_err;
+
+    else if (std::holds_alternative<uint64_t>(
+                 array_info.dimensions[idx].byte_stride))
+      shape.SetByteStride(
+          std::get<uint64_t>(array_info.dimensions[idx].byte_stride));
     // If the elements for this dimension are unknown it is either colon or star
     // Star can only appear as the last bound
-    if (!elements_per_dimension[idx]) {
+
+    if (!std::holds_alternative<uint64_t>(
+            array_info.dimensions[idx].element_count)) {
       bound_category = ArrayBound::Category::Colon;
 
-      if (is_star && idx == rank - 1)
+      if (std::holds_alternative<std::monostate>(
+              array_info.dimensions[idx].element_count) &&
+          idx == rank - 1)
         bound_category = ArrayBound::Category::Star;
-    } else {
+    }
+
+    else {
       bound_category = ArrayBound::Category::Explicit;
-      ub.SetBound(lower_bounds[idx] + *elements_per_dimension[idx] - 1);
+      dim_elements =
+          std::get<uint64_t>(array_info.dimensions[idx].element_count);
+      shape.SetElementCount(dim_elements);
     }
+
     lb.SetCategory(bound_category);
-    lb.SetBound(lower_bounds[idx]);
     ub.SetCategory(bound_category);
-    array_shapes.emplace_back(lb, ub, byte_stride);
+
+    if (std::holds_alternative<int64_t>(
+            array_info.dimensions[idx].lower_bound)) {
+      int64_t lbound =
+          std::get<int64_t>(array_info.dimensions[idx].lower_bound);
+      lb.SetBound(lbound);
+      if (dim_elements != -1)
+        ub.SetBound(lbound + dim_elements - 1);
+    }
+
+    else if (std::holds_alternative<std::monostate>(
+                 array_info.dimensions[idx].lower_bound)) {
+      lb.SetBound(1);
+      ub.SetBound(dim_elements);
+    }
+
+    if (std::holds_alternative<int64_t>(array_info.dimensions[idx].upper_bound))
+      ub.SetBound(std::get<int64_t>(array_info.dimensions[idx].upper_bound));
+
+    shape.SetLowerBound(lb);
+    shape.SetUpperBound(ub);
+
+    if (std::holds_alternative<DWARFExpressionList>(
+            array_info.dimensions[idx].upper_bound))
+      shape.SetUpperBoundExpression(std::get<DWARFExpressionList>(
+          array_info.dimensions[idx].upper_bound));
+    if (std::holds_alternative<DWARFExpressionList>(
+            array_info.dimensions[idx].lower_bound))
+      shape.SetLowerBoundExpression(std::get<DWARFExpressionList>(
+          array_info.dimensions[idx].lower_bound));
+    if (std::holds_alternative<DWARFExpressionList>(
+            array_info.dimensions[idx].element_count))
+      shape.SetElementCountExpression(std::get<DWARFExpressionList>(
+          array_info.dimensions[idx].element_count));
+    if (std::holds_alternative<DWARFExpressionList>(
+            array_info.dimensions[idx].byte_stride))
+      shape.SetByteStrideExpression(std::get<DWARFExpressionList>(
+          array_info.dimensions[idx].byte_stride));
+
+    array_shapes.push_back(shape);
   }
   ConstString array_type_name =
-      CreateArrayTypeName(element_type, array_shapes, is_allocatable, is_star);
+      CreateArrayTypeName(array_info.element_type, array_shapes,
+                          array_info.is_allocatable, array_info.is_star);
 
   FortranArray *array_type = new FortranArray(
-      element_type, array_shapes, array_type_name, total_array_size,
-      is_allocatable, is_size_known, total_elements);
+      array_info.element_type, array_shapes, array_type_name, total_array_size,
+      array_info.is_allocatable, array_info.is_dynamic, total_elements,
+      *array_info.allocated_exp, *array_info.data_location_exp);
 
   return CompilerType(weak_from_this(), (void *)array_type);
 }
@@ -417,94 +472,6 @@ TypeSystemFortran::GetNumChildren(opaque_compiler_type_t type,
   }
 }
 
-Expected<CompilerType> TypeSystemFortran::GetChildCompilerTypeAtIndex(
-    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) {
-  if (!type)
-    return createStringError(
-        inconvertibleErrorCode(),
-        "Failed to craft intermediate Fortran array type: type is null.");
-  FortranType *super_type = static_cast<FortranType *>(type);
-
-  if (super_type->GetKind() != FortranType::KIND_ARRAY)
-    return CompilerType();
-
-  FortranArray *fortran_type = static_cast<FortranArray *>(super_type);
-
-  if (!fortran_type)
-    return CompilerType();
-
-  ArrayRef<ArrayShape> old_dimensions = fortran_type->GetDimensions();
-  int64_t ub = old_dimensions.front().GetUpperBound().GetBound();
-  int64_t lb = old_dimensions.front().GetLowerBound().GetBound();
-  if ((idx + 1) < lb || (idx + 1) > ub)
-    return createStringError(
-        inconvertibleErrorCode(),
-        llvm::formatv(
-            "Failed to craft intermediate Fortran array type: physical index "
-            "{0} is out of bounds (array only has {1} elements)",
-            idx, fortran_type->GetTotalElements()));
-
-  if (old_dimensions.size() > 1) {
-
-    SmallVector<ArrayShape, 2> new_dimensions(old_dimensions.begin() + 1,
-                                              old_dimensions.end());
-
-    ArrayShape old_first_dimension = old_dimensions.front();
-    uint64_t new_byte_stride;
-
-    if (old_first_dimension.GetByteStride() != 0)
-      new_byte_stride = old_first_dimension.GetNumberOfElements() *
-                        old_first_dimension.GetByteStride();
-    else
-      new_byte_stride = old_first_dimension.GetNumberOfElements() *
-                        fortran_type->GetElementByteSize();
-
-    new_dimensions.front().SetByteStride(new_byte_stride);
-    bool is_star = new_dimensions.back().GetLowerBound().IsStar();
-    bool is_allocatable = fortran_type->IsAllocatable();
-    uint64_t new_total_elements = fortran_type->GetTotalElements() /
-                                  old_first_dimension.GetNumberOfElements();
-    // Fortran is 1-base indexed, and the offset of element array(1) is 0
-    if (old_dimensions.front().GetByteStride() != 0)
-      child_byte_offset = idx * old_dimensions.front().GetByteStride();
-    else
-      child_byte_offset = idx * fortran_type->GetElementByteSize();
-
-    uint64_t last_dim_stride = new_dimensions.back().GetByteStride();
-
-    if (last_dim_stride != 0) {
-      child_byte_size =
-          new_dimensions.back().GetNumberOfElements() * last_dim_stride;
-    } else {
-      child_byte_size = new_total_elements * fortran_type->GetElementByteSize();
-    }
-
-    child_name = llvm::formatv("[{0}]", idx);
-    ConstString type_name =
-        CreateArrayTypeName(fortran_type->GetElementType(), new_dimensions,
-                            is_allocatable, is_star);
-    FortranArray *array_type =
-        new FortranArray(fortran_type->GetElementType(), new_dimensions,
-                         type_name, child_byte_size, is_allocatable,
-                         fortran_type->IsSizeKnown(), new_total_elements);
-
-    return CompilerType(weak_from_this(), (void *)array_type);
-  } else {
-    if (old_dimensions.front().GetByteStride() != 0)
-      child_byte_offset = idx * old_dimensions.front().GetByteStride();
-    else
-      child_byte_offset = idx * fortran_type->GetElementByteSize();
-    child_byte_size = fortran_type->GetElementByteSize();
-    return fortran_type->GetElementType();
-  }
-}
-
 bool TypeSystemFortran::IsIntegerType(opaque_compiler_type_t type,
                                       bool &is_signed) {
   if (!type)
@@ -546,7 +513,7 @@ bool TypeSystemFortran::IsArrayType(lldb::opaque_compiler_type_t type,
   if (element_type)
     *element_type = array_type->GetElementType();
   // TODO: If it isn't we have to evaluate the DWARFExpressionList
-  if (array_type->IsSizeKnown() && size)
+  if (!array_type->IsDynamic() && size)
     *size = array_type->GetTotalElements();
 
   return true;
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index c6a3b42698eb7..076978ea09d5f 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -15,7 +15,13 @@
 
 namespace lldb_private {
 
+namespace plugin {
+namespace fortran {
 class FortranType;
+struct FortranDimension;
+struct FortranArrayMetadata;
+} // namespace fortran
+} // namespace plugin
 
 /// A TypeSystem implementation for the Fortran language.
 ///
@@ -44,12 +50,9 @@ class TypeSystemFortran : public TypeSystem {
 
   CompilerType CreateType(uint32_t kind, uint64_t bitsize, ConstString name);
 
-  CompilerType CreateArrayType(
-      llvm::SmallVectorImpl<std::optional<uint64_t>> &elements_per_dimension,
-      llvm::SmallVectorImpl<std::optional<uint64_t>> &byte_strides,
-      llvm::SmallVectorImpl<int64_t> &lower_bounds, CompilerType element_type,
-      bool is_allocatable, bool is_star, uint64_t total_array_size,
-      uint64_t total_elements);
+  CompilerType CreateArrayType(plugin::fortran::FortranArrayMetadata array_info,
+                               uint64_t total_array_size,
+                               uint64_t total_elements);
 
   static LanguageSet GetSupportedLanguagesForTypes();
 
@@ -356,7 +359,9 @@ class TypeSystemFortran : public TypeSystem {
       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;
+      ValueObject *valobj, uint64_t &language_flags) override {
+    return CompilerType();
+  }
 
   // Lookup a child given a name. This function will match base class names and
   // member member names in "clang_type" only, not descendants.
@@ -375,23 +380,6 @@ class TypeSystemFortran : public TypeSystem {
     return 0;
   }
 
-  DWARFExpressionList
-  GetDataLocationExpression(lldb::opaque_compiler_type_t type);
-
-  DWARFExpressionList
-  GetUpperBoundExpression(lldb::opaque_compiler_type_t type);
-
-  DWARFExpressionList
-  GetLowerBoundExpression(lldb::opaque_compiler_type_t type);
-
-  DWARFExpressionList
-  GetElementCountExpression(lldb::opaque_compiler_type_t type);
-
-  DWARFExpressionList GetAllocatedExpression(lldb::opaque_compiler_type_t type);
-
-  DWARFExpressionList
-  GetByteStrideExpression(lldb::opaque_compiler_type_t type);
-
 #ifndef NDEBUG
   /// Convenience LLVM-style dump method for use in the debugger only.
   LLVM_DUMP_METHOD void dump(lldb::opaque_compiler_type_t type) const override {
@@ -503,8 +491,11 @@ class TypeSystemFortran : public TypeSystem {
 
 private:
   typedef std::pair<int, uint64_t> TypeKey;
-  typedef llvm::DenseMap<TypeKey, std::unique_ptr<FortranType>> BasicTypeMap;
-  typedef llvm::DenseMap<ConstString, std::unique_ptr<FortranType>> FunctionMap;
+  typedef llvm::DenseMap<TypeKey, std::unique_ptr<plugin::fortran::FortranType>>
+      BasicTypeMap;
+  typedef llvm::DenseMap<ConstString,
+                         std::unique_ptr<plugin::fortran::FortranType>>
+      FunctionMap;
 
   // TODO: Types are assosciated by their kind and bitsize, this helps to
   // return from their basic type and is enough for basic types but

>From 4a566302ee7a5548d2c06dc58bd407314d5a86d0 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Mon, 27 Jul 2026 22:01:33 +0300
Subject: [PATCH 38/44] [lldb][Fortran] Array support completed for simple
 dynamics and explicit types

---
 .../Plugins/Language/Fortran/DynamicArray.cpp | 235 ++++++++++--------
 .../Language/Fortran/FortranLanguage.cpp      |  45 +++-
 .../Language/Fortran/FortranLanguage.h        |   5 +
 .../DWARF/DWARFASTParserFortran.cpp           |   9 +-
 .../Plugins/TypeSystem/Fortran/FortranTypes.h |  19 +-
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 156 +++++++++++-
 .../TypeSystem/Fortran/TypeSystemFortran.h    |  16 +-
 7 files changed, 365 insertions(+), 120 deletions(-)

diff --git a/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp b/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
index 789bf53764f58..2fa8978044120 100644
--- a/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
+++ b/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
@@ -7,12 +7,14 @@
 //===----------------------------------------------------------------------===//
 
 // TODO: Clean this up, fix names, add comments
+// TODO: Fix the BitSize...
 #include "DynamicArray.h"
 
+#include "lldb/DataFormatters/FormattersHelpers.h"
 #include "lldb/Expression/DWARFExpressionList.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/SymbolContext.h"
-
+#include "lldb/ValueObject/ValueObject.h"
 #include "Plugins/TypeSystem/Fortran/FortranTypes.h"
 #include "Plugins/TypeSystem/Fortran/TypeSystemFortran.h"
 
@@ -30,7 +32,7 @@ class DynamicArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
 public:
   DynamicArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
 
-  ~DynamicArraySyntheticFrontEnd();
+  ~DynamicArraySyntheticFrontEnd() = default;
 
   llvm::Expected<uint32_t> CalculateNumChildren() override;
 
@@ -45,7 +47,9 @@ class DynamicArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
   CompilerType m_array_type;
   lldb::addr_t m_array_addr;
   bool m_allocated;
-  llvm::DenseMap<FortranArray *, FortranType *> m_children_map;
+  std::shared_ptr<lldb_private::TypeSystemFortran> m_ast_sp;
+  // TODO: very bad design, children will overwrite themselves...
+  llvm::DenseMap<FortranArray *, CompilerType> m_children_map;
 };
 
 DynamicArraySyntheticFrontEnd::DynamicArraySyntheticFrontEnd(
@@ -66,10 +70,23 @@ lldb::ChildCacheState DynamicArraySyntheticFrontEnd::Update() {
   auto ast_sp = m_backend.GetCompilerType().GetTypeSystem<TypeSystemFortran>();
   if (!ast_sp)
     return lldb::ChildCacheState::eRefetch;
+  m_ast_sp = ast_sp;
   FortranArray *array_type = static_cast<FortranArray *>(raw_type);
+  if (!array_type) {
+    return lldb::ChildCacheState::eRefetch;
+  }
   m_element_type = array_type->GetElementType();
-  if (!array_type->IsDynamic())
+  if (!array_type->IsDynamic()) {
+    m_allocated = true;
+    m_array_addr = m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+    if (m_array_addr == LLDB_INVALID_ADDRESS) {
+      m_array_addr = m_backend.GetLoadAddress();
+    }
+
+    m_array_type = m_backend.GetCompilerType();
     return lldb::ChildCacheState::eReuse;
+  }
   lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
   ExecutionContext exe_ctx(m_backend.GetExecutionContextRef());
   Target *target = exe_ctx.GetTargetPtr();
@@ -84,14 +101,25 @@ lldb::ChildCacheState DynamicArraySyntheticFrontEnd::Update() {
 
   loclist_base_load_addr = sc.function->GetAddress().GetLoadAddress(target);
 
+  lldb::addr_t obj_load_addr = m_backend.GetLoadAddress();
+
+  if (obj_load_addr == LLDB_INVALID_ADDRESS)
+    return lldb::ChildCacheState::eRefetch;
+
+  Value object_address_val;
+  object_address_val.SetValueType(Value::ValueType::LoadAddress);
+  object_address_val.GetScalar() = obj_load_addr;
+
   DWARFExpressionList allocated_exp = array_type->GetAllocatedExpression();
   DWARFExpressionList data_location_exp =
       array_type->GetDataLocationExpression();
 
   llvm::Expected<Value> allocated_val_or_err = allocated_exp.Evaluate(
-      &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
-  if (!allocated_val_or_err)
+      &exe_ctx, nullptr, loclist_base_load_addr, nullptr, &object_address_val);
+  if (!allocated_val_or_err) {
+    llvm::consumeError(allocated_val_or_err.takeError());
     return lldb::ChildCacheState::eRefetch;
+  }
 
   Value allocated_val = *allocated_val_or_err;
   if (allocated_val.ResolveValue(&exe_ctx).IsZero())
@@ -100,9 +128,11 @@ lldb::ChildCacheState DynamicArraySyntheticFrontEnd::Update() {
   m_allocated = true;
 
   llvm::Expected<Value> array_addr_or_err = data_location_exp.Evaluate(
-      &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
-  if (!array_addr_or_err)
+      &exe_ctx, nullptr, loclist_base_load_addr, nullptr, &object_address_val);
+  if (!array_addr_or_err) {
+    llvm::consumeError(array_addr_or_err.takeError());
     return lldb::ChildCacheState::eRefetch;
+  }
 
   Value array_addr = *array_addr_or_err;
 
@@ -123,10 +153,13 @@ lldb::ChildCacheState DynamicArraySyntheticFrontEnd::Update() {
         dimension.GetElementCountExpression();
     DWARFExpressionList byte_stride_exp = dimension.GetByteStrideExpression();
     if (lower_bound_exp.IsValid()) {
-      llvm::Expected<Value> lower_bound_or_err = lower_bound_exp.Evaluate(
-          &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
-      if (!lower_bound_or_err)
+      llvm::Expected<Value> lower_bound_or_err =
+          lower_bound_exp.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr,
+                                   nullptr, &object_address_val);
+      if (!lower_bound_or_err) {
+        llvm::consumeError(lower_bound_or_err.takeError());
         return lldb::ChildCacheState::eRefetch;
+      }
 
       Value lower_bound = *lower_bound_or_err;
 
@@ -135,39 +168,52 @@ lldb::ChildCacheState DynamicArraySyntheticFrontEnd::Update() {
     } else
       dimension_info.lower_bound = dimension.GetLowerBound().GetBound();
 
-    if (upper_bound_exp.IsValid()) {
-      llvm::Expected<Value> upper_bound_or_err = upper_bound_exp.Evaluate(
-          &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
-      if (!upper_bound_or_err)
-        return lldb::ChildCacheState::eRefetch;
-
-      Value upper_bound = *upper_bound_or_err;
-      dimension_info.upper_bound =
-          upper_bound.ResolveValue(&exe_ctx).SLongLong(0);
-    } else
-      dimension_info.upper_bound = dimension.GetUpperBound().GetBound();
     // TODO: Handle cases where we only upper and lower bound
     if (element_count_exp.IsValid()) {
-      llvm::Expected<Value> element_count_or_err = element_count_exp.Evaluate(
-          &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
-      if (!element_count_or_err)
+      llvm::Expected<Value> element_count_or_err =
+          element_count_exp.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr,
+                                     nullptr, &object_address_val);
+      if (!element_count_or_err) {
+        llvm::consumeError(element_count_or_err.takeError());
         return lldb::ChildCacheState::eRefetch;
-
+      }
       Value element_count = *element_count_or_err;
       dimension_info.element_count =
           element_count.ResolveValue(&exe_ctx).ULongLong(0);
     } else
       dimension_info.element_count = dimension.GetElementCount();
 
+    if (upper_bound_exp.IsValid()) {
+      llvm::Expected<Value> upper_bound_or_err =
+          upper_bound_exp.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr,
+                                   nullptr, &object_address_val);
+      if (!upper_bound_or_err) {
+        llvm::consumeError(upper_bound_or_err.takeError());
+        return lldb::ChildCacheState::eRefetch;
+      }
+
+      Value upper_bound = *upper_bound_or_err;
+      dimension_info.upper_bound =
+          upper_bound.ResolveValue(&exe_ctx).SLongLong(0);
+    } else if (dimension.GetUpperBound().IsBoundKnown())
+      dimension_info.upper_bound = dimension.GetUpperBound().GetBound();
+    else
+      dimension_info.upper_bound =
+          std::get<int64_t>(dimension_info.lower_bound) +
+          std::get<uint64_t>(dimension_info.element_count);
+
     if (byte_stride_exp.IsValid()) {
-      llvm::Expected<Value> byte_stride_or_err = byte_stride_exp.Evaluate(
-          &exe_ctx, nullptr, loclist_base_load_addr, nullptr, nullptr);
-      if (!byte_stride_or_err)
+      llvm::Expected<Value> byte_stride_or_err =
+          byte_stride_exp.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr,
+                                   nullptr, &object_address_val);
+      if (!byte_stride_or_err) {
+        llvm::consumeError(byte_stride_or_err.takeError());
         return lldb::ChildCacheState::eRefetch;
+      }
 
       Value byte_stride = *byte_stride_or_err;
       dimension_info.byte_stride =
-          byte_stride.ResolveValue(&exe_ctx).SLongLong(0);
+          byte_stride.ResolveValue(&exe_ctx).ULongLong(0);
     } else
       dimension_info.byte_stride = dimension.GetByteStride();
 
@@ -203,12 +249,13 @@ lldb::ChildCacheState DynamicArraySyntheticFrontEnd::Update() {
   llvm::Expected<uint64_t> elem_byte_size_or_err =
       m_element_type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
 
-  if (elem_byte_size_or_err) {
-    total_array_size = total_elements * (*elem_byte_size_or_err);
-  } else {
-    // Fallback if the element type is incomplete
+  if (!elem_byte_size_or_err) {
+    llvm::consumeError(elem_byte_size_or_err.takeError());
     total_array_size = 0;
-  }
+  } else
+    // Fallback if the element type is incomplete
+    total_array_size = total_elements * (*elem_byte_size_or_err);
+
   m_array_type =
       ast_sp->CreateArrayType(array_info, total_array_size, total_elements);
   return lldb::ChildCacheState::eRefetch;
@@ -244,8 +291,17 @@ DynamicArraySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
 
   if (!fortran_type)
     return ValueObjectSP();
-  uint32_t child_byte_size;
-  int32_t child_byte_offset;
+  ExecutionContext exe_ctx(m_backend.GetExecutionContextRef());
+  bool omit_empty_base_classes = true;
+  bool ignore_array_bounds = false;
+  uint32_t child_byte_size = 0;
+  int32_t child_byte_offset = 0;
+  uint32_t child_bitfield_bit_size = 0;
+  uint32_t child_bitfield_bit_offset = 0;
+  bool child_is_base_class = false;
+  bool child_is_deref_of_parent = false;
+  uint64_t language_flags = 0;
+  const bool transparent_pointers = true;
   std::string child_name;
   llvm::ArrayRef<ArrayShape> old_dimensions = fortran_type->GetDimensions();
   int64_t ub = old_dimensions.front().GetUpperBound().GetBound();
@@ -254,69 +310,54 @@ DynamicArraySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
   if (idx >= num_elements)
     return ValueObjectSP();
 
-  if (old_dimensions.size() > 1) {
-
-    llvm::SmallVector<ArrayShape, 2> new_dimensions(old_dimensions.begin() + 1,
-                                                    old_dimensions.end());
-
-    ArrayShape old_first_dimension = old_dimensions.front();
-    uint64_t new_byte_stride;
-
-    if (old_first_dimension.GetByteStride() != 0)
-      new_byte_stride = old_first_dimension.GetNumberOfElements() *
-                        old_first_dimension.GetByteStride();
-    else
-      new_byte_stride = old_first_dimension.GetNumberOfElements() *
-                        fortran_type->GetElementByteSize();
-
-    new_dimensions.front().SetByteStride(new_byte_stride);
-    bool is_star = new_dimensions.back().GetLowerBound().IsStar();
-    bool is_allocatable = fortran_type->IsAllocatable();
-    uint64_t new_total_elements = fortran_type->GetTotalElements() /
-                                  old_first_dimension.GetNumberOfElements();
-    if (old_dimensions.front().GetByteStride() != 0)
-      child_byte_offset = idx * old_dimensions.front().GetByteStride();
-    else
-      child_byte_offset = idx * fortran_type->GetElementByteSize();
-
-    uint64_t last_dim_stride = new_dimensions.back().GetByteStride();
+  child_name = llvm::formatv("[{0}]", idx);
+  llvm::Expected<CompilerType> child_type_orr_err =
+      m_ast_sp->GetChildCompilerTypeAtIndex(
+          raw_type, &exe_ctx, idx, transparent_pointers,
+          omit_empty_base_classes, ignore_array_bounds, child_name,
+          child_byte_size, child_byte_offset, child_bitfield_bit_size,
+          child_bitfield_bit_offset, child_is_base_class,
+          child_is_deref_of_parent, &m_backend, language_flags);
+  if (!child_type_orr_err) {
+    llvm::consumeError(child_type_orr_err.takeError());
+    return ValueObjectSP();
+  }
+  CompilerType child_type = *child_type_orr_err;
+  m_children_map[fortran_type] = child_type;
+  uint64_t array_address = m_array_addr + child_byte_offset;
+  if (!fortran_type->IsDynamic() && m_array_addr == LLDB_INVALID_ADDRESS) {
+    return m_backend.GetSyntheticChildAtOffset(child_byte_offset, child_type,
+                                               true, ConstString(child_name));
+  }
 
-    if (last_dim_stride != 0) {
-      child_byte_size =
-          new_dimensions.back().GetNumberOfElements() * last_dim_stride;
-    } else {
-      child_byte_size = new_total_elements * fortran_type->GetElementByteSize();
-    }
+  lldb::ValueObjectSP child_sp = CreateChildValueObjectFromAddress(child_name, array_address,
+                                           m_backend.GetExecutionContextRef(),
+                                           child_type, false);
+  if (child_sp) {
+    child_sp->GetValue().SetValueType(Value::ValueType::LoadAddress);
+    child_sp->GetValue().GetScalar() = array_address;
+  }
+  
+  return child_sp;
+}
 
-    child_name = llvm::formatv("[{0}]", lb + idx);
-    ConstString type_name =
-        CreateArrayTypeName(fortran_type->GetElementType(), new_dimensions,
-                            is_allocatable, is_star);
-    FortranArray *array_type = new FortranArray(
-        fortran_type->GetElementType(), new_dimensions, type_name,
-        child_byte_size, is_allocatable, fortran_type->IsDynamic(),
-        new_total_elements, fortran_type->GetAllocatedExpression(),
-        fortran_type->GetDataLocationExpression());
-    CompilerType array_compiler_type(
-        TypeSystemWP(m_array_type.GetTypeSystem().GetSharedPointer()),
-        (void *)array_type);
-    m_children_map[fortran_type] = array_type;
-    uint64_t array_address = m_array_addr + child_byte_offset;
-    return CreateChildValueObjectFromAddress(child_name, array_address,
-                                             m_backend.GetExecutionContextRef(),
-                                             array_compiler_type);
-  } else {
-    if (old_dimensions.front().GetByteStride() != 0)
-      child_byte_offset = idx * old_dimensions.front().GetByteStride();
-    else
-      child_byte_offset = idx * fortran_type->GetElementByteSize();
-    child_byte_size = fortran_type->GetElementByteSize();
-    StreamString name;
-    name.Printf("[%" PRIu64 "]", (uint64_t)idx);
-    return CreateChildValueObjectFromAddress(
-        name.GetString(), m_array_addr + child_byte_offset,
-        m_backend.GetExecutionContextRef(), m_element_type);
+llvm::Expected<size_t> lldb_private::formatters::DynamicArraySyntheticFrontEnd::
+    GetIndexOfChildWithName(ConstString name) {
+  if (!m_array_type)
+    return llvm::createStringErrorV("type has no child named '{0}'", name);
+  auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());
+  if (!optional_idx) {
+    return llvm::createStringErrorV("type has no child named '{0}'", name);
   }
+  return *optional_idx;
+}
+
+lldb_private::SyntheticChildrenFrontEnd *
+FortranDynamicArraySyntheticFrontEndCreator(CXXSyntheticChildren *,
+                                            lldb::ValueObjectSP valobj_sp) {
+  if (!valobj_sp)
+    return nullptr;
+  return new DynamicArraySyntheticFrontEnd(valobj_sp);
 }
 
 } // namespace formatters
diff --git a/lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp b/lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp
index a7040ae337b17..115e1487889e4 100644
--- a/lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp
+++ b/lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp
@@ -10,7 +10,11 @@
 
 #include "FortranLanguage.h"
 
+#include "DynamicArray.h"
+
 #include "lldb/Core/PluginManager.h"
+#include "lldb/DataFormatters/DataVisualization.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
 
 #include "Plugins/TypeSystem/Fortran/TypeSystemFortran.h"
 
@@ -43,7 +47,6 @@ StringRef FortranLanguage::GetPluginName() { return GetPluginNameStatic(); }
 uint32_t FortranLanguage::GetPluginVersion() { return 1; }
 
 Language *FortranLanguage::CreateInstance(LanguageType language) {
-  // FIXME: Should Fortran 77 be supported???
   if (Language::LanguageIsFortran(language)) {
     return new FortranLanguage();
   }
@@ -58,3 +61,43 @@ bool FortranLanguage::IsSourceFile(StringRef file_path) const {
   }
   return false;
 }
+
+static lldb::SyntheticChildrenSP
+FortranDynamicArrayFinder(ValueObject &valobj,
+                          lldb::DynamicValueType use_dynamic) {
+  CompilerType type = valobj.GetCompilerType();
+
+  // 1. Query if it is actually an array type according to DWARF
+  if (type.IsValid() && type.IsArrayType(nullptr, nullptr, nullptr)) {
+
+    // 2. Setup the flags
+    SyntheticChildren::Flags flags;
+    flags.SetCascades(true)
+        .SetSkipPointers(false)
+        .SetSkipReferences(false)
+        .SetFrontEndWantsDereference();
+
+    // 3. Bind and return your custom frontend creator
+    return lldb::SyntheticChildrenSP(new CXXSyntheticChildren(
+        flags, "fortran array synthetic children",
+        lldb_private::formatters::FortranDynamicArraySyntheticFrontEndCreator));
+  }
+
+  // Return null if it's not an array, so LLDB can try other formatters
+  return nullptr;
+}
+
+// Implement the Language plugin override
+HardcodedFormatters::HardcodedSyntheticFinder
+FortranLanguage::GetHardcodedSynthetics() {
+  HardcodedFormatters::HardcodedSyntheticFinder formatters;
+
+  // Push our structural finder into the formatters list
+  formatters.push_back([](lldb_private::ValueObject &valobj,
+                          lldb::DynamicValueType use_dynamic,
+                          FormatManager &fmt_mgr) -> lldb::SyntheticChildrenSP {
+    return FortranDynamicArrayFinder(valobj, use_dynamic);
+  });
+
+  return formatters;
+}
diff --git a/lldb/source/Plugins/Language/Fortran/FortranLanguage.h b/lldb/source/Plugins/Language/Fortran/FortranLanguage.h
index e6313b7377deb..391336629848f 100644
--- a/lldb/source/Plugins/Language/Fortran/FortranLanguage.h
+++ b/lldb/source/Plugins/Language/Fortran/FortranLanguage.h
@@ -37,6 +37,8 @@ class FortranLanguage : public Language {
 
   static llvm::StringRef GetPluginNameStatic();
 
+  static void LoadFortranFormatters(lldb::TypeCategoryImplSP cpp_category_sp);
+
   //------------------------------------------------------------------
   // PluginInterface protocol
   //------------------------------------------------------------------
@@ -45,6 +47,9 @@ class FortranLanguage : public Language {
   uint32_t GetPluginVersion();
 
   bool IsSourceFile(llvm::StringRef file_path) const override;
+
+  HardcodedFormatters::HardcodedSyntheticFinder
+  GetHardcodedSynthetics() override;
 };
 
 }; // namespace lldb_private
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
index c165caf67d2ca..a507296b3a7c6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
@@ -126,7 +126,7 @@ FortranArrayMetadata ParseArray(const DWARFDIE &parent_die,
       case DW_AT_byte_stride:
         if (DWARFFormValue::IsBlockForm(form_value.Form())) {
           byte_stride = GetDWARFExpression(die, form_value, module);
-          array_info.is_dynamic = false;
+          array_info.is_dynamic = true;
         } else
           byte_stride = form_value.Unsigned();
         break;
@@ -134,16 +134,15 @@ FortranArrayMetadata ParseArray(const DWARFDIE &parent_die,
       case DW_AT_lower_bound:
         if (DWARFFormValue::IsBlockForm(form_value.Form())) {
           lower_bound = GetDWARFExpression(die, form_value, module);
-          array_info.is_dynamic = false;
+          array_info.is_dynamic = true;
         } else
           lower_bound = form_value.Signed();
         break;
 
       case DW_AT_upper_bound:
         upper_bound_valid = true;
-        // TODO: Handle cases where we have to read the dope vector
         if (DWARFFormValue::IsBlockForm(form_value.Form())) {
-          array_info.is_dynamic = false;
+          array_info.is_dynamic = true;
           upper_bound = GetDWARFExpression(die, form_value, module);
         } else
           upper_bound = form_value.Signed();
@@ -259,6 +258,8 @@ lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(const SymbolContext &sc,
           uint64_t total_elements = 1;
           if (array_element_type.GetCompleteType()) {
             FortranArrayMetadata array_info = ParseArray(die, nullptr);
+
+            array_info.element_type = array_element_type;
             // We need to calculate the total array size, if it is known
             // at compile time
             if (!array_info.is_dynamic) {
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h b/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h
index f1c5cdb3a8345..0791569f184f1 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h
@@ -40,8 +40,8 @@ struct FortranArrayMetadata {
   bool is_allocatable = false;
   bool is_dynamic = false;
   bool is_star = false;
-  std::optional<DWARFExpressionList> allocated_exp;
-  std::optional<DWARFExpressionList> data_location_exp;
+  DWARFExpressionList allocated_exp;
+  DWARFExpressionList data_location_exp;
 };
 
 /// A simplified internal representation of a Fortran type.
@@ -55,6 +55,7 @@ class FortranType {
     KIND_COMPLEX,
     KIND_FUNCTION,
     KIND_ARRAY,
+    KIND_POINTER,
     KIND_UNKNOWN
   };
   FortranType(int kind, const ConstString &name, uint64_t bitsize)
@@ -99,6 +100,8 @@ class ArrayBound {
 
   void SetCategory(Category c) { m_category = c; }
 
+  bool IsBoundKnown() const { return m_is_bound_known; }
+
   int64_t GetBound() const {
     assert(m_is_bound_known && "Can't get the bound if it is not explicit");
     return m_bound;
@@ -223,6 +226,18 @@ class FortranArray : public FortranType {
   DWARFExpressionList m_data_location_exp;
 };
 
+class FortranPointer : public FortranType {
+public:
+  FortranPointer(FortranType *pointee, ConstString type_name)
+      : m_pointee(pointee), FortranType(KIND_POINTER, type_name, 64) {}
+
+  void SetPointee(FortranType *pointee) { m_pointee = pointee; }
+  FortranType *GetPointee() const { return m_pointee; }
+
+private:
+  FortranType *m_pointee;
+};
+
 inline ConstString CreateArrayTypeName(const CompilerType &element_type,
                                        const llvm::ArrayRef<ArrayShape> shapes,
                                        bool is_allocatable, bool is_star) {
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index ecbb185e6694f..5b996bf380e2c 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -305,12 +305,94 @@ CompilerType TypeSystemFortran::CreateArrayType(FortranArrayMetadata array_info,
       CreateArrayTypeName(array_info.element_type, array_shapes,
                           array_info.is_allocatable, array_info.is_star);
 
-  FortranArray *array_type = new FortranArray(
+  FortranArray *child_type = new FortranArray(
       array_info.element_type, array_shapes, array_type_name, total_array_size,
       array_info.is_allocatable, array_info.is_dynamic, total_elements,
-      *array_info.allocated_exp, *array_info.data_location_exp);
+      array_info.allocated_exp, array_info.data_location_exp);
 
-  return CompilerType(weak_from_this(), (void *)array_type);
+  return CompilerType(weak_from_this(), (void *)child_type);
+}
+
+llvm::Expected<CompilerType> TypeSystemFortran::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) {
+  if (!type)
+    return createStringError(
+        inconvertibleErrorCode(),
+        "Failed to craft intermediate Fortran array type: type is null.");
+
+  FortranType *super_type = static_cast<FortranType *>(type);
+
+  if (super_type->GetKind() != FortranType::KIND_ARRAY)
+    return CompilerType();
+
+  FortranArray *fortran_type = static_cast<FortranArray *>(super_type);
+
+  if (!fortran_type)
+    return CompilerType();
+
+  if (fortran_type->IsDynamic())
+    return CompilerType();
+  llvm::ArrayRef<ArrayShape> old_dimensions = fortran_type->GetDimensions();
+  int64_t ub = old_dimensions.front().GetUpperBound().GetBound();
+  int64_t lb = old_dimensions.front().GetLowerBound().GetBound();
+  uint64_t num_elements = old_dimensions.front().GetNumberOfElements();
+
+  if (idx >= num_elements)
+    return CompilerType();
+
+  if (old_dimensions.size() > 1) {
+
+    llvm::SmallVector<ArrayShape, 2> new_dimensions(old_dimensions.begin() + 1,
+                                                    old_dimensions.end());
+
+    ArrayShape old_first_dimension = old_dimensions.front();
+    uint64_t new_byte_stride;
+
+    if (old_first_dimension.GetByteStride() != 0)
+      new_byte_stride = old_first_dimension.GetNumberOfElements() *
+                        old_first_dimension.GetByteStride();
+    else
+      new_byte_stride = old_first_dimension.GetNumberOfElements() *
+                        fortran_type->GetElementByteSize();
+
+    new_dimensions.front().SetByteStride(new_byte_stride);
+    bool is_star = new_dimensions.back().GetLowerBound().IsStar();
+    bool is_allocatable = fortran_type->IsAllocatable();
+    uint64_t new_total_elements = fortran_type->GetTotalElements() /
+                                  old_first_dimension.GetNumberOfElements();
+    if (old_dimensions.front().GetByteStride() != 0)
+      child_byte_offset = idx * old_dimensions.front().GetByteStride();
+    else
+      child_byte_offset = idx * fortran_type->GetElementByteSize();
+
+    uint64_t last_dim_stride = new_dimensions.back().GetByteStride();
+
+    if (last_dim_stride != 0) {
+      child_byte_size =
+          new_dimensions.back().GetNumberOfElements() * last_dim_stride;
+    } else {
+      child_byte_size = new_total_elements * fortran_type->GetElementByteSize();
+    }
+    child_name = llvm::formatv("[{0}]", lb + idx);
+    ConstString type_name =
+        CreateArrayTypeName(fortran_type->GetElementType(), new_dimensions,
+                            is_allocatable, is_star);
+    FortranArray *array_type = new FortranArray(
+        fortran_type->GetElementType(), new_dimensions, type_name,
+        child_byte_size, false, false, new_total_elements,
+        DWARFExpressionList(), DWARFExpressionList());
+    return CompilerType(weak_from_this(), (void *)array_type);
+  } else {
+    child_byte_offset = idx * old_dimensions.front().GetByteStride();
+    child_byte_size = fortran_type->GetElementByteSize();
+    return fortran_type->GetElementType();
+  }
 }
 
 /// Returns the type name upper-cased to follow Fortran's general style
@@ -465,13 +547,76 @@ TypeSystemFortran::GetNumChildren(opaque_compiler_type_t type,
           "Couldn't get number of children, bad Fortran type.");
 
     // Fetch the number of elements
-    return fortran_array->GetDimensions().front().GetNumberOfElements();
+    if (!fortran_array->IsDynamic())
+      return fortran_array->GetDimensions().front().GetNumberOfElements();
+    return 0;
   }
   default:
     return 0;
   }
 }
 
+CompilerType
+TypeSystemFortran::GetPointeeType(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return CompilerType();
+  FortranType *fortran_type = static_cast<FortranType *>(type);
+  if (fortran_type->GetKind() != FortranType::KIND_POINTER)
+    return CompilerType();
+  FortranPointer *pointer_type = static_cast<FortranPointer *>(fortran_type);
+  FortranType *pointee_type = pointer_type->GetPointee();
+  if (!pointee_type)
+    return CompilerType();
+
+  return CompilerType(weak_from_this(), (void *)pointee_type);
+}
+
+CompilerType
+TypeSystemFortran::GetPointerType(lldb::opaque_compiler_type_t type) {
+  if (!type)
+    return CompilerType();
+
+  FortranType *pointee_type = static_cast<FortranType *>(type);
+  if (!pointee_type)
+    return CompilerType();
+  std::string ptr_name = pointee_type->GetName().GetStringRef().str() + " *";
+  FortranPointer *pointer_type =
+      new FortranPointer(pointee_type, ConstString(ptr_name));
+  return CompilerType(weak_from_this(), (void *)pointer_type);
+}
+
+llvm::Expected<CompilerType> TypeSystemFortran::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) {
+  if (!type)
+    return createStringError(inconvertibleErrorCode(),
+                             "Couldn't get dereferenced type, type is null.");
+
+  FortranType *fortran_type = static_cast<FortranType *>(type);
+
+  if (!fortran_type)
+    return createStringError(
+        inconvertibleErrorCode(),
+        "Couldn't get dereferenced type, type is not a fortran type.");
+
+  if (fortran_type->GetKind() != FortranType::KIND_POINTER)
+    return CompilerType();
+
+  CompilerType pointee_type = GetPointeeType(type);
+
+  deref_byte_offset = 0;
+
+  if (exe_ctx && pointee_type.IsValid()) {
+    llvm::Expected<uint64_t> size_or_err =
+        pointee_type.GetByteSize(exe_ctx->GetBestExecutionContextScope());
+    if (size_or_err)
+      deref_byte_size = *size_or_err;
+  }
+
+  return pointee_type;
+}
+
 bool TypeSystemFortran::IsIntegerType(opaque_compiler_type_t type,
                                       bool &is_signed) {
   if (!type)
@@ -505,6 +650,9 @@ bool TypeSystemFortran::IsArrayType(lldb::opaque_compiler_type_t type,
   if (!super_type)
     return false;
 
+  if (super_type->GetKind() != FortranType::KIND_ARRAY)
+    return false;
+
   FortranArray *array_type = static_cast<FortranArray *>(super_type);
 
   if (!array_type)
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index 076978ea09d5f..753168e44d12c 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -276,13 +276,9 @@ class TypeSystemFortran : public TypeSystem {
     return TypeMemberFunctionImpl();
   }
 
-  CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) override {
-    return CompilerType();
-  }
+  CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) override;
 
-  CompilerType GetPointerType(lldb::opaque_compiler_type_t type) override {
-    return CompilerType();
-  }
+  CompilerType GetPointerType(lldb::opaque_compiler_type_t type) override;
 
   void SetByteOrder(lldb::ByteOrder byte_order) { m_byte_order = byte_order; }
 
@@ -348,9 +344,7 @@ class TypeSystemFortran : public TypeSystem {
   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 {
-    return CompilerType();
-  }
+                      ValueObject *valobj, uint64_t &language_flags) override;
 
   llvm::Expected<CompilerType> GetChildCompilerTypeAtIndex(
       lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
@@ -359,9 +353,7 @@ class TypeSystemFortran : public TypeSystem {
       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 {
-    return CompilerType();
-  }
+      ValueObject *valobj, uint64_t &language_flags) override;
 
   // Lookup a child given a name. This function will match base class names and
   // member member names in "clang_type" only, not descendants.

>From 1a861c50bc422d696188ab1eeeb68886d1fd775a Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Mon, 27 Jul 2026 22:03:10 +0300
Subject: [PATCH 39/44] [lldb][Fortran] Fixed formatting

---
 .../Plugins/Language/Fortran/DynamicArray.cpp   | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp b/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
index 2fa8978044120..3eefaee97d786 100644
--- a/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
+++ b/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
@@ -10,13 +10,13 @@
 // TODO: Fix the BitSize...
 #include "DynamicArray.h"
 
+#include "Plugins/TypeSystem/Fortran/FortranTypes.h"
+#include "Plugins/TypeSystem/Fortran/TypeSystemFortran.h"
 #include "lldb/DataFormatters/FormattersHelpers.h"
 #include "lldb/Expression/DWARFExpressionList.h"
 #include "lldb/Symbol/Function.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/ValueObject/ValueObject.h"
-#include "Plugins/TypeSystem/Fortran/FortranTypes.h"
-#include "Plugins/TypeSystem/Fortran/TypeSystemFortran.h"
 
 #include "llvm/Support/Error.h"
 
@@ -329,15 +329,18 @@ DynamicArraySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
     return m_backend.GetSyntheticChildAtOffset(child_byte_offset, child_type,
                                                true, ConstString(child_name));
   }
-
-  lldb::ValueObjectSP child_sp = CreateChildValueObjectFromAddress(child_name, array_address,
-                                           m_backend.GetExecutionContextRef(),
-                                           child_type, false);
+  // We set do_deref to false since this expects the array elements to be
+  // pointers.
+  lldb::ValueObjectSP child_sp = CreateChildValueObjectFromAddress(
+      child_name, array_address, m_backend.GetExecutionContextRef(), child_type,
+      false);
+  // We explicitly set the value to be a load so it can dereference the array
+  // address correctly.
   if (child_sp) {
     child_sp->GetValue().SetValueType(Value::ValueType::LoadAddress);
     child_sp->GetValue().GetScalar() = array_address;
   }
-  
+
   return child_sp;
 }
 

>From d771dd876c2f2115ab10860295e9b93a272646f7 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Wed, 29 Jul 2026 19:26:49 +0300
Subject: [PATCH 40/44] [lldb][Fortran] Switched to using FoldingSet for
 storing types, fixed child array names and added GetArrayLowerBound API route
 to TypeSystem and CompilerType

---
 lldb/include/lldb/Symbol/CompilerType.h       |   2 +
 lldb/include/lldb/Symbol/TypeSystem.h         |   4 +
 .../Plugins/Language/Fortran/DynamicArray.cpp |  11 +-
 .../DWARF/DWARFASTParserFortran.cpp           |   9 +-
 .../Plugins/TypeSystem/Fortran/FortranTypes.h | 113 +++++++++++++++--
 .../TypeSystem/Fortran/TypeSystemFortran.cpp  | 117 ++++++++++++++----
 .../TypeSystem/Fortran/TypeSystemFortran.h    |  28 ++---
 lldb/source/Symbol/CompilerType.cpp           |   7 ++
 8 files changed, 224 insertions(+), 67 deletions(-)

diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h
index 168946cf17475..c66b11ba06a06 100644
--- a/lldb/include/lldb/Symbol/CompilerType.h
+++ b/lldb/include/lldb/Symbol/CompilerType.h
@@ -320,6 +320,8 @@ class CompilerType {
 
   CompilerType GetArrayType(uint64_t size) const;
 
+  int64_t GetArrayLowerBound() const;
+
   CompilerType GetCanonicalType() const;
 
   CompilerType GetFullyUnqualifiedType() const;
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index 1fa9d4ba26cfe..4b77c03718437 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -264,6 +264,10 @@ class TypeSystem : public PluginInterface,
   virtual CompilerType GetArrayType(lldb::opaque_compiler_type_t type,
                                     uint64_t size);
 
+  virtual int64_t GetArrayLowerBound(lldb::opaque_compiler_type_t type) {
+    return 0;
+  }
+
   virtual CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) = 0;
 
   virtual CompilerType
diff --git a/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp b/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
index 3eefaee97d786..0f5a0bccee0c0 100644
--- a/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
+++ b/lldb/source/Plugins/Language/Fortran/DynamicArray.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 // TODO: Clean this up, fix names, add comments
-// TODO: Fix the BitSize...
 #include "DynamicArray.h"
 
 #include "Plugins/TypeSystem/Fortran/FortranTypes.h"
@@ -48,8 +47,6 @@ class DynamicArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
   lldb::addr_t m_array_addr;
   bool m_allocated;
   std::shared_ptr<lldb_private::TypeSystemFortran> m_ast_sp;
-  // TODO: very bad design, children will overwrite themselves...
-  llvm::DenseMap<FortranArray *, CompilerType> m_children_map;
 };
 
 DynamicArraySyntheticFrontEnd::DynamicArraySyntheticFrontEnd(
@@ -60,7 +57,6 @@ DynamicArraySyntheticFrontEnd::DynamicArraySyntheticFrontEnd(
 }
 // TODO: Handle star arrays
 lldb::ChildCacheState DynamicArraySyntheticFrontEnd::Update() {
-  m_children_map.clear();
   m_allocated = false;
 
   lldb::opaque_compiler_type_t raw_type =
@@ -304,13 +300,13 @@ DynamicArraySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
   const bool transparent_pointers = true;
   std::string child_name;
   llvm::ArrayRef<ArrayShape> old_dimensions = fortran_type->GetDimensions();
-  int64_t ub = old_dimensions.front().GetUpperBound().GetBound();
   int64_t lb = old_dimensions.front().GetLowerBound().GetBound();
   uint64_t num_elements = old_dimensions.front().GetNumberOfElements();
-  if (idx >= num_elements)
+
+  if (idx > num_elements)
     return ValueObjectSP();
 
-  child_name = llvm::formatv("[{0}]", idx);
+  child_name = llvm::formatv("[{0}]", idx + lb);
   llvm::Expected<CompilerType> child_type_orr_err =
       m_ast_sp->GetChildCompilerTypeAtIndex(
           raw_type, &exe_ctx, idx, transparent_pointers,
@@ -323,7 +319,6 @@ DynamicArraySyntheticFrontEnd::GetChildAtIndex(uint32_t idx) {
     return ValueObjectSP();
   }
   CompilerType child_type = *child_type_orr_err;
-  m_children_map[fortran_type] = child_type;
   uint64_t array_address = m_array_addr + child_byte_offset;
   if (!fortran_type->IsDynamic() && m_array_addr == LLDB_INVALID_ADDRESS) {
     return m_backend.GetSyntheticChildAtOffset(child_byte_offset, child_type,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
index a507296b3a7c6..e214a45569e7f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserFortran.cpp
@@ -50,7 +50,7 @@ FortranArrayMetadata ParseArray(const DWARFDIE &parent_die,
   FortranArrayMetadata array_info;
   DWARFAttributes parent_attributes = parent_die.GetAttributes();
   ModuleSP parent_module(parent_die.GetModule());
-  for (int idx = 0; idx < parent_attributes.Size(); idx++) {
+  for (size_t idx = 0; idx < parent_attributes.Size(); idx++) {
     const dw_attr_t attr = parent_attributes.AttributeAtIndex(idx);
     DWARFFormValue form_value;
     if (!parent_attributes.ExtractFormValueAtIndex(idx, form_value))
@@ -90,7 +90,6 @@ FortranArrayMetadata ParseArray(const DWARFDIE &parent_die,
     DWARFValue byte_stride;
     DWARFValue lower_bound;
     DWARFValue upper_bound;
-    bool upper_bound_valid = false;
     for (size_t i = 0; i < attributes.Size(); ++i) {
       const dw_attr_t attr = attributes.AttributeAtIndex(i);
       DWARFFormValue form_value;
@@ -140,7 +139,6 @@ FortranArrayMetadata ParseArray(const DWARFDIE &parent_die,
         break;
 
       case DW_AT_upper_bound:
-        upper_bound_valid = true;
         if (DWARFFormValue::IsBlockForm(form_value.Form())) {
           array_info.is_dynamic = true;
           upper_bound = GetDWARFExpression(die, form_value, module);
@@ -244,9 +242,6 @@ lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(const SymbolContext &sc,
       case DW_TAG_array_type: {
         dwarf->GetDIEToType()[die.GetDIE()] = DIE_IS_BEING_PARSED;
 
-        uint32_t byte_stride = 0;
-        uint32_t bit_stride = 0;
-
         DWARFDIE element_die = die.GetAttributeValueAsReferenceDIE(DW_AT_type);
 
         Type *element_type = dwarf->ResolveTypeUID(element_die, true);
@@ -263,7 +258,7 @@ lldb::TypeSP DWARFASTParserFortran::ParseTypeFromDWARF(const SymbolContext &sc,
             // We need to calculate the total array size, if it is known
             // at compile time
             if (!array_info.is_dynamic) {
-              for (int idx = 0; idx < array_info.dimensions.size(); idx++) {
+              for (size_t idx = 0; idx < array_info.dimensions.size(); idx++) {
                 total_elements *= std::get<uint64_t>(
                     array_info.dimensions[idx].element_count);
               }
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h b/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h
index 0791569f184f1..0c2db0b323c7c 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/FortranTypes.h
@@ -14,6 +14,7 @@
 #include "lldb/Utility/ConstString.h"
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/SmallVector.h"
 
 namespace lldb_private {
@@ -46,7 +47,7 @@ struct FortranArrayMetadata {
 
 /// A simplified internal representation of a Fortran type.
 /// In the future, this will likely be replaced by a Flang-backed AST.
-class FortranType {
+class FortranType : public llvm::FoldingSetNode {
 public:
   enum TypeKind {
     KIND_INTEGER,
@@ -58,14 +59,25 @@ class FortranType {
     KIND_POINTER,
     KIND_UNKNOWN
   };
-  FortranType(int kind, const ConstString &name, uint64_t bitsize)
+  FortranType(int32_t kind, uint64_t bitsize, const ConstString &name)
       : m_kind(kind), m_bitsize(bitsize), m_type_name(name) {}
+  virtual ~FortranType() = default;
   int GetKind() const { return m_kind; }
   uint64_t GetBitSize() const { return m_bitsize; }
   ConstString GetName() const { return m_type_name; }
 
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    Profile(ID, m_kind, m_bitsize);
+  }
+
+  static void Profile(llvm::FoldingSetNodeID &ID, int32_t kind,
+                      uint64_t bitsize) {
+    ID.AddInteger(kind);
+    ID.AddInteger(bitsize);
+  }
+
 private:
-  int m_kind;
+  int32_t m_kind;
   uint64_t m_bitsize;
   ConstString m_type_name;
 };
@@ -74,12 +86,25 @@ class FortranFunction : public FortranType {
 public:
   FortranFunction(ConstString func_name,
                   const llvm::SmallVectorImpl<CompilerType> &parameters)
-      : FortranType(FortranType::KIND_FUNCTION, func_name, 0) {
+      : FortranType(FortranType::KIND_FUNCTION, 0, func_name) {
     m_parameters.assign(parameters.begin(), parameters.end());
   }
   llvm::ArrayRef<CompilerType> GetParameters() const { return m_parameters; }
   size_t GetNumberOfParameters() const { return m_parameters.size(); }
 
+  void Profile(llvm::FoldingSetNodeID &id) const {
+    Profile(id, GetName(), m_parameters);
+  }
+
+  static void Profile(llvm::FoldingSetNodeID &id, ConstString func_name,
+                      llvm::ArrayRef<CompilerType> parameters) {
+    id.AddString(func_name.GetStringRef());
+    id.AddInteger(parameters.size());
+
+    for (const auto &param : parameters)
+      id.AddPointer(param.GetOpaqueQualType());
+  }
+
 private:
   llvm::SmallVector<CompilerType, 4> m_parameters;
 };
@@ -112,6 +137,20 @@ class ArrayBound {
     m_bound = bound;
   }
 
+  void Profile(llvm::FoldingSetNodeID &id) const {
+    Profile(id, m_category, m_is_bound_known, m_bound);
+  }
+
+  static void Profile(llvm::FoldingSetNodeID &id, Category category,
+                      bool is_bound_known, int64_t bound) {
+    id.AddInteger(static_cast<uint32_t>(category));
+
+    id.AddBoolean(is_bound_known);
+
+    if (is_bound_known)
+      id.AddInteger(bound);
+  }
+
 private:
   Category m_category{Category::Explicit};
   int64_t m_bound;
@@ -126,8 +165,8 @@ class ArrayShape {
 
   const ArrayBound &GetLowerBound() const { return m_lb; }
   const ArrayBound &GetUpperBound() const { return m_ub; }
-  const uint64_t GetByteStride() const { return m_byte_stride; }
-  const uint64_t GetElementCount() const { return m_element_count; }
+  uint64_t GetByteStride() const { return m_byte_stride; }
+  uint64_t GetElementCount() const { return m_element_count; }
 
   int64_t GetNumberOfElements() const {
     return m_ub.GetBound() - m_lb.GetBound() + 1;
@@ -166,6 +205,29 @@ class ArrayShape {
     m_byte_stride_exp = std::move(expr);
   }
 
+  void Profile(llvm::FoldingSetNodeID &id) const {
+    Profile(id, m_lb, m_ub, m_byte_stride, m_element_count, m_element_count_exp,
+            m_upper_bound_exp, m_lower_bound_exp, m_byte_stride_exp);
+  }
+
+  static void Profile(llvm::FoldingSetNodeID &id, const ArrayBound &lb,
+                      const ArrayBound &ub, const uint64_t byte_stride,
+                      const uint64_t element_count,
+
+                      const DWARFExpressionList &element_count_exp,
+                      const DWARFExpressionList &upper_bound_exp,
+                      const DWARFExpressionList &lower_bound_exp,
+                      const DWARFExpressionList &byte_stride_exp) {
+    lb.Profile(id);
+    ub.Profile(id);
+    id.AddInteger(byte_stride);
+    id.AddInteger(element_count);
+    id.AddBoolean(element_count_exp.IsValid());
+    id.AddBoolean(upper_bound_exp.IsValid());
+    id.AddBoolean(lower_bound_exp.IsValid());
+    id.AddBoolean(byte_stride_exp.IsValid());
+  }
+
 private:
   ArrayBound m_lb;
   ArrayBound m_ub;
@@ -186,13 +248,12 @@ class FortranArray : public FortranType {
                bool is_allocatable, bool is_dynamic, uint64_t total_elements,
                DWARFExpressionList allocated_exp,
                DWARFExpressionList data_location_exp)
-      : m_element_type(element_type),
+      : FortranType(TypeKind::KIND_ARRAY, total_array_size, array_type_name),
+        m_element_type(element_type),
         m_dimensions(dimensions.begin(), dimensions.end()),
         m_is_allocatable(is_allocatable), m_is_dynamic(is_dynamic),
         m_total_elements(total_elements), m_allocated_exp(allocated_exp),
-        m_data_location_exp(data_location_exp),
-        FortranType(TypeKind::KIND_ARRAY, array_type_name, total_array_size) {}
-  // TODO: Add necessary methods here
+        m_data_location_exp(data_location_exp) {}
   CompilerType GetElementType() const { return m_element_type; }
   uint64_t GetTotalElements() const { return m_total_elements; }
   bool IsAllocatable() const { return m_is_allocatable; }
@@ -213,27 +274,55 @@ class FortranArray : public FortranType {
   DWARFExpressionList GetDataLocationExpression() const {
     return m_data_location_exp;
   }
+  void Profile(llvm::FoldingSetNodeID &id) const {
+    Profile(id, m_element_type, m_dimensions, m_is_allocatable, m_is_dynamic,
+            m_allocated_exp, m_data_location_exp);
+  }
+
+  static void Profile(llvm::FoldingSetNodeID &id, CompilerType element_type,
+                      llvm::ArrayRef<ArrayShape> dimensions,
+                      bool is_allocatable, bool is_dynamic,
+                      const DWARFExpressionList &allocated_exp,
+                      const DWARFExpressionList &data_location_exp) {
+    id.AddPointer(element_type.GetOpaqueQualType());
+    id.AddBoolean(is_allocatable);
+    id.AddBoolean(is_dynamic);
+    id.AddBoolean(allocated_exp.IsValid());
+    id.AddBoolean(data_location_exp.IsValid());
+    id.AddInteger(dimensions.size());
+
+    for (const auto &shape : dimensions)
+      shape.Profile(id);
+  }
 
 private:
   CompilerType m_element_type;
   llvm::SmallVector<ArrayShape, 2> m_dimensions;
-  uint64_t m_total_elements;
   bool m_is_allocatable;
   // To know if the array is fully explicit without looping through the shapes
   // every time
   bool m_is_dynamic;
+  uint64_t m_total_elements;
   DWARFExpressionList m_allocated_exp;
   DWARFExpressionList m_data_location_exp;
 };
 
+// TODO: Calculate correct pointer size
 class FortranPointer : public FortranType {
 public:
   FortranPointer(FortranType *pointee, ConstString type_name)
-      : m_pointee(pointee), FortranType(KIND_POINTER, type_name, 64) {}
+      : FortranType(KIND_POINTER, sizeof(void *), type_name),
+        m_pointee(pointee) {}
 
   void SetPointee(FortranType *pointee) { m_pointee = pointee; }
   FortranType *GetPointee() const { return m_pointee; }
 
+  void Profile(llvm::FoldingSetNodeID &id) const { Profile(id, m_pointee); }
+  static void Profile(llvm::FoldingSetNodeID &id,
+                      const FortranType *m_pointee) {
+    id.AddPointer(m_pointee);
+  }
+
 private:
   FortranType *m_pointee;
 };
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
index 5b996bf380e2c..f33b9b6e45f57 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.cpp
@@ -18,6 +18,8 @@
 
 #include "Plugins/SymbolFile/DWARF/DWARFASTParserFortran.h"
 
+#include <new>
+
 using namespace lldb;
 using namespace lldb_private;
 using namespace llvm;
@@ -152,30 +154,38 @@ bool TypeSystemFortran::SupportsLanguage(lldb::LanguageType language) {
 CompilerType TypeSystemFortran::GetOrCreateFortranType(int kind,
                                                        uint64_t bitsize,
                                                        ConstString name) {
-  FortranType *type = m_basic_type_map[{kind, bitsize}].get();
-  if (type)
-    return CompilerType(weak_from_this(), (void *)type);
-  auto new_type_up = std::make_unique<FortranType>(kind, name, bitsize);
-  FortranType *raw_ptr = new_type_up.get();
-
-  m_basic_type_map[{kind, bitsize}] = std::move(new_type_up);
-
-  return CompilerType(weak_from_this(), (void *)raw_ptr);
+  llvm::FoldingSetNodeID id;
+  FortranType::Profile(id, kind, bitsize);
+  void *insert_pos = nullptr;
+  FortranType *fortran_type = m_basic_types.FindNodeOrInsertPos(id, insert_pos);
+  if (fortran_type)
+    return CompilerType(weak_from_this(), (void *)fortran_type);
+  auto new_type_up = std::make_unique<FortranType>(kind, bitsize, name);
+  fortran_type = new_type_up.get();
+
+  m_types.push_back(std::move(new_type_up));
+  m_basic_types.InsertNode(fortran_type, insert_pos);
+  return CompilerType(weak_from_this(), (void *)fortran_type);
 }
 
 /// Returns the type assosciated with the name, or creates it
 /// if it is not in the map
 CompilerType TypeSystemFortran::GetOrCreateFortranFunction(
     ConstString name, const SmallVectorImpl<CompilerType> &parameters) {
-  FortranType *type = m_function_map[name].get();
-  if (type)
-    return CompilerType(weak_from_this(), (void *)type);
+  llvm::FoldingSetNodeID id;
+  FortranFunction::Profile(id, name, parameters);
+  void *insert_pos = nullptr;
+  FortranFunction *fortran_function =
+      m_functions.FindNodeOrInsertPos(id, insert_pos);
+  if (fortran_function)
+    return CompilerType(weak_from_this(), (void *)fortran_function);
   auto new_type_up = std::make_unique<FortranFunction>(name, parameters);
-  FortranType *raw_ptr = new_type_up.get();
+  fortran_function = new_type_up.get();
 
-  m_function_map[name] = std::move(new_type_up);
+  m_functions.InsertNode(fortran_function, insert_pos);
+  m_types.push_back(std::move(new_type_up));
 
-  return CompilerType(weak_from_this(), (void *)raw_ptr);
+  return CompilerType(weak_from_this(), (void *)fortran_function);
 }
 
 CompilerType TypeSystemFortran::CreateType(uint32_t kind, uint64_t bitsize,
@@ -215,12 +225,11 @@ CompilerType TypeSystemFortran::CreateArrayType(FortranArrayMetadata array_info,
   size_t rank = array_info.dimensions.size();
   llvm::SmallVector<ArrayShape, 2> array_shapes;
   ConstString type_name;
-  for (int idx = 0; idx < rank; ++idx) {
+  for (size_t idx = 0; idx < rank; ++idx) {
     ArrayShape shape;
     ArrayBound lb;
     ArrayBound ub;
     ArrayBound::Category bound_category;
-    uint64_t byte_stride;
     int64_t dim_elements = -1;
 
     if (std::holds_alternative<std::monostate>(
@@ -286,14 +295,17 @@ CompilerType TypeSystemFortran::CreateArrayType(FortranArrayMetadata array_info,
             array_info.dimensions[idx].upper_bound))
       shape.SetUpperBoundExpression(std::get<DWARFExpressionList>(
           array_info.dimensions[idx].upper_bound));
+
     if (std::holds_alternative<DWARFExpressionList>(
             array_info.dimensions[idx].lower_bound))
       shape.SetLowerBoundExpression(std::get<DWARFExpressionList>(
           array_info.dimensions[idx].lower_bound));
+
     if (std::holds_alternative<DWARFExpressionList>(
             array_info.dimensions[idx].element_count))
       shape.SetElementCountExpression(std::get<DWARFExpressionList>(
           array_info.dimensions[idx].element_count));
+
     if (std::holds_alternative<DWARFExpressionList>(
             array_info.dimensions[idx].byte_stride))
       shape.SetByteStrideExpression(std::get<DWARFExpressionList>(
@@ -301,16 +313,29 @@ CompilerType TypeSystemFortran::CreateArrayType(FortranArrayMetadata array_info,
 
     array_shapes.push_back(shape);
   }
+  llvm::FoldingSetNodeID id;
+  FortranArray::Profile(id, array_info.element_type, array_shapes,
+                        array_info.is_allocatable, array_info.is_dynamic,
+                        array_info.allocated_exp, array_info.data_location_exp);
+  void *insert_pos = nullptr;
+  FortranArray *array_type = m_arrays.FindNodeOrInsertPos(id, insert_pos);
+  if (array_type)
+    return CompilerType(weak_from_this(), (void *)array_type);
+
   ConstString array_type_name =
       CreateArrayTypeName(array_info.element_type, array_shapes,
                           array_info.is_allocatable, array_info.is_star);
 
-  FortranArray *child_type = new FortranArray(
+  auto new_type_up = std::make_unique<FortranArray>(
       array_info.element_type, array_shapes, array_type_name, total_array_size,
       array_info.is_allocatable, array_info.is_dynamic, total_elements,
       array_info.allocated_exp, array_info.data_location_exp);
 
-  return CompilerType(weak_from_this(), (void *)child_type);
+  array_type = new_type_up.get();
+  m_arrays.InsertNode(array_type, insert_pos);
+  m_types.push_back(std::move(new_type_up));
+
+  return CompilerType(weak_from_this(), (void *)array_type);
 }
 
 llvm::Expected<CompilerType> TypeSystemFortran::GetChildCompilerTypeAtIndex(
@@ -339,10 +364,11 @@ llvm::Expected<CompilerType> TypeSystemFortran::GetChildCompilerTypeAtIndex(
   if (fortran_type->IsDynamic())
     return CompilerType();
   llvm::ArrayRef<ArrayShape> old_dimensions = fortran_type->GetDimensions();
-  int64_t ub = old_dimensions.front().GetUpperBound().GetBound();
   int64_t lb = old_dimensions.front().GetLowerBound().GetBound();
   uint64_t num_elements = old_dimensions.front().GetNumberOfElements();
-
+  // In Fortran indices can be negative, but lldb defaults to using unsigned
+  // by casting the index to a signed integer we can access elements with
+  // negative indices.
   if (idx >= num_elements)
     return CompilerType();
 
@@ -379,14 +405,26 @@ llvm::Expected<CompilerType> TypeSystemFortran::GetChildCompilerTypeAtIndex(
     } else {
       child_byte_size = new_total_elements * fortran_type->GetElementByteSize();
     }
-    child_name = llvm::formatv("[{0}]", lb + idx);
+    child_name = llvm::formatv("[{0}]", idx + lb);
+    llvm::FoldingSetNodeID id;
+    FortranArray::Profile(id, fortran_type->GetElementType(), new_dimensions,
+                          false, false, DWARFExpressionList(),
+                          DWARFExpressionList());
+    void *insert_pos = nullptr;
+    FortranArray *array_type = m_arrays.FindNodeOrInsertPos(id, insert_pos);
+    if (array_type)
+      return CompilerType(weak_from_this(), (void *)array_type);
+
     ConstString type_name =
         CreateArrayTypeName(fortran_type->GetElementType(), new_dimensions,
                             is_allocatable, is_star);
-    FortranArray *array_type = new FortranArray(
+    auto new_type_up = std::make_unique<FortranArray>(
         fortran_type->GetElementType(), new_dimensions, type_name,
         child_byte_size, false, false, new_total_elements,
         DWARFExpressionList(), DWARFExpressionList());
+    array_type = new_type_up.get();
+    m_arrays.InsertNode(array_type, insert_pos);
+    m_types.push_back(std::move(new_type_up));
     return CompilerType(weak_from_this(), (void *)array_type);
   } else {
     child_byte_offset = idx * old_dimensions.front().GetByteStride();
@@ -395,6 +433,20 @@ llvm::Expected<CompilerType> TypeSystemFortran::GetChildCompilerTypeAtIndex(
   }
 }
 
+int64_t TypeSystemFortran::GetArrayLowerBound(opaque_compiler_type_t type) {
+  if (!type)
+    return 0;
+  FortranType *fortran_type = static_cast<FortranType *>(type);
+  if (!fortran_type)
+    return 0;
+  if (fortran_type->GetKind() != FortranType::KIND_ARRAY)
+    return 0;
+  FortranArray *array_type = static_cast<FortranArray *>(fortran_type);
+  if (!array_type->GetDimensions().front().GetLowerBound().IsBoundKnown())
+    return 0;
+  return array_type->GetDimensions().front().GetLowerBound().GetBound();
+}
+
 /// Returns the type name upper-cased to follow Fortran's general style
 ConstString TypeSystemFortran::GetTypeName(opaque_compiler_type_t type,
                                            bool BaseOnly) {
@@ -547,8 +599,11 @@ TypeSystemFortran::GetNumChildren(opaque_compiler_type_t type,
           "Couldn't get number of children, bad Fortran type.");
 
     // Fetch the number of elements
-    if (!fortran_array->IsDynamic())
+    if (!fortran_array->IsDynamic()) {
+      if (fortran_array->GetDimensions().empty())
+        return 0;
       return fortran_array->GetDimensions().front().GetNumberOfElements();
+    }
     return 0;
   }
   default:
@@ -579,9 +634,19 @@ TypeSystemFortran::GetPointerType(lldb::opaque_compiler_type_t type) {
   FortranType *pointee_type = static_cast<FortranType *>(type);
   if (!pointee_type)
     return CompilerType();
+
+  llvm::FoldingSetNodeID id;
+  FortranPointer::Profile(id, pointee_type);
+  void *insert_pos = nullptr;
+  FortranPointer *pointer_type = m_pointers.FindNodeOrInsertPos(id, insert_pos);
+  if (pointer_type)
+    return CompilerType(weak_from_this(), (void *)pointer_type);
   std::string ptr_name = pointee_type->GetName().GetStringRef().str() + " *";
-  FortranPointer *pointer_type =
-      new FortranPointer(pointee_type, ConstString(ptr_name));
+  auto new_type_up =
+      std::make_unique<FortranPointer>(pointee_type, ConstString(ptr_name));
+  pointer_type = new_type_up.get();
+  m_pointers.InsertNode(pointer_type, insert_pos);
+  m_types.push_back(std::move(new_type_up));
   return CompilerType(weak_from_this(), (void *)pointer_type);
 }
 
diff --git a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
index 753168e44d12c..7d052289a3b97 100644
--- a/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
+++ b/lldb/source/Plugins/TypeSystem/Fortran/TypeSystemFortran.h
@@ -11,6 +11,7 @@
 #include "lldb/Symbol/TypeSystem.h"
 
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
 #include "llvm/Support/ErrorHandling.h"
 
 namespace lldb_private {
@@ -18,6 +19,9 @@ namespace lldb_private {
 namespace plugin {
 namespace fortran {
 class FortranType;
+class FortranFunction;
+class FortranArray;
+class FortranPointer;
 struct FortranDimension;
 struct FortranArrayMetadata;
 } // namespace fortran
@@ -238,6 +242,8 @@ class TypeSystemFortran : public TypeSystem {
                                    ExecutionContextScope *exe_scope) override {
     return CompilerType();
   }
+
+  int64_t GetArrayLowerBound(lldb::opaque_compiler_type_t type) override;
   //
   CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) override {
     if (!type)
@@ -482,20 +488,14 @@ class TypeSystemFortran : public TypeSystem {
   }
 
 private:
-  typedef std::pair<int, uint64_t> TypeKey;
-  typedef llvm::DenseMap<TypeKey, std::unique_ptr<plugin::fortran::FortranType>>
-      BasicTypeMap;
-  typedef llvm::DenseMap<ConstString,
-                         std::unique_ptr<plugin::fortran::FortranType>>
-      FunctionMap;
-
-  // TODO: Types are assosciated by their kind and bitsize, this helps to
-  // return from their basic type and is enough for basic types but
-  // will change once more types are supported
-  BasicTypeMap m_basic_type_map;
-  // Right now we can index functions just by their name, but a more
-  // effecient solution might replace this
-  FunctionMap m_function_map;
+  mutable llvm::FoldingSet<plugin::fortran::FortranType> m_basic_types;
+  mutable llvm::FoldingSet<plugin::fortran::FortranFunction> m_functions;
+  mutable llvm::FoldingSet<plugin::fortran::FortranArray> m_arrays;
+  mutable llvm::FoldingSet<plugin::fortran::FortranPointer> m_pointers;
+  // We store all unique pointer types here so we can manage the lifecycle
+  // of the types
+  mutable llvm::SmallVector<std::unique_ptr<plugin::fortran::FortranType>>
+      m_types;
   std::unique_ptr<plugin::dwarf::DWARFASTParser> m_dwarf_ast_parser_up;
   /// Store byte order of the system so variables can be printed correctly
   lldb::ByteOrder m_byte_order;
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index 6f20bfa89ed38..2e4e9824d0a31 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -603,6 +603,13 @@ CompilerType CompilerType::GetArrayType(uint64_t size) const {
   }
   return CompilerType();
 }
+int64_t CompilerType::GetArrayLowerBound() const {
+  if (IsValid()) {
+    if (auto type_system_sp = GetTypeSystem())
+      return type_system_sp->GetArrayLowerBound(m_type);
+  }
+  return 0;
+}
 
 CompilerType CompilerType::GetCanonicalType() const {
   if (IsValid())

>From 1a4621dc88854404e6c1125df339460efad9da4d Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Thu, 30 Jul 2026 15:13:14 +0300
Subject: [PATCH 41/44] [lldb][Fortran] Added support for setting breakpoints
 with case-insensitivity in Fortran

---
 .../Language/Fortran/FortranLanguage.cpp       | 18 ++++++++++++++++++
 .../Plugins/Language/Fortran/FortranLanguage.h |  3 +++
 2 files changed, 21 insertions(+)

diff --git a/lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp b/lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp
index 115e1487889e4..149ffc003e5fd 100644
--- a/lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp
+++ b/lldb/source/Plugins/Language/Fortran/FortranLanguage.cpp
@@ -101,3 +101,21 @@ FortranLanguage::GetHardcodedSynthetics() {
 
   return formatters;
 }
+
+std::vector<Language::MethodNameVariant>
+FortranLanguage::GetMethodNameVariants(llvm::StringRef name) const {
+  // Flang lower-cases subprograms internally, with the exception of the main 
+  // subprogram which is upper-cased.
+  std::vector<Language::MethodNameVariant> variants;
+  std::string lower_name = name.lower();
+  if (name != lower_name) 
+    variants.emplace_back(lower_name, lldb::eFunctionNameTypeFull);
+  
+  std::string upper_name = name.upper();
+  if (name != upper_name) 
+    variants.emplace_back(upper_name, lldb::eFunctionNameTypeFull);
+  
+  variants.emplace_back(lower_name + "_", lldb::eFunctionNameTypeFull);
+
+  return variants;
+}
diff --git a/lldb/source/Plugins/Language/Fortran/FortranLanguage.h b/lldb/source/Plugins/Language/Fortran/FortranLanguage.h
index 391336629848f..a35d19e0ee006 100644
--- a/lldb/source/Plugins/Language/Fortran/FortranLanguage.h
+++ b/lldb/source/Plugins/Language/Fortran/FortranLanguage.h
@@ -50,6 +50,9 @@ class FortranLanguage : public Language {
 
   HardcodedFormatters::HardcodedSyntheticFinder
   GetHardcodedSynthetics() override;
+
+  std::vector<Language::MethodNameVariant>
+  GetMethodNameVariants(llvm::StringRef name) const override;
 };
 
 }; // namespace lldb_private

>From a1c953f3c01fb56a8f98aa0fc16804ebdfe14e9d Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 31 Jul 2026 20:34:41 +0300
Subject: [PATCH 42/44] [lldb] Added tests for case-insensitivity and removed
 redundant loop in NameToDIE

---
 .../Plugins/SymbolFile/DWARF/NameToDIE.cpp    |  10 +-
 .../basics/CaseSensitiveLookup/Makefile       |   3 +
 .../TestFrameVarDILCaseSensitiveLookup.py     |  59 +++++
 .../basics/CaseSensitiveLookup/main.cpp       |   6 +
 .../DWARF/DWARFDebugNamesIndexTest.cpp        | 201 +++++++++++++++++-
 5 files changed, 269 insertions(+), 10 deletions(-)
 create mode 100644 lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/Makefile
 create mode 100644 lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/TestFrameVarDILCaseSensitiveLookup.py
 create mode 100644 lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/main.cpp

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
index d6636195e2bbb..c370eaa2a6471 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -38,14 +38,10 @@ bool NameToDIE::Find(
   for (const auto &entry : m_map.equal_range(name))
     if (callback(entry.value) == IterationAction::Stop)
       return false;
-  
-  if(!NameCaseInsensitive){
-    for (const auto &entry : m_map.equal_range(name))
-      if (callback(entry.value) == IterationAction::Stop)
-        return false;
+
+  if (!NameCaseInsensitive)
     return true;
-  }
-  
+
   for (const auto &entry : m_map){
     if(ConstString::Equals(ConstString(entry.cstring.GetCString()), name, false))
       if (callback(entry.value) == IterationAction::Stop)
diff --git a/lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/Makefile b/lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/Makefile
new file mode 100644
index 0000000000000..2bb9ce046a907
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
\ No newline at end of file
diff --git a/lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/TestFrameVarDILCaseSensitiveLookup.py b/lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/TestFrameVarDILCaseSensitiveLookup.py
new file mode 100644
index 0000000000000..876107f1e4017
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/TestFrameVarDILCaseSensitiveLookup.py
@@ -0,0 +1,59 @@
+"""
+Test that DIL matches variables correctly for case-sensitive languages.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test import lldbutil
+
+
+class TestFrameVarDILCaseSensitiveLookup(TestBase):
+    # If your test case doesn't stress debug info, then
+    # set this to true.  That way it won't be run once for
+    # each debug info format.
+    NO_DEBUG_INFO_TESTCASE = True
+
+    def test_frame_var(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(
+            self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
+        )
+
+        self.runCmd("settings set target.experimental.use-DIL true")
+
+        self.expect_var_path("globalVar", type="int", value="-559038737")  # 0xDEADBEEF
+
+        self.expect(
+            "frame var GlobaLVaR",
+            error=True,
+            substrs=["use of undeclared identifier 'GlobaLVaR'"],
+        )
+        self.expect(
+            "frame var GLOBALVAR",
+            error=True,
+            substrs=["use of undeclared identifier 'GLOBALVAR'"],
+        )
+        self.expect(
+            "frame var globalvar",
+            error=True,
+            substrs=["use of undeclared identifier 'globalvar'"],
+        )
+
+        self.expect_var_path("testVariable", type="int", value="3")
+
+        self.expect(
+            "frame var TestVaRiable",
+            error=True,
+            substrs=["use of undeclared identifier 'TestVaRiable'"],
+        )
+        self.expect(
+            "frame var testvariable",
+            error=True,
+            substrs=["use of undeclared identifier 'testvariable'"],
+        )
+        self.expect(
+            "frame var TESTVARIABLE",
+            error=True,
+            substrs=["use of undeclared identifier 'TESTVARIABLE'"],
+        )
diff --git a/lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/main.cpp b/lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/main.cpp
new file mode 100644
index 0000000000000..c604dc67e73bc
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/basics/CaseSensitiveLookup/main.cpp
@@ -0,0 +1,6 @@
+int globalVar = 0xDEADBEEF;
+int main(int argc, char **argv) {
+  int testVariable;
+  testVariable = 3;
+  return 0; // Set a breakpoint here
+}
\ No newline at end of file
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp
index dd8a0742f6b70..854e6e1f49898 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp
@@ -1,4 +1,5 @@
-//===-- DWARFDIETest.cpp ----------------------------------------------=---===//
+//===-- DWARFDebugNamesIndexTest.cpp
+//----------------------------------------------=---===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -10,7 +11,9 @@
 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
 #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
 #include "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h"
+#include "TestingSupport/SubsystemRAII.h"
 #include "TestingSupport/Symbol/YAMLModuleTester.h"
+#include "lldb/Core/Debugger.h"
 #include "lldb/lldb-private-enumerations.h"
 #include "llvm/ADT/STLExtras.h"
 #include "gmock/gmock.h"
@@ -21,6 +24,15 @@ using namespace lldb_private;
 using namespace lldb_private::plugin::dwarf;
 using StringRef = llvm::StringRef;
 
+class DWARFDebugNamesIndexTest : public testing::Test {
+public:
+  void SetUp() override {
+    Debugger::Initialize(nullptr);
+  }
+
+  void TearDown() override { Debugger::Terminate(); }
+};
+
 static void
 check_num_matches(DebugNamesDWARFIndex &index, int expected_num_matches,
                   llvm::ArrayRef<DWARFDeclContext::Entry> ctx_entries) {
@@ -38,7 +50,7 @@ static DWARFDeclContext::Entry make_entry(const char *c) {
   return DWARFDeclContext::Entry(llvm::dwarf::DW_TAG_class_type, c);
 }
 
-TEST(DWARFDebugNamesIndexTest, FullyQualifiedQueryWithIDXParent) {
+TEST_F(DWARFDebugNamesIndexTest, FullyQualifiedQueryWithIDXParent) {
   const char *yamldata = R"(
 --- !ELF
 FileHeader:
@@ -130,7 +142,7 @@ TEST(DWARFDebugNamesIndexTest, FullyQualifiedQueryWithIDXParent) {
   check_num_matches(*index, 1, {make_entry("3")});
 }
 
-TEST(DWARFDebugNamesIndexTest, FullyQualifiedQueryWithoutIDXParent) {
+TEST_F(DWARFDebugNamesIndexTest, FullyQualifiedQueryWithoutIDXParent) {
   const char *yamldata = R"(
 --- !ELF
 FileHeader:
@@ -207,3 +219,186 @@ TEST(DWARFDebugNamesIndexTest, FullyQualifiedQueryWithoutIDXParent) {
   check_num_matches(*index, 1, {make_entry("2"), make_entry("1")});
   check_num_matches(*index, 1, {make_entry("2")});
 }
+
+TEST_F(DWARFDebugNamesIndexTest, CaseInsesitiveQuery) {
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+DWARF:
+  debug_str:
+    - 'num_int'
+  debug_abbrev:
+    - Table:
+        - Code:            0x1
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+            - Attribute:       DW_AT_identifier_case
+              Form:            DW_FORM_data1
+        - Code:            0x2
+          Tag:             DW_TAG_variable
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_strp
+            - Attribute:       DW_AT_const_value    
+              Form:            DW_FORM_udata        
+  debug_info:
+    - Version:         4
+      AddrSize:        8
+      Entries:
+        - AbbrCode:        0x1
+          Values:
+            - Value:       0x0008 # DW_LANG_Fortran90
+            - Value:       0x03   # DW_ID_case_insensitive (0x3)
+        - AbbrCode:        0x2
+          Values:
+            - Value:       0x0    
+            - Value:       0x2a                     
+        - AbbrCode:        0x0
+)";
+
+  YAMLModuleTester t(yamldata);
+  auto *symbol_file =
+      llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile());
+  auto *index = symbol_file->getIndex();
+  int num_matches = 0;
+  index->GetGlobalVariables(ConstString("NUM_INT"), [&](DWARFDIE die) {
+    num_matches++;
+    return IterationAction::Stop;
+  });
+  EXPECT_EQ(num_matches, 1);
+
+  num_matches = 0;
+  index->GetGlobalVariables(ConstString("num_int"), [&](DWARFDIE die) {
+    num_matches++;
+    return IterationAction::Stop;
+  });
+  EXPECT_EQ(num_matches, 1);
+
+  num_matches = 0;
+  index->GetGlobalVariables(ConstString("NuM_iNT"), [&](DWARFDIE die) {
+    num_matches++;
+    return IterationAction::Stop;
+  });
+  EXPECT_EQ(num_matches, 1);
+
+  num_matches = 0;
+  index->GetGlobalVariables(ConstString("num_in"), [&](DWARFDIE die) {
+    num_matches++;
+    return IterationAction::Stop;
+  });
+  EXPECT_EQ(num_matches, 0);
+}
+
+TEST_F(DWARFDebugNamesIndexTest, CasesSesitiveDefaultQuery) {
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_X86_64
+DWARF:
+  debug_abbrev:
+    - Table:
+        - Code:            0x1
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+        - Code:            0x2
+          Tag:             DW_TAG_variable
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_string
+            - Attribute:       DW_AT_const_value    
+              Form:            DW_FORM_udata        
+
+    - Table:
+        - Code:            0x1
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_yes
+          Attributes:
+            - Attribute:       DW_AT_language
+              Form:            DW_FORM_data2
+            - Attribute:       DW_AT_identifier_case
+              Form:            DW_FORM_data1
+        - Code:            0x2
+          Tag:             DW_TAG_variable
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_name
+              Form:            DW_FORM_string
+            - Attribute:       DW_AT_const_value    
+              Form:            DW_FORM_udata        
+
+  debug_info:
+    - Version:         4
+      AddrSize:        8
+      Entries:
+        - AbbrCode:        0x1
+          Values:
+            - Value:       0x0004 # DW_LANG_C_plus_plus
+        - AbbrCode:        0x2
+          Values:
+            - CStr:        'SensitiveVar'
+            - Value:       0x2a                     
+        - AbbrCode:        0x0
+
+    - Version:         4
+      AddrSize:        8
+      Entries:
+        - AbbrCode:        0x1
+          Values:
+            - Value:       0x0008 # DW_LANG_Fortran90
+            - Value:       0x03   # DW_ID_case_insensitive
+        - AbbrCode:        0x2
+          Values:
+            - CStr:        'InsensitiveVar'
+            - Value:       0x2a                    
+        - AbbrCode:        0x0
+)";
+  // If one Compile unit is case-insensitive and the other is case-sensitive we
+  // should default to all compile units being case-sensitive.
+  YAMLModuleTester t(yamldata);
+  auto *symbol_file =
+      llvm::cast<SymbolFileDWARF>(t.GetModule()->GetSymbolFile());
+  auto *index = symbol_file->getIndex();
+
+  int sens_exact = 0;
+  index->GetGlobalVariables(ConstString("SensitiveVar"), [&](DWARFDIE die) {
+    sens_exact++;
+    return IterationAction::Stop;
+  });
+  EXPECT_EQ(sens_exact, 1);
+
+  int sens_mismatch = 0;
+  index->GetGlobalVariables(ConstString("sensitivevar"), [&](DWARFDIE die) {
+    sens_mismatch++;
+    return IterationAction::Stop;
+  });
+  EXPECT_EQ(sens_mismatch, 0);
+
+  int insens_exact = 0;
+  index->GetGlobalVariables(ConstString("InsensitiveVar"), [&](DWARFDIE die) {
+    insens_exact++;
+    return IterationAction::Stop;
+  });
+  EXPECT_EQ(insens_exact, 1);
+
+  int insens_mismatch = 0;
+  index->GetGlobalVariables(ConstString("insensitivevar"), [&](DWARFDIE die) {
+    insens_mismatch++;
+    return IterationAction::Stop;
+  });
+  EXPECT_EQ(insens_mismatch, 0);
+}
\ No newline at end of file

>From e1073f6b3ba4c063a191eef87ddd7e97491bd879 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Fri, 31 Jul 2026 20:55:12 +0300
Subject: [PATCH 43/44] [lldb] Fixed formatting

---
 lldb/include/lldb/Symbol/CompileUnit.h        |  6 +--
 .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp    | 35 ++++++++--------
 .../SymbolFile/DWARF/ManualDWARFIndex.cpp     |  4 +-
 .../SymbolFile/DWARF/ManualDWARFIndex.h       | 42 +++++++++----------
 .../Plugins/SymbolFile/DWARF/NameToDIE.cpp    |  5 ++-
 .../Plugins/SymbolFile/DWARF/NameToDIE.h      |  7 +++-
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      |  5 ++-
 lldb/source/ValueObject/DILEval.cpp           | 24 +++++------
 .../DWARF/DWARFDebugNamesIndexTest.cpp        |  4 +-
 9 files changed, 67 insertions(+), 65 deletions(-)

diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h
index 7d99bd16ae02d..e598a0794acb3 100644
--- a/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/lldb/include/lldb/Symbol/CompileUnit.h
@@ -152,11 +152,9 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
     m_language = language;
   }
 
-  lldb::IdentifierCaseType GetCasing() {
-    return m_identifier_case;
-  }
+  lldb::IdentifierCaseType GetCasing() { return m_identifier_case; }
 
-  void SetCasing(lldb::IdentifierCaseType identifier_case){
+  void SetCasing(lldb::IdentifierCaseType identifier_case) {
     m_identifier_case = identifier_case;
   }
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 7fbef4a831ff1..f1068ea4aec20 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -889,31 +889,32 @@ llvm::VersionTuple DWARFUnit::GetProducerVersion() {
 }
 
 lldb::IdentifierCaseType DWARFUnit::GetIdentifierCase() {
-  if(m_identifier_case != eCaseUnknown)
+  if (m_identifier_case != eCaseUnknown)
     return m_identifier_case;
 
   const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
 
-  if(!die) 
+  if (!die)
     m_identifier_case = eCaseSensitive;
-    
+
   else {
-    uint64_t identifier_case = die->GetAttributeValueAsUnsigned(this, DW_AT_identifier_case, llvm::dwarf::DW_ID_case_sensitive);
+    uint64_t identifier_case = die->GetAttributeValueAsUnsigned(
+        this, DW_AT_identifier_case, llvm::dwarf::DW_ID_case_sensitive);
 
     switch (identifier_case) {
-      case llvm::dwarf::DW_ID_up_case:
-        m_identifier_case = eUpperCase;
-        break;
-      case llvm::dwarf::DW_ID_down_case:
-        m_identifier_case = eLowerCase;
-        break;
-      case llvm::dwarf::DW_ID_case_insensitive:
-        m_identifier_case = eCaseInsensitive;
-        break;
-      case llvm::dwarf::DW_ID_case_sensitive:
-      default:
-        m_identifier_case = eCaseSensitive;
-        break;
+    case llvm::dwarf::DW_ID_up_case:
+      m_identifier_case = eUpperCase;
+      break;
+    case llvm::dwarf::DW_ID_down_case:
+      m_identifier_case = eLowerCase;
+      break;
+    case llvm::dwarf::DW_ID_case_insensitive:
+      m_identifier_case = eCaseInsensitive;
+      break;
+    case llvm::dwarf::DW_ID_case_sensitive:
+    default:
+      m_identifier_case = eCaseSensitive;
+      break;
     }
   }
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index 43f53ea34163b..76506daea4450 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -160,9 +160,9 @@ void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp,
 
   lldb::IdentifierCaseType cu_identifier_case = unit.GetIdentifierCase();
 
-  // If at least one of the Compile Units is case sensitive, then all compile  
+  // If at least one of the Compile Units is case sensitive, then all compile
   // units will be case sensitive
-  if(cu_identifier_case != eCaseSensitive)
+  if (cu_identifier_case != eCaseSensitive)
     SetNameCaseInsensitive();
   else
     SetStrictlyCaseSensitive();
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
index 5e137c0f930d8..4612e7b97f2d8 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -169,27 +169,27 @@ class ManualDWARFIndex : public DWARFIndex {
   ///   True if this index is a partial index, false otherwise.
   bool IsPartial() const;
 
-	void SetNameCaseInsensitive() {
-		m_set.function_basenames.SetNameCaseInsensitive();
-		m_set.function_fullnames.SetNameCaseInsensitive();
-		m_set.function_methods.SetNameCaseInsensitive();
-		m_set.function_selectors.SetNameCaseInsensitive();
-		m_set.objc_class_selectors.SetNameCaseInsensitive();
-		m_set.globals.SetNameCaseInsensitive();
-		m_set.types.SetNameCaseInsensitive();
-		m_set.namespaces.SetNameCaseInsensitive();
-	}
-
-	void SetStrictlyCaseSensitive() {
-		m_set.function_basenames.SetStrictlyCaseSensitive();
-		m_set.function_fullnames.SetStrictlyCaseSensitive();
-		m_set.function_methods.SetStrictlyCaseSensitive();
-		m_set.function_selectors.SetStrictlyCaseSensitive();
-		m_set.objc_class_selectors.SetStrictlyCaseSensitive();
-		m_set.globals.SetStrictlyCaseSensitive();
-		m_set.types.SetStrictlyCaseSensitive();
-		m_set.namespaces.SetStrictlyCaseSensitive();
-	}
+  void SetNameCaseInsensitive() {
+    m_set.function_basenames.SetNameCaseInsensitive();
+    m_set.function_fullnames.SetNameCaseInsensitive();
+    m_set.function_methods.SetNameCaseInsensitive();
+    m_set.function_selectors.SetNameCaseInsensitive();
+    m_set.objc_class_selectors.SetNameCaseInsensitive();
+    m_set.globals.SetNameCaseInsensitive();
+    m_set.types.SetNameCaseInsensitive();
+    m_set.namespaces.SetNameCaseInsensitive();
+  }
+
+  void SetStrictlyCaseSensitive() {
+    m_set.function_basenames.SetStrictlyCaseSensitive();
+    m_set.function_fullnames.SetStrictlyCaseSensitive();
+    m_set.function_methods.SetStrictlyCaseSensitive();
+    m_set.function_selectors.SetStrictlyCaseSensitive();
+    m_set.objc_class_selectors.SetStrictlyCaseSensitive();
+    m_set.globals.SetStrictlyCaseSensitive();
+    m_set.types.SetStrictlyCaseSensitive();
+    m_set.namespaces.SetStrictlyCaseSensitive();
+  }
 
   /// The DWARF file which we are indexing.
   SymbolFileDWARF *m_dwarf;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
index c370eaa2a6471..c2699517b8950 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -42,8 +42,9 @@ bool NameToDIE::Find(
   if (!NameCaseInsensitive)
     return true;
 
-  for (const auto &entry : m_map){
-    if(ConstString::Equals(ConstString(entry.cstring.GetCString()), name, false))
+  for (const auto &entry : m_map) {
+    if (ConstString::Equals(ConstString(entry.cstring.GetCString()), name,
+                            false))
       if (callback(entry.value) == IterationAction::Stop)
         return false;
   }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
index a85c6a2cda846..01cdffb5bb2db 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -86,8 +86,11 @@ class NameToDIE {
 
   void Clear() { m_map.Clear(); }
 
-  void SetNameCaseInsensitive() { if(!StrictlyCaseSensitive) NameCaseInsensitive = true; }
-  
+  void SetNameCaseInsensitive() {
+    if (!StrictlyCaseSensitive)
+      NameCaseInsensitive = true;
+  }
+
   void SetStrictlyCaseSensitive() {
     NameCaseInsensitive = false;
     StrictlyCaseSensitive = true;
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 881a009553df2..68294913de962 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -803,7 +803,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
           cu_sp->SetCasing(cu_casing);
 
           dwarf_cu.SetLLDBCompUnit(cu_sp.get());
-          
+
           SetCompileUnitAtIndex(dwarf_cu.GetID(), cu_sp);
         };
 
@@ -832,7 +832,8 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
           if (support_files.GetSize() == 0)
             return false;
           initialize_cu(support_files.GetSupportFileAtIndex(0),
-                        eLanguageTypeUnknown, dwarf_cu.GetIdentifierCase(), std::move(support_files));
+                        eLanguageTypeUnknown, dwarf_cu.GetIdentifierCase(),
+                        std::move(support_files));
           return true;
         };
 
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index b358948bee093..374faaed043f9 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -291,20 +291,19 @@ lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref,
   lldb::VariableListSP variable_list;
   lldb::IdentifierCaseType identifier_case = lldb::eCaseSensitive;
 
-  if (symbol_context.comp_unit){
+  if (symbol_context.comp_unit) {
     variable_list = symbol_context.comp_unit->GetVariableList(true);
     identifier_case = symbol_context.comp_unit->GetCasing();
   }
-    
 
   name_ref.consume_front("::");
 
   std::string search_string;
-  if(identifier_case == lldb::eLowerCase)
+  if (identifier_case == lldb::eLowerCase)
     search_string = name_ref.lower();
-  else if(identifier_case == lldb::eUpperCase)
+  else if (identifier_case == lldb::eUpperCase)
     search_string = name_ref.upper();
-  else 
+  else
     search_string = name_ref.str();
 
   lldb::ValueObjectSP value_sp;
@@ -359,18 +358,19 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
     lldb::VariableListSP variable_list(
         stack_frame.GetInScopeVariableList(false));
 
-    SymbolContext sc = stack_frame.GetSymbolContext(lldb::eSymbolContextCompUnit);
+    SymbolContext sc =
+        stack_frame.GetSymbolContext(lldb::eSymbolContextCompUnit);
 
     lldb::IdentifierCaseType identifier_case = lldb::eCaseSensitive;
-    if(sc.comp_unit)
+    if (sc.comp_unit)
       identifier_case = sc.comp_unit->GetCasing();
 
     std::string search_string;
-    if(identifier_case == lldb::eLowerCase)
+    if (identifier_case == lldb::eLowerCase)
       search_string = name_ref.lower();
-    else if(identifier_case == lldb::eUpperCase)
+    else if (identifier_case == lldb::eUpperCase)
       search_string = name_ref.upper();
-    else 
+    else
       search_string = name_ref.str();
 
     lldb::ValueObjectSP value_sp;
@@ -386,8 +386,8 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
       return value_sp;
 
     // Try looking for an instance variable (class member).
-    sc = stack_frame.GetSymbolContext(
-        lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
+    sc = stack_frame.GetSymbolContext(lldb::eSymbolContextFunction |
+                                      lldb::eSymbolContextBlock);
     llvm::StringRef instance_name = sc.GetInstanceName();
     value_sp = stack_frame.FindVariable(ConstString(instance_name));
     if (value_sp)
diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp
index 854e6e1f49898..81fa3aca72da2 100644
--- a/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp
+++ b/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp
@@ -26,9 +26,7 @@ using StringRef = llvm::StringRef;
 
 class DWARFDebugNamesIndexTest : public testing::Test {
 public:
-  void SetUp() override {
-    Debugger::Initialize(nullptr);
-  }
+  void SetUp() override { Debugger::Initialize(nullptr); }
 
   void TearDown() override { Debugger::Terminate(); }
 };

>From daa4b246cf9322350480da0ce8eded49751fba06 Mon Sep 17 00:00:00 2001
From: Iasonaskrpr <iaskarapro at gmail.com>
Date: Sat, 1 Aug 2026 13:33:27 +0300
Subject: [PATCH 44/44] [lldb][NFC] Fixed unformatted files

---
 lldb/include/lldb/Symbol/CompileUnit.h        |  6 ++--
 .../Plugins/SymbolFile/DWARF/DWARFUnit.cpp    | 35 ++++++++++---------
 .../SymbolFile/DWARF/ManualDWARFIndex.cpp     | 18 +++++-----
 .../SymbolFile/DWARF/ManualDWARFIndex.h       |  2 +-
 .../Plugins/SymbolFile/DWARF/NameToDIE.cpp    |  9 ++---
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      |  5 +--
 lldb/source/ValueObject/DILEval.cpp           | 24 ++++++-------
 7 files changed, 50 insertions(+), 49 deletions(-)

diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h
index 7d99bd16ae02d..e598a0794acb3 100644
--- a/lldb/include/lldb/Symbol/CompileUnit.h
+++ b/lldb/include/lldb/Symbol/CompileUnit.h
@@ -152,11 +152,9 @@ class CompileUnit : public std::enable_shared_from_this<CompileUnit>,
     m_language = language;
   }
 
-  lldb::IdentifierCaseType GetCasing() {
-    return m_identifier_case;
-  }
+  lldb::IdentifierCaseType GetCasing() { return m_identifier_case; }
 
-  void SetCasing(lldb::IdentifierCaseType identifier_case){
+  void SetCasing(lldb::IdentifierCaseType identifier_case) {
     m_identifier_case = identifier_case;
   }
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index 7fbef4a831ff1..f1068ea4aec20 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -889,31 +889,32 @@ llvm::VersionTuple DWARFUnit::GetProducerVersion() {
 }
 
 lldb::IdentifierCaseType DWARFUnit::GetIdentifierCase() {
-  if(m_identifier_case != eCaseUnknown)
+  if (m_identifier_case != eCaseUnknown)
     return m_identifier_case;
 
   const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly();
 
-  if(!die) 
+  if (!die)
     m_identifier_case = eCaseSensitive;
-    
+
   else {
-    uint64_t identifier_case = die->GetAttributeValueAsUnsigned(this, DW_AT_identifier_case, llvm::dwarf::DW_ID_case_sensitive);
+    uint64_t identifier_case = die->GetAttributeValueAsUnsigned(
+        this, DW_AT_identifier_case, llvm::dwarf::DW_ID_case_sensitive);
 
     switch (identifier_case) {
-      case llvm::dwarf::DW_ID_up_case:
-        m_identifier_case = eUpperCase;
-        break;
-      case llvm::dwarf::DW_ID_down_case:
-        m_identifier_case = eLowerCase;
-        break;
-      case llvm::dwarf::DW_ID_case_insensitive:
-        m_identifier_case = eCaseInsensitive;
-        break;
-      case llvm::dwarf::DW_ID_case_sensitive:
-      default:
-        m_identifier_case = eCaseSensitive;
-        break;
+    case llvm::dwarf::DW_ID_up_case:
+      m_identifier_case = eUpperCase;
+      break;
+    case llvm::dwarf::DW_ID_down_case:
+      m_identifier_case = eLowerCase;
+      break;
+    case llvm::dwarf::DW_ID_case_insensitive:
+      m_identifier_case = eCaseInsensitive;
+      break;
+    case llvm::dwarf::DW_ID_case_sensitive:
+    default:
+      m_identifier_case = eCaseSensitive;
+      break;
     }
   }
 
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index 4c881d0ac41e8..9992a6666c3cc 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -162,7 +162,7 @@ void ManualDWARFIndex::IndexUnit(DWARFUnit &unit, SymbolFileDWARFDwo *dwp,
 
   // If at least one of the Compile Units is case sensitive, then all compile
   // units will be case sensitive
-  if(cu_identifier_case != eCaseSensitive)
+  if (cu_identifier_case != eCaseSensitive)
     SetNameCaseInsensitive();
   else
     SetStrictlyCaseSensitive();
@@ -665,14 +665,14 @@ void ManualDWARFIndex::SaveToCache() {
 }
 
 void ManualDWARFIndex::SetNameCaseInsensitive() {
-		m_set.function_basenames.SetNameCaseInsensitive();
-		m_set.function_fullnames.SetNameCaseInsensitive();
-		m_set.function_methods.SetNameCaseInsensitive();
-		m_set.function_selectors.SetNameCaseInsensitive();
-		m_set.objc_class_selectors.SetNameCaseInsensitive();
-		m_set.globals.SetNameCaseInsensitive();
-		m_set.types.SetNameCaseInsensitive();
-		m_set.namespaces.SetNameCaseInsensitive();
+  m_set.function_basenames.SetNameCaseInsensitive();
+  m_set.function_fullnames.SetNameCaseInsensitive();
+  m_set.function_methods.SetNameCaseInsensitive();
+  m_set.function_selectors.SetNameCaseInsensitive();
+  m_set.objc_class_selectors.SetNameCaseInsensitive();
+  m_set.globals.SetNameCaseInsensitive();
+  m_set.types.SetNameCaseInsensitive();
+  m_set.namespaces.SetNameCaseInsensitive();
 }
 
 void ManualDWARFIndex::SetStrictlyCaseSensitive() {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
index c85e1543fc921..37e551985a538 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h
@@ -169,7 +169,7 @@ class ManualDWARFIndex : public DWARFIndex {
   ///   True if this index is a partial index, false otherwise.
   bool IsPartial() const;
 
-	void SetNameCaseInsensitive();
+  void SetNameCaseInsensitive();
 
   void SetStrictlyCaseSensitive();
   /// The DWARF file which we are indexing.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
index fc62f726783d6..855676364a69f 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -35,15 +35,16 @@ void NameToDIE::Insert(ConstString name, const DIERef &die_ref) {
 bool NameToDIE::Find(
     ConstString name,
     llvm::function_ref<IterationAction(DIERef ref)> callback) const {
-  if(!NameCaseInsensitive){
+  if (!NameCaseInsensitive) {
     for (const auto &entry : m_map.equal_range(name))
       if (callback(entry.value) == IterationAction::Stop)
         return false;
     return true;
   }
-  
-  for (const auto &entry : m_map){
-    if(ConstString::Equals(ConstString(entry.cstring.GetCString()), name, false))
+
+  for (const auto &entry : m_map) {
+    if (ConstString::Equals(ConstString(entry.cstring.GetCString()), name,
+                            false))
       if (callback(entry.value) == IterationAction::Stop)
         return false;
   }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 881a009553df2..68294913de962 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -803,7 +803,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
           cu_sp->SetCasing(cu_casing);
 
           dwarf_cu.SetLLDBCompUnit(cu_sp.get());
-          
+
           SetCompileUnitAtIndex(dwarf_cu.GetID(), cu_sp);
         };
 
@@ -832,7 +832,8 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFCompileUnit &dwarf_cu) {
           if (support_files.GetSize() == 0)
             return false;
           initialize_cu(support_files.GetSupportFileAtIndex(0),
-                        eLanguageTypeUnknown, dwarf_cu.GetIdentifierCase(), std::move(support_files));
+                        eLanguageTypeUnknown, dwarf_cu.GetIdentifierCase(),
+                        std::move(support_files));
           return true;
         };
 
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index b358948bee093..374faaed043f9 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -291,20 +291,19 @@ lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref,
   lldb::VariableListSP variable_list;
   lldb::IdentifierCaseType identifier_case = lldb::eCaseSensitive;
 
-  if (symbol_context.comp_unit){
+  if (symbol_context.comp_unit) {
     variable_list = symbol_context.comp_unit->GetVariableList(true);
     identifier_case = symbol_context.comp_unit->GetCasing();
   }
-    
 
   name_ref.consume_front("::");
 
   std::string search_string;
-  if(identifier_case == lldb::eLowerCase)
+  if (identifier_case == lldb::eLowerCase)
     search_string = name_ref.lower();
-  else if(identifier_case == lldb::eUpperCase)
+  else if (identifier_case == lldb::eUpperCase)
     search_string = name_ref.upper();
-  else 
+  else
     search_string = name_ref.str();
 
   lldb::ValueObjectSP value_sp;
@@ -359,18 +358,19 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
     lldb::VariableListSP variable_list(
         stack_frame.GetInScopeVariableList(false));
 
-    SymbolContext sc = stack_frame.GetSymbolContext(lldb::eSymbolContextCompUnit);
+    SymbolContext sc =
+        stack_frame.GetSymbolContext(lldb::eSymbolContextCompUnit);
 
     lldb::IdentifierCaseType identifier_case = lldb::eCaseSensitive;
-    if(sc.comp_unit)
+    if (sc.comp_unit)
       identifier_case = sc.comp_unit->GetCasing();
 
     std::string search_string;
-    if(identifier_case == lldb::eLowerCase)
+    if (identifier_case == lldb::eLowerCase)
       search_string = name_ref.lower();
-    else if(identifier_case == lldb::eUpperCase)
+    else if (identifier_case == lldb::eUpperCase)
       search_string = name_ref.upper();
-    else 
+    else
       search_string = name_ref.str();
 
     lldb::ValueObjectSP value_sp;
@@ -386,8 +386,8 @@ lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
       return value_sp;
 
     // Try looking for an instance variable (class member).
-    sc = stack_frame.GetSymbolContext(
-        lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
+    sc = stack_frame.GetSymbolContext(lldb::eSymbolContextFunction |
+                                      lldb::eSymbolContextBlock);
     llvm::StringRef instance_name = sc.GetInstanceName();
     value_sp = stack_frame.FindVariable(ConstString(instance_name));
     if (value_sp)



More information about the lldb-commits mailing list