diff options
author | Harald Anlauf <anlauf@gmx.de> | 2025-08-31 20:42:23 +0200 |
---|---|---|
committer | Harald Anlauf <anlauf@gmx.de> | 2025-09-01 21:51:17 +0200 |
commit | 082483dd79040d49351fac9074fc10c7dd810598 (patch) | |
tree | c96b76d3e9f6edbc7675c112ccf96daf52f4d4a8 /gcc/fortran | |
parent | 188be0dff053050a4fe73d596fbefdb612d7646b (diff) | |
download | gcc-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.cc | 34 |
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. |