Bug 46838

Summary: [OOP] Initialization of polymorphic allocatable components
Product: gcc Reporter: Salvatore Filippone <sfilippone>
Component: fortranAssignee: janus
Status: RESOLVED FIXED    
Severity: normal CC: burnus, janus, tkoenig
Priority: P3 Keywords: wrong-code
Version: 4.6.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2010-12-28 10:52:23
Attachments: test-case

Description Salvatore Filippone 2010-12-07 16:36:02 UTC
Created attachment 22672 [details]
test-case

Hello,
At r167487 the polymorphic component of an INTENT(OUT) dummy starts as ALLOCATED, which is obviously wrong. 
[sfilippo@localhost bug28]$ gfortran -v 
Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/usr/local/gnu46/libexec/gcc/x86_64-unknown-linux-gnu/4.6.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../gcc/configure --prefix=/usr/local/gnu46 --enable-languages=c,c++,fortran --with-gmp=/home/travel/GCC/BUILDS/gmp --with-mpfr=/home/travel/GCC/BUILDS/mpfr --with-mpc=/home/travel/GCC/BUILDS/mpc : (reconfigured) ../gcc/configure --prefix=/usr/local/gnu46 --enable-languages=c,c++,fortran --with-gmp=/home/travel/GCC/BUILDS/gmp --with-mpfr=/home/travel/GCC/BUILDS/mpfr --with-mpc=/home/travel/GCC/BUILDS/mpc : (reconfigured) ../gcc/configure --prefix=/usr/local/gnu46 --with-gmp=/home/travel/GCC/BUILDS/gmp --with-mpfr=/home/travel/GCC/BUILDS/mpfr --with-mpc=/home/travel/GCC/BUILDS/mpc --enable-languages=c,c++,fortran,lto --no-create --no-recursion
Thread model: posix
gcc version 4.6.0 20101206 (experimental) (GCC) 
[sfilippo@localhost bug28]$ gfortran -o bug28 bug28.f90
[sfilippo@localhost bug28]$ ./bug28 
Generating Matrix (size=512)...
 Allocated on an intent(OUT) var?
Comment 1 Tobias Burnus 2010-12-07 17:00:19 UTC
Work here as expected - but I get:

==32139== Conditional jump or move depends on uninitialised value(s)
==32139==    at 0x400A36: cdall.1593 (oop.f90:139)
==32139==    by 0x400CCE: create_matrix.1606 (oop.f90:117)

Line 139 is:
    if (allocated(desc%indxmap)) then

From the dump:

cdall (struct desc_type & restrict desc)
    struct desc_type D.1561;
    struct desc_type desc_type.0;
    desc_type.0.matrix_data = 0B;
    D.1561 = *desc;
    *desc = desc_type.0;
    D.1561.matrix_data = 0B;
    D.1561.indxmap._data = 0B;

  if (desc->indxmap._data != 0B)

The way one has to read it is as follows:

  D.1561 = *desc;       // Save pointers
  *dest = desc_type.0;  // Default initialize
  // free allocatables via D.1561

The freeing works OK (except for a missing deep freeing, which is a different PR). However, the initializing does not work. There is a line missing which reads:
    desc_type.0.indxmap._data = 0B;

The initialization happens via gfc_init_default_dt, which uses sym->value. Hence, the problem might be in resolve.c.

* * *

Modified version: If one changes indxmap into an array, one gets:

oop.f90:21:0: internal compiler error: in gfc_conv_descriptor_data_get, at fortran/trans-array.c:144

* * *


Reduced test case:
module descriptor_type
  implicit none
  type      :: indx_map
  end type indx_map
  type desc_type
    integer, allocatable  :: matrix_data
    class(indx_map), allocatable :: indxmap
  end type desc_type
end module descriptor_type

program bug28
  use descriptor_type
  implicit none
  type(desc_type)   :: desc_a
  call cdall(desc_a)
contains
  subroutine cdall(desc)
    type(desc_type), intent(out)  :: desc
    if (allocated(desc%indxmap)) stop 'ERROR'
    STOP 'OK'
  end subroutine cdall
end program bug28
Comment 2 Tobias Burnus 2010-12-07 17:04:04 UTC
The default initializer is obtained via expr.c's gfc_default_initializer.
Comment 3 Salvatore Filippone 2010-12-15 13:08:12 UTC
(In reply to comment #2)
> The default initializer is obtained via expr.c's gfc_default_initializer.

The original code gives 
Overall matrix creation time :  1.69176E-01
 
[localhost:06639] Signal: Segmentation fault (11)
[localhost:06639] Signal code:  (128)
[localhost:06639] Failing at address: (nil)
*** glibc detected *** ./ppde: munmap_chunk(): invalid pointer: 0x000000000064a8e6 ***
======= Backtrace: =========
/lib64/libc.so.6[0x39dc875676]
./ppde(__copy_psb_gen_block_map_mod_psb_gen_block_map_+0x143)[0x4c5f43]
./ppde(psb_cdcpy_+0x5c0)[0x4c11e0]
./ppde(psb_dcdbldext_+0x802)[0x4b3f92]
./ppde[0x419d26]
./ppde[0x41cbdd]
/lib64/libc.so.6(__libc_start_main+0xfd)[0x39dc81ec5d]
./ppde[0x419339]

i.e. the problem surfaces in a SOURCE= allocation.
Comment 4 janus 2010-12-28 10:52:23 UTC
(In reply to comment #2)
> The default initializer is obtained via expr.c's gfc_default_initializer.

Indeed this is the place where things go wrong. Here's a patch:


Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c	(revision 168277)
+++ gcc/fortran/expr.c	(working copy)
@@ -3648,7 +3648,8 @@ gfc_default_initializer (gfc_typespec *ts)
   /* See if we have a default initializer in this, but not in nested
      types (otherwise we could use gfc_has_default_initializer()).  */
   for (comp = ts->u.derived->components; comp; comp = comp->next)
-    if (comp->initializer || comp->attr.allocatable)
+    if (comp->initializer || comp->attr.allocatable
+	|| (comp->ts.type == BT_CLASS && CLASS_DATA (comp)->attr.allocatable))
       break;
 
   if (!comp)
@@ -3664,8 +3665,9 @@ gfc_default_initializer (gfc_typespec *ts)
 
       if (comp->initializer)
 	ctor->expr = gfc_copy_expr (comp->initializer);
-
-      if (comp->attr.allocatable)
+      else if (comp->attr.allocatable
+	       || (comp->ts.type == BT_CLASS
+		   && CLASS_DATA (comp)->attr.allocatable))
 	{
 	  ctor->expr = gfc_get_expr ();
 	  ctor->expr->expr_type = EXPR_NULL;


This fixes the test case in comment #1. However, I was not able to see a failure with the test case in comment #0. Salvatore, can you check whether the patch cures your troubles?
Comment 5 janus 2010-12-28 12:51:22 UTC
(In reply to comment #4)
> Here's a patch:

The patch in comment #4 had a few regressions (e.g. on alloc_comp_basics_1.f90 etc), but the following version regtests cleanly:


Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c	(revision 168293)
+++ gcc/fortran/expr.c	(working copy)
@@ -3648,7 +3648,8 @@ gfc_default_initializer (gfc_typespec *ts)
   /* See if we have a default initializer in this, but not in nested
      types (otherwise we could use gfc_has_default_initializer()).  */
   for (comp = ts->u.derived->components; comp; comp = comp->next)
-    if (comp->initializer || comp->attr.allocatable)
+    if (comp->initializer || comp->attr.allocatable
+	|| (comp->ts.type == BT_CLASS && CLASS_DATA (comp)->attr.allocatable))
       break;
 
   if (!comp)
@@ -3665,7 +3666,8 @@ gfc_default_initializer (gfc_typespec *ts)
       if (comp->initializer)
 	ctor->expr = gfc_copy_expr (comp->initializer);
 
-      if (comp->attr.allocatable)
+      if (comp->attr.allocatable
+	  || (comp->ts.type == BT_CLASS && CLASS_DATA (comp)->attr.allocatable))
 	{
 	  ctor->expr = gfc_get_expr ();
 	  ctor->expr->expr_type = EXPR_NULL;
Comment 6 Salvatore Filippone 2010-12-28 13:40:52 UTC
(In reply to comment #5)
> (In reply to comment #4)
> > Here's a patch:
> 
> The patch in comment #4 had a few regressions (e.g. on alloc_comp_basics_1.f90
> etc), but the following version regtests cleanly:
> 
> 

For me, it cures the reduced test case (bug28.f90) in comment #0, so it's definitely a step in the right direction. 
Unfortunately in the full application I still get this: 

 
[localhost:15473] Signal: Segmentation fault (11)
[localhost:15473] Signal code: Address not mapped (1)
[localhost:15473] Failing at address: 0x13440000133b
[localhost:15472] [ 0] /lib64/libpthread.so.0(+0xf4a0) [0x7fae89b8b4a0]
[localhost:15472] [ 1] /lib64/libc.so.6(cfree+0x1c) [0x7fae898782dc]
[localhost:15472] [ 2] ./ppde(__copy_psb_gen_block_map_mod_psb_gen_block_map_+0x143) [0x4c45b3]
[localhost:15472] [ 3] ./ppde(psb_cdcpy_+0x700) [0x4bf850]
[localhost:15472] [ 4] ./ppde(psb_dcdbldext_+0x7e2) [0x4b2762]
[localhost:15472] [ 5] ./ppde() [0x41985f]
[localhost:15472] [ 6] ./ppde() [0x41c6dd]
[localhost:15472] [ 7] /lib64/libc.so.6(__libc_start_main+0xfd) [0x7fae8981cc5d]
[localhost:15472] [ 8] ./ppde() [0x418ef9]
[localhost:15472] *** End of error message ***

I suppose this means that the original test case did not catch all there was;  I guess it would be best to declare this fixed and open a new one, as soon as I have time to get a new reduced test case.
Comment 7 janus 2010-12-29 16:14:20 UTC
Author: janus
Date: Wed Dec 29 16:14:11 2010
New Revision: 168322

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=168322
Log:
2010-12-29  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/46838
	* expr.c (gfc_default_initializer): Handle allocatable CLASS components.


2010-12-29  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/46838
	* gfortran.dg/alloc_comp_class_2.f90: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/alloc_comp_class_2.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/expr.c
    trunk/gcc/testsuite/ChangeLog
Comment 8 janus 2010-12-29 16:30:47 UTC
r168322 fixes the original test case as well as the reduction in comment #1.

ToDo: The array version (cf. comment #1) still ICEs:


  implicit none

  type indx_map
  end type

  type desc_type
    class(indx_map), allocatable :: indxmap(:)
  end type

  type(desc_type)  :: desc
  if (allocated(desc%indxmap)) call abort()

end



internal compiler error: in gfc_conv_descriptor_data_get, at fortran/trans-array.c:144
Comment 9 janus 2010-12-29 17:04:02 UTC
(In reply to comment #8)
> ToDo: The array version (cf. comment #1) still ICEs:

This is now being tracked by PR 43969, therefore I'm closing this one.