Skip to content

[lldb] Don't recursively load types of static member variables in the… #2971

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2533,7 +2533,7 @@ void DWARFASTParserClang::ParseSingleMember(
if (accessibility == eAccessNone)
accessibility = eAccessPublic;
TypeSystemClang::AddVariableToRecordType(
class_clang_type, name, var_type->GetLayoutCompilerType(),
class_clang_type, name, var_type->GetForwardCompilerType(),
accessibility);
}
return;
Expand Down
4 changes: 4 additions & 0 deletions lldb/test/API/functionalities/lazy-loading/TestLazyLoading.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def setUp(self):
class_in_namespace_decl = [class_decl_kind, "ClassInNamespace"]
class_we_enter_decl = [class_decl_kind, "ClassWeEnter"]
class_member_decl = [struct_decl_kind, "ClassMember"]
class_static_member_decl = [struct_decl_kind, "StaticClassMember"]
unused_class_member_decl = [struct_decl_kind, "UnusedClassMember"]
unused_class_member_ptr_decl = [struct_decl_kind, "UnusedClassMemberPtr"]

Expand All @@ -56,6 +57,7 @@ def assert_no_decls_loaded(self):
self.assert_decl_not_loaded(self.other_struct_decl)
self.assert_decl_not_loaded(self.class_in_namespace_decl)
self.assert_decl_not_loaded(self.class_member_decl)
self.assert_decl_not_loaded(self.class_static_member_decl)
self.assert_decl_not_loaded(self.unused_class_member_decl)

def get_ast_dump(self):
Expand Down Expand Up @@ -228,6 +230,8 @@ def test_class_function_access_member(self):
self.assert_decl_not_completed(self.unused_class_member_ptr_decl)
# We loaded the member we used.
self.assert_decl_loaded(self.class_member_decl)
# We didn't load the type of the unused static member.
self.assert_decl_not_completed(self.class_static_member_decl)

# This should not have loaded anything else.
self.assert_decl_not_loaded(self.other_struct_decl)
Expand Down
3 changes: 3 additions & 0 deletions lldb/test/API/functionalities/lazy-loading/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct OtherStruct {
// Class loading declarations.

struct ClassMember { int i; };
struct StaticClassMember { int i; };
struct UnusedClassMember { int i; };
struct UnusedClassMemberPtr { int i; };

Expand All @@ -34,12 +35,14 @@ class ClassWeEnter {
public:
int dummy; // Prevent bug where LLDB always completes first member.
ClassMember member;
static StaticClassMember static_member;
UnusedClassMember unused_member;
UnusedClassMemberPtr *unused_member_ptr;
int enteredFunction() {
return member.i; // Location: class function
}
};
StaticClassMember ClassWeEnter::static_member;
};

//----------------------------------------------------------------------------//
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CXX_SOURCES := main.cpp

include Makefile.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil

class TestCase(TestBase):

mydir = TestBase.compute_mydir(__file__)

@no_debug_info_test
def test(self):
"""
This tests a static member with a type which size depends on the
surrounding class. LLDB should *not* try to generate the record layout
for those types while parsing the members from debug info.
"""
self.build()
self.dbg.CreateTarget(self.getBuildArtifact("a.out"))

# Force the record layout for 'ToLayout' to be generated by printing
# a value of it's type.
self.expect("target variable test_var")
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// This class just serves as an indirection between LLDB and Clang. LLDB might
// be tempted to check the member type of DependsOnParam2 for whether it's
// in some 'currently-loading' state before trying to produce the record layout.
// By inheriting from ToLayout this will make LLDB just check if
// DependsOnParam1 is currently being loaded (which it's not) but it will
template <typename ToLayoutParam> struct DependsOnParam1 : ToLayoutParam {};
// This class forces the memory layout of it's type parameter to be created.
template <typename ToLayoutParam> struct DependsOnParam2 {
DependsOnParam1<ToLayoutParam> m;
};

// This is the class that LLDB has to generate the record layout for.
struct ToLayout {
// A static member variable which memory layout depends on the surrounding
// class. This comes first so that if we accidentially generate the layout
// for static member types we end up recursively going back to 'ToLayout'
// before 'some_member' has been loaded.
static DependsOnParam2<ToLayout> a_static_member;
// Some dummy member variable. This is only there so that Clang can detect
// that the record layout is inconsistent (i.e., the number of fields in the
// layout doesn't fit to the fields in the declaration).
int some_member;
};
DependsOnParam2<ToLayout> ToLayout::a_static_member;

ToLayout test_var;

int main() { return test_var.some_member; }