@@ -962,22 +962,91 @@ bool swift::extractCompilerFlagsFromInterface(StringRef buffer,
962962
963963bool SerializedModuleLoaderBase::canImportModule (
964964 ImportPath::Element mID , llvm::VersionTuple version, bool underlyingVersion) {
965+ // If underlying version is specified, this should be handled by Clang importer.
966+ if (!version.empty () && underlyingVersion)
967+ return false ;
965968 // Look on disk.
966- SmallVector <char , 0 > *unusedModuleInterfacePath = nullptr ;
969+ SmallVectorImpl <char > *unusedModuleInterfacePath = nullptr ;
967970 std::unique_ptr<llvm::MemoryBuffer> *unusedModuleBuffer = nullptr ;
968971 std::unique_ptr<llvm::MemoryBuffer> *unusedModuleDocBuffer = nullptr ;
969972 std::unique_ptr<llvm::MemoryBuffer> *unusedModuleSourceInfoBuffer = nullptr ;
970973 bool isFramework = false ;
971974 bool isSystemModule = false ;
972- return findModule (mID , unusedModuleInterfacePath, unusedModuleBuffer,
973- unusedModuleDocBuffer, unusedModuleSourceInfoBuffer,
974- isFramework, isSystemModule);
975+
976+ llvm::SmallString<256 > moduleInterfacePath;
977+ std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer;
978+ std::unique_ptr<llvm::MemoryBuffer> moduleDocBuffer;
979+ if (!version.empty ()) {
980+ unusedModuleInterfacePath = &moduleInterfacePath;
981+ unusedModuleBuffer = &moduleInputBuffer;
982+ unusedModuleDocBuffer = &moduleDocBuffer;
983+ }
984+
985+ auto found = findModule (mID , unusedModuleInterfacePath, unusedModuleBuffer,
986+ unusedModuleDocBuffer, unusedModuleSourceInfoBuffer,
987+ isFramework, isSystemModule);
988+ // If we cannot find the module, don't continue.
989+ if (!found)
990+ return false ;
991+ // If no version number is specified, don't continue.
992+ if (version.empty ())
993+ return true ;
994+ assert (found);
995+ assert (!version.empty ());
996+ assert (!underlyingVersion);
997+ llvm::VersionTuple currentVersion;
998+ if (!moduleInterfacePath.empty ()) {
999+ // Read the inteface file and extract its compiler arguments line
1000+ if (auto file = llvm::MemoryBuffer::getFile (moduleInterfacePath)) {
1001+ llvm::BumpPtrAllocator alloc;
1002+ llvm::StringSaver argSaver (alloc);
1003+ SmallVector<const char *, 8 > args;
1004+ (void )extractCompilerFlagsFromInterface ((*file)->getBuffer (), argSaver, args);
1005+ for (unsigned I = 0 , N = args.size (); I + 1 < N; I++) {
1006+ // Check the version number specified via -user-module-version.
1007+ StringRef current (args[I]), next (args[I + 1 ]);
1008+ if (current == " -user-module-version" ) {
1009+ currentVersion.tryParse (next);
1010+ break ;
1011+ }
1012+ }
1013+ }
1014+ }
1015+ // If failing to extract the user version from the interface file, try the binary
1016+ // format, if present.
1017+ if (currentVersion.empty () && unusedModuleBuffer) {
1018+ auto metaData =
1019+ serialization::validateSerializedAST ((*unusedModuleBuffer)->getBuffer ());
1020+ currentVersion = metaData.userModuleVersion ;
1021+ }
1022+
1023+ if (currentVersion.empty ()) {
1024+ Ctx.Diags .diagnose (mID .Loc , diag::cannot_find_project_version, " Swift" ,
1025+ mID .Item .str ());
1026+ return true ;
1027+ }
1028+
1029+ return currentVersion >= version;
9751030}
9761031
9771032bool MemoryBufferSerializedModuleLoader::canImportModule (
9781033 ImportPath::Element mID , llvm::VersionTuple version, bool underlyingVersion) {
979- // See if we find it in the registered memory buffers.
980- return MemoryBuffers.count (mID .Item .str ());
1034+ // If underlying version is specified, this should be handled by Clang importer.
1035+ if (!version.empty () && underlyingVersion)
1036+ return false ;
1037+ auto mIt = MemoryBuffers.find (mID .Item .str ());
1038+ if (mIt == MemoryBuffers.end ())
1039+ return false ;
1040+ if (version.empty ())
1041+ return true ;
1042+ if (mIt ->second .userVersion .empty ()) {
1043+ Ctx.Diags .diagnose (mID .Loc , diag::cannot_find_project_version, " Swift" ,
1044+ mID .Item .str ());
1045+ return true ;
1046+ }
1047+ assert (!version.empty ());
1048+ assert (!(mIt ->second .userVersion .empty ()));
1049+ return mIt ->second .userVersion >= version;
9811050}
9821051
9831052ModuleDecl *
@@ -1055,7 +1124,7 @@ MemoryBufferSerializedModuleLoader::loadModule(SourceLoc importLoc,
10551124
10561125 bool isFramework = false ;
10571126 std::unique_ptr<llvm::MemoryBuffer> moduleInputBuffer;
1058- moduleInputBuffer = std::move (bufIter->second );
1127+ moduleInputBuffer = std::move (bufIter->second . buffer );
10591128 MemoryBuffers.erase (bufIter);
10601129 assert (moduleInputBuffer);
10611130
0 commit comments