1"""
2Test completing types using information from other shared libraries.
3"""
4
5import os
6import lldb
7from lldbsuite.test.decorators import *
8from lldbsuite.test.lldbtest import *
9from lldbsuite.test import lldbutil
10
11
12class LimitDebugInfoTestCase(TestBase):
13
14    def _check_type(self, target, name):
15        exe = target.FindModule(lldb.SBFileSpec("a.out"))
16        type_ = exe.FindFirstType(name)
17        self.trace("type_: %s"%type_)
18        self.assertTrue(type_)
19        base = type_.GetDirectBaseClassAtIndex(0).GetType()
20        self.trace("base:%s"%base)
21        self.assertTrue(base)
22        self.assertEquals(base.GetNumberOfFields(), 0)
23
24    def _check_debug_info_is_limited(self, target):
25        # Without other shared libraries we should only see the member declared
26        # in the derived class. This serves as a sanity check that we are truly
27        # building with limited debug info.
28        self._check_type(target, "InheritsFromOne")
29        self._check_type(target, "InheritsFromTwo")
30
31    @skipIf(bugnumber="pr46284", debug_info="gmodules")
32    @skipIfWindows # Clang emits type info even with -flimit-debug-info
33    # Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call
34    # by-value functions.
35    @skipIf(compiler="clang", compiler_version=['<', '7.0'])
36    def test_one_and_two_debug(self):
37        self.build()
38        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
39
40        self._check_debug_info_is_limited(target)
41
42        lldbutil.run_to_name_breakpoint(self, "main",
43                extra_images=["one", "two"])
44
45        # But when other shared libraries are loaded, we should be able to see
46        # all members.
47        self.expect_expr("inherits_from_one.member", result_value="47")
48        self.expect_expr("inherits_from_one.one", result_value="142")
49        self.expect_expr("inherits_from_two.member", result_value="47")
50        self.expect_expr("inherits_from_two.one", result_value="142")
51        self.expect_expr("inherits_from_two.two", result_value="242")
52
53        self.expect_expr("one_as_member.member", result_value="47")
54        self.expect_expr("one_as_member.one.member", result_value="147")
55        self.expect_expr("two_as_member.member", result_value="47")
56        self.expect_expr("two_as_member.two.one.member", result_value="147")
57        self.expect_expr("two_as_member.two.member", result_value="247")
58
59        self.expect_expr("array_of_one[2].member", result_value="174")
60        self.expect_expr("array_of_two[2].one[2].member", result_value="174")
61        self.expect_expr("array_of_two[2].member", result_value="274")
62
63        self.expect_expr("get_one().member", result_value="124")
64        self.expect_expr("get_two().one().member", result_value="124")
65        self.expect_expr("get_two().member", result_value="224")
66
67        self.expect_expr("shadowed_one.member", result_value="47")
68        self.expect_expr("shadowed_one.one", result_value="142")
69
70    @skipIf(bugnumber="pr46284", debug_info="gmodules")
71    @skipIfWindows # Clang emits type info even with -flimit-debug-info
72    # Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call
73    # by-value functions.
74    @skipIf(compiler="clang", compiler_version=['<', '7.0'])
75    def test_two_debug(self):
76        self.build(dictionary=dict(STRIP_ONE="1"))
77        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
78
79        self._check_debug_info_is_limited(target)
80
81        lldbutil.run_to_name_breakpoint(self, "main",
82                extra_images=["one", "two"])
83
84        # This time, we should only see the members from the second library.
85        self.expect_expr("inherits_from_one.member", result_value="47")
86        self.expect("expr inherits_from_one.one", error=True,
87            substrs=["no member named 'one' in 'InheritsFromOne'"])
88        self.expect_expr("inherits_from_two.member", result_value="47")
89        self.expect("expr inherits_from_two.one", error=True,
90            substrs=["no member named 'one' in 'InheritsFromTwo'"])
91        self.expect_expr("inherits_from_two.two", result_value="242")
92
93        self.expect_expr("one_as_member.member", result_value="47")
94        self.expect("expr one_as_member.one.member", error=True,
95                substrs=["no member named 'member' in 'member::One'"])
96        self.expect_expr("two_as_member.member", result_value="47")
97        self.expect("expr two_as_member.two.one.member", error=True,
98                substrs=["no member named 'member' in 'member::One'"])
99        self.expect_expr("two_as_member.two.member", result_value="247")
100
101        self.expect("expr array_of_one[2].member", error=True,
102                substrs=["no member named 'member' in 'array::One'"])
103        self.expect("expr array_of_two[2].one[2].member", error=True,
104                substrs=["no member named 'member' in 'array::One'"])
105        self.expect_expr("array_of_two[2].member", result_value="274")
106
107        self.expect("expr get_one().member", error=True,
108                substrs=["calling 'get_one' with incomplete return type 'result::One'"])
109        self.expect("expr get_two().one().member", error=True,
110                substrs=["calling 'one' with incomplete return type 'result::One'"])
111        self.expect_expr("get_two().member", result_value="224")
112
113    @skipIf(bugnumber="pr46284", debug_info="gmodules")
114    @skipIfWindows # Clang emits type info even with -flimit-debug-info
115    # Requires DW_CC_pass_by_* attributes from Clang 7 to correctly call
116    # by-value functions.
117    @skipIf(compiler="clang", compiler_version=['<', '7.0'])
118    def test_one_debug(self):
119        self.build(dictionary=dict(STRIP_TWO="1"))
120        target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
121
122        self._check_debug_info_is_limited(target)
123
124        lldbutil.run_to_name_breakpoint(self, "main",
125                extra_images=["one", "two"])
126
127        # In this case we should only see the members from the second library.
128        # Note that we cannot see inherits_from_two.one because without debug
129        # info for "Two", we cannot determine that it in fact inherits from
130        # "One".
131        self.expect_expr("inherits_from_one.member", result_value="47")
132        self.expect_expr("inherits_from_one.one", result_value="142")
133        self.expect_expr("inherits_from_two.member", result_value="47")
134        self.expect("expr inherits_from_two.one", error=True,
135            substrs=["no member named 'one' in 'InheritsFromTwo'"])
136        self.expect("expr inherits_from_two.two", error=True,
137            substrs=["no member named 'two' in 'InheritsFromTwo'"])
138
139        self.expect_expr("one_as_member.member", result_value="47")
140        self.expect_expr("one_as_member.one.member", result_value="147")
141        self.expect_expr("two_as_member.member", result_value="47")
142        self.expect("expr two_as_member.two.one.member", error=True,
143                substrs=["no member named 'one' in 'member::Two'"])
144        self.expect("expr two_as_member.two.member", error=True,
145                substrs=["no member named 'member' in 'member::Two'"])
146
147        self.expect_expr("array_of_one[2].member", result_value="174")
148        self.expect("expr array_of_two[2].one[2].member", error=True,
149                substrs=["no member named 'one' in 'array::Two'"])
150        self.expect("expr array_of_two[2].member", error=True,
151                substrs=["no member named 'member' in 'array::Two'"])
152
153        self.expect_expr("get_one().member", result_value="124")
154        self.expect("expr get_two().one().member", error=True,
155                substrs=["calling 'get_two' with incomplete return type 'result::Two'"])
156        self.expect("expr get_two().member", error=True,
157                substrs=["calling 'get_two' with incomplete return type 'result::Two'"])
158