Bug 49802 - [F03] [F08] Wrong code with VALUE, VALUE with arrays/DIMENSION
Summary: [F03] [F08] Wrong code with VALUE, VALUE with arrays/DIMENSION
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code, rejects-valid
Depends on: 35203
Blocks: F2003 F2008
  Show dependency treegraph
 
Reported: 2011-07-21 09:04 UTC by Tobias Burnus
Modified: 2018-11-22 17:21 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-06-17 00:00:00


Attachments
Patch for the resolver/parse part - not for the actual implementation (1022 bytes, patch)
2011-07-21 09:55 UTC, Tobias Burnus
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2011-07-21 09:04:35 UTC
Fortran 2008 relaxed the constrains with regards to VALUE. While Fortran 2003 only allowed it for objects which can be transferred by pass-by-value (in sprite of BIND(C) dummys/C nonpointer parameters), Fortran 2003 now allows for everything which may be copied in, which is nearly everything.

Fortran 2008 has:

C557  An entity with the VALUE attribute shall be a dummy data object
      that is not an assumed-size array or a coarray, and does not have
      a coarray ultimate component.

C558  An entity with the VALUE attribute shall not have the ALLOCATABLE,
      INTENT (INOUT), INTENT(OUT), POINTER, or VOLATILE attributes.


Fortran 2003 has:

C527 (R501)   If the VALUE attribute is specified, the PARAMETER, EXTERNAL,
     POINTER, ALLOCATABLE, DIMENSION, VOLATILE, INTENT(INOUT), or INTENT(OUT)
     attribute shall not be specified.

Thus: DIMENSION has been removed and just attr.codimension/attr.coarray_comp are prohibited - as a dummy with assumed size as there copy-in/copy-out will fail.
Comment 1 Tobias Burnus 2011-07-21 09:20:22 UTC
Additionally, the follow constraint of Fortran 2003 is gone:

C528 (R501)   If the VALUE attribute is specified, the length type
              parameter values shall be omitted or specified by
              initialization expressions.
Comment 2 Tobias Burnus 2011-07-21 09:55:16 UTC
Created attachment 24803 [details]
Patch for the resolver/parse part - not for the actual implementation

Implementation strategy:

* For scalar types, continue to pass by value (for optimization purpose)

* For strings, arrays, and complicated DT: Copy the data and pass by reference.

* For VALUE + OPTIONAL - also for scalars: copy and pass by reference

Note: For generating a copy one needs - as already currently - do a deep copy to capture also the allocatable components.

Example for alloc components with VALUE. The example fails (wrong result) with NAG, ifort, gfortran and g95; pgi gets an ICE and crayftn states "The array syntax statement is not conformable", which also looks bogus.

I believe that the test case is valid Fortran 2003.

implicit none
type t
  integer, allocatable :: A(:)
end type t

integer :: i
type(t) :: x

allocate(x%A(8))
x%A = [(i, i = 1, 8)]

call by_value(x)
print *, x%A

if (any (x%A /= [(i, i = 1, 8)])) call abort()

contains
  subroutine by_value(y)
    type(t), value :: y
    y%A = [(-10*i, i=1,9)]
    print *, y%A
  end subroutine
end
Comment 3 Tobias Burnus 2011-07-21 10:13:33 UTC
As postscript: Using strings works - but only as long as the length is known at compile time (as F2003 mandates). If not, the dump looks OK at a glance but it does not work:

CALLER:
   by_value (str, 10);
CALLEE:
   by_value (character(kind=1)[1:_y] y, integer(kind=4) _y)
      D.1554 = _y;
      _gfortran_transfer_integer_write (&dt_parm.0, &D.1554, 4);

but the latter does not print the expected "10" but some seemingly random number. Obviously, passing strings by value fails if the length is not known - one should thus go back to pass them by reference after copying.


Test case: Change "(*)" to "(10)" for a working program:

implicit none
character(len=10) :: str

str = "123456789"
call by_value(str)
print *, str
if (str /= "123456789") call abort()

contains
  subroutine by_value(y)
    character(len=*), value :: y
    print *, len(y)
    if (len(y) /= 10) call abort()
    print *, y
    y = "abcdefghij"
    print *, y
    if (str /= "abcdefghij") call abort()
  end subroutine
end
Comment 4 Tobias Burnus 2011-07-21 10:21:22 UTC
(In reply to comment #3)
>    by_value (character(kind=1)[1:_y] y, integer(kind=4) _y)

Technically, it makes sense that it does not work: The caller passes <m>+<n> bytes: sizeof(str) and sizeof(strlen); in this example: 10 bytes for str and 4 bytes for the length (value: 10). How should the poor callee know which bytes belong to the string length?

That's different to printf(char *format, ...): There one first knows what to expect before the unknown data comes.
Comment 5 Tobias Burnus 2013-03-21 16:19:56 UTC
The following gives an ICE:

call foo()
call foo("abc")
contains
subroutine foo(str)
character(len=3), value, optional :: str
if (present(str)) print *, str
end subroutine foo
end
Comment 6 Dominique d'Humieres 2013-06-17 15:05:05 UTC
The test in comment #3 (with  "(*)" changed to "(10)") aborts because the test

    if (str /= "abcdefghij") call abort()

fails (str=="123456789"). Is it expected?

I also confirm that compiling the test in comment #5 gives an ICE

pr49802_2.f90:6:0: internal compiler error: in fold_convert_loc, at fold-const.c:2075
 if (present(str)) print *, str
Comment 7 Dominique d'Humieres 2014-03-23 00:23:41 UTC
No idea why I set it to WAITING, moved to NEW.
Comment 8 Dominique d'Humieres 2014-07-20 18:41:26 UTC
> I also confirm that compiling the test in comment #5 gives an ICE

I get the same ICE with the following code

  call pr53876
end

subroutine pr53876
  IMPLICIT NONE
  TYPE :: individual
    integer :: icomp ! Add an extra component to test offset
    REAL, DIMENSION(:), ALLOCATABLE :: genes
  END TYPE
  CLASS(individual), DIMENSION(:), ALLOCATABLE :: indv, indv1
  allocate (indv(2), source = [individual(1, [99,999]), &
                               individual(2, [999,9999])])
!  allocate (indv1(2), source = [indv(1),indv(2)])
  print *, fun([indv(1),indv(2)])
contains
  elemental function fun(x) result(res)
     integer :: res
     class(individual), intent(in) :: x
     res = x%genes(1)
  end
END
Comment 9 Jürgen Reuter 2018-10-28 17:44:32 UTC
(In reply to Dominique d'Humieres from comment #8)
> > I also confirm that compiling the test in comment #5 gives an ICE
> 
> I get the same ICE with the following code
> 
>   call pr53876
> end
> 
> subroutine pr53876
>   IMPLICIT NONE
>   TYPE :: individual
>     integer :: icomp ! Add an extra component to test offset
>     REAL, DIMENSION(:), ALLOCATABLE :: genes
>   END TYPE
>   CLASS(individual), DIMENSION(:), ALLOCATABLE :: indv, indv1
>   allocate (indv(2), source = [individual(1, [99,999]), &
>                                individual(2, [999,9999])])
> !  allocate (indv1(2), source = [indv(1),indv(2)])
>   print *, fun([indv(1),indv(2)])
> contains
>   elemental function fun(x) result(res)
>      integer :: res
>      class(individual), intent(in) :: x
>      res = x%genes(1)
>   end
> END

This ICE is no longer present in trunk.
Comment 10 G. Steinmetz 2018-11-22 17:21:29 UTC
Update from comment 5 (combination of value and optional) :


$ cat z1.f90
subroutine s(x)
   character, value, optional :: x
   print *, present(x)
end


$ gfortran-9-20181111 -c z1.f90
z1.f90:3:0:

    3 |    print *, present(x)
      |
internal compiler error: in fold_convert_loc, at fold-const.c:2548
0x8a9bb3 fold_convert_loc(unsigned int, tree_node*, tree_node*)
        ../../gcc/fold-const.c:2548
0x6eafd6 gfc_conv_expr_present(gfc_symbol*)
        ../../gcc/fortran/trans-expr.c:1724
0x7155e9 gfc_conv_intrinsic_present
        ../../gcc/fortran/trans-intrinsic.c:3493
0x7155e9 gfc_conv_intrinsic_function(gfc_se*, gfc_expr*)
        ../../gcc/fortran/trans-intrinsic.c:9726
0x6fa2b4 gfc_conv_function_expr
        ../../gcc/fortran/trans-expr.c:6905
0x6ee90a gfc_conv_expr(gfc_se*, gfc_expr*)
        ../../gcc/fortran/trans-expr.c:8039
0x6f43b5 gfc_conv_expr_reference(gfc_se*, gfc_expr*, bool)
        ../../gcc/fortran/trans-expr.c:8184
0x71b007 gfc_trans_transfer(gfc_code*)
        ../../gcc/fortran/trans-io.c:2584
0x6c0067 trans_code
        ../../gcc/fortran/trans.c:2038
0x718afe build_dt
        ../../gcc/fortran/trans-io.c:2026
0x6c0047 trans_code
        ../../gcc/fortran/trans.c:2010
0x6e7674 gfc_generate_function_code(gfc_namespace*)
        ../../gcc/fortran/trans-decl.c:6509
0x6744d6 translate_all_program_units
        ../../gcc/fortran/parse.c:6125
0x6744d6 gfc_parse_file()
        ../../gcc/fortran/parse.c:6328
0x6bc89f gfc_be_parse_file
        ../../gcc/fortran/f95-lang.c:204