[Lldb-commits] [lldb] [lldb] Lookup static const members in FindGlobalVariables (PR #111859)

Ilia Kuklin via lldb-commits lldb-commits at lists.llvm.org
Thu Oct 24 11:08:57 PDT 2024


https://github.com/kuilpd updated https://github.com/llvm/llvm-project/pull/111859

>From 4c394ec162b58b3cde3af924a5e9be1de8250a07 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 30 Jul 2024 17:02:10 +0500
Subject: [PATCH 1/2] [lldb] Lookup static const members in FindGlobalVariables

Static const members initialized inside a class definition might not have a corresponding DW_TAG_variable (DWARF 4 and earlier), so they're not indexed by ManualDWARFIndex.

Add an additional lookup in FindGlobalVariables. Try looking up the enclosing type (e.g. foo::bar for foo::bar::A) and then searching for a static const member (A) within this type.
---
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      | 130 ++++++++++++++++++
 .../SymbolFile/DWARF/SymbolFileDWARF.h        |   3 +
 .../API/python_api/frame/globals/Makefile     |   4 +
 .../frame/globals/TestTargetGlobals.py        |  43 ++++++
 .../API/python_api/frame/globals/main.cpp     |  12 ++
 5 files changed, 192 insertions(+)
 create mode 100644 lldb/test/API/python_api/frame/globals/Makefile
 create mode 100644 lldb/test/API/python_api/frame/globals/TestTargetGlobals.py
 create mode 100644 lldb/test/API/python_api/frame/globals/main.cpp

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 9287d4baf19e9c..d53da79c1efcee 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2439,6 +2439,48 @@ void SymbolFileDWARF::FindGlobalVariables(
     return variables.GetSize() - original_size < max_matches;
   });
 
+  // If we don't have enough matches and the variable context is not empty, try
+  // to resolve the context as a type and look for static const members.
+  if (variables.GetSize() - original_size < max_matches && !context.empty()) {
+    llvm::StringRef type_name;
+    if (std::optional<Type::ParsedName> parsed_name =
+            Type::GetTypeScopeAndBasename(context))
+      type_name = parsed_name->basename;
+    else
+      type_name = context;
+
+    m_index->GetTypes(ConstString(type_name), [&](DWARFDIE parent) {
+      llvm::StringRef parent_type_name = parent.GetDWARFDeclContext()
+                                             .GetQualifiedNameAsConstString()
+                                             .GetStringRef();
+
+      // This type is from another scope, skip it.
+      if (!parent_type_name.ends_with(context))
+        return true;
+
+      auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(parent.GetCU());
+      if (!dwarf_cu)
+        return true;
+
+      sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu);
+
+      for (DWARFDIE die = parent.GetFirstChild(); die.IsValid();
+           die = die.GetSibling()) {
+        // Try parsing the entry as a static const member.
+        if (auto var_sp = ParseStaticConstMemberDIE(sc, die)) {
+          if (var_sp->GetUnqualifiedName().GetStringRef() != basename)
+            continue;
+
+          // There can be only one member with a given name.
+          variables.AddVariableIfUnique(var_sp);
+          break;
+        }
+      }
+
+      return variables.GetSize() - original_size < max_matches;
+    });
+  }
+
   // Return the number of variable that were appended to the list
   const uint32_t num_matches = variables.GetSize() - original_size;
   if (log && num_matches > 0) {
@@ -3371,6 +3413,94 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
   return 0;
 }
 
+VariableSP SymbolFileDWARF::ParseStaticConstMemberDIE(
+    const lldb_private::SymbolContext &sc, const DWARFDIE &die) {
+  if (die.GetDWARF() != this)
+    return die.GetDWARF()->ParseStaticConstMemberDIE(sc, die);
+
+  // Look only for members, ignore all other types of entries.
+  if (die.Tag() != DW_TAG_member)
+    return nullptr;
+
+  if (VariableSP var_sp = GetDIEToVariable()[die.GetDIE()])
+    return var_sp; // Already been parsed!
+
+  const char *name = nullptr;
+  const char *mangled = nullptr;
+  Declaration decl;
+  DWARFExpression location;
+  DWARFFormValue type_die_form;
+  DWARFFormValue const_value_form;
+
+  DWARFAttributes attributes = die.GetAttributes();
+  const size_t num_attributes = attributes.Size();
+
+  for (size_t i = 0; i < num_attributes; ++i) {
+    dw_attr_t attr = attributes.AttributeAtIndex(i);
+    DWARFFormValue form_value;
+
+    if (!attributes.ExtractFormValueAtIndex(i, form_value))
+      continue;
+
+    switch (attr) {
+    case DW_AT_decl_file:
+      decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
+          form_value.Unsigned()));
+      break;
+    case DW_AT_decl_line:
+      decl.SetLine(form_value.Unsigned());
+      break;
+    case DW_AT_decl_column:
+      decl.SetColumn(form_value.Unsigned());
+      break;
+    case DW_AT_name:
+      name = form_value.AsCString();
+      break;
+    case DW_AT_type:
+      type_die_form = form_value;
+      break;
+    case DW_AT_const_value:
+      const_value_form = form_value;
+      break;
+    default:
+      break;
+    }
+  }
+
+  // Look only for static const members with const values.
+  if (!DWARFFormValue::IsDataForm(const_value_form.Form()))
+    return nullptr;
+
+  SymbolFileTypeSP type_sp = std::make_shared<SymbolFileType>(
+      *this, type_die_form.Reference().GetID());
+
+  if (type_sp->GetType()) {
+    location.UpdateValue(const_value_form.Unsigned(),
+                         type_sp->GetType()->GetByteSize(nullptr).value_or(0),
+                         die.GetCU()->GetAddressByteSize());
+  }
+
+  if (Language::LanguageIsCPlusPlus(GetLanguage(*die.GetCU())))
+    mangled =
+        die.GetDWARFDeclContext().GetQualifiedNameAsConstString().GetCString();
+
+  ValueType scope = eValueTypeVariableGlobal;
+  Variable::RangeList scope_ranges;
+
+  DWARFExpressionList location_list(GetObjectFile()->GetModule(), location,
+                                    die.GetCU());
+  VariableSP var_sp = std::make_shared<Variable>(
+      die.GetID(), name, mangled, type_sp, scope, sc.comp_unit, scope_ranges,
+      &decl, location_list, /*is_external*/ true, /*is_artificial*/ false,
+      /*is_static_member*/ true);
+  var_sp->SetLocationIsConstantValueData(true);
+
+  // Cache this variable, so we don't parse it over and over again.
+  GetDIEToVariable()[die.GetDIE()] = var_sp;
+
+  return var_sp;
+}
+
 VariableSP SymbolFileDWARF::ParseVariableDIECached(const SymbolContext &sc,
                                                    const DWARFDIE &die) {
   if (!die)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 4967b37d753a09..380b5d4a289300 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -408,6 +408,9 @@ class SymbolFileDWARF : public SymbolFileCommon {
   bool ParseSupportFiles(DWARFUnit &dwarf_cu, const lldb::ModuleSP &module,
                          SupportFileList &support_files);
 
+  lldb::VariableSP ParseStaticConstMemberDIE(const SymbolContext &sc,
+                                             const DWARFDIE &die);
+
   lldb::VariableSP ParseVariableDIE(const SymbolContext &sc,
                                     const DWARFDIE &die,
                                     const lldb::addr_t func_low_pc);
diff --git a/lldb/test/API/python_api/frame/globals/Makefile b/lldb/test/API/python_api/frame/globals/Makefile
new file mode 100644
index 00000000000000..c24259ec8c9d93
--- /dev/null
+++ b/lldb/test/API/python_api/frame/globals/Makefile
@@ -0,0 +1,4 @@
+CXX_SOURCES := main.cpp
+CXXFLAGS_EXTRAS := -gdwarf-4
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/frame/globals/TestTargetGlobals.py b/lldb/test/API/python_api/frame/globals/TestTargetGlobals.py
new file mode 100644
index 00000000000000..54d2cd89560a1a
--- /dev/null
+++ b/lldb/test/API/python_api/frame/globals/TestTargetGlobals.py
@@ -0,0 +1,43 @@
+"""
+Test SBTarget::FindGlobalVariables API.
+"""
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+class TargetAPITestCase(TestBase):
+    mydir = TestBase.compute_mydir(__file__)
+
+    @add_test_categories(["pyapi"])
+    def test_find_global_variables(self):
+        """Exercise SBTarget.FindGlobalVariables() API."""
+        self.build()
+
+        # Don't need to launch a process, since we're only interested in
+        # looking up global variables.
+        target = self.dbg.CreateTarget(self.getBuildArtifact())
+
+        def test_global_var(query, name, type_name, value):
+            value_list = target.FindGlobalVariables(query, 1)
+            self.assertEqual(value_list.GetSize(), 1)
+            var = value_list.GetValueAtIndex(0)
+            self.DebugSBValue(var)
+            self.assertTrue(var)
+            self.assertEqual(var.GetName(), name)
+            self.assertEqual(var.GetTypeName(), type_name)
+            self.assertEqual(var.GetValue(), value)
+
+        test_global_var("Vars::inline_static", "Vars::inline_static", "double", "1.5")
+        test_global_var(
+            "Vars::static_constexpr", "Vars::static_constexpr", "const int", "2"
+        )
+        test_global_var(
+            "Vars::static_const_out_out_class",
+            "Vars::static_const_out_out_class",
+            "const int",
+            "3",
+        )
+        test_global_var(
+            "global_var_of_char_type", "::global_var_of_char_type", "char", "'X'"
+        )
\ No newline at end of file
diff --git a/lldb/test/API/python_api/frame/globals/main.cpp b/lldb/test/API/python_api/frame/globals/main.cpp
new file mode 100644
index 00000000000000..e2095e80082677
--- /dev/null
+++ b/lldb/test/API/python_api/frame/globals/main.cpp
@@ -0,0 +1,12 @@
+class Vars {
+public:
+  inline static double inline_static = 1.5;
+  static constexpr int static_constexpr = 2;
+  static const int static_const_out_out_class;
+};
+
+const int Vars::static_const_out_out_class = 3;
+
+char global_var_of_char_type = 'X';
+
+int main() {}

>From 8f7c944be19963362e7e46019b37f7222744195b Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Thu, 24 Oct 2024 23:06:54 +0500
Subject: [PATCH 2/2] Implemented manual indexing of DW_TAG_member in DWARF 4,
 combined the test with TestConstStaticIntegralMember.

---
 .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp  |   2 +-
 .../SymbolFile/DWARF/ManualDWARFIndex.cpp     |  24 ++++
 .../SymbolFile/DWARF/SymbolFileDWARF.cpp      | 136 +-----------------
 .../TestConstStaticIntegralMember.py          |  35 +++--
 .../cpp/const_static_integral_member/main.cpp |   1 +
 5 files changed, 54 insertions(+), 144 deletions(-)

diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index 66d0bc4b90cb52..c0a2066f8239e5 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -614,7 +614,7 @@ DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const {
 }
 
 bool DWARFDebugInfoEntry::IsGlobalOrStaticScopeVariable() const {
-  if (Tag() != DW_TAG_variable)
+  if (Tag() != DW_TAG_variable && Tag() != DW_TAG_member)
     return false;
   const DWARFDebugInfoEntry *parent_die = GetParent();
   while (parent_die != nullptr) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
index 887983de2e8516..dabaf34237617d 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
@@ -219,6 +219,7 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
     case DW_TAG_typedef:
     case DW_TAG_union_type:
     case DW_TAG_unspecified_type:
+    case DW_TAG_member:
     case DW_TAG_variable:
       break;
 
@@ -228,6 +229,7 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
 
     const char *name = nullptr;
     const char *mangled_cstr = nullptr;
+    bool is_external = false;
     bool is_declaration = false;
     bool has_address = false;
     bool has_location_or_const_value = false;
@@ -246,6 +248,11 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
           name = form_value.AsCString();
         break;
 
+      case DW_AT_external:
+        if (attributes.ExtractFormValueAtIndex(i, form_value))
+          is_external = form_value.Unsigned() != 0;
+        break;
+
       case DW_AT_declaration:
         if (attributes.ExtractFormValueAtIndex(i, form_value))
           is_declaration = form_value.Unsigned() != 0;
@@ -362,6 +369,23 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
         set.namespaces.Insert(ConstString(name), ref);
       break;
 
+    case DW_TAG_member: {
+      // In DWARF 4 and earlier `static const` members of a struct, a class or a
+      // union have an entry tag `DW_TAG_member`, and are also tagged as
+      // `DW_AT_external` and `DW_AT_declaration`, but otherwise follow the
+      // same rules as `DW_TAG_variable`.
+      if (unit.GetVersion() >= 5)
+        break;
+      bool parent_is_class_type = false;
+      if (auto parent = die.GetParent()) {
+        parent_is_class_type = parent->Tag() == DW_TAG_structure_type ||
+                               parent->Tag() == DW_TAG_class_type ||
+                               parent->Tag() == DW_TAG_union_type;
+      }
+      if (!parent_is_class_type || !is_external || !is_declaration)
+        break;
+      [[fallthrough]];
+    }
     case DW_TAG_variable:
       if (name && has_location_or_const_value && is_global_or_static_variable) {
         set.globals.Insert(ConstString(name), ref);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index d53da79c1efcee..e8f9896a2dc8db 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2402,7 +2402,7 @@ void SymbolFileDWARF::FindGlobalVariables(
       sc.module_sp = m_objfile_sp->GetModule();
     assert(sc.module_sp);
 
-    if (die.Tag() != DW_TAG_variable)
+    if (die.Tag() != DW_TAG_variable && die.Tag() != DW_TAG_member)
       return true;
 
     auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU());
@@ -2439,48 +2439,6 @@ void SymbolFileDWARF::FindGlobalVariables(
     return variables.GetSize() - original_size < max_matches;
   });
 
-  // If we don't have enough matches and the variable context is not empty, try
-  // to resolve the context as a type and look for static const members.
-  if (variables.GetSize() - original_size < max_matches && !context.empty()) {
-    llvm::StringRef type_name;
-    if (std::optional<Type::ParsedName> parsed_name =
-            Type::GetTypeScopeAndBasename(context))
-      type_name = parsed_name->basename;
-    else
-      type_name = context;
-
-    m_index->GetTypes(ConstString(type_name), [&](DWARFDIE parent) {
-      llvm::StringRef parent_type_name = parent.GetDWARFDeclContext()
-                                             .GetQualifiedNameAsConstString()
-                                             .GetStringRef();
-
-      // This type is from another scope, skip it.
-      if (!parent_type_name.ends_with(context))
-        return true;
-
-      auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(parent.GetCU());
-      if (!dwarf_cu)
-        return true;
-
-      sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu);
-
-      for (DWARFDIE die = parent.GetFirstChild(); die.IsValid();
-           die = die.GetSibling()) {
-        // Try parsing the entry as a static const member.
-        if (auto var_sp = ParseStaticConstMemberDIE(sc, die)) {
-          if (var_sp->GetUnqualifiedName().GetStringRef() != basename)
-            continue;
-
-          // There can be only one member with a given name.
-          variables.AddVariableIfUnique(var_sp);
-          break;
-        }
-      }
-
-      return variables.GetSize() - original_size < max_matches;
-    });
-  }
-
   // Return the number of variable that were appended to the list
   const uint32_t num_matches = variables.GetSize() - original_size;
   if (log && num_matches > 0) {
@@ -3413,94 +3371,6 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
   return 0;
 }
 
-VariableSP SymbolFileDWARF::ParseStaticConstMemberDIE(
-    const lldb_private::SymbolContext &sc, const DWARFDIE &die) {
-  if (die.GetDWARF() != this)
-    return die.GetDWARF()->ParseStaticConstMemberDIE(sc, die);
-
-  // Look only for members, ignore all other types of entries.
-  if (die.Tag() != DW_TAG_member)
-    return nullptr;
-
-  if (VariableSP var_sp = GetDIEToVariable()[die.GetDIE()])
-    return var_sp; // Already been parsed!
-
-  const char *name = nullptr;
-  const char *mangled = nullptr;
-  Declaration decl;
-  DWARFExpression location;
-  DWARFFormValue type_die_form;
-  DWARFFormValue const_value_form;
-
-  DWARFAttributes attributes = die.GetAttributes();
-  const size_t num_attributes = attributes.Size();
-
-  for (size_t i = 0; i < num_attributes; ++i) {
-    dw_attr_t attr = attributes.AttributeAtIndex(i);
-    DWARFFormValue form_value;
-
-    if (!attributes.ExtractFormValueAtIndex(i, form_value))
-      continue;
-
-    switch (attr) {
-    case DW_AT_decl_file:
-      decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
-          form_value.Unsigned()));
-      break;
-    case DW_AT_decl_line:
-      decl.SetLine(form_value.Unsigned());
-      break;
-    case DW_AT_decl_column:
-      decl.SetColumn(form_value.Unsigned());
-      break;
-    case DW_AT_name:
-      name = form_value.AsCString();
-      break;
-    case DW_AT_type:
-      type_die_form = form_value;
-      break;
-    case DW_AT_const_value:
-      const_value_form = form_value;
-      break;
-    default:
-      break;
-    }
-  }
-
-  // Look only for static const members with const values.
-  if (!DWARFFormValue::IsDataForm(const_value_form.Form()))
-    return nullptr;
-
-  SymbolFileTypeSP type_sp = std::make_shared<SymbolFileType>(
-      *this, type_die_form.Reference().GetID());
-
-  if (type_sp->GetType()) {
-    location.UpdateValue(const_value_form.Unsigned(),
-                         type_sp->GetType()->GetByteSize(nullptr).value_or(0),
-                         die.GetCU()->GetAddressByteSize());
-  }
-
-  if (Language::LanguageIsCPlusPlus(GetLanguage(*die.GetCU())))
-    mangled =
-        die.GetDWARFDeclContext().GetQualifiedNameAsConstString().GetCString();
-
-  ValueType scope = eValueTypeVariableGlobal;
-  Variable::RangeList scope_ranges;
-
-  DWARFExpressionList location_list(GetObjectFile()->GetModule(), location,
-                                    die.GetCU());
-  VariableSP var_sp = std::make_shared<Variable>(
-      die.GetID(), name, mangled, type_sp, scope, sc.comp_unit, scope_ranges,
-      &decl, location_list, /*is_external*/ true, /*is_artificial*/ false,
-      /*is_static_member*/ true);
-  var_sp->SetLocationIsConstantValueData(true);
-
-  // Cache this variable, so we don't parse it over and over again.
-  GetDIEToVariable()[die.GetDIE()] = var_sp;
-
-  return var_sp;
-}
-
 VariableSP SymbolFileDWARF::ParseVariableDIECached(const SymbolContext &sc,
                                                    const DWARFDIE &die) {
   if (!die)
@@ -3620,7 +3490,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
   ModuleSP module = GetObjectFile()->GetModule();
 
   if (tag != DW_TAG_variable && tag != DW_TAG_constant &&
-      (tag != DW_TAG_formal_parameter || !sc.function))
+      tag != DW_TAG_member && (tag != DW_TAG_formal_parameter || !sc.function))
     return nullptr;
 
   DWARFAttributes attributes = die.GetAttributes();
@@ -3926,7 +3796,7 @@ void SymbolFileDWARF::ParseAndAppendGlobalVariable(
     return;
 
   dw_tag_t tag = die.Tag();
-  if (tag != DW_TAG_variable && tag != DW_TAG_constant)
+  if (tag != DW_TAG_variable && tag != DW_TAG_constant && tag != DW_TAG_member)
     return;
 
   // Check to see if we have already parsed this variable or constant?
diff --git a/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py b/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py
index cdade2d335df0b..e3d004b38a1571 100644
--- a/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py
+++ b/lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py
@@ -120,17 +120,15 @@ def check_global_var(self, name: str, expect_type, expect_val):
         self.assertEqual(varobj.type.name, expect_type)
         self.assertEqual(varobj.value, expect_val)
 
-    @expectedFailureAll(dwarf_version=["<", "5"])
-    # On linux this passes due to the manual index
-    @expectedFailureDarwin(debug_info=no_match(["dsym"]))
-    def test_inline_static_members(self):
-        self.build()
+    def check_inline_static_members(self, flags):
+        self.build(dictionary={"CXXFLAGS_EXTRAS": flags})
         lldbutil.run_to_source_breakpoint(
             self, "// break here", lldb.SBFileSpec("main.cpp")
         )
 
         self.check_global_var("A::int_val", "const int", "1")
         self.check_global_var("A::int_val_with_address", "const int", "2")
+        self.check_global_var("A::inline_int_val", "const int", "3")
         self.check_global_var("A::bool_val", "const bool", "true")
         self.check_global_var("A::enum_val", "Enum", "enum_case2")
         self.check_global_var("A::enum_bool_val", "EnumBool", "enum_bool_case1")
@@ -144,6 +142,16 @@ def test_inline_static_members(self):
             "ClassWithConstexprs::scoped_enum_val", "ScopedEnum", "scoped_enum_case2"
         )
 
+    # On linux this passes due to the manual index
+    @expectedFailureDarwin(debug_info=no_match(["dsym"]))
+    def test_inline_static_members_dwarf5(self):
+        self.check_inline_static_members("-gdwarf-5")
+
+    # On linux this passes due to the manual index
+    @expectedFailureDarwin(debug_info=no_match(["dsym"]))
+    def test_inline_static_members_dwarf4(self):
+        self.check_inline_static_members("-gdwarf-4")
+
     # With older versions of Clang, LLDB fails to evaluate classes with only
     # constexpr members when dsymutil is enabled
     @expectedFailureAll(
@@ -170,15 +178,12 @@ def test_class_with_only_constexpr_static(self):
             "ClassWithEnumAlias::enum_alias_alias", result_value="scoped_enum_case1"
         )
 
-    @expectedFailureAll(dwarf_version=["<", "5"])
-    # On linux this passes due to the manual index
-    @expectedFailureDarwin(debug_info=no_match(["dsym"]))
-    def test_shadowed_static_inline_members(self):
+    def check_shadowed_static_inline_members(self, flags):
         """Tests that the expression evaluator and SBAPI can both
         correctly determine the requested inline static variable
         in the presence of multiple variables of the same name."""
 
-        self.build()
+        self.build(dictionary={"CXXFLAGS_EXTRAS": flags})
         lldbutil.run_to_name_breakpoint(self, "bar")
 
         self.check_global_var("ns::Foo::mem", "const int", "10")
@@ -188,6 +193,16 @@ def test_shadowed_static_inline_members(self):
         self.expect_expr("ns::Foo::mem", result_value="10")
         self.expect_expr("::Foo::mem", result_value="-29")
 
+    # On linux this passes due to the manual index
+    @expectedFailureDarwin(debug_info=no_match(["dsym"]))
+    def test_shadowed_static_inline_members_dwarf5(self):
+        self.check_shadowed_static_inline_members("-gdwarf-5")
+
+    # On linux this passes due to the manual index
+    @expectedFailureDarwin(debug_info=no_match(["dsym"]))
+    def test_shadowed_static_inline_members_dwarf4(self):
+        self.check_shadowed_static_inline_members("-gdwarf-4")
+
     @expectedFailureAll(bugnumber="target var doesn't honour global namespace")
     def test_shadowed_static_inline_members_xfail(self):
         self.build()
diff --git a/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp b/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp
index fb0b49e2d7aad7..564a3643dd8fcd 100644
--- a/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp
+++ b/lldb/test/API/lang/cpp/const_static_integral_member/main.cpp
@@ -29,6 +29,7 @@ enum class ScopedLongLongEnum : long long {
 struct A {
   const static int int_val = 1;
   const static int int_val_with_address = 2;
+  inline const static int inline_int_val = 3;
   const static bool bool_val = true;
 
   const static auto char_max = std::numeric_limits<char>::max();



More information about the lldb-commits mailing list