@@ -1242,7 +1242,7 @@ static void GetModuleDependences(
12421242 std::size_t limit{content.size ()};
12431243 std::string_view str{content.data (), limit};
12441244 for (std::size_t j{ModHeader::len};
1245- str.substr (j, ModHeader::needLen) == ModHeader::need;) {
1245+ str.substr (j, ModHeader::needLen) == ModHeader::need; ++j ) {
12461246 j += 7 ;
12471247 auto checkSum{ExtractCheckSum (str.substr (j, ModHeader::sumLen))};
12481248 if (!checkSum) {
@@ -1260,8 +1260,8 @@ static void GetModuleDependences(
12601260 for (; j < limit && str.at (j) != ' \n ' ; ++j) {
12611261 }
12621262 if (j > start && j < limit && str.at (j) == ' \n ' ) {
1263- dependences. AddDependence (
1264- std::string{str. substr (start, j - start)} , intrinsic, *checkSum);
1263+ std::string depModName{str. substr (start, j - start)};
1264+ dependences. AddDependence ( std::move (depModName) , intrinsic, *checkSum);
12651265 } else {
12661266 break ;
12671267 }
@@ -1271,7 +1271,7 @@ static void GetModuleDependences(
12711271Scope *ModFileReader::Read (SourceName name, std::optional<bool > isIntrinsic,
12721272 Scope *ancestor, bool silent) {
12731273 std::string ancestorName; // empty for module
1274- Symbol *notAModule{nullptr };
1274+ const Symbol *notAModule{nullptr };
12751275 bool fatalError{false };
12761276 if (ancestor) {
12771277 if (auto *scope{ancestor->FindSubmodule (name)}) {
@@ -1287,26 +1287,28 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
12871287 if (it != context_.globalScope ().end ()) {
12881288 Scope *scope{it->second ->scope ()};
12891289 if (scope->kind () == Scope::Kind::Module) {
1290- if (requiredHash) {
1291- if (const Symbol * foundModule{scope->symbol ()}) {
1292- if (const auto *module {foundModule->detailsIf <ModuleDetails>()};
1293- module && module ->moduleFileHash () &&
1294- *requiredHash != *module ->moduleFileHash ()) {
1295- Say (name, ancestorName,
1296- " Multiple versions of the module '%s' cannot be required by the same compilation" _err_en_US,
1297- name.ToString ());
1298- return nullptr ;
1290+ for (const Symbol *found{scope->symbol ()}; found;) {
1291+ if (const auto *module {found->detailsIf <ModuleDetails>()}) {
1292+ if (!requiredHash ||
1293+ *requiredHash ==
1294+ module ->moduleFileHash ().value_or (*requiredHash)) {
1295+ return const_cast <Scope *>(found->scope ());
12991296 }
1297+ found = module ->previous (); // same name, distinct hash
1298+ } else {
1299+ notAModule = found;
1300+ break ;
13001301 }
13011302 }
1302- return scope;
13031303 } else {
13041304 notAModule = scope->symbol ();
1305- // USE, NON_INTRINSIC global name isn't a module?
1306- fatalError = isIntrinsic.has_value ();
13071305 }
13081306 }
13091307 }
1308+ if (notAModule) {
1309+ // USE, NON_INTRINSIC global name isn't a module?
1310+ fatalError = isIntrinsic.has_value ();
1311+ }
13101312 auto path{ModFileName (name, ancestorName, context_.moduleFileSuffix ())};
13111313 parser::Parsing parsing{context_.allCookedSources ()};
13121314 parser::Options options;
@@ -1360,42 +1362,18 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
13601362
13611363 // Look for the right module file if its hash is known
13621364 if (requiredHash && !fatalError) {
1363- std::vector<std::string> misses;
13641365 for (const std::string &maybe :
13651366 parser::LocateSourceFileAll (path, options.searchDirectories )) {
13661367 if (const auto *srcFile{context_.allCookedSources ().allSources ().OpenPath (
13671368 maybe, llvm::errs ())}) {
1368- if (auto checkSum{VerifyHeader (srcFile->content ())}) {
1369- if (*checkSum == *requiredHash) {
1370- path = maybe;
1371- if (!misses.empty ()) {
1372- auto &msg{context_.Say (name,
1373- " Module file for '%s' appears later in the module search path than conflicting modules with different checksums" _warn_en_US,
1374- name.ToString ())};
1375- for (const std::string &m : misses) {
1376- msg.Attach (
1377- name, " Module file with a conflicting name: '%s'" _en_US, m);
1378- }
1379- }
1380- misses.clear ();
1381- break ;
1382- } else {
1383- misses.emplace_back (maybe);
1384- }
1369+ if (auto checkSum{VerifyHeader (srcFile->content ())};
1370+ checkSum && *checkSum == *requiredHash) {
1371+ path = maybe;
1372+ break ;
13851373 }
13861374 }
13871375 }
1388- if (!misses.empty ()) {
1389- auto &msg{Say (name, ancestorName,
1390- " Could not find a module file for '%s' in the module search path with the expected checksum" _err_en_US,
1391- name.ToString ())};
1392- for (const std::string &m : misses) {
1393- msg.Attach (name, " Module file with different checksum: '%s'" _en_US, m);
1394- }
1395- return nullptr ;
1396- }
13971376 }
1398-
13991377 const auto *sourceFile{fatalError ? nullptr : parsing.Prescan (path, options)};
14001378 if (fatalError || parsing.messages ().AnyFatalError ()) {
14011379 if (!silent) {
@@ -1451,11 +1429,24 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
14511429 Scope &topScope{isIntrinsic.value_or (false ) ? context_.intrinsicModulesScope ()
14521430 : context_.globalScope ()};
14531431 Symbol *moduleSymbol{nullptr };
1432+ const Symbol *previousModuleSymbol{nullptr };
14541433 if (!ancestor) { // module, not submodule
14551434 parentScope = &topScope;
14561435 auto pair{parentScope->try_emplace (name, UnknownDetails{})};
14571436 if (!pair.second ) {
1458- return nullptr ;
1437+ // There is already a global symbol or intrinsic module of the same name.
1438+ previousModuleSymbol = &*pair.first ->second ;
1439+ if (const auto *details{
1440+ previousModuleSymbol->detailsIf <ModuleDetails>()}) {
1441+ if (!details->moduleFileHash ().has_value ()) {
1442+ return nullptr ;
1443+ }
1444+ } else {
1445+ return nullptr ;
1446+ }
1447+ CHECK (parentScope->erase (name) != 0 );
1448+ pair = parentScope->try_emplace (name, UnknownDetails{});
1449+ CHECK (pair.second );
14591450 }
14601451 moduleSymbol = &*pair.first ->second ;
14611452 moduleSymbol->set (Symbol::Flag::ModFile);
@@ -1486,7 +1477,9 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
14861477 }
14871478 if (moduleSymbol) {
14881479 CHECK (moduleSymbol->test (Symbol::Flag::ModFile));
1489- moduleSymbol->get <ModuleDetails>().set_moduleFileHash (checkSum.value ());
1480+ auto &details{moduleSymbol->get <ModuleDetails>()};
1481+ details.set_moduleFileHash (checkSum.value ());
1482+ details.set_previous (previousModuleSymbol);
14901483 if (isIntrinsic.value_or (false )) {
14911484 moduleSymbol->attrs ().set (Attr::INTRINSIC);
14921485 }
0 commit comments