Skip to content

Commit ab6d133

Browse files
authored
Merge pull request #2971 from Teemperor/cherry/34c697c85e9d
[lldb] Don't recursively load types of static member variables in the…
2 parents 100dcf4 + 03bcfb4 commit ab6d133

File tree

6 files changed

+61
-1
lines changed

6 files changed

+61
-1
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2533,7 +2533,7 @@ void DWARFASTParserClang::ParseSingleMember(
25332533
if (accessibility == eAccessNone)
25342534
accessibility = eAccessPublic;
25352535
TypeSystemClang::AddVariableToRecordType(
2536-
class_clang_type, name, var_type->GetLayoutCompilerType(),
2536+
class_clang_type, name, var_type->GetForwardCompilerType(),
25372537
accessibility);
25382538
}
25392539
return;

lldb/test/API/functionalities/lazy-loading/TestLazyLoading.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def setUp(self):
4040
class_in_namespace_decl = [class_decl_kind, "ClassInNamespace"]
4141
class_we_enter_decl = [class_decl_kind, "ClassWeEnter"]
4242
class_member_decl = [struct_decl_kind, "ClassMember"]
43+
class_static_member_decl = [struct_decl_kind, "StaticClassMember"]
4344
unused_class_member_decl = [struct_decl_kind, "UnusedClassMember"]
4445
unused_class_member_ptr_decl = [struct_decl_kind, "UnusedClassMemberPtr"]
4546

@@ -56,6 +57,7 @@ def assert_no_decls_loaded(self):
5657
self.assert_decl_not_loaded(self.other_struct_decl)
5758
self.assert_decl_not_loaded(self.class_in_namespace_decl)
5859
self.assert_decl_not_loaded(self.class_member_decl)
60+
self.assert_decl_not_loaded(self.class_static_member_decl)
5961
self.assert_decl_not_loaded(self.unused_class_member_decl)
6062

6163
def get_ast_dump(self):
@@ -228,6 +230,8 @@ def test_class_function_access_member(self):
228230
self.assert_decl_not_completed(self.unused_class_member_ptr_decl)
229231
# We loaded the member we used.
230232
self.assert_decl_loaded(self.class_member_decl)
233+
# We didn't load the type of the unused static member.
234+
self.assert_decl_not_completed(self.class_static_member_decl)
231235

232236
# This should not have loaded anything else.
233237
self.assert_decl_not_loaded(self.other_struct_decl)

lldb/test/API/functionalities/lazy-loading/main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct OtherStruct {
2323
// Class loading declarations.
2424

2525
struct ClassMember { int i; };
26+
struct StaticClassMember { int i; };
2627
struct UnusedClassMember { int i; };
2728
struct UnusedClassMemberPtr { int i; };
2829

@@ -34,12 +35,14 @@ class ClassWeEnter {
3435
public:
3536
int dummy; // Prevent bug where LLDB always completes first member.
3637
ClassMember member;
38+
static StaticClassMember static_member;
3739
UnusedClassMember unused_member;
3840
UnusedClassMemberPtr *unused_member_ptr;
3941
int enteredFunction() {
4042
return member.i; // Location: class function
4143
}
4244
};
45+
StaticClassMember ClassWeEnter::static_member;
4346
};
4447

4548
//----------------------------------------------------------------------------//
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CXX_SOURCES := main.cpp
2+
3+
include Makefile.rules
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
from lldbsuite.test.lldbtest import *
4+
from lldbsuite.test import lldbutil
5+
6+
class TestCase(TestBase):
7+
8+
mydir = TestBase.compute_mydir(__file__)
9+
10+
@no_debug_info_test
11+
def test(self):
12+
"""
13+
This tests a static member with a type which size depends on the
14+
surrounding class. LLDB should *not* try to generate the record layout
15+
for those types while parsing the members from debug info.
16+
"""
17+
self.build()
18+
self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
19+
20+
# Force the record layout for 'ToLayout' to be generated by printing
21+
# a value of it's type.
22+
self.expect("target variable test_var")
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// This class just serves as an indirection between LLDB and Clang. LLDB might
2+
// be tempted to check the member type of DependsOnParam2 for whether it's
3+
// in some 'currently-loading' state before trying to produce the record layout.
4+
// By inheriting from ToLayout this will make LLDB just check if
5+
// DependsOnParam1 is currently being loaded (which it's not) but it will
6+
template <typename ToLayoutParam> struct DependsOnParam1 : ToLayoutParam {};
7+
// This class forces the memory layout of it's type parameter to be created.
8+
template <typename ToLayoutParam> struct DependsOnParam2 {
9+
DependsOnParam1<ToLayoutParam> m;
10+
};
11+
12+
// This is the class that LLDB has to generate the record layout for.
13+
struct ToLayout {
14+
// A static member variable which memory layout depends on the surrounding
15+
// class. This comes first so that if we accidentially generate the layout
16+
// for static member types we end up recursively going back to 'ToLayout'
17+
// before 'some_member' has been loaded.
18+
static DependsOnParam2<ToLayout> a_static_member;
19+
// Some dummy member variable. This is only there so that Clang can detect
20+
// that the record layout is inconsistent (i.e., the number of fields in the
21+
// layout doesn't fit to the fields in the declaration).
22+
int some_member;
23+
};
24+
DependsOnParam2<ToLayout> ToLayout::a_static_member;
25+
26+
ToLayout test_var;
27+
28+
int main() { return test_var.some_member; }

0 commit comments

Comments
 (0)