diff --git a/flang/docs/ModFiles.md b/flang/docs/ModFiles.md index cde2e4218d6fd..dd0ade5cebbfc 100644 --- a/flang/docs/ModFiles.md +++ b/flang/docs/ModFiles.md @@ -98,7 +98,14 @@ Entities that have been included in a module by means of USE association are represented in the module file with `USE` statements. Name aliases are sometimes necessary when an entity from another module is needed for a declaration and conflicts with another -entity of the same name. +entity of the same name, or is `PRIVATE`. +These aliases have currency symbols (`$`) in them. +When a module +is parsed from a module file, no error is emitted for associating +such an alias with a `PRIVATE` name. +A module parsed from another source file that is not a module file +(notably, the output of the `-fdebug-unparse-with-modules` option) +will emit only warnings. ## Reading and writing module files diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 74367b5229548..7ec6252530d55 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -3325,9 +3325,19 @@ ModuleVisitor::SymbolRename ModuleVisitor::AddUse( // Privacy is not enforced in module files so that generic interfaces // can be resolved to private specific procedures in specification // expressions. - Say(useName, "'%s' is PRIVATE in '%s'"_err_en_US, MakeOpName(useName), - useModuleScope_->GetName().value()); - return {}; + // Local names that contain currency symbols ('$') are created by the + // module file writer when a private name in another module is needed to + // process a local declaration. These can show up in the output of + // -fdebug-unparse-with-modules, too, so go easy on them. + if (currScope().IsModule() && + localName.ToString().find("$") != std::string::npos) { + Say(useName, "'%s' is PRIVATE in '%s'"_warn_en_US, MakeOpName(useName), + useModuleScope_->GetName().value()); + } else { + Say(useName, "'%s' is PRIVATE in '%s'"_err_en_US, MakeOpName(useName), + useModuleScope_->GetName().value()); + return {}; + } } auto &localSymbol{MakeSymbol(localName)}; DoAddUse(useName, localName, localSymbol, *useSymbol); diff --git a/flang/test/Semantics/resolve11.f90 b/flang/test/Semantics/resolve11.f90 index db508f062d1d1..39a30b858ebb6 100644 --- a/flang/test/Semantics/resolve11.f90 +++ b/flang/test/Semantics/resolve11.f90 @@ -86,3 +86,17 @@ subroutine s5 use m5, only: foo, fun print *, fun() ! ok end + +module m6 + !WARNING: 'foo' is PRIVATE in 'm5' + use m5, only: name$with$dollar => foo + !ERROR: 'foo' is PRIVATE in 'm5' + use m5, only: normal_name => foo +end + +subroutine s6 + !The special dispensation for USE association of private names to local + !aliases with '$' in them only applies to modules. + !ERROR: 'foo' is PRIVATE in 'm5' + use m5, only: name$with$dollar => foo +end