2 Test completing types using information from other shared libraries.
7 from lldbsuite
.test
.decorators
import *
8 from lldbsuite
.test
.lldbtest
import *
9 from lldbsuite
.test
import lldbutil
12 class LimitDebugInfoTestCase(TestBase
):
13 def _check_type(self
, target
, name
):
14 exe
= target
.FindModule(lldb
.SBFileSpec("a.out"))
15 type_
= exe
.FindFirstType(name
)
16 self
.trace("type_: %s" % type_
)
17 self
.assertTrue(type_
)
18 self
.assertTrue(type_
.IsTypeComplete())
19 base
= type_
.GetDirectBaseClassAtIndex(0).GetType()
20 self
.trace("base:%s" % base
)
22 self
.assertEquals(base
.GetNumberOfFields(), 0)
23 self
.assertFalse(base
.IsTypeComplete())
25 def _check_debug_info_is_limited(self
, target
):
26 # Without other shared libraries we should only see the member declared
27 # in the derived class. This serves as a sanity check that we are truly
28 # building with limited debug info.
29 self
._check
_type
(target
, "InheritsFromOne")
30 self
._check
_type
(target
, "InheritsFromTwo")
32 # Check that the statistics show that we had incomplete debug info.
33 stats
= self
.get_stats()
34 # Find the a.out module info in the stats and verify it has the
35 # "debugInfoHadIncompleteTypes" key value pair set to True
36 exe_module_found
= False
37 for module
in stats
["modules"]:
38 if module
["path"].endswith("a.out"):
39 self
.assertTrue(module
["debugInfoHadIncompleteTypes"])
40 exe_module_found
= True
42 self
.assertTrue(exe_module_found
)
43 # Verify that "totalModuleCountWithIncompleteTypes" at the top level
44 # is greater than zero which shows we had incomplete debug info in a
46 self
.assertGreater(stats
["totalModuleCountWithIncompleteTypes"], 0)
48 def _check_incomplete_frame_variable_output(self
):
49 # Check that the display of the "frame variable" output identifies the
50 # incomplete types. Currently the expression parser will find the real
51 # definition for a type when running an expression for any forcefully
52 # completed types, but "frame variable" won't. I hope to fix this with
53 # a follow up patch, but if we don't find the actual definition we
54 # should clearly show this to the user by showing which types were
55 # incomplete. So this will test verifies the expected output for such
56 # types. We also need to verify the standard "frame variable" output
57 # which will inline all of the members on one line, versus the full
58 # output from "frame variable --raw" and a few other options.
59 # self.expect("frame variable two_as_member", error=True,
60 # substrs=["no member named 'one' in 'InheritsFromOne'"])
62 command_expect_pairs
= [
63 # Test standard "frame variable" output for types to make sure
64 # "<incomplete type>" shows up where we expect it to
68 "(TwoAsMember) ::two_as_member = (two = <incomplete type>, member = 47)"
72 "var inherits_from_one",
74 "(InheritsFromOne) ::inherits_from_one = (One = <incomplete type>, member = 47)"
78 "var inherits_from_two",
80 "(InheritsFromTwo) ::inherits_from_two = (Two = <incomplete type>, member = 47)"
86 "(OneAsMember) ::one_as_member = (one = <incomplete type>, member = 47)"
92 "(TwoAsMember) ::two_as_member = (two = <incomplete type>, member = 47)"
98 "(array::One[3]) ::array_of_one = ([0] = <incomplete type>, [1] = <incomplete type>, [2] = <incomplete type>)"
104 "(array::Two[3]) ::array_of_two = ([0] = <incomplete type>, [1] = <incomplete type>, [2] = <incomplete type>)"
110 "(ShadowedOne) ::shadowed_one = (func_shadow::One = <incomplete type>, member = 47)"
113 # Now test "frame variable --show-types output" which has multi-line
114 # output and should not always show classes that were forcefully
115 # completed to the user to let them know they have a type that should
116 # have been complete but wasn't.
118 "var --show-types inherits_from_one",
120 "(InheritsFromOne) ::inherits_from_one = {",
121 " (One) One = <incomplete type> {}",
122 " (int) member = 47",
127 "var --show-types inherits_from_two",
129 "(InheritsFromTwo) ::inherits_from_two = {",
130 " (Two) Two = <incomplete type> {}",
131 " (int) member = 47",
136 "var --show-types one_as_member",
138 "(OneAsMember) ::one_as_member = {",
139 " (member::One) one = <incomplete type> {}",
140 " (int) member = 47",
145 "var --show-types two_as_member",
147 "(TwoAsMember) ::two_as_member = {",
148 " (member::Two) two = <incomplete type> {}",
149 " (int) member = 47",
154 "var --show-types array_of_one",
156 "(array::One[3]) ::array_of_one = {",
157 " (array::One) [0] = <incomplete type> {}",
158 " (array::One) [1] = <incomplete type> {}",
159 " (array::One) [2] = <incomplete type> {}",
164 "var --show-types array_of_two",
166 "(array::Two[3]) ::array_of_two = {",
167 " (array::Two) [0] = <incomplete type> {}",
168 " (array::Two) [1] = <incomplete type> {}",
169 " (array::Two) [2] = <incomplete type> {}",
174 "var --show-types shadowed_one",
176 "(ShadowedOne) ::shadowed_one = {",
177 " (func_shadow::One) func_shadow::One = <incomplete type> {}",
178 " (int) member = 47",
183 for command
, expect_items
in command_expect_pairs
:
184 self
.expect(command
, substrs
=expect_items
)
186 @skipIf(bugnumber
="pr46284", debug_info
="gmodules")
187 @skipIfWindows # Clang emits type info even with -flimit-debug-info
188 # Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call
189 # by-value functions.
190 @skipIf(compiler
="clang", compiler_version
=["<", "7.0"])
191 def test_one_and_two_debug(self
):
193 target
= self
.dbg
.CreateTarget(self
.getBuildArtifact("a.out"))
195 self
._check
_debug
_info
_is
_limited
(target
)
197 lldbutil
.run_to_name_breakpoint(self
, "main", extra_images
=["one", "two"])
199 # But when other shared libraries are loaded, we should be able to see
201 self
.expect_expr("inherits_from_one.member", result_value
="47")
202 self
.expect_expr("inherits_from_one.one", result_value
="142")
203 self
.expect_expr("inherits_from_two.member", result_value
="47")
204 self
.expect_expr("inherits_from_two.one", result_value
="142")
205 self
.expect_expr("inherits_from_two.two", result_value
="242")
207 self
.expect_expr("one_as_member.member", result_value
="47")
208 self
.expect_expr("one_as_member.one.member", result_value
="147")
209 self
.expect_expr("two_as_member.member", result_value
="47")
210 self
.expect_expr("two_as_member.two.one.member", result_value
="147")
211 self
.expect_expr("two_as_member.two.member", result_value
="247")
213 self
.expect_expr("array_of_one[2].member", result_value
="174")
214 self
.expect_expr("array_of_two[2].one[2].member", result_value
="174")
215 self
.expect_expr("array_of_two[2].member", result_value
="274")
217 self
.expect_expr("get_one().member", result_value
="124")
218 self
.expect_expr("get_two().one().member", result_value
="124")
219 self
.expect_expr("get_two().member", result_value
="224")
221 self
.expect_expr("shadowed_one.member", result_value
="47")
222 self
.expect_expr("shadowed_one.one", result_value
="142")
224 self
._check
_incomplete
_frame
_variable
_output
()
226 @skipIf(bugnumber
="pr46284", debug_info
="gmodules")
227 @skipIfWindows # Clang emits type info even with -flimit-debug-info
228 # Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call
229 # by-value functions.
230 @skipIf(compiler
="clang", compiler_version
=["<", "7.0"])
231 def test_two_debug(self
):
232 self
.build(dictionary
=dict(STRIP_ONE
="1"))
233 target
= self
.dbg
.CreateTarget(self
.getBuildArtifact("a.out"))
235 self
._check
_debug
_info
_is
_limited
(target
)
237 lldbutil
.run_to_name_breakpoint(self
, "main", extra_images
=["one", "two"])
239 # This time, we should only see the members from the second library.
240 self
.expect_expr("inherits_from_one.member", result_value
="47")
242 "expr inherits_from_one.one",
244 substrs
=["no member named 'one' in 'InheritsFromOne'"],
246 self
.expect_expr("inherits_from_two.member", result_value
="47")
248 "expr inherits_from_two.one",
250 substrs
=["no member named 'one' in 'InheritsFromTwo'"],
252 self
.expect_expr("inherits_from_two.two", result_value
="242")
254 self
.expect_expr("one_as_member.member", result_value
="47")
256 "expr one_as_member.one.member",
258 substrs
=["no member named 'member' in 'member::One'"],
260 self
.expect_expr("two_as_member.member", result_value
="47")
262 "expr two_as_member.two.one.member",
264 substrs
=["no member named 'member' in 'member::One'"],
266 self
.expect_expr("two_as_member.two.member", result_value
="247")
269 "expr array_of_one[2].member",
271 substrs
=["no member named 'member' in 'array::One'"],
274 "expr array_of_two[2].one[2].member",
276 substrs
=["no member named 'member' in 'array::One'"],
278 self
.expect_expr("array_of_two[2].member", result_value
="274")
281 "expr get_one().member",
283 substrs
=["calling 'get_one' with incomplete return type 'result::One'"],
286 "expr get_two().one().member",
288 substrs
=["calling 'one' with incomplete return type 'result::One'"],
290 self
.expect_expr("get_two().member", result_value
="224")
292 self
._check
_incomplete
_frame
_variable
_output
()
294 @skipIf(bugnumber
="pr46284", debug_info
="gmodules")
295 @skipIfWindows # Clang emits type info even with -flimit-debug-info
296 # Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call
297 # by-value functions.
298 @skipIf(compiler
="clang", compiler_version
=["<", "7.0"])
299 def test_one_debug(self
):
300 self
.build(dictionary
=dict(STRIP_TWO
="1"))
301 target
= self
.dbg
.CreateTarget(self
.getBuildArtifact("a.out"))
303 self
._check
_debug
_info
_is
_limited
(target
)
305 lldbutil
.run_to_name_breakpoint(self
, "main", extra_images
=["one", "two"])
307 # In this case we should only see the members from the second library.
308 # Note that we cannot see inherits_from_two.one because without debug
309 # info for "Two", we cannot determine that it in fact inherits from
311 self
.expect_expr("inherits_from_one.member", result_value
="47")
312 self
.expect_expr("inherits_from_one.one", result_value
="142")
313 self
.expect_expr("inherits_from_two.member", result_value
="47")
315 "expr inherits_from_two.one",
317 substrs
=["no member named 'one' in 'InheritsFromTwo'"],
320 "expr inherits_from_two.two",
322 substrs
=["no member named 'two' in 'InheritsFromTwo'"],
325 self
.expect_expr("one_as_member.member", result_value
="47")
326 self
.expect_expr("one_as_member.one.member", result_value
="147")
327 self
.expect_expr("two_as_member.member", result_value
="47")
329 "expr two_as_member.two.one.member",
331 substrs
=["no member named 'one' in 'member::Two'"],
334 "expr two_as_member.two.member",
336 substrs
=["no member named 'member' in 'member::Two'"],
339 self
.expect_expr("array_of_one[2].member", result_value
="174")
341 "expr array_of_two[2].one[2].member",
343 substrs
=["no member named 'one' in 'array::Two'"],
346 "expr array_of_two[2].member",
348 substrs
=["no member named 'member' in 'array::Two'"],
351 self
.expect_expr("get_one().member", result_value
="124")
353 "expr get_two().one().member",
355 substrs
=["calling 'get_two' with incomplete return type 'result::Two'"],
358 "expr get_two().member",
360 substrs
=["calling 'get_two' with incomplete return type 'result::Two'"],
363 self
._check
_incomplete
_frame
_variable
_output
()