aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarald Anlauf <anlauf@gmx.de>2024-06-23 22:36:43 +0200
committerHarald Anlauf <anlauf@gmx.de>2024-06-24 18:49:54 +0200
commitf02c70dafd384f0c44d7a0920f4a75a30e267045 (patch)
tree10f73e6d0a859179beca9eedf82e8bb85a07f95b
parentd8b05aef77443e1d3d8f3f5d2c56ac49a503fee3 (diff)
downloadgcc-f02c70dafd384f0c44d7a0920f4a75a30e267045.zip
gcc-f02c70dafd384f0c44d7a0920f4a75a30e267045.tar.gz
gcc-f02c70dafd384f0c44d7a0920f4a75a30e267045.tar.bz2
Fortran: fix passing of optional dummy as actual to optional argument [PR55978]
gcc/fortran/ChangeLog: PR fortran/55978 * trans-array.cc (gfc_conv_array_parameter): Do not dereference data component of a missing allocatable dummy array argument for passing as actual to optional dummy. Harden logic of presence check for optional pointer dummy by using TRUTH_ANDIF_EXPR instead of TRUTH_AND_EXPR. gcc/testsuite/ChangeLog: PR fortran/55978 * gfortran.dg/optional_absent_12.f90: New test.
-rw-r--r--gcc/fortran/trans-array.cc20
-rw-r--r--gcc/testsuite/gfortran.dg/optional_absent_12.f9030
2 files changed, 46 insertions, 4 deletions
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 19d69ae..26237f4 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -8703,6 +8703,10 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
&& (sym->backend_decl != parent))
this_array_result = false;
+ /* Passing an optional dummy argument as actual to an optional dummy? */
+ bool pass_optional;
+ pass_optional = fsym && fsym->attr.optional && sym && sym->attr.optional;
+
/* Passing address of the array if it is not pointer or assumed-shape. */
if (full_array_var && g77 && !this_array_result
&& sym->ts.type != BT_DERIVED && sym->ts.type != BT_CLASS)
@@ -8740,6 +8744,14 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
if (size)
array_parameter_size (&se->pre, tmp, expr, size);
se->expr = gfc_conv_array_data (tmp);
+ if (pass_optional)
+ {
+ tree cond = gfc_conv_expr_present (sym);
+ se->expr = build3_loc (input_location, COND_EXPR,
+ TREE_TYPE (se->expr), cond, se->expr,
+ fold_convert (TREE_TYPE (se->expr),
+ null_pointer_node));
+ }
return;
}
}
@@ -8989,8 +9001,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
fold_convert (TREE_TYPE (tmp), ptr), tmp);
- if (fsym && fsym->attr.optional && sym && sym->attr.optional)
- tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+ if (pass_optional)
+ tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
logical_type_node,
gfc_conv_expr_present (sym), tmp);
@@ -9024,8 +9036,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77,
tmp = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
fold_convert (TREE_TYPE (tmp), ptr), tmp);
- if (fsym && fsym->attr.optional && sym && sym->attr.optional)
- tmp = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+ if (pass_optional)
+ tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
logical_type_node,
gfc_conv_expr_present (sym), tmp);
diff --git a/gcc/testsuite/gfortran.dg/optional_absent_12.f90 b/gcc/testsuite/gfortran.dg/optional_absent_12.f90
new file mode 100644
index 0000000..1e61d91
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/optional_absent_12.f90
@@ -0,0 +1,30 @@
+! { dg-do run }
+! { dg-additional-options "-fcheck=array-temps" }
+!
+! PR fortran/55978 - comment#19
+!
+! Test passing of (missing) optional dummy to optional array argument
+
+program test
+ implicit none
+ integer, pointer :: p(:) => null()
+ call one (p)
+ call one (null())
+ call one ()
+ call three ()
+contains
+ subroutine one (y)
+ integer, pointer, optional, intent(in) :: y(:)
+ call two (y)
+ end subroutine one
+
+ subroutine three (z)
+ integer, allocatable, optional, intent(in) :: z(:)
+ call two (z)
+ end subroutine three
+
+ subroutine two (x)
+ integer, optional, intent(in) :: x(*)
+ if (present (x)) stop 1
+ end subroutine two
+end