Re: [PATCH] Fortran: fix passing of NULL() actual argument to character dummy [PR104819]

2024-11-14 Thread Harald Anlauf

Hi Jerry,

Am 14.11.24 um 01:17 schrieb Jerry D:

On 11/13/24 2:26 PM, Harald Anlauf wrote:

Dear all,

the attached patch is the third part of a series to fix the handling of
NULL() passed to pointer dummy arguments.  This one addresses character
dummy arguments (scalar, assumed-shape, assumed-rank) for various
uses in the caller.

The patch is a little larger than I expected, due to corner cases
(MOLD present or not, assumed-rank or other).  If someone finds a
more clever version, I would be happy to learn about it.
Especially the treatment of assumed-rank dummy could certainly
be done differently.

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

As this fixes wrong code on the one hand, and is very localized,
I would like to backport this to 14-branch after some waiting.
Is this ok?

Thanks,
Harald



OK for mainline and backport.

Food for thought at another time:

gfc_conv_procedure_call contains about 2100 lines of code. One can read
through this fairly directly and the comments are very helpful. It begs
for some refactoring into a set of smaller functions.


you are absolutely right!  I keep telling that to others, but didn't
follow my own recommendations...

Refactored and pushed the attached version as r15-5295-gf70c1d517e09c4.


Kind and Type regards,

Jerry



Thanks for the review!

Harald

From f70c1d517e09c4dde421774a8cec591ca3c479a0 Mon Sep 17 00:00:00 2001
From: Harald Anlauf 
Date: Thu, 14 Nov 2024 21:38:04 +0100
Subject: [PATCH] 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.
---
 gcc/fortran/trans-expr.cc   |  79 +++
 gcc/testsuite/gfortran.dg/null_actual_6.f90 | 221 
 2 files changed, 300 insertions(+)
 create mode 100644 gcc/testsuite/gfortran.dg/null_actual_6.f90

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index ddbb5ecf068..f004af71334 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
+	{
+	  parm

Re: Fix type of malloc call in trans-expr.cc

2024-11-14 Thread Paul Richard Thomas
Hi Jakub,

Good catch! Does it fix any specific PR?

If you don't have the time, I would be happy to apply the correction to
13-branch through to mainline.

Regards

Paul


On Thu, 14 Nov 2024 at 22:24, Jakub Jelinek  wrote:

> On Thu, Nov 14, 2024 at 08:58:26PM +0100, Jan Hubicka wrote:
> > fortran produces malloc call with signed size instead of unsigned. This
> > in turn makes gimple_call_builtin_p to fail type checking and we do not
> > treat the call as malloc call.
> >
> > regtested x86_64-linux, OK?
> >
> > gcc/fortran/ChangeLog:
> >
> >   * trans-expr.cc (gfc_trans_subcomponent_assign): Convert malloc
> >   parameter to size_type.
>
> LGTM.
>
> > diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
> > index ddbb5ecf068..951ac26c4ea 100644
> > --- a/gcc/fortran/trans-expr.cc
> > +++ b/gcc/fortran/trans-expr.cc
> > @@ -9661,6 +9661,7 @@ gfc_trans_subcomponent_assign (tree dest,
> gfc_component * cm,
> > gfc_init_se (&se, NULL);
> > gfc_conv_expr (&se, expr);
> > size = size_of_string_in_bytes (cm->ts.kind, se.string_length);
> > +   size = fold_convert (size_type_node, size);
> > tmp = build_call_expr_loc (input_location,
> >builtin_decl_explicit
> (BUILT_IN_MALLOC),
> >1, size);
>
> Jakub
>
>


Re: [PATCH] Fortran: fix passing of NULL() actual argument to character dummy [PR104819]

2024-11-14 Thread Paul Richard Thomas
Hi Jerry and Harald,

I have on several occasions perused gfc_conv_procedure_call with a view to
doing exactly the refactoring that you suggest. However, it has grown like
Topsy and the logic has become very difficult to follow. This, of course,
makes it ripe for refactoring but has turned it into a substantial task.
Thus far I have recoiled with the reaction, "Don't fix it if it (mostly)
ain't broke." Something for early 16-branch development?

Regards

Paul


On Thu, 14 Nov 2024 at 00:18, Jerry D  wrote:

> On 11/13/24 2:26 PM, Harald Anlauf wrote:
> > Dear all,
> >
> > the attached patch is the third part of a series to fix the handling of
> > NULL() passed to pointer dummy arguments.  This one addresses character
> > dummy arguments (scalar, assumed-shape, assumed-rank) for various
> > uses in the caller.
> >
> > The patch is a little larger than I expected, due to corner cases
> > (MOLD present or not, assumed-rank or other).  If someone finds a
> > more clever version, I would be happy to learn about it.
> > Especially the treatment of assumed-rank dummy could certainly
> > be done differently.
> >
> > Regtested on x86_64-pc-linux-gnu.  OK for mainline?
> >
> > As this fixes wrong code on the one hand, and is very localized,
> > I would like to backport this to 14-branch after some waiting.
> > Is this ok?
> >
> > Thanks,
> > Harald
> >
>
> OK for mainline and backport.
>
> Food for thought at another time:
>
> gfc_conv_procedure_call contains about 2100 lines of code. One can read
> through this fairly directly and the comments are very helpful. It begs
> for some refactoring into a set of smaller functions.
>
> Kind and Type regards,
>
> Jerry
>


Re: Fix type of malloc call in trans-expr.cc

2024-11-14 Thread Jakub Jelinek
On Thu, Nov 14, 2024 at 08:58:26PM +0100, Jan Hubicka wrote:
> fortran produces malloc call with signed size instead of unsigned. This
> in turn makes gimple_call_builtin_p to fail type checking and we do not
> treat the call as malloc call.
> 
> regtested x86_64-linux, OK?
> 
> gcc/fortran/ChangeLog:
> 
>   * trans-expr.cc (gfc_trans_subcomponent_assign): Convert malloc
>   parameter to size_type.

LGTM.

> diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
> index ddbb5ecf068..951ac26c4ea 100644
> --- a/gcc/fortran/trans-expr.cc
> +++ b/gcc/fortran/trans-expr.cc
> @@ -9661,6 +9661,7 @@ gfc_trans_subcomponent_assign (tree dest, gfc_component 
> * cm,
> gfc_init_se (&se, NULL);
> gfc_conv_expr (&se, expr);
> size = size_of_string_in_bytes (cm->ts.kind, se.string_length);
> +   size = fold_convert (size_type_node, size);
> tmp = build_call_expr_loc (input_location,
>builtin_decl_explicit (BUILT_IN_MALLOC),
>1, size);

Jakub