Here we crash on a cp_gimplify_expr/TARGET_EXPR assert:
/* A TARGET_EXPR that expresses direct-initialization should have been
elided by cp_gimplify_init_expr. */
gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p));
the TARGET_EXPR in question is created for the NSDMI in:
class Vector { int m_size; };
struct S {
const Vector &vec{};
};
where we first need to create a Vector{} temporary, and then bind the
vec reference to it. The temporary is represented by a TARGET_EXPR
and it cannot be elided. When we create an object of type S, we get
D.2848 = {.vec=(const struct Vector &) &TARGET_EXPR <D.2840, {.m_size=0}>}
where the TARGET_EXPR is no longer direct-initializing anything.
Fixed by not setting TARGET_EXPR_DIRECT_INIT_P in convert_like_internal/ck_user.
PR c++/114854
gcc/cp/ChangeLog:
* call.cc (convert_like_internal) <case ck_user>: Don't set
TARGET_EXPR_DIRECT_INIT_P.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1y/nsdmi-aggr22.C: New test.
&& TYPE_HAS_DEFAULT_CONSTRUCTOR (totype)
&& !processing_template_decl)
{
- bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr);
if (abstract_virtuals_error (NULL_TREE, totype, complain))
return error_mark_node;
expr = build_value_init (totype, complain);
expr = get_target_expr (expr, complain);
if (expr != error_mark_node)
- {
- TARGET_EXPR_LIST_INIT_P (expr) = true;
- TARGET_EXPR_DIRECT_INIT_P (expr) = direct;
- }
+ TARGET_EXPR_LIST_INIT_P (expr) = true;
return expr;
}
--- /dev/null
+// PR c++/114854
+// { dg-do compile { target c++14 } }
+
+struct Vector {
+ int m_size;
+};
+struct S {
+ const Vector &vec{};
+};
+
+void spawn(S);
+void test() { spawn({}); }