199451b44SJordan Rupprechtfrom lldbsuite.test.decorators import * 299451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import * 399451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil 499451b44SJordan Rupprecht 599451b44SJordan Rupprecht""" 699451b44SJordan RupprechtThis test ensures that we only create Clang AST nodes in our module AST 799451b44SJordan Rupprechtwhen we actually need them. 899451b44SJordan Rupprecht 999451b44SJordan RupprechtAll tests in this file behave like this: 1099451b44SJordan Rupprecht 1. Use LLDB to do something (expression evaluation, breakpoint setting, etc.). 1199451b44SJordan Rupprecht 2. Check that certain Clang AST nodes were not loaded during the previous 1299451b44SJordan Rupprecht step. 1399451b44SJordan Rupprecht""" 1499451b44SJordan Rupprecht 1599451b44SJordan Rupprecht 16*2238dcc3SJonas Devlieghereclass TestCase(TestBase): 1799451b44SJordan Rupprecht NO_DEBUG_INFO_TESTCASE = True 1899451b44SJordan Rupprecht 1999451b44SJordan Rupprecht def setUp(self): 2099451b44SJordan Rupprecht TestBase.setUp(self) 2199451b44SJordan Rupprecht # Only build this test once. 2299451b44SJordan Rupprecht self.build() 2399451b44SJordan Rupprecht 2499451b44SJordan Rupprecht # Clang declaration kind we are looking for. 2599451b44SJordan Rupprecht class_decl_kind = "CXXRecordDecl" 2699451b44SJordan Rupprecht # FIXME: This shouldn't be a CXXRecordDecl, but that's how we model 2799451b44SJordan Rupprecht # structs in Clang. 2899451b44SJordan Rupprecht struct_decl_kind = "CXXRecordDecl" 2999451b44SJordan Rupprecht 3099451b44SJordan Rupprecht # The decls we use in this program in the format that 3199451b44SJordan Rupprecht # decl_in_line and decl_completed_in_line expect (which is a pair of 3299451b44SJordan Rupprecht # node type and the unqualified declaration name. 3399451b44SJordan Rupprecht struct_first_member_decl = [struct_decl_kind, "StructFirstMember"] 3499451b44SJordan Rupprecht struct_behind_ptr_decl = [struct_decl_kind, "StructBehindPointer"] 3599451b44SJordan Rupprecht struct_behind_ref_decl = [struct_decl_kind, "StructBehindRef"] 3699451b44SJordan Rupprecht struct_member_decl = [struct_decl_kind, "StructMember"] 3799451b44SJordan Rupprecht some_struct_decl = [struct_decl_kind, "SomeStruct"] 3899451b44SJordan Rupprecht other_struct_decl = [struct_decl_kind, "OtherStruct"] 3999451b44SJordan Rupprecht class_in_namespace_decl = [class_decl_kind, "ClassInNamespace"] 4099451b44SJordan Rupprecht class_we_enter_decl = [class_decl_kind, "ClassWeEnter"] 4199451b44SJordan Rupprecht class_member_decl = [struct_decl_kind, "ClassMember"] 4234c697c8SRaphael Isemann class_static_member_decl = [struct_decl_kind, "StaticClassMember"] 4399451b44SJordan Rupprecht unused_class_member_decl = [struct_decl_kind, "UnusedClassMember"] 4499451b44SJordan Rupprecht unused_class_member_ptr_decl = [struct_decl_kind, "UnusedClassMemberPtr"] 4599451b44SJordan Rupprecht 4699451b44SJordan Rupprecht def assert_no_decls_loaded(self): 4799451b44SJordan Rupprecht """ 4899451b44SJordan Rupprecht Asserts that no known declarations in this test are loaded 4999451b44SJordan Rupprecht into the module's AST. 5099451b44SJordan Rupprecht """ 5199451b44SJordan Rupprecht self.assert_decl_not_loaded(self.struct_first_member_decl) 5299451b44SJordan Rupprecht self.assert_decl_not_loaded(self.struct_behind_ptr_decl) 5399451b44SJordan Rupprecht self.assert_decl_not_loaded(self.struct_behind_ref_decl) 5499451b44SJordan Rupprecht self.assert_decl_not_loaded(self.struct_member_decl) 5599451b44SJordan Rupprecht self.assert_decl_not_loaded(self.some_struct_decl) 5699451b44SJordan Rupprecht self.assert_decl_not_loaded(self.other_struct_decl) 5799451b44SJordan Rupprecht self.assert_decl_not_loaded(self.class_in_namespace_decl) 5899451b44SJordan Rupprecht self.assert_decl_not_loaded(self.class_member_decl) 5934c697c8SRaphael Isemann self.assert_decl_not_loaded(self.class_static_member_decl) 6099451b44SJordan Rupprecht self.assert_decl_not_loaded(self.unused_class_member_decl) 6199451b44SJordan Rupprecht 6299451b44SJordan Rupprecht def get_ast_dump(self): 6399451b44SJordan Rupprecht """Returns the dumped Clang AST of the module as a string""" 6499451b44SJordan Rupprecht res = lldb.SBCommandReturnObject() 6599451b44SJordan Rupprecht ci = self.dbg.GetCommandInterpreter() 66*2238dcc3SJonas Devlieghere ci.HandleCommand("target modules dump ast a.out", res) 6799451b44SJordan Rupprecht self.assertTrue(res.Succeeded()) 6899451b44SJordan Rupprecht return res.GetOutput() 6999451b44SJordan Rupprecht 7099451b44SJordan Rupprecht def decl_in_line(self, line, decl): 7199451b44SJordan Rupprecht """ 7299451b44SJordan Rupprecht Returns true iff the given line declares the given Clang decl. 7399451b44SJordan Rupprecht The line is expected to be in the form of Clang's AST dump. 7499451b44SJordan Rupprecht """ 7599451b44SJordan Rupprecht line = line.rstrip() + "\n" 7699451b44SJordan Rupprecht decl_kind = "-" + decl[0] + " " 7799451b44SJordan Rupprecht # Either the decl is somewhere in the line or at the end of 7899451b44SJordan Rupprecht # the line. 7999451b44SJordan Rupprecht decl_name = " " + decl[1] + " " 8099451b44SJordan Rupprecht decl_name_eol = " " + decl[1] + "\n" 8199451b44SJordan Rupprecht if not decl_kind in line: 8299451b44SJordan Rupprecht return False 8399451b44SJordan Rupprecht return decl_name in line or decl_name_eol in line 8499451b44SJordan Rupprecht 8599451b44SJordan Rupprecht def decl_completed_in_line(self, line, decl): 8699451b44SJordan Rupprecht """ 8799451b44SJordan Rupprecht Returns true iff the given line declares the given Clang decl and 8899451b44SJordan Rupprecht the decl was completed (i.e., it has no undeserialized declarations 8999451b44SJordan Rupprecht in it). 9099451b44SJordan Rupprecht """ 91*2238dcc3SJonas Devlieghere return ( 92*2238dcc3SJonas Devlieghere self.decl_in_line(line, decl) 93*2238dcc3SJonas Devlieghere and not "<undeserialized declarations>" in line 94*2238dcc3SJonas Devlieghere ) 9599451b44SJordan Rupprecht 9699451b44SJordan Rupprecht # The following asserts are used for checking if certain Clang declarations 9799451b44SJordan Rupprecht # were loaded or not since the target was created. 9899451b44SJordan Rupprecht 9999451b44SJordan Rupprecht def assert_decl_loaded(self, decl): 10099451b44SJordan Rupprecht """ 10199451b44SJordan Rupprecht Asserts the given decl is currently loaded. 10299451b44SJordan Rupprecht Note: This test is about checking that types/declarations are not 10399451b44SJordan Rupprecht loaded. If this assert fails it is usually fine to turn it into a 10499451b44SJordan Rupprecht assert_decl_not_loaded or assert_decl_not_completed assuming LLDB's 10599451b44SJordan Rupprecht functionality has not suffered by not loading this declaration. 10699451b44SJordan Rupprecht """ 10799451b44SJordan Rupprecht ast = self.get_ast_dump() 10899451b44SJordan Rupprecht found = False 10999451b44SJordan Rupprecht for line in ast.splitlines(): 11099451b44SJordan Rupprecht if self.decl_in_line(line, decl): 11199451b44SJordan Rupprecht found = True 112*2238dcc3SJonas Devlieghere self.assertTrue( 113*2238dcc3SJonas Devlieghere self.decl_completed_in_line(line, decl), 114*2238dcc3SJonas Devlieghere "Should have called assert_decl_not_completed", 115*2238dcc3SJonas Devlieghere ) 116*2238dcc3SJonas Devlieghere self.assertTrue( 117*2238dcc3SJonas Devlieghere found, "Declaration no longer loaded " + str(decl) + ".\nAST:\n" + ast 118*2238dcc3SJonas Devlieghere ) 11999451b44SJordan Rupprecht 12099451b44SJordan Rupprecht def assert_decl_not_completed(self, decl): 12199451b44SJordan Rupprecht """ 12299451b44SJordan Rupprecht Asserts that the given decl is currently not completed in the module's 12399451b44SJordan Rupprecht AST. It may be loaded but then can can only contain undeserialized 12499451b44SJordan Rupprecht declarations. 12599451b44SJordan Rupprecht """ 12699451b44SJordan Rupprecht ast = self.get_ast_dump() 12799451b44SJordan Rupprecht found = False 12899451b44SJordan Rupprecht for line in ast.splitlines(): 12999451b44SJordan Rupprecht error_msg = "Unexpected completed decl: '" + line + "'.\nAST:\n" + ast 13099451b44SJordan Rupprecht self.assertFalse(self.decl_completed_in_line(line, decl), error_msg) 13199451b44SJordan Rupprecht 13299451b44SJordan Rupprecht def assert_decl_not_loaded(self, decl): 13399451b44SJordan Rupprecht """ 13499451b44SJordan Rupprecht Asserts that the given decl is currently not loaded in the module's 13599451b44SJordan Rupprecht AST. 13699451b44SJordan Rupprecht """ 13799451b44SJordan Rupprecht ast = self.get_ast_dump() 13899451b44SJordan Rupprecht found = False 13999451b44SJordan Rupprecht for line in ast.splitlines(): 14099451b44SJordan Rupprecht error_msg = "Unexpected loaded decl: '" + line + "'\nAST:\n" + ast 14199451b44SJordan Rupprecht self.assertFalse(self.decl_in_line(line, decl), error_msg) 14299451b44SJordan Rupprecht 14399451b44SJordan Rupprecht def clean_setup(self, location): 14499451b44SJordan Rupprecht """ 14599451b44SJordan Rupprecht Runs to the line with the source line with the given location string 14699451b44SJordan Rupprecht and ensures that our module AST is empty. 14799451b44SJordan Rupprecht """ 148*2238dcc3SJonas Devlieghere lldbutil.run_to_source_breakpoint( 149*2238dcc3SJonas Devlieghere self, "// Location: " + location, lldb.SBFileSpec("main.cpp") 150*2238dcc3SJonas Devlieghere ) 15199451b44SJordan Rupprecht # Make sure no declarations are loaded initially. 15299451b44SJordan Rupprecht self.assert_no_decls_loaded() 15399451b44SJordan Rupprecht 15499451b44SJordan Rupprecht @add_test_categories(["dwarf"]) 15599451b44SJordan Rupprecht def test_arithmetic_expression_in_main(self): 15699451b44SJordan Rupprecht """Runs a simple arithmetic expression which should load nothing.""" 15799451b44SJordan Rupprecht self.clean_setup(location="multiple locals function") 15899451b44SJordan Rupprecht 159*2238dcc3SJonas Devlieghere self.expect("expr 1 + (int)2.0", substrs=["(int) $0"]) 16099451b44SJordan Rupprecht 16199451b44SJordan Rupprecht # This should not have loaded any decls. 16299451b44SJordan Rupprecht self.assert_no_decls_loaded() 16399451b44SJordan Rupprecht 16499451b44SJordan Rupprecht @add_test_categories(["dwarf"]) 16599451b44SJordan Rupprecht def test_printing_local_variable_in_other_struct_func(self): 16699451b44SJordan Rupprecht """ 16799451b44SJordan Rupprecht Prints a local variable and makes sure no unrelated types are loaded. 16899451b44SJordan Rupprecht """ 16999451b44SJordan Rupprecht self.clean_setup(location="other struct function") 17099451b44SJordan Rupprecht 171*2238dcc3SJonas Devlieghere self.expect("expr other_struct_var", substrs=["(OtherStruct) $0"]) 17299451b44SJordan Rupprecht # The decl we run on was loaded. 17399451b44SJordan Rupprecht self.assert_decl_loaded(self.other_struct_decl) 17499451b44SJordan Rupprecht 17599451b44SJordan Rupprecht # This should not have loaded anything else. 17699451b44SJordan Rupprecht self.assert_decl_not_loaded(self.some_struct_decl) 17799451b44SJordan Rupprecht self.assert_decl_not_loaded(self.class_in_namespace_decl) 17899451b44SJordan Rupprecht 17999451b44SJordan Rupprecht @add_test_categories(["dwarf"]) 18099451b44SJordan Rupprecht def test_printing_struct_with_multiple_locals(self): 18199451b44SJordan Rupprecht """ 18299451b44SJordan Rupprecht Prints a local variable and checks that we don't load other local 18399451b44SJordan Rupprecht variables. 18499451b44SJordan Rupprecht """ 18599451b44SJordan Rupprecht self.clean_setup(location="multiple locals function") 18699451b44SJordan Rupprecht 187*2238dcc3SJonas Devlieghere self.expect("expr struct_var", substrs=["(SomeStruct) $0"]) 18899451b44SJordan Rupprecht 18999451b44SJordan Rupprecht # We loaded SomeStruct and its member types for printing. 19099451b44SJordan Rupprecht self.assert_decl_loaded(self.some_struct_decl) 19199451b44SJordan Rupprecht self.assert_decl_loaded(self.struct_behind_ptr_decl) 19299451b44SJordan Rupprecht self.assert_decl_loaded(self.struct_behind_ref_decl) 19399451b44SJordan Rupprecht 19499451b44SJordan Rupprecht # FIXME: We don't use these variables, but we seem to load all local 19599451b44SJordan Rupprecht # local variables. 19699451b44SJordan Rupprecht self.assert_decl_not_completed(self.other_struct_decl) 19799451b44SJordan Rupprecht self.assert_decl_not_completed(self.class_in_namespace_decl) 19899451b44SJordan Rupprecht 19999451b44SJordan Rupprecht @add_test_categories(["dwarf"]) 20099451b44SJordan Rupprecht def test_addr_of_struct(self): 20199451b44SJordan Rupprecht """ 20299451b44SJordan Rupprecht Prints the address of a local variable (which is a struct). 20399451b44SJordan Rupprecht """ 20499451b44SJordan Rupprecht self.clean_setup(location="multiple locals function") 20599451b44SJordan Rupprecht 206*2238dcc3SJonas Devlieghere self.expect("expr &struct_var", substrs=["(SomeStruct *) $0"]) 20799451b44SJordan Rupprecht 20899451b44SJordan Rupprecht # We loaded SomeStruct. 20999451b44SJordan Rupprecht self.assert_decl_loaded(self.some_struct_decl) 21099451b44SJordan Rupprecht 21199451b44SJordan Rupprecht # The member declarations should not be completed. 21299451b44SJordan Rupprecht self.assert_decl_not_completed(self.struct_behind_ptr_decl) 21399451b44SJordan Rupprecht self.assert_decl_not_completed(self.struct_behind_ref_decl) 21499451b44SJordan Rupprecht 21599451b44SJordan Rupprecht # FIXME: The first member was behind a pointer so it shouldn't be 21699451b44SJordan Rupprecht # completed. Somehow LLDB really wants to load the first member, so 21799451b44SJordan Rupprecht # that is why have it defined here. 21899451b44SJordan Rupprecht self.assert_decl_loaded(self.struct_first_member_decl) 21999451b44SJordan Rupprecht 22099451b44SJordan Rupprecht # FIXME: We don't use these variables, but we seem to load all local 22199451b44SJordan Rupprecht # local variables. 22299451b44SJordan Rupprecht self.assert_decl_not_completed(self.other_struct_decl) 22399451b44SJordan Rupprecht self.assert_decl_not_completed(self.class_in_namespace_decl) 22499451b44SJordan Rupprecht 22599451b44SJordan Rupprecht @add_test_categories(["dwarf"]) 22699451b44SJordan Rupprecht def test_class_function_access_member(self): 22799451b44SJordan Rupprecht self.clean_setup(location="class function") 22899451b44SJordan Rupprecht 229*2238dcc3SJonas Devlieghere self.expect("expr member", substrs=["(ClassMember) $0"]) 23099451b44SJordan Rupprecht 23199451b44SJordan Rupprecht # We loaded the current class we touched. 23299451b44SJordan Rupprecht self.assert_decl_loaded(self.class_we_enter_decl) 23399451b44SJordan Rupprecht # We loaded the unused members of this class. 23499451b44SJordan Rupprecht self.assert_decl_loaded(self.unused_class_member_decl) 23599451b44SJordan Rupprecht self.assert_decl_not_completed(self.unused_class_member_ptr_decl) 23699451b44SJordan Rupprecht # We loaded the member we used. 23799451b44SJordan Rupprecht self.assert_decl_loaded(self.class_member_decl) 23834c697c8SRaphael Isemann # We didn't load the type of the unused static member. 23934c697c8SRaphael Isemann self.assert_decl_not_completed(self.class_static_member_decl) 24099451b44SJordan Rupprecht 24199451b44SJordan Rupprecht # This should not have loaded anything else. 24299451b44SJordan Rupprecht self.assert_decl_not_loaded(self.other_struct_decl) 24399451b44SJordan Rupprecht self.assert_decl_not_loaded(self.some_struct_decl) 24499451b44SJordan Rupprecht self.assert_decl_not_loaded(self.class_in_namespace_decl) 245