PR fortran/102368 - Failure to compile program using the C_SIZEOF function in ISO_C_BINDING

Message ID trinity-f485a27b-2425-4203-8931-df0e244fe304-1636738788711@3c-app-gmx-bap24
State New
Headers
Series PR fortran/102368 - Failure to compile program using the C_SIZEOF function in ISO_C_BINDING |

Commit Message

Harald Anlauf Nov. 12, 2021, 5:39 p.m. UTC
  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
  

Comments

Bernhard Reutner-Fischer Nov. 12, 2021, 8:18 p.m. UTC | #1
On Fri, 12 Nov 2021 18:39:48 +0100
Harald Anlauf via Fortran <fortran@gcc.gnu.org> wrote:

Sounds plausible.
Nits:

> 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

[I'd name this .f08, no?]

> @@ -0,0 +1,13 @@
> +! { dg-do compile }
> +! { dg-options "-std=f2008 -fdump-tree-original" }

[and drop the -std]

> +! { dg-final { scan-tree-dump-times "_gfortran_stop_numeric" 0 "original" } }

[ ...-times 0 == scan-tree-dump-not ]

> +! 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

character(kind=c_char, len=-42) :: c ! { dg-error "positive integer greater than 0" }
character(kind=c_char, len=-0) :: d ! { dg-error "positive integer greater than 0" }
character(kind=c_char, len=0) :: e ! { dg-error "positive integer greater than 0" }
character(kind=c_char, len=+0) :: f ! { dg-error "positive integer greater than 0" }
character(kind=c_char, len=0.0d) :: g ! { dg-error "positive integer greater than 0" }
character(kind=c_char, len=3.) :: h ! { dg-error "positive integer greater than 0" }
character(kind=c_char, len=.031415e2) :: i ! { dg-error "positive integer greater than 0" }
...
are caught elsewhere if one assumes that len should be a positive int > 0 (didn't look)
Also did not look if
character(kind=c_char, len=SELECTED_REAL_KIND(10)) :: j ! is that constant? Should it be?

> +  if (c_sizeof (a) /= 3) stop 1
> +  if (c_sizeof (b) /= 8) stop 2

indeed.
cheers,

> +end program main
> --
> 2.26.2
>
  
Harald Anlauf Nov. 12, 2021, 8:35 p.m. UTC | #2
Hi Bernhard,

Am 12.11.21 um 21:18 schrieb Bernhard Reutner-Fischer via Fortran:
> On Fri, 12 Nov 2021 18:39:48 +0100
> Harald Anlauf via Fortran <fortran@gcc.gnu.org> wrote:
>
> Sounds plausible.

this is what I thought, too.  And nvfortran and flang accept the
testcase, as well as crayftn (cce/12.0.2).

Intel accepts the first case (a), but rejects the second (b).
I asked in the Intel forum.  Steve Lionel doubts that the code is
valid.

There might be some confusion on my side, but having Cray on my
side feels good.  (Although the PR was entered into bugzilla by
a Cray employee).

> Nits:
>
>> 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
>
> [I'd name this .f08, no?]
>
>> @@ -0,0 +1,13 @@
>> +! { dg-do compile }
>> +! { dg-options "-std=f2008 -fdump-tree-original" }
>
> [and drop the -std]
>
>> +! { dg-final { scan-tree-dump-times "_gfortran_stop_numeric" 0 "original" } }
>
> [ ...-times 0 == scan-tree-dump-not ]

Good point.

>> +! 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
>
> character(kind=c_char, len=-42) :: c ! { dg-error "positive integer greater than 0" }
> character(kind=c_char, len=-0) :: d ! { dg-error "positive integer greater than 0" }
> character(kind=c_char, len=0) :: e ! { dg-error "positive integer greater than 0" }
> character(kind=c_char, len=+0) :: f ! { dg-error "positive integer greater than 0" }
> character(kind=c_char, len=0.0d) :: g ! { dg-error "positive integer greater than 0" }
> character(kind=c_char, len=3.) :: h ! { dg-error "positive integer greater than 0" }
> character(kind=c_char, len=.031415e2) :: i ! { dg-error "positive integer greater than 0" }
> ...
> are caught elsewhere if one assumes that len should be a positive int > 0 (didn't look)
> Also did not look if
> character(kind=c_char, len=SELECTED_REAL_KIND(10)) :: j ! is that constant? Should it be?

These things should already be handled in general and
elsewhere, as they are not about interoperability.

>> +  if (c_sizeof (a) /= 3) stop 1
>> +  if (c_sizeof (b) /= 8) stop 2
>
> indeed.
> cheers,
>
>> +end program main
>> --
>> 2.26.2
>>
>

Thanks,
Harald
  

Patch

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