[flang-commits] [flang] c322e92 - [flang] Silence bogus USE statement error (#79896)

via flang-commits flang-commits at lists.llvm.org
Mon Jan 29 14:51:51 PST 2024


Author: Peter Klausler
Date: 2024-01-29T14:51:47-08:00
New Revision: c322e92841fae1d756c4126a3e4c5e1b3366f042

URL: https://github.com/llvm/llvm-project/commit/c322e92841fae1d756c4126a3e4c5e1b3366f042
DIFF: https://github.com/llvm/llvm-project/commit/c322e92841fae1d756c4126a3e4c5e1b3366f042.diff

LOG: [flang] Silence bogus USE statement error (#79896)

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.

Added: 
    flang/test/Semantics/resolve122.f90

Modified: 
    flang/lib/Semantics/resolve-names.cpp

Removed: 
    


################################################################################
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..7bccd50f7a9144e
--- /dev/null
+++ b/flang/test/Semantics/resolve122.f90
@@ -0,0 +1,21 @@
+! RUN: %flang_fc1 -fsyntax-only -pedantic %s  2>&1 | FileCheck %s --allow-empty
+! Regression test for bogus use-association name conflict
+!   error: Cannot use-associate 's2'; it is already declared in this scope
+! 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


        


More information about the flang-commits mailing list