1 from lldbsuite
.test
.decorators
import *
2 from lldbsuite
.test
.lldbtest
import *
3 from lldbsuite
.test
import lldbutil
6 This test ensures that we only create Clang AST nodes in our module AST
7 when we actually need them.
9 All tests in this file behave like this:
10 1. Use LLDB to do something (expression evaluation, breakpoint setting, etc.).
11 2. Check that certain Clang AST nodes were not loaded during the previous
16 class TestCase(TestBase
):
17 NO_DEBUG_INFO_TESTCASE
= True
21 # Only build this test once.
24 # Clang declaration kind we are looking for.
25 class_decl_kind
= "CXXRecordDecl"
26 # FIXME: This shouldn't be a CXXRecordDecl, but that's how we model
28 struct_decl_kind
= "CXXRecordDecl"
30 # The decls we use in this program in the format that
31 # decl_in_line and decl_completed_in_line expect (which is a pair of
32 # node type and the unqualified declaration name.
33 struct_first_member_decl
= [struct_decl_kind
, "StructFirstMember"]
34 struct_behind_ptr_decl
= [struct_decl_kind
, "StructBehindPointer"]
35 struct_behind_ref_decl
= [struct_decl_kind
, "StructBehindRef"]
36 struct_member_decl
= [struct_decl_kind
, "StructMember"]
37 some_struct_decl
= [struct_decl_kind
, "SomeStruct"]
38 other_struct_decl
= [struct_decl_kind
, "OtherStruct"]
39 class_in_namespace_decl
= [class_decl_kind
, "ClassInNamespace"]
40 class_we_enter_decl
= [class_decl_kind
, "ClassWeEnter"]
41 class_member_decl
= [struct_decl_kind
, "ClassMember"]
42 class_static_member_decl
= [struct_decl_kind
, "StaticClassMember"]
43 unused_class_member_decl
= [struct_decl_kind
, "UnusedClassMember"]
44 unused_class_member_ptr_decl
= [struct_decl_kind
, "UnusedClassMemberPtr"]
46 def assert_no_decls_loaded(self
):
48 Asserts that no known declarations in this test are loaded
49 into the module's AST.
51 self
.assert_decl_not_loaded(self
.struct_first_member_decl
)
52 self
.assert_decl_not_loaded(self
.struct_behind_ptr_decl
)
53 self
.assert_decl_not_loaded(self
.struct_behind_ref_decl
)
54 self
.assert_decl_not_loaded(self
.struct_member_decl
)
55 self
.assert_decl_not_loaded(self
.some_struct_decl
)
56 self
.assert_decl_not_loaded(self
.other_struct_decl
)
57 self
.assert_decl_not_loaded(self
.class_in_namespace_decl
)
58 self
.assert_decl_not_loaded(self
.class_member_decl
)
59 self
.assert_decl_not_loaded(self
.class_static_member_decl
)
60 self
.assert_decl_not_loaded(self
.unused_class_member_decl
)
62 def get_ast_dump(self
):
63 """Returns the dumped Clang AST of the module as a string"""
64 res
= lldb
.SBCommandReturnObject()
65 ci
= self
.dbg
.GetCommandInterpreter()
66 ci
.HandleCommand("target modules dump ast a.out", res
)
67 self
.assertTrue(res
.Succeeded())
68 return res
.GetOutput()
70 def decl_in_line(self
, line
, decl
):
72 Returns true iff the given line declares the given Clang decl.
73 The line is expected to be in the form of Clang's AST dump.
75 line
= line
.rstrip() + "\n"
76 decl_kind
= "-" + decl
[0] + " "
77 # Either the decl is somewhere in the line or at the end of
79 decl_name
= " " + decl
[1] + " "
80 decl_name_eol
= " " + decl
[1] + "\n"
81 if not decl_kind
in line
:
83 return decl_name
in line
or decl_name_eol
in line
85 def decl_completed_in_line(self
, line
, decl
):
87 Returns true iff the given line declares the given Clang decl and
88 the decl was completed (i.e., it has no undeserialized declarations
92 self
.decl_in_line(line
, decl
)
93 and not "<undeserialized declarations>" in line
96 # The following asserts are used for checking if certain Clang declarations
97 # were loaded or not since the target was created.
99 def assert_decl_loaded(self
, decl
):
101 Asserts the given decl is currently loaded.
102 Note: This test is about checking that types/declarations are not
103 loaded. If this assert fails it is usually fine to turn it into a
104 assert_decl_not_loaded or assert_decl_not_completed assuming LLDB's
105 functionality has not suffered by not loading this declaration.
107 ast
= self
.get_ast_dump()
109 for line
in ast
.splitlines():
110 if self
.decl_in_line(line
, decl
):
113 self
.decl_completed_in_line(line
, decl
),
114 "Should have called assert_decl_not_completed",
117 found
, "Declaration no longer loaded " + str(decl
) + ".\nAST:\n" + ast
120 def assert_decl_not_completed(self
, decl
):
122 Asserts that the given decl is currently not completed in the module's
123 AST. It may be loaded but then can can only contain undeserialized
126 ast
= self
.get_ast_dump()
128 for line
in ast
.splitlines():
129 error_msg
= "Unexpected completed decl: '" + line
+ "'.\nAST:\n" + ast
130 self
.assertFalse(self
.decl_completed_in_line(line
, decl
), error_msg
)
132 def assert_decl_not_loaded(self
, decl
):
134 Asserts that the given decl is currently not loaded in the module's
137 ast
= self
.get_ast_dump()
139 for line
in ast
.splitlines():
140 error_msg
= "Unexpected loaded decl: '" + line
+ "'\nAST:\n" + ast
141 self
.assertFalse(self
.decl_in_line(line
, decl
), error_msg
)
143 def clean_setup(self
, location
):
145 Runs to the line with the source line with the given location string
146 and ensures that our module AST is empty.
148 lldbutil
.run_to_source_breakpoint(
149 self
, "// Location: " + location
, lldb
.SBFileSpec("main.cpp")
151 # Make sure no declarations are loaded initially.
152 self
.assert_no_decls_loaded()
154 @add_test_categories(["dwarf"])
155 def test_arithmetic_expression_in_main(self
):
156 """Runs a simple arithmetic expression which should load nothing."""
157 self
.clean_setup(location
="multiple locals function")
159 self
.expect("expr 1 + (int)2.0", substrs
=["(int) $0"])
161 # This should not have loaded any decls.
162 self
.assert_no_decls_loaded()
164 @add_test_categories(["dwarf"])
165 def test_printing_local_variable_in_other_struct_func(self
):
167 Prints a local variable and makes sure no unrelated types are loaded.
169 self
.clean_setup(location
="other struct function")
171 self
.expect("expr other_struct_var", substrs
=["(OtherStruct) $0"])
172 # The decl we run on was loaded.
173 self
.assert_decl_loaded(self
.other_struct_decl
)
175 # This should not have loaded anything else.
176 self
.assert_decl_not_loaded(self
.some_struct_decl
)
177 self
.assert_decl_not_loaded(self
.class_in_namespace_decl
)
179 @add_test_categories(["dwarf"])
180 def test_printing_struct_with_multiple_locals(self
):
182 Prints a local variable and checks that we don't load other local
185 self
.clean_setup(location
="multiple locals function")
187 self
.expect("expr struct_var", substrs
=["(SomeStruct) $0"])
189 # We loaded SomeStruct and its member types for printing.
190 self
.assert_decl_loaded(self
.some_struct_decl
)
191 self
.assert_decl_loaded(self
.struct_behind_ptr_decl
)
192 self
.assert_decl_loaded(self
.struct_behind_ref_decl
)
194 # FIXME: We don't use these variables, but we seem to load all local
196 self
.assert_decl_not_completed(self
.other_struct_decl
)
197 self
.assert_decl_not_completed(self
.class_in_namespace_decl
)
199 @add_test_categories(["dwarf"])
200 def test_addr_of_struct(self
):
202 Prints the address of a local variable (which is a struct).
204 self
.clean_setup(location
="multiple locals function")
206 self
.expect("expr &struct_var", substrs
=["(SomeStruct *) $0"])
208 # We loaded SomeStruct.
209 self
.assert_decl_loaded(self
.some_struct_decl
)
211 # The member declarations should not be completed.
212 self
.assert_decl_not_completed(self
.struct_behind_ptr_decl
)
213 self
.assert_decl_not_completed(self
.struct_behind_ref_decl
)
215 # FIXME: The first member was behind a pointer so it shouldn't be
216 # completed. Somehow LLDB really wants to load the first member, so
217 # that is why have it defined here.
218 self
.assert_decl_loaded(self
.struct_first_member_decl
)
220 # FIXME: We don't use these variables, but we seem to load all local
222 self
.assert_decl_not_completed(self
.other_struct_decl
)
223 self
.assert_decl_not_completed(self
.class_in_namespace_decl
)
225 @add_test_categories(["dwarf"])
226 def test_class_function_access_member(self
):
227 self
.clean_setup(location
="class function")
229 self
.expect("expr member", substrs
=["(ClassMember) $0"])
231 # We loaded the current class we touched.
232 self
.assert_decl_loaded(self
.class_we_enter_decl
)
233 # We loaded the unused members of this class.
234 self
.assert_decl_loaded(self
.unused_class_member_decl
)
235 self
.assert_decl_not_completed(self
.unused_class_member_ptr_decl
)
236 # We loaded the member we used.
237 self
.assert_decl_loaded(self
.class_member_decl
)
238 # We didn't load the type of the unused static member.
239 self
.assert_decl_not_completed(self
.class_static_member_decl
)
241 # This should not have loaded anything else.
242 self
.assert_decl_not_loaded(self
.other_struct_decl
)
243 self
.assert_decl_not_loaded(self
.some_struct_decl
)
244 self
.assert_decl_not_loaded(self
.class_in_namespace_decl
)