Hi Thomas, hi all,

first, I have now attached a different fix for PR 85781 (= original bug). Can you have a look?

I have the feeling (but didn't check) that your patch does not handle the following variant of the test case: "print *, x(m:n)" (i.e. the lower bound is not known at compile time).

I hope my patch covers all issues. – OK for the trunk?

Secondly:

On 1/21/20 7:32 PM, Thomas König wrote:
the attached patch fixes an ICE which could occur for empty
substrings (see test case).
I think one should rather fix the following issue.
I am not sure what you mean.  Does that mean that fixing the following
issue will also fix PR 85781

I am no longer sure what I meant myself ;-)

I initially thought those are directly related – but they now look related but independent bugs:

PR 85781 is about getting a non-ARRAY_TYPE (tree dump: "character") and using it as ARRAY_TYPE (tree dump: "character[lb:ub]").

While PR93336 is about (1) using  an ARRAY_TYPE when one should not. – And, additionally, about missing diagnostic related to (2) bind(c) and kind=4, (3) passing zero-length strings to non-zero-length dummy args, (4) diagnostic about truncating too long strings (esp. if of non-default, non-c_char kind).

Tobias

	PR fortran/85781
	* trans-expr.c (gfc_conv_substring): Handle non-ARRAY_TYPE strings
	of Bind(C) procedures.

	PR fortran/85781
	* gfortran.dg/bind_c_char_2.f90: New.
	* gfortran.dg/bind_c_char_3.f90: New.
	* gfortran.dg/bind_c_char_4.f90: New.
	* gfortran.dg/bind_c_char_5.f90: New.

diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index e1c0fb271de..5825a4b8ce3 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -2334,8 +2334,12 @@ gfc_conv_substring (gfc_se * se, gfc_ref * ref, int kind,
       else
 	tmp = build_fold_indirect_ref_loc (input_location,
 				       se->expr);
-      tmp = gfc_build_array_ref (tmp, start.expr, NULL);
-      se->expr = gfc_build_addr_expr (type, tmp);
+      /* For BIND(C), a BT_CHARACTER is not an ARRAY_TYPE.  */
+      if (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
+	{
+	  tmp = gfc_build_array_ref (tmp, start.expr, NULL);
+	  se->expr = gfc_build_addr_expr (type, tmp);
+	}
     }
 
   /* Length = end + 1 - start.  */
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_2.f90 b/gcc/testsuite/gfortran.dg/bind_c_char_2.f90
new file mode 100644
index 00000000000..23a0cac2b4f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_2.f90
@@ -0,0 +1,50 @@
+! { dg-do run }
+!
+! PR fortran/85781
+!
+! Co-contributed by G. Steinmetz 
+
+  use iso_c_binding, only: c_char
+  call s(c_char_'x', 1, 1)
+  call s(c_char_'x', 1, 0)
+  call s(c_char_'x', 0, -2)
+contains
+  subroutine s(x,m,n) bind(c)
+    use iso_c_binding, only: c_char
+    character(kind=c_char), value :: x
+    call foo(x(m:n), m, n)
+    if (n < m) then
+      if (len(x(m:n)) /= 0) stop 1
+      if (x(m:n) /= "") stop 2
+    else if (n == 1) then
+      if (len(x(m:n)) /= 1) stop 1
+      if (x(m:n) /= "x") stop 2
+    else
+      stop 14
+    end if
+    call foo(x(1:1), 1, 1)
+    call foo(x(1:0), 1, 0)
+    call foo(x(2:1), 2, 1)
+    call foo(x(0:-4), 0, -4)
+
+    call foo(x(1:), 1, 1)
+    call foo(x(2:), 2, 1)
+    call foo(x(:1), 1, 1)
+    call foo(x(:0), 1, 0)
+
+    if (n == 1) call foo(x(m:), m, n)
+    if (m == 1) call foo(x(:n), m, n)
+  end
+  subroutine foo(str, m, n)
+    character(len=*) :: str
+    if (n < m) then
+      if (len(str) /= 0) stop 11
+      if (str /= "") stop 12
+    else if (n == 1) then
+      if (len(str) /= 1) stop 13
+      if (str /= "x") stop 14
+    else
+      stop 14
+    end if
+  end
+end
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_3.f90 b/gcc/testsuite/gfortran.dg/bind_c_char_3.f90
new file mode 100644
index 00000000000..01113aad0c5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_3.f90
@@ -0,0 +1,51 @@
+! { dg-do run }
+! { dg-additional-options "-fcheck=all" }
+!
+! PR fortran/85781
+!
+! Co-contributed by G. Steinmetz 
+
+  use iso_c_binding, only: c_char
+  call s(c_char_'x', 1, 1)
+  call s(c_char_'x', 1, 0)
+  call s(c_char_'x', 0, -2)
+contains
+  subroutine s(x,m,n) bind(c)
+    use iso_c_binding, only: c_char
+    character(kind=c_char), value :: x
+    call foo(x(m:n), m, n)
+    if (n < m) then
+      if (len(x(m:n)) /= 0) stop 1
+      if (x(m:n) /= "") stop 2
+    else if (n == 1) then
+      if (len(x(m:n)) /= 1) stop 1
+      if (x(m:n) /= "x") stop 2
+    else
+      stop 14
+    end if
+    call foo(x(1:1), 1, 1)
+    call foo(x(1:0), 1, 0)
+    call foo(x(2:1), 2, 1)
+    call foo(x(0:-4), 0, -4)
+
+    call foo(x(1:), 1, 1)
+    call foo(x(2:), 2, 1)
+    call foo(x(:1), 1, 1)
+    call foo(x(:0), 1, 0)
+
+    if (n == 1) call foo(x(m:), m, n)
+    if (m == 1) call foo(x(:n), m, n)
+  end
+  subroutine foo(str, m, n)
+    character(len=*) :: str
+    if (n < m) then
+      if (len(str) /= 0) stop 11
+      if (str /= "") stop 12
+    else if (n == 1) then
+      if (len(str) /= 1) stop 13
+      if (str /= "x") stop 14
+    else
+      stop 14
+    end if
+  end
+end
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_4.f90 b/gcc/testsuite/gfortran.dg/bind_c_char_4.f90
new file mode 100644
index 00000000000..cce9270f1b6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_4.f90
@@ -0,0 +1,21 @@
+! { dg-do run }
+! { dg-additional-options "-fcheck=all" }
+! { dg-shouldfail "Substring out of bounds" }
+!
+! PR fortran/85781
+!
+! Co-contributed by G. Steinmetz 
+
+  use iso_c_binding, only: c_char
+  call s(c_char_'x', 1, 2)
+contains
+  subroutine s(x,m,n) bind(c)
+    use iso_c_binding, only: c_char
+    character(kind=c_char), value :: x
+    call foo(x(m:n), m, n)
+  end
+  subroutine foo(str, m, n)
+    character(len=*) :: str
+  end
+end
+! { dg-output "Fortran runtime error: Substring out of bounds: upper bound .2. of 'x' exceeds string length .1." }
diff --git a/gcc/testsuite/gfortran.dg/bind_c_char_5.f90 b/gcc/testsuite/gfortran.dg/bind_c_char_5.f90
new file mode 100644
index 00000000000..9092dd58396
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bind_c_char_5.f90
@@ -0,0 +1,21 @@
+! { dg-do run }
+! { dg-additional-options "-fcheck=all" }
+! { dg-shouldfail "Substring out of bounds" }
+!
+! PR fortran/85781
+!
+! Co-contributed by G. Steinmetz 
+
+  use iso_c_binding, only: c_char
+  call s(c_char_'x', -2, -2)
+contains
+  subroutine s(x,m,n) bind(c)
+    use iso_c_binding, only: c_char
+    character(kind=c_char), value :: x
+    call foo(x(m:), m, n)
+  end
+  subroutine foo(str, m, n)
+    character(len=*) :: str
+  end
+end
+! { dg-output "Fortran runtime error: Substring out of bounds: lower bound .-2. of 'x' is less than one" }

Reply via email to