[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
Fri Jul 31 10:50:20 PDT 2026


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

This patch adds support for case-insensitive lookups. Whether the lookups should be case-sensitive or case-insensitive is determined by DW_AT_identifier_case. If this attribute is not present, then the compile unit is considered case-sensitive.

Changes:
 - Added an identifier case field to the compile unit.
- DIL now looks at casing when looking up identifiers and handles them appropriately.
- DWARFUnit now parses DW_AT_identifier_case when asked.
- NameToDIE now looks at casing and searches for identifiers appropriately.

Part of the "Add Fortran support to LLDB" GSoC 2026 project.

>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 1/3] [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 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 2/3] [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 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 3/3] [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



More information about the lldb-commits mailing list