[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> ¶meters)
+ : 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> ¶meters) {
+ 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> ¶meters);
+
// 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> ¶meters) {
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> ¶meters)
+ : 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> ¶meters)
- : 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> ¶meters)
- : 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 ¶m : 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> ¶meters) {
- 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