Dear all,
the attached patch adds the following:
- diagnostics of different string length of allocate-object and of the
source-expr (SOURCE/MOLD) as hard error when it can be determined at
compile-time
- a runtime-diagnostics und -fcheck=bounds (reuse of existing checks)
- a fallback solution (GNU extension) to use the length of allocate-object
if the length mismatch is not diagnosed at compile-time or runtime.
This avoids heap corruption and leads to string truncation or padding
during assignment.
F2008 demands same values of the kind type parameters, and this is
diagnosed by NAG. It also always gives a hard error, even at runtime.
Some brands (NVidia, AMD flang) tolerate a length mismatch silently
and perform string truncation or padding, without crashing.
Regtested on x86_64-pc-linux-gnu. OK for mainline?
Thanks,
Harald
From b9ece695a178319e35cd9f36cc731855302dd57f Mon Sep 17 00:00:00 2001
From: Harald Anlauf
Date: Sat, 13 Apr 2024 19:09:24 +0200
Subject: [PATCH] Fortran: ALLOCATE of fixed-length CHARACTER with SOURCE/MOLD
[PR113793]
F2008 requires for ALLOCATE with SOURCE= or MOLD= specifier that the kind
type parameters of allocate-object and source-expr have the same values.
Add compile-time diagnostics for different character length and a runtime
check (under -fcheck=bounds). Use length from allocate-object to prevent
heap corruption and to allow string padding or truncation on assignment.
gcc/fortran/ChangeLog:
PR fortran/113793
* resolve.cc (resolve_allocate_expr): Reject ALLOCATE with SOURCE=
or MOLD= specifier for unequal length.
* trans-stmt.cc (gfc_trans_allocate): If an allocatable character
variable has fixed length, use it and do not use the source length.
With bounds-checking enabled, add a runtime check for same length.
gcc/testsuite/ChangeLog:
PR fortran/113793
* gfortran.dg/allocate_with_source_29.f90: New test.
* gfortran.dg/allocate_with_source_30.f90: New test.
* gfortran.dg/allocate_with_source_31.f90: New test.
---
gcc/fortran/resolve.cc| 10
gcc/fortran/trans-stmt.cc | 36 +++--
.../gfortran.dg/allocate_with_source_29.f90 | 48 +
.../gfortran.dg/allocate_with_source_30.f90 | 51 +++
.../gfortran.dg/allocate_with_source_31.f90 | 38 ++
5 files changed, 179 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/gfortran.dg/allocate_with_source_29.f90
create mode 100644 gcc/testsuite/gfortran.dg/allocate_with_source_30.f90
create mode 100644 gcc/testsuite/gfortran.dg/allocate_with_source_31.f90
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 4cbf7186119..6b3e5ba4fcb 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -8278,6 +8278,16 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code, bool *array_alloc_wo_spec)
goto failure;
}
+ /* Check F2008:C639: "Corresponding kind type parameters of
+ allocate-object and source-expr shall have the same values." */
+ if (e->ts.type == BT_CHARACTER
+ && !e->ts.deferred
+ && e->ts.u.cl->length
+ && code->expr3->ts.type == BT_CHARACTER
+ && !gfc_check_same_strlen (e, code->expr3, "ALLOCATE with "
+ "SOURCE= or MOLD= specifier"))
+ goto failure;
+
/* Check TS18508, C702/C703. */
if (code->expr3->ts.type == BT_DERIVED
&& ((codimension && gfc_expr_attr (code->expr3).event_comp)
diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 7997c167bae..c34e0b4c0cd 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -6829,10 +6829,26 @@ gfc_trans_allocate (gfc_code * code, gfc_omp_namelist *omp_allocate)
in the array is needed, which is the product of the len and
esize for char arrays. For unlimited polymorphics len can be
zero, therefore take the maximum of len and one. */
+ tree lhs_len;
+
+ /* If an allocatable character variable has fixed length, use it.
+ Otherwise use source length. As different lengths are not
+ allowed by the standard, generate a runtime check. */
+ if (expr->ts.type == BT_CHARACTER && !expr->ts.deferred)
+ {
+ gfc_trans_same_strlen_check ("ALLOCATE with SOURCE= or MOLD=",
+ &code->expr3->where,
+ se.string_length, expr3_len,
+ &block);
+ lhs_len = fold_convert (TREE_TYPE (expr3_len), se.string_length);
+ }
+ else
+ lhs_len = expr3_len;
+
tmp = fold_build2_loc (input_location, MAX_EXPR,
TREE_TYPE (expr3_len),
- expr3_len, fold_convert (TREE_TYPE (expr3_len),
- integer_one_node));
+ lhs_len, fold_convert (TREE_TYPE (expr3_len),
+ integer_one_node));
tmp = fold_build2_loc (input_location, MULT_EXPR,
TREE_TYPE (expr3_esize), expr3_esize,
fold_convert (TREE_TYPE (expr3_esi