if (complain & tf_warning)
warn_for_address_of_packed_member (type, val);
- /* gimplify_arg elides TARGET_EXPRs that initialize a function argument. */
- if (SIMPLE_TARGET_EXPR_P (val))
+ /* gimplify_arg elides TARGET_EXPRs that initialize a function argument,
+ unless the initializer is a CONSTRUCTOR. In that case, we fail to
+ elide the copy anyway. See that function for more information. */
+ if (SIMPLE_TARGET_EXPR_P (val)
+ && TREE_CODE (TARGET_EXPR_INITIAL (val)) != CONSTRUCTOR)
set_target_expr_eliding (val);
return val;
{
tree init = TARGET_EXPR_INITIAL (*arg_p);
if (init
- && !VOID_TYPE_P (TREE_TYPE (init)))
+ && !VOID_TYPE_P (TREE_TYPE (init))
+ /* Currently, due to c++/116015, it is not desirable to
+ strip a TARGET_EXPR whose initializer is a {}. The
+ problem is that if we do elide it, we also have to
+ replace all the occurrences of the slot temporary in the
+ initializer with the temporary created for the argument.
+ But we do not have that temporary yet so the replacement
+ would be quite awkward and it might be needed to resort
+ back to a PLACEHOLDER_EXPR. Note that stripping the
+ TARGET_EXPR wouldn't help anyway, as gimplify_expr would
+ just allocate a temporary to store the CONSTRUCTOR into.
+ (FIXME PR116375.)
+
+ See convert_for_arg_passing for the C++ code that marks
+ the TARGET_EXPR as eliding or not. */
+ && TREE_CODE (init) != CONSTRUCTOR)
*arg_p = init;
}
}
--- /dev/null
+// PR c++/116015
+// { dg-do compile { target c++14 } }
+// { dg-additional-options "-Wno-c++20-extensions" }
+
+struct MatrixLayout {
+ int rows = 0;
+ int outer_stride = rows;
+};
+struct Matrix {
+ Matrix(MatrixLayout m) {}
+};
+struct Widget {
+ int n = 5;
+ Matrix A0{{}};
+ Matrix A1{{n}};
+ Matrix A1_{{.rows = n}};
+ Matrix A2{{n, n}};
+};
+
+int
+main ()
+{
+ Widget w{};
+ Widget w1;
+ Widget w2 = {};
+}