aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-expr.cc
diff options
context:
space:
mode:
authorHarald Anlauf <anlauf@gmx.de>2024-11-14 21:38:04 +0100
committerHarald Anlauf <anlauf@gmx.de>2024-11-14 22:37:56 +0100
commitf70c1d517e09c4dde421774a8cec591ca3c479a0 (patch)
treeb8c21563762b493772549ba83764a313fb146669 /gcc/fortran/trans-expr.cc
parent7744da67e95824e15de5773e608aeb3d2bbd8653 (diff)
downloadgcc-f70c1d517e09c4dde421774a8cec591ca3c479a0.zip
gcc-f70c1d517e09c4dde421774a8cec591ca3c479a0.tar.gz
gcc-f70c1d517e09c4dde421774a8cec591ca3c479a0.tar.bz2
Fortran: fix passing of NULL() actual argument to character dummy [PR104819]
Ensure that character length is set and passed by the call to a procedure when its dummy argument is NULL() with MOLD argument present, or set length to either 0 or the callee's expected character length. For assumed-rank dummies, use the rank of the MOLD argument. Generate temporaries for passed arguments when needed. PR fortran/104819 gcc/fortran/ChangeLog: * trans-expr.cc (conv_null_actual): Helper function to handle passing of NULL() to non-optional dummy arguments of non-bind(c) procedures. (gfc_conv_procedure_call): Use it for character dummies. gcc/testsuite/ChangeLog: * gfortran.dg/null_actual_6.f90: New test.
Diffstat (limited to 'gcc/fortran/trans-expr.cc')
-rw-r--r--gcc/fortran/trans-expr.cc79
1 files changed, 79 insertions, 0 deletions
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index ddbb5ec..f004af7 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -6378,6 +6378,76 @@ conv_dummy_value (gfc_se * parmse, gfc_expr * e, gfc_symbol * fsym,
}
+/* Helper function for the handling of NULL() actual arguments associated with
+ non-optional dummy variables. Argument parmse should already be set up. */
+static void
+conv_null_actual (gfc_se * parmse, gfc_expr * e, gfc_symbol * fsym)
+{
+ gcc_assert (fsym && !fsym->attr.optional);
+
+ /* Obtain the character length for a NULL() actual with a character
+ MOLD argument. Otherwise substitute a suitable dummy length.
+ Here we handle only non-optional dummies of non-bind(c) procedures. */
+ if (fsym->ts.type == BT_CHARACTER)
+ {
+ if (e->ts.type == BT_CHARACTER
+ && e->symtree->n.sym->ts.type == BT_CHARACTER)
+ {
+ /* MOLD is present. Substitute a temporary character NULL pointer.
+ For an assumed-rank dummy we need a descriptor that passes the
+ correct rank. */
+ if (fsym->as && fsym->as->type == AS_ASSUMED_RANK)
+ {
+ tree rank;
+ tree tmp = parmse->expr;
+ tmp = gfc_conv_scalar_to_descriptor (parmse, tmp, fsym->attr);
+ rank = gfc_conv_descriptor_rank (tmp);
+ gfc_add_modify (&parmse->pre, rank,
+ build_int_cst (TREE_TYPE (rank), e->rank));
+ parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp);
+ }
+ else
+ {
+ tree tmp = gfc_create_var (TREE_TYPE (parmse->expr), "null");
+ gfc_add_modify (&parmse->pre, tmp,
+ build_zero_cst (TREE_TYPE (tmp)));
+ parmse->expr = gfc_build_addr_expr (NULL_TREE, tmp);
+ }
+
+ /* Ensure that a usable length is available. */
+ if (parmse->string_length == NULL_TREE)
+ {
+ gfc_typespec *ts = &e->symtree->n.sym->ts;
+
+ if (ts->u.cl->length != NULL
+ && ts->u.cl->length->expr_type == EXPR_CONSTANT)
+ gfc_conv_const_charlen (ts->u.cl);
+
+ if (ts->u.cl->backend_decl)
+ parmse->string_length = ts->u.cl->backend_decl;
+ }
+ }
+ else if (e->ts.type == BT_UNKNOWN && parmse->string_length == NULL_TREE)
+ {
+ /* MOLD is not present. Pass length of associated dummy character
+ argument if constant, or zero. */
+ if (fsym->ts.u.cl->length != NULL
+ && fsym->ts.u.cl->length->expr_type == EXPR_CONSTANT)
+ {
+ gfc_conv_const_charlen (fsym->ts.u.cl);
+ parmse->string_length = fsym->ts.u.cl->backend_decl;
+ }
+ else
+ {
+ parmse->string_length = gfc_create_var (gfc_charlen_type_node,
+ "slen");
+ gfc_add_modify (&parmse->pre, parmse->string_length,
+ build_zero_cst (gfc_charlen_type_node));
+ }
+ }
+ }
+}
+
/* Generate code for a procedure call. Note can return se->post != NULL.
If se->direct_byref is set then se->expr contains the return parameter.
@@ -7542,6 +7612,15 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_conv_const_charlen (e->symtree->n.sym->ts.u.cl);
parmse.string_length = e->symtree->n.sym->ts.u.cl->backend_decl;
}
+
+ /* Obtain the character length for a NULL() actual with a character
+ MOLD argument. Otherwise substitute a suitable dummy length.
+ Here we handle non-optional dummies of non-bind(c) procedures. */
+ if (e->expr_type == EXPR_NULL
+ && fsym->ts.type == BT_CHARACTER
+ && !fsym->attr.optional
+ && !(sym->attr.is_bind_c && is_CFI_desc (fsym, NULL)))
+ conv_null_actual (&parmse, e, fsym);
}
/* If any actual argument of the procedure is allocatable and passed