Bug 24470 - [3.4 Regression] segmentation fault in cc1plus when compiling with -O
Summary: [3.4 Regression] segmentation fault in cc1plus when compiling with -O
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 3.4.3
: P2 normal
Target Milestone: 3.4.6
Assignee: Richard Biener
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: ice-on-valid-code, patch
Depends on:
Blocks:
 
Reported: 2005-10-21 10:09 UTC by Thorsten Raasch
Modified: 2005-12-06 21:37 UTC (History)
1 user (show)

See Also:
Host: i386-redhat-linux
Target: i386-redhat-linux
Build: i386-redhat-linux
Known to work: 3.3.6 4.0.2 4.1.0
Known to fail: 3.4.5
Last reconfirmed: 2005-10-21 10:41:53


Attachments
gzipped .ii file (214 bytes, application/x-gzip)
2005-10-21 10:10 UTC, Thorsten Raasch
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Thorsten Raasch 2005-10-21 10:09:02 UTC
The following program yields a segmentation fault in cc1plus when being compiled with any optimization option -O.

If the argument in TestClass::f() is replaced either by a "const int" or an "unsigned int", the program can indeed be compiled.
Moreover, if the ?-operator construct is replaced by, say, c[g(i)],
where g is another method, then the code is also compileable.
So the entire problem results from composing a ?-operator construct based on a "const unsigned int" method parameter with a successive array access.


The program source code:

class TestClass {
public:
  TestClass() {
    c[0] = 1;
    c[1] = 2;
  }

  int f(const unsigned int i) {
    return c[(i==1) ? 1 : 0];
  }

  int c[2];
};

int main()
{
  TestClass c;
  int x = c.f(1);

  return 0;
}


output when compiling with "g++ -O2 bug.cpp -o bug.o":

bug.cpp: In function `int main()':
bug.cpp:18: warning: unused variable 'x'
g++: Internal error: Segmentation fault (program cc1plus)
Please submit a full bug report.
See <URL:http://bugzilla.redhat.com/bugzilla> for instructions.

Release: (output of "g++ -v")
Reading specs from /usr/lib/gcc/i386-redhat-linux/3.4.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux
Thread model: posix
gcc version 3.4.3 20050227 (Red Hat 3.4.3-22.1)

Environment:
(Red Hat) Linux 2.6.9-11, i686 pc
Comment 1 Thorsten Raasch 2005-10-21 10:10:39 UTC
Created attachment 10038 [details]
gzipped .ii file
Comment 2 Richard Biener 2005-10-21 10:28:03 UTC
With checking enabled and 3.4 branch HEAD we go loop infinitely allocating _lots_ of ram.

Investigating.
Comment 3 Richard Biener 2005-10-21 10:41:53 UTC
We are endlessly folding

(gdb) call debug_tree(expr)
 <cond_expr 0x403fc2e0
    type <integer_type 0x4018a9b4 unsigned int unsigned sizetype SI
        size <integer_cst 0x40025208 constant 32>
        unit size <integer_cst 0x40025294 constant 4>
        align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0x400252d0 0> max <integer_cst 0x400252e4 4294967295>>
   
    arg 0 <eq_expr 0x4002c828
        type <boolean_type 0x40027870 bool unsigned QI
            size <integer_cst 0x400250f0 constant 8>
            unit size <integer_cst 0x40025104 constant 1>
            align 8 symtab 0 alias set -1 precision 1 min <integer_cst 0x40025424 0> max <integer_cst 0x40025460 1>>
       
        arg 0 <nop_expr 0x4025a3ac type <integer_type 0x40027654 unsigned int>
            readonly
            arg 0 <integer_cst 0x4025a154 constant 1>>
        arg 1 <integer_cst 0x4025a3c0 constant 1>>
    arg 1 <integer_cst 0x4002594c type <integer_type 0x4018a9b4 unsigned int> constant 1>
    arg 2 <integer_cst 0x400259c4 type <integer_type 0x4018a9b4 unsigned int> constant 0>>

#1  0x08330424 in fold (expr=0x403fc380) at fold-const.c:8151
#2  0x08330424 in fold (expr=0x403fc360) at fold-const.c:8151
#3  0x08330424 in fold (expr=0x403fc340) at fold-const.c:8151
...

coming from

#0  fold (expr=0x40023760) at fold-const.c:8151
#1  0x08310ed5 in fold (expr=0x4025a5dc) at fold-const.c:5507
#2  0x0816c538 in ocp_convert (type=0x4018a9b4, expr=0x40023300, convtype=15, 
    flags=131) at cvt.c:699
#3  0x0816d729 in convert (type=0x4018a9b4, expr=0x40023300) at cvt.c:944
#4  0x082cc8ed in expand_expr_real (exp=0x4002c7f8, target=0x40248aa0, 
    tmode=SImode, modifier=EXPAND_NORMAL, alt_rtl=0xbfcf2468) at expr.c:6916
#5  0x082bd8eb in store_expr (exp=0x4002c7f8, target=0x40248aa0, want_value=0)
    at expr.c:4221
#6  0x082bc798 in expand_assignment (to=0x40257bd0, from=0x4002c7f8, 
    want_value=0) at expr.c:4001
#7  0x082e199b in expand_expr_real (exp=0x4002c7e0, target=0x0, 
    tmode=VOIDmode, modifier=EXPAND_NORMAL, alt_rtl=0xbfcf445c) at expr.c:8710

Expanding

#4  0x082cc8ed in expand_expr_real (exp=0x4002c7f8, target=0x40248aa0, 
    tmode=SImode, modifier=EXPAND_NORMAL, alt_rtl=0xbfcf2468) at expr.c:6916
Line number 6916 out of range; expr.c has 141 lines.
(gdb) call debug_tree (exp)
 <array_ref 0x4002c7f8
    type <integer_type 0x400275e8 int SI
        size <integer_cst 0x4025a30c constant 32>
        unit size <integer_cst 0x4025a320 constant 4>
        align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0x4025a334 -2147483648> max <integer_cst 0x4025a348 2147483647>
        pointer_to_this <pointer_type 0x4018b0d8>>
   
    arg 0 <component_ref 0x4002c810
        type <array_type 0x40251ec4 type <integer_type 0x400275e8 int>
            DI
            size <integer_cst 0x4025a2e4 constant 64>
            unit size <integer_cst 0x4025a2f8 constant 8>
            align 32 symtab 0 alias set -1 domain <integer_type 0x4018b6c0>>
       
        arg 0 <indirect_ref 0x4025a26c type <record_type 0x402516c0 TestClass>
           
            arg 0 <nop_expr 0x4025a280 type <pointer_type 0x40251798>
                readonly arg 0 <var_decl 0x40257af8 this>>>
        arg 1 <field_decl 0x40251f30 c type <array_type 0x40251ec4>
            used nonlocal decl_3 DI file bug.cpp line 12
            size <integer_cst 0x400255a0 constant 64>
            unit size <integer_cst 0x40025924 constant 8>
            align 32 offset_align 128
            offset <integer_cst 0x400259c4 constant 0>
            bit offset <integer_cst 0x40025a64 constant 0> context <record_type 0x402516c0 TestClass> arguments <integer_cst 0x400259c4 0> chain <type_decl 0x402518dc TestClass>>>
    arg 1 <cond_expr 0x40023300 type <integer_type 0x400275e8 int>
       
        arg 0 <eq_expr 0x4002c828 type <boolean_type 0x40027870 bool>
           
            arg 0 <nop_expr 0x4025a3ac type <integer_type 0x40027654 unsigned int>
                readonly
                arg 0 <integer_cst 0x4025a154 constant 1>>
            arg 1 <integer_cst 0x4025a3c0 constant 1>>
        arg 1 <integer_cst 0x4025a3d4 constant 1>
        arg 2 <integer_cst 0x4025a3e8 constant 0>>>
Comment 4 Richard Biener 2005-10-21 10:54:47 UTC
The problem is the condition of the COND_EXPR is not folded:

        arg 0 <eq_expr 0x4002c828 type <boolean_type 0x40027870 bool>

            arg 0 <nop_expr 0x4025a3ac type <integer_type 0x40027654 unsigned
int>
                readonly
                arg 0 <integer_cst 0x4025a154 constant 1>>
            arg 1 <integer_cst 0x4025a3c0 constant 1>>

so the transformation

          /* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
             we might still be able to simplify this.  For example,
             if C1 is one less or one more than C2, this might have started
             out as a MIN or MAX and been transformed by this function.
             Only good for INTEGER_TYPEs, because we need TYPE_MAX_VALUE.  */

          if (INTEGRAL_TYPE_P (type)
              && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
              && TREE_CODE (arg2) == INTEGER_CST)
            switch (comp_code)
              {
              case EQ_EXPR:
                /* We can replace A with C1 in this case.  */
                arg1 = fold_convert (type, TREE_OPERAND (arg0, 1));
                return fold (build (code, type, TREE_OPERAND (t, 0), arg1,
                                    TREE_OPERAND (t, 2)));

does not make any changes.
Comment 5 Richard Biener 2005-10-21 11:00:29 UTC
I have a patch that papers over the problem.
Comment 6 Eric Botcazou 2005-10-21 11:06:50 UTC
> I have a patch that papers over the problem.

The best ones. ;-)
Comment 7 Richard Biener 2005-10-21 12:11:52 UTC
The problem is we didn't fold

           arg 0 <nop_expr 0x4025a3ac type <integer_type 0x40027654 unsigned
int>
                readonly
                arg 0 <integer_cst 0x4025a154 constant 1>>

which originates from build_binary_op() where default_conversion converts

 <parm_decl 0x40251c3c i
    type <integer_type 0x40251bd0 unsigned int readonly unsigned SI
        size <integer_cst 0x40025208 constant 32>
        unit size <integer_cst 0x40025294 constant 4>
        align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0x400252d0 0> max <integer_cst 0x400252e4 4294967295>>
    readonly unsigned used SI file bug.cpp line 8 size <integer_cst 0x40025208 32> unit size <integer_cst 0x40025294 4>
    align 32 context <function_decl 0x40251d80 f> initial <integer_type 0x40251bd0 unsigned int> arg-type <integer_type 0x40251bd0 unsigned int>>

to

 <nop_expr 0x402567e4
    type <integer_type 0x40027654 unsigned int unsigned SI
        size <integer_cst 0x40025208 constant 32>
        unit size <integer_cst 0x40025294 constant 4>
        align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0x400252d0 0> max <integer_cst 0x400252e4 4294967295>>
    readonly
    arg 0 <parm_decl 0x40251c3c i
        type <integer_type 0x40251bd0 unsigned int readonly unsigned SI size <integer_cst 0x40025208 32> unit size <integer_cst 0x40025294 4>
            align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0x400252d0 0> max <integer_cst 0x400252e4 4294967295>>
        readonly unsigned used SI file bug.cpp line 8 size <integer_cst 0x40025208 32> unit size <integer_cst 0x40025294 4>
        align 32 context <function_decl 0x40251d80 f> initial <integer_type 0x40251bd0 unsigned int> arg-type <integer_type 0x40251bd0 unsigned int>>>

i.e. (const unsigned int)i  where i is already unsigned int.  We later don't
fold after inlining and parameter substitution.

I'll test the papering-over.  Not worth a real fix.
Comment 8 Richard Biener 2005-11-03 09:30:17 UTC
Subject: Bug 24470

Author: rguenth
Date: Thu Nov  3 09:30:12 2005
New Revision: 106426

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=106426
Log:
2005-11-03  Richard Guenther  <rguenther@suse.de>

	PR middle-end/24470
	* fold-const.c (fold): Avoid running in circles if we
	got some un-folded subtree.

Modified:
    branches/gcc-3_4-branch/gcc/ChangeLog
    branches/gcc-3_4-branch/gcc/fold-const.c

Comment 9 Richard Biener 2005-11-03 09:31:39 UTC
Fixed.