[PATCH] Fix PR58941

Richard Biener rguenther@suse.de
Tue Nov 5 13:24:00 GMT 2013


The following fixes PR58941 - we fail to detect a trailing array
access in get_ref_base_and_extent because, while we remember
the type to check, we still apply an extra offset that confuses us.
Fixed by handling trailing arrays at places we view-convert.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk
sofar.

Richard.

2013-11-05  Richard Biener  <rguenther@suse.de>

	PR middle-end/58941
	* tree-dfa.c (get_ref_base_and_extent): Merge common code
	in MEM_REF and TARGET_MEM_REF handling.  Make sure to
	process trailing array detection before diving into the
	view-converted object (and possibly apply some extra offset).

	* gcc.dg/torture/pr58941.c: New testcase.

Index: gcc/tree-dfa.c
===================================================================
*** gcc/tree-dfa.c	(revision 204346)
--- gcc/tree-dfa.c	(working copy)
*************** get_ref_base_and_extent (tree exp, HOST_
*** 389,395 ****
    double_int bit_offset = double_int_zero;
    HOST_WIDE_INT hbit_offset;
    bool seen_variable_array_ref = false;
-   tree base_type;
  
    /* First get the final access size from just the outermost expression.  */
    if (TREE_CODE (exp) == COMPONENT_REF)
--- 389,394 ----
*************** get_ref_base_and_extent (tree exp, HOST_
*** 420,427 ****
       and find the ultimate containing object.  */
    while (1)
      {
-       base_type = TREE_TYPE (exp);
- 
        switch (TREE_CODE (exp))
  	{
  	case BIT_FIELD_REF:
--- 419,424 ----
*************** get_ref_base_and_extent (tree exp, HOST_
*** 544,550 ****
--- 541,578 ----
  	case VIEW_CONVERT_EXPR:
  	  break;
  
+ 	case TARGET_MEM_REF:
+ 	  /* Via the variable index or index2 we can reach the
+ 	     whole object.  Still hand back the decl here.  */
+ 	  if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR
+ 	      && (TMR_INDEX (exp) || TMR_INDEX2 (exp)))
+ 	    {
+ 	      exp = TREE_OPERAND (TMR_BASE (exp), 0);
+ 	      bit_offset = double_int_zero;
+ 	      maxsize = -1;
+ 	      goto done;
+ 	    }
+ 	  /* Fallthru.  */
  	case MEM_REF:
+ 	  /* We need to deal with variable arrays ending structures such as
+ 	     struct { int length; int a[1]; } x;           x.a[d]
+ 	     struct { struct { int a; int b; } a[1]; } x;  x.a[d].a
+ 	     struct { struct { int a[1]; } a[1]; } x;      x.a[0][d], x.a[d][0]
+ 	     struct { int len; union { int a[1]; struct X x; } u; } x; x.u.a[d]
+ 	     where we do not know maxsize for variable index accesses to
+ 	     the array.  The simplest way to conservatively deal with this
+ 	     is to punt in the case that offset + maxsize reaches the
+ 	     base type boundary.  This needs to include possible trailing
+ 	     padding that is there for alignment purposes.  */
+ 	  if (seen_variable_array_ref
+ 	      && maxsize != -1
+ 	      && (!bit_offset.fits_shwi ()
+ 		  || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+ 		  || (bit_offset.to_shwi () + maxsize
+ 		      == (signed) TREE_INT_CST_LOW
+ 		            (TYPE_SIZE (TREE_TYPE (exp))))))
+ 	    maxsize = -1;
+ 
  	  /* Hand back the decl for MEM[&decl, off].  */
  	  if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
  	    {
*************** get_ref_base_and_extent (tree exp, HOST_
*** 555,595 ****
  		  double_int off = mem_ref_offset (exp);
  		  off = off.lshift (BITS_PER_UNIT == 8
  				    ? 3 : exact_log2 (BITS_PER_UNIT));
- 		  off = off + bit_offset;
- 		  if (off.fits_shwi ())
- 		    {
- 		      bit_offset = off;
- 		      exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
- 		    }
- 		}
- 	    }
- 	  goto done;
- 
- 	case TARGET_MEM_REF:
- 	  /* Hand back the decl for MEM[&decl, off].  */
- 	  if (TREE_CODE (TMR_BASE (exp)) == ADDR_EXPR)
- 	    {
- 	      /* Via the variable index or index2 we can reach the
- 		 whole object.  */
- 	      if (TMR_INDEX (exp) || TMR_INDEX2 (exp))
- 		{
- 		  exp = TREE_OPERAND (TMR_BASE (exp), 0);
- 		  bit_offset = double_int_zero;
- 		  maxsize = -1;
- 		  goto done;
- 		}
- 	      if (integer_zerop (TMR_OFFSET (exp)))
- 		exp = TREE_OPERAND (TMR_BASE (exp), 0);
- 	      else
- 		{
- 		  double_int off = mem_ref_offset (exp);
- 		  off = off.lshift (BITS_PER_UNIT == 8
- 				    ? 3 : exact_log2 (BITS_PER_UNIT));
  		  off += bit_offset;
  		  if (off.fits_shwi ())
  		    {
  		      bit_offset = off;
! 		      exp = TREE_OPERAND (TMR_BASE (exp), 0);
  		    }
  		}
  	    }
--- 583,593 ----
  		  double_int off = mem_ref_offset (exp);
  		  off = off.lshift (BITS_PER_UNIT == 8
  				    ? 3 : exact_log2 (BITS_PER_UNIT));
  		  off += bit_offset;
  		  if (off.fits_shwi ())
  		    {
  		      bit_offset = off;
! 		      exp = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
  		    }
  		}
  	    }
*************** get_ref_base_and_extent (tree exp, HOST_
*** 601,608 ****
  
        exp = TREE_OPERAND (exp, 0);
      }
-  done:
  
    if (!bit_offset.fits_shwi ())
      {
        *poffset = 0;
--- 599,615 ----
  
        exp = TREE_OPERAND (exp, 0);
      }
  
+   /* We need to deal with variable arrays ending structures.  */
+   if (seen_variable_array_ref
+       && maxsize != -1
+       && (!bit_offset.fits_shwi ()
+ 	  || !host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
+ 	  || (bit_offset.to_shwi () + maxsize
+ 	      == (signed) TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))))
+     maxsize = -1;
+ 
+  done:
    if (!bit_offset.fits_shwi ())
      {
        *poffset = 0;
*************** get_ref_base_and_extent (tree exp, HOST_
*** 614,637 ****
  
    hbit_offset = bit_offset.to_shwi ();
  
-   /* We need to deal with variable arrays ending structures such as
-        struct { int length; int a[1]; } x;           x.a[d]
-        struct { struct { int a; int b; } a[1]; } x;  x.a[d].a
-        struct { struct { int a[1]; } a[1]; } x;      x.a[0][d], x.a[d][0]
-        struct { int len; union { int a[1]; struct X x; } u; } x; x.u.a[d]
-      where we do not know maxsize for variable index accesses to
-      the array.  The simplest way to conservatively deal with this
-      is to punt in the case that offset + maxsize reaches the
-      base type boundary.  This needs to include possible trailing padding
-      that is there for alignment purposes.  */
- 
-   if (seen_variable_array_ref
-       && maxsize != -1
-       && (!host_integerp (TYPE_SIZE (base_type), 1)
- 	  || (hbit_offset + maxsize
- 	      == (signed) TREE_INT_CST_LOW (TYPE_SIZE (base_type)))))
-     maxsize = -1;
- 
    /* In case of a decl or constant base object we can do better.  */
  
    if (DECL_P (exp))
--- 621,626 ----
Index: gcc/testsuite/gcc.dg/torture/pr58941.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr58941.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr58941.c	(working copy)
***************
*** 0 ****
--- 1,33 ----
+ /* { dg-do run } */
+ 
+ extern void abort (void);
+ 
+ typedef struct {
+     int msgLength;
+     unsigned char data[1000];
+ } SMsg;
+ 
+ typedef struct {
+     int dummy;
+     int d[0];
+ } SData;
+ 
+ int condition = 3;
+ 
+ int main()
+ {
+   SMsg msg;
+   SData *pData = (SData*)(msg.data);
+   unsigned int i = 0;
+   for (i = 0; i < 1; i++)
+     {
+       pData->d[i] = 0;
+       if(condition & 1)
+ 	pData->d[i] |= 0x55;
+       if(condition & 2)
+ 	pData->d[i] |= 0xaa;
+     }
+   if (pData->d[0] != 0xff)
+     abort ();
+   return 0;
+ }



More information about the Gcc-patches mailing list