c++: broken direct-init with trailing array member [PR114439]

can_init_array_with_p is wrongly saying that the init for 's' here:

  struct S {
    int *list = arr;
    int arr[];
  };

  struct A {
    A() {}
    S s[2]{};
  };

is invalid.  But as process_init_constructor_array says, for "non-constant
initialization of trailing elements with no explicit initializers" we use
a VEC_INIT_EXPR wrapped in a TARGET_EXPR, built in process_init_constructor.

Unfortunately we didn't have a test for this scenario so I didn't
realize can_init_array_with_p must handle it.

	PR c++/114439

gcc/cp/ChangeLog:

	* init.cc (can_init_array_with_p): Return true for a VEC_INIT_EXPR
	wrapped in a TARGET_EXPR.

gcc/testsuite/ChangeLog:

	* g++.dg/init/array65.C: New test.
This commit is contained in:
Marek Polacek 2024-03-25 15:32:20 -04:00
parent a89fb3ae7b
commit de0886d480
2 changed files with 43 additions and 1 deletions

View file

@ -950,12 +950,16 @@ can_init_array_with_p (tree type, tree init)
mem-initializers of a constructor. */
if (DECL_DEFAULTED_FN (current_function_decl))
return true;
/* As an extension, we allow copying from a compound literal. */
if (TREE_CODE (init) == TARGET_EXPR)
{
init = TARGET_EXPR_INITIAL (init);
/* As an extension, we allow copying from a compound literal. */
if (TREE_CODE (init) == CONSTRUCTOR)
return CONSTRUCTOR_C99_COMPOUND_LITERAL (init);
/* VEC_INIT_EXPR is used for non-constant initialization of trailing
elements with no explicit initializers. */
else if (TREE_CODE (init) == VEC_INIT_EXPR)
return true;
}
return false;

View file

@ -0,0 +1,38 @@
// PR c++/114439
// { dg-do compile { target c++11 } }
struct S {
int *list = arr;
__extension__ int arr[];
};
struct R {
int *list = arr;
int arr[2];
};
struct A {
A() {}
S s[2]{};
};
struct A2 {
A2() {}
S s[2]{ {}, {} };
};
struct B {
B() {}
R r[2]{};
};
struct B2 {
B2() {}
R r[2]{ {}, {} };
};
struct S1 { S1(); };
struct S2 {
S2() {}
S1 a[1] {};
};