[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
Sun Mar 29 00:40:08 PDT 2026


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

Fixes #185344.
CC: @ohno-fj @kparzysz @NimishMishra 

>From 5e6a6bc555496bfe506a1a6612c3dbaca7320a02 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 implicit symbol resolution for
 USE-renamed arrays Fixes #185344. When an implicitly data-shared OpenMP array
 was an alias created via a USE rename, we were assigning the new OpenMP
 access entity the SourceName of the ultimate symbol instead of the local
 aliased symbol. This broke dimension checks for arrays with the same ultimate
 name but different subscripts across modules.

---
 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