1"""Test that anonymous structs/unions are transparent to member access""" 2 3 4import lldb 5from lldbsuite.test.decorators import * 6from lldbsuite.test.lldbtest import * 7from lldbsuite.test import lldbutil 8 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 run 84 # 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 mode 91 self.dbg.SetAsync(False) 92 93 # Create a target 94 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 mode 150 self.dbg.SetAsync(False) 151 152 # Create a target 153 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 the 158 # containing struct. 159 lldbutil.run_break_set_by_file_and_line( 160 self, self.source, line, num_expected_locations=1, loc_exact=True 161 ) 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