Bug 89077 - ICE using * as len specifier for character parameter
Summary: ICE using * as len specifier for character parameter
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 8.2.0
: P3 normal
Target Milestone: 8.4
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: 31237
  Show dependency treegraph
 
Reported: 2019-01-27 08:48 UTC by Rodrigo Rodrigues
Modified: 2019-03-03 22:27 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-01-27 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Rodrigo Rodrigues 2019-01-27 08:48:30 UTC
I am getting an Internal Compiler Error when I use assumed character length (*) in a parameter declaration, when using character substring (apparently, compiler fails to determine the character length and crashes).



program test
  implicit none
  integer :: i

  ! assumed character length works normally here
  character(*), parameter :: str = 'abcdef'

  ! also works, with intrinsic char inside transfer
  character(*), parameter :: str1 = transfer([(char(64+i), i=1,len(str))], str)

  ! crashes with ICE here, with character substring inside transfer
  character(*), parameter :: str2 = transfer([(str(i:i), i=1,len(str))], str)

  ! it works when the type is specified in array constructor
  character(*), parameter :: str3 = transfer([character :: (str(i:i), i=1,len(str))], str)

  ! also works, without assumed character length
  character(len(str)), parameter :: str4 = transfer([(str(i:i), i=1,len(str))], str)

  print *, str, len(str)       ! 'abcdef', 6
  print *, str1, len(str1)     ! 'ABCDEF', 6
  ! print *, str2, len(str2)   ! should output 'abcdef', 6, but crashes
  print *, str3, len(str3)     ! 'abcdef', 6
  print *, str4, len(str4)     ! 'abcdef', 6
end
Comment 1 Rodrigo Rodrigues 2019-01-27 09:46:57 UTC
Moreover, removing the parameter specifier also produces an ICE:

  character(len(str)) :: str2 = transfer([(str(i:i), i=1,len(str))], str)

> internal compiler error: in gfc_conv_string_init, at fortran/trans-const.c:148
> libbacktrace could not find executable to open
Comment 2 Dominique d'Humieres 2019-01-27 10:11:00 UTC
Confirmed from at least 4.8 up to trunk (9.0).

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x10)
    frame #0: 0x000000010001eb42 f951`::add_init_expr_to_sym(name=<unavailable>, initp=0x00007ffeefbfeb60, var_locus=<unavailable>) at decl.c:1924
   1921			    }
   1922			  else if (init->ts.u.cl && init->ts.u.cl->length)
   1923			    sym->ts.u.cl->length =
-> 1924					gfc_copy_expr (sym->value->ts.u.cl->length);
   1925			}
   1926		    }
   1927		  /* Update initializer character length according symbol.  */
(lldb) p sym->value
(gfc_expr *) $1 = 0x0000000000000000
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x10)
  * frame #0: 0x000000010001eb42 f951`::add_init_expr_to_sym(name=<unavailable>, initp=0x00007ffeefbfeb60, var_locus=<unavailable>) at decl.c:1924
    frame #1: 0x00000001000280e6 f951`gfc_match_data_decl() at decl.c:2869
    frame #2: 0x0000000100089096 f951`::decode_statement() at parse.c:65
    frame #3: 0x0000000100089091 f951`::decode_statement()
    frame #4: 0x000000010008cfa0 f951`::next_statement() at parse.c:1241
    frame #5: 0x000000010008fa36 f951`::parse_spec(st=ST_DATA_DECL) at parse.c:3865
    frame #6: 0x0000000100092c10 f951`::parse_progunit(st=ST_NONE) at parse.c:5680
    frame #7: 0x000000010009457d f951`gfc_parse_file() at parse.c:6220
    frame #8: 0x00000001000dd3ec f951`::gfc_be_parse_file() at f95-lang.c:204
    frame #9: 0x0000000100cb0bda f951`::compile_file() at toplev.c:456
    frame #10: 0x0000000101387064 f951`toplev::main(int, char**) at toplev.c:2176
    frame #11: 0x0000000101386f30 f951`toplev::main(this=0x00007ffeefbff10e, argc=<unavailable>, argv=<unavailable>)
    frame #12: 0x00000001013898d1 f951`main(argc=2, argv=0x00007ffeefbff148) at main.c:39
Comment 3 Rodrigo Rodrigues 2019-01-29 04:06:25 UTC
I'm not sure it is related, but in this test case, I don't get internal errors, but wrong results:

program reverse
  implicit none
  character(20), parameter :: input = 'Forward'
  integer i
  character(len(input)), parameter :: output = &
     transfer([(input(i:i),i=len_trim(input),1,-1)],trim(input))
  print *, input, '#', len(input)
  print *, output, '#', len(output)
end program reverse

My expected output was:

 Forward             #          20
 drawroF             #          20
But I got this:

 Forward             #          20
 drawroF#           20
Comment 4 Harald Anlauf 2019-01-29 21:28:31 UTC
Replacing

  character(*), parameter :: str2 = transfer([(str(i:i), i=1,len(str))], str)

by

  character, parameter    :: str2a(*) = [(str(i:i), i=1,len(str))]
  character(*), parameter :: str2 = transfer(str2a, str)

'solves' the issue.  I think there are close (code-wise) duplicates to
this issue, where some information of an array constructor is lost in
constant expressions.
Comment 5 Harald Anlauf 2019-01-29 22:09:50 UTC
The following patch fixes the testcase and seems to pass regression testing.

Index: gcc/fortran/decl.c
===================================================================
--- gcc/fortran/decl.c  (revision 268369)
+++ gcc/fortran/decl.c  (working copy)
@@ -1921,7 +1921,7 @@
                    }
                  else if (init->ts.u.cl && init->ts.u.cl->length)
                    sym->ts.u.cl->length =
-                               gfc_copy_expr (sym->value->ts.u.cl->length);
+                               gfc_copy_expr (init->ts.u.cl->length);
                }
            }
          /* Update initializer character length according symbol.  */


Maybe it needs to be checked against a larger code base.

It changes (and hopefully fixes) almost 10-year old code.

Thanks, Dominique, for pointing to the right area.
Comment 6 Harald Anlauf 2019-01-29 22:27:32 UTC
(In reply to Harald Anlauf from comment #5)
It does not fix the issue in comment #3.  In fact, the simpler testcase

program pr89077_3
  implicit none
  character(20), parameter :: input = 'Forward'
  integer i
  character(len(input)), parameter :: same = &
       transfer (trim (input), trim (input))
  print *, input, '#', len(input)
  print *, same, '#', len(same)
end program pr89077_3

prints random junk on the second line:

 Forward             #          20
 ForwardQÀ@(#          20

:-(
Comment 7 Harald Anlauf 2019-01-31 22:17:50 UTC
(In reply to Harald Anlauf from comment #6)

Playing around and getting completely lost during a gdb session,
I became suspicious that the second issue has to do with missed
padding that interestingly occurs also with Hollerith constants:

program pr89077_3
  implicit none
  integer,      parameter :: m = 20
  character(*), parameter :: s = 'Forward'
  character(m), parameter :: t = s
  character(m), parameter :: u = transfer (s, s)
  character(m), parameter :: v = 7HFORWARD
  character(m), parameter :: w = transfer (s, s) // ""
  print *, t, '#'
  print *, u, '#'
  print *, v, '#'
  print *, w, '#'
end program pr89077_3

This prints:

 % ./a.out | cat -v
 Forward             #
 Forward^@^@^@Q^@M-P^@p^@^@^@^@a#
 FORWARD ^@^@Q^@M-P^@M-Pa^H^@M-ha#
 Forward             #
Comment 8 Harald Anlauf 2019-01-31 22:44:44 UTC
OK, here's another one for fun:

program pr89077_4
  implicit none
  character(*), parameter :: s = 7HForward
  print *, '#', s, '#', len (s)
end program pr89077_4

prints:

 #Forward #           8

This time it is really padded with a space which comes out of the blue.

Oracle sunf95 prints:

 #Forward# 7

Intel rejects it.
Comment 9 anlauf 2019-02-04 20:44:53 UTC
Author: anlauf
Date: Mon Feb  4 20:44:22 2019
New Revision: 268525

URL: https://gcc.gnu.org/viewcvs?rev=268525&root=gcc&view=rev
Log:
2019-02-04  Harald Anlauf  <anlauf@gmx.de>

	PR fortran/89077
	* gfortran.dg/pr89077.f90: New test.

2019-02-04  Harald Anlauf  <anlauf@gmx.de>

	PR fortran/89077
	* gfortran.dg/pr89077.f90: New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/pr89077.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/decl.c
    trunk/gcc/testsuite/ChangeLog
Comment 10 Harald Anlauf 2019-02-04 20:48:17 UTC
The ICE in comment #0 is fixed on trunk so far.

The ICE is comment #1 is occurring on a different path and is under
further investigation, as well as the other wrong-code issues.
Comment 11 Harald Anlauf 2019-02-05 21:14:02 UTC
I'm currently using the following minimal testcases for further debugging:

==> f1.f90 <==
  character(1), parameter :: u = transfer ([('a'(i:i),i=1,1)], 'x')
  print *, u
end

==> f2.f90 <==
  character(1), save      :: v = transfer ([('a'(i:i),i=1,1)], 'x')
  print *, v
end

==> f3.f90 <==
  character(1), save      :: w = transfer ([('a'     ,i=1,1)], 'x')
  print *, w
end


f1 and f3 work, f2 does ICE.
Comment 12 Harald Anlauf 2019-02-05 22:25:22 UTC
Further variant:

==> f4.f90 <==
  character(1), save      :: y = transfer ([('a'(1:1),i=1,1)], 'x')
  print *, y
end

generates exactly the same code as f3, although it passes along slightly
different pathes during simplification.

BTW, I noticed that f1 produces an IMHO insane dump-tree, with a call
to _gfortran_internal_pack!

I'd never expected to get such inefficient code in that case.
Comment 13 anlauf 2019-02-09 17:25:54 UTC
Author: anlauf
Date: Sat Feb  9 17:25:23 2019
New Revision: 268726

URL: https://gcc.gnu.org/viewcvs?rev=268726&root=gcc&view=rev
Log:
2019-02-09  Harald Anlauf  <anlauf@gmx.de>

	PR fortran/89077
	* resolve.c (gfc_resolve_substring_charlen): Check substring
	length for constantness prior to general calculation of length.

	PR fortran/89077
	* gfortran.dg/substr_simplify.f90: New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/substr_simplify.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog
Comment 14 anlauf 2019-02-10 20:01:46 UTC
Author: anlauf
Date: Sun Feb 10 20:01:15 2019
New Revision: 268752

URL: https://gcc.gnu.org/viewcvs?rev=268752&root=gcc&view=rev
Log:
2019-02-10  Harald Anlauf  <anlauf@gmx.de>

	Backport from trunk
	PR fortran/89077
	* decl.c (add_init_expr_to_sym): Copy length of string initializer
	to declared symbol.

	PR fortran/89077
	* gfortran.dg/pr89077.f90: New test.


Added:
    branches/gcc-8-branch/gcc/testsuite/gfortran.dg/pr89077.f90
Modified:
    branches/gcc-8-branch/gcc/fortran/ChangeLog
    branches/gcc-8-branch/gcc/fortran/decl.c
    branches/gcc-8-branch/gcc/testsuite/ChangeLog
Comment 15 anlauf 2019-02-10 20:06:05 UTC
Author: anlauf
Date: Sun Feb 10 20:05:34 2019
New Revision: 268753

URL: https://gcc.gnu.org/viewcvs?rev=268753&root=gcc&view=rev
Log:
2019-02-10  Harald Anlauf  <anlauf@gmx.de>

	Backport from trunk
	PR fortran/89077
	* decl.c (add_init_expr_to_sym): Copy length of string initializer
	to declared symbol.

	PR fortran/89077
	* gfortran.dg/pr89077.f90: New test.


Added:
    branches/gcc-7-branch/gcc/testsuite/gfortran.dg/pr89077.f90
Modified:
    branches/gcc-7-branch/gcc/fortran/ChangeLog
    branches/gcc-7-branch/gcc/fortran/decl.c
    branches/gcc-7-branch/gcc/testsuite/ChangeLog
Comment 16 Harald Anlauf 2019-02-14 22:41:10 UTC
Regarding the unwanted padding with \0, the following patch seems to
solve the issue with transfer.

Index: decl.c
===================================================================
--- decl.c      (revision 268897)
+++ decl.c      (working copy)
@@ -1754,6 +1754,12 @@
       free (expr->value.character.string);
       expr->value.character.string = s;
       expr->value.character.length = len;
+      if (expr->representation.length)
+       {
+         expr->representation.length = 0;
+         free (expr->representation.string);
+         expr->representation.string = NULL;
+       }
     }
 }

Testcase:

  character(8) ,parameter :: s = transfer ('ab', 'cd')
  character(8) ,parameter :: t = 2Hxy
  print *, "'", s, "'"
  print *, "'", t, "'"
end

./a.out  | cat -v
 'ab      '
 'xy      '
Comment 17 Harald Anlauf 2019-02-15 20:48:38 UTC
(In reply to Harald Anlauf from comment #16)
> Regarding the unwanted padding with \0, the following patch seems to
> solve the issue with transfer.

Regtested cleanly and submitted here:

https://gcc.gnu.org/ml/fortran/2019-02/msg00126.html
Comment 18 anlauf 2019-02-17 21:14:55 UTC
Author: anlauf
Date: Sun Feb 17 21:14:14 2019
New Revision: 268973

URL: https://gcc.gnu.org/viewcvs?rev=268973&root=gcc&view=rev
Log:
2019-02-17  Harald Anlauf  <anlauf@gmx.de>

	PR fortran/89077
	* decl.c (gfc_set_constant_character_len): Clear original string
	representation after padding has been performed to target length.

	PR fortran/89077
	* gfortran.dg/transfer_simplify_12.f90: New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/transfer_simplify_12.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/decl.c
    trunk/gcc/testsuite/ChangeLog
Comment 19 Harald Anlauf 2019-02-17 21:28:13 UTC
The issues reported in comment #0, #1 and #3 should be fixed on trunk.
The fix for comment #0 has been backported to 7- and 8-branches.

Can the OP please confirm that the reported issues have been fixed?
Comment 20 Dominique d'Humieres 2019-03-03 22:10:55 UTC
Is there any plan to back port r268973?
Comment 21 anlauf 2019-03-03 22:24:32 UTC
Author: anlauf
Date: Sun Mar  3 22:24:00 2019
New Revision: 269357

URL: https://gcc.gnu.org/viewcvs?rev=269357&root=gcc&view=rev
Log:
2019-03-03  Harald Anlauf  <anlauf@gmx.de>

	Backport from trunk
	PR fortran/89077
	* decl.c (gfc_set_constant_character_len): Clear original string
	representation after padding has been performed to target length.
	* resolve.c (gfc_resolve_substring_charlen): Check substring
	length for constantness prior to general calculation of length.

	Backport from trunk
	PR fortran/89077
	* gfortran.dg/transfer_simplify_12.f90: New test.
	* gfortran.dg/substr_simplify.f90: New test.


Added:
    branches/gcc-8-branch/gcc/testsuite/gfortran.dg/substr_simplify.f90
    branches/gcc-8-branch/gcc/testsuite/gfortran.dg/transfer_simplify_12.f90
Modified:
    branches/gcc-8-branch/gcc/fortran/ChangeLog
    branches/gcc-8-branch/gcc/fortran/decl.c
    branches/gcc-8-branch/gcc/fortran/resolve.c
    branches/gcc-8-branch/gcc/testsuite/ChangeLog
Comment 22 anlauf 2019-03-03 22:27:36 UTC
Fixed on 9-trunk and 8-branch.

Backporting patches parts 2 and 3 to 7-branch may be too risky.

So closing.