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