diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 87bd5e118b3..257be51d1c9 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1848,12 +1848,27 @@ ASTContext::getLoadedModules() const { } ModuleDecl *ASTContext::getLoadedModule(Identifier ModuleName) const { - return getImpl().LoadedModules.lookup(ModuleName); + // Look up a loaded module using an actual module name (physical name + // on disk). If the -module-alias option is used, the module name that + // appears in source code will be different from the real module name + // on disk, otherwise the same. + // + // For example, if '-module-alias Foo=Bar' is passed in to the frontend, + // and a source file has 'import Foo', a module called Bar (real name) + // will be loaded and returned. + auto realName = getRealModuleName(ModuleName); + return getImpl().LoadedModules.lookup(realName); } void ASTContext::addLoadedModule(ModuleDecl *M) { assert(M); - getImpl().LoadedModules[M->getName()] = M; + // Add a loaded module using an actual module name (physical name + // on disk), in case -module-alias is used (otherwise same). + // + // For example, if '-module-alias Foo=Bar' is passed in to the frontend, + // and a source file has 'import Foo', a module called Bar (real name) + // will be loaded and added to the map. + getImpl().LoadedModules[M->getRealName()] = M; } void ASTContext::registerGenericSignatureBuilder( diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index 6db72727e64..d81eedd8641 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -1739,7 +1739,13 @@ bool ExplicitSwiftModuleLoader::findModule(ImportPath::Element ModuleID, std::unique_ptr *ModuleDocBuffer, std::unique_ptr *ModuleSourceInfoBuffer, bool skipBuildingInterface, bool &IsFramework, bool &IsSystemModule) { - StringRef moduleName = ModuleID.Item.str(); + // Find a module with an actual, physical name on disk, in case + // -module-alias is used (otherwise same). + // + // For example, if '-module-alias Foo=Bar' is passed in to the frontend, and an + // input file has 'import Foo', a module called Bar (real name) should be searched. + StringRef moduleName = Ctx.getRealModuleName(ModuleID.Item).str(); + auto it = Impl.ExplicitModuleMap.find(moduleName); // If no explicit module path is given matches the name, return with an // error code. diff --git a/lib/Sema/SourceLoader.cpp b/lib/Sema/SourceLoader.cpp index e46e5c8ae1e..45338794960 100644 --- a/lib/Sema/SourceLoader.cpp +++ b/lib/Sema/SourceLoader.cpp @@ -34,13 +34,20 @@ using namespace swift; // FIXME: Basically the same as SerializedModuleLoader. using FileOrError = llvm::ErrorOr>; -static FileOrError findModule(ASTContext &ctx, StringRef moduleID, +static FileOrError findModule(ASTContext &ctx, Identifier moduleID, SourceLoc importLoc) { llvm::SmallString<128> inputFilename; + // Find a module with an actual, physical name on disk, in case + // -module-alias is used (otherwise same). + // + // For example, if '-module-alias Foo=Bar' is passed in to the frontend, + // and a source file has 'import Foo', a module called Bar (real name) + // should be searched. + StringRef moduleNameRef = ctx.getRealModuleName(moduleID).str(); for (auto Path : ctx.SearchPathOpts.ImportSearchPaths) { inputFilename = Path; - llvm::sys::path::append(inputFilename, moduleID); + llvm::sys::path::append(inputFilename, moduleNameRef); inputFilename.append(".swift"); llvm::ErrorOr> FileBufOrErr = ctx.SourceMgr.getFileSystem()->getBufferForFile(inputFilename.str()); @@ -66,7 +73,7 @@ bool SourceLoader::canImportModule(ImportPath::Element ID, llvm::VersionTuple version, bool underlyingVersion) { // Search the memory buffers to see if we can find this file on disk. - FileOrError inputFileOrError = findModule(Ctx, ID.Item.str(), + FileOrError inputFileOrError = findModule(Ctx, ID.Item, ID.Loc); if (!inputFileOrError) { auto err = inputFileOrError.getError(); @@ -88,7 +95,7 @@ ModuleDecl *SourceLoader::loadModule(SourceLoc importLoc, auto moduleID = path[0]; - FileOrError inputFileOrError = findModule(Ctx, moduleID.Item.str(), + FileOrError inputFileOrError = findModule(Ctx, moduleID.Item, moduleID.Loc); if (!inputFileOrError) { auto err = inputFileOrError.getError(); diff --git a/lib/Serialization/SerializedModuleLoader.cpp b/lib/Serialization/SerializedModuleLoader.cpp index d7d88dcc24e..58a626e1a37 100644 --- a/lib/Serialization/SerializedModuleLoader.cpp +++ b/lib/Serialization/SerializedModuleLoader.cpp @@ -533,7 +533,14 @@ SerializedModuleLoaderBase::findModule(ImportPath::Element moduleID, std::unique_ptr *moduleDocBuffer, std::unique_ptr *moduleSourceInfoBuffer, bool skipBuildingInterface, bool &isFramework, bool &isSystemModule) { - SmallString<32> moduleName(moduleID.Item.str()); + // Find a module with an actual, physical name on disk, in case + // -module-alias is used (otherwise same). + // + // For example, if '-module-alias Foo=Bar' is passed in to the frontend, + // and a source file has 'import Foo', a module called Bar (real name) + // should be searched. + StringRef moduleNameRef = Ctx.getRealModuleName(moduleID.Item).str(); + SmallString<32> moduleName(moduleNameRef); SerializedModuleBaseName genericBaseName(moduleName); auto genericModuleFileName = @@ -1156,7 +1163,6 @@ bool MemoryBufferSerializedModuleLoader::canImportModule( assert(!(mIt->second.userVersion.empty())); return mIt->second.userVersion >= version; } - ModuleDecl * SerializedModuleLoaderBase::loadModule(SourceLoc importLoc, ImportPath::Module path) { @@ -1220,13 +1226,14 @@ MemoryBufferSerializedModuleLoader::loadModule(SourceLoc importLoc, return nullptr; auto moduleID = path[0]; + auto moduleName = Ctx.getRealModuleName(moduleID.Item).str(); // See if we find it in the registered memory buffers. // FIXME: Right now this works only with access paths of length 1. // Once submodules are designed, this needs to support suffix // matching and a search path. - auto bufIter = MemoryBuffers.find(moduleID.Item.str()); + auto bufIter = MemoryBuffers.find(moduleName); if (bufIter == MemoryBuffers.end()) return nullptr; diff --git a/test/Frontend/load-module-with-alias.swift b/test/Frontend/load-module-with-alias.swift new file mode 100644 index 00000000000..58b6368b072 --- /dev/null +++ b/test/Frontend/load-module-with-alias.swift @@ -0,0 +1,20 @@ +/// Test the -module-alias flag. + +// RUN: %empty-directory(%t) + +/// Create a module Bar +// RUN: echo 'public func bar() {}' > %t/FileBar.swift +// RUN: %target-swift-frontend -module-name Bar %t/FileBar.swift -emit-module -emit-module-path %t/Bar.swiftmodule + +/// Check if Bar.swiftmodule is created +// RUN: test -f %t/Bar.swiftmodule +// RUN: not test -f %t/Cat.swiftmodule + +/// Create a module Foo that imports Cat with -module-alias Cat=Bar +// RUN: echo 'import Cat' > %t/FileFoo.swift +// RUN: %target-swift-frontend -module-name Foo -module-alias Cat=Bar %t/FileFoo.swift -emit-module -emit-module-path %t/Foo.swiftmodule -I %t + +/// Check if Foo.swiftmodule is created without an error +// RUN: test -f %t/Foo.swiftmodule +// RUN: test -f %t/Bar.swiftmodule +// RUN: not test -f %t/Cat.swiftmodule