This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PR middle-end/30017 (ICE in C++ size hook)
>
> I think returning NULL_TREE would be OK. You should then make expr_size
> and int_expr_size abort, if they get NULL. But, you could use the hook
> directly while folding, and only do the simplification to a block copy
> if you get a non-NULL value.
OK, I am testing the attached patch that should do the trick
(and in addition it replaces operands_equal_p with tree_int_cst_equal in
the test validating the size as I don't think the size and signedness of
operand should matter. It already has the nice property of reutrning
false when operandis NULL).
Honza
* cp/cp-objcp-common.c (cp_expr_size): Return NULL in the case
size is undefined.
* builtins.c (fold_builtin_memory_op): Check that expr_size match.
* explow.c (expr_size, int_expr_size): Assert that size is non_NULL.
Index: cp/cp-objcp-common.c
===================================================================
*** cp/cp-objcp-common.c (revision 119467)
--- cp/cp-objcp-common.c (working copy)
*************** cp_expr_size (tree exp)
*** 82,104 ****
/* The backend should not be interested in the size of an expression
of a type with both of these set; all copies of such types must go
through a constructor or assignment op. */
! gcc_assert (!TYPE_HAS_COMPLEX_INIT_REF (type)
! || !TYPE_HAS_COMPLEX_ASSIGN_REF (type)
! /* But storing a CONSTRUCTOR isn't a copy. */
! || TREE_CODE (exp) == CONSTRUCTOR
! /* And, the gimplifier will sometimes make a copy of
! an aggregate. In particular, for a case like:
!
! struct S { S(); };
! struct X { int a; S s; };
! X x = { 0 };
!
! the gimplifier will create a temporary with
! static storage duration, perform static
! initialization of the temporary, and then copy
! the result. Since the "s" subobject is never
! constructed, this is a valid transformation. */
! || CP_AGGREGATE_TYPE_P (type));
/* This would be wrong for a type with virtual bases, but they are
caught by the assert above. */
--- 82,105 ----
/* The backend should not be interested in the size of an expression
of a type with both of these set; all copies of such types must go
through a constructor or assignment op. */
! if (!TYPE_HAS_COMPLEX_INIT_REF (type)
! || !TYPE_HAS_COMPLEX_ASSIGN_REF (type)
! /* But storing a CONSTRUCTOR isn't a copy. */
! || TREE_CODE (exp) == CONSTRUCTOR
! /* And, the gimplifier will sometimes make a copy of
! an aggregate. In particular, for a case like:
!
! struct S { S(); };
! struct X { int a; S s; };
! X x = { 0 };
!
! the gimplifier will create a temporary with
! static storage duration, perform static
! initialization of the temporary, and then copy
! the result. Since the "s" subobject is never
! constructed, this is a valid transformation. */
! || CP_AGGREGATE_TYPE_P (type))
! return NULL;
/* This would be wrong for a type with virtual bases, but they are
caught by the assert above. */
Index: builtins.c
===================================================================
*** builtins.c (revision 119467)
--- builtins.c (working copy)
*************** fold_builtin_memory_op (tree arglist, tr
*** 8202,8209 ****
|| !TYPE_SIZE_UNIT (desttype)
|| TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
|| TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST
! || !operand_equal_p (TYPE_SIZE_UNIT (srctype), len, 0)
! || !operand_equal_p (TYPE_SIZE_UNIT (desttype), len, 0))
return 0;
if (get_pointer_alignment (dest, BIGGEST_ALIGNMENT)
--- 8202,8209 ----
|| !TYPE_SIZE_UNIT (desttype)
|| TREE_CODE (TYPE_SIZE_UNIT (srctype)) != INTEGER_CST
|| TREE_CODE (TYPE_SIZE_UNIT (desttype)) != INTEGER_CST
! || !tree_int_cst_equal (TYPE_SIZE_UNIT (srctype), len)
! || !tree_int_cst_equal (TYPE_SIZE_UNIT (desttype), len))
return 0;
if (get_pointer_alignment (dest, BIGGEST_ALIGNMENT)
*************** fold_builtin_memory_op (tree arglist, tr
*** 8218,8223 ****
--- 8218,8225 ----
srcvar = build_fold_indirect_ref (src);
if (TREE_THIS_VOLATILE (srcvar))
return 0;
+ if (!tree_int_cst_equal (lang_hooks.expr_size (srcvar), len))
+ return 0;
/* With memcpy, it is possible to bypass aliasing rules, so without
this check i. e. execute/20060930-2.c would be misoptimized, because
it use conflicting alias set to hold argument for the memcpy call.
*************** fold_builtin_memory_op (tree arglist, tr
*** 8233,8238 ****
--- 8235,8242 ----
destvar = build_fold_indirect_ref (dest);
if (TREE_THIS_VOLATILE (destvar))
return 0;
+ if (!tree_int_cst_equal (lang_hooks.expr_size (destvar), len))
+ return 0;
if (!var_decl_component_p (destvar))
return 0;
Index: explow.c
===================================================================
*** explow.c (revision 119467)
--- explow.c (working copy)
*************** expr_size (tree exp)
*** 245,251 ****
if (TREE_CODE (exp) == WITH_SIZE_EXPR)
size = TREE_OPERAND (exp, 1);
else
! size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (lang_hooks.expr_size (exp), exp);
return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
}
--- 245,255 ----
if (TREE_CODE (exp) == WITH_SIZE_EXPR)
size = TREE_OPERAND (exp, 1);
else
! {
! size = lang_hooks.expr_size (exp);
! gcc_assert (size);
! size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, exp);
! }
return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), 0);
}
*************** int_expr_size (tree exp)
*** 261,267 ****
if (TREE_CODE (exp) == WITH_SIZE_EXPR)
size = TREE_OPERAND (exp, 1);
else
! size = lang_hooks.expr_size (exp);
if (size == 0 || !host_integerp (size, 0))
return -1;
--- 265,274 ----
if (TREE_CODE (exp) == WITH_SIZE_EXPR)
size = TREE_OPERAND (exp, 1);
else
! {
! size = lang_hooks.expr_size (exp);
! gcc_assert (size);
! }
if (size == 0 || !host_integerp (size, 0))
return -1;