Hi! When generic is unshared, we generally don't unshare DECL_VALUE_EXPRs, so those are assumed to be not shared, otherwise as in the testcase we can clear first argument of a COMPOUND_EXPR after it has been gimplified in one use and by that clobbering all others.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2017-02-20 Jakub Jelinek <ja...@redhat.com> PR sanitizer/79589 * decl.c: Include gimplify.h. (cp_finish_decomp): Make sure there is no sharing of trees in between DECL_VALUE_EXPR of decomposition decls. * g++.dg/ubsan/pr79589.C: New test. --- gcc/cp/decl.c.jj 2017-02-17 18:29:21.000000000 +0100 +++ gcc/cp/decl.c 2017-02-20 11:45:55.281636544 +0100 @@ -50,6 +50,7 @@ along with GCC; see the file COPYING3. #include "plugin.h" #include "cilk.h" #include "builtins.h" +#include "gimplify.h" /* Possible cases of bad specifiers type used by bad_specifiers. */ enum bad_spec_place { @@ -7467,7 +7468,7 @@ cp_finish_decomp (tree decl, tree first, { TREE_TYPE (v[i]) = eltype; layout_decl (v[i], 0); - tree t = dexp; + tree t = unshare_expr (dexp); t = build4_loc (DECL_SOURCE_LOCATION (v[i]), ARRAY_REF, eltype, t, size_int (i), NULL_TREE, NULL_TREE); @@ -7486,7 +7487,7 @@ cp_finish_decomp (tree decl, tree first, { TREE_TYPE (v[i]) = eltype; layout_decl (v[i], 0); - tree t = dexp; + tree t = unshare_expr (dexp); t = build1_loc (DECL_SOURCE_LOCATION (v[i]), i ? IMAGPART_EXPR : REALPART_EXPR, eltype, t); @@ -7504,7 +7505,7 @@ cp_finish_decomp (tree decl, tree first, { TREE_TYPE (v[i]) = eltype; layout_decl (v[i], 0); - tree t = dexp; + tree t = unshare_expr (dexp); convert_vector_to_array_for_subscript (DECL_SOURCE_LOCATION (v[i]), &t, size_int (i)); t = build4_loc (DECL_SOURCE_LOCATION (v[i]), ARRAY_REF, @@ -7603,7 +7604,8 @@ cp_finish_decomp (tree decl, tree first, continue; else { - tree tt = finish_non_static_data_member (field, t, NULL_TREE); + tree tt = finish_non_static_data_member (field, unshare_expr (t), + NULL_TREE); if (REFERENCE_REF_P (tt)) tt = TREE_OPERAND (tt, 0); TREE_TYPE (v[i]) = TREE_TYPE (tt); --- gcc/testsuite/g++.dg/ubsan/pr79589.C.jj 2017-02-20 11:51:36.732130221 +0100 +++ gcc/testsuite/g++.dg/ubsan/pr79589.C 2017-02-20 11:52:09.012704729 +0100 @@ -0,0 +1,13 @@ +// PR sanitizer/79589 +// { dg-do compile } +// { dg-options "-fsanitize=undefined -std=c++1z" } + +struct A { char a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r; } a[64]; + +void +foo () +{ + int z = 0; + for (auto & [ b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s ] : a) + z += b + c + d + e + f + g + h + i + j + k + l + m + n + o + p + q + r + s; +} Jakub