Summary: This effectively reverts r188124, which added code to handle (DW_AT_)declarations of structures with some kinds of children as definitions. The commit message claims this is a workaround for some kind of debug info produced by gcc. However, it does not go into specifics, so it's hard to reproduce or verify that this is indeed still a problem. Having this code is definitely a problem though, because it mistakenly declares incomplete dwarf declarations to be complete. Both clang (with -flimit-debug-info) and gcc (by default) generate DW_AT_declarations of structs with children. This happens when full debug info for a class is not emitted in a given compile unit (e.g. because of vtable homing), but the class has inline methods which are used in the given compile unit. In that case, the compilers emit a DW_AT_declaration of a class, but add a DW_TAG_subprogram child to it to describe the inlined instance of the method. Even though the class tag has some children, it definitely does not contain enough information to construct a full class definition (most notably, it lacks any members). Keeping the class as incomplete allows us to search for a real definition in other modules, helping the -flimit-debug-info flow. And in case the definition is not found we can display a error message saying that, instead of just showing an empty struct. Reviewers: clayborg, aprantl, JDevlieghere, shafik Subscribers: lldb-commits Tags: #lldb Differential Revision: https://reviews.llvm.org/D83302
148 lines
7.1 KiB
Python
148 lines
7.1 KiB
Python
"""
|
|
Test completing types using information from other shared libraries.
|
|
"""
|
|
|
|
import os
|
|
import lldb
|
|
from lldbsuite.test.decorators import *
|
|
from lldbsuite.test.lldbtest import *
|
|
from lldbsuite.test import lldbutil
|
|
|
|
|
|
class LimitDebugInfoTestCase(TestBase):
|
|
|
|
mydir = TestBase.compute_mydir(__file__)
|
|
|
|
def _check_type(self, target, name):
|
|
exe = target.FindModule(lldb.SBFileSpec("a.out"))
|
|
type_ = exe.FindFirstType(name)
|
|
self.trace("type_: %s"%type_)
|
|
self.assertTrue(type_)
|
|
base = type_.GetDirectBaseClassAtIndex(0).GetType()
|
|
self.trace("base:%s"%base)
|
|
self.assertTrue(base)
|
|
self.assertEquals(base.GetNumberOfFields(), 0)
|
|
|
|
def _check_debug_info_is_limited(self, target):
|
|
# Without other shared libraries we should only see the member declared
|
|
# in the derived class. This serves as a sanity check that we are truly
|
|
# building with limited debug info.
|
|
self._check_type(target, "InheritsFromOne")
|
|
self._check_type(target, "InheritsFromTwo")
|
|
|
|
@skipIf(bugnumber="pr46284", debug_info="gmodules")
|
|
@skipIfWindows # Clang emits type info even with -flimit-debug-info
|
|
def test_one_and_two_debug(self):
|
|
self.build()
|
|
target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
|
|
|
|
self._check_debug_info_is_limited(target)
|
|
|
|
lldbutil.run_to_name_breakpoint(self, "main",
|
|
extra_images=["one", "two"])
|
|
|
|
# But when other shared libraries are loaded, we should be able to see
|
|
# all members.
|
|
self.expect_expr("inherits_from_one.member", result_value="47")
|
|
self.expect_expr("inherits_from_one.one", result_value="142")
|
|
self.expect_expr("inherits_from_two.member", result_value="47")
|
|
self.expect_expr("inherits_from_two.one", result_value="142")
|
|
self.expect_expr("inherits_from_two.two", result_value="242")
|
|
|
|
self.expect_expr("one_as_member.member", result_value="47")
|
|
self.expect_expr("one_as_member.one.member", result_value="147")
|
|
self.expect_expr("two_as_member.member", result_value="47")
|
|
self.expect_expr("two_as_member.two.one.member", result_value="147")
|
|
self.expect_expr("two_as_member.two.member", result_value="247")
|
|
|
|
self.expect_expr("array_of_one[2].member", result_value="174")
|
|
self.expect_expr("array_of_two[2].one[2].member", result_value="174")
|
|
self.expect_expr("array_of_two[2].member", result_value="274")
|
|
|
|
self.expect_expr("get_one().member", result_value="124")
|
|
self.expect_expr("get_two().one().member", result_value="124")
|
|
self.expect_expr("get_two().member", result_value="224")
|
|
|
|
@skipIf(bugnumber="pr46284", debug_info="gmodules")
|
|
@skipIfWindows # Clang emits type info even with -flimit-debug-info
|
|
def test_two_debug(self):
|
|
self.build(dictionary=dict(STRIP_ONE="1"))
|
|
target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
|
|
|
|
self._check_debug_info_is_limited(target)
|
|
|
|
lldbutil.run_to_name_breakpoint(self, "main",
|
|
extra_images=["one", "two"])
|
|
|
|
# This time, we should only see the members from the second library.
|
|
self.expect_expr("inherits_from_one.member", result_value="47")
|
|
self.expect("expr inherits_from_one.one", error=True,
|
|
substrs=["no member named 'one' in 'InheritsFromOne'"])
|
|
self.expect_expr("inherits_from_two.member", result_value="47")
|
|
self.expect("expr inherits_from_two.one", error=True,
|
|
substrs=["no member named 'one' in 'InheritsFromTwo'"])
|
|
self.expect_expr("inherits_from_two.two", result_value="242")
|
|
|
|
self.expect_expr("one_as_member.member", result_value="47")
|
|
self.expect("expr one_as_member.one.member", error=True,
|
|
substrs=["no member named 'member' in 'member::One'"])
|
|
self.expect_expr("two_as_member.member", result_value="47")
|
|
self.expect("expr two_as_member.two.one.member", error=True,
|
|
substrs=["no member named 'member' in 'member::One'"])
|
|
self.expect_expr("two_as_member.two.member", result_value="247")
|
|
|
|
self.expect("expr array_of_one[2].member", error=True,
|
|
substrs=["no member named 'member' in 'array::One'"])
|
|
self.expect("expr array_of_two[2].one[2].member", error=True,
|
|
substrs=["no member named 'member' in 'array::One'"])
|
|
self.expect_expr("array_of_two[2].member", result_value="274")
|
|
|
|
self.expect("expr get_one().member", error=True,
|
|
substrs=["calling 'get_one' with incomplete return type 'result::One'"])
|
|
self.expect("expr get_two().one().member", error=True,
|
|
substrs=["calling 'one' with incomplete return type 'result::One'"])
|
|
self.expect_expr("get_two().member", result_value="224")
|
|
|
|
@skipIf(bugnumber="pr46284", debug_info="gmodules")
|
|
@skipIfWindows # Clang emits type info even with -flimit-debug-info
|
|
def test_one_debug(self):
|
|
self.build(dictionary=dict(STRIP_TWO="1"))
|
|
target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
|
|
|
|
self._check_debug_info_is_limited(target)
|
|
|
|
lldbutil.run_to_name_breakpoint(self, "main",
|
|
extra_images=["one", "two"])
|
|
|
|
# In this case we should only see the members from the second library.
|
|
# Note that we cannot see inherits_from_two.one because without debug
|
|
# info for "Two", we cannot determine that it in fact inherits from
|
|
# "One".
|
|
self.expect_expr("inherits_from_one.member", result_value="47")
|
|
self.expect_expr("inherits_from_one.one", result_value="142")
|
|
self.expect_expr("inherits_from_two.member", result_value="47")
|
|
self.expect("expr inherits_from_two.one", error=True,
|
|
substrs=["no member named 'one' in 'InheritsFromTwo'"])
|
|
self.expect("expr inherits_from_two.two", error=True,
|
|
substrs=["no member named 'two' in 'InheritsFromTwo'"])
|
|
|
|
self.expect_expr("one_as_member.member", result_value="47")
|
|
self.expect_expr("one_as_member.one.member", result_value="147")
|
|
self.expect_expr("two_as_member.member", result_value="47")
|
|
self.expect("expr two_as_member.two.one.member", error=True,
|
|
substrs=["no member named 'one' in 'member::Two'"])
|
|
self.expect("expr two_as_member.two.member", error=True,
|
|
substrs=["no member named 'member' in 'member::Two'"])
|
|
|
|
self.expect_expr("array_of_one[2].member", result_value="174")
|
|
self.expect("expr array_of_two[2].one[2].member", error=True,
|
|
substrs=["no member named 'one' in 'array::Two'"])
|
|
self.expect("expr array_of_two[2].member", error=True,
|
|
substrs=["no member named 'member' in 'array::Two'"])
|
|
|
|
self.expect_expr("get_one().member", result_value="124")
|
|
self.expect("expr get_two().one().member", error=True,
|
|
substrs=["calling 'get_two' with incomplete return type 'result::Two'"])
|
|
self.expect("expr get_two().member", error=True,
|
|
substrs=["calling 'get_two' with incomplete return type 'result::Two'"])
|