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 Rupprechtclass TestCase(TestBase): 1699451b44SJordan Rupprecht 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"] 42*34c697c8SRaphael 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) 59*34c697c8SRaphael 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() 6699451b44SJordan Rupprecht 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 """ 9199451b44SJordan Rupprecht return self.decl_in_line(line, decl) and not "<undeserialized declarations>" in line 9299451b44SJordan Rupprecht 9399451b44SJordan Rupprecht # The following asserts are used for checking if certain Clang declarations 9499451b44SJordan Rupprecht # were loaded or not since the target was created. 9599451b44SJordan Rupprecht 9699451b44SJordan Rupprecht def assert_decl_loaded(self, decl): 9799451b44SJordan Rupprecht """ 9899451b44SJordan Rupprecht Asserts the given decl is currently loaded. 9999451b44SJordan Rupprecht Note: This test is about checking that types/declarations are not 10099451b44SJordan Rupprecht loaded. If this assert fails it is usually fine to turn it into a 10199451b44SJordan Rupprecht assert_decl_not_loaded or assert_decl_not_completed assuming LLDB's 10299451b44SJordan Rupprecht functionality has not suffered by not loading this declaration. 10399451b44SJordan Rupprecht """ 10499451b44SJordan Rupprecht ast = self.get_ast_dump() 10599451b44SJordan Rupprecht found = False 10699451b44SJordan Rupprecht for line in ast.splitlines(): 10799451b44SJordan Rupprecht if self.decl_in_line(line, decl): 10899451b44SJordan Rupprecht found = True 10999451b44SJordan Rupprecht self.assertTrue(self.decl_completed_in_line(line, decl), 11099451b44SJordan Rupprecht "Should have called assert_decl_not_completed") 11199451b44SJordan Rupprecht self.assertTrue(found, "Declaration no longer loaded " + str(decl) + 11299451b44SJordan Rupprecht ".\nAST:\n" + ast) 11399451b44SJordan Rupprecht 11499451b44SJordan Rupprecht def assert_decl_not_completed(self, decl): 11599451b44SJordan Rupprecht """ 11699451b44SJordan Rupprecht Asserts that the given decl is currently not completed in the module's 11799451b44SJordan Rupprecht AST. It may be loaded but then can can only contain undeserialized 11899451b44SJordan Rupprecht declarations. 11999451b44SJordan Rupprecht """ 12099451b44SJordan Rupprecht ast = self.get_ast_dump() 12199451b44SJordan Rupprecht found = False 12299451b44SJordan Rupprecht for line in ast.splitlines(): 12399451b44SJordan Rupprecht error_msg = "Unexpected completed decl: '" + line + "'.\nAST:\n" + ast 12499451b44SJordan Rupprecht self.assertFalse(self.decl_completed_in_line(line, decl), error_msg) 12599451b44SJordan Rupprecht 12699451b44SJordan Rupprecht def assert_decl_not_loaded(self, decl): 12799451b44SJordan Rupprecht """ 12899451b44SJordan Rupprecht Asserts that the given decl is currently not loaded in the module's 12999451b44SJordan Rupprecht AST. 13099451b44SJordan Rupprecht """ 13199451b44SJordan Rupprecht ast = self.get_ast_dump() 13299451b44SJordan Rupprecht found = False 13399451b44SJordan Rupprecht for line in ast.splitlines(): 13499451b44SJordan Rupprecht error_msg = "Unexpected loaded decl: '" + line + "'\nAST:\n" + ast 13599451b44SJordan Rupprecht self.assertFalse(self.decl_in_line(line, decl), error_msg) 13699451b44SJordan Rupprecht 13799451b44SJordan Rupprecht 13899451b44SJordan Rupprecht def clean_setup(self, location): 13999451b44SJordan Rupprecht """ 14099451b44SJordan Rupprecht Runs to the line with the source line with the given location string 14199451b44SJordan Rupprecht and ensures that our module AST is empty. 14299451b44SJordan Rupprecht """ 14399451b44SJordan Rupprecht lldbutil.run_to_source_breakpoint(self, 14499451b44SJordan Rupprecht "// Location: " + location, lldb.SBFileSpec("main.cpp")) 14599451b44SJordan Rupprecht # Make sure no declarations are loaded initially. 14699451b44SJordan Rupprecht self.assert_no_decls_loaded() 14799451b44SJordan Rupprecht 14899451b44SJordan Rupprecht @add_test_categories(["dwarf"]) 14999451b44SJordan Rupprecht def test_arithmetic_expression_in_main(self): 15099451b44SJordan Rupprecht """ Runs a simple arithmetic expression which should load nothing. """ 15199451b44SJordan Rupprecht self.clean_setup(location="multiple locals function") 15299451b44SJordan Rupprecht 15399451b44SJordan Rupprecht self.expect("expr 1 + (int)2.0", substrs=['(int) $0']) 15499451b44SJordan Rupprecht 15599451b44SJordan Rupprecht # This should not have loaded any decls. 15699451b44SJordan Rupprecht self.assert_no_decls_loaded() 15799451b44SJordan Rupprecht 15899451b44SJordan Rupprecht @add_test_categories(["dwarf"]) 15999451b44SJordan Rupprecht def test_printing_local_variable_in_other_struct_func(self): 16099451b44SJordan Rupprecht """ 16199451b44SJordan Rupprecht Prints a local variable and makes sure no unrelated types are loaded. 16299451b44SJordan Rupprecht """ 16399451b44SJordan Rupprecht self.clean_setup(location="other struct function") 16499451b44SJordan Rupprecht 16599451b44SJordan Rupprecht self.expect("expr other_struct_var", substrs=['(OtherStruct) $0']) 16699451b44SJordan Rupprecht # The decl we run on was loaded. 16799451b44SJordan Rupprecht self.assert_decl_loaded(self.other_struct_decl) 16899451b44SJordan Rupprecht 16999451b44SJordan Rupprecht # This should not have loaded anything else. 17099451b44SJordan Rupprecht self.assert_decl_not_loaded(self.some_struct_decl) 17199451b44SJordan Rupprecht self.assert_decl_not_loaded(self.class_in_namespace_decl) 17299451b44SJordan Rupprecht 17399451b44SJordan Rupprecht @add_test_categories(["dwarf"]) 17499451b44SJordan Rupprecht def test_printing_struct_with_multiple_locals(self): 17599451b44SJordan Rupprecht """ 17699451b44SJordan Rupprecht Prints a local variable and checks that we don't load other local 17799451b44SJordan Rupprecht variables. 17899451b44SJordan Rupprecht """ 17999451b44SJordan Rupprecht self.clean_setup(location="multiple locals function") 18099451b44SJordan Rupprecht 18199451b44SJordan Rupprecht self.expect("expr struct_var", substrs=['(SomeStruct) $0']) 18299451b44SJordan Rupprecht 18399451b44SJordan Rupprecht # We loaded SomeStruct and its member types for printing. 18499451b44SJordan Rupprecht self.assert_decl_loaded(self.some_struct_decl) 18599451b44SJordan Rupprecht self.assert_decl_loaded(self.struct_behind_ptr_decl) 18699451b44SJordan Rupprecht self.assert_decl_loaded(self.struct_behind_ref_decl) 18799451b44SJordan Rupprecht 18899451b44SJordan Rupprecht # FIXME: We don't use these variables, but we seem to load all local 18999451b44SJordan Rupprecht # local variables. 19099451b44SJordan Rupprecht self.assert_decl_not_completed(self.other_struct_decl) 19199451b44SJordan Rupprecht self.assert_decl_not_completed(self.class_in_namespace_decl) 19299451b44SJordan Rupprecht 19399451b44SJordan Rupprecht @add_test_categories(["dwarf"]) 19499451b44SJordan Rupprecht def test_addr_of_struct(self): 19599451b44SJordan Rupprecht """ 19699451b44SJordan Rupprecht Prints the address of a local variable (which is a struct). 19799451b44SJordan Rupprecht """ 19899451b44SJordan Rupprecht self.clean_setup(location="multiple locals function") 19999451b44SJordan Rupprecht 20099451b44SJordan Rupprecht self.expect("expr &struct_var", substrs=['(SomeStruct *) $0']) 20199451b44SJordan Rupprecht 20299451b44SJordan Rupprecht # We loaded SomeStruct. 20399451b44SJordan Rupprecht self.assert_decl_loaded(self.some_struct_decl) 20499451b44SJordan Rupprecht 20599451b44SJordan Rupprecht # The member declarations should not be completed. 20699451b44SJordan Rupprecht self.assert_decl_not_completed(self.struct_behind_ptr_decl) 20799451b44SJordan Rupprecht self.assert_decl_not_completed(self.struct_behind_ref_decl) 20899451b44SJordan Rupprecht 20999451b44SJordan Rupprecht # FIXME: The first member was behind a pointer so it shouldn't be 21099451b44SJordan Rupprecht # completed. Somehow LLDB really wants to load the first member, so 21199451b44SJordan Rupprecht # that is why have it defined here. 21299451b44SJordan Rupprecht self.assert_decl_loaded(self.struct_first_member_decl) 21399451b44SJordan Rupprecht 21499451b44SJordan Rupprecht # FIXME: We don't use these variables, but we seem to load all local 21599451b44SJordan Rupprecht # local variables. 21699451b44SJordan Rupprecht self.assert_decl_not_completed(self.other_struct_decl) 21799451b44SJordan Rupprecht self.assert_decl_not_completed(self.class_in_namespace_decl) 21899451b44SJordan Rupprecht 21999451b44SJordan Rupprecht @add_test_categories(["dwarf"]) 22099451b44SJordan Rupprecht def test_class_function_access_member(self): 22199451b44SJordan Rupprecht self.clean_setup(location="class function") 22299451b44SJordan Rupprecht 22399451b44SJordan Rupprecht self.expect("expr member", substrs=['(ClassMember) $0']) 22499451b44SJordan Rupprecht 22599451b44SJordan Rupprecht # We loaded the current class we touched. 22699451b44SJordan Rupprecht self.assert_decl_loaded(self.class_we_enter_decl) 22799451b44SJordan Rupprecht # We loaded the unused members of this class. 22899451b44SJordan Rupprecht self.assert_decl_loaded(self.unused_class_member_decl) 22999451b44SJordan Rupprecht self.assert_decl_not_completed(self.unused_class_member_ptr_decl) 23099451b44SJordan Rupprecht # We loaded the member we used. 23199451b44SJordan Rupprecht self.assert_decl_loaded(self.class_member_decl) 232*34c697c8SRaphael Isemann # We didn't load the type of the unused static member. 233*34c697c8SRaphael Isemann self.assert_decl_not_completed(self.class_static_member_decl) 23499451b44SJordan Rupprecht 23599451b44SJordan Rupprecht # This should not have loaded anything else. 23699451b44SJordan Rupprecht self.assert_decl_not_loaded(self.other_struct_decl) 23799451b44SJordan Rupprecht self.assert_decl_not_loaded(self.some_struct_decl) 23899451b44SJordan Rupprecht self.assert_decl_not_loaded(self.class_in_namespace_decl) 23999451b44SJordan Rupprecht 240