Patchwork [Fortran,committed] PR49110/52843 - allow len=: string as result of PURE functions

login
register
mail settings
Submitter Tobias Burnus
Date May 12, 2012, 9:56 a.m.
Message ID <4FAE33C9.2010408@net-b.de>
Download mbox | patch
Permalink /patch/158728/
State New
Headers show

Comments

Tobias Burnus - May 12, 2012, 9:56 a.m.
Committed as obvious: character(len=:) is allowed as result in pure 
functions - while character(len=*) functions are not. (In the latter 
case, the length the function returns depends on the definition of the 
caller (!).)

The attached patch was build and regtested on x86-64-linux and committed 
as Rev. 187427 to the trunk.

  * * *

There are a few other deferred-string patches in the pipeline:

* Function-result related (e.g. REPEAT bugs), see my (RFC) patch, posted 
yesterday.
* Alessandro's patch. (The first draft has been posted and reviewed; 
Alessandro will soon post an updated version.)

I think the main still missing features are: 
"allocate(character(len=var) :: str)" (which is currently rejected) and 
deferred-length components of derived types. However, there are still a 
couple of other bugs - especially related to arrays/array constructors.

Tobias

Patch

2012-05-12  Tobias Burnus  <burnus@net-b.de>

	PR fortran/49110
	PR fortran/52843
	* resolve.c (resolve_fl_procedure): Don't regard
	character(len=:) as character(*) in the diagnostic.

2012-05-12  Tobias Burnus  <burnus@net-b.de>

	PR fortran/49110
	PR fortran/52843
	* gfortran.dg/deferred_type_param_5.f90: New.

diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index b3a23ed..9814c14 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -10721,17 +10721,17 @@  resolve_fl_procedure (gfc_symbol *sym, int mp_flag)
 
   /* 5.1.1.5 of the Standard: A function name declared with an asterisk
      char-len-param shall not be array-valued, pointer-valued, recursive
      or pure.  ....snip... A character value of * may only be used in the
      following ways: (i) Dummy arg of procedure - dummy associates with
      actual length; (ii) To declare a named constant; or (iii) External
      function - but length must be declared in calling scoping unit.  */
   if (sym->attr.function
-      && sym->ts.type == BT_CHARACTER
+      && sym->ts.type == BT_CHARACTER && !sym->ts.deferred
       && sym->ts.u.cl && sym->ts.u.cl->length == NULL)
     {
       if ((sym->as && sym->as->rank) || (sym->attr.pointer)
 	  || (sym->attr.recursive) || (sym->attr.pure))
 	{
 	  if (sym->as && sym->as->rank)
 	    gfc_error ("CHARACTER(*) function '%s' at %L cannot be "
 		       "array-valued", sym->name, &sym->declared_at);
--- /dev/null	2012-05-12 08:53:12.703771173 +0200
+++ gcc/gcc/testsuite/gfortran.dg/deferred_type_param_5.f90	2012-05-12 11:27:49.000000000 +0200
@@ -0,0 +1,51 @@ 
+! { dg-do compile }
+!
+! PR fortran/49110
+! PR fortran/52843
+!
+! Based on a contributed code by jwmwalrus@gmail.com
+!
+! Before, character(len=:) result variable were rejected in PURE functions. 
+!
+module mod1
+    use iso_c_binding
+    implicit none
+
+contains
+    pure function c_strlen(str)
+      character(KIND = C_CHAR), intent(IN) :: str(*)
+      integer :: c_strlen,i
+
+      i = 1
+      do
+        if (i < 1) then
+          c_strlen = 0
+          return
+        end if
+        if (str(i) == c_null_char) exit
+        i = i + 1
+      end do
+      c_strlen = i - 1
+    end function c_strlen
+    pure function c2fstring(cbuffer) result(string)
+        character(:), allocatable :: string
+        character(KIND = C_CHAR), intent(IN) :: cbuffer(*)
+        integer :: i
+
+    continue
+        string = REPEAT(' ', c_strlen(cbuffer))
+
+        do i = 1, c_strlen(cbuffer)
+            if (cbuffer(i) == C_NULL_CHAR) exit
+            string(i:i) = cbuffer(i)
+        enddo
+
+        string = TRIM(string)
+    end function
+end module mod1
+
+use mod1
+character(len=:), allocatable :: str
+str = c2fstring("ABCDEF"//c_null_char//"GHI")
+if (len(str) /= 6 .or. str /= "ABCDEF") call abort()
+end