Bug 51976 - [F2003] Support deferred-length character components of derived types (allocatable string length)
Summary: [F2003] Support deferred-length character components of derived types (alloca...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Paul Thomas
URL:
Keywords: rejects-valid
: 47545 49050 51075 51394 51550 (view as bug list)
Depends on: 57456
Blocks: 45170 56138
  Show dependency treegraph
 
Reported: 2012-01-24 08:00 UTC by Tobias Burnus
Modified: 2015-09-03 21:18 UTC (History)
12 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-01-30 00:00:00


Attachments
Draft patch for the PR (1.48 KB, patch)
2013-02-09 20:33 UTC, Paul Thomas
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2012-01-24 08:00:04 UTC
See also PR 45170 comment 9 - and the examples in PR fortran/51550, PR fortran/47545, PR fortran/49050 and PR fortran/51075.

Currently, using

type t
  character(len=:), allocatable :: str_comp
end type t

is not supported and is rejected by a not-yet-supported error.

TODO: There needs to be a hidden (integer) component, which stores the string length.
Comment 1 Tobias Burnus 2012-01-24 08:04:21 UTC
*** Bug 51075 has been marked as a duplicate of this bug. ***
Comment 2 Tobias Burnus 2012-01-24 08:04:35 UTC
*** Bug 49050 has been marked as a duplicate of this bug. ***
Comment 3 Tobias Burnus 2012-01-24 08:04:46 UTC
*** Bug 51550 has been marked as a duplicate of this bug. ***
Comment 4 Tobias Burnus 2012-01-24 08:04:54 UTC
*** Bug 47545 has been marked as a duplicate of this bug. ***
Comment 5 Tobias Burnus 2012-05-14 16:43:52 UTC
*** Bug 51394 has been marked as a duplicate of this bug. ***
Comment 6 Tobias Burnus 2012-11-08 15:00:05 UTC
Note that after this feature works, we have to ensure that FORALL with a generated temporary works with different string lengths:

  type t
    character(len=:), pointer :: str
  end type t
  type(t), pointer :: strarry(:), strarray2

  allocate(strarray(3), strarray2)
  allocate(character(len=5) :: strarray(1)%str, strarray2(1)%str)
  allocate(character(len=7) :: strarray(2)%str, strarray2(2)%str)
  allocate(character(len=2) :: strarray(2)%str, strarray2(3)%str)

  forall(i=1:3) strarray2(i)%str = strarray(i)%str
Comment 7 Paul Thomas 2013-02-09 20:33:56 UTC
Created attachment 29406 [details]
Draft patch for the PR

This turned out to be easier than I expected.  It obviously needs a bit of cleaning up; deferred character length variables should be made consistent with their variable cousins.  This will not take much doing and I expect to submit the patch tomorrow.

Bootstraps and regtests on trunk.  Proto-testcase:
  type t
    character(len=:), allocatable :: str_comp
  end type t
  type(t) :: x
  allocate (x%str_comp, source = "abc")
  print *, len (x%str_comp), x%str_comp

  deallocate (x%str_comp)

  allocate (x%str_comp, source = "abcdefghijklmnop")
  print *, len (x%str_comp), x%str_comp

  x%str_comp = "xyz"
  print *, len (x%str_comp), x%str_comp

  x%str_comp = "abcdefghijklmnop"
  call foo (x%str_comp)
contains
  subroutine foo (chr)
    character (*) :: chr
    print *, len (chr), chr
  end subroutine
end

Cheers

Paul
Comment 8 Dominique d'Humieres 2013-02-10 19:59:37 UTC
With the patch in comment #7 most of the duplicates compile and run, but:

pr49050 which gives

pr49050.f90:13.10:

   item = item_type('key')
          1
Error: No initializer for component '_key' given in the structure constructor at (1)!

(note that the original code at  http://gcc.gnu.org/ml/fortran/2011-05/msg00129.html compiles but segfault at runtime);

pr51550 which gives an ICE

gimplification failed:
0 <integer_cst 0x14280bc80 type <integer_type 0x1428125e8 integer(kind=4)> constant 0>
pr51550.f90: In function 'add_key_only':
pr51550.f90:64:0: internal compiler error: gimplification failed
     allocate( character(len=len(key)) :: value%key )
 ^

and a similar error for the test in comment #6

  type t
    character(len=:), pointer :: str
  end type t
  type(t), pointer :: strarray(:), strarray2(:)

  allocate(strarray(3), strarray2(3))
  allocate(character(len=5) :: strarray(1)%str, strarray2(1)%str)
  allocate(character(len=7) :: strarray(2)%str, strarray2(2)%str)
  allocate(character(len=2) :: strarray(2)%str, strarray2(3)%str)

!  forall(i=1:3) strarray2(i)%str = strarray(i)%str
  print *, (len(strarray2(i)%str), i=1,3)
end

gimplification failed:
0 <integer_cst 0x14280bc80 type <integer_type 0x1428125e8 integer(kind=4)> constant 0>
pr51976_1.f90: In function 'MAIN__':
pr51976_1.f90:7:0: internal compiler error: gimplification failed
   allocate(character(len=5) :: strarray(1)%str, strarray2(1)%str)
 ^

If the FORALL is uncommented, the ICE is

pr51976_1.f90: In function 'MAIN__':
pr51976_1.f90:11:0: internal compiler error: in gfc_add_modify_loc, at fortran/trans.c:159
   forall(i=1:3) strarray2(i)%str = strarray(i)%str
 ^

At runtime the test attached to pr48654 gives a segmentation fault (fixed by the revised patch sent privately).

The iso_varying_string I have in store also compiles and run (limited testing).
Comment 9 Tobias Burnus 2013-02-25 08:49:03 UTC
Latest patch: http://gcc.gnu.org/ml/fortran/2013-02/msg00136.html
Comment 10 Tobias Burnus 2013-05-20 09:23:44 UTC
FYI: Ian Hardy has some fancy examples uses character(:) in DT at the bottom of the thread http://software.intel.com/en-us/forums/topic/326077 (attached files)
Comment 12 Walter Spector 2013-08-28 22:33:24 UTC
Adding myself (Walter Spector) to the cc list.  My contribution is a simple little test case that works with current versions of Intel (with -assume realloc_lhs option) and NAG.  As of todays gfortran snapshot (20130828), I get a lot of 'Deferred-length character component 'city' at (1) is not yet supported' errors.


program city_names
  implicit none
 
  type city_entry_t
    character(:), allocatable :: city
    character(:), allocatable :: state
  end type
 
  type(city_entry_t), allocatable :: cities(:)
 
  integer :: i
 
  cities = (/  &
    city_entry_t ("San Francisco", "California"),  &
    city_entry_t ("Portland", "Oregon"),  &
    city_entry_t ("Seattle", "Washington"),  &
    city_entry_t ("Salt Lake City", "Utah"),  &
    city_entry_t ("Reno", "Nevada"),  &
    city_entry_t ("Tucson", "Arizona"),  &
    city_entry_t ("Denver", "Colorado"),  &
    city_entry_t ("Kansas City","Kansas"),  &
    city_entry_t ("Tulsa", "Oklahoma"),  &
    city_entry_t ("Houston", "Texas")  &
  /)
 
  print '(5a)', (">",cities(i)%city, ", ", cities(i)%state,"<", i=1,size (cities))
 
end program
Comment 13 janus 2014-02-19 15:54:03 UTC
The latest patch posted at

http://gcc.gnu.org/ml/fortran/2014-02/msg00109.html

works smoothly on the test case in comment 12.
Comment 14 Dominique d'Humieres 2014-02-21 14:06:45 UTC
Hi all,

> I think it went as follows: We found out that some code doesn't - in
> particular code which uses array-valued deferred-length characters.
> After trying to fix it, you (Paul) decided that the simplest way to fix
> it would be the new array descriptor - and then it got stuck.

A list of known problems can be found at

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51976#c8

> Regarding this patch, I have mixed feelings.  I think it is a much wished
> feature - but I am not sure about the stability of the patch and it is
> rather large, given that we are in stage 4.

I have the patch in my working tree since more than a year without any 
related problem. Indeed I had to practice minor surgery to keep it alive.
AFAICT the changes are quite localized and I don't expect any major 
problem if it is committed.

> Regarding the new array descriptor: I think it would be useful if we
> could get the new descriptor working early in the GCC 4.10/5.0/2015
> development stage.  I think the main large task is to convert all all
> remaining stride-based code to stride-multiplier code without breaking
> vectorization and causing other regressions.  Additionally, it would be
> nice to get rid of "offset" - and have in the descriptor always an
> lower_bound of 0, except for pointers/allocatables (cf.  TS29113).  I
> think the version on the branch is in a relatively good shape; however,
> the stride and offset changes seem to be of such a kind that one needs to
> modify several code locations simultaneously - otherwise, it will break
> badly.  Additionally, all remaining regressions have to be fixed.  When
> that's done, adding some extra field is all what's needed.  (As follow
> up, enough remains to be done: I'd like to use it for all class(*),
> possibly even for nonarray class(type), assumed-rank needs an update,
> assumed-shape/-rank/deferred-shape character arrays also have to be
> adapted (also mandated by TS29113 for interop).  And we should do an ABI
> cleanup in libgfortran as we have now the chance to break the ABI.) - Is
> anyone volunteering?

I think the new array descriptor should be given the highest priority and 
fortran-dev merged to trunk as soon as the last regression is fixed. My 
tests show that its present state is quite close (note regtesting should 
be done for both -m32 and -m64: some scanning tests fail with -m32).

Cheers,

Dominique
Comment 15 janus 2014-03-06 21:46:03 UTC
Author: janus
Date: Thu Mar  6 21:45:31 2014
New Revision: 208386

URL: http://gcc.gnu.org/viewcvs?rev=208386&root=gcc&view=rev
Log:
2014-03-06  Paul Thomas  <pault@gcc.gnu.org>
	    Janus Weil  <janus@gcc.gnu.org>

	PR fortran/51976
	* gfortran.h (symbol_attribute): Add deferred_parameter attribute.
	* primary.c (build_actual_constructor): It is not an error if
	a missing component has the deferred_parameter attribute;
	equally, if one is given a value, it is an error.
	* resolve.c (resolve_fl_derived0): Remove error for deferred
	character length components.  Add the hidden string length
	field to the structure. Give it the deferred_parameter
	attribute.
	* trans-array.c (duplicate_allocatable): Add a strlen field
	which is used as the element size if it is non-null.
	(gfc_duplicate_allocatable, gfc_copy_allocatable_data): Pass a
	NULL to the new argument in duplicate_allocatable.
	(structure_alloc_comps): Set the hidden string length as
	appropriate. Use it in calls to duplicate_allocatable.
	(gfc_alloc_allocatable_for_assignment): When a deferred length
	backend declaration is variable, use that; otherwise use the
	string length from the expression evaluation.
	* trans-expr.c (gfc_conv_component_ref): If this is a deferred
	character length component, the string length should have the
	value of the hidden string length field.
	(gfc_trans_subcomponent_assign): Set the hidden string length
	field for deferred character length components.  Allocate the
	necessary memory for the string.
	(alloc_scalar_allocatable_for_assignment): Same change as in
	gfc_alloc_allocatable_for_assignment above.
	* trans-stmt.c (gfc_trans_allocate): Likewise.
	* trans-intrinsic (size_of_string_in_bytes): Make non-static.
	* trans-types.c (gfc_get_derived_type): Set the tree type for
	a deferred character length component.
	* trans.c (gfc_deferred_strlen): New function.
	* trans.h (size_of_string_in_bytes,gfc_deferred_strlen): New prototypes.


2014-03-06  Paul Thomas  <pault@gcc.gnu.org>
	    Janus Weil  <janus@gcc.gnu.org>

	PR fortran/51976
	* gfortran.dg/deferred_type_component_1.f90 : New test.
	* gfortran.dg/deferred_type_component_2.f90 : New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/deferred_type_component_1.f90
    trunk/gcc/testsuite/gfortran.dg/deferred_type_component_2.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/fortran/primary.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/trans-array.c
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans-intrinsic.c
    trunk/gcc/fortran/trans-stmt.c
    trunk/gcc/fortran/trans-types.c
    trunk/gcc/fortran/trans.c
    trunk/gcc/fortran/trans.h
    trunk/gcc/testsuite/ChangeLog
Comment 16 Jakub Jelinek 2014-06-03 19:54:20 UTC
subroutine foo ()
  type dt
    character(len=:), allocatable :: o
    character(len=:), allocatable :: n(:)
  end type
  type (dt) :: d
  logical :: l
  integer :: n
  n = 4
  allocate(character(len=n+1) :: d%o)
  allocate(character(len=n+2) :: d%n(4))
end

seems to ICE during gimplification (there is 0 = 4; stmt in *.original), and the length of d%n allocation is weird too.
subroutine bar ()
  character(len=:), allocatable :: o, o2
  character(len=:), allocatable :: n(:), n2(:)
  allocate(character(len=4) :: o, n(10))
  o2 = o
  n2 = n
end
ICEs too.
Comment 17 Dominique d'Humieres 2014-11-16 15:35:48 UTC
I think the last issues in comment 16 can be tracked by pr54070 and this PR closed as FIXED.
Comment 18 Dominique d'Humieres 2015-09-03 21:18:41 UTC
> I think the last issues in comment 16 can be tracked by pr54070 and
> this PR closed as FIXED.

No answer since more than a year and a half. Closing as FIXED. Please open new PRs for new issues.