Skip to content

Commit 9aa49ef

Browse files
committed
[lldb][SymbolFileDWARF] CompleteType: Lookup type in the declaration DIE's SymbolFile
The problem here manifests as follows: 1. We are stopped in main.o, so the first `ParseTypeFromDWARF` on `FooImpl<char>` gets called on `main.o`'s SymbolFile. This adds a mapping from *declaration die* -> `TypeSP` into `main.o`'s `GetDIEToType` map. 2. We then `CompleteType(FooImpl<char>)`. Depending on the order of entries in the debug-map, this might call `CompleteType` on `lib.o`'s SymbolFile. In which case, `GetDIEToType().lookup(decl_die)` will return a `nullptr`. This is already a bit iffy because surrounding code used to assume we don't call `CompleteTypeFromDWARF` with a `nullptr` `Type*`. This used to be more of an issue when `CompleteRecordType` actually made use of the `Type*` parameter (see #120456). 3. While in `CompleteTypeFromDWARF`, we call `ParseTypeFromDWARF` again. This will parse the member function `FooImpl::Create` and its return type which is a typedef to `FooImpl*`. But now we're inside `lib.o`'s SymbolFile, so we call it on the definition DIE. In step (2) we just inserted a `nullptr` into `GetDIEToType` for the definition DIE, so we trivially return a `nullptr` from `ParseTypeFromDWARF`. Instead of reporting back this parse failure to the user LLDB trucks on and marks `FooImpl::Ref` to be `void*`. This test-case will trigger an assert in `TypeSystemClang::VerifyDecl` even if we just `frame var` (but only in debug-builds). In release builds where this function is a no-op, we'll create an incorrect Clang AST node for the `Ref` typedef.
1 parent 3769fcb commit 9aa49ef

File tree

6 files changed

+71
-1
lines changed

6 files changed

+71
-1
lines changed

lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1593,7 +1593,9 @@ bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
15931593
DWARFASTParser *dwarf_ast = GetDWARFParser(*def_die.GetCU());
15941594
if (!dwarf_ast)
15951595
return false;
1596-
Type *type = GetDIEToType().lookup(decl_die.GetDIE());
1596+
Type *type = decl_die.GetDWARF()->GetDIEToType().lookup(decl_die.GetDIE());
1597+
assert (type);
1598+
15971599
if (decl_die != def_die) {
15981600
GetDIEToType()[def_die.GetDIE()] = type;
15991601
DWARFASTParserClang *ast_parser =
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CXX_SOURCES := lib.cpp main.cpp
2+
3+
include Makefile.rules
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import lldb
2+
from lldbsuite.test.decorators import *
3+
from lldbsuite.test.lldbtest import *
4+
from lldbsuite.test import lldbutil
5+
6+
7+
class TestCaseTypedefToOuterFwd(TestBase):
8+
'''
9+
We are stopped in main.o, which only sees a forward declaration
10+
of FooImpl. We then try to get the FooImpl::Ref typedef (whose
11+
definition is in lib.o). Make sure we correctly resolve this
12+
typedef.
13+
'''
14+
def test(self):
15+
self.build()
16+
(_, _, thread, _) = lldbutil.run_to_source_breakpoint(
17+
self, "return", lldb.SBFileSpec("main.cpp")
18+
)
19+
20+
foo = thread.frames[0].FindVariable('foo')
21+
self.assertSuccess(foo.GetError(), "Found foo")
22+
23+
foo_type = foo.GetType()
24+
self.assertTrue(foo_type)
25+
26+
impl = foo_type.GetPointeeType()
27+
self.assertTrue(impl)
28+
29+
ref = impl.FindDirectNestedType('Ref')
30+
self.assertTrue(ref)
31+
32+
self.assertEqual(ref.GetCanonicalType(), foo_type)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include "lib.h"
2+
3+
template <typename T> struct FooImpl {
4+
using Ref = FooImpl<T> *;
5+
6+
Ref Create() { return new FooImpl<T>(); }
7+
};
8+
9+
Foo getString() {
10+
FooImpl<char> impl;
11+
Foo ret;
12+
ret.impl = impl.Create();
13+
14+
return ret;
15+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef LIB_H_IN
2+
#define LIB_H_IN
3+
4+
template <typename T> struct FooImpl;
5+
6+
struct Foo {
7+
FooImpl<char> *impl = nullptr;
8+
};
9+
10+
#endif // LIB_H_IN
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#include "lib.h"
2+
3+
extern Foo getString();
4+
5+
int main() {
6+
FooImpl<char> *foo = getString().impl;
7+
return 0;
8+
}

0 commit comments

Comments
 (0)