Bug 42104 - [F03] runtime segfault with procedure pointer component
Summary: [F03] runtime segfault with procedure pointer component
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Paul Thomas
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2009-11-19 05:51 UTC by Martien Hulsen
Modified: 2009-11-20 07:57 UTC (History)
2 users (show)

See Also:
Host: Linux x86_64
Target: Linux x86_64
Build:
Known to work:
Known to fail:
Last reconfirmed: 2009-11-19 13:25:32


Attachments
source exposing the problem (430 bytes, text/plain)
2009-11-19 05:52 UTC, Martien Hulsen
Details
simplified (removed pp in main) (423 bytes, text/plain)
2009-11-19 06:08 UTC, Martien Hulsen
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Martien Hulsen 2009-11-19 05:51:50 UTC
The attached file gives:
   1.9045084    
   1.9045084    
Segmentation fault

Both ifort and g95 seems fine.
Comment 1 Martien Hulsen 2009-11-19 05:52:56 UTC
Created attachment 19042 [details]
source exposing the problem
Comment 2 Martien Hulsen 2009-11-19 06:08:31 UTC
Created attachment 19043 [details]
simplified (removed pp in main)

Removed the pp in the main program, because ifort does not seem to like it.
Comment 3 janus 2009-11-19 10:45:21 UTC
Confirmed.
Comment 4 janus 2009-11-19 11:57:07 UTC
Let's have a look at the dump for the test case in comment #2.

The call to 'func' is translated to:

      real(kind=4) D.1568;
      struct array1_real(kind=4) parm.7;
      static real(kind=4) A.6[2] = {1.00000001490116119384765625e-1, 1.00000001490116119384765625e-1};
      static integer(kind=4) C.1562 = 3;

      parm.7.dtype = 281;
      parm.7.dim[0].lbound = 1;
      parm.7.dim[0].ubound = 2;
      parm.7.dim[0].stride = 1;
      parm.7.data = (void *) &A.6[0];
      parm.7.offset = 0;
      D.1568 = func (&C.1562, &parm.7);


The PPC call to 'funcp%p' looks simlar, except for:

      D.1576 = _gfortran_internal_pack (&parm.10);
      D.1578 = funcp.p (&C.1570, D.1576);

(i.e. it has an additional _gfortran_internal_pack).
Comment 5 Paul Thomas 2009-11-19 13:25:31 UTC
Martien,

Thank you very much for this report.

I have assigned it to myself and have a non-regtested fix:

As remarked by Janus, the problem is with the array argument.  The code produced for the proc_pointer call is

      parm.13.dtype = 281;
      parm.13.dim[0].lbound = 1;
      parm.13.dim[0].ubound = 2;
      parm.13.dim[0].stride = 1;
      parm.13.data = (void *) &A.12[0];
      parm.13.offset = 0;
      D.1402 = _gfortran_internal_pack (&parm.13);
      D.1404 = funcp.p (&C.1396, D.1402);

The internal_pack should not be there, since the assumed shape formal argument requires that a descriptor be passed.  This, in its turn comes about because the symbol funcp is not marked as being always_explicit.

(In fact, he and I had a mid-air collision on this!)

The fix is to make use of the fact a proc_pointer component call is already detected and can be used to suppress the internal_pack.  Thusly:

Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c	(revision 153651)
+++ gcc/fortran/trans-expr.c	(working copy)
@@ -2918,7 +2918,7 @@
 	      f = (fsym != NULL)
 		  && !(fsym->attr.pointer || fsym->attr.allocatable)
 		  && fsym->as->type != AS_ASSUMED_SHAPE;
-	      f = f || !sym->attr.always_explicit;
+	      f = f || (!sym->attr.always_explicit && !comp);
 
 	      if (e->expr_type == EXPR_VARIABLE
 		    && is_subref_array (e))

This fixes the PR but has not been regtested.  I will do this tonight.  If all is well, I will commit as obvious, although your OK would be helpful, Janus!

Paul
Comment 6 janus 2009-11-19 21:09:28 UTC
(In reply to comment #5)
> The fix is to make use of the fact a proc_pointer component call is already
> detected and can be used to suppress the internal_pack.  Thusly:
> 
> Index: gcc/fortran/trans-expr.c
> ===================================================================
> --- gcc/fortran/trans-expr.c    (revision 153651)
> +++ gcc/fortran/trans-expr.c    (working copy)
> @@ -2918,7 +2918,7 @@
>               f = (fsym != NULL)
>                   && !(fsym->attr.pointer || fsym->attr.allocatable)
>                   && fsym->as->type != AS_ASSUMED_SHAPE;
> -             f = f || !sym->attr.always_explicit;
> +             f = f || (!sym->attr.always_explicit && !comp);
> 
>               if (e->expr_type == EXPR_VARIABLE
>                     && is_subref_array (e))
> 
> This fixes the PR but has not been regtested.  I will do this tonight.  If all
> is well, I will commit as obvious, although your OK would be helpful, Janus!

The question is if you want to do this for *all* PPCs. It seems the 'always_explicit' flag is correctly set for PPCs (by the same criteria as for normal procedures). Therefore I would propose the following:

Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c    (revision 154327)
+++ gcc/fortran/trans-expr.c    (working copy)
@@ -2979,7 +2979,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol *
              f = (fsym != NULL)
                  && !(fsym->attr.pointer || fsym->attr.allocatable)
                  && fsym->as->type != AS_ASSUMED_SHAPE;
-             f = f || !sym->attr.always_explicit;
+             if (comp)
+               f = f || !comp->attr.always_explicit;
+             else
+               f = f || !sym->attr.always_explicit;

              if (e->expr_type == EXPR_VARIABLE
                    && is_subref_array (e))
Comment 7 janus 2009-11-19 21:59:04 UTC
(In reply to comment #6)
> Index: gcc/fortran/trans-expr.c
> ===================================================================
> --- gcc/fortran/trans-expr.c    (revision 154327)
> +++ gcc/fortran/trans-expr.c    (working copy)
> @@ -2979,7 +2979,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol *
>               f = (fsym != NULL)
>                   && !(fsym->attr.pointer || fsym->attr.allocatable)
>                   && fsym->as->type != AS_ASSUMED_SHAPE;
> -             f = f || !sym->attr.always_explicit;
> +             if (comp)
> +               f = f || !comp->attr.always_explicit;
> +             else
> +               f = f || !sym->attr.always_explicit;
> 
>               if (e->expr_type == EXPR_VARIABLE
>                     && is_subref_array (e))

This patch makes the test case work and regtests without regressions. Paul, should I commit it or do you prefer your version?
Comment 8 Paul Thomas 2009-11-20 04:59:35 UTC
(In reply to comment #7)

Janus,

That version is a very good suggestion - thanks.  I am set up to apply the patch, so, although component procedure pointers is one of your specialisations, I can efficiently get on and do it.

I will take it that this is an OK from you.

Cheers

Paul
Comment 9 Paul Thomas 2009-11-20 06:43:31 UTC
Subject: Bug 42104

Author: pault
Date: Fri Nov 20 06:43:13 2009
New Revision: 154358

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=154358
Log:
2009-11-20  Paul Thomas  <pault@gcc.gnu.org>
	    Janus Weil  <janus@gcc.gnu.org>

	PR fortran/42104
	* trans-expr.c (gfc_conv_procedure_call): If procedure pointer
	component call, use the component's 'always_explicit' attr
	for array arguments.

2009-11-20  Paul Thomas  <pault@gcc.gnu.org>
	    Janus Weil  <janus@gcc.gnu.org>

	PR fortran/42104
	* gfortran.dg/proc_ptr_comp_23.f90 : New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/proc_ptr_comp_23.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/testsuite/ChangeLog

Comment 10 janus 2009-11-20 06:57:26 UTC
(In reply to comment #8)
> I will take it that this is an OK from you.

Sure thing. Thanks for committing.

Comment 11 Paul Thomas 2009-11-20 07:57:58 UTC
Many thanks for the report.

Fixed on trunk

Paul
Comment 12 Paul Thomas 2009-12-03 05:33:19 UTC
Subject: Bug 42104

Author: pault
Date: Thu Dec  3 05:32:58 2009
New Revision: 154935

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=154935
Log:
2009-12-03  Paul Thomas  <pault@gcc.gnu.org>
	    Janus Weil  <janus@gcc.gnu.org>

	PR fortran/42104
	* trans-expr.c (select_class_proc): Remove function.
	(conv_function_val): Delete reference to previous.
	(gfc_conv_derived_to_class): Add second argument to the call to
	gfc_find_derived_vtab.
	(gfc_conv_structure): Exclude proc_pointer components when
	accessing $data field of class objects.
	(gfc_trans_assign_vtab_procs): New function.
	(gfc_trans_class_assign): Add second argument to the call to
	gfc_find_derived_vtab.
	* symbol.c (gfc_build_class_symbol): Add delayed_vtab arg and
	implement holding off searching for the vptr derived type.
	(add_proc_component): New function.
	(add_proc_comps): New function.
	(add_procs_to_declared_vtab1): New function.
	(copy_vtab_proc_comps): New function.
	(add_procs_to_declared_vtab): New function.
	(void add_generic_specifics): New function.
	(add_generics_to_declared_vtab): New function.
	(gfc_find_derived_vtab): Add second argument to the call to
	gfc_find_derived_vtab. Add the calls to
	add_procs_to_declared_vtab and add_generics_to_declared_vtab.
	* decl.c (build_sym, build_struct): Use new arg in calls to
	gfc_build_class_symbol.
	* gfortran.h : Add vtype bitfield to symbol_attr. Remove the
	definition of struct gfc_class_esym_list. Modify prototypes
	of gfc_build_class_symbol and gfc_find_derived_vtab.
	* trans-stmt.c (gfc_trans_allocate): Add second argument to the
	call to gfc_find_derived_vtab.
	* module.c : Add the vtype attribute.
	* trans.h : Add prototype for gfc_trans_assign_vtab_procs.
	* resolve.c (resolve_typebound_generic_call): Add second arg
	to pass along the generic name for class methods.
	(resolve_typebound_call): The same.
	(resolve_compcall): Use the second arg to carry the generic
	name from the above. Remove the reference to class_esym.
	(check_members, check_class_members, resolve_class_esym,
	hash_value_expr): Remove functions.
	(resolve_class_compcall, resolve_class_typebound_call): Modify
	to use vtable rather than member by member calls.
	(gfc_resolve_expr): Modify second arg in call to
	resolve_compcall.
	(resolve_select_type): Add second arg in call to
	gfc_find_derived_vtab.
	(resolve_code): Add second arg in call resolve_typebound_call.
	(resolve_fl_derived): Exclude vtypes from check for late
	procedure definitions. Likewise for checking of explicit
	interface and checking of pass arg.
	* iresolve.c (gfc_resolve_extends_type_of): Add second arg in
	calls to gfc_find_derived_vtab.
	* match.c (select_type_set_tmp): Use new arg in call to
	gfc_build_class_symbol.
	* trans-decl.c (gfc_get_symbol_decl): Complete vtable if
	necessary.
	* parse.c (endType): Finish incomplete classes.
	

2009-12-03  Paul Thomas  <pault@gcc.gnu.org>
	    Janus Weil  <janus@gcc.gnu.org>

	PR fortran/41829
	* gfortran.dg/dynamic_dispatch_5.f03 : Change to "run".
	* gfortran.dg/dynamic_dispatch_6.f03 : New test.
	* gfortran.dg/dynamic_dispatch_7.f03 : New test.


Added:
    branches/fortran-dev/gcc/testsuite/gfortran.dg/dynamic_dispatch_6.f03
    branches/fortran-dev/gcc/testsuite/gfortran.dg/dynamic_dispatch_7.f03
Modified:
    branches/fortran-dev/gcc/fortran/ChangeLog.fortran-dev
    branches/fortran-dev/gcc/fortran/decl.c
    branches/fortran-dev/gcc/fortran/gfortran.h
    branches/fortran-dev/gcc/fortran/iresolve.c
    branches/fortran-dev/gcc/fortran/match.c
    branches/fortran-dev/gcc/fortran/module.c
    branches/fortran-dev/gcc/fortran/parse.c
    branches/fortran-dev/gcc/fortran/resolve.c
    branches/fortran-dev/gcc/fortran/symbol.c
    branches/fortran-dev/gcc/fortran/trans-decl.c
    branches/fortran-dev/gcc/fortran/trans-expr.c
    branches/fortran-dev/gcc/fortran/trans-stmt.c
    branches/fortran-dev/gcc/fortran/trans.h
    branches/fortran-dev/gcc/testsuite/ChangeLog.fortran-dev
    branches/fortran-dev/gcc/testsuite/gfortran.dg/dynamic_dispatch_5.f03