Hi all,
this patch came up when discussing Sandra's TS29113 patch internally.
There is presumably also some overlap with José's patches.
This patch tries to rectify the BIND(C) CHARACTER handling on the
diagnostic side, only. That is: what to accept and what
to reject for which Fortran standard.
The rules are:
* [F2003-F2018] Interoperable is character(len=1)
→ F2018, 18.3.1 Interoperability of intrinsic types
(General, unchanged)
* Fortran 2008: In some cases, const-length chars are
permitted as well:
→ F2018, 18.3.4 Interoperability of scalar variables
→ F2018, 18.3.5 Interoperability of array variables
→ F2018, 18.3.6 Interoperability of procedures and procedure interfaces
[= F2008, 15.3.{4,5,6}
For global vars with bind(C), 18.3.4 + 18.3.5 applies directly (TODO: Add
support, not in this patch)
For passed-by ref dummy arguments, 18.3.4 + 18.3.5 are referenced in
- F2008: R1229 proc-language-binding-spec is language-binding-spec
C1255 (R1229)
- F2018, F2018, C1554
While it is not very clearly spelt out, I regard 'char parm[4]'
interoperable with 'character(len=4) :: a', 'character(len=2) :: b(2)'
and 'character(len=1) :: c(4)' for both global variables and for
dummy arguments.
* Fortran 2018/TS29113: Uses additionally CFI array descriptor
- allocatable, pointer: must be len=:
- nonallocatable/nonpointer: len=* → implies array descriptor also
for assumed-size/explicit-size/scalar arguments.
- All which all passed by an array descriptor already without further
restrictions: assumed-shape, assumed-rank, i.e. len= seems
to be also fine
→ 18.3.6 under item (5) bullet point 2 and 3 plus (6).
I hope I got the conditions right. I also fixed an issue with
character(len=5) :: str – the code in trans-expr.c did crash for
scalars (decl.c did not check any constraints for arrays).
I believe the condition is wrong and for len= no descriptor
is used.
Any comments, remarks?
OK for mainline?
Tobias
PS: To do are global variables, the implementation of the sorries;
PPS: At other places like with VALUE or for function return values,
Fortran still requires len=1 with Bind(C).
-
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank
Thürauf
Fortran: Fix bind(C) character length checks
gcc/fortran/ChangeLog:
* decl.c (gfc_verify_c_interop_param): Update for F2008 + F2018
changes; reject unsupported bits with 'Error: Sorry,'.
* trans-expr.c (gfc_conv_procedure_call): Fix condition to
For using CFI descriptor with characters.
gcc/testsuite/ChangeLog:
* gfortran.dg/iso_c_binding_char_1.f90: Update dg-error.
* gfortran.dg/pr32599.f03: Use -std=-f2003 + update comment.
* gfortran.dg/bind_c_char_10.f90: New test.
* gfortran.dg/bind_c_char_6.f90: New test.
* gfortran.dg/bind_c_char_7.f90: New test.
* gfortran.dg/bind_c_char_8.f90: New test.
* gfortran.dg/bind_c_char_9.f90: New test.
gcc/fortran/decl.c | 107 -
gcc/fortran/trans-expr.c | 18 +-
gcc/testsuite/gfortran.dg/bind_c_char_10.f90 | 480 +
gcc/testsuite/gfortran.dg/bind_c_char_6.f90| 262 +++
gcc/testsuite/gfortran.dg/bind_c_char_7.f90| 261 +++
gcc/testsuite/gfortran.dg/bind_c_char_8.f90| 249 +++
gcc/testsuite/gfortran.dg/bind_c_char_9.f90| 188
gcc/testsuite/gfortran.dg/iso_c_binding_char_1.f90 | 2 +-
gcc/testsuite/gfortran.dg/pr32599.f03 | 8 +-
9 files changed, 1551 insertions(+), 24 deletions(-)
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 413c7a75e0c..4a9f74306ff 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -1552,20 +1552,109 @@ gfc_verify_c_interop_param (gfc_symbol *sym)
}
/* Character strings are only C interoperable if they have a
- length of 1. */
- if (sym->ts.type == BT_CHARACTER && !sym->attr.dimension)
+ length of 1. However, as argument they are either iteroperable
+ when passed as descriptor (which requires len=: or len=*) or
+ when having a constant length or are always passed by
+ descriptor. */
+ if (sym->ts.type == BT_CHARACTER)
{
gfc_charlen *cl = sym->ts.u.cl;
- if (!cl || !cl->length || cl->length->expr_type != EXPR_CONSTANT
- || mpz_cmp_si (cl->length->value.integer, 1) != 0)
+
+ if (sym->attr.allocatable || sym->attr.pointer)
{
- gfc_error ("Character argument %qs at %L "
- "must be length 1 because "
- "procedure %qs is BIND(C)",
- sym->name, &sym->declared_at,
- sym->ns->proc_name->name);
+ /* F2018, 18.3.6 (6). */
+ if (!sym->ts.deferred)
+ {
+ gfc_error ("Allocatable and pointer character dummy "
+ "argument %qs at %L must have deferred length "
+ "as procedure %qs is BIND(C)", sym->name,
+