Bootstrapping gcc from the 19 Aug 2008 mainline sources (and possibly earlier and/or later) with an integrated source tree containing the binutils mainline sources fails with: gcc/current/opcodes/i386-dis.c: In function 'dofloat': gcc/current/opcodes/i386-dis.c:4193: error: type mismatch in pointer plus expression struct dis386 * struct dis386[8] * long unsigned int dp = &float_reg + D.7971 The source line in question (line 4213 in opcodes/i386-dis.c) is correct: dp = &float_reg[floatop - 0xd8][modrm.reg]; where dp is a "const struct dis386 *" and float_reg is a "const struct dis386 [][8]"
Created attachment 14080 [details] Compressed, pre-processed source file used to reproduce the problem This source file was compiled with this command line: cc1 -fpreprocessed i386-dis.i -quiet -dumpbase i386-dis.c -mtune=generic -auxbase-strip i386-dis.o -g -O2 -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -version -o i386-dis.s which was executed by gcc from this original command line: /work/sources/non-sources/builds/maintainer/FSF/FSF-bootstrap/./prev-gcc/xgcc -B/work/sources/non-sources/builds/maintainer/FSF/FSF-bootstrap/./prev-gcc/ -B/work/sources/non-sources/builds/maintainer/FSF/FSF-bootstrap/install/x86_64-unknown-linux-gnu/bin/ -DHAVE_CONFIG_H -I. -I/work/sources/gcc/current/opcodes -I. -D_GNU_SOURCE -I. -I/work/sources/gcc/current/opcodes -I../bfd -I/work/sources/gcc/current/opcodes/../include -I/work/sources/gcc/current/opcodes/../bfd -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Werror -g -O2 -c /work/sources/gcc/current/opcodes/i386-dis.c -o i386-dis.o --save-temps -v
Reduced testcase: struct dis386 { const char *x; }; static const struct dis386 float_reg[][2] = { { { "fadd" }, { "fadd" } }, }; void foo(int i, int j) { const struct dis386 *dp; dp = &float_reg[i - 1][j]; } Note that with &float_reg[i][j] it works just fine. The fronted generates dp = &float_reg + (((long unsigned int) ((long unsigned int) i * 2) + (long unsigned int) (long unsigned int) j) * 8 + 0xfffffffffffffffffffffffffffffff0); which has a missing conversion to (struct dis386 *). Without the subtraction in the first array ref we get dp = (struct dis386 *) &float_reg + ((long unsigned int) ((long unsigned int) i * 2) + (long unsigned int) (long unsigned int) j) * 8; instead, which is correct.
Ah no, this is a bug in fold-const introduced by the pplus merge. Fix: @@ -9541,7 +9547,9 @@ fold_binary (enum tree_code code, tree t tree arg01 = fold_convert (sizetype, TREE_OPERAND (arg0, 1)); tree arg00 = TREE_OPERAND (arg0, 0); inner = fold_build2 (PLUS_EXPR, sizetype, arg01, fold_convert (sizetype, arg1)); - return fold_build2 (POINTER_PLUS_EXPR, type, arg00, inner); + return fold_convert (type, + fold_build2 (POINTER_PLUS_EXPR, + TREE_TYPE (arg00), arg00, inner)); } /* PTR_CST +p CST -> CST1 */
Created attachment 14081 [details] patch
Fixed.
Subject: Bug 33122 Author: rguenth Date: Tue Aug 21 08:23:50 2007 New Revision: 127659 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=127659 Log: 2007-08-21 Richard Guenther <rguenther@suse.de> PR middle-end/33122 * fold-const.c (fold_binary): Remove index +p PTR folding. Fix types of POINTER_PLUS_EXPR generated by folding of (PTR +p B) +p A. * gcc.c-torture/compile/pr33122.c: New testcase. Added: trunk/gcc/testsuite/gcc.c-torture/compile/pr33122.c Modified: trunk/gcc/ChangeLog trunk/gcc/fold-const.c trunk/gcc/testsuite/ChangeLog