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.
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.
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
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
(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.
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
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
No idea why I set it to WAITING, moved to NEW.
> 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
(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.
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