aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorHarald Anlauf <anlauf@gmx.de>2025-08-31 20:42:23 +0200
committerHarald Anlauf <anlauf@gmx.de>2025-09-01 21:51:17 +0200
commit082483dd79040d49351fac9074fc10c7dd810598 (patch)
treec96b76d3e9f6edbc7675c112ccf96daf52f4d4a8 /gcc/fortran
parent188be0dff053050a4fe73d596fbefdb612d7646b (diff)
downloadgcc-082483dd79040d49351fac9074fc10c7dd810598.zip
gcc-082483dd79040d49351fac9074fc10c7dd810598.tar.gz
gcc-082483dd79040d49351fac9074fc10c7dd810598.tar.bz2
Fortran: truncate constant string passed to character,value dummy [PR121727]
PR fortran/121727 gcc/fortran/ChangeLog: * trans-expr.cc (gfc_const_length_character_type_p): New helper function. (conv_dummy_value): Use it to determine if a character actual argument has a constant length. If a character actual argument is constant and longer than the dummy, truncate it at compile time. gcc/testsuite/ChangeLog: * gfortran.dg/value_10.f90: New test.
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/trans-expr.cc34
1 files changed, 34 insertions, 0 deletions
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 6a21e8c..97431d9 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -6510,6 +6510,20 @@ conv_cond_temp (gfc_se * parmse, gfc_expr * e, tree cond)
}
+/* Returns true if the type specified in TS is a character type whose length
+ is constant. Otherwise returns false. */
+
+static bool
+gfc_const_length_character_type_p (gfc_typespec *ts)
+{
+ return (ts->type == BT_CHARACTER
+ && ts->u.cl
+ && ts->u.cl->length
+ && ts->u.cl->length->expr_type == EXPR_CONSTANT
+ && ts->u.cl->length->ts.type == BT_INTEGER);
+}
+
+
/* Helper function for the handling of (currently) scalar dummy variables
with the VALUE attribute. Argument parmse should already be set up. */
static void
@@ -6565,6 +6579,26 @@ conv_dummy_value (gfc_se * parmse, gfc_expr * e, gfc_symbol * fsym,
return;
}
+ /* Truncate a too long constant character actual argument. */
+ if (gfc_const_length_character_type_p (&fsym->ts)
+ && e->expr_type == EXPR_CONSTANT
+ && mpz_cmp_ui (fsym->ts.u.cl->length->value.integer,
+ e->value.character.length) < 0)
+ {
+ gfc_charlen_t flen = mpz_get_ui (fsym->ts.u.cl->length->value.integer);
+
+ /* Truncate actual string argument. */
+ gfc_conv_expr (parmse, e);
+ parmse->expr = gfc_build_wide_string_const (e->ts.kind, flen,
+ e->value.character.string);
+ parmse->string_length = build_int_cst (gfc_charlen_type_node, flen);
+
+ /* Indicate value,optional scalar dummy argument as present. */
+ if (fsym->attr.optional)
+ vec_safe_push (optionalargs, boolean_true_node);
+ return;
+ }
+
/* gfortran argument passing conventions:
actual arguments to CHARACTER(len=1),VALUE
dummy arguments are actually passed by value.