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 20 mydir = TestBase.compute_mydir(__file__) 21 22 def common_setup(self): 23 self.build() 24 lldbutil.run_to_source_breakpoint( 25 self, "// break here", lldb.SBFileSpec("main.cpp") 26 ) 27 28 def do_pass(self, kind, var, expected_type, expected_children): 29 if kind == "expression": 30 self.expect_expr( 31 var, result_type=expected_type, result_children=expected_children 32 ) 33 elif kind == "path": 34 self.expect_var_path(var, type=expected_type, children=expected_children) 35 else: 36 self.fail("Unknown var evaluation kind: " + var) 37 38 def pull_in_and_merge(self, var, type, children): 39 """ 40 Pulls in the specified variable into the scratch AST. Afterwards tries 41 merging the declaration. The method of pulling the declaration into the 42 scratch AST is defined by the first_pass/second_pass instance variables. 43 """ 44 45 # This pulls in the declaration into the scratch AST. 46 self.do_pass(self.first_pass, var, type, children) 47 # This pulls in the declaration a second time and forces us to merge with 48 # the existing declaration (or reuse the existing declaration). 49 self.do_pass(self.second_pass, var, type, children) 50 51 def do_tests(self): 52 """ Just forwards all the variables/types/childrens to pull_in_and_merge. """ 53 self.pull_in_and_merge( 54 "decl_in_func", type="DeclInFunc", children=[ValueCheck(name="member")] 55 ) 56 self.pull_in_and_merge( 57 "top_level_struct", 58 type="TopLevelStruct", 59 children=[ValueCheck(name="member")], 60 ) 61 self.pull_in_and_merge( 62 "inner_struct", 63 type="OuterStruct::InnerStruct", 64 children=[ValueCheck(name="member")], 65 ) 66 self.pull_in_and_merge( 67 "typedef_struct", 68 type="TypedefStruct", 69 children=[ValueCheck(name="member")], 70 ) 71 self.pull_in_and_merge( 72 "namespace_struct", 73 type="NS::NamespaceStruct", 74 children=[ValueCheck(name="member")], 75 ) 76 self.pull_in_and_merge( 77 "unnamed_namespace_struct", 78 type="UnnamedNamespaceStruct", 79 children=[ValueCheck(name="member")], 80 ) 81 self.pull_in_and_merge( 82 "extern_c_struct", 83 type="ExternCStruct", 84 children=[ValueCheck(name="member")], 85 ) 86 87 @no_debug_info_test 88 def test_direct_and_indirect(self): 89 """ 90 First variable paths pull in a declaration directly. Then the expression 91 evaluator pulls the declaration in indirectly. 92 """ 93 self.common_setup() 94 self.first_pass = "path" 95 self.second_pass = "expression" 96 self.do_tests() 97 98 @no_debug_info_test 99 def test_indirect_and_indirect(self): 100 """ 101 The expression evaluator pulls in the declaration indirectly and then 102 repeat that process. 103 """ 104 self.common_setup() 105 self.first_pass = "expression" 106 self.second_pass = "expression" 107 self.do_tests() 108 109 @no_debug_info_test 110 def test_indirect_and_direct(self): 111 """ 112 The expression evaluator pulls in the declaration indirectly and then 113 variable paths pull it in directly. 114 """ 115 self.common_setup() 116 self.first_pass = "expression" 117 self.second_pass = "path" 118 self.do_tests() 119 120 @no_debug_info_test 121 def test_direct_and_direct(self): 122 """ 123 Variable paths pulls in the declaration indirectly and then repeat that 124 process. 125 """ 126 self.common_setup() 127 self.first_pass = "path" 128 self.second_pass = "path" 129 self.do_tests() 130