[flang-commits] [flang] [flang] Ignore -fno-realloc-lhs for polymorphic allocatable LHS with warning (PR #192697)

Eugene Epshteyn via flang-commits flang-commits at lists.llvm.org
Sun Apr 19 05:58:53 PDT 2026


https://github.com/eugeneepshteyn updated https://github.com/llvm/llvm-project/pull/192697

>From dad003517f01faf824eff2915d2951f755e29cb8 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Fri, 17 Apr 2026 12:48:58 -0400
Subject: [PATCH 1/3] [flang] Ignore -fno-realloc-lhs for polymorphic
 allocatable LHS with warning

When -fno-realloc-lhs is specified and the LHS of an assignment is a
polymorphic allocatable (class(*) or class(T)), reallocation semantics
are required by the Fortran 2003 standard for dynamic type tracking and
cannot be safely skipped.  Previously, the compiler generated invalid
FIR in such cases (type mismatch between i32 and
!fir.class<!fir.heap<none>>), causing a compilation error.

With this change, when -fno-realloc-lhs is in effect and a polymorphic
allocatable LHS is detected, the compiler emits a warning that the
option is being ignored for that assignment and proceeds with
reallocation semantics.
---
 flang/lib/Lower/Bridge.cpp          | 24 +++++++++++++++++++-----
 flang/test/Lower/reallocate-lhs.f90 | 20 ++++++++++++++++++--
 2 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 28c82a6ca99ce..2153c07e03020 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -5592,15 +5592,29 @@ class FirConverter : public Fortran::lower::AbstractConverter {
 
     // Gather some information about the assignment that will impact how it is
     // lowered.
-    const bool isWholeAllocatableAssignment =
+    const bool lhsIsWholeAllocatable =
         !userDefinedAssignment && !isInsideHlfirWhere() &&
-        Fortran::lower::isWholeAllocatable(assign.lhs) &&
-        bridge.getLoweringOptions().getReallocateLHS();
+        Fortran::lower::isWholeAllocatable(assign.lhs);
+    std::optional<Fortran::evaluate::DynamicType> lhsType =
+        assign.lhs.GetType();
+    // Polymorphic allocatable LHS always requires reallocation semantics
+    // regardless of -fno-realloc-lhs: assignment to a polymorphic variable
+    // is a F2003+ feature that requires dynamic type tracking, which cannot
+    // be safely skipped.  When -fno-realloc-lhs is specified but the LHS is
+    // polymorphic, emit a warning and proceed with reallocation semantics.
+    const bool lhsIsPolymorphic =
+        lhsType.has_value() && lhsType->IsPolymorphic();
+    if (lhsIsWholeAllocatable && lhsIsPolymorphic &&
+        !bridge.getLoweringOptions().getReallocateLHS())
+      mlir::emitWarning(loc,
+                        "-fno-realloc-lhs is ignored for assignment to "
+                        "polymorphic allocatable");
+    const bool isWholeAllocatableAssignment =
+        lhsIsWholeAllocatable &&
+        (bridge.getLoweringOptions().getReallocateLHS() || lhsIsPolymorphic);
     const bool isUserDefAssignToPointerOrAllocatable =
         userDefinedAssignment &&
         firstDummyIsPointerOrAllocatable(*userDefinedAssignment);
-    std::optional<Fortran::evaluate::DynamicType> lhsType =
-        assign.lhs.GetType();
     const bool keepLhsLengthInAllocatableAssignment =
         isWholeAllocatableAssignment && lhsType.has_value() &&
         lhsType->category() == Fortran::common::TypeCategory::Character &&
diff --git a/flang/test/Lower/reallocate-lhs.f90 b/flang/test/Lower/reallocate-lhs.f90
index 82a4edab787c7..7b65d6b6a9741 100644
--- a/flang/test/Lower/reallocate-lhs.f90
+++ b/flang/test/Lower/reallocate-lhs.f90
@@ -1,9 +1,13 @@
 ! RUN: bbc %s -o - -emit-hlfir | FileCheck %s --check-prefixes=ALL,REALLOCLHS
 ! RUN: bbc %s -o - -emit-hlfir -frealloc-lhs | FileCheck %s --check-prefixes=ALL,REALLOCLHS
-! RUN: bbc %s -o - -emit-hlfir -frealloc-lhs=false | FileCheck %s --check-prefixes=ALL,NOREALLOCLHS
+! RUN: bbc %s -o - -emit-hlfir -frealloc-lhs=false 2>&1 | FileCheck %s --check-prefixes=ALL,NOREALLOCLHS,POLYWARNING
 ! RUN: %flang_fc1 %s -o - -emit-hlfir | FileCheck %s --check-prefixes=ALL,REALLOCLHS
 ! RUN: %flang_fc1 %s -o - -emit-hlfir -frealloc-lhs | FileCheck %s --check-prefixes=ALL,REALLOCLHS
-! RUN: %flang_fc1 %s -o - -emit-hlfir -fno-realloc-lhs | FileCheck %s --check-prefixes=ALL,NOREALLOCLHS
+! RUN: %flang_fc1 %s -o - -emit-hlfir -fno-realloc-lhs 2>&1 | FileCheck %s --check-prefixes=ALL,NOREALLOCLHS,POLYWARNING
+
+! -fno-realloc-lhs must be ignored for polymorphic allocatable LHS (test3 below).
+! The warning below is emitted before the MLIR output, so it must be checked first.
+! POLYWARNING: warning: {{.*}}-fno-realloc-lhs is ignored for assignment to polymorphic allocatable left-hand side
 
 subroutine test1(a, b)
   integer, allocatable :: a(:), b(:)
@@ -30,3 +34,15 @@ end subroutine test2
 ! NOREALLOCLHS:  %[[VAL_7:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>>
 ! NOREALLOCLHS:  hlfir.assign %{{.*}} to %[[VAL_7]] : !fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.box<!fir.heap<!fir.array<?x!fir.char<1,?>>>>
 
+! Polymorphic allocatable LHS: reallocation semantics must be used regardless of
+! -fno-realloc-lhs, because the Fortran standard requires dynamic type tracking
+! for polymorphic assignments (a F2003+ feature that cannot be safely skipped).
+subroutine test3(x)
+  class(*), allocatable :: x
+  x = 1
+end subroutine test3
+
+! ALL-LABEL:   func.func @_QPtest3(
+! ALL:           %[[VAL_1:.*]]:2 = hlfir.declare{{.*}}{fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest3Ex"}
+! ALL:           hlfir.assign %{{.*}} to %[[VAL_1]]#0 realloc : i32, !fir.ref<!fir.class<!fir.heap<none>>>
+

>From 932d0c05c4e25df83cb3d487184ea125562229e6 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Fri, 17 Apr 2026 12:59:28 -0400
Subject: [PATCH 2/3] I didn't change the message everywhere. Fixed

---
 flang/test/Lower/reallocate-lhs.f90 | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/flang/test/Lower/reallocate-lhs.f90 b/flang/test/Lower/reallocate-lhs.f90
index 7b65d6b6a9741..cf01f304eda44 100644
--- a/flang/test/Lower/reallocate-lhs.f90
+++ b/flang/test/Lower/reallocate-lhs.f90
@@ -7,7 +7,7 @@
 
 ! -fno-realloc-lhs must be ignored for polymorphic allocatable LHS (test3 below).
 ! The warning below is emitted before the MLIR output, so it must be checked first.
-! POLYWARNING: warning: {{.*}}-fno-realloc-lhs is ignored for assignment to polymorphic allocatable left-hand side
+! POLYWARNING: warning: {{.*}}-fno-realloc-lhs is ignored for assignment to polymorphic allocatable
 
 subroutine test1(a, b)
   integer, allocatable :: a(:), b(:)

>From c03ccc46e8507877a8b2b2d7522634cdf1191639 Mon Sep 17 00:00:00 2001
From: Eugene Epshteyn <eepshteyn at nvidia.com>
Date: Fri, 17 Apr 2026 12:59:46 -0400
Subject: [PATCH 3/3] clang-format

---
 flang/lib/Lower/Bridge.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 2153c07e03020..bbdd7ded1c84e 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -5606,9 +5606,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
         lhsType.has_value() && lhsType->IsPolymorphic();
     if (lhsIsWholeAllocatable && lhsIsPolymorphic &&
         !bridge.getLoweringOptions().getReallocateLHS())
-      mlir::emitWarning(loc,
-                        "-fno-realloc-lhs is ignored for assignment to "
-                        "polymorphic allocatable");
+      mlir::emitWarning(loc, "-fno-realloc-lhs is ignored for assignment to "
+                             "polymorphic allocatable");
     const bool isWholeAllocatableAssignment =
         lhsIsWholeAllocatable &&
         (bridge.getLoweringOptions().getReallocateLHS() || lhsIsPolymorphic);



More information about the flang-commits mailing list