[flang-commits] [flang] [flang] Silence bogus USE statement error (PR #79896)
via flang-commits
flang-commits at lists.llvm.org
Mon Jan 29 12:52:19 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Peter Klausler (klausler)
<details>
<summary>Changes</summary>
When there are multiple USE statement for a particular module using renaming, it is necessary to collect a set of all of the original renaming targets before processing any of USE statements that don't have ONLY: clauses.
Currently, if there is a name in the module that can't be added to the current scope -- due to a conflict with an internal or module subprogram, or with a previously use-associated name -- the compiler will emit a bogus error message even if that conflicting name appear on a later USE statement of the same module as the target of a renaming.
The new regression test case added with this patch provides a motivating example.
---
Full diff: https://github.com/llvm/llvm-project/pull/79896.diff
2 Files Affected:
- (modified) flang/lib/Semantics/resolve-names.cpp (+35-31)
- (added) flang/test/Semantics/resolve122.f90 (+20)
``````````diff
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index af47327659632ab..6914f95837f676a 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -757,6 +757,7 @@ class ModuleVisitor : public virtual ScopeHandler {
void ApplyDefaultAccess();
Symbol &AddGenericUse(GenericDetails &, const SourceName &, const Symbol &);
void AddAndCheckModuleUse(SourceName, bool isIntrinsic);
+ void CollectUseRenames(const parser::UseStmt &);
void ClearUseRenames() { useRenames_.clear(); }
void ClearUseOnly() { useOnly_.clear(); }
void ClearModuleUses() {
@@ -769,8 +770,8 @@ class ModuleVisitor : public virtual ScopeHandler {
std::optional<SourceName> prevAccessStmt_;
// The scope of the module during a UseStmt
Scope *useModuleScope_{nullptr};
- // Names that have appeared in a rename clause of a USE statement
- std::set<std::pair<SourceName, Scope *>> useRenames_;
+ // Names that have appeared in a rename clause of USE statements
+ std::set<std::pair<SourceName, SourceName>> useRenames_;
// Names that have appeared in an ONLY clause of a USE statement
std::set<std::pair<SourceName, Scope *>> useOnly_;
// Intrinsic and non-intrinsic (explicit or not) module names that
@@ -790,14 +791,14 @@ class ModuleVisitor : public virtual ScopeHandler {
void DoAddUse(
SourceName, SourceName, Symbol &localSymbol, const Symbol &useSymbol);
void AddUse(const GenericSpecInfo &);
- // If appropriate, erase a previously USE-associated symbol
- void EraseRenamedUse(const Symbol *);
// Record a name appearing as the target of a USE rename clause
- void AddUseRename(const SourceName &name) {
- useRenames_.emplace(std::make_pair(name, useModuleScope_));
+ void AddUseRename(SourceName name, SourceName moduleName) {
+ useRenames_.emplace(std::make_pair(name, moduleName));
}
bool IsUseRenamed(const SourceName &name) const {
- return useRenames_.find({name, useModuleScope_}) != useRenames_.end();
+ return useModuleScope_ && useModuleScope_->symbol() &&
+ useRenames_.find({name, useModuleScope_->symbol()->name()}) !=
+ useRenames_.end();
}
// Record a name appearing in a USE ONLY clause
void AddUseOnly(const SourceName &name) {
@@ -2838,11 +2839,34 @@ bool ModuleVisitor::Pre(const parser::Only &x) {
return false;
}
+void ModuleVisitor::CollectUseRenames(const parser::UseStmt &useStmt) {
+ auto doRename{[&](const parser::Rename &rename) {
+ if (const auto *names{std::get_if<parser::Rename::Names>(&rename.u)}) {
+ AddUseRename(std::get<1>(names->t).source, useStmt.moduleName.source);
+ }
+ }};
+ common::visit(
+ common::visitors{
+ [&](const std::list<parser::Rename> &renames) {
+ for (const auto &rename : renames) {
+ doRename(rename);
+ }
+ },
+ [&](const std::list<parser::Only> &onlys) {
+ for (const auto &only : onlys) {
+ if (const auto *rename{std::get_if<parser::Rename>(&only.u)}) {
+ doRename(*rename);
+ }
+ }
+ },
+ },
+ useStmt.u);
+}
+
bool ModuleVisitor::Pre(const parser::Rename::Names &x) {
const auto &localName{std::get<0>(x.t)};
const auto &useName{std::get<1>(x.t)};
SymbolRename rename{AddUse(localName.source, useName.source)};
- AddUseRename(useName.source);
Resolve(useName, rename.use);
Resolve(localName, rename.local);
return false;
@@ -2970,31 +2994,8 @@ static bool ConvertToUseError(
}
}
-// If a symbol has previously been USE-associated and did not appear in
-// an ONLY clause or renaming, erase it from the current scope. This is
-// necessary when a name appears as the target of a later USE rename clause.
-void ModuleVisitor::EraseRenamedUse(const Symbol *useSymbol) {
- if (!useSymbol) {
- return;
- }
- const SourceName &name{useSymbol->name()};
- if (const Symbol * symbol{FindInScope(name)}) {
- if (const auto *useDetails{symbol->detailsIf<UseDetails>()}) {
- const Symbol &moduleSymbol{useDetails->symbol()};
- if (moduleSymbol.name() == name &&
- moduleSymbol.owner() == useSymbol->owner() && !IsUseOnly(name) &&
- !IsUseRenamed(name)) {
- EraseSymbol(*symbol);
- }
- }
- }
-}
-
void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
Symbol &originalLocal, const Symbol &useSymbol) {
- if (localName != useSymbol.name()) {
- EraseRenamedUse(&useSymbol);
- }
Symbol *localSymbol{&originalLocal};
if (auto *details{localSymbol->detailsIf<UseErrorDetails>()}) {
details->add_occurrence(location, *useModuleScope_);
@@ -8073,6 +8074,9 @@ bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
Walk(accDecls);
Walk(ompDecls);
Walk(compilerDirectives);
+ for (const auto &useStmt : useStmts) {
+ CollectUseRenames(useStmt.statement.value());
+ }
Walk(useStmts);
UseCUDABuiltinNames();
ClearUseRenames();
diff --git a/flang/test/Semantics/resolve122.f90 b/flang/test/Semantics/resolve122.f90
new file mode 100644
index 000000000000000..4dc7549c0407964
--- /dev/null
+++ b/flang/test/Semantics/resolve122.f90
@@ -0,0 +1,20 @@
+! RUN: %flang_fc1 -fsyntax-only -pedantic %s 2>&1 | FileCheck %s --allow-empty
+! Regression test for bogus use-association name conflict
+! CHECK-NOT: error:
+module m1
+ contains
+ subroutine s1
+ end
+ subroutine s2
+ end
+end
+
+module m2
+ use m1, s1a => s1
+ use m1, s2a => s2
+ contains
+ subroutine s1
+ end
+ subroutine s2
+ end
+end
``````````
</details>
https://github.com/llvm/llvm-project/pull/79896
More information about the flang-commits
mailing list