[flang-commits] [flang] [Flang][OpenMP] Fix implicit symbol resolution for USE-renamed arrays (PR #189215)

Aditya Trivedi via flang-commits flang-commits at lists.llvm.org
Mon Mar 30 05:52:15 PDT 2026


https://github.com/adit4443ya updated https://github.com/llvm/llvm-project/pull/189215

>From 9de86c3ad832548778980f36b39be5490346e97f Mon Sep 17 00:00:00 2001
From: Aditya Trivedi <adit4443ya at gmail.com>
Date: Sun, 29 Mar 2026 07:36:33 +0000
Subject: [PATCH] [Flang][OpenMP] Fix rank mismatch for USE-renamed arrays in
 OpenMP regions

When a module array is imported with a local alias via USE renaming
(e.g. USE mod, ONLY: s_ary => ary), the OpenMP implicit symbol
resolution was incorrectly creating the new scoped symbol using the
ultimate symbol's name ("ary") rather than the local alias ("s_ary").
This caused a false rank mismatch error if another array named "ary"
existed with different dimensions.

Fixed by passing the local symbol's SourceName explicitly to
DeclareNewAccessEntity when creating implicit DSA symbols.

Fixes #185344
---
 flang/lib/Semantics/resolve-directives.cpp    | 47 +++++++++++--------
 .../Semantics/OpenMP/use-rename-array-dsa.f90 | 38 +++++++++++++++
 2 files changed, 66 insertions(+), 19 deletions(-)
 create mode 100644 flang/test/Semantics/OpenMP/use-rename-array-dsa.f90

diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index d5cfcabc319ab..1c16a6b00ac13 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -174,6 +174,8 @@ template <typename T> class DirectiveAttributeVisitor {
   const parser::DoConstruct *GetDoConstructIf(
       const parser::ExecutionPartConstruct &);
   Symbol *DeclareNewAccessEntity(const Symbol &, Symbol::Flag, Scope &);
+  Symbol *DeclareNewAccessEntity(
+      const SourceName &, const Symbol &, Symbol::Flag, Scope &);
   Symbol *DeclareAccessEntity(const parser::Name &, Symbol::Flag, Scope &);
   Symbol *DeclareAccessEntity(Symbol &, Symbol::Flag, Scope &);
   Symbol *DeclareOrMarkOtherAccessEntity(const parser::Name &, Symbol::Flag);
@@ -1210,8 +1212,15 @@ const parser::DoConstruct *DirectiveAttributeVisitor<T>::GetDoConstructIf(
 template <typename T>
 Symbol *DirectiveAttributeVisitor<T>::DeclareNewAccessEntity(
     const Symbol &object, Symbol::Flag flag, Scope &scope) {
+  return DeclareNewAccessEntity(object.name(), object, flag, scope);
+}
+
+template <typename T>
+Symbol *DirectiveAttributeVisitor<T>::DeclareNewAccessEntity(
+    const SourceName &name, const Symbol &object, Symbol::Flag flag,
+    Scope &scope) {
   assert(object.owner() != currScope());
-  auto &symbol{MakeAssocSymbol(object.name(), object, scope)};
+  auto &symbol{MakeAssocSymbol(name, object, scope)};
   symbol.set(flag);
   if (flag == Symbol::Flag::OmpCopyIn) {
     // The symbol in copyin clause must be threadprivate entity.
@@ -1538,18 +1547,18 @@ bool AccAttributeVisitor::Pre(const parser::OpenACCCombinedConstruct &x) {
 static bool IsLastNameArray(const parser::Designator &designator) {
   const auto &name{GetLastName(designator)};
   const evaluate::DataRef dataRef{*(name.symbol)};
-  return common::visit(
-      common::visitors{
-          [](const evaluate::SymbolRef &ref) {
-            return ref->Rank() > 0 ||
-                ref->GetType()->category() == DeclTypeSpec::Numeric;
-          },
-          [](const evaluate::ArrayRef &aref) {
-            return aref.base().IsSymbol() ||
-                aref.base().GetComponent().base().Rank() == 0;
-          },
-          [](const auto &) { return false; },
-      },
+  return common::visit(common::visitors{
+                           [](const evaluate::SymbolRef &ref) {
+                             return ref->Rank() > 0 ||
+                                 ref->GetType()->category() ==
+                                 DeclTypeSpec::Numeric;
+                           },
+                           [](const evaluate::ArrayRef &aref) {
+                             return aref.base().IsSymbol() ||
+                                 aref.base().GetComponent().base().Rank() == 0;
+                           },
+                           [](const auto &) { return false; },
+                       },
       dataRef.u);
 }
 
@@ -1748,10 +1757,10 @@ void AccAttributeVisitor::CheckAssociatedLoop(
   using Bounds = parser::LoopControl::Bounds;
   for (const parser::DoConstruct *loop{&outerDoConstruct}; loop && level > 0;) {
     // Go through all nested loops to ensure index variable exists.
-    if (const parser::Name * ivName{GetLoopIndex(*loop)}) {
+    if (const parser::Name *ivName{GetLoopIndex(*loop)}) {
       if (auto *symbol{ResolveAcc(*ivName, flag, currScope())}) {
         if (auto &control{loop->GetLoopControl()}) {
-          if (const Bounds * b{std::get_if<Bounds>(&control->u)}) {
+          if (const Bounds *b{std::get_if<Bounds>(&control->u)}) {
             if (auto lowerExpr{semantics::AnalyzeExpr(context_, b->Lower())}) {
               semantics::UnorderedSymbolSet lowerSyms =
                   evaluate::CollectSymbols(*lowerExpr);
@@ -2095,7 +2104,7 @@ void OmpAttributeVisitor::ResolveSeqLoopIndexInParallelOrTaskConstruct(
   }
   // If this symbol already has a data-sharing attribute then there is nothing
   // to do here.
-  if (const Symbol * symbol{iv.symbol}) {
+  if (const Symbol *symbol{iv.symbol}) {
     for (auto symMap : targetIt->objectWithDSA) {
       if (symMap.first->name() == symbol->name()) {
         return;
@@ -2740,8 +2749,8 @@ void OmpAttributeVisitor::CreateImplicitSymbols(
           lastDeclSymbol ? lastDeclSymbol : &symbol->GetUltimate();
       assert(flags.LeastElement());
       Symbol::Flag flag = *flags.LeastElement();
-      lastDeclSymbol = DeclareNewAccessEntity(
-          *hostSymbol, flag, context_.FindScope(dirContext.directiveSource));
+      lastDeclSymbol = DeclareNewAccessEntity(symbol->name(), *hostSymbol, flag,
+          context_.FindScope(dirContext.directiveSource));
       lastDeclSymbol->flags() |= flags;
       return lastDeclSymbol;
     };
@@ -3058,7 +3067,7 @@ Symbol *OmpAttributeVisitor::ResolveOmpCommonBlockName(
     return nullptr;
   }
   if (auto *cb{GetProgramUnitOrBlockConstructContaining(GetContext().scope)
-                   .FindCommonBlock(name->source)}) {
+              .FindCommonBlock(name->source)}) {
     name->symbol = cb;
     return cb;
   }
diff --git a/flang/test/Semantics/OpenMP/use-rename-array-dsa.f90 b/flang/test/Semantics/OpenMP/use-rename-array-dsa.f90
new file mode 100644
index 0000000000000..ea32d04afb4aa
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/use-rename-array-dsa.f90
@@ -0,0 +1,38 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
+
+! Check that compiling a USE-renamed array inside an OpenMP construct
+! does not trigger a dimension mismatch error against the original symbol name.
+
+module mod1
+  implicit none
+  real(8), allocatable :: ary(:,:,:)
+end module mod1
+
+module mod2
+  implicit none
+  real(8), allocatable :: ary(:,:,:,:,:)
+end module mod2
+
+module mod3
+  implicit none
+contains
+  subroutine sub(arg)
+    use mod1, only: s_ary => ary
+    use mod2, only: ary
+    implicit none
+    integer(4), intent(in) :: arg
+    integer(4) :: i, j, k
+    integer(4) :: xx, yy, zs, ze, mm
+
+    !$omp parallel do
+    do j = 0, yy+1
+      do i = 0, xx+1
+        do k = zs, ze
+          s_ary(k,i,j) = s_ary(k,i,j) + ary(k,-1,i,j,mm)
+          ary(k,-1,i,j,mm) = 0._8
+        end do
+      end do
+    end do
+    !$omp end parallel do
+  end subroutine sub
+end module mod3



More information about the flang-commits mailing list