128 lines
4.3 KiB
Python
128 lines
4.3 KiB
Python
"""
|
|
This tests LLDB's ability to merge structs into the shared per-target Clang
|
|
ASTContext.
|
|
|
|
This just focuses on indirect imports (i.e., a declaration gets imported from
|
|
the lldb::Module AST into the expression AST and then the declaration gets
|
|
imported to the scratch AST because it is part of the ValueObject type of the
|
|
result) and direct imports (i.e., a declaration gets directly imported from a
|
|
lldb::Module AST to the scratch AST, e.g., via 'frame var').
|
|
"""
|
|
|
|
import lldb
|
|
from lldbsuite.test.decorators import *
|
|
from lldbsuite.test.lldbtest import *
|
|
from lldbsuite.test import lldbutil
|
|
|
|
|
|
class TestCase(TestBase):
|
|
|
|
def common_setup(self):
|
|
self.build()
|
|
lldbutil.run_to_source_breakpoint(
|
|
self, "// break here", lldb.SBFileSpec("main.cpp")
|
|
)
|
|
|
|
def do_pass(self, kind, var, expected_type, expected_children):
|
|
if kind == "expression":
|
|
self.expect_expr(
|
|
var, result_type=expected_type, result_children=expected_children
|
|
)
|
|
elif kind == "path":
|
|
self.expect_var_path(var, type=expected_type, children=expected_children)
|
|
else:
|
|
self.fail("Unknown var evaluation kind: " + var)
|
|
|
|
def pull_in_and_merge(self, var, type, children):
|
|
"""
|
|
Pulls in the specified variable into the scratch AST. Afterwards tries
|
|
merging the declaration. The method of pulling the declaration into the
|
|
scratch AST is defined by the first_pass/second_pass instance variables.
|
|
"""
|
|
|
|
# This pulls in the declaration into the scratch AST.
|
|
self.do_pass(self.first_pass, var, type, children)
|
|
# This pulls in the declaration a second time and forces us to merge with
|
|
# the existing declaration (or reuse the existing declaration).
|
|
self.do_pass(self.second_pass, var, type, children)
|
|
|
|
def do_tests(self):
|
|
""" Just forwards all the variables/types/childrens to pull_in_and_merge. """
|
|
self.pull_in_and_merge(
|
|
"decl_in_func", type="DeclInFunc", children=[ValueCheck(name="member")]
|
|
)
|
|
self.pull_in_and_merge(
|
|
"top_level_struct",
|
|
type="TopLevelStruct",
|
|
children=[ValueCheck(name="member")],
|
|
)
|
|
self.pull_in_and_merge(
|
|
"inner_struct",
|
|
type="OuterStruct::InnerStruct",
|
|
children=[ValueCheck(name="member")],
|
|
)
|
|
self.pull_in_and_merge(
|
|
"typedef_struct",
|
|
type="TypedefStruct",
|
|
children=[ValueCheck(name="member")],
|
|
)
|
|
self.pull_in_and_merge(
|
|
"namespace_struct",
|
|
type="NS::NamespaceStruct",
|
|
children=[ValueCheck(name="member")],
|
|
)
|
|
self.pull_in_and_merge(
|
|
"unnamed_namespace_struct",
|
|
type="UnnamedNamespaceStruct",
|
|
children=[ValueCheck(name="member")],
|
|
)
|
|
self.pull_in_and_merge(
|
|
"extern_c_struct",
|
|
type="ExternCStruct",
|
|
children=[ValueCheck(name="member")],
|
|
)
|
|
|
|
@no_debug_info_test
|
|
def test_direct_and_indirect(self):
|
|
"""
|
|
First variable paths pull in a declaration directly. Then the expression
|
|
evaluator pulls the declaration in indirectly.
|
|
"""
|
|
self.common_setup()
|
|
self.first_pass = "path"
|
|
self.second_pass = "expression"
|
|
self.do_tests()
|
|
|
|
@no_debug_info_test
|
|
def test_indirect_and_indirect(self):
|
|
"""
|
|
The expression evaluator pulls in the declaration indirectly and then
|
|
repeat that process.
|
|
"""
|
|
self.common_setup()
|
|
self.first_pass = "expression"
|
|
self.second_pass = "expression"
|
|
self.do_tests()
|
|
|
|
@no_debug_info_test
|
|
def test_indirect_and_direct(self):
|
|
"""
|
|
The expression evaluator pulls in the declaration indirectly and then
|
|
variable paths pull it in directly.
|
|
"""
|
|
self.common_setup()
|
|
self.first_pass = "expression"
|
|
self.second_pass = "path"
|
|
self.do_tests()
|
|
|
|
@no_debug_info_test
|
|
def test_direct_and_direct(self):
|
|
"""
|
|
Variable paths pulls in the declaration indirectly and then repeat that
|
|
process.
|
|
"""
|
|
self.common_setup()
|
|
self.first_pass = "path"
|
|
self.second_pass = "path"
|
|
self.do_tests()
|