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