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