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