Bug 78492 - [OOP] Compiler segfault with non_overridable function in generic interface
Summary: [OOP] Compiler segfault with non_overridable function in generic interface
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 6.1.0
: P4 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks: 29670
  Show dependency treegraph
 
Reported: 2016-11-23 10:29 UTC by federico
Modified: 2022-06-15 12:32 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-11-23 00:00:00


Attachments
Minimal program to test non_overridable functions in generic type-bound set (742 bytes, text/plain)
2016-11-23 10:29 UTC, federico
Details
test program: call non_overridable function from generic interface within polymorphic procedure (383 bytes, text/plain)
2022-06-15 12:31 UTC, federico
Details

Note You need to log in before you can comment on or make changes to this bug.
Description federico 2016-11-23 10:29:44 UTC
Created attachment 40128 [details]
Minimal program to test non_overridable functions in generic type-bound set

Hi, 

As from object, I get internal compiler error (segfault) with both gcc 5.3.0 and gcc 6.1.0 in this case: 

In a derived type (either polymorphic or not), there is a generic type-bound procedure interface where any of the procedures are listed as "non_overridable". 
If the code calls any of the individual specific procedures, no error occurs. If the code calls the generic interface, I get compiler segmentation fault. 

I am attaching a minimal example that reproduces this behavior for both gcc 5.3.0 and 6.1.0. 

Thanks, 
Federico
Comment 1 janus 2016-11-23 10:41:44 UTC
I can confirm this ICE with every gfortran version from 4.7 to current trunk. The test case as provided compiles fine, but when uncommenting one of the marked lines the ICE appears.


The backtrace on current trunk is:

       print *, ' dot_1d, generic call = ',this%dot_no_override(x1d,y1d) ! causes compiler segfault
 
internal compiler error: in conv_function_val, at fortran/trans-expr.c:3704
0x91c09c conv_function_val
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans-expr.c:3703
0x9240a2 gfc_conv_procedure_call(gfc_se*, gfc_symbol*, gfc_actual_arglist*, gfc_expr*, vec<tree_node*, va_gc, vl_embed>*)
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans-expr.c:6061
0x926520 gfc_conv_function_expr
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans-expr.c:6657
0x92a092 gfc_conv_expr(gfc_se*, gfc_expr*)
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans-expr.c:7696
0x92a589 gfc_conv_expr_reference(gfc_se*, gfc_expr*)
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans-expr.c:7831
0x95db8c gfc_trans_transfer(gfc_code*)
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans-io.c:2482
0x8ce99d trans_code
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans.c:1902
0x8ceb1a gfc_trans_code_cond(gfc_code*, tree_node*)
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans.c:2005
0x95c7cd build_dt
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans-io.c:1980
0x95c8b9 gfc_trans_write(gfc_code*)
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans-io.c:2019
0x8ce913 trans_code
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans.c:1874
0x8ceb39 gfc_trans_code(gfc_code*)
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans.c:2013
0x90bdc8 gfc_generate_function_code(gfc_namespace*)
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans-decl.c:6261
0x8ceddc gfc_generate_module_code(gfc_namespace*)
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/trans.c:2080
0x85dc5f translate_all_program_units
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/parse.c:6025
0x85e3a2 gfc_parse_file()
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/parse.c:6238
0x8b7525 gfc_be_parse_file
	/home/jweil/gcc/gcc7/trunk/gcc/fortran/f95-lang.c:202
Comment 2 janus 2016-11-23 10:59:20 UTC
Here is a reduced (and slightly modified) version which gives the same ICE:

module types
    implicit none
    type :: generic_class
    contains
        procedure, non_overridable :: dot_1d_no_override
        generic :: dot => dot_1d_no_override
    end type
contains
    real function dot_1d_no_override(this,x,y) result(xdoty)
       class(generic_class), intent(in) :: this
       real, intent(in), dimension(3) :: x,y
       xdoty = dot_product(x,y)
    end function
end module

program main
    use types
    implicit none
    type(generic_class) :: a
    call test(a)
contains
    subroutine test(this)
       class(generic_class), intent(in) :: this
       real, dimension(3) :: x1d = 1., y1d = -1.
       print *, ' dot_1d, generic call = ',this%dot(x1d,y1d) ! ICE
    end subroutine
end
Comment 3 janus 2016-11-23 13:13:50 UTC
I think what happens is this: After resolving the generic TBP call to the specific one, we try to generate a polymorphic call, but that fails since the vtab does not contain an entry for the non-overridable TBP.

A simple workaround is to do what had already been proposed for PR78443, namely generate a vtab entry for each TBP, no matter if it's overridable or not:


Index: gcc/fortran/class.c
===================================================================
--- gcc/fortran/class.c	(revision 242725)
+++ gcc/fortran/class.c	(working copy)
@@ -751,9 +751,6 @@
 {
   gfc_component *c;
 
-  if (tb->non_overridable && !tb->overridden)
-    return;
-
   c = gfc_find_component (vtype, name, true, true, NULL);
 
   if (c == NULL)


That seems to work well and makes both comment #2 and comment #0 compile and run without error.

However, a better fix would be to generate a non-polymorphic call after resolving the generic, just as in the case where no generics TBPs are involved.
Comment 4 G. Steinmetz 2018-11-12 17:55:51 UTC
Update with a simplification :


$ cat z1.f90
module m
   type t
   contains
      procedure, non_overridable :: g
      generic :: f => g
   end type
contains
   recursive function g(x)
      class(t), intent(in) :: x
      print *, x%f()
   end
end


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

   10 |       print *, x%f()
      |
internal compiler error: in conv_function_val, at fortran/trans-expr.c:3810
0x6f95e0 conv_function_val
        ../../gcc/fortran/trans-expr.c:3809
0x6f95e0 gfc_conv_procedure_call(gfc_se*, gfc_symbol*, gfc_actual_arglist*, gfc_expr*, vec<tree_node*, va_gc, vl_embed>*)
        ../../gcc/fortran/trans-expr.c:6300
0x6fa29c gfc_conv_function_expr
        ../../gcc/fortran/trans-expr.c:6928
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
0x6c3b39 gfc_generate_module_code(gfc_namespace*)
        ../../gcc/fortran/trans.c:2216
0x67440b translate_all_program_units
        ../../gcc/fortran/parse.c:6112
0x67440b gfc_parse_file()
        ../../gcc/fortran/parse.c:6328
0x6bc89f gfc_be_parse_file
        ../../gcc/fortran/f95-lang.c:204
Comment 5 federico 2022-06-15 12:31:30 UTC
Created attachment 53145 [details]
test program: call non_overridable function from generic interface within polymorphic procedure
Comment 6 federico 2022-06-15 12:32:46 UTC
I've attached a simple test program that confirms ICE on gfortran 11.3.0. 
ICE is returned only if
- the non_overridable procedure is part of a generic type-bound interface
- that same generic is being called from another type-bound procedure