re PR c/39983 (ICE: type mismatch in address expression)
2009-05-03 Richard Guenther <rguenther@suse.de> PR c/39983 * c-typeck.c (array_to_pointer_conversion): Do not built ADDR_EXPRs of arrays of pointer-to-element type. * c-gimplify.c (c_gimplify_expr): Revert change fixing up wrong ADDR_EXPRs after-the-fact. * c-common.c (strict_aliasing_warning): Strip pointer conversions for obtaining the original type. * builtins.c (fold_builtin_memset): Handle array types. (fold_builtin_memory_op): Handle folded POINTER_PLUS_EXPRs and array types * gcc.c-torture/compile/pr39983.c: New testcase. From-SVN: r147083
This commit is contained in:
parent
16c337707b
commit
255d3827b4
7 changed files with 80 additions and 36 deletions
|
@ -1,3 +1,16 @@
|
|||
2009-05-03 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR c/39983
|
||||
* c-typeck.c (array_to_pointer_conversion): Do not built
|
||||
ADDR_EXPRs of arrays of pointer-to-element type.
|
||||
* c-gimplify.c (c_gimplify_expr): Revert change fixing
|
||||
up wrong ADDR_EXPRs after-the-fact.
|
||||
* c-common.c (strict_aliasing_warning): Strip pointer
|
||||
conversions for obtaining the original type.
|
||||
* builtins.c (fold_builtin_memset): Handle array types.
|
||||
(fold_builtin_memory_op): Handle folded POINTER_PLUS_EXPRs
|
||||
and array types
|
||||
|
||||
2009-05-03 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR middle-end/23329
|
||||
|
|
|
@ -8737,7 +8737,7 @@ var_decl_component_p (tree var)
|
|||
static tree
|
||||
fold_builtin_memset (tree dest, tree c, tree len, tree type, bool ignore)
|
||||
{
|
||||
tree var, ret;
|
||||
tree var, ret, etype;
|
||||
unsigned HOST_WIDE_INT length, cval;
|
||||
|
||||
if (! validate_arg (dest, POINTER_TYPE)
|
||||
|
@ -8764,15 +8764,19 @@ fold_builtin_memset (tree dest, tree c, tree len, tree type, bool ignore)
|
|||
if (TREE_THIS_VOLATILE (var))
|
||||
return NULL_TREE;
|
||||
|
||||
if (!INTEGRAL_TYPE_P (TREE_TYPE (var))
|
||||
&& !POINTER_TYPE_P (TREE_TYPE (var)))
|
||||
etype = TREE_TYPE (var);
|
||||
if (TREE_CODE (etype) == ARRAY_TYPE)
|
||||
etype = TREE_TYPE (etype);
|
||||
|
||||
if (!INTEGRAL_TYPE_P (etype)
|
||||
&& !POINTER_TYPE_P (etype))
|
||||
return NULL_TREE;
|
||||
|
||||
if (! var_decl_component_p (var))
|
||||
return NULL_TREE;
|
||||
|
||||
length = tree_low_cst (len, 1);
|
||||
if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (var))) != length
|
||||
if (GET_MODE_SIZE (TYPE_MODE (etype)) != length
|
||||
|| get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
|
||||
< (int) length)
|
||||
return NULL_TREE;
|
||||
|
@ -8794,8 +8798,10 @@ fold_builtin_memset (tree dest, tree c, tree len, tree type, bool ignore)
|
|||
cval |= (cval << 31) << 1;
|
||||
}
|
||||
|
||||
ret = build_int_cst_type (TREE_TYPE (var), cval);
|
||||
ret = build2 (MODIFY_EXPR, TREE_TYPE (var), var, ret);
|
||||
ret = build_int_cst_type (etype, cval);
|
||||
var = build_fold_indirect_ref (fold_convert (build_pointer_type (etype),
|
||||
dest));
|
||||
ret = build2 (MODIFY_EXPR, etype, var, ret);
|
||||
if (ignore)
|
||||
return ret;
|
||||
|
||||
|
@ -8947,8 +8953,37 @@ fold_builtin_memory_op (tree dest, tree src, tree len, tree type, bool ignore, i
|
|||
Perhaps we ought to inherit type from non-VOID argument here? */
|
||||
STRIP_NOPS (src);
|
||||
STRIP_NOPS (dest);
|
||||
/* As we fold (void *)(p + CST) to (void *)p + CST undo this here. */
|
||||
if (TREE_CODE (src) == POINTER_PLUS_EXPR)
|
||||
{
|
||||
tree tem = TREE_OPERAND (src, 0);
|
||||
STRIP_NOPS (tem);
|
||||
if (tem != TREE_OPERAND (src, 0))
|
||||
src = build1 (NOP_EXPR, TREE_TYPE (tem), src);
|
||||
}
|
||||
if (TREE_CODE (dest) == POINTER_PLUS_EXPR)
|
||||
{
|
||||
tree tem = TREE_OPERAND (dest, 0);
|
||||
STRIP_NOPS (tem);
|
||||
if (tem != TREE_OPERAND (dest, 0))
|
||||
dest = build1 (NOP_EXPR, TREE_TYPE (tem), dest);
|
||||
}
|
||||
srctype = TREE_TYPE (TREE_TYPE (src));
|
||||
if (srctype
|
||||
&& TREE_CODE (srctype) == ARRAY_TYPE)
|
||||
{
|
||||
srctype = TREE_TYPE (srctype);
|
||||
STRIP_NOPS (src);
|
||||
src = build1 (NOP_EXPR, build_pointer_type (srctype), src);
|
||||
}
|
||||
desttype = TREE_TYPE (TREE_TYPE (dest));
|
||||
if (desttype
|
||||
&& TREE_CODE (desttype) == ARRAY_TYPE)
|
||||
{
|
||||
desttype = TREE_TYPE (desttype);
|
||||
STRIP_NOPS (dest);
|
||||
dest = build1 (NOP_EXPR, build_pointer_type (desttype), dest);
|
||||
}
|
||||
if (!srctype || !desttype
|
||||
|| !TYPE_SIZE_UNIT (srctype)
|
||||
|| !TYPE_SIZE_UNIT (desttype)
|
||||
|
|
|
@ -1762,6 +1762,10 @@ warn_logical_operator (location_t location, enum tree_code code,
|
|||
bool
|
||||
strict_aliasing_warning (tree otype, tree type, tree expr)
|
||||
{
|
||||
/* Strip pointer conversion chains and get to the correct original type. */
|
||||
STRIP_NOPS (expr);
|
||||
otype = TREE_TYPE (expr);
|
||||
|
||||
if (!(flag_strict_aliasing
|
||||
&& POINTER_TYPE_P (type)
|
||||
&& POINTER_TYPE_P (otype)
|
||||
|
|
|
@ -196,20 +196,5 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
|
|||
&& !warn_init_self)
|
||||
TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
|
||||
|
||||
/* The C frontend is the only one producing &ARRAY with pointer-to-element
|
||||
type. This is invalid in gimple, so produce a properly typed
|
||||
ADDR_EXPR instead and wrap a conversion around it. */
|
||||
if (code == ADDR_EXPR
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (*expr_p, 0))) == ARRAY_TYPE
|
||||
&& !lang_hooks.types_compatible_p (TREE_TYPE (TREE_TYPE (*expr_p)),
|
||||
TREE_TYPE (TREE_OPERAND (*expr_p, 0))))
|
||||
{
|
||||
tree type = TREE_TYPE (*expr_p);
|
||||
TREE_TYPE (*expr_p)
|
||||
= build_pointer_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0)));
|
||||
*expr_p = build1 (NOP_EXPR, type, *expr_p);
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
return GS_UNHANDLED;
|
||||
}
|
||||
|
|
|
@ -1634,21 +1634,6 @@ array_to_pointer_conversion (tree exp)
|
|||
if (TREE_CODE (exp) == INDIRECT_REF)
|
||||
return convert (ptrtype, TREE_OPERAND (exp, 0));
|
||||
|
||||
if (TREE_CODE (exp) == VAR_DECL)
|
||||
{
|
||||
/* We are making an ADDR_EXPR of ptrtype. This is a valid
|
||||
ADDR_EXPR because it's the best way of representing what
|
||||
happens in C when we take the address of an array and place
|
||||
it in a pointer to the element type. */
|
||||
adr = build1 (ADDR_EXPR, ptrtype, exp);
|
||||
if (!c_mark_addressable (exp))
|
||||
return error_mark_node;
|
||||
TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
|
||||
return adr;
|
||||
}
|
||||
|
||||
/* This way is better for a COMPONENT_REF since it can
|
||||
simplify the offset for a component. */
|
||||
adr = build_unary_op (EXPR_LOCATION (exp), ADDR_EXPR, exp, 1);
|
||||
return convert (ptrtype, adr);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2009-05-03 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR c/39983
|
||||
* gcc.c-torture/compile/pr39983.c: New testcase.
|
||||
|
||||
2009-05-03 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* gcc.dg/c99-complex-3.c: New test.
|
||||
|
|
17
gcc/testsuite/gcc.c-torture/compile/pr39983.c
Normal file
17
gcc/testsuite/gcc.c-torture/compile/pr39983.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
typedef struct {
|
||||
int *p;
|
||||
} *A;
|
||||
|
||||
extern const int a[1];
|
||||
extern const int b[1];
|
||||
|
||||
void foo()
|
||||
{
|
||||
A x;
|
||||
A y;
|
||||
static const int * const c[] = { b };
|
||||
|
||||
x->p = (int*)c[0];
|
||||
y->p = (int*)a;
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue