GCC Bugzilla has been upgraded from version 4.4.9 to 5.0rc3. If you see any problem, please report it to bug 64968.
Bug 45004 - [OOP] Segfault with allocatable scalars and move_alloc
Summary: [OOP] Segfault with allocatable scalars and move_alloc
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: ---
Assignee: janus
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2010-07-20 12:52 UTC by Salvatore Filippone
Modified: 2010-07-29 18:18 UTC (History)
2 users (show)

See Also:
Host: x86_64-unknown-linux-gnu
Target: x86_64-unknown-linux-gnu
Build: x86_64-unknown-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2010-07-23 16:19:41


Attachments
test case (590 bytes, text/plain)
2010-07-20 12:52 UTC, Salvatore Filippone
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Salvatore Filippone 2010-07-20 12:52:16 UTC
I keep getting segfaults at (more or less) random places. Moreover, the segfaults on the same code are different on X86_64 from i686 (in the latter case, they are less frequent). 
This is probably due to move_alloc not being fully/correctly implemented. 
I see nothing wrong with the attached code (indeed, the library from which this is extracted compiles and runs fine with NAG and XLF). 

[sfilippo@donald bug18]$ 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
Thread model: posix
gcc version 4.6.0 20100715 (experimental) (GCC) 
[sfilippo@donald bug18]$ gfortran -o bug18 bug18.f03  
[sfilippo@donald bug18]$ ./bug18
 Ok on move target
 Ok on move source
 Test completed 
Segmentation fault
Comment 1 Salvatore Filippone 2010-07-20 12:52:50 UTC
Created attachment 21263 [details]
test case
Comment 2 janus 2010-07-22 21:21:57 UTC
Reduced test case with the same output:

program bug18

  type foo
    integer :: i
  end type foo

  type bar
    class(foo), allocatable :: bf
  end type bar

  class(foo), allocatable :: afab
  type(bar) :: bb

  allocate(foo :: afab)
  call move_alloc(afab, bb%bf)
  if (allocated(bb%bf)) then
    write(0,*) 'Ok on move target'
  else
    write(0,*) 'Bad move target'
  endif
  if (.not.allocated(afab)) then
    write(0,*) 'Ok on move source'
  else
    write(0,*) 'Bad move source'
  endif
  write(0,*) 'Test completed '

end program bug18

Comment 3 janus 2010-07-22 21:44:53 UTC
Here is an even more elementary example which shows that there is a problem for allocatable scalars, already without any polymorphic variables:

  implicit none
  integer, allocatable :: afab1,afab2
  allocate(afab1)
  afab1 = irand()
  print *,afab1
  call move_alloc(afab1, afab2)
  print *,afab2
  print *,allocated(afab2)
  print *,allocated(afab1)
end


This directly segfaults on move_alloc:

       16807
Segmentation fault


The problem is that _gfortran_move_alloc expects two array descriptors as arguments, but allocatable scalars have none. Therefore we probably need something like '_gfortran_move_alloc_scalar'.

For classes we will probably have to add a reference to the $data component before passing them to move_alloc.
Comment 4 janus 2010-07-23 16:19:41 UTC
Here is a draft patch which deals with allocatable scalars:

Index: gcc/fortran/trans.c
===================================================================
--- gcc/fortran/trans.c	(revision 162448)
+++ gcc/fortran/trans.c	(working copy)
@@ -1157,8 +1157,27 @@ trans_code (gfc_code * code, tree cond)
 	    if (code->resolved_isym
 		&& code->resolved_isym->id == GFC_ISYM_MVBITS)
 	      is_mvbits = true;
-	    res = gfc_trans_call (code, is_mvbits, NULL_TREE,
-				  NULL_TREE, false);
+	    if (code->resolved_isym
+		&& code->resolved_isym->id == GFC_ISYM_MOVE_ALLOC
+		&& code->ext.actual->expr->rank == 0)
+	      {
+		gfc_expr *from, *to;
+		stmtblock_t block;
+		tree tmp;
+		
+		from = code->ext.actual->expr;
+		to = code->ext.actual->next->expr;
+		
+		gfc_start_block (&block);
+		tmp = gfc_trans_pointer_assignment (to, from);
+		gfc_add_expr_to_block (&block, tmp);
+		tmp = gfc_trans_pointer_assignment (from, gfc_get_null_expr (NULL));
+		gfc_add_expr_to_block (&block, tmp);
+		res = gfc_finish_block (&block);
+	      }
+	    else
+	      res = gfc_trans_call (code, is_mvbits, NULL_TREE,
+				    NULL_TREE, false);
 	  }
 	  break;
 
Comment 5 janus 2010-07-29 18:14:48 UTC
Subject: Bug 45004

Author: janus
Date: Thu Jul 29 18:14:16 2010
New Revision: 162688

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

	PR fortran/45004
	* trans-stmt.h (gfc_trans_class_init_assign): New prototype.
	(gfc_trans_class_assign): Modified prototype.
	* trans.h (gfc_conv_intrinsic_move_alloc): New prototype.
	* trans-expr.c (gfc_trans_class_init_assign): Split off from ...
	(gfc_trans_class_assign): ... here. Modified actual arguments.
	* trans-intrinsic.c (gfc_conv_intrinsic_move_alloc): New function to
	handle the MOVE_ALLOC intrinsic with scalar and class arguments.
	* trans.c (trans_code): Call 'gfc_conv_intrinsic_move_alloc'.


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

	PR fortran/45004
	* gfortran.dg/move_alloc_2.f90: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/move_alloc_2.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans-intrinsic.c
    trunk/gcc/fortran/trans-stmt.h
    trunk/gcc/fortran/trans.c
    trunk/gcc/fortran/trans.h
    trunk/gcc/testsuite/ChangeLog

Comment 6 janus 2010-07-29 18:18:34 UTC
Fixed with r162688. Closing.