Bug 50410

Summary: [6/7/8 Regression] ICE in record_reference
Product: gcc Reporter: Vittorio Zecca <zeccav>
Component: fortranAssignee: Not yet assigned to anyone <unassigned>
Status: NEW ---    
Severity: normal CC: janus, jvdelisle, tkoenig
Priority: P4 Keywords: ice-on-invalid-code
Version: 7.0   
Target Milestone: 6.5   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2011-09-15 00:00:00
Bug Depends on:    
Bug Blocks: 33056    
Attachments: just compile it
Draft patch
Patch to fix the regressions caused by the patch in comment 8

Description Vittorio Zecca 2011-09-15 08:40:49 UTC
Created attachment 25286 [details]
just compile it

ICE in record_reference
Comment 1 Dominique d'Humieres 2011-09-15 11:08:55 UTC
Confirmed on 4.6.1 and trunk:

pr50410.f90:7:0: internal compiler error: in record_reference, at cgraphbuild.c:67

no ICE on 4.4.6 and 4.5.3 (no error). g95 gives the following error:

In file pr50410.f90:6

      data  u%g /1/
            1
Error: Can't dereference POINTER in DATA statement at (1)
Comment 2 Vittorio Zecca 2011-09-18 17:38:10 UTC
The following produces a Segmentation fault in gfc_conv_structure (r178925)

      type t
       integer g
      end type
      type(t) :: u=t(1)
      data u%g /2/
      end
Comment 3 Dominique d'Humieres 2011-09-18 18:20:57 UTC
The problem for the code in comment #2 seems different:
it gives a segmentation fault with 4.6.1 and trunk and an ICE with 4.4.6 and 4.5.3:

f951: internal compiler error: in formalize_structure_cons, at fortran/data.c:(756|755)

g95 gives the following error

In file pr50410_1.f90:5

      data u%g /2/
           1
Error: Variable 'u' at (1) already has an initialization
Comment 4 kargl 2011-09-18 23:31:53 UTC
(In reply to comment #2)
> The following produces a Segmentation fault in gfc_conv_structure (r178925)
> 
>       type t
>        integer g
>       end type
>       type(t) :: u=t(1)
>       data u%g /2/
>       end

The code is invalid and so gfortran can do anything that it
wishes, including segfault.

5.2.5 Data Statement

  ...
  A variable, or part of a variable, shall not be explicitly
  initialized more than once in a program.
  ...
Comment 5 janus 2011-09-21 16:58:29 UTC
(In reply to comment #4)
> The code is invalid and so gfortran can do anything that it
> wishes, including segfault.

Well, no. An ICE on invalid code may not be as bad as an ICE on valid code, but it's still a bug. gfortran should give a meaningful error message.
Comment 6 Tobias Burnus 2011-10-17 16:38:28 UTC
To check:
- Pointer attribute in the part ref - or an allocate attribute.
- Whether there is already some initialization.
  If one uses a constructor, it affects the whole variable,
  but mixing different data statements is OK as long as different
  parts are initialized.
- If one directly access the variable: Pointer init is only OK for null()

Example for the last item:
      integer, pointer :: u
      data u /1/  ! Accepted, but probably shouldn't
      ! data u/null()/ ! Probably OK (and currently accepted).
      end

I think it could be sufficient to check decl.c's var_element though it might fail if one initializes a DT piecewise; if so, one needs to add a check to data.c or modify something else in decl.c
Comment 7 kargl 2011-10-17 17:36:33 UTC
(In reply to comment #2)
> The following produces a Segmentation fault in gfc_conv_structure (r178925)
> 
>       type t
>        integer g
>       end type
>       type(t) :: u=t(1)
>       data u%g /2/
>       end

The following patch removes the seqfault.  If one adds
'print *, u%g' before end and compiles the resulting
program, then one gets 1.  This is acceptable, IMHO,
because the code is invalid.


Index: trans-expr.c
===================================================================
--- trans-expr.c        (revision 180099)
+++ trans-expr.c        (working copy)
@@ -4747,7 +4747,7 @@ gfc_conv_structure (gfc_se * se, gfc_exp
   cm = expr->ts.u.derived->components;
 
   for (c = gfc_constructor_first (expr->value.constructor);
-       c; c = gfc_constructor_next (c), cm = cm->next)
+       c && cm; c = gfc_constructor_next (c), cm = cm->next)
     {
       /* Skip absent members in default initializers and allocatable
         components.  Although the latter have a default initializer
Comment 8 Tobias Burnus 2011-10-17 21:20:25 UTC
Created attachment 25534 [details]
Draft patch

The attached patch should fix all issues; however, I think the error message text can be improved. Additionally, one should re-check the standard and add some more test cases.
Comment 9 Tobias Burnus 2011-10-18 07:23:10 UTC
From the standard:
"C568 (R536) A data-i-do-object or a variable that appears as a
 data-stmt-object shall not be an object designator in which a
 pointer appears other than as the entire rightmost part-ref."

"C567 (R536) A variable whose designator appears as a
 data-stmt-object or a data-i-do-object shall not be a dummy
 argument, accessed by use or host association, in a named
 common block unless the DATA statement is in a block data
 program unit, in blank common, a function name, a function
 result name, an automatic object, or an allocatable variable."

To be fixed beyond the patch of attachment 25534 [details]
* ICE below (1) for init of DT with default init
* ICE below (2) with structure constructor, which initializes a pointer
(plus: test cases, revised error message wording)
* (3) Pointer init in DATA: Also "initial-data-target" is allowed

For the pointer init, see also PR 45290.

! =============== (1) =======================
module m
type t
  integer :: a  = 7
end type t
type t2
  integer :: b
end type t2
end module m

use m
implicit type(t)(x), type(t2)(y)
! ICE in trans:
! Invalid as "nonpointer object has default initialization"
DATA x%a/8/

! OK:
!DATA y%b/5/
!type(t2) :: y = t2(7) ! { dg-error "initializer already appears in a DATA statement" }
end
! ============= (2) =========================
module m
  type t
    integer :: a
    integer, pointer :: bar
  end type t
end module m

subroutine test()
  use m
  type(t) :: x ! = t(4, null()) ! OK
 DATA x/t(4, null())/ ! ICE in the middle end
end subroutine test
! ============= (3) =========================
type t
  integer, pointer :: ptr
end type t
integer, target, save :: tgt

! Version A:
!type(t) :: x = t(tgt)
! Rejected with "has not been declared or is a variable,
!         which does not reduce to a constant expression"

! Version 2
type(t) :: x
DATA x%ptr /tgt/ ! error "must be a PARAMETER in DATA statement"

tgt = 7
print *, ptr
end
Comment 10 Jakub Jelinek 2011-10-26 17:13:37 UTC
GCC 4.6.2 is being released.
Comment 12 Jakub Jelinek 2012-03-01 14:38:32 UTC
GCC 4.6.3 is being released.
Comment 13 Jakub Jelinek 2013-04-12 15:16:50 UTC
GCC 4.6.4 has been released and the branch has been closed.
Comment 14 Vittorio Zecca 2013-04-16 08:47:09 UTC
I still have the same bug on gfortran 4.8.0.
Comment 15 Richard Biener 2014-06-12 13:45:47 UTC
The 4.7 branch is being closed, moving target milestone to 4.8.4.
Comment 16 Jakub Jelinek 2014-12-19 13:28:53 UTC
GCC 4.8.4 has been released.
Comment 17 Richard Biener 2015-06-23 08:18:12 UTC
The gcc-4_8-branch is being closed, re-targeting regressions to 4.9.3.
Comment 18 Jakub Jelinek 2015-06-26 19:54:20 UTC
GCC 4.9.3 has been released.
Comment 19 Vittorio Zecca 2015-09-02 13:14:18 UTC
ICE still there in 5.2.0
Comment 20 Dominique d'Humieres 2016-02-01 12:03:48 UTC
The test in comment 2 is a duplicate of pr49278.
Comment 21 Vittorio Zecca 2016-04-28 06:46:35 UTC
ICE still in 5.3.0
Comment 22 Vittorio Zecca 2016-04-29 21:26:02 UTC
Same ICE in 6.1.0
Comment 23 Gerhard Steinmetz 2016-05-04 15:01:12 UTC
These variants give :


$ cat z1.f90
program p
   type ta
      integer :: a
   end type
   type t
      type(ta), pointer :: b
   end type
   type(t) :: z
   data z / t(ta(1)) /
end

$ gfortran-6 z1.f90
f951: internal compiler error: in record_reference, at cgraphbuild.c:64



$ cat z2.f90
program p
   type ta
      integer :: a
   end type
   type t
      type(ta) :: b
   end type
   type(t), pointer :: z
   data z / t(ta(1)) /
end

$ gfortran-6 z2.f90
f951: internal compiler error: in record_reference, at cgraphbuild.c:64



$ cat z3.f90
program p
   type ta
      integer :: a
   end type
   type t
      type(ta), pointer :: b
   end type
   type(t), pointer :: z
   data z / t(ta(1)) /
end

$ gfortran-6 z3.f90
internal compiler error: in fold_convert_loc, at fold-const.c:2256
Comment 24 Gerhard Steinmetz 2016-05-04 15:02:51 UTC
And an exotic case :

$ cat z5.f90
module m
   real, target :: a[*]
   real, pointer :: z => a
end

$ gfortran-6 -fcoarray=lib -c z5.f90
f951: internal compiler error: in record_reference, at cgraphbuild.c:64



$ cat z6.f90
program p
   real, target :: a[*]
   real, pointer :: z => a
end

$ gfortran-6 -fcoarray=lib -finit-local-zero -c z6.f90
internal compiler error: in fold_convert_loc, at fold-const.c:2256
Comment 25 Richard Biener 2016-08-03 10:53:49 UTC
GCC 4.9 branch is being closed
Comment 26 Vittorio Zecca 2016-08-11 13:32:30 UTC
Still there in gcc 7.0 trunk 239276
Comment 27 Vittorio Zecca 2017-05-15 04:52:46 UTC
Still in 7.1.0 and trunk 8.0.0
Comment 28 Dominique d'Humieres 2017-10-03 11:47:30 UTC
I have revisited the draft patch in comment 8 and it fixes all the ICEs, but those in comment 23. The last two of them emit now

in gfc_format_decoder, at fortran/error.c:934
libbacktrace could not find executable to open

I have found a typo in the patch "initalized" should be replaced with "initialized".

With the patch the following tests

gfortran.dg/data_constraints_1.f90
gfortran.dg/data_initialized.f90
gfortran.dg/data_initialized_2.f90
gfortran.dg/data_invalid.f90
gfortran.dg/data_pointer_1.f90

regress. I'll attach the patch fixing these regressions, noting that there is probably something wrong for gfortran.dg/data_pointer_1.f90. The patch seems to break some gnu extensions (but AFAICT not all them).

BTW what is the best expression in English "already is" or "is already", the later being easier to parse for French readers.
Comment 29 Dominique d'Humieres 2017-10-03 11:49:14 UTC
Created attachment 42294 [details]
Patch to fix the regressions caused by the patch in comment 8
Comment 30 Jerry DeLisle 2017-10-07 02:29:03 UTC
(In reply to Dominique d'Humieres from comment #28)
--- snip ---
> BTW what is the best expression in English "already is" or "is already", the
> later being easier to parse for French readers.

"is already" is fine.