Dear Fortranners,

F2008:15.3.5 relaxed the condition on interoperable character variables
and now allows values different from one.  Similar text in F2018:18.3.4.
This required an adjustment in the interoperability check.

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

Thanks,
Harald

From 1fc44a5bf0b294021490f3c0a1539982a09000f5 Mon Sep 17 00:00:00 2001
From: Harald Anlauf <anl...@gmx.de>
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

Reply via email to