c++: ICE with aligned member and trivial assign op [PR117512]

build_over_call has:

	  t = build2 (MODIFY_EXPR, void_type_node,
		      build2 (MEM_REF, array_type, arg0, alias_set),
		      build2 (MEM_REF, array_type, arg, alias_set));
	  val = build2 (COMPOUND_EXPR, TREE_TYPE (to), t, to);

which creates an expression that can look like:

  d = MEM <unsigned char[4]> [(struct A *)&TARGET_EXPR <D.2894, foo()]
    = MEM <unsigned char[4]> [(struct A *)(const struct A &) &e],
      TARGET_EXPR <D.2894, foo()>

that is, a COMPOUND_EXPR where a TARGET_EXPR is used twice, and its
address is taken in the left-hand side operand, so it can't be elided.
But set_target_expr_eliding simply recurses on the second operand of
a COMPOUND_EXPR and marks the TARGET_EXPR as eliding.  This then causes
a crash.

cp_build_indirect_ref_1 should not be changing the value category.
While *&TARGET_EXPR is an lvalue, folding it into TARGET_EXPR would
render is a prvalue of class type.

	PR c++/117512

gcc/cp/ChangeLog:

	* typeck.cc (cp_build_indirect_ref_1): Only do the *&e -> e
	folding if the result would be an lvalue.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/alignas23.C: New test.
	* g++.dg/ext/align3.C: New test.
	* g++.dg/ext/align4.C: New test.
	* g++.dg/ext/align5.C: New test.

Reviewed-by: Jason Merrill <jason@redhat.com>
This commit is contained in:
Marek Polacek 2025-03-12 14:49:53 -04:00
parent cfb20f17bd
commit 3dd7b59806
5 changed files with 66 additions and 1 deletions

View file

@ -3870,7 +3870,11 @@ cp_build_indirect_ref_1 (location_t loc, tree ptr, ref_operator errorstring,
return error_mark_node;
}
else if (do_fold && TREE_CODE (pointer) == ADDR_EXPR
&& same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0))))
&& same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0)))
/* Don't let this change the value category. '*&TARGET_EXPR'
is an lvalue, but folding it into 'TARGET_EXPR' would turn
it into a prvalue of class type. */
&& lvalue_p (TREE_OPERAND (pointer, 0)))
/* The POINTER was something like `&x'. We simplify `*&x' to
`x'. */
return TREE_OPERAND (pointer, 0);

View file

@ -0,0 +1,15 @@
// PR c++/117512
// { dg-do compile { target c++11 } }
struct A {
alignas(sizeof (long long)) int b;
~A ();
};
A foo (int);
void
bar ()
{
A e = { 0 };
A d = foo (0) = e;
}

View file

@ -0,0 +1,14 @@
// PR c++/117512
struct A {
__attribute__((aligned)) int b;
~A ();
};
A foo (int);
void
bar ()
{
A e = { 0 };
A d = foo (0) = e;
}

View file

@ -0,0 +1,14 @@
// PR c++/117512
struct __attribute__((aligned (2 * sizeof (int)))) A {
int b;
~A ();
};
A foo (int);
void
bar ()
{
A e = { 0 };
A d = foo (0) = e;
}

View file

@ -0,0 +1,18 @@
// PR c++/117512
// { dg-do run }
struct A {
__attribute__((aligned(2 * sizeof (int)))) int i;
~A() {}
};
A foo () { A a = { 19 }; return a; }
int
main ()
{
A a = { 42 };
A r = foo () = a;
if (r.i != 42)
__builtin_abort ();
}