If use a non-constant integer as the length for an allocatable character variable array get a confusing error message. If the integer LINE_LENGTH is a PARAMETER it works. A work-around where the array is first allocated as a zero-size array and then included in the assignment works. Otherwise get an odd compile-time error about "A.0" being too large. program testit implicit none integer :: line_length=50 character(len=:),allocatable :: test_in(:) #ifdef BAD test_in=[ character(len=line_length) :: 'aaa','bb' ] #else allocate(character(len=line_length) :: test_in(0)) test_in=[character(len=line_length) :: test_in,'aaa','bb'] #endif write(*,*)test_in end program testit gfortran -UBAD xx.F90 aaa bb gfortran -DBAD xx.F90 xx.f90:4:0: test_in=[ character(len=line_length) :: 'this is a test' ] Error: size of variable 'A.0' is too large
Compiling the test with gcc4.8 or 4.9 gives an ICE pr91544.f90:6:0: internal compiler error: in gimplify_var_or_parm_decl, at gimplify.c:1741 test_in=[ character(len=line_length) :: 'aaa','bb' ] I get the error starting at gcc5.
Reconfirmed with GCC 13. Internally, the following code is generated (for my example, -fdump-tree-original): static character(kind=1) A.0[3][1:D.4246] = {"abcde", "fhji", "klmno"}; The problem is that D.4246 is a variable and not a constant. I think the proper solution is to create an array for max length, i.e. 5 in this example with right padding if too short: static character(kind=1) A.0[3][1:5] = {"abcde", "fhji ", "klmno"}; And then in the array use, there is already some code like the following. However, here, not only the .x (= desired length) but also the actual length (here: 5) has to be taken into account for the memmove/memset bit, i.e. min(.x, 5). (In the example below, .x, D.4251 and D.4252 are all the same - and match either the LHS after allocation or RHS of the assignment.) .x = i >= -2 ? (integer(kind=8)) (i + 2) : 0; ... D.4252 = .x; D.4253 = (void *) D.4242 + (sizetype) (((S.1 + D.4249) + D.4243) * x.span); D.4254 = (void *) &A.0[S.1]; if (D.4252 > 0) { if (NON_LVALUE_EXPR <D.4251> < NON_LVALUE_EXPR <D.4252>) { __builtin_memmove (D.4253, D.4254, (unsigned long) NON_LVALUE_EXPR <D.4251>); __builtin_memset (D.4253 + (sizetype) NON_LVALUE_EXPR <D.4251>, 32, (unsigned long) (NON_LVALUE_EXPR <D.4252> - NON_LVALUE_EXPR <D.4251>));