This test fails on Visium because of 3 separate issues.  The first one is 
benign, it's a warning about a pointer mismatch between int32_t* and int*
(On most newlib targets, int32_t is long int instead of int) in the test.
The other 2 are in the code itself (but cancel each other on most targets):
builtin_memref::builtin_memref contains these lines:

      /* Determine the base object or pointer of the reference
         and its constant offset from the beginning of the base.  */
      base = get_addr_base_and_unit_offset (oper, &off);

      HOST_WIDE_INT const_off;
      if (base && off.is_constant (&const_off))
        {
          offrange[0] += const_off;
          offrange[1] += const_off;

          /* Stash the reference for offset validation.  */
          ref = oper;

          /* Also stash the constant offset for offset validation.  */
          tree_code code = TREE_CODE (oper);
          if (code == COMPONENT_REF)
            {
              tree field = TREE_OPERAND (ref, 1);
              tree fldoff = DECL_FIELD_OFFSET (field);
              if (TREE_CODE (fldoff) == INTEGER_CST)
                refoff = const_off + wi::to_offset (fldoff);
            }
        }

The first problem is that DECL_FIELD_OFFSET doesn't return the offset of a 
field, it's byte_position because DECL_FIELD_BIT_OFFSET needs to be taken into 
account:

/* In a FIELD_DECL, this is the offset, in bits, of the first bit of the
   field from DECL_FIELD_OFFSET.  This field may be nonzero even for fields
   that are not bit fields (since DECL_OFFSET_ALIGN may be larger than the
   natural alignment of the field's type).  */
#define DECL_FIELD_BIT_OFFSET(NODE) \
  (FIELD_DECL_CHECK (NODE)->field_decl.bit_offset)

But replacing DECL_FIELD_OFFSET with byte_position is actually worse, because 
the offset of the field is then counted twice in refoff since it is already 
comprised in const_off.  In the end, the correct thing to do is just to equate 
refoff and const_off.

Tested on visium-elf & x86_64-suse-linux, applied on the mainline as obvious.


2018-01-16  Eric Botcazou  <ebotca...@adacore.com>

        * gimple-ssa-warn-restrict.c (builtin_memref::builtin_memref): For an
        ADDR_EXPR, do not count the offset of a COMPONENT_REF twice.


2018-01-16  Eric Botcazou  <ebotca...@adacore.com>

        * c-c++-common/Warray-bounds-3.c (test_memmove_bounds): Fix mismatch.

-- 
Eric Botcazou
Index: gimple-ssa-warn-restrict.c
===================================================================
--- gimple-ssa-warn-restrict.c	(revision 256562)
+++ gimple-ssa-warn-restrict.c	(working copy)
@@ -312,11 +312,11 @@ builtin_memref::builtin_memref (tree exp
   if (TREE_CODE (expr) == ADDR_EXPR)
     {
       poly_int64 off;
-      tree oper = TREE_OPERAND (expr, 0);
+      tree op = TREE_OPERAND (expr, 0);
 
       /* Determine the base object or pointer of the reference
 	 and its constant offset from the beginning of the base.  */
-      base = get_addr_base_and_unit_offset (oper, &off);
+      base = get_addr_base_and_unit_offset (op, &off);
 
       HOST_WIDE_INT const_off;
       if (base && off.is_constant (&const_off))
@@ -325,17 +325,11 @@ builtin_memref::builtin_memref (tree exp
 	  offrange[1] += const_off;
 
 	  /* Stash the reference for offset validation.  */
-	  ref = oper;
+	  ref = op;
 
 	  /* Also stash the constant offset for offset validation.  */
-	  tree_code code = TREE_CODE (oper);
-	  if (code == COMPONENT_REF)
-	    {
-	      tree field = TREE_OPERAND (ref, 1);
-	      tree fldoff = DECL_FIELD_OFFSET (field);
-	      if (TREE_CODE (fldoff) == INTEGER_CST)
-		refoff = const_off + wi::to_offset (fldoff);
-	    }
+	  if (TREE_CODE (op) == COMPONENT_REF)
+	    refoff = const_off;
 	}
       else
 	{
Index: testsuite/c-c++-common/Warray-bounds-3.c
===================================================================
--- testsuite/c-c++-common/Warray-bounds-3.c	(revision 256562)
+++ testsuite/c-c++-common/Warray-bounds-3.c	(working copy)
@@ -199,7 +199,8 @@ void test_memmove_bounds (char *d, const
   T (int,  2, a + SR ( 1, 3), pi, n);
   T (int,  2, a + SR ( 2, 3), pi, n);
 
-  T (int32_t, 2, a + SR ( 3, 4), pi, n);      /* { dg-warning "offset \\\[12, 16] is out of the bounds \\\[0, 8] of object .\[^\n\r]+. with type .int32_t ?\\\[2]." } */
+  const int32_t *pi32 = (const int32_t*)s;
+  T (int32_t, 2, a + SR ( 3, 4), pi32, n);      /* { dg-warning "offset \\\[12, 16] is out of the bounds \\\[0, 8] of object .\[^\n\r]+. with type .int32_t ?\\\[2]." } */
 }
 
 

Reply via email to