From: Jakub Jelinek Date: Fri, 10 May 2019 08:19:44 +0000 (+0200) Subject: re PR c++/90383 (GCC generates invalid constexpr copy/move assignment operators for... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b5cbaee240380ba1a3a48fad3810409dea32b888;p=gcc.git re PR c++/90383 (GCC generates invalid constexpr copy/move assignment operators for types with trailing padding. (Again)) PR c++/90383 * tree-inline.h (struct copy_body_data): Add do_not_fold member. * tree-inline.c (remap_gimple_op_r): Avoid folding expressions if id->do_not_fold. (copy_tree_body_r): Likewise. (copy_fn): Set id.do_not_fold to true. * g++.dg/cpp1y/constexpr-90383-1.C: New test. * g++.dg/cpp1y/constexpr-90383-2.C: New test. From-SVN: r271058 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5e30430cbe2..d1b912307c0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2019-05-10 Jakub Jelinek + + PR c++/90383 + * tree-inline.h (struct copy_body_data): Add do_not_fold member. + * tree-inline.c (remap_gimple_op_r): Avoid folding expressions if + id->do_not_fold. + (copy_tree_body_r): Likewise. + (copy_fn): Set id.do_not_fold to true. + 2019-05-10 Martin Liska * config/i386/i386-expand.c (ix86_expand_floorceildf_32): diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 889c08dfce0..0ca0b5a2a2e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2019-05-10 Jakub Jelinek + + PR c++/90383 + * g++.dg/cpp1y/constexpr-90383-1.C: New test. + * g++.dg/cpp1y/constexpr-90383-2.C: New test. + 2019-05-10 Paul Thomas PR fortran/90093 diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-1.C new file mode 100644 index 00000000000..b398331ad7d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-1.C @@ -0,0 +1,15 @@ +// PR c++/90383 +// { dg-do compile { target c++14 } } + +struct alignas(8) A { constexpr A (bool x) : a(x) {} A () = delete; bool a; }; +struct B { A b; }; + +constexpr bool +foo () +{ + B w{A (true)}; + w.b = A (true); + return w.b.a; +} + +static_assert (foo (), ""); diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-2.C new file mode 100644 index 00000000000..a08b1dd6f44 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-90383-2.C @@ -0,0 +1,22 @@ +// PR c++/90383 +// { dg-do run { target c++14 } } +// { dg-options "-O2" } + +extern "C" void abort (); +struct alignas(8) A { constexpr A (bool x) : a(x) {} A () = default; bool a; }; +struct B { A b; }; + +constexpr bool +foo () +{ + B w{A (true)}; + w.b = A (true); + return w.b.a; +} + +int +main () +{ + if (!foo ()) + abort (); +} diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 2d314a7c0c3..35c005ee989 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1101,7 +1101,7 @@ remap_gimple_op_r (tree *tp, int *walk_subtrees, void *data) /* Otherwise, just copy the node. Note that copy_tree_r already knows not to copy VAR_DECLs, etc., so this is safe. */ - if (TREE_CODE (*tp) == MEM_REF) + if (TREE_CODE (*tp) == MEM_REF && !id->do_not_fold) { /* We need to re-canonicalize MEM_REFs from inline substitutions that can happen when a pointer argument is an ADDR_EXPR. @@ -1327,11 +1327,11 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) tree type = TREE_TYPE (*tp); tree ptr = id->do_not_unshare ? *n : unshare_expr (*n); tree old = *tp; - *tp = gimple_fold_indirect_ref (ptr); + *tp = id->do_not_fold ? NULL : gimple_fold_indirect_ref (ptr); if (! *tp) { type = remap_type (type, id); - if (TREE_CODE (ptr) == ADDR_EXPR) + if (TREE_CODE (ptr) == ADDR_EXPR && !id->do_not_fold) { *tp = fold_indirect_ref_1 (EXPR_LOCATION (ptr), type, ptr); @@ -1360,7 +1360,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) return NULL; } } - else if (TREE_CODE (*tp) == MEM_REF) + else if (TREE_CODE (*tp) == MEM_REF && !id->do_not_fold) { /* We need to re-canonicalize MEM_REFs from inline substitutions that can happen when a pointer argument is an ADDR_EXPR. @@ -1432,7 +1432,8 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data) /* Handle the case where we substituted an INDIRECT_REF into the operand of the ADDR_EXPR. */ - if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF) + if (TREE_CODE (TREE_OPERAND (*tp, 0)) == INDIRECT_REF + && !id->do_not_fold) { tree t = TREE_OPERAND (TREE_OPERAND (*tp, 0), 0); if (TREE_TYPE (t) != TREE_TYPE (*tp)) @@ -6370,6 +6371,7 @@ copy_fn (tree fn, tree& parms, tree& result) since front-end specific mechanisms may rely on sharing. */ id.regimplify = false; id.do_not_unshare = true; + id.do_not_fold = true; /* We're not inside any EH region. */ id.eh_lp_nr = 0; diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h index 4c954a0d46f..3ede89ee697 100644 --- a/gcc/tree-inline.h +++ b/gcc/tree-inline.h @@ -113,6 +113,9 @@ struct copy_body_data /* True if trees may not be unshared. */ bool do_not_unshare; + /* True if trees should not be folded during the copying. */ + bool do_not_fold; + /* True if new declarations may not be created during type remapping. */ bool prevent_decl_creation_for_types;