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