The testcase in the PR, while previously ICEing because the C++ FE doesn't properly capture VLA size fields, now ICEs because gimplification introduces SSA uses that appear in a different function than its definition. This happens because there is tree sharing between the functions. For nested functions (which the C++ lambdas are not) such tree sharing ended up being harmless before GCC7 because unnesting resolves all locals with wrong origin to the static chain (and gimplification ordering made sure definitions always appear in the outer function).
The following resolves this by unsharing size expressions in c-common.c I realize that this may end up pessimizing early code since 1:1 tree-sharing with what is gimplified from a DECL_EXPR doesn't share the gimplification result. Another option might be to force gimplification to not generate SSA temporaries when gimplifying size positions but gimplify_one_sizepos oddly enough unshares trees before gimplifying ...(!?) This would need to be removed (see patch after the tested patch below). Bootstrapped / tested on x86_64-unknown-linux-gnu. Richard. 2018-07-13 Richard Biener <rguent...@suse.de> PR c/86216 * c-common.c (c_sizeof_or_alignof_type): Unshare TYPE_SIZE_UNIT. (fold_offsetof): Unshare DECL_FIELD_OFFSET and TYPE_SIZE_UNIT. 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: alternative, untested: diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 6b76d17dbaf..455bc940bac 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -12706,11 +12706,14 @@ gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p) || CONTAINS_PLACEHOLDER_P (expr)) return; - *expr_p = unshare_expr (expr); - /* SSA names in decl/type fields are a bad idea - they'll get reclaimed - if the def vanishes. */ + if the def vanishes. And since tree sharing across functions can + happen for size expressions no temporaries generated by the + gimplification may be SSA names either. */ + bool saved_into_ssa = gimplify_ctxp->into_ssa; + gimplify_ctxp->into_ssa = false; gimplify_expr (expr_p, stmt_p, NULL, is_gimple_val, fb_rvalue, false); + gimplify_ctxp->into_ssa = saved_into_ssa; /* If expr wasn't already is_gimple_sizepos or is_gimple_constant from the FE, ensure that it is a VAR_DECL, otherwise we might handle some decls