[flang-commits] [flang] [flang][Semantics] Warn on repeated do-variable in nested I/O implied DO (PR #198757)

Eugene Epshteyn via flang-commits flang-commits at lists.llvm.org
Wed May 20 06:25:30 PDT 2026


================
@@ -1191,16 +1191,70 @@ static void CheckIoImpliedDoIndex(
   }
 }
 
+// F2023 12.6.3p7: The do-variable of an io-implied-do that is in another
+// io-implied-do shall not appear as, nor be associated with, the do-variable
+// of the containing io-implied-do.
+void DoForallChecker::CheckActiveIoImpliedDoVar(const parser::Name &name) {
+  if (!name.symbol) {
+    return;
+  }
+  const Symbol &resolved{ResolveAssociations(*name.symbol)};
+  const EquivalenceSet *equivSet{FindEquivalenceSet(resolved)};
+  for (const Symbol *active : activeIoImpliedDoVars_) {
+    const Symbol &activeResolved{ResolveAssociations(*active)};
+    bool associated{&resolved == &activeResolved};
+    if (!associated && equivSet) {
+      for (const EquivalenceObject &obj : *equivSet) {
+        if (obj.symbol == activeResolved) {
+          associated = true;
+          break;
+        }
+      }
+    }
+    if (associated) {
+      if (name.symbol == active) {
+        context_.Warn(common::UsageWarning::IoImpliedDoIndexConflict,
+            name.source,
+            "I/O implied DO index '%s' appears in an enclosing I/O implied DO loop and should not have the same name"_warn_en_US,
+            name.source);
+      } else {
+        context_.Warn(common::UsageWarning::IoImpliedDoIndexConflict,
+            name.source,
+            "I/O implied DO index '%s' should not be associated with do-variable '%s' of an enclosing I/O implied DO loop"_warn_en_US,
+            name.source, active->name());
+      }
+      break;
+    }
+  }
+  activeIoImpliedDoVars_.insert(name.symbol);
+}
+
+void DoForallChecker::Enter(const parser::OutputImpliedDo &outputImpliedDo) {
+  CheckActiveIoImpliedDoVar(parser::UnwrapRef<parser::Name>(
+      std::get<parser::IoImpliedDoControl>(outputImpliedDo.t).Name()));
+}
+
+void DoForallChecker::Enter(const parser::InputImpliedDo &inputImpliedDo) {
+  CheckActiveIoImpliedDoVar(parser::UnwrapRef<parser::Name>(
+      std::get<parser::IoImpliedDoControl>(inputImpliedDo.t).Name()));
+}
+
 void DoForallChecker::Leave(const parser::OutputImpliedDo &outputImpliedDo) {
-  CheckIoImpliedDoIndex(context_,
-      parser::UnwrapRef<parser::Name>(
-          std::get<parser::IoImpliedDoControl>(outputImpliedDo.t).Name()));
+  const auto &name{parser::UnwrapRef<parser::Name>(
+      std::get<parser::IoImpliedDoControl>(outputImpliedDo.t).Name())};
+  CheckIoImpliedDoIndex(context_, name);
+  if (name.symbol) {
----------------
eugeneepshteyn wrote:

AI reviewer is concerned that this will break with sufficient nesting. Could you please check?
```
program p
  integer :: cube(5,5,5), i, j, k
  write(*,*) (((cube(i,j,k), k=1,5), (cube(i,j,k), k=1,5), j=1,5), k=1,5)
end
```

https://github.com/llvm/llvm-project/pull/198757


More information about the flang-commits mailing list