1from lldbsuite.test.decorators import *
2from lldbsuite.test.lldbtest import *
3from lldbsuite.test import lldbutil
4
5"""
6This test ensures that we only create Clang AST nodes in our module AST
7when we actually need them.
8
9All tests in this file behave like this:
10  1. Use LLDB to do something (expression evaluation, breakpoint setting, etc.).
11  2. Check that certain Clang AST nodes were not loaded during the previous
12     step.
13"""
14
15class TestCase(TestBase):
16
17    NO_DEBUG_INFO_TESTCASE = True
18    mydir = TestBase.compute_mydir(__file__)
19
20    def setUp(self):
21      TestBase.setUp(self)
22      # Only build this test once.
23      self.build()
24
25    # Clang declaration kind we are looking for.
26    class_decl_kind = "CXXRecordDecl"
27    # FIXME: This shouldn't be a CXXRecordDecl, but that's how we model
28    # structs in Clang.
29    struct_decl_kind = "CXXRecordDecl"
30
31    # The decls we use in this program in the format that
32    # decl_in_line and decl_completed_in_line expect (which is a pair of
33    # node type and the unqualified declaration name.
34    struct_first_member_decl = [struct_decl_kind, "StructFirstMember"]
35    struct_behind_ptr_decl = [struct_decl_kind, "StructBehindPointer"]
36    struct_behind_ref_decl = [struct_decl_kind, "StructBehindRef"]
37    struct_member_decl = [struct_decl_kind, "StructMember"]
38    some_struct_decl = [struct_decl_kind, "SomeStruct"]
39    other_struct_decl = [struct_decl_kind, "OtherStruct"]
40    class_in_namespace_decl = [class_decl_kind, "ClassInNamespace"]
41    class_we_enter_decl = [class_decl_kind, "ClassWeEnter"]
42    class_member_decl = [struct_decl_kind, "ClassMember"]
43    unused_class_member_decl = [struct_decl_kind, "UnusedClassMember"]
44    unused_class_member_ptr_decl = [struct_decl_kind, "UnusedClassMemberPtr"]
45
46    def assert_no_decls_loaded(self):
47        """
48        Asserts that no known declarations in this test are loaded
49        into the module's AST.
50        """
51        self.assert_decl_not_loaded(self.struct_first_member_decl)
52        self.assert_decl_not_loaded(self.struct_behind_ptr_decl)
53        self.assert_decl_not_loaded(self.struct_behind_ref_decl)
54        self.assert_decl_not_loaded(self.struct_member_decl)
55        self.assert_decl_not_loaded(self.some_struct_decl)
56        self.assert_decl_not_loaded(self.other_struct_decl)
57        self.assert_decl_not_loaded(self.class_in_namespace_decl)
58        self.assert_decl_not_loaded(self.class_member_decl)
59        self.assert_decl_not_loaded(self.unused_class_member_decl)
60
61    def get_ast_dump(self):
62        """Returns the dumped Clang AST of the module as a string"""
63        res = lldb.SBCommandReturnObject()
64        ci = self.dbg.GetCommandInterpreter()
65        ci.HandleCommand('target modules dump ast a.out', res)
66        self.assertTrue(res.Succeeded())
67        return res.GetOutput()
68
69    def decl_in_line(self, line, decl):
70        """
71        Returns true iff the given line declares the given Clang decl.
72        The line is expected to be in the form of Clang's AST dump.
73        """
74        line = line.rstrip() + "\n"
75        decl_kind = "-" + decl[0] + " "
76        # Either the decl is somewhere in the line or at the end of
77        # the line.
78        decl_name = " " + decl[1] + " "
79        decl_name_eol = " " + decl[1] + "\n"
80        if not decl_kind in line:
81          return False
82        return decl_name in line or decl_name_eol in line
83
84    def decl_completed_in_line(self, line, decl):
85        """
86        Returns true iff the given line declares the given Clang decl and
87        the decl was completed (i.e., it has no undeserialized declarations
88        in it).
89        """
90        return self.decl_in_line(line, decl) and not "<undeserialized declarations>" in line
91
92    # The following asserts are used for checking if certain Clang declarations
93    # were loaded or not since the target was created.
94
95    def assert_decl_loaded(self, decl):
96        """
97        Asserts the given decl is currently loaded.
98        Note: This test is about checking that types/declarations are not
99        loaded. If this assert fails it is usually fine to turn it into a
100        assert_decl_not_loaded or assert_decl_not_completed assuming LLDB's
101        functionality has not suffered by not loading this declaration.
102        """
103        ast = self.get_ast_dump()
104        found = False
105        for line in ast.splitlines():
106          if self.decl_in_line(line, decl):
107            found = True
108            self.assertTrue(self.decl_completed_in_line(line, decl),
109                            "Should have called assert_decl_not_completed")
110        self.assertTrue(found, "Declaration no longer loaded " + str(decl) +
111            ".\nAST:\n" + ast)
112
113    def assert_decl_not_completed(self, decl):
114        """
115        Asserts that the given decl is currently not completed in the module's
116        AST. It may be loaded but then can can only contain undeserialized
117        declarations.
118        """
119        ast = self.get_ast_dump()
120        found = False
121        for line in ast.splitlines():
122          error_msg = "Unexpected completed decl: '" + line + "'.\nAST:\n" + ast
123          self.assertFalse(self.decl_completed_in_line(line, decl), error_msg)
124
125    def assert_decl_not_loaded(self, decl):
126        """
127        Asserts that the given decl is currently not loaded in the module's
128        AST.
129        """
130        ast = self.get_ast_dump()
131        found = False
132        for line in ast.splitlines():
133          error_msg = "Unexpected loaded decl: '" + line + "'\nAST:\n" + ast
134          self.assertFalse(self.decl_in_line(line, decl), error_msg)
135
136
137    def clean_setup(self, location):
138        """
139        Runs to the line with the source line with the given location string
140        and ensures that our module AST is empty.
141        """
142        lldbutil.run_to_source_breakpoint(self,
143            "// Location: " + location, lldb.SBFileSpec("main.cpp"))
144        # Make sure no declarations are loaded initially.
145        self.assert_no_decls_loaded()
146
147    @add_test_categories(["dwarf"])
148    def test_arithmetic_expression_in_main(self):
149        """ Runs a simple arithmetic expression which should load nothing. """
150        self.clean_setup(location="multiple locals function")
151
152        self.expect("expr 1 + (int)2.0", substrs=['(int) $0'])
153
154        # This should not have loaded any decls.
155        self.assert_no_decls_loaded()
156
157    @add_test_categories(["dwarf"])
158    def test_printing_local_variable_in_other_struct_func(self):
159        """
160        Prints a local variable and makes sure no unrelated types are loaded.
161        """
162        self.clean_setup(location="other struct function")
163
164        self.expect("expr other_struct_var", substrs=['(OtherStruct) $0'])
165        # The decl we run on was loaded.
166        self.assert_decl_loaded(self.other_struct_decl)
167
168        # This should not have loaded anything else.
169        self.assert_decl_not_loaded(self.some_struct_decl)
170        self.assert_decl_not_loaded(self.class_in_namespace_decl)
171
172    @add_test_categories(["dwarf"])
173    def test_printing_struct_with_multiple_locals(self):
174        """
175        Prints a local variable and checks that we don't load other local
176        variables.
177        """
178        self.clean_setup(location="multiple locals function")
179
180        self.expect("expr struct_var", substrs=['(SomeStruct) $0'])
181
182        # We loaded SomeStruct and its member types for printing.
183        self.assert_decl_loaded(self.some_struct_decl)
184        self.assert_decl_loaded(self.struct_behind_ptr_decl)
185        self.assert_decl_loaded(self.struct_behind_ref_decl)
186
187        # FIXME: We don't use these variables, but we seem to load all local
188        # local variables.
189        self.assert_decl_not_completed(self.other_struct_decl)
190        self.assert_decl_not_completed(self.class_in_namespace_decl)
191
192    @add_test_categories(["dwarf"])
193    def test_addr_of_struct(self):
194        """
195        Prints the address of a local variable (which is a struct).
196        """
197        self.clean_setup(location="multiple locals function")
198
199        self.expect("expr &struct_var", substrs=['(SomeStruct *) $0'])
200
201        # We loaded SomeStruct.
202        self.assert_decl_loaded(self.some_struct_decl)
203
204        # The member declarations should not be completed.
205        self.assert_decl_not_completed(self.struct_behind_ptr_decl)
206        self.assert_decl_not_completed(self.struct_behind_ref_decl)
207
208        # FIXME: The first member was behind a pointer so it shouldn't be
209        # completed. Somehow LLDB really wants to load the first member, so
210        # that is why have it defined here.
211        self.assert_decl_loaded(self.struct_first_member_decl)
212
213        # FIXME: We don't use these variables, but we seem to load all local
214        # local variables.
215        self.assert_decl_not_completed(self.other_struct_decl)
216        self.assert_decl_not_completed(self.class_in_namespace_decl)
217
218    @add_test_categories(["dwarf"])
219    def test_class_function_access_member(self):
220        self.clean_setup(location="class function")
221
222        self.expect("expr member", substrs=['(ClassMember) $0'])
223
224        # We loaded the current class we touched.
225        self.assert_decl_loaded(self.class_we_enter_decl)
226        # We loaded the unused members of this class.
227        self.assert_decl_loaded(self.unused_class_member_decl)
228        self.assert_decl_not_completed(self.unused_class_member_ptr_decl)
229        # We loaded the member we used.
230        self.assert_decl_loaded(self.class_member_decl)
231
232        # This should not have loaded anything else.
233        self.assert_decl_not_loaded(self.other_struct_decl)
234        self.assert_decl_not_loaded(self.some_struct_decl)
235        self.assert_decl_not_loaded(self.class_in_namespace_decl)
236
237