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