@@ -1242,7 +1242,7 @@ static void GetModuleDependences(
1242
1242
std::size_t limit{content.size ()};
1243
1243
std::string_view str{content.data (), limit};
1244
1244
for (std::size_t j{ModHeader::len};
1245
- str.substr (j, ModHeader::needLen) == ModHeader::need;) {
1245
+ str.substr (j, ModHeader::needLen) == ModHeader::need; ++j ) {
1246
1246
j += 7 ;
1247
1247
auto checkSum{ExtractCheckSum (str.substr (j, ModHeader::sumLen))};
1248
1248
if (!checkSum) {
@@ -1260,8 +1260,8 @@ static void GetModuleDependences(
1260
1260
for (; j < limit && str.at (j) != ' \n ' ; ++j) {
1261
1261
}
1262
1262
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);
1265
1265
} else {
1266
1266
break ;
1267
1267
}
@@ -1271,7 +1271,7 @@ static void GetModuleDependences(
1271
1271
Scope *ModFileReader::Read (SourceName name, std::optional<bool > isIntrinsic,
1272
1272
Scope *ancestor, bool silent) {
1273
1273
std::string ancestorName; // empty for module
1274
- Symbol *notAModule{nullptr };
1274
+ const Symbol *notAModule{nullptr };
1275
1275
bool fatalError{false };
1276
1276
if (ancestor) {
1277
1277
if (auto *scope{ancestor->FindSubmodule (name)}) {
@@ -1287,26 +1287,28 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
1287
1287
if (it != context_.globalScope ().end ()) {
1288
1288
Scope *scope{it->second ->scope ()};
1289
1289
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 ());
1299
1296
}
1297
+ found = module ->previous (); // same name, distinct hash
1298
+ } else {
1299
+ notAModule = found;
1300
+ break ;
1300
1301
}
1301
1302
}
1302
- return scope;
1303
1303
} else {
1304
1304
notAModule = scope->symbol ();
1305
- // USE, NON_INTRINSIC global name isn't a module?
1306
- fatalError = isIntrinsic.has_value ();
1307
1305
}
1308
1306
}
1309
1307
}
1308
+ if (notAModule) {
1309
+ // USE, NON_INTRINSIC global name isn't a module?
1310
+ fatalError = isIntrinsic.has_value ();
1311
+ }
1310
1312
auto path{ModFileName (name, ancestorName, context_.moduleFileSuffix ())};
1311
1313
parser::Parsing parsing{context_.allCookedSources ()};
1312
1314
parser::Options options;
@@ -1360,42 +1362,18 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
1360
1362
1361
1363
// Look for the right module file if its hash is known
1362
1364
if (requiredHash && !fatalError) {
1363
- std::vector<std::string> misses;
1364
1365
for (const std::string &maybe :
1365
1366
parser::LocateSourceFileAll (path, options.searchDirectories )) {
1366
1367
if (const auto *srcFile{context_.allCookedSources ().allSources ().OpenPath (
1367
1368
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 ;
1385
1373
}
1386
1374
}
1387
1375
}
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
- }
1397
1376
}
1398
-
1399
1377
const auto *sourceFile{fatalError ? nullptr : parsing.Prescan (path, options)};
1400
1378
if (fatalError || parsing.messages ().AnyFatalError ()) {
1401
1379
if (!silent) {
@@ -1451,11 +1429,24 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
1451
1429
Scope &topScope{isIntrinsic.value_or (false ) ? context_.intrinsicModulesScope ()
1452
1430
: context_.globalScope ()};
1453
1431
Symbol *moduleSymbol{nullptr };
1432
+ const Symbol *previousModuleSymbol{nullptr };
1454
1433
if (!ancestor) { // module, not submodule
1455
1434
parentScope = &topScope;
1456
1435
auto pair{parentScope->try_emplace (name, UnknownDetails{})};
1457
1436
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 );
1459
1450
}
1460
1451
moduleSymbol = &*pair.first ->second ;
1461
1452
moduleSymbol->set (Symbol::Flag::ModFile);
@@ -1486,7 +1477,9 @@ Scope *ModFileReader::Read(SourceName name, std::optional<bool> isIntrinsic,
1486
1477
}
1487
1478
if (moduleSymbol) {
1488
1479
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);
1490
1483
if (isIntrinsic.value_or (false )) {
1491
1484
moduleSymbol->attrs ().set (Attr::INTRINSIC);
1492
1485
}
0 commit comments