]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fortran: ICE in gfc_conv_expr_present w. defined assignment [PR118640]
authorPaul Thomas <pault@gcc.gnu.org>
Mon, 27 Jan 2025 09:55:26 +0000 (09:55 +0000)
committerPaul Thomas <pault@gcc.gnu.org>
Mon, 27 Jan 2025 09:56:14 +0000 (09:56 +0000)
2025-01-27  Paul Thomas  <pault@gcc.gnu.org>

gcc/fortran
PR fortran/118640
* resolve.cc (generate_component_assignments): Make sure that
the rhs temporary does not pick up the optional attribute from
the lhs.

gcc/testsuite/
PR fortran/118640
* gfortran.dg/pr118640.f90: New test.

gcc/fortran/resolve.cc
gcc/testsuite/gfortran.dg/pr118640.f90 [new file with mode: 0644]

index 124f4ac4edcdca5406fd6b0e0e24cde95c4e5485..7f73d53e31ef11b8822974bf83e6c9fbd39fcb9f 100644 (file)
@@ -13383,7 +13383,12 @@ generate_component_assignments (gfc_code **code, gfc_namespace *ns)
       tmp_expr = get_temp_from_expr ((*code)->expr1, ns);
       if (tmp_expr->symtree->n.sym->attr.pointer)
        {
+         /* Use allocate on assignment for the sake of simplicity. The
+            temporary must not take on the optional attribute. Assume
+            that the assignment is guarded by a PRESENT condition if the
+            lhs is optional.  */
          tmp_expr->symtree->n.sym->attr.pointer = 0;
+         tmp_expr->symtree->n.sym->attr.optional = 0;
          tmp_expr->symtree->n.sym->attr.allocatable = 1;
        }
       this_code = build_assignment (EXEC_ASSIGN,
diff --git a/gcc/testsuite/gfortran.dg/pr118640.f90 b/gcc/testsuite/gfortran.dg/pr118640.f90
new file mode 100644 (file)
index 0000000..8f74dbf
--- /dev/null
@@ -0,0 +1,38 @@
+! { dg-do compile }
+!
+! Check the fix for an ICE in gfc_conv_expr_present, which resulted from
+! the rhs temporary picking up the optional attribute from the lhs in a
+! defined assignment.
+!
+! Contributed by Jakub Jelenik  <jakub@gcc.gnu.org>
+!
+module foo
+  type t1
+  contains
+    procedure bar
+    generic :: assignment(=) => bar
+  end type
+  type t2
+    type(t1) m
+  end type
+contains
+  subroutine bar (x, y)
+    intent(in) y
+    class(t1), intent(out) :: x
+  end subroutine
+end module
+subroutine baz (x, y)
+  use foo
+  integer y
+  type(t2), pointer, optional :: x
+  interface
+    function qux (x)
+      use foo
+      integer x
+      type(t2) qux
+    end function
+  end interface
+  if (present (x)) then
+    x = qux (y)  ! ICE was here
+  end if
+end subroutine