From 6081d8994ed1a0aef6b7f5fb34f091faa3580416 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Fri, 26 Mar 2021 09:35:26 +0100 Subject: [PATCH] c++: Fix ICE with nsdmi [PR99705] When adding P0784R7 constexpr new support, we still didn't have P1331R2 implemented and so I had to change also build_vec_delete_1 - instead of having uninitialized tbase temporary later initialized by MODIFY_EXPR I've set the DECL_INITIAL for it - because otherwise it would be rejected during constexpr evaluation which didn't like uninitialized vars. Unfortunately, that change broke the following testcase. The problem is that these temporaries (not just tbase but tbase was the only one with an initializer) are created during NSDMI parsing and current_function_decl is NULL at that point. Later when we clone body of constructors, auto_var_in_fn_p is false for those (as they have NULL DECL_CONTEXT) and so they aren't duplicated, and what is worse, the DECL_INITIAL isn't duplicated either nor processed, and during expansion we ICE because the code from DECL_INITIAL of that var refers to the abstract constructor's PARM_DECL (this) rather than the actual constructor's one. So, either we can just revert those build_vec_delete_1 changes (as done in the second patch - in attachment), or, as the first patch does, we can copy the temporaries during bot_manip like we copy the temporaries of TARGET_EXPRs. To me that looks like a better fix because e.g. if break_out_of_target_exprs is called for the same NSDMI multiple times, sharing the temporaries looks just wrong to me. If the temporaries are declared as BIND_EXPR_VARS of some BIND_EXPR (which is the case of the tbase variable built by build_vec_delete_1 and is the only way how the DECL_INITIAL can be walked by *walk_tree*), then we need to copy it also in the BIND_EXPR BIND_EXPR_VARS chain, other temporaries (those that don't need DECL_INITIAL) often have just DECL_EXPR and no corresponding BIND_EXPR. Note, ({ }) are rejected in nsdmis, so all we run into are temporaries the FE creates artificially. 2021-03-26 Jakub Jelinek PR c++/99705 * tree.c (bot_manip): Remap artificial automatic temporaries mentioned in DECL_EXPR or in BIND_EXPR_VARS. * g++.dg/cpp0x/new5.C: New test. --- gcc/cp/tree.c | 42 +++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/new5.C | 21 ++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/new5.C diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 3acb6433b64..8c4bd156d3f 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -3128,6 +3128,48 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_) } return NULL_TREE; } + if (TREE_CODE (*tp) == DECL_EXPR + && VAR_P (DECL_EXPR_DECL (*tp)) + && DECL_ARTIFICIAL (DECL_EXPR_DECL (*tp)) + && !TREE_STATIC (DECL_EXPR_DECL (*tp))) + { + tree t; + splay_tree_node n + = splay_tree_lookup (target_remap, + (splay_tree_key) DECL_EXPR_DECL (*tp)); + if (n) + t = (tree) n->value; + else + { + t = create_temporary_var (TREE_TYPE (DECL_EXPR_DECL (*tp))); + DECL_INITIAL (t) = DECL_INITIAL (DECL_EXPR_DECL (*tp)); + splay_tree_insert (target_remap, + (splay_tree_key) DECL_EXPR_DECL (*tp), + (splay_tree_value) t); + } + copy_tree_r (tp, walk_subtrees, NULL); + DECL_EXPR_DECL (*tp) = t; + if (data.clear_location && EXPR_HAS_LOCATION (*tp)) + SET_EXPR_LOCATION (*tp, input_location); + return NULL_TREE; + } + if (TREE_CODE (*tp) == BIND_EXPR && BIND_EXPR_VARS (*tp)) + { + copy_tree_r (tp, walk_subtrees, NULL); + for (tree *p = &BIND_EXPR_VARS (*tp); *p; p = &DECL_CHAIN (*p)) + { + gcc_assert (VAR_P (*p) && DECL_ARTIFICIAL (*p) && !TREE_STATIC (*p)); + tree t = create_temporary_var (TREE_TYPE (*p)); + DECL_INITIAL (t) = DECL_INITIAL (*p); + DECL_CHAIN (t) = DECL_CHAIN (*p); + splay_tree_insert (target_remap, (splay_tree_key) *p, + (splay_tree_value) t); + *p = t; + } + if (data.clear_location && EXPR_HAS_LOCATION (*tp)) + SET_EXPR_LOCATION (*tp, input_location); + return NULL_TREE; + } /* Make a copy of this node. */ t = copy_tree_r (tp, walk_subtrees, NULL); diff --git a/gcc/testsuite/g++.dg/cpp0x/new5.C b/gcc/testsuite/g++.dg/cpp0x/new5.C new file mode 100644 index 00000000000..b5a9ca282b5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/new5.C @@ -0,0 +1,21 @@ +// PR c++/99705 +// { dg-do compile { target c++11 } } + +template +struct C +{ + C () { f (); } + ~C () {} + static void f () {} +}; + +struct X +{ + X (); + int n = 10; + C *p = new C[n]; +}; + +X::X () +{ +}