Message ID | 4FB928DA.8090806@acm.org |
---|---|
State | New |
Headers | show |
On Sun, May 20, 2012 at 7:24 PM, Nathan Sidwell <nathan@acm.org> wrote: > In building a ppc cross compiler using a freshly built native compiler, I > encountered an ICE in iterative_hash_expr compiling c-lex.c. I extracted > the attached testcase, showing the problem is with statement expressions. > Investigation showed I_H_E seeing BLOCK and BIND_EXPR nodes, which is was > unprepared for. These two nodes are never considered equal by > operand_equal_p, so we don't need to look into them further to refine the > hash. > > I'm not sure why a native i686-pc-linux-gnu bootstrap doesn't encounter this > problem. > > The attached patch resolves the ICE. built and tested on i686-pc-linux-gnu, > ok? Hmm - I think this papers over the issue that the CONSTRUCTOR is not properly gimplified - it still contains a TARGET_EXPR which is not valid GIMPLE. Why is that TARGET_EXPR not gimplified? Richard. > nathan
On 05/21/12 11:03, Richard Guenther wrote: > Hmm - I think this papers over the issue that the CONSTRUCTOR is not > properly gimplified - it still contains a TARGET_EXPR which is not valid GIMPLE. > Why is that TARGET_EXPR not gimplified? As far as I can make out, it just doesn't look inside the constructor. 0 gimplify_expr (expr_p=0xb7e90394, pre_p=0xbfffe514, post_p=0xbfffd08c, gimple_test_f=0x84b0a80 <is_gimple_min_lval(tree_node*)>, fallback=3) at ../../src/gcc/gimplify.c:7356 #1 0x084f5882 in gimplify_compound_lval (expr_p=0xb7e9cb94, pre_p=0xbfffe514, post_p=0xbfffd08c, fallback=1) at ../../src/gcc/gimplify.c:2259 #2 0x08519878 in gimplify_expr (expr_p=0xb7e9cb94, pre_p=0xbfffe514, post_p=0xbfffd08c, gimple_test_f=0x84eaf9f <is_gimple_reg_rhs_or_call(tree)>, fallback=1) at ../../src/gcc/gimplify.c:7081 #3 0x085087f7 in gimplify_modify_expr (expr_p=0xbfffd6d0, pre_p=0xbfffe514, post_p=0xbfffd08c, want_value=false) at ../../src/gcc/gimplify.c:4843 The switch case at that stack frame is for CONSTRUCTORs. It has the comment: /* Don't reduce this in place; let gimplify_init_constructor work its magic. Buf if we're just elaborating this for side effects, just gimplify any element that has side-effects. */ But we never enter G_I_C before the ICE. On the second time we get here, fallback has the value 1 at that point (fb_rvalue), so neither if condition is satisified, and we end up at ret = GS_ALL_DONE; we then proceed down to enter: else if ((fallback & fb_rvalue) && is_gimple_reg_rhs_or_call (*expr_p)) { /* An rvalue will do. Assign the gimplified expression into a new temporary TMP and replace the original expression with TMP. First, make sure that the expression has a type so that it can be assigned into a temporary. */ gcc_assert (!VOID_TYPE_P (TREE_TYPE (*expr_p))); *expr_p = get_formal_tmp_var (*expr_p, pre_p); } and ICE inside GFTV when it attempts to generate the hash. AFAICT, changing the test case to: char *str = ((union {const char * _q; char * _nq;}) ((const char *)((num_string) ->string.str)))._nq; (i.e. removing the stmt-expr) results in the same logical flow as above, but there's no TARGET_EXPR inside the constructor. I'm not sure how it's supposed to work, so I'm a little lost.
2012-05-20 Nathan Sidwell <nathan@acm.org> * tree.c (iterative_hash_expr): Add BLOCK and BIND_EXPR cases. * gcc.dg/stmt-expr-4.c: New. Index: tree.c =================================================================== --- tree.c (revision 187628) +++ tree.c (working copy) @@ -6998,6 +6998,11 @@ iterative_hash_expr (const_tree t, hashv } return val; } + case BLOCK: + case BIND_EXPR: + /* These are never equal operands. The contain nodes we're not + prepared for, so stop now. */ + return val; case MEM_REF: { /* The type of the second operand is relevant, except for Index: testsuite/gcc.dg/stmt-expr-4.c =================================================================== --- testsuite/gcc.dg/stmt-expr-4.c (revision 0) +++ testsuite/gcc.dg/stmt-expr-4.c (revision 0) @@ -0,0 +1,22 @@ + +/* { dg-options "-O2 -std=gnu99" } */ +/* Internal compiler error in iterative_hash_expr */ + +struct tree_string +{ + char str[1]; +}; + +union tree_node +{ + struct tree_string string; +}; + +char *Foo (union tree_node * num_string) +{ + char *str = ((union {const char * _q; char * _nq;}) + ((const char *)(({ __typeof (num_string) const __t + = num_string; __t; }) + ->string.str)))._nq; + return str; +}