1""" 2This tests LLDB's ability to merge structs into the shared per-target Clang 3ASTContext. 4 5This just focuses on indirect imports (i.e., a declaration gets imported from 6the lldb::Module AST into the expression AST and then the declaration gets 7imported to the scratch AST because it is part of the ValueObject type of the 8result) and direct imports (i.e., a declaration gets directly imported from a 9lldb::Module AST to the scratch AST, e.g., via 'frame var'). 10""" 11 12import lldb 13from lldbsuite.test.decorators import * 14from lldbsuite.test.lldbtest import * 15from lldbsuite.test import lldbutil 16 17 18class TestCase(TestBase): 19 def common_setup(self): 20 self.build() 21 lldbutil.run_to_source_breakpoint( 22 self, "// break here", lldb.SBFileSpec("main.cpp") 23 ) 24 25 def do_pass(self, kind, var, expected_type, expected_children): 26 if kind == "expression": 27 self.expect_expr( 28 var, result_type=expected_type, result_children=expected_children 29 ) 30 elif kind == "path": 31 self.expect_var_path(var, type=expected_type, children=expected_children) 32 else: 33 self.fail("Unknown var evaluation kind: " + var) 34 35 def pull_in_and_merge(self, var, type, children): 36 """ 37 Pulls in the specified variable into the scratch AST. Afterwards tries 38 merging the declaration. The method of pulling the declaration into the 39 scratch AST is defined by the first_pass/second_pass instance variables. 40 """ 41 42 # This pulls in the declaration into the scratch AST. 43 self.do_pass(self.first_pass, var, type, children) 44 # This pulls in the declaration a second time and forces us to merge with 45 # the existing declaration (or reuse the existing declaration). 46 self.do_pass(self.second_pass, var, type, children) 47 48 def do_tests(self): 49 """Just forwards all the variables/types/childrens to pull_in_and_merge.""" 50 self.pull_in_and_merge( 51 "decl_in_func", type="DeclInFunc", children=[ValueCheck(name="member")] 52 ) 53 self.pull_in_and_merge( 54 "top_level_struct", 55 type="TopLevelStruct", 56 children=[ValueCheck(name="member")], 57 ) 58 self.pull_in_and_merge( 59 "inner_struct", 60 type="OuterStruct::InnerStruct", 61 children=[ValueCheck(name="member")], 62 ) 63 self.pull_in_and_merge( 64 "typedef_struct", 65 type="TypedefStruct", 66 children=[ValueCheck(name="member")], 67 ) 68 self.pull_in_and_merge( 69 "namespace_struct", 70 type="NS::NamespaceStruct", 71 children=[ValueCheck(name="member")], 72 ) 73 self.pull_in_and_merge( 74 "unnamed_namespace_struct", 75 type="UnnamedNamespaceStruct", 76 children=[ValueCheck(name="member")], 77 ) 78 self.pull_in_and_merge( 79 "extern_c_struct", 80 type="ExternCStruct", 81 children=[ValueCheck(name="member")], 82 ) 83 84 @no_debug_info_test 85 def test_direct_and_indirect(self): 86 """ 87 First variable paths pull in a declaration directly. Then the expression 88 evaluator pulls the declaration in indirectly. 89 """ 90 self.common_setup() 91 self.first_pass = "path" 92 self.second_pass = "expression" 93 self.do_tests() 94 95 @no_debug_info_test 96 def test_indirect_and_indirect(self): 97 """ 98 The expression evaluator pulls in the declaration indirectly and then 99 repeat that process. 100 """ 101 self.common_setup() 102 self.first_pass = "expression" 103 self.second_pass = "expression" 104 self.do_tests() 105 106 @no_debug_info_test 107 def test_indirect_and_direct(self): 108 """ 109 The expression evaluator pulls in the declaration indirectly and then 110 variable paths pull it in directly. 111 """ 112 self.common_setup() 113 self.first_pass = "expression" 114 self.second_pass = "path" 115 self.do_tests() 116 117 @no_debug_info_test 118 def test_direct_and_direct(self): 119 """ 120 Variable paths pulls in the declaration indirectly and then repeat that 121 process. 122 """ 123 self.common_setup() 124 self.first_pass = "path" 125 self.second_pass = "path" 126 self.do_tests() 127