This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]