Skip to content

Commit 1361c19

Browse files
authored
[lldb] Index static const members of classes, structs and unions as global variables in DWARF 4 and earlier (#111859)
In DWARF 4 and earlier `static const` members of structs, classes and unions have an entry tag `DW_TAG_member`, and are also tagged as `DW_AT_declaration`, but otherwise follow the same rules as `DW_TAG_variable`.
1 parent 0c0d7a6 commit 1361c19

File tree

5 files changed

+49
-14
lines changed

5 files changed

+49
-14
lines changed

lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const {
614614
}
615615

616616
bool DWARFDebugInfoEntry::IsGlobalOrStaticScopeVariable() const {
617-
if (Tag() != DW_TAG_variable)
617+
if (Tag() != DW_TAG_variable && Tag() != DW_TAG_member)
618618
return false;
619619
const DWARFDebugInfoEntry *parent_die = GetParent();
620620
while (parent_die != nullptr) {

lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,13 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
222222
case DW_TAG_variable:
223223
break;
224224

225+
case DW_TAG_member:
226+
// Only in DWARF 4 and earlier `static const` members of a struct, a class
227+
// or a union have an entry tag `DW_TAG_member`
228+
if (unit.GetVersion() >= 5)
229+
continue;
230+
break;
231+
225232
default:
226233
continue;
227234
}
@@ -362,6 +369,18 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit,
362369
set.namespaces.Insert(ConstString(name), ref);
363370
break;
364371

372+
case DW_TAG_member: {
373+
// In DWARF 4 and earlier `static const` members of a struct, a class or a
374+
// union have an entry tag `DW_TAG_member`, and are also tagged as
375+
// `DW_AT_declaration`, but otherwise follow the same rules as
376+
// `DW_TAG_variable`.
377+
bool parent_is_class_type = false;
378+
if (auto parent = die.GetParent())
379+
parent_is_class_type = DWARFDIE(&unit, parent).IsStructUnionOrClass();
380+
if (!parent_is_class_type || !is_declaration)
381+
break;
382+
[[fallthrough]];
383+
}
365384
case DW_TAG_variable:
366385
if (name && has_location_or_const_value && is_global_or_static_variable) {
367386
set.globals.Insert(ConstString(name), ref);

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2403,7 +2403,7 @@ void SymbolFileDWARF::FindGlobalVariables(
24032403
sc.module_sp = m_objfile_sp->GetModule();
24042404
assert(sc.module_sp);
24052405

2406-
if (die.Tag() != DW_TAG_variable)
2406+
if (die.Tag() != DW_TAG_variable && die.Tag() != DW_TAG_member)
24072407
return true;
24082408

24092409
auto *dwarf_cu = llvm::dyn_cast<DWARFCompileUnit>(die.GetCU());
@@ -3505,7 +3505,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
35053505
ModuleSP module = GetObjectFile()->GetModule();
35063506

35073507
if (tag != DW_TAG_variable && tag != DW_TAG_constant &&
3508-
(tag != DW_TAG_formal_parameter || !sc.function))
3508+
tag != DW_TAG_member && (tag != DW_TAG_formal_parameter || !sc.function))
35093509
return nullptr;
35103510

35113511
DWARFAttributes attributes = die.GetAttributes();
@@ -3811,7 +3811,7 @@ void SymbolFileDWARF::ParseAndAppendGlobalVariable(
38113811
return;
38123812

38133813
dw_tag_t tag = die.Tag();
3814-
if (tag != DW_TAG_variable && tag != DW_TAG_constant)
3814+
if (tag != DW_TAG_variable && tag != DW_TAG_constant && tag != DW_TAG_member)
38153815
return;
38163816

38173817
// Check to see if we have already parsed this variable or constant?

lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,15 @@ def check_global_var(self, name: str, expect_type, expect_val):
120120
self.assertEqual(varobj.type.name, expect_type)
121121
self.assertEqual(varobj.value, expect_val)
122122

123-
@expectedFailureAll(dwarf_version=["<", "5"])
124-
# On linux this passes due to the manual index
125-
@expectedFailureDarwin(debug_info=no_match(["dsym"]))
126-
def test_inline_static_members(self):
127-
self.build()
123+
def check_inline_static_members(self, flags):
124+
self.build(dictionary={"CXXFLAGS_EXTRAS": flags})
128125
lldbutil.run_to_source_breakpoint(
129126
self, "// break here", lldb.SBFileSpec("main.cpp")
130127
)
131128

132129
self.check_global_var("A::int_val", "const int", "1")
133130
self.check_global_var("A::int_val_with_address", "const int", "2")
131+
self.check_global_var("A::inline_int_val", "const int", "3")
134132
self.check_global_var("A::bool_val", "const bool", "true")
135133
self.check_global_var("A::enum_val", "Enum", "enum_case2")
136134
self.check_global_var("A::enum_bool_val", "EnumBool", "enum_bool_case1")
@@ -144,6 +142,16 @@ def test_inline_static_members(self):
144142
"ClassWithConstexprs::scoped_enum_val", "ScopedEnum", "scoped_enum_case2"
145143
)
146144

145+
# On linux this passes due to the manual index
146+
@expectedFailureDarwin(debug_info=no_match(["dsym"]))
147+
def test_inline_static_members_dwarf5(self):
148+
self.check_inline_static_members("-gdwarf-5")
149+
150+
# On linux this passes due to the manual index
151+
@expectedFailureDarwin(debug_info=no_match(["dsym"]))
152+
def test_inline_static_members_dwarf4(self):
153+
self.check_inline_static_members("-gdwarf-4")
154+
147155
# With older versions of Clang, LLDB fails to evaluate classes with only
148156
# constexpr members when dsymutil is enabled
149157
@expectedFailureAll(
@@ -170,15 +178,12 @@ def test_class_with_only_constexpr_static(self):
170178
"ClassWithEnumAlias::enum_alias_alias", result_value="scoped_enum_case1"
171179
)
172180

173-
@expectedFailureAll(dwarf_version=["<", "5"])
174-
# On linux this passes due to the manual index
175-
@expectedFailureDarwin(debug_info=no_match(["dsym"]))
176-
def test_shadowed_static_inline_members(self):
181+
def check_shadowed_static_inline_members(self, flags):
177182
"""Tests that the expression evaluator and SBAPI can both
178183
correctly determine the requested inline static variable
179184
in the presence of multiple variables of the same name."""
180185

181-
self.build()
186+
self.build(dictionary={"CXXFLAGS_EXTRAS": flags})
182187
lldbutil.run_to_name_breakpoint(self, "bar")
183188

184189
self.check_global_var("ns::Foo::mem", "const int", "10")
@@ -188,6 +193,16 @@ def test_shadowed_static_inline_members(self):
188193
self.expect_expr("ns::Foo::mem", result_value="10")
189194
self.expect_expr("::Foo::mem", result_value="-29")
190195

196+
# On linux this passes due to the manual index
197+
@expectedFailureDarwin(debug_info=no_match(["dsym"]))
198+
def test_shadowed_static_inline_members_dwarf5(self):
199+
self.check_shadowed_static_inline_members("-gdwarf-5")
200+
201+
# On linux this passes due to the manual index
202+
@expectedFailureDarwin(debug_info=no_match(["dsym"]))
203+
def test_shadowed_static_inline_members_dwarf4(self):
204+
self.check_shadowed_static_inline_members("-gdwarf-4")
205+
191206
@expectedFailureAll(bugnumber="target var doesn't honour global namespace")
192207
def test_shadowed_static_inline_members_xfail(self):
193208
self.build()

lldb/test/API/lang/cpp/const_static_integral_member/main.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ enum class ScopedLongLongEnum : long long {
2929
struct A {
3030
const static int int_val = 1;
3131
const static int int_val_with_address = 2;
32+
inline const static int inline_int_val = 3;
3233
const static bool bool_val = true;
3334

3435
const static auto char_max = std::numeric_limits<char>::max();

0 commit comments

Comments
 (0)