176 lines · python
1"""Test that anonymous structs/unions are transparent to member access"""2 3 4import lldb5from lldbsuite.test.decorators import *6from lldbsuite.test.lldbtest import *7from lldbsuite.test import lldbutil8 9 10class AnonymousTestCase(TestBase):11 @skipIf(12 compiler="icc",13 bugnumber="llvm.org/pr15036: LLDB generates an incorrect AST layout for an anonymous struct when DWARF is generated by ICC",14 )15 def test_expr_nest(self):16 self.build()17 self.common_setup(self.line0)18 19 # These should display correctly.20 self.expect(21 "expression n->foo.d", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 4"]22 )23 24 self.expect("expression n->b", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 2"])25 26 def test_expr_child(self):27 self.build()28 self.common_setup(self.line1)29 30 # These should display correctly.31 self.expect(32 "expression c->foo.d", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 4"]33 )34 35 self.expect(36 "expression c->grandchild.b", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 2"]37 )38 39 @skipIf(40 compiler="icc",41 bugnumber="llvm.org/pr15036: This particular regression was introduced by r181498",42 )43 def test_expr_grandchild(self):44 self.build()45 self.common_setup(self.line2)46 47 # These should display correctly.48 self.expect(49 "expression g.child.foo.d", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 4"]50 )51 52 self.expect(53 "expression g.child.b", VARIABLES_DISPLAYED_CORRECTLY, substrs=["= 2"]54 )55 56 def test_expr_parent(self):57 self.build()58 if "clang" in self.getCompiler() and "3.4" in self.getCompilerVersion():59 self.skipTest(60 "llvm.org/pr16214 -- clang emits partial DWARF for structures referenced via typedef"61 )62 self.common_setup(self.line2)63 64 # These should display correctly.65 self.expect(66 "expression pz",67 VARIABLES_DISPLAYED_CORRECTLY,68 substrs=["(type_z *) $", " = NULL"],69 )70 71 self.expect(72 "expression z.y",73 VARIABLES_DISPLAYED_CORRECTLY,74 substrs=["(type_y) $", "dummy = 2"],75 )76 77 def test_expr_null(self):78 self.build()79 self.common_setup(self.line2)80 81 # This should fail because pz is 0, but it succeeds on OS/X.82 # This fails on Linux with an upstream error "Couldn't dematerialize struct", as does "p *n" with "int *n = 0".83 # Note that this can also trigger llvm.org/pr15036 when run84 # interactively at the lldb command prompt.85 self.expect("expression *(type_z *)pz", error=True)86 87 def test_child_by_name(self):88 self.build()89 90 # Set debugger into synchronous mode91 self.dbg.SetAsync(False)92 93 # Create a target94 exe = self.getBuildArtifact("a.out")95 target = self.dbg.CreateTarget(exe)96 self.assertTrue(target, VALID_TARGET)97 98 break_in_main = target.BreakpointCreateBySourceRegex(99 "// Set breakpoint 2 here.", lldb.SBFileSpec(self.source)100 )101 self.assertTrue(break_in_main, VALID_BREAKPOINT)102 103 process = target.LaunchSimple(None, None, self.get_process_working_directory())104 self.assertTrue(process, PROCESS_IS_VALID)105 106 threads = lldbutil.get_threads_stopped_at_breakpoint(process, break_in_main)107 if len(threads) != 1:108 self.fail("Failed to stop at breakpoint in main.")109 110 thread = threads[0]111 frame = thread.frames[0]112 113 if not frame.IsValid():114 self.fail("Failed to get frame 0.")115 116 var_n = frame.FindVariable("n")117 if not var_n.IsValid():118 self.fail("Failed to get the variable 'n'")119 120 elem_a = var_n.GetChildMemberWithName("a")121 if not elem_a.IsValid():122 self.fail("Failed to get the element a in n")123 124 error = lldb.SBError()125 value = elem_a.GetValueAsSigned(error, 1000)126 if not error.Success() or value != 0:127 self.fail("failed to get the correct value for element a in n")128 129 def test_nest_flat(self):130 self.build()131 self.common_setup(self.line2)132 133 # These should display correctly.134 self.expect(135 "frame variable n --flat",136 substrs=["n.a = 0", "n.b = 2", "n.foo.c = 0", "n.foo.d = 4"],137 )138 139 def setUp(self):140 # Call super's setUp().141 TestBase.setUp(self)142 # Find the line numbers to break in main.c.143 self.source = "main.c"144 self.line0 = line_number(self.source, "// Set breakpoint 0 here.")145 self.line1 = line_number(self.source, "// Set breakpoint 1 here.")146 self.line2 = line_number(self.source, "// Set breakpoint 2 here.")147 148 def common_setup(self, line):149 # Set debugger into synchronous mode150 self.dbg.SetAsync(False)151 152 # Create a target153 exe = self.getBuildArtifact("a.out")154 target = self.dbg.CreateTarget(exe)155 self.assertTrue(target, VALID_TARGET)156 157 # Set breakpoints inside and outside methods that take pointers to the158 # containing struct.159 lldbutil.run_break_set_by_file_and_line(160 self, self.source, line, num_expected_locations=1, loc_exact=True161 )162 163 # Now launch the process, and do not stop at entry point.164 process = target.LaunchSimple(None, None, self.get_process_working_directory())165 self.assertTrue(process, PROCESS_IS_VALID)166 167 # The stop reason of the thread should be breakpoint.168 self.expect(169 "thread list",170 STOPPED_DUE_TO_BREAKPOINT,171 substrs=["stopped", "stop reason = breakpoint"],172 )173 174 # The breakpoint should have a hit count of 1.175 lldbutil.check_breakpoint(self, bpno=1, expected_hit_count=1)176