diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -928,49 +928,64 @@ return scope; } ancestorName = ancestor->GetName().value().ToString(); - } else { - if (!isIntrinsic.value_or(false)) { - auto it{context_.globalScope().find(name)}; - if (it != context_.globalScope().end()) { - Scope *scope{it->second->scope()}; - if (scope->kind() == Scope::Kind::Module) { - return scope; - } else { - notAModule = scope->symbol(); - // USE, NON_INTRINSIC global name isn't a module? - fatalError = isIntrinsic.has_value(); - } - } - } - if (isIntrinsic.value_or(true)) { - auto it{context_.intrinsicModulesScope().find(name)}; - if (it != context_.intrinsicModulesScope().end()) { - return it->second->scope(); + } + if (!isIntrinsic.value_or(false) && !ancestor) { + // Already present in the symbol table as a usable non-intrinsic module? + auto it{context_.globalScope().find(name)}; + if (it != context_.globalScope().end()) { + Scope *scope{it->second->scope()}; + if (scope->kind() == Scope::Kind::Module) { + return scope; + } else { + notAModule = scope->symbol(); + // USE, NON_INTRINSIC global name isn't a module? + fatalError = isIntrinsic.has_value(); } } } + auto path{ModFileName(name, ancestorName, context_.moduleFileSuffix())}; parser::Parsing parsing{context_.allCookedSources()}; parser::Options options; options.isModuleFile = true; options.features.Enable(common::LanguageFeature::BackslashEscapes); options.features.Enable(common::LanguageFeature::OpenMP); if (!isIntrinsic.value_or(false) && !notAModule) { - // Scan non-intrinsic module directories + // The search for this module file will scan non-intrinsic module + // directories. If a directory is in both the intrinsic and non-intrinsic + // directory lists, the intrinsic module directory takes precedence. options.searchDirectories = context_.searchDirectories(); - // If a directory is in both lists, the intrinsic module directory - // takes precedence. for (const auto &dir : context_.intrinsicModuleDirectories()) { std::remove(options.searchDirectories.begin(), options.searchDirectories.end(), dir); } options.searchDirectories.insert(options.searchDirectories.begin(), "."s); } + bool foundNonIntrinsicModuleFile{false}; + if (!isIntrinsic) { + std::list searchDirs; + for (const auto &d : options.searchDirectories) { + searchDirs.push_back(d); + } + foundNonIntrinsicModuleFile = + parser::LocateSourceFile(path, searchDirs).has_value(); + } + if (isIntrinsic.value_or(!foundNonIntrinsicModuleFile)) { + // Explicitly intrinsic, or not specified and not found in the search + // path; see whether it's already in the symbol table as an intrinsic + // module. + auto it{context_.intrinsicModulesScope().find(name)}; + if (it != context_.intrinsicModulesScope().end()) { + return it->second->scope(); + } + } + // We don't have this module in the symbol table yet. + // Find its module file and parse it. Define or extend the search + // path with intrinsic module directories, if appropriate. if (isIntrinsic.value_or(true)) { for (const auto &dir : context_.intrinsicModuleDirectories()) { options.searchDirectories.push_back(dir); } } - auto path{ModFileName(name, ancestorName, context_.moduleFileSuffix())}; const auto *sourceFile{fatalError ? nullptr : parsing.Prescan(path, options)}; if (fatalError || parsing.messages().AnyFatalError()) { if (!silent) {