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