diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -346,6 +346,9 @@ * User (non-intrinsic) `ELEMENTAL` procedures may not be passed as actual arguments, in accordance with the standard; some Fortran compilers permit such usage. +* Constraint C1406, which prohibits the same module name from being used + in a scope for both an intrinsic and a non-intrinsic module, is implemented + as a portability warning only, not a hard error. ## Preprocessing behavior diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -740,12 +740,12 @@ bool BeginSubmodule(const parser::Name &, const parser::ParentIdentifier &); void ApplyDefaultAccess(); Symbol &AddGenericUse(GenericDetails &, const SourceName &, const Symbol &); - void AddAndCheckExplicitIntrinsicUse(SourceName, bool isIntrinsic); + void AddAndCheckModuleUse(SourceName, bool isIntrinsic); void ClearUseRenames() { useRenames_.clear(); } void ClearUseOnly() { useOnly_.clear(); } - void ClearExplicitIntrinsicUses() { - explicitIntrinsicUses_.clear(); - explicitNonIntrinsicUses_.clear(); + void ClearModuleUses() { + intrinsicUses_.clear(); + nonIntrinsicUses_.clear(); } private: @@ -759,10 +759,10 @@ std::set> useRenames_; // Names that have appeared in an ONLY clause of a USE statement std::set> useOnly_; - // Module names that have appeared in USE statements with explicit - // INTRINSIC or NON_INTRINSIC keywords - std::set explicitIntrinsicUses_; - std::set explicitNonIntrinsicUses_; + // Intrinsic and non-intrinsic (explicit or not) module names that + // have appeared in USE statements; used for C1406 warnings. + std::set intrinsicUses_; + std::set nonIntrinsicUses_; Symbol &SetAccess(const SourceName &, Attr attr, Symbol * = nullptr); // A rename in a USE statement: local => use @@ -2748,7 +2748,6 @@ std::optional isIntrinsic; if (x.nature) { isIntrinsic = *x.nature == parser::UseStmt::ModuleNature::Intrinsic; - AddAndCheckExplicitIntrinsicUse(x.moduleName.source, *isIntrinsic); } else if (currScope().IsModule() && currScope().symbol() && currScope().symbol()->attrs().test(Attr::INTRINSIC)) { // Intrinsic modules USE only other intrinsic modules @@ -2758,6 +2757,8 @@ if (!useModuleScope_) { return false; } + AddAndCheckModuleUse(x.moduleName.source, + useModuleScope_->parent().kind() == Scope::Kind::IntrinsicModules); // use the name from this source file useModuleScope_->symbol()->ReplaceName(x.moduleName.source); return true; @@ -3062,27 +3063,25 @@ return newSymbol; } -// Enforce C1406 -void ModuleVisitor::AddAndCheckExplicitIntrinsicUse( - SourceName name, bool isIntrinsic) { +// Enforce C1406 as a warning +void ModuleVisitor::AddAndCheckModuleUse(SourceName name, bool isIntrinsic) { if (isIntrinsic) { - if (auto iter{explicitNonIntrinsicUses_.find(name)}; - iter != explicitNonIntrinsicUses_.end()) { + if (auto iter{nonIntrinsicUses_.find(name)}; + iter != nonIntrinsicUses_.end()) { Say(name, - "Cannot USE,INTRINSIC module '%s' in the same scope as USE,NON_INTRINSIC"_err_en_US, + "Should not USE the intrinsic module '%s' in the same scope as a USE of the non-intrinsic module"_port_en_US, name) .Attach(*iter, "Previous USE of '%s'"_en_US, *iter); } - explicitIntrinsicUses_.insert(name); + intrinsicUses_.insert(name); } else { - if (auto iter{explicitIntrinsicUses_.find(name)}; - iter != explicitIntrinsicUses_.end()) { + if (auto iter{intrinsicUses_.find(name)}; iter != intrinsicUses_.end()) { Say(name, - "Cannot USE,NON_INTRINSIC module '%s' in the same scope as USE,INTRINSIC"_err_en_US, + "Should not USE the non-intrinsic module '%s' in the same scope as a USE of the intrinsic module"_port_en_US, name) .Attach(*iter, "Previous USE of '%s'"_en_US, *iter); } - explicitNonIntrinsicUses_.insert(name); + nonIntrinsicUses_.insert(name); } } @@ -7406,7 +7405,7 @@ Walk(useStmts); ClearUseRenames(); ClearUseOnly(); - ClearExplicitIntrinsicUses(); + ClearModuleUses(); Walk(importStmts); Walk(implicitPart); for (const auto &decl : decls) { diff --git a/flang/test/Semantics/modfile43.f90 b/flang/test/Semantics/modfile43.f90 --- a/flang/test/Semantics/modfile43.f90 +++ b/flang/test/Semantics/modfile43.f90 @@ -5,7 +5,7 @@ end module module m1 use, intrinsic :: iso_fortran_env, only: int32 - !ERROR: Cannot USE,NON_INTRINSIC module 'iso_fortran_env' in the same scope as USE,INTRINSIC + !PORTABILITY: Should not USE the non-intrinsic module 'iso_fortran_env' in the same scope as a USE of the intrinsic module use, non_intrinsic :: iso_fortran_env, only: user_defined_123 end module module m2