This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][C] Fix PR39983, more &a vs. &a[0] issues
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 3 May 2009 18:31:20 +0200 (CEST)
- Subject: [PATCH][C] Fix PR39983, more &a vs. &a[0] issues
This fixes PR39983 - a case where the gimplification time fixup of
&a vs. &a[0] doesn't work because we do not gimplify static initializers.
Thus I revisited yet another option of fixing the C frontend for real
instead of fixing things up after-the-fact. The following is what
comes out of this (and x86-64 {,-m32} testing).
The fallout is in builtin folding where the builtins accept void *
typed arguments and in the aliasing warning machinery. Both due
to the fact that int a[25] now decays to (int *)&a instead of &a
(or &a[0] after fixup) just like struct { int a[25]; } x; x.a always
did. Both are latent missed optimizations / warnings anyway.
Bootstrapped and tested on x86_64-unknown-linux-gnu for all C family
languages with {,-m32}.
Are the C frontend changes ok for trunk?
Thanks,
Richard.
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.
Index: gcc/c-typeck.c
===================================================================
*** gcc/c-typeck.c.orig 2009-05-02 21:04:53.000000000 +0200
--- gcc/c-typeck.c 2009-05-02 21:05:40.000000000 +0200
*************** array_to_pointer_conversion (tree exp)
*** 1634,1654 ****
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);
}
--- 1634,1639 ----
Index: gcc/c-gimplify.c
===================================================================
*** gcc/c-gimplify.c.orig 2009-05-02 21:04:53.000000000 +0200
--- gcc/c-gimplify.c 2009-05-02 21:05:40.000000000 +0200
*************** c_gimplify_expr (tree *expr_p, gimple_se
*** 196,215 ****
&& !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;
}
--- 196,200 ----
Index: gcc/testsuite/gcc.c-torture/compile/pr39983.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.c-torture/compile/pr39983.c 2009-05-02 21:05:40.000000000 +0200
***************
*** 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;
+ }
+
Index: gcc/builtins.c
===================================================================
*** gcc/builtins.c.orig 2009-05-02 21:08:22.000000000 +0200
--- gcc/builtins.c 2009-05-02 23:55:20.000000000 +0200
*************** var_decl_component_p (tree var)
*** 8737,8743 ****
static tree
fold_builtin_memset (tree dest, tree c, tree len, tree type, bool ignore)
{
! tree var, ret;
unsigned HOST_WIDE_INT length, cval;
if (! validate_arg (dest, POINTER_TYPE)
--- 8737,8743 ----
static tree
fold_builtin_memset (tree dest, tree c, tree len, tree type, bool ignore)
{
! tree var, ret, etype;
unsigned HOST_WIDE_INT length, cval;
if (! validate_arg (dest, POINTER_TYPE)
*************** fold_builtin_memset (tree dest, tree c,
*** 8764,8778 ****
if (TREE_THIS_VOLATILE (var))
return NULL_TREE;
! if (!INTEGRAL_TYPE_P (TREE_TYPE (var))
! && !POINTER_TYPE_P (TREE_TYPE (var)))
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
|| get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
< (int) length)
return NULL_TREE;
--- 8764,8782 ----
if (TREE_THIS_VOLATILE (var))
return NULL_TREE;
! 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 (etype)) != length
|| get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT
< (int) length)
return NULL_TREE;
*************** fold_builtin_memset (tree dest, tree c,
*** 8794,8801 ****
cval |= (cval << 31) << 1;
}
! ret = build_int_cst_type (TREE_TYPE (var), cval);
! ret = build2 (MODIFY_EXPR, TREE_TYPE (var), var, ret);
if (ignore)
return ret;
--- 8798,8807 ----
cval |= (cval << 31) << 1;
}
! 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;
*************** fold_builtin_memory_op (tree dest, tree
*** 8947,8954 ****
--- 8953,8989 ----
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)
Index: gcc/c-common.c
===================================================================
*** gcc/c-common.c.orig 2009-05-02 22:43:44.000000000 +0200
--- gcc/c-common.c 2009-05-02 22:49:25.000000000 +0200
*************** warn_logical_operator (location_t locati
*** 1761,1766 ****
--- 1761,1770 ----
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)