From 1fc44a5bf0b294021490f3c0a1539982a09000f5 Mon Sep 17 00:00:00 2001 From: Harald Anlauf Date: Fri, 12 Nov 2021 18:32:18 +0100 Subject: [PATCH] Fortran: fix interoperability check for character variables for F2008 gcc/fortran/ChangeLog: PR fortran/102368 * check.c (is_c_interoperable): F2008:15.3.5 relaxed the condition on interoperable character variables and allows values different from one. gcc/testsuite/ChangeLog: PR fortran/102368 * gfortran.dg/c_sizeof_7.f90: New test. --- gcc/fortran/check.c | 20 ++++++++++++++------ gcc/testsuite/gfortran.dg/c_sizeof_7.f90 | 13 +++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/c_sizeof_7.f90 diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c index ffa07b510cd..69a2e35e81b 100644 --- a/gcc/fortran/check.c +++ b/gcc/fortran/check.c @@ -5272,13 +5272,21 @@ is_c_interoperable (gfc_expr *expr, const char **msg, bool c_loc, bool c_f_ptr) && !gfc_simplify_expr (expr->ts.u.cl->length, 0)) gfc_internal_error ("is_c_interoperable(): gfc_simplify_expr failed"); - if (!c_loc && expr->ts.u.cl - && (!expr->ts.u.cl->length - || expr->ts.u.cl->length->expr_type != EXPR_CONSTANT - || mpz_cmp_si (expr->ts.u.cl->length->value.integer, 1) != 0)) + if (!c_loc && expr->ts.u.cl) { - *msg = "Type shall have a character length of 1"; - return false; + bool len_ok = (expr->ts.u.cl->length + && expr->ts.u.cl->length->expr_type == EXPR_CONSTANT); + + /* F2003:15.2.1 required the length of a character variable to be one. + F2008:15.3.5 relaxed this to constant length. */ + if (len_ok && !(gfc_option.allow_std & GFC_STD_F2008)) + len_ok = mpz_cmp_si (expr->ts.u.cl->length->value.integer, 1) == 0; + + if (!len_ok) + { + *msg = "Type shall have a character length of 1"; + return false; + } } } diff --git a/gcc/testsuite/gfortran.dg/c_sizeof_7.f90 b/gcc/testsuite/gfortran.dg/c_sizeof_7.f90 new file mode 100644 index 00000000000..3cfa3371f72 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/c_sizeof_7.f90 @@ -0,0 +1,13 @@ +! { dg-do compile } +! { dg-options "-std=f2008 -fdump-tree-original" } +! { dg-final { scan-tree-dump-times "_gfortran_stop_numeric" 0 "original" } } +! PR fortran/102368 + +program main + use, intrinsic :: iso_c_binding + implicit none + character(kind=c_char, len=*), parameter :: a = 'abc' + character(kind=c_char, len=8) :: b + if (c_sizeof (a) /= 3) stop 1 + if (c_sizeof (b) /= 8) stop 2 +end program main -- 2.26.2