Bug 33288 - ICE (segfault) in mpfr_cmp2 when evaluating array initializers containing addition
Summary: ICE (segfault) in mpfr_cmp2 when evaluating array initializers containing add...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: 4.3.0
Assignee: Francois-Xavier Coudert
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: ice-on-valid-code, patch, wrong-code
Depends on:
Blocks: 32834
  Show dependency treegraph
 
Reported: 2007-09-03 06:58 UTC by rainy6144
Modified: 2007-09-20 21:58 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.1.3 4.2.2 4.3.0
Last reconfirmed: 2007-09-19 11:52:17


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description rainy6144 2007-09-03 06:58:21 UTC
gfortran 4.1.2/4.2.0/4.3.0 segfaults when compiling the following program:

program initbug
     integer,parameter :: n0 = 3, n = 5
     real(kind=8),parameter :: x0(n0) = (/ 0.0d0, 0.0d0, 0.0d0 /)
     real(kind=8),parameter :: x(n) = (/ -x0, x0(n0-1:1:-1) /) + 1.0d0
end program initbug

Valgrind output:

$ valgrind /home/r6144/apps/gcc-4.3.0-070903-bin/bin/../libexec/gcc/i386-pc-linux-gnu/4.3.0/f951 initbug.f90 -quiet -dumpbase initbug.f90 -march=pentium4 -mfpmath=sse -auxbase-strip initbug.o -g -O2 -Wall -W -Wno-unused -Wimplicit-interface -Wtabs -version -ffree-form -ffree-line-length-none -fimplicit-none -ffpe-trap=invalid,zero,overflow -fintrinsic-modules-path /home/r6144/apps/gcc-4.3.0-070903-bin/bin/../lib/gcc/i386-pc-linux-gnu/4.3.0/finclude -o /tmp/ccZfWmpd.s
==5331== Memcheck, a memory error detector.
==5331== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.
==5331== Using LibVEX rev 1658, a library for dynamic binary translation.
==5331== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.
==5331== Using valgrind-3.2.1, a dynamic binary instrumentation framework.
==5331== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.
==5331== For more details, rerun with: -v
==5331==
GNU F95 (GCC) version 4.3.0 20070902 (experimental) [trunk revision 128023] (i386-pc-linux-gnu)
        compiled by GNU C version 4.3.0 20070902 (experimental) [trunk revision 128023], GMP version 4.2.1, MPFR version 2.2.1.
GGC heuristics: --param ggc-min-expand=63 --param ggc-min-heapsize=63256
==5331== Invalid read of size 4
==5331==    at 0x84CCEDB: mpfr_cmp2 (in /home/r6144/apps/gcc-4.3.0-070903-bin/libexec/gcc/i386-pc-linux-gnu/4.3.0/f951)
==5331==    by 0x84C6D35: mpfr_sub1 (in /home/r6144/apps/gcc-4.3.0-070903-bin/libexec/gcc/i386-pc-linux-gnu/4.3.0/f951)
==5331==    by 0x84B9AB2: mpfr_add (in /home/r6144/apps/gcc-4.3.0-070903-bin/libexec/gcc/i386-pc-linux-gnu/4.3.0/f951)
==5331==    by 0x804CB56: gfc_arith_plus (arith.c:657)
==5331==  Address 0x812488 is not stack'd, malloc'd or (recently) free'd
initbug.f90:0: 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 1 Dominique d'Humieres 2007-09-03 07:39:45 UTC
I don't see the ICE on PPC Darwin8, revision 128037, but the following modifed code gives a wrong answer:

program initbug
     integer,parameter :: n0 = 3, n = 5
     real(kind=8),parameter :: x0(n0) = (/ 2.0d0, 2.0d0, 2.0d0 /)
     real(kind=8),parameter :: x(n) = (/ -x0, x0(n0-1:1:-1) /) + 1.0d0
     print *, x
end program initbug

gives

  -1.00000000000000       -1.00000000000000       -1.00000000000000        1.00000000000000        0.00000000000000     

xlf and g95 gives:

 -1.00000000000000000 -1.00000000000000000 -1.00000000000000000 3.00000000000000000 3.00000000000000000

or  -1. -1. -1. 3. 3. as I expect.
Comment 2 Tobias Burnus 2007-09-03 09:34:53 UTC
> I don't see the ICE on PPC Darwin8, revision 128037, but the following modifed
> code gives a wrong answer:

For me (4.3.0 20070903, r128037, x86_64-unknown-linux-gnu) both examples cause a segmentation fault in mpfr_cmp2. Interestingly, I don't get any failure if I run the program through valgrind.
Comment 3 Dominique d'Humieres 2007-09-03 09:43:19 UTC
If I try to "regtestify" the code (uncomment the commented line):

program initbug
     integer,parameter :: n0 = 3, n = 5
     real(kind=8),parameter :: x0(n0) = (/ 2.0d0, 2.0d0, 2.0d0 /)
     real(kind=8),parameter :: x(n) = (/ -x0, x0(n0-1:1:-1) /) + 1.0d0
     print *, x
!     if (any(x /= (/ -1.0d0, -1.0d0, -1.0d0, 3.0d0, 3.0d0 /))) call abort()
end program initbug

I get:

[karma] f90/bug% gfc pr33288.f90
pr33288.f90:4.37:

     real(kind=8),parameter :: x(n) = (/ -x0, x0(n0-1:1:-1) /) + 1.0d0
                                    1
Error: Array operands are incommensurate at (1)

Comment 4 Tobias Burnus 2007-09-03 10:12:11 UTC
The following does not ICE for me and produces the right result (note the extra "+0.0"):
     real,parameter :: x(n) =  (/ -x0, x0(n0-1:1:-1) + 0.0 /) +1.0
analogously for (note extra "(...)"):
     real,parameter :: x(n) =  (/ -x0, ( x0(n0-1:1:-1) ) /) +1.0

Seemingly, the array range x0(n0-1:1:-1) does not get properly simplified and thus ->value.real points to the nirvana.
Comment 5 Dominique d'Humieres 2007-09-03 11:01:56 UTC
I confirm that

program initbug
     integer,parameter :: n0 = 3, n = 5
     real(kind=8),parameter :: x0(n0) = (/ 2.0d0, 2.0d0, 2.0d0 /)
     real(kind=8),parameter :: x(n) = (/ -x0, x0(n0-1:1:-1) + 0.0d0 /) + 1.0d0
     print *, x
     if (any(x /= (/ -1.0d0, -1.0d0, -1.0d0, 3.0d0, 3.0d0 /))) call abort()
end program initbug

works as expected.

Comment 6 Francois-Xavier Coudert 2007-09-03 11:31:46 UTC
(In reply to comment #4)
> Seemingly, the array range x0(n0-1:1:-1) does not get properly simplified and
> thus ->value.real points to the nirvana.

Nope. I get an ICE for the following testcase:
  real, parameter :: x0(1) = 0
  real, parameter :: x(1) = (/ x0 /) + 1
  end

The problem is that we come into gfc_arith_plus() with one operand being an EXPR_ARRAY, so looking at its value.real is wrong (if you want to do something with it, it's value.constructor that should be looked at). I guess reduce_binary_ac() should really look deeper: in the loop "for (c = head; c; c = c->next)", we should see whether c->expr is an EXPR_CONSTANT before calling eval(), and look deeper into it if it's an EXPR_ARRAY. (Though it's the first time I look at this code and array constructors, I might be misunderstanding it all.)
Comment 7 Francois-Xavier Coudert 2007-09-19 11:52:17 UTC
Mine. A straightforward patch following the idea laid in my previous comment fixes it.


Index: arith.c
===================================================================
--- arith.c     (revision 128540)
+++ arith.c     (working copy)
@@ -1288,7 +1288,11 @@ reduce_unary (arith (*eval) (gfc_expr *,

   for (c = head; c; c = c->next)
     {
-      rc = eval (c->expr, &r);
+      if (c->expr->expr_type == EXPR_CONSTANT)
+       rc = eval (c->expr, &r);
+      else
+       rc = reduce_unary (eval, c->expr, &r);
+
       if (rc != ARITH_OK)
        break;

@@ -1328,7 +1332,11 @@ reduce_binary_ac (arith (*eval) (gfc_exp

   for (c = head; c; c = c->next)
     {
-      rc = eval (c->expr, op2, &r);
+      if (c->expr->expr_type == EXPR_CONSTANT)
+        rc = eval (c->expr, op2, &r);
+      else
+       rc = reduce_binary_ac (eval, c->expr, op2, &r);
+
       if (rc != ARITH_OK)
        break;

@@ -1368,7 +1376,11 @@ reduce_binary_ca (arith (*eval) (gfc_exp

   for (c = head; c; c = c->next)
     {
-      rc = eval (op1, c->expr, &r);
+      if (c->expr->expr_type == EXPR_CONSTANT)
+       rc = eval (op1, c->expr, &r);
+      else
+       rc = reduce_binary_ca (eval, op1, c->expr, &r);
+
       if (rc != ARITH_OK)
        break;

@@ -1395,6 +1407,11 @@ reduce_binary_ca (arith (*eval) (gfc_exp
 }


+/* We need a forward declaration of reduce_binary.  */
+static arith reduce_binary (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
+                           gfc_expr *op1, gfc_expr *op2, gfc_expr **result);
+
+
 static arith
 reduce_binary_aa (arith (*eval) (gfc_expr *, gfc_expr *, gfc_expr **),
                  gfc_expr *op1, gfc_expr *op2, gfc_expr **result)
@@ -1421,7 +1438,7 @@ reduce_binary_aa (arith (*eval) (gfc_exp
              break;
            }

-         rc = eval (c->expr, d->expr, &r);
+         rc = reduce_binary (eval, c->expr, d->expr, &r);
          if (rc != ARITH_OK)
            break;
Comment 8 Francois-Xavier Coudert 2007-09-20 21:58:35 UTC
Subject: Bug 33288

Author: fxcoudert
Date: Thu Sep 20 21:58:23 2007
New Revision: 128632

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=128632
Log:
	PR fortran/33288

	* arith.c (reduce_unary, reduce_binary_ac, reduce_binary_ca,
	reduce_binary_aa): Call ourselves recursively if an element of
	the constructor is itself a constant array.

	* gfortran.dg/array_constructor_19.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/array_constructor_19.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/arith.c
    trunk/gcc/testsuite/ChangeLog

Comment 9 Francois-Xavier Coudert 2007-09-20 21:58:55 UTC
Fixed.