Hello,

Le 20/01/2024 à 22:58, Harald Anlauf a écrit :
Dear all,

here's the first part of an attempt to fix issues with optional
dummy arguments as actual arguments to optional dummies.  This patch
rectifies the case of scalar dummies with the VALUE attribute,
which in gfortran's argument passing convention are passed on the
stack when they are of intrinsic type, and have a hidden variable
for the presence status.

The testcase tries to cover valid combinations of actual and dummy
argument.  A few tests that are not standard-conforming but would
still work with gfortran (due to the argument passing convention)
are left there but commented out with a pointer to the standard
(thanks, Mikael!).

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

Well, not yet.


diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 9dd1f4086f4..2f47a75955c 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -6526,6 +6526,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
                            gfc_init_se (&argse, NULL);
                            argse.want_pointer = 1;
                            gfc_conv_expr (&argse, e);
+                           if (e->symtree->n.sym->attr.dummy
+                               && POINTER_TYPE_P (TREE_TYPE (argse.expr)))
+                             argse.expr = gfc_build_addr_expr (NULL_TREE,
+                                                               argse.expr);

The second part of the condition looks superfluous: if argse.want_pointer was set, we can expect to get a pointer result.

But more important, I don't understand the need for this whole part, the new test seems to pass without it.
And here is an example that regresses with it.

program p
  type :: t
    integer, allocatable :: c
  end type
  call s2(t())
contains
  subroutine s1(a)
    integer, value, optional :: a
    if (present(a)) stop 1
  end subroutine
  subroutine s2(a)
    type(t) :: a
    call s1(a%c)
  end subroutine
end program


                            cond = fold_convert (TREE_TYPE (argse.expr),
                                                 null_pointer_node);
                            cond = fold_build2_loc (input_location, NE_EXPR,
@@ -7256,6 +7260,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
              && e->symtree->n.sym->attr.optional
              && (((e->rank != 0 && elemental_proc)
                   || e->representation.length || e->ts.type == BT_CHARACTER
+                  || (e->rank == 0 && e->symtree->n.sym->attr.value)

This looks good.

                   || (e->rank != 0
                       && (fsym == NULL
                           || (fsym->as
diff --git a/gcc/testsuite/gfortran.dg/optional_absent_9.f90 
b/gcc/testsuite/gfortran.dg/optional_absent_9.f90
new file mode 100644
index 00000000000..495a6c00d7f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/optional_absent_9.f90
@@ -0,0 +1,324 @@
+! { dg-do run }
+! PR fortran/113377
+!
+! Test passing of missing optional scalar dummies of intrinsic type
+
+module m_int
+  implicit none
+contains
+  subroutine test_int ()
+    integer :: k = 1
+    call one     (k)
+    call one_val (k)
+    call one_all (k)
+    call one_ptr (k)
+  end
+
+  subroutine one (i, j)
+    integer, intent(in)           :: i
+    integer             ,optional :: j
+    integer, allocatable :: aa
+    integer, pointer     :: pp => NULL()
+    if (present (j)) error stop "j is present"
+    call two     (i, j)
+    call two_val (i, j)
+    call two     (i, aa)
+    call two     (i, pp)

To be complete, you could check two_val(i, aa) and two_val(i, pp) as well.
Both seem to pass already without the patch, so not absolutely needed.
Your call.

+  end
+

I think the patch is OK with the first trans-expr.cc hunk removed.
Thanks.

Mikael

Reply via email to