With c++14 an NSDMI no longer makes a class type non-aggregate so it's possible to perform aggregate initialization on a class that has an NSDMI, but tsubst_copy() currently ICEs on a use of 'this' in such a situation.
This patch makes tsubst_copy() handle a use of 'this' in an NSDMI as part of an aggregate initialization. In that case current_class_ref will be a PLACEHOLDER_EXPR (as set by get_nsdmi()) and this PLACEHOLDER_EXPR will later get resolved to the true object by replace_placeholders(). Does this patch look OK to commit after testing? gcc/cp/ChangeLog: PR c++/70332 * pt.c (tsubst_copy) [PARM_DECL]: Handle the use of 'this' in an NSDMI that's part of an aggregrate initialization. gcc/testsuite/ChangeLog: PR c++/70332 * g++.dg/cpp1y/nsdmi-aggr5.C: New test. --- gcc/cp/pt.c | 20 ++++++++++++++++---- gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr5.C | 24 ++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr5.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ebfc45b..49ef9d3 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13878,10 +13878,22 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (r == NULL_TREE) { /* We get here for a use of 'this' in an NSDMI. */ - if (DECL_NAME (t) == this_identifier - && current_function_decl - && DECL_CONSTRUCTOR_P (current_function_decl)) - return current_class_ptr; + if (DECL_NAME (t) == this_identifier) + { + /* We're processing an NSDMI as part of a constructor call. */ + if (current_function_decl + && DECL_CONSTRUCTOR_P (current_function_decl)) + return current_class_ptr; + + /* Or as part of an aggregate initialization. */ + if (cp_unevaluated_operand == 0 + && current_class_ref + && TREE_CODE (current_class_ref) == PLACEHOLDER_EXPR) + { + gcc_assert (cxx_dialect >= cxx14); + return current_class_ptr; + } + } /* This can happen for a parameter name used later in a function declaration (such as in a late-specified return type). Just diff --git a/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr5.C b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr5.C new file mode 100644 index 0000000..fe377c3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr5.C @@ -0,0 +1,24 @@ +// PR c++/70332 +// { dg-do run { target c++14 } } + +template <class T> +struct C +{ + T m; + T *n = &m; +}; + +C<int> c { }; + +int +main () +{ + *c.n = 5; + if (c.m != 5) + __builtin_abort (); + + C<int> d { 10 }; + *d.n = *d.n + 1; + if (d.m != 11) + __builtin_abort (); +} -- 2.8.0.rc3.27.gade0865