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