https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86216
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- The interesting thing is that the RHS _1 is from a different function, a SAVE_EXPR expansion actually, which means this is another case of cross-function tree sharing (I remember fixing such thing in the fortran FE). Breakpoint 7, gimplify_save_expr (expr_p=0x7ffff6db3b18, pre_p=0x7fffffffd058, post_p=0x7fffffffca98) at ../../src/trunk/gcc/gimplify.c:5870 5870 enum gimplify_status ret = GS_ALL_DONE; $38 = <save_expr 0x7ffff6da3a80> $39 = <function_decl 0x7ffff6dac100 b> ... Breakpoint 7, gimplify_save_expr (expr_p=0x7ffff6da3ab8, pre_p=0x7fffffffc658, post_p=0x7fffffffc458) at ../../src/trunk/gcc/gimplify.c:5870 5870 enum gimplify_status ret = GS_ALL_DONE; $42 = <save_expr 0x7ffff6da3a80> $43 = <function_decl 0x7ffff6dac400 operator()> (gdb) p (*expr_p)->base.public_flag $45 = 1 I guess we can track down at least the SAVE_EXPR case with Index: gcc/gimplify.c =================================================================== --- gcc/gimplify.c (revision 262624) +++ gcc/gimplify.c (working copy) @@ -869,7 +869,11 @@ copy_if_shared_r (tree *tp, int *walk_su /* Otherwise, mark the node as visited and keep looking. */ else - TREE_VISITED (t) = 1; + { + if (TREE_CODE (t) == SAVE_EXPR) + gcc_assert (!SAVE_EXPR_RESOLVED_P (t)); + TREE_VISITED (t) = 1; + } return NULL_TREE; } It's probably easy that this case of sharing happens for nested functions since most type sizes are wrapped in SAVE_EXPRs and those do not get unshared even when that is explicitely asked for. But it looks like the tree sharing happens outside of a SAVE_EXPR given we have at gimplify_function_tree time { intptr_t & n [value-expr: this->__n]; intptr_t & n [value-expr: this->__n]; { <<cleanup_point <<< Unknown tree: expr_stmt (void) (*n = (intptr_t) ((unsigned int) (_1 + 1) * 4)) >>>>>; } } where _1 + 1 was what a SAVE_EXPR was resolved to but here we should have seen the DECL created for it rather than the in-place gimplified result. The .original dump though has ;; Function b(intptr_t, T) [with T = int; intptr_t = int]::<lambda()>::<lambda()> (null) ;; enabled by -tree-original { intptr_t & n [value-expr: this->__n]; intptr_t & n [value-expr: this->__n]; { <<cleanup_point <<< Unknown tree: expr_stmt (void) (*n = (intptr_t) ((unsigned int) ((sizetype) (SAVE_EXPR <(ssizetype) arg + -1>) + 1) * 4)) >>>>>; } } it looks like there's tree sharing for a bigger part of the expression... Indeed, between the above and { intptr_t & n [value-expr: this->__n]; intptr_t & n [value-expr: this->__n]; { { typedef struct __lambda3 __lambda3; <<cleanup_point <<< Unknown tree: expr_stmt (void) (*n = (intptr_t) ((unsigned int) ((sizetype) (SAVE_EXPR <(ssizetype) arg + -1>) + 1) * 4)) >>>>>; <<cleanup_point <<< Unknown tree: expr_stmt b(intptr_t, T) [with T = int; intptr_t = int]::<lambda()>::<lambda()>::operator() (&TARGET_EXPR <D.2347, {.__n=n}>) >>>>>; } } } we have shared arg:0 <plus_expr 0x7ffff6dae140 type <integer_type 0x7ffff6c5b000 sizetype> side-effects arg:0 <nop_expr 0x7ffff6da3aa0 type <integer_type 0x7ffff6c5b000 sizetype> side-effects arg:0 <save_expr 0x7ffff6da3a80 type <integer_type 0x7ffff6c5b150 ssizetype> side-effects arg:0 <plus_expr 0x7ffff6daee60> t.ii:3:22 start: t.ii:3:22 finish: t.ii:3:26>> arg:1 <integer_cst 0x7ffff6c3df78 constant 1>>> which is the (sizetype) (SAVE_EXPR <(ssizetype) arg + -1>) + 1 part. <nop_expr 0x7ffff6db30e0 vs. <nop_expr 0x7ffff6da3e00 type <integer_type 0x7ffff6c5b7e0 long unsigned int public unsigned DI size <integer_cst 0x7ffff6c3de70 constant 64> unit-size <integer_cst 0x7ffff6c3de88 constant 8> align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff6c5b7e0 precision:64 min <integer_cst 0x7ffff6c5e150 0> max <integer_cst 0x7ffff6c3e5c0 18446744073709551615> pointer_to_this <pointer_type 0x7ffff6c6b498>> side-effects arg:0 <mult_expr 0x7ffff6dae168 type <integer_type 0x7ffff6c5b000 sizetype public unsigned DI size <integer_cst 0x7ffff6c3de70 64> unit-size <integer_cst 0x7ffff6c3de88 8> align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x7ffff6c5b000 precision:64 min <integer_cst 0x7ffff6c3dea0 0> max <integer_cst 0x7ffff6c3e560 18446744073709551615>> side-effects arg:0 <plus_expr 0x7ffff6dae140 type <integer_type 0x7ffff6c5b000 sizetype> side-effects these nodes are built by c_sizeof_or_alignof_type #4 0x0000000000bde3e2 in c_sizeof_or_alignof_type (loc=283249, type=<array_type 0x7ffff6da95e8 ArrTy>, is_sizeof=true, min_alignof=false, complain=1) at ../../src/trunk/gcc/c-family/c-common.c:3650 3650 value = fold_convert_loc (loc, size_type_node, value); where TYPE_SIZE_UNIT of type is ((sizetype) (SAVE_EXPR <(ssizetype) arg - 1>) + 1) * 4 which is of course asking for trouble :/ In the end this is layout_type doing 2483 if (TYPE_SIZE_UNIT (element)) 2484 TYPE_SIZE_UNIT (type) 2485 = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (element), length); on (sizetype) (SAVE_EXPR <(ssizetype) arg - 1>) + 1 The gimplifier is not set up to do unsharing across functions, so this has to be fixed elsewhere. The particular case could be fixed in c_sizeof_or_alignof_type by doing unshare_expr on TYPE_SIZE_UNIT for all types that might be shared between functions (thus where the gimplifier doesn't take care of unsharing). Or we could make layout_type make sure to wrap all non-constant TYPE_* in a SAVE_EXPR. So the following patch restores the ICE we see in earlier releases. I have audited all possibly variable-size processing in c-common.c. Any comments? Index: gcc/c-family/c-common.c =================================================================== --- gcc/c-family/c-common.c (revision 262624) +++ gcc/c-family/c-common.c (working copy) @@ -3635,7 +3635,8 @@ c_sizeof_or_alignof_type (location_t loc { if (is_sizeof) /* Convert in case a char is more than one unit. */ - value = size_binop_loc (loc, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type), + value = size_binop_loc (loc, CEIL_DIV_EXPR, + unshare_expr (TYPE_SIZE_UNIT (type)), size_int (TYPE_PRECISION (char_type_node) / BITS_PER_UNIT)); else if (min_alignof) @@ -6210,7 +6211,8 @@ fold_offsetof (tree expr, tree type, enu "member %qD", t); return error_mark_node; } - off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t), + off = size_binop_loc (input_location, PLUS_EXPR, + unshare_expr (DECL_FIELD_OFFSET (t)), size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t)) / BITS_PER_UNIT)); break; @@ -6266,7 +6268,8 @@ fold_offsetof (tree expr, tree type, enu } t = convert (sizetype, t); - off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t); + off = size_binop (MULT_EXPR, + unshare_expr (TYPE_SIZE_UNIT (TREE_TYPE (expr))), t); break; case COMPOUND_EXPR: