ISO C binding and character variables

Christopher D. Rickett crickett@lanl.gov
Tue Jul 17 17:00:00 GMT 2007


hi Tobias,

i've attached a second attempt at this patch that should fix the bug 
illustrated below (it has been added as a test case).  the updated patch 
now changes by-value character dummies to not expect an address 
expression.

bootstrapped and regtested on x86 and x86_64 linux with no new failures.

Chris

On Mon, 16 Jul 2007, Tobias Burnus wrote:

> Hi Chris,
>
> Christopher D. Rickett wrote:
>> it should provide different output for -fdump-tree-original for having
>> the patch applied and not having it applied (at least it does on my
>> boxes).
> Ok, it does but only for:
>
> c_char_tests.f03
> -  if (my_char[1]{lb: 1 sz: 1} != 121)
> +  if (my_char != 121)
>     {
>       _gfortran_abort ();
>     }
> -  if (my_char_2[1]{lb: 1 sz: 1} != 122)
> +  if (my_char_2 != 122)
>
> I would expect:
>  call test('a')
> to be converted into
>  test('a')
> or
>  test(*"a")
> but in the dump I see:
>  test ("a", 1);
>
> That is goes wrong can be seen in the following program; I get "a=_"
> instead of the expected "a=a".
>
> Tobias
>
>
> module c_char_tests
>  use, intrinsic :: iso_c_binding, only: c_char
>  implicit none
> contains
>  subroutine test(a) bind(c)
>    character(kind=c_char), value :: a
>    call test2(a)
>  end subroutine test
>  subroutine test2(a) bind(c)
>    character(kind=c_char), value :: a
>    print *, 'a=',a
>  end subroutine test2
> end module
>
> program main
>  use c_char_tests
>  implicit none
>  call test('a')
> end program main
>
-------------- next part --------------
Index: gcc/testsuite/gfortran.dg/c_char_tests.f03
===================================================================
--- gcc/testsuite/gfortran.dg/c_char_tests.f03	(revision 0)
+++ gcc/testsuite/gfortran.dg/c_char_tests.f03	(revision 0)
@@ -0,0 +1,28 @@
+! { dg-do run }
+! { dg-additional-sources c_char_driver.c }
+! Verify that character dummy arguments for bind(c) procedures can work both 
+! by-value and by-reference when called by either C or Fortran.
+module c_char_tests
+  use, intrinsic :: iso_c_binding, only: c_char
+  implicit none
+contains
+  subroutine param_test(my_char, my_char_2) bind(c)
+    character(c_char), value :: my_char
+    character(c_char), value :: my_char_2
+    if(my_char /= c_char_'y') call abort()
+    if(my_char_2 /= c_char_'z') call abort()
+    
+    call sub1(my_char)
+  end subroutine param_test
+
+  subroutine sub0() bind(c)
+    call param_test('y', 'z')
+  end subroutine sub0
+
+  subroutine sub1(my_char_ref) bind(c)
+    character(c_char) :: my_char_ref
+    if(my_char_ref /= c_char_'y') call abort()
+  end subroutine sub1
+end module c_char_tests
+
+! { dg-final { cleanup-modules "c_char_tests" } }
Index: gcc/testsuite/gfortran.dg/c_char_tests_2.f03
===================================================================
--- gcc/testsuite/gfortran.dg/c_char_tests_2.f03	(revision 0)
+++ gcc/testsuite/gfortran.dg/c_char_tests_2.f03	(revision 0)
@@ -0,0 +1,32 @@
+! { dg-do run }
+! Verify that the changes made to character dummy arguments for bind(c) 
+! procedures doesn't break non-bind(c) routines.
+subroutine bar(a)
+  use, intrinsic :: iso_c_binding, only: c_char
+  character(c_char), value :: a
+  if(a /= c_char_'a') call abort()
+end subroutine bar
+
+subroutine bar2(a)
+  use, intrinsic :: iso_c_binding, only: c_char
+  character(c_char) :: a
+  if(a /= c_char_'a') call abort()
+end subroutine bar2
+
+use iso_c_binding
+implicit none
+interface
+  subroutine bar(a)
+    import
+    character(c_char),value :: a
+  end subroutine bar
+  subroutine bar2(a)
+    import
+    character(c_char) :: a
+  end subroutine bar2
+end interface
+ character(c_char) :: z
+ z = 'a'
+ call bar(z)
+ call bar2(z)
+end
Index: gcc/testsuite/gfortran.dg/pr32732.f03
===================================================================
--- gcc/testsuite/gfortran.dg/pr32732.f03	(revision 0)
+++ gcc/testsuite/gfortran.dg/pr32732.f03	(revision 0)
@@ -0,0 +1,24 @@
+! { dg-do run }
+! Verify by-value passing of character arguments w/in Fortran to a bind(c) 
+! procedure.  
+module pr32732
+  use, intrinsic :: iso_c_binding, only: c_char
+  implicit none
+contains
+  subroutine test(a) bind(c)
+    character(kind=c_char), value :: a
+    call test2(a)
+  end subroutine test
+  subroutine test2(a) bind(c)
+    character(kind=c_char), value :: a
+    if(a /= c_char_'a') call abort ()
+    print *, 'a=',a
+  end subroutine test2
+end module pr32732
+
+program main
+  use pr32732
+  implicit none
+  call test('a')
+end program main
+! { dg-final { cleanup-modules "pr32732" } }
Index: gcc/testsuite/gfortran.dg/c_char_driver.c
===================================================================
--- gcc/testsuite/gfortran.dg/c_char_driver.c	(revision 0)
+++ gcc/testsuite/gfortran.dg/c_char_driver.c	(revision 0)
@@ -0,0 +1,14 @@
+void param_test(char my_char, char my_char_2);
+void sub0(void);
+void sub1(char *my_char);
+
+int main(int argc, char **argv)
+{
+  char my_char = 'y';
+  
+  param_test('y', 'z');
+  sub0();
+  sub1(&my_char);
+  
+  return 0;
+}
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(revision 126694)
+++ gcc/fortran/trans-expr.c	(working copy)
@@ -473,8 +473,9 @@ gfc_conv_variable (gfc_se * se, gfc_expr
 	    se->expr = build_fold_indirect_ref (se->expr);
 
 	  /* A character with VALUE attribute needs an address
-	     expression.  */
-	  if (sym->attr.value)
+	     expression if it's a dummy arg of a bind(c) routine.  */
+	  if (sym->attr.value
+	      && (sym->ns == NULL || !sym->ns->proc_name->attr.is_bind_c))
 	    se->expr = build_fold_addr_expr (se->expr);
 
 	}
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c	(revision 126694)
+++ gcc/fortran/trans-decl.c	(working copy)
@@ -3018,6 +3018,19 @@ generate_local_decl (gfc_symbol * sym)
 		     &sym->declared_at);
     }
 
+  if (sym->attr.dummy == 1)
+    {
+      /* Modify the tree type for scalar character dummy arguments of bind(c)
+	 procedures if they are passed by value.  The tree type for them will
+	 be promoted to INTEGER_TYPE for the middle end, which appears to be
+	 what C would do with characters passed by-value.  The value attribute
+         implies the dummy is a scalar.  */
+      if (sym->attr.value == 1 && sym->backend_decl != NULL
+	  && sym->ts.type == BT_CHARACTER && sym->ts.is_c_interop
+	  && sym->ns->proc_name != NULL && sym->ns->proc_name->attr.is_bind_c)
+	TREE_TYPE (sym->backend_decl) = unsigned_char_type_node;
+    }
+
   /* Make sure we convert the types of the derived types from iso_c_binding
      into (void *).  */
   if (sym->attr.flavor != FL_PROCEDURE && sym->attr.is_iso_c
 
 


More information about the Fortran mailing list