Bug 34545 - ICE when compiling Fortran 95 code
Summary: ICE when compiling Fortran 95 code
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: ---
Assignee: Paul Thomas
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks: 32834
  Show dependency treegraph
 
Reported: 2007-12-21 04:46 UTC by Jon D. Richards
Modified: 2008-01-07 08:15 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.1.3 4.2.2 4.3.0
Last reconfirmed: 2008-01-01 17:23:35


Attachments
Source code that causes ICE (13.42 KB, text/plain)
2007-12-21 04:50 UTC, Jon D. Richards
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Jon D. Richards 2007-12-21 04:46:56 UTC
Overview Description: ICE when compiling source code.
Steps to Reproduce: Download code from 
   http://www.k9shrink.com/kmeans.f90 
and compile with 
   gfortran -Wall -v -save-temps kmeans.f90    
What happens is ICE with segmentation fault.
Actual Results: ICE
Expected Results: compilation or list of warnings and errors encountered.
Build Date & Platform: 20070813, Windows Vista

Additional Information:
Platform is Windows Vista. gcc version 4.3.0 20070813 (experimental)

using gfortran

Source is available from http://www.k9shrink.com/kmeans.f90

I enter following compile command and get following response:
G:\fortran\KMeansClust>gfortran -v -Wall -save-temps kmeans.f90
Driving: gfortran -v -Wall -save-temps kmeans.f90 -lgfortranbegin -lgfortran
Using built-in specs.
Target: i386-pc-mingw32
Configured with: ../trunk/configure --prefix=/mingw --enable-languages=c,fortran --with-gmp=/home/FX/local --with-ld=/mingw/bin/ld -
-with-as=/mingw/bin/as --disable-werror --enable-bootstrap --enable-threads --disable-nls --build=i386-pc-mingw32 --enable-libgomp
Thread model: win32
gcc version 4.3.0 20070813 (experimental)
 f951 kmeans.f90 -quiet -dumpbase kmeans.f90 -mtune=i386 -auxbase kmeans -Wall -version -fintrinsic-modules-path finclude -o kmeans.
s
GNU F95 version 4.3.0 20070813 (experimental) (i386-pc-mingw32)
        compiled by GNU C version 4.3.0 20070813 (experimental), GMP version 4.2.1, MPFR version 2.2.1-p5.
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
kmeans.f90: In function 'MAIN__':
kmeans.f90:2054: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.

Code compiles and runs with Lahey/Fujitsu LF95 Version 7.1 Win32 compiler (although gfortran finds valid problems whilst LF95 does not, so this may not mean much).

Pardon if this is not best format, this is my first submission.
Comment 1 Jon D. Richards 2007-12-21 04:50:11 UTC
Created attachment 14803 [details]
Source code that causes ICE

This is the code that caused the ICE.
Comment 2 Jon D. Richards 2007-12-21 04:57:04 UTC
Downloaded and installed later version of gfortran. 

GNU F95 (GCC) version 4.3.0 20071130 (experimental) [trunk revision 130537]

I still get ICE:

G:\fortran\KMeansClust>gfortran -v -Wall -save-temps kmeans.f90
Driving: gfortran -v -Wall -save-temps kmeans.f90 -lgfortranbegin -lgfortran
Using built-in specs.
Target: i386-pc-mingw32
Configured with: ../trunk/configure --prefix=/mingw --enable-languages=c,fortran --with-gmp=/home/FX/local --with-ld=/mingw/bin/ld -
-with-as=/mingw/bin/as --disable-werror --enable-bootstrap --enable-threads --disable-nls --build=i386-pc-mingw32 --enable-libgomp -
-disable-shared
Thread model: win32
gcc version 4.3.0 20071130 (experimental) [trunk revision 130537] (GCC)
COLLECT_GCC_OPTIONS='-v' '-Wall' '-save-temps' '-mtune=i386'
 c:/program files/gfortran/bin/../libexec/gcc/i386-pc-mingw32/4.3.0/f951.exe kmeans.f90 -quiet -dumpbase kmeans.f90 -mtune=i386 -aux
base kmeans -Wall -version -fintrinsic-modules-path c:/program files/gfortran/bin/../lib/gcc/i386-pc-mingw32/4.3.0/finclude -o kmean
s.s
GNU F95 (GCC) version 4.3.0 20071130 (experimental) [trunk revision 130537] (i386-pc-mingw32)
        compiled by GNU C version 4.3.0 20071130 (experimental) [trunk revision 130537], GMP version 4.2.1, MPFR version 2.2.1-p5.
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
kmeans.f90: In function 'kmeans_driver':
kmeans.f90:2054: internal compiler error: Segmentation fault
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
Comment 3 Joost VandeVondele 2007-12-21 06:09:04 UTC
code compiles fine with NAG and g95, the line at the segfault looks OK.
Comment 4 kargl 2007-12-21 06:14:15 UTC
Here's a reduced testcase.

module const_mod
  implicit none
  integer, parameter :: mp = selected_real_kind(15,300)
end module const_mod

module blk1_mod
  implicit none
  integer :: numclusters = 2
end module blk1_mod

module kmeans_aux
  implicit none
  contains
    function get_nfirst( ) result(fnres)
      use const_mod, only: mp
      use blk1_mod, only: numclusters
      implicit none
      real(mp) :: fnres(numclusters)
    end function get_nfirst
end module kmeans_aux

program kmeans_driver
   use blk1_mod
   use kmeans_aux
   implicit none
   integer, allocatable :: nfirst(:)
   allocate(nfirst(1:numclusters))
   nfirst(1:numclusters) = get_nfirst( )
end program kmeans_driver

Comment 5 Tobias Burnus 2007-12-21 07:39:48 UTC
valgrind:

==6521== Invalid read of size 1
==6521==    at 0x49C7D0: gfc_get_symbol_decl (trans-decl.c:899)
==6521==    by 0x4A47DC: gfc_conv_variable (trans-expr.c:424)
==6521==    by 0x4A7079: gfc_apply_interface_mapping (trans-expr.c:1949)
==6521==    by 0x486BFA: gfc_set_loop_bounds_from_array_spec (trans-array.c:474)
==6521==    by 0x4A16C3: gfc_conv_function_call (trans-expr.c:2633)
==6521==    by 0x4A2398: gfc_conv_function_expr (trans-expr.c:3050)
Comment 6 Daniel Franke 2007-12-21 09:47:10 UTC
I can not reproduce the valgrind error, but ...

> module blk1_mod
>  implicit none
>  integer :: numclusters = 2
> end module blk1_mod

... the ICE goes away if 'numclusters' is defined as a parameter.

Further reduced testcase:
module blk1_mod
  implicit none
  integer :: numclusters = 2
end module blk1_mod

module kmeans_aux
  implicit none
  contains
    function get_nfirst( ) result(fnres)
      use blk1_mod, only: numclusters
      implicit none
      real :: fnres(numclusters)
    end function get_nfirst
end module kmeans_aux

program kmeans_driver
   use blk1_mod
   use kmeans_aux
   implicit none
   integer, allocatable :: nfirst(:)
   allocate(nfirst(1:numclusters))
   nfirst(1:numclusters) = get_nfirst( )
end program kmeans_driver
Comment 7 Jon D. Richards 2007-12-26 18:36:06 UTC
Maybe this should best be described as:
"ICE when function returns array of values to dynamically allocated array"
If the LHS is a 'statically allocated' array, the function returns array of values without problem.  If the LHS is a dynamically allocated array, attempting to assign the array of values from the functions causes an ICE.

So gfortran fails to implement an essential feature of Fortran 95.

Workaround is to call a subroutine and have the array of values returned in the argument list.
Comment 8 kargl 2007-12-26 22:07:38 UTC
(In reply to comment #7)
> Maybe this should best be described as:
> "ICE when function returns array of values to dynamically allocated array"
> If the LHS is a 'statically allocated' array, the function returns array of
> values without problem.  If the LHS is a dynamically allocated array,
> attempting to assign the array of values from the functions causes an ICE.

Well, no.  A better description probably involves the use of stack
memory for a function result gets trashed when you return from
the function.

I can assure that gfortran can assign array function results to
allocated memory.  You appear to have stumbled on a bug.

> 
> So gfortran fails to implement an essential feature of Fortran 95.
>

This statement is in rather poor taste, and is an example of why I
quit working on gfortran.  But, thanks for the bug report.

> Workaround is to call a subroutine and have the array of values
> returned in the argument list.

One can also learn to do proper memory management.

module kmeans_aux
  implicit none
  contains
    function get_nfirst( ) result(fnres)
      use const_mod, only: mp
      use blk1_mod, only: numclusters
      implicit none
!      real(mp) :: fnres(numbcluster)   ! This uses the stack instead of heap.
      real(mp), allocatable :: fnres(:) ! Properly manage heap memory
      if (allocated(fnres) .eqv. .true.) deallocate(fnres)
      allocate(fnres(numclusters))
      fnres = 1
    end function get_nfirst
end module kmeans_aux

Comment 9 Jon D. Richards 2007-12-27 10:33:53 UTC
Subject: RE:  ICE when compiling Fortran 95 code


 

-----Original Message-----
From: kargl at gcc dot gnu dot org [mailto:gcc-bugzilla@gcc.gnu.org] 
Sent: Wednesday, December 26, 2007 3:08 PM
To: jon_d_r@msn.com
Subject: [Bug fortran/34545] ICE when compiling Fortran 95 code



------- Comment #8 from kargl at gcc dot gnu dot org  2007-12-26 22:07
------- (In reply to comment #7)
> Maybe this should best be described as:
> "ICE when function returns array of values to dynamically allocated
array"
> If the LHS is a 'statically allocated' array, the function returns 
> array of values without problem.  If the LHS is a dynamically 
> allocated array, attempting to assign the array of values from the
functions causes an ICE.

Well, no.  A better description probably involves the use of stack memory
for a function result gets trashed when you return from the .function.

I can assure that gfortran can assign array function results to allocated
memory.  You appear to have stumbled on a bug.

> 
> So gfortran fails to implement an essential feature of Fortran 95.
>

This statement is in rather poor taste, and is an example of why I quit
working on gfortran.  But, thanks for the bug report.


I really apologize if this seemed harsh. When I learned to program, I tried
to become less sensitive to apparent critisism, because often it wasn't
meant in the manner I interpreted it. That wasn't supposed to be a hurtful
comment. My point may have been off, but what I was saying (awkwardly) was
that (in my mind) if the compiler can't do what is expected according to the
standard, then it fails to perform up to standard. Fortran itself doesn't
recognise nor care whether values are in stack or heap memory, it does
require that code is produced so that values are returned from the function.
Fortran is agnostic about implementation details. But, yes, it is good for
the programmer to be aware. I'm fairly satisfied with gfortran, really.

When I first encountered the problem, I had no idea what was causing it.  I
really do admire your quick and succinct analysis, resulting in a small test
case that exhibits the problem.  I never could have done that. (At least in
a reasonable time).  You'll never know how much I admire the skill you show
in your work, and how much I appreciate it. Thanks.


> Workaround is to call a subroutine and have the array of values 
> returned in the argument list.

One can also learn to do proper memory management.

module kmeans_aux
  implicit none
  contains
    function get_nfirst( ) result(fnres)
      use const_mod, only: mp
      use blk1_mod, only: numclusters
      implicit none
!      real(mp) :: fnres(numbcluster)   ! This uses the stack instead of
heap.
      real(mp), allocatable :: fnres(:) ! Properly manage heap memory
      if (allocated(fnres)) deallocate(fnres)
      allocate(fnres(1:numclusters), stat=istat) ! and check if the
allocation apparently worked.
      fnres = 1
    end function get_nfirst
end module kmeans_aux

Yes, that is a really good way, and I do generally do allocations like this.
Realize that I am refactoring some very old code here, and what you see is
only phase one. This is actually the first time I'd used the particular
pattern that caused the problem. The original code had several hundred lines
in the main program. I simply excised sections (cut/paste) into separate
procedures, while still retaining the essense of the common blocks. This was
a quick and dirty chunking of the original code: this is not in my style
when I write code de novo. 

The second phase would be to rewrite the main program and remove the
spaghetti code. Then, with the ability to see where the former elements of
the common blocks are active, I'd completely rearrange where and how memory
is allocated. I'd prefer to remove the apparent globalization of many of the
arrays. I'd like to hide them as far as possible from the main program,
which I like to see as the user's view of the problem. All the elements not
relating to the user's problem would be hidden away in the modules. The
original Fortran 77 code, with static array sizes, had all these arrays
upfront.

Actually the partially refactored code is working now. I'm disappointed in
how it works, but that is a problem I have with cluster analysis itself
<grin>.

In the future, I'll simply report the bugs and keep away from what might
seem as value judgements. Lesson learned.

Comment 10 Daniel Franke 2007-12-29 08:57:37 UTC
I'm only passing through, but ...

Jon:
> > If the LHS is a dynamically allocated array, attempting  
> > to assign the array of values from the functions causes an ICE.

Steve:
> Well, no.  A better description probably involves the use of stack
> memory for a function result gets trashed when you return from
> the function.

rings a bell. This is maybe related to PR32795?
Comment 11 Paul Thomas 2008-01-01 17:11:08 UTC
This is a most peculiar bug, which has nothing to do with allocatability or temporariness.  The result variables of the functions 'get_numbr' and 'get_nfirst' are REAL(mp), whereas they are assigned to INTEGER arrays.  Changing the results to INTEGER in the original clears the problem and, up to missing input files, the code seems OK.

This very much reduced example illustrates the problem:

module m1
  integer :: numclusters = 2
end module m1

module m2
  contains
    function get_nfirst( ) result(fnres)
      use m1, only: numclusters
      real :: fnres(numclusters)   ! change to REAL and it works!!  
    end function get_nfirst
end module m2

program kmeans_driver
   use m1
   use m2
   integer :: nfirst(3)
   nfirst(1:numclusters) = get_nfirst( )
end program kmeans_driver

Alternatively, moving the USE m1 in 'get_nfirst' to be a module specification statement, fixes the problem.....:)

I'm thinking about it; the offending version of numclusters is linked to a namespace that has no proc_name.  Why this should cause problems when there is a type mismatch, I have no idea.

Paul
Comment 12 Paul Thomas 2008-01-01 17:23:35 UTC
Ah! I feel a light bulb moment coming on.

The type mismatch necessitates the use of the internal real to integer conversion function, which in its turn checks the interface with 'get_nfirst'.  Being a formal argument to a use associated function, 'numclusters' seems to wind up with a bad namespace.  I have encountered this before and should now sort it out properly.  A kludgy fix is:

Index: ../trunk/gcc/fortran/trans-decl.c
===================================================================
*** ../trunk/gcc/fortran/trans-decl.c   (revision 131237)
--- ../trunk/gcc/fortran/trans-decl.c   (working copy)
*************** gfc_get_symbol_decl (gfc_symbol * sym)
*** 896,901 ****
--- 896,904 ----
                || sym->attr.use_assoc
                || sym->ns->proc_name->attr.if_source == IFSRC_IFBODY);

+   if (sym->ns && !sym->ns->proc_name)
+     sym->ns = gfc_current_ns;
+
    if (sym->ns && sym->ns->proc_name->attr.function)
      byref = gfc_return_by_reference (sym->ns->proc_name);
    else

Paul
Comment 13 Dominique d'Humieres 2008-01-01 22:47:14 UTC
The patch in comment #12 works as advertised without regression in 32 and 64 bit modes on ppc/Intel and my favourite platform.

Comment 14 Paul Thomas 2008-01-02 21:00:24 UTC
(In reply to comment #13)
> The patch in comment #12 works as advertised without regression in 32 and 64
> bit modes on ppc/Intel and my favourite platform.
> 
Thanks for the test.  I have been through several variants and think that this is the most hygenic:

Index: gcc/fortran/module.c
===================================================================
*** gcc/fortran/module.c        (revision 131237)
--- gcc/fortran/module.c        (working copy)
*************** load_needed (pointer_info *p)
*** 3525,3530 ****
--- 3525,3536 ----
          associate_integer_pointer (q, ns);
        }

+       /* Use the module sym as 'proc_name' so that gfc_get_symbol_decl
+        doesn't go pear-shaped if the symbol is used.  */
+       if (!ns->proc_name)
+       gfc_find_symbol (p->u.rsym.module, gfc_current_ns,
+                        1, &ns->proc_name);
+
        sym = gfc_new_symbol (p->u.rsym.true_name, ns);
        sym->module = gfc_get_string (p->u.rsym.module);
        strcpy (sym->binding_label, p->u.rsym.binding_label);

I'm going to regtest in a few minutes but I'm confident that it's OK.  It has the advantage too that -fdump-parse-tree produces soemthing useful.

Paul
Comment 15 Tobias Burnus 2008-01-06 18:48:56 UTC
Patch: http://gcc.gnu.org/ml/fortran/2008-01/msg00017.html

Paul, what is with your patch (see above)? (I OKed it a few days ago.)
Comment 16 Paul Thomas 2008-01-06 20:39:54 UTC
Subject: Re:  ICE when compiling Fortran 95 code

Tobias,

Nothing - I have just updated to FC8 and blew all my nice set-up to 
pieces.  This is the first time that Fedora has let me down.  I will be 
operational first thing tomorrow morning - I just got back in action 
about 20 minutes ago but am too dog-tired to do anything right now.

BTW The PR34431 etc. patch is coming along.  I have cured all the 
regressions but have found other, very curious bugs.

eg.

integer (kind(1_8)) foo ()

fails with the patch.  The bailing out to defer kind association until 
USE and IMPORT are over is too soon - the kind expression needs to be 
converted and, on the basis of the expression, the deferral mechanism 
triggered.  I think that it is sufficient to do this if the expression 
contains a variable.

I am pretty sure that I know what I have to do to complete this but it 
will take a couple of days yet.  I'll tidy up the statement decoding, 
whilst I am about it.

Cheers

Paul

Comment 17 Paul Thomas 2008-01-06 22:00:53 UTC
Subject: Bug 34545

Author: pault
Date: Sun Jan  6 22:00:00 2008
New Revision: 131364

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=131364
Log:
2008-01-06  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/34545
	* module.c (load_needed): If the namespace has no proc_name
	give it the module symbol.

2008-01-06  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/34545
	* gfortran.dg/use_12.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/use_12.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/module.c
    trunk/gcc/testsuite/ChangeLog

Comment 18 Paul Thomas 2008-01-07 08:15:25 UTC
Fixed on trunk

Paul