1from lldbsuite.test.decorators import * 2from lldbsuite.test.lldbtest import * 3from lldbsuite.test import lldbutil 4 5""" 6This test ensures that we only create Clang AST nodes in our module AST 7when we actually need them. 8 9All tests in this file behave like this: 10 1. Use LLDB to do something (expression evaluation, breakpoint setting, etc.). 11 2. Check that certain Clang AST nodes were not loaded during the previous 12 step. 13""" 14 15class TestCase(TestBase): 16 17 NO_DEBUG_INFO_TESTCASE = True 18 mydir = TestBase.compute_mydir(__file__) 19 20 def setUp(self): 21 TestBase.setUp(self) 22 # Only build this test once. 23 self.build() 24 25 # Clang declaration kind we are looking for. 26 class_decl_kind = "CXXRecordDecl" 27 # FIXME: This shouldn't be a CXXRecordDecl, but that's how we model 28 # structs in Clang. 29 struct_decl_kind = "CXXRecordDecl" 30 31 # The decls we use in this program in the format that 32 # decl_in_line and decl_completed_in_line expect (which is a pair of 33 # node type and the unqualified declaration name. 34 struct_first_member_decl = [struct_decl_kind, "StructFirstMember"] 35 struct_behind_ptr_decl = [struct_decl_kind, "StructBehindPointer"] 36 struct_behind_ref_decl = [struct_decl_kind, "StructBehindRef"] 37 struct_member_decl = [struct_decl_kind, "StructMember"] 38 some_struct_decl = [struct_decl_kind, "SomeStruct"] 39 other_struct_decl = [struct_decl_kind, "OtherStruct"] 40 class_in_namespace_decl = [class_decl_kind, "ClassInNamespace"] 41 class_we_enter_decl = [class_decl_kind, "ClassWeEnter"] 42 class_member_decl = [struct_decl_kind, "ClassMember"] 43 unused_class_member_decl = [struct_decl_kind, "UnusedClassMember"] 44 unused_class_member_ptr_decl = [struct_decl_kind, "UnusedClassMemberPtr"] 45 46 def assert_no_decls_loaded(self): 47 """ 48 Asserts that no known declarations in this test are loaded 49 into the module's AST. 50 """ 51 self.assert_decl_not_loaded(self.struct_first_member_decl) 52 self.assert_decl_not_loaded(self.struct_behind_ptr_decl) 53 self.assert_decl_not_loaded(self.struct_behind_ref_decl) 54 self.assert_decl_not_loaded(self.struct_member_decl) 55 self.assert_decl_not_loaded(self.some_struct_decl) 56 self.assert_decl_not_loaded(self.other_struct_decl) 57 self.assert_decl_not_loaded(self.class_in_namespace_decl) 58 self.assert_decl_not_loaded(self.class_member_decl) 59 self.assert_decl_not_loaded(self.unused_class_member_decl) 60 61 def get_ast_dump(self): 62 """Returns the dumped Clang AST of the module as a string""" 63 res = lldb.SBCommandReturnObject() 64 ci = self.dbg.GetCommandInterpreter() 65 ci.HandleCommand('target modules dump ast a.out', res) 66 self.assertTrue(res.Succeeded()) 67 return res.GetOutput() 68 69 def decl_in_line(self, line, decl): 70 """ 71 Returns true iff the given line declares the given Clang decl. 72 The line is expected to be in the form of Clang's AST dump. 73 """ 74 line = line.rstrip() + "\n" 75 decl_kind = "-" + decl[0] + " " 76 # Either the decl is somewhere in the line or at the end of 77 # the line. 78 decl_name = " " + decl[1] + " " 79 decl_name_eol = " " + decl[1] + "\n" 80 if not decl_kind in line: 81 return False 82 return decl_name in line or decl_name_eol in line 83 84 def decl_completed_in_line(self, line, decl): 85 """ 86 Returns true iff the given line declares the given Clang decl and 87 the decl was completed (i.e., it has no undeserialized declarations 88 in it). 89 """ 90 return self.decl_in_line(line, decl) and not "<undeserialized declarations>" in line 91 92 # The following asserts are used for checking if certain Clang declarations 93 # were loaded or not since the target was created. 94 95 def assert_decl_loaded(self, decl): 96 """ 97 Asserts the given decl is currently loaded. 98 Note: This test is about checking that types/declarations are not 99 loaded. If this assert fails it is usually fine to turn it into a 100 assert_decl_not_loaded or assert_decl_not_completed assuming LLDB's 101 functionality has not suffered by not loading this declaration. 102 """ 103 ast = self.get_ast_dump() 104 found = False 105 for line in ast.splitlines(): 106 if self.decl_in_line(line, decl): 107 found = True 108 self.assertTrue(self.decl_completed_in_line(line, decl), 109 "Should have called assert_decl_not_completed") 110 self.assertTrue(found, "Declaration no longer loaded " + str(decl) + 111 ".\nAST:\n" + ast) 112 113 def assert_decl_not_completed(self, decl): 114 """ 115 Asserts that the given decl is currently not completed in the module's 116 AST. It may be loaded but then can can only contain undeserialized 117 declarations. 118 """ 119 ast = self.get_ast_dump() 120 found = False 121 for line in ast.splitlines(): 122 error_msg = "Unexpected completed decl: '" + line + "'.\nAST:\n" + ast 123 self.assertFalse(self.decl_completed_in_line(line, decl), error_msg) 124 125 def assert_decl_not_loaded(self, decl): 126 """ 127 Asserts that the given decl is currently not loaded in the module's 128 AST. 129 """ 130 ast = self.get_ast_dump() 131 found = False 132 for line in ast.splitlines(): 133 error_msg = "Unexpected loaded decl: '" + line + "'\nAST:\n" + ast 134 self.assertFalse(self.decl_in_line(line, decl), error_msg) 135 136 137 def clean_setup(self, location): 138 """ 139 Runs to the line with the source line with the given location string 140 and ensures that our module AST is empty. 141 """ 142 lldbutil.run_to_source_breakpoint(self, 143 "// Location: " + location, lldb.SBFileSpec("main.cpp")) 144 # Make sure no declarations are loaded initially. 145 self.assert_no_decls_loaded() 146 147 @add_test_categories(["dwarf"]) 148 def test_arithmetic_expression_in_main(self): 149 """ Runs a simple arithmetic expression which should load nothing. """ 150 self.clean_setup(location="multiple locals function") 151 152 self.expect("expr 1 + (int)2.0", substrs=['(int) $0']) 153 154 # This should not have loaded any decls. 155 self.assert_no_decls_loaded() 156 157 @add_test_categories(["dwarf"]) 158 def test_printing_local_variable_in_other_struct_func(self): 159 """ 160 Prints a local variable and makes sure no unrelated types are loaded. 161 """ 162 self.clean_setup(location="other struct function") 163 164 self.expect("expr other_struct_var", substrs=['(OtherStruct) $0']) 165 # The decl we run on was loaded. 166 self.assert_decl_loaded(self.other_struct_decl) 167 168 # This should not have loaded anything else. 169 self.assert_decl_not_loaded(self.some_struct_decl) 170 self.assert_decl_not_loaded(self.class_in_namespace_decl) 171 172 @add_test_categories(["dwarf"]) 173 def test_printing_struct_with_multiple_locals(self): 174 """ 175 Prints a local variable and checks that we don't load other local 176 variables. 177 """ 178 self.clean_setup(location="multiple locals function") 179 180 self.expect("expr struct_var", substrs=['(SomeStruct) $0']) 181 182 # We loaded SomeStruct and its member types for printing. 183 self.assert_decl_loaded(self.some_struct_decl) 184 self.assert_decl_loaded(self.struct_behind_ptr_decl) 185 self.assert_decl_loaded(self.struct_behind_ref_decl) 186 187 # FIXME: We don't use these variables, but we seem to load all local 188 # local variables. 189 self.assert_decl_not_completed(self.other_struct_decl) 190 self.assert_decl_not_completed(self.class_in_namespace_decl) 191 192 @add_test_categories(["dwarf"]) 193 def test_addr_of_struct(self): 194 """ 195 Prints the address of a local variable (which is a struct). 196 """ 197 self.clean_setup(location="multiple locals function") 198 199 self.expect("expr &struct_var", substrs=['(SomeStruct *) $0']) 200 201 # We loaded SomeStruct. 202 self.assert_decl_loaded(self.some_struct_decl) 203 204 # The member declarations should not be completed. 205 self.assert_decl_not_completed(self.struct_behind_ptr_decl) 206 self.assert_decl_not_completed(self.struct_behind_ref_decl) 207 208 # FIXME: The first member was behind a pointer so it shouldn't be 209 # completed. Somehow LLDB really wants to load the first member, so 210 # that is why have it defined here. 211 self.assert_decl_loaded(self.struct_first_member_decl) 212 213 # FIXME: We don't use these variables, but we seem to load all local 214 # local variables. 215 self.assert_decl_not_completed(self.other_struct_decl) 216 self.assert_decl_not_completed(self.class_in_namespace_decl) 217 218 @add_test_categories(["dwarf"]) 219 def test_class_function_access_member(self): 220 self.clean_setup(location="class function") 221 222 self.expect("expr member", substrs=['(ClassMember) $0']) 223 224 # We loaded the current class we touched. 225 self.assert_decl_loaded(self.class_we_enter_decl) 226 # We loaded the unused members of this class. 227 self.assert_decl_loaded(self.unused_class_member_decl) 228 self.assert_decl_not_completed(self.unused_class_member_ptr_decl) 229 # We loaded the member we used. 230 self.assert_decl_loaded(self.class_member_decl) 231 232 # This should not have loaded anything else. 233 self.assert_decl_not_loaded(self.other_struct_decl) 234 self.assert_decl_not_loaded(self.some_struct_decl) 235 self.assert_decl_not_loaded(self.class_in_namespace_decl) 236 237