Skip to content

Commit daa335c

Browse files
authored
Merge pull request swiftlang#39533 from apple/es-mod3
[Module Aliasing] Modify module loaders to use module 'real name' (physical name on-disk) when loading, since it can be different from 'name' if module aliasing is used. Also use the 'real name' to add/retrieve loaded modules in ASTContext. Resolves rdar://83591943.
2 parents d43fe18 + e182c23 commit daa335c

12 files changed

+322
-12
lines changed

include/swift/Option/Options.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,9 +431,9 @@ def module_name_EQ : Joined<["-"], "module-name=">, Flags<[FrontendOption]>,
431431
Alias<module_name>;
432432

433433
def module_alias : Separate<["-"], "module-alias">,
434-
Flags<[FrontendOption]>,
434+
Flags<[FrontendOption, ModuleInterfaceOption]>,
435435
MetaVarName<"<alias_name=underlying_name>">,
436-
HelpText<"If a source file imports or references module <alias_name>, the underlying name is used for the contents of the file">;
436+
HelpText<"If a source file imports or references module <alias_name>, the <underlying_name> is used for the contents of the file">;
437437

438438
def module_link_name : Separate<["-"], "module-link-name">,
439439
Flags<[FrontendOption, ModuleInterfaceOption]>,

lib/AST/ASTContext.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,12 +1848,27 @@ ASTContext::getLoadedModules() const {
18481848
}
18491849

18501850
ModuleDecl *ASTContext::getLoadedModule(Identifier ModuleName) const {
1851-
return getImpl().LoadedModules.lookup(ModuleName);
1851+
// Look up a loaded module using an actual module name (physical name
1852+
// on disk). If the -module-alias option is used, the module name that
1853+
// appears in source code will be different from the real module name
1854+
// on disk, otherwise the same.
1855+
//
1856+
// For example, if '-module-alias Foo=Bar' is passed in to the frontend,
1857+
// and a source file has 'import Foo', a module called Bar (real name)
1858+
// will be loaded and returned.
1859+
auto realName = getRealModuleName(ModuleName);
1860+
return getImpl().LoadedModules.lookup(realName);
18521861
}
18531862

18541863
void ASTContext::addLoadedModule(ModuleDecl *M) {
18551864
assert(M);
1856-
getImpl().LoadedModules[M->getName()] = M;
1865+
// Add a loaded module using an actual module name (physical name
1866+
// on disk), in case -module-alias is used (otherwise same).
1867+
//
1868+
// For example, if '-module-alias Foo=Bar' is passed in to the frontend,
1869+
// and a source file has 'import Foo', a module called Bar (real name)
1870+
// will be loaded and added to the map.
1871+
getImpl().LoadedModules[M->getRealName()] = M;
18571872
}
18581873

18591874
void ASTContext::registerGenericSignatureBuilder(

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1739,7 +1739,13 @@ bool ExplicitSwiftModuleLoader::findModule(ImportPath::Element ModuleID,
17391739
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
17401740
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer,
17411741
bool skipBuildingInterface, bool &IsFramework, bool &IsSystemModule) {
1742-
StringRef moduleName = ModuleID.Item.str();
1742+
// Find a module with an actual, physical name on disk, in case
1743+
// -module-alias is used (otherwise same).
1744+
//
1745+
// For example, if '-module-alias Foo=Bar' is passed in to the frontend, and an
1746+
// input file has 'import Foo', a module called Bar (real name) should be searched.
1747+
StringRef moduleName = Ctx.getRealModuleName(ModuleID.Item).str();
1748+
17431749
auto it = Impl.ExplicitModuleMap.find(moduleName);
17441750
// If no explicit module path is given matches the name, return with an
17451751
// error code.

lib/Sema/SourceLoader.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,20 @@ using namespace swift;
3434
// FIXME: Basically the same as SerializedModuleLoader.
3535
using FileOrError = llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>;
3636

37-
static FileOrError findModule(ASTContext &ctx, StringRef moduleID,
37+
static FileOrError findModule(ASTContext &ctx, Identifier moduleID,
3838
SourceLoc importLoc) {
3939
llvm::SmallString<128> inputFilename;
40+
// Find a module with an actual, physical name on disk, in case
41+
// -module-alias is used (otherwise same).
42+
//
43+
// For example, if '-module-alias Foo=Bar' is passed in to the frontend,
44+
// and a source file has 'import Foo', a module called Bar (real name)
45+
// should be searched.
46+
StringRef moduleNameRef = ctx.getRealModuleName(moduleID).str();
4047

4148
for (auto Path : ctx.SearchPathOpts.ImportSearchPaths) {
4249
inputFilename = Path;
43-
llvm::sys::path::append(inputFilename, moduleID);
50+
llvm::sys::path::append(inputFilename, moduleNameRef);
4451
inputFilename.append(".swift");
4552
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
4653
ctx.SourceMgr.getFileSystem()->getBufferForFile(inputFilename.str());
@@ -66,7 +73,7 @@ bool SourceLoader::canImportModule(ImportPath::Element ID,
6673
llvm::VersionTuple version,
6774
bool underlyingVersion) {
6875
// Search the memory buffers to see if we can find this file on disk.
69-
FileOrError inputFileOrError = findModule(Ctx, ID.Item.str(),
76+
FileOrError inputFileOrError = findModule(Ctx, ID.Item,
7077
ID.Loc);
7178
if (!inputFileOrError) {
7279
auto err = inputFileOrError.getError();
@@ -88,7 +95,7 @@ ModuleDecl *SourceLoader::loadModule(SourceLoc importLoc,
8895

8996
auto moduleID = path[0];
9097

91-
FileOrError inputFileOrError = findModule(Ctx, moduleID.Item.str(),
98+
FileOrError inputFileOrError = findModule(Ctx, moduleID.Item,
9299
moduleID.Loc);
93100
if (!inputFileOrError) {
94101
auto err = inputFileOrError.getError();

lib/Serialization/ModuleFile.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,15 @@ Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc,
131131
Status status = Status::Valid;
132132

133133
ModuleDecl *M = file->getParentModule();
134-
if (M->getName().str() != Core->Name)
134+
// The real (on-disk) name of the module should be checked here as that's the
135+
// actually loaded module. In case module aliasing is used when building the main
136+
// module, e.g. -module-name MyModule -module-alias Foo=Bar, the loaded module
137+
// that maps to 'Foo' is actually Bar.swiftmodule|.swiftinterface (applies to swift
138+
// modules only), which is retrieved via M->getRealName(). If no module aliasing is
139+
// used, M->getRealName() will return the same value as M->getName(), which is 'Foo'.
140+
if (M->getRealName().str() != Core->Name) {
135141
return error(Status::NameMismatch);
142+
}
136143

137144
ASTContext &ctx = getContext();
138145

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,14 @@ SerializedModuleLoaderBase::findModule(ImportPath::Element moduleID,
533533
std::unique_ptr<llvm::MemoryBuffer> *moduleDocBuffer,
534534
std::unique_ptr<llvm::MemoryBuffer> *moduleSourceInfoBuffer,
535535
bool skipBuildingInterface, bool &isFramework, bool &isSystemModule) {
536-
SmallString<32> moduleName(moduleID.Item.str());
536+
// Find a module with an actual, physical name on disk, in case
537+
// -module-alias is used (otherwise same).
538+
//
539+
// For example, if '-module-alias Foo=Bar' is passed in to the frontend,
540+
// and a source file has 'import Foo', a module called Bar (real name)
541+
// should be searched.
542+
StringRef moduleNameRef = Ctx.getRealModuleName(moduleID.Item).str();
543+
SmallString<32> moduleName(moduleNameRef);
537544
SerializedModuleBaseName genericBaseName(moduleName);
538545

539546
auto genericModuleFileName =
@@ -1156,7 +1163,6 @@ bool MemoryBufferSerializedModuleLoader::canImportModule(
11561163
assert(!(mIt->second.userVersion.empty()));
11571164
return mIt->second.userVersion >= version;
11581165
}
1159-
11601166
ModuleDecl *
11611167
SerializedModuleLoaderBase::loadModule(SourceLoc importLoc,
11621168
ImportPath::Module path) {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// Test the -module-alias flag on a sample scenario:
2+
/// Module 'Utils' imports module 'Logging'.
3+
/// 'Logging' needs to be aliased due to a name collision, so is renamed 'AppleLogging'.
4+
5+
// RUN: %empty-directory(%t)
6+
7+
/// Logging has a source file that has a reference to its module name Logging
8+
// RUN: echo 'public struct Logger { }' > %t/FileLog.swift
9+
// RUN: echo 'public func setup() -> Logging.Logger? { return nil }' >> %t/FileLog.swift
10+
11+
/// Create AppleLogging.swiftmodule by aliasing Logging via -module-alias Logging=AppleLogging
12+
// RUN: %target-swift-frontend -module-name AppleLogging -module-alias Logging=AppleLogging %t/FileLog.swift -emit-module -emit-module-path %t/AppleLogging.swiftmodule
13+
14+
/// Check AppleLogging.swiftmodule is created
15+
// RUN: test -f %t/AppleLogging.swiftmodule
16+
// RUN: not test -f %t/Logging.swiftmodule
17+
18+
/// Create a module Utils that imports Logging with -module-alias Logging=AppleLogging
19+
// RUN: echo 'import Logging' > %t/FileUtils.swift
20+
// RUN: echo 'public func start() { Logging.setup() }' >> %t/FileUtils.swift
21+
// RUN: %target-swift-frontend -module-name Utils %t/FileUtils.swift -module-alias Logging=AppleLogging -I %t -emit-module -emit-module-path %t/Utils.swiftmodule -Rmodule-loading 2> %t/load-result.output
22+
23+
/// Check Utils.swiftmodule is created and AppleLogging.swiftmodule is loaded
24+
// RUN: test -f %t/Utils.swiftmodule
25+
// RUN: test -f %t/AppleLogging.swiftmodule
26+
// RUN: not test -f %t/Logging.swiftmodule
27+
28+
// RUN: %FileCheck %s -input-file %t/load-result.output -check-prefix CHECK-LOAD
29+
// CHECK-LOAD: remark: loaded module at {{.*}}AppleLogging.swiftmodule
30+
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/// Test the -module-alias flag on the following scenario:
2+
/// Module 'Utils' imports module 'Logging', and module 'UserN' imports both 'Utils' and 'Logging'.
3+
/// 'Logging' needs to be aliased due to a name collision, so is renamed 'AppleLogging'.
4+
5+
// RUN: %empty-directory(%t)
6+
7+
/// Input file with a reference to its enclosing module called Logging
8+
// RUN: echo 'public struct Logger { }' > %t/FileLog.swift
9+
// RUN: echo 'public func setup() -> Logging.Logger? { return nil }' >> %t/FileLog.swift
10+
11+
/// Create AppleLogging.swiftmodule by aliasing Logging via -module-alias Logging=AppleLogging
12+
// RUN: %target-swift-frontend -module-name AppleLogging -module-alias Logging=AppleLogging %t/FileLog.swift -emit-module -emit-module-path %t/AppleLogging.swiftmodule
13+
14+
/// Check AppleLogging.swiftmodule is created
15+
// RUN: test -f %t/AppleLogging.swiftmodule
16+
// RUN: not test -f %t/Logging.swiftmodule
17+
18+
/// Create a module Utils that imports Logging with -module-alias Logging=AppleLogging
19+
// RUN: echo 'import Logging' > %t/FileUtils.swift
20+
// RUN: echo 'public func start() { Logging.setup() }' >> %t/FileUtils.swift
21+
// RUN: %target-swift-frontend -module-name Utils %t/FileUtils.swift -module-alias Logging=AppleLogging -I %t -emit-module -emit-module-path %t/Utils.swiftmodule -Rmodule-loading 2> %t/result-Utils.output
22+
23+
/// Check Utils.swiftmodule is created and AppleLogging.swiftmodule is loaded
24+
// RUN: test -f %t/Utils.swiftmodule
25+
// RUN: test -f %t/AppleLogging.swiftmodule
26+
// RUN: not test -f %t/Logging.swiftmodule
27+
28+
// RUN: %FileCheck %s -input-file %t/result-Utils.output -check-prefix CHECK-UTILS
29+
// CHECK-UTILS: remark: loaded module at {{.*}}AppleLogging.swiftmodule
30+
31+
/// Create a module User1 that imports both Utils and Logging, with module aliasing for Logging
32+
// RUN: echo 'import Logging' > %t/File.swift
33+
// RUN: echo 'import Utils' >> %t/File.swift
34+
// RUN: echo 'public func run() { Utils.start() }' >> %t/File.swift
35+
// RUN: %target-swift-frontend -module-name User1 %t/File.swift -module-alias Logging=AppleLogging -I %t -emit-module -emit-module-path %t/User1.swiftmodule -Rmodule-loading 2> %t/result-User1.output
36+
37+
/// Check User1.swiftmodule is created and Utils.swiftmodule and AppleLogging.swiftmodule are loaded
38+
// RUN: test -f %t/User1.swiftmodule
39+
// RUN: test -f %t/Utils.swiftmodule
40+
// RUN: test -f %t/AppleLogging.swiftmodule
41+
// RUN: not test -f %t/Logging.swiftmodule
42+
43+
// RUN: %FileCheck %s -input-file %t/result-User1.output -check-prefix CHECK-1
44+
// CHECK-1: remark: loaded module at {{.*}}AppleLogging.swiftmodule
45+
// CHECK-1: remark: loaded module at {{.*}}Utils.swiftmodule
46+
47+
/// Try creating a module User2 that imports both Utils and Logging, without module aliasing
48+
// RUN: not %target-swift-frontend -module-name User2 %t/File.swift -I %t -emit-module -emit-module-path %t/User2.swiftmodule 2> %t/result-User2.output
49+
50+
/// Check that it fails
51+
// RUN: %FileCheck %s -input-file %t/result-User2.output -check-prefix CHECK-2
52+
// CHECK-2: {{.*}}error: no such module 'Logging'
53+
54+
/// Try creating a module User3 that imports both Utils and AppleLogging, without module aliasing
55+
// RUN: echo 'import AppleLogging' > %t/AnotherFile.swift
56+
// RUN: echo 'import Utils' >> %t/AnotherFile.swift
57+
// RUN: echo 'public func run() { _ = AppleLogging.setup() }' >> %t/AnotherFile.swift
58+
// RUN: not %target-swift-frontend -module-name User3 %t/AnotherFile.swift -I %t -emit-module -emit-module-path %t/User3.swiftmodule 2> %t/result-User3.output
59+
60+
/// Check that it fails
61+
// RUN: %FileCheck %s -input-file %t/result-User3.output -check-prefix CHECK-3
62+
// CHECK-3: {{.*}}error: missing required module 'Logging'
63+
64+
/// Try creating a module User4 that imports both Utils and AppleLogging, with module aliasing for Logging
65+
// RUN: %target-swift-frontend -module-name User4 -module-alias Logging=AppleLogging %t/AnotherFile.swift -I %t -emit-module -emit-module-path %t/User4.swiftmodule -Rmodule-loading 2> %t/result-User4.output
66+
67+
/// Check that it fails
68+
// RUN: %FileCheck %s -input-file %t/result-User4.output -check-prefix CHECK-4
69+
// CHECK-4: remark: loaded module at {{.*}}AppleLogging.swiftmodule
70+
// CHECK-4: remark: loaded module at {{.*}}Utils.swiftmodule
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/// Test the -module-alias flag with the following scenario:
2+
/// Module 'Utils' imports module 'LoggingApple', and module 'UserN' imports both 'Utils' and 'Logging'.
3+
/// 'Logging' can be aliased 'LoggingApple' via -module-alias.
4+
5+
// RUN: %empty-directory(%t)
6+
7+
/// Create Logging.swiftmodule
8+
// RUN: echo 'public struct Logger { }' > %t/FileLog.swift
9+
// RUN: echo 'public func setup() -> Logging.Logger? { return nil }' >> %t/FileLog.swift
10+
// RUN: %target-swift-frontend -module-name Logging %t/FileLog.swift -emit-module -emit-module-path %t/Logging.swiftmodule
11+
12+
/// Check Logging.swiftmodule is created
13+
// RUN: test -f %t/Logging.swiftmodule
14+
15+
/// Create LoggingApple.swiftmodule
16+
// RUN: echo 'public struct Logger { }' > %t/FileAppleLog.swift
17+
// RUN: echo 'public func setup() -> LoggingApple.Logger? { return nil }' >> %t/FileAppleLog.swift
18+
// RUN: echo 'public func pie() -> LoggingApple.Logger? { return nil }' >> %t/FileAppleLog.swift
19+
// RUN: %target-swift-frontend -module-name LoggingApple %t/FileAppleLog.swift -emit-module -emit-module-path %t/LoggingApple.swiftmodule
20+
21+
/// Check LoggingApple.swiftmodule is created
22+
// RUN: test -f %t/LoggingApple.swiftmodule
23+
24+
/// Create a module Utils that imports LoggingApple
25+
// RUN: echo 'import LoggingApple' > %t/FileUtils.swift
26+
// RUN: echo 'public func start() { _ = LoggingApple.setup() }' >> %t/FileUtils.swift
27+
// RUN: %target-swift-frontend -module-name Utils %t/FileUtils.swift -I %t -emit-module -emit-module-path %t/Utils.swiftmodule -Rmodule-loading 2> %t/result-Utils.output
28+
29+
/// Check Utils.swiftmodule is created and LoggingApple.swiftmodule is loaded
30+
// RUN: test -f %t/Utils.swiftmodule
31+
// RUN: %FileCheck %s -input-file %t/result-Utils.output -check-prefix CHECK-UTILS
32+
// CHECK-UTILS: remark: loaded module at {{.*}}LoggingApple.swiftmodule
33+
34+
/// Create a module User1 that imports both Utils and Logging, without module aliasing for Logging
35+
// RUN: echo 'import Logging' > %t/File.swift
36+
// RUN: echo 'import Utils' >> %t/File.swift
37+
// RUN: echo 'public func runUtils() { Utils.start() }' >> %t/File.swift
38+
// RUN: echo 'public func runLog() { _ = Logging.setup() }' >> %t/File.swift
39+
// RUN: %target-swift-frontend -module-name User1 %t/File.swift -I %t -emit-module -emit-module-path %t/User1.swiftmodule -Rmodule-loading 2> %t/result-User1.output
40+
41+
/// Check User1.swiftmodule is created and Utils.swiftmodule and Logging.swiftmodule are loaded
42+
// RUN: test -f %t/User1.swiftmodule
43+
// RUN: %FileCheck %s -input-file %t/result-User1.output -check-prefix CHECK-1
44+
// CHECK-1: remark: loaded module at {{.*}}Logging.swiftmodule
45+
// CHECK-1: remark: loaded module at {{.*}}Utils.swiftmodule
46+
47+
/// Create a module User2 that imports both Utils and Logging, with module aliasing for Logging
48+
// RUN: echo 'import Logging' > %t/File.swift
49+
// RUN: echo 'import Utils' >> %t/File.swift
50+
// RUN: echo 'public func runUtils() { Utils.start() }' >> %t/File.swift
51+
// RUN: echo 'public func runLog() { _ = Logging.setup() }' >> %t/File.swift
52+
// RUN: %target-swift-frontend -module-name User2 -module-alias Logging=LoggingApple %t/File.swift -I %t -emit-module -emit-module-path %t/User2.swiftmodule -Rmodule-loading 2> %t/result-User2.output
53+
54+
/// Check User2.swiftmodule is created and Utils.swiftmodule and LoggingApple.swiftmodule are loaded but
55+
/// Logging.swiftmodule is not loaded.
56+
// RUN: test -f %t/User2.swiftmodule
57+
// RUN: %FileCheck %s -input-file %t/result-User2.output -check-prefix CHECK-2A
58+
// CHECK-2A: remark: loaded module at {{.*}}LoggingApple.swiftmodule
59+
// CHECK-2A: remark: loaded module at {{.*}}Utils.swiftmodule
60+
// RUN: not %FileCheck %s -input-file %t/result-User2.output -check-prefix CHECK-2B
61+
// CHECK-2B: remark: loaded module at {{.*}}Logging.swiftmodule
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/// Test the -module-alias flag with an explicit module loader.
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: mkdir -p %t/inputs
5+
// RUN: mkdir -p %t/outputs
6+
7+
/// Create a module Bar
8+
// RUN: echo 'public func bar() {}' > %t/inputs/FileBar.swift
9+
// RUN: %target-swift-frontend -module-name Bar %t/inputs/FileBar.swift -emit-module -emit-module-path %t/inputs/Bar.swiftmodule
10+
11+
/// Check Bar.swiftmodule is created
12+
// RUN: test -f %t/inputs/Bar.swiftmodule
13+
14+
/// Next create an explicit module dependency map to build module Foo
15+
// RUN: echo 'import Cat' > %t/inputs/FileFoo.swift
16+
17+
// RUN: echo "[{" > %/t/inputs/map.json
18+
// RUN: echo "\"moduleName\": \"Bar\"," >> %/t/inputs/map.json
19+
// RUN: echo "\"modulePath\": \"%/t/inputs/Bar.swiftmodule\"," >> %/t/inputs/map.json
20+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
21+
// RUN: echo "}," >> %/t/inputs/map.json
22+
// RUN: echo "{" >> %/t/inputs/map.json
23+
// RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json
24+
// RUN: echo "\"modulePath\": \"%/stdlib_module\"," >> %/t/inputs/map.json
25+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
26+
// RUN: echo "}," >> %/t/inputs/map.json
27+
// RUN: echo "{" >> %/t/inputs/map.json
28+
// RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json
29+
// RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %/t/inputs/map.json
30+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
31+
// RUN: echo "}," >> %/t/inputs/map.json
32+
// RUN: echo "{" >> %/t/inputs/map.json
33+
// RUN: echo "\"moduleName\": \"_Concurrency\"," >> %/t/inputs/map.json
34+
// RUN: echo "\"modulePath\": \"%/concurrency_module\"," >> %/t/inputs/map.json
35+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
36+
// RUN: echo "}]" >> %/t/inputs/map.json
37+
38+
/// Create a module Foo that imports Cat with -module-alias Cat=Bar with an explicit module loader
39+
// RUN: %target-swift-frontend -module-name Foo %t/inputs/FileFoo.swift -module-alias Cat=Bar -I %t/inputs -emit-module -emit-module-path %t/outputs/Foo.swiftmodule -disable-implicit-swift-modules -explicit-swift-module-map-file %t/inputs/map.json -Rmodule-loading 2> %t/outputs/load-result.output
40+
41+
// RUN: test -f %t/outputs/Foo.swiftmodule
42+
// RUN: test -f %t/inputs/Bar.swiftmodule
43+
// RUN: not test -f %t/inputs/Cat.swiftmodule
44+
45+
// RUN: %FileCheck %s -input-file %t/outputs/load-result.output -check-prefix CHECK
46+
// CHECK: remark: loaded module at {{.*}}Bar.swiftmodule
47+

0 commit comments

Comments
 (0)