[PATCH] Fortran: fix ICE on LOC intrinsic with polymorphic argument [PR125606]

Harald Anlauf <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.fortran
Message-ID <[email protected]>
Dear all,

this patch fixes a 15/16/17 regression when using the LOC() intrinsic
on SELECT TYPE temporaries, where gfc_is_simply_contiguous could
return false and gfc_conv_array_parameter would create unnecessarily
messy code that lead to an ICE.

I looked at how C_LOC solved this, and adjusted gfc_conv_intrinsic_loc
accordingly.

Regtested on x86_64-pc-linux-gnu.  OK for mainline / 16 / 15?

Thanks,
Harald
pr125606.diff (text/x-patch, 2.9 KB)
From 2dcdb2463f89930b8cdd2b15f962bd3df5dd83f7 Mon Sep 17 00:00:00 2001
From: Harald Anlauf <[email protected]>
Date: Sat, 6 Jun 2026 21:59:49 +0200
Subject: [PATCH] Fortran: fix ICE on LOC intrinsic with polymorphic argument
 [PR125606]

The fix for PR122977 improved the gfc_is_simply_contiguous check for
associate variables, but had a side effect when using the LOC() intrinsic
on SELECT TYPE temporaries where gfc_is_simply_contiguous could return
false.  Fall back to simply taking the address of the variable's address.

	PR fortran/125606

gcc/fortran/ChangeLog:

	* trans-intrinsic.cc (gfc_conv_intrinsic_loc): When the argument
	of LOC() is not scalar or known to be simply contiguous, simply
	take the address of the argument array's first element.

gcc/testsuite/ChangeLog:

	* gfortran.dg/loc_3.f90: New test.
---
 gcc/fortran/trans-intrinsic.cc      |  8 ++++++-
 gcc/testsuite/gfortran.dg/loc_3.f90 | 36 +++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gfortran.dg/loc_3.f90

diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index fdb9ddb52ea..a2a6c6979d9 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -9829,9 +9829,15 @@ gfc_conv_intrinsic_loc (gfc_se * se, gfc_expr * expr)
 	gfc_add_data_component (arg_expr);
       gfc_conv_expr_reference (se, arg_expr);
     }
-  else
+  else if (gfc_is_simply_contiguous (arg_expr, false, false))
     gfc_conv_array_parameter (se, arg_expr, true, NULL, NULL, NULL);
+  else
+    {
+      gfc_conv_expr_descriptor (se, arg_expr);
+      se->expr = gfc_conv_descriptor_data_get (se->expr);
+    }
   se->expr = convert (gfc_get_int_type (gfc_index_integer_kind), se->expr);
+  se->expr = gfc_evaluate_now (se->expr, &se->pre);
 
   /* Create a temporary variable for loc return value.  Without this,
      we get an error an ICE in gcc/expr.cc(expand_expr_addr_expr_1).  */
diff --git a/gcc/testsuite/gfortran.dg/loc_3.f90 b/gcc/testsuite/gfortran.dg/loc_3.f90
new file mode 100644
index 00000000000..efc7d0e56e7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/loc_3.f90
@@ -0,0 +1,36 @@
+! { dg-do compile }
+! { dg-additional-options "-O1" }
+!
+! PR fortran/125606
+!
+! Derived from Fujitsu testsuite
+! Reported by David Binderman
+
+module m
+  implicit none
+  type ty
+     class(*), allocatable :: c1(:)
+  end type ty
+  type tt
+     class(*), allocatable :: node1(:)
+  end type tt
+  type,extends(tt)::tte
+     class(*), allocatable :: c2e(:)
+  end type tte
+contains
+  subroutine put_addr
+    class(*), allocatable :: t(:)
+    integer :: unit
+    select type (t)
+    class is (tt)
+       select type (p=>t(2)%node1)
+       class is (ty)
+          write (unit) loc(p(2)%c1)
+       end select
+       select type (t)
+       type is (tte)
+          write (7) loc(t(2)%c2e)
+       end select
+    end select
+  end subroutine put_addr
+end module m
-- 
2.51.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.