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

Reply via email to