Skip to content

Commit cfff55e

Browse files
committed
[InterfaceGen] Fix deserializing submodule ImportDecls
Use the isScoped() bit to distinguish scoped imports from submodule imports (both of which are split by null bytes in the string) so that we don't try to lookup a submodule name as if it were a decl (leading to assertion failures when it wasn't found). This fixes interface generation of swift modules that import clang submodules. rdar://problem/24534122
1 parent d58b14d commit cfff55e

File tree

3 files changed

+43
-13
lines changed

3 files changed

+43
-13
lines changed

lib/Serialization/ModuleFile.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,19 +1219,21 @@ void ModuleFile::getImportDecls(SmallVectorImpl<Decl *> &Results) {
12191219
if (Dep.isHeader())
12201220
continue;
12211221

1222-
StringRef ModulePath, ScopePath;
1223-
std::tie(ModulePath, ScopePath) = Dep.RawPath.split('\0');
1224-
1225-
auto ModuleID = Ctx.getIdentifier(ModulePath);
1226-
assert(!ModuleID.empty() &&
1227-
"invalid module name (submodules not yet supported)");
1222+
StringRef ModulePathStr = Dep.RawPath;
1223+
StringRef ScopePath;
1224+
if (Dep.isScoped())
1225+
std::tie(ModulePathStr, ScopePath) = ModulePathStr.rsplit('\0');
1226+
1227+
SmallVector<std::pair<swift::Identifier, swift::SourceLoc>, 1> AccessPath;
1228+
while (!ModulePathStr.empty()) {
1229+
StringRef NextComponent;
1230+
std::tie(NextComponent, ModulePathStr) = ModulePathStr.split('\0');
1231+
AccessPath.push_back({Ctx.getIdentifier(NextComponent), SourceLoc()});
1232+
}
12281233

1229-
if (ModuleID == Ctx.StdlibModuleName)
1234+
if (AccessPath.size() == 1 && AccessPath[0].first == Ctx.StdlibModuleName)
12301235
continue;
12311236

1232-
SmallVector<std::pair<swift::Identifier, swift::SourceLoc>, 1>
1233-
AccessPath;
1234-
AccessPath.push_back({ ModuleID, SourceLoc() });
12351237
Module *M = Ctx.getModule(AccessPath);
12361238

12371239
auto Kind = ImportKind::Module;
@@ -1245,10 +1247,15 @@ void ModuleFile::getImportDecls(SmallVectorImpl<Decl *> &Results) {
12451247
// about the import kind, we cannot do better.
12461248
Kind = ImportKind::Func;
12471249
} else {
1250+
// Lookup the decl in the top-level module.
1251+
Module *TopLevelModule = M;
1252+
if (AccessPath.size() > 1)
1253+
TopLevelModule = Ctx.getLoadedModule(AccessPath.front().first);
1254+
12481255
SmallVector<ValueDecl *, 8> Decls;
1249-
M->lookupQualified(ModuleType::get(M), ScopeID,
1250-
NL_QualifiedDefault | NL_KnownNoDependency,
1251-
nullptr, Decls);
1256+
TopLevelModule->lookupQualified(
1257+
ModuleType::get(TopLevelModule), ScopeID,
1258+
NL_QualifiedDefault | NL_KnownNoDependency, nullptr, Decls);
12521259
Optional<ImportKind> FoundKind = ImportDecl::findBestImportKind(Decls);
12531260
assert(FoundKind.hasValue() &&
12541261
"deserialized imports should not be ambiguous");

test/IDE/Inputs/FooOverlay.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@_exported import Foo // not scoped, top-level module
2+
@_exported import Foo.FooSub // not scoped, submodule
3+
@_exported import func Foo.FooSub.fooSubFunc1 // scoped, from submodule
4+
@_exported import struct Foo.FooStruct1 // scoped, from top-level module
5+
6+
func fooSubOverlayFunc1(x: Int32) -> Int32 {
7+
return fooSubFunc1(x)
8+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
4+
// RUN: %target-swift-frontend(mock-sdk: -F %S/Inputs/mock-sdk) -I %t -emit-module -o %t/FooOverlay.swiftmodule %S/Inputs/FooOverlay.swift
5+
// RUN: %target-swift-ide-test(mock-sdk: -F %S/Inputs/mock-sdk) -I %t -print-module -source-filename %s -module-to-print=FooOverlay -function-definitions=false | FileCheck %s
6+
7+
import FooOverlay
8+
9+
// CHECK: @_exported import Foo
10+
// CHECK: @_exported import struct Foo.FooStruct1
11+
// CHECK: @_exported import Foo.FooSub
12+
// CHECK: @_exported import func Foo.FooSub.fooSubFunc1
13+
// FIXME: this duplicate import is silly, but not harmful.
14+
// CHECK: @_exported import func Foo.fooSubFunc1
15+
// CHECK: func fooSubOverlayFunc1(x: Int32) -> Int32

0 commit comments

Comments
 (0)