Skip to content

Commit 5391176

Browse files
committed
Complete complete types early when importing types from Clang module DWARF.
This affects -gmodules only. Under normal operation pcm_type is a shallow forward declaration that gets completed later. This is necessary to support cyclic data structures. If, however, pcm_type is already complete (for example, because it was loaded for a different target before), the definition needs to be imported right away, too. Type::ResolveClangType() effectively ignores the ResolveState inside type_sp and only looks at IsDefined(), so it never calls ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(), which does extra work for Objective-C classes. This would result in only the forward declaration to be visible. An alternative implementation would be to sink this into Type::ResolveClangType ( https://github.com/llvm/llvm-project/blob/88235812a71d99c082e7aa2ef9356d43d1f83a80/lldb/source/Symbol/Type.cpp#L5809) though it isn't clear to me how to best do this from a layering perspective. rdar://problem/52134074 Differential Revision: https://reviews.llvm.org/D70415
1 parent c0eeea5 commit 5391176

File tree

7 files changed

+109
-1
lines changed

7 files changed

+109
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CFLAGS_EXTRAS = -I$(BUILDDIR)
2+
USE_PRIVATE_MODULE_CACHE := YES
3+
OBJC_SOURCES := main.m foo.m
4+
5+
include Makefile.rules
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
from __future__ import print_function
2+
3+
import unittest2
4+
import os
5+
import shutil
6+
7+
import lldb
8+
from lldbsuite.test.decorators import *
9+
from lldbsuite.test.lldbtest import *
10+
from lldbsuite.test import lldbutil
11+
12+
13+
class TestClangModuleAppUpdate(TestBase):
14+
mydir = TestBase.compute_mydir(__file__)
15+
16+
def setUp(self):
17+
TestBase.setUp(self)
18+
19+
@skipUnlessDarwin
20+
@skipIf(debug_info=no_match(["gmodules"]))
21+
def test_rebuild_app_modules_untouched(self):
22+
with open(self.getBuildArtifact("module.modulemap"), "w") as f:
23+
f.write("""
24+
module Foo { header "f.h" }
25+
""")
26+
with open(self.getBuildArtifact("f.h"), "w") as f:
27+
f.write("""
28+
@import Foundation;
29+
@interface Foo : NSObject {
30+
int i;
31+
}
32+
+(instancetype)init;
33+
@end
34+
""")
35+
36+
mod_cache = self.getBuildArtifact("private-module-cache")
37+
import os
38+
if os.path.isdir(mod_cache):
39+
shutil.rmtree(mod_cache)
40+
self.build()
41+
self.assertTrue(os.path.isdir(mod_cache), "module cache exists")
42+
43+
target, process, _, bkpt = lldbutil.run_to_source_breakpoint(
44+
self, "break here", lldb.SBFileSpec("main.m"))
45+
bar = target.FindTypes('Bar').GetTypeAtIndex(0)
46+
foo = bar.GetDirectBaseClassAtIndex(0).GetType()
47+
self.assertEqual(foo.GetNumberOfFields(), 1)
48+
self.assertEqual(foo.GetFieldAtIndex(0).GetName(), "i")
49+
50+
# Rebuild.
51+
process.Kill()
52+
os.remove(self.getBuildArtifact('main.o'))
53+
os.remove(self.getBuildArtifact('a.out'))
54+
self.build()
55+
56+
# Reattach.
57+
target, process, _, _ = lldbutil.run_to_breakpoint_do_run(self, target, bkpt)
58+
bar = target.FindTypes('Bar').GetTypeAtIndex(0)
59+
foo = bar.GetDirectBaseClassAtIndex(0).GetType()
60+
self.assertEqual(foo.GetNumberOfFields(), 1)
61+
self.assertEqual(foo.GetFieldAtIndex(0).GetName(), "i")
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@import Foundation;
2+
@import Foo;
3+
@implementation Foo
4+
+(instancetype)init {
5+
return [super init];
6+
}
7+
@end
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
@import Umbrella;
2+
3+
@interface Bar : Foo
4+
+(instancetype)init;
5+
@end
6+
7+
@implementation Bar
8+
+(instancetype)init {
9+
return [super init];
10+
}
11+
@end
12+
13+
int main(int argc, char **argv) {
14+
id bar = [Bar new];
15+
[bar i]; // break here
16+
return 0;
17+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Umbrella {
2+
header "umbrella.h"
3+
export *
4+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@import Foo;

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
187187
languages.Insert(die.GetCU()->GetLanguageType());
188188
llvm::DenseSet<SymbolFile *> searched_symbol_files;
189189
clang_module_sp->GetSymbolFile()->FindTypes(decl_context, languages,
190-
searched_symbol_files, pcm_types);
190+
searched_symbol_files, pcm_types);
191191
if (pcm_types.Empty()) {
192192
// Since this type is defined in one of the Clang modules imported
193193
// by this symbol file, search all of them. Instead of calling
@@ -222,6 +222,19 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc,
222222
if (!type)
223223
return TypeSP();
224224

225+
// Under normal operation pcm_type is a shallow forward declaration
226+
// that gets completed later. This is necessary to support cyclic
227+
// data structures. If, however, pcm_type is already complete (for
228+
// example, because it was loaded for a different target before),
229+
// the definition needs to be imported right away, too.
230+
// Type::ResolveClangType() effectively ignores the ResolveState
231+
// inside type_sp and only looks at IsDefined(), so it never calls
232+
// ClangASTImporter::ASTImporterDelegate::ImportDefinitionTo(),
233+
// which does extra work for Objective-C classes. This would result
234+
// in only the forward declaration to be visible.
235+
if (pcm_type.IsDefined())
236+
GetClangASTImporter().RequireCompleteType(ClangUtil::GetQualType(type));
237+
225238
SymbolFileDWARF *dwarf = die.GetDWARF();
226239
TypeSP type_sp(new Type(
227240
die.GetID(), dwarf, pcm_type_sp->GetName(), pcm_type_sp->GetByteSize(),

0 commit comments

Comments
 (0)