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] correct -Wrestrict handling of arrays of arrays (PR 84095)


Testing GCC 8 with recent Linux kernel sources has uncovered
a bug in the handling of arrays of arrays by the -Wrestrict
checker where it fails to take references to different array
elements into consideration, issuing false positives.

The attached patch corrects this mistake.

In addition, to make warnings involving excessive offset bounds
more meaningful (less confusing), I've made a cosmetic change
to constrain them to the bounds of the accessed object.  I've
done this in response to multiple comments indicating that
the warnings are hard to interpret.  This change is meant to
be applied on top of the patch for bug 83698 (submitted mainly
to improve the readability of the offsets):

  https://gcc.gnu.org/ml/gcc-patches/2018-01/msg01488.html

Martin
PR middle-end/84095 - false-positive -Wrestrict warnings for memcpy within array

gcc/ChangeLog:

	PR middle-end/84095
	* gimple-ssa-warn-restrict.c (builtin_memref::builtin_memref): Handle
	inner references.

gcc/testsuite/ChangeLog:

	PR middle-end/84095
	* c-c++-common/Warray-bounds-3.c: Adjust text of expected warnings.
	* c-c++-common/Wrestrict.c: Same.
	* gcc.dg/Wrestrict-6.c: Same.
	* gcc.dg/Wrestrict-8.c: New test.

diff --git a/gcc/gimple-ssa-warn-restrict.c b/gcc/gimple-ssa-warn-restrict.c
index 528eb5b..8bdf928 100644
--- a/gcc/gimple-ssa-warn-restrict.c
+++ b/gcc/gimple-ssa-warn-restrict.c
@@ -311,19 +311,40 @@ builtin_memref::builtin_memref (tree expr, tree size)
 
   if (TREE_CODE (expr) == ADDR_EXPR)
     {
-      poly_int64 off;
       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 (op, &off);
+      /* Determine the base object or pointer of the reference and
+	 the constant bit offset from the beginning of the base.
+	 If the offset has a non-constant component, it will be in
+	 VAR_OFF.  MODE, SIGN, REVERSE, and VOL are write only and
+	 unused here.  */
+      poly_int64 bitsize, bitpos;
+      tree var_off;
+      machine_mode mode;
+      int sign, reverse, vol;
+      base = get_inner_reference (op, &bitsize, &bitpos, &var_off,
+				  &mode, &sign, &reverse, &vol);
+
+      poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
 
       HOST_WIDE_INT const_off;
-      if (base && off.is_constant (&const_off))
+      if (base && bytepos.is_constant (&const_off))
 	{
 	  offrange[0] += const_off;
 	  offrange[1] += const_off;
 
+	  if (var_off)
+	    {
+	      if (TREE_CODE (var_off) == INTEGER_CST)
+		{
+		  offset_int cstoff = wi::to_offset (var_off);
+		  offrange[0] += cstoff;
+		  offrange[1] += cstoff;
+		}
+	      else
+		offrange[1] += maxobjsize;
+	    }
+
 	  /* Stash the reference for offset validation.  */
 	  ref = op;
 
@@ -375,12 +396,6 @@ builtin_memref::builtin_memref (tree expr, tree size)
 	    }
       }
 
-  if (DECL_P (base) && TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
-    {
-      if (offrange[0] < 0 && offrange[1] > 0)
-	offrange[0] = 0;
-    }
-
   if (size)
     {
       tree range[2];
@@ -396,6 +411,29 @@ builtin_memref::builtin_memref (tree expr, tree size)
     }
   else
     sizrange[1] = maxobjsize;
+
+  tree basetype = TREE_TYPE (base);
+  if (DECL_P (base) && TREE_CODE (basetype) == ARRAY_TYPE)
+    {
+      /* If the offset could be in range of the referenced object
+	 constrain its bounds so neither exceeds those of the obhect.  */
+      if (offrange[0] < 0 && offrange[1] > 0)
+	offrange[0] = 0;
+
+      offset_int maxoff = maxobjsize;
+      if (ref && array_at_struct_end_p (ref))
+	;   /* Use the maximum possible offset for last member arrays.  */
+      else if (tree basesize = TYPE_SIZE_UNIT (basetype))
+	maxoff = wi::to_offset (basesize);
+
+      if (offrange[0] >= 0)
+	{
+	  if (offrange[1] < 0)
+	    offrange[1] = offrange[0] <= maxoff ? maxoff : maxobjsize;
+	  else if (offrange[0] <= maxoff && offrange[1] > maxoff)
+	    offrange[1] = maxoff;
+	}
+    }
 }
 
 /* Return error_mark_node if the signed offset exceeds the bounds
diff --git a/gcc/testsuite/c-c++-common/Warray-bounds-3.c b/gcc/testsuite/c-c++-common/Warray-bounds-3.c
index 3445b95..2ee8146 100644
--- a/gcc/testsuite/c-c++-common/Warray-bounds-3.c
+++ b/gcc/testsuite/c-c++-common/Warray-bounds-3.c
@@ -61,7 +61,7 @@ void test_memcpy_bounds (char *d, const char *s, size_t n)
      they appear as large positive in the source.  It would be nice
      if they retained their type but unfortunately that's not how
      it works so be prepared for both in case it even gets fixed.  */
-  T (char, 1, a + UR (3, SIZE_MAX - 1), s, n);   /* { dg-warning "offset \\\[3, -2] is out of the bounds \\\[0, 1] of object" "memcpy" } */
+  T (char, 1, a + UR (3, SIZE_MAX - 1), s, n);   /* { dg-warning "offset \\\[3, -?\[0-9\]+] is out of the bounds \\\[0, 1] of object" "memcpy" } */
 
   /* Verify that invalid offsets into an array of unknown size are
      detected.  */
@@ -226,7 +226,7 @@ T (char, 1, a + SR (-2, -1), s, n);     /* { dg-warning "offset \\\[-2, -1] is o
      they appear as large positive in the source.  It would be nice
      if they retained their type but unfortunately that's not how
      it works so be prepared for both in case it ever gets fixed.  */
-  T (char, 1, a + UR (3, SIZE_MAX), s, n);   /* { dg-warning "offset \\\[3, -1] is out of the bounds \\\[0, 1] of object "  "mempcpy" } */
+  T (char, 1, a + UR (3, SIZE_MAX), s, n);   /* { dg-warning "offset \\\[3, -?\[0-9\]+] is out of the bounds \\\[0, 1] of object "  "mempcpy" } */
 
   /* Verify that invalid offsets into an array of unknown size are
      detected.  */
diff --git a/gcc/testsuite/c-c++-common/Wrestrict.c b/gcc/testsuite/c-c++-common/Wrestrict.c
index 72d9a47..22df9dd 100644
--- a/gcc/testsuite/c-c++-common/Wrestrict.c
+++ b/gcc/testsuite/c-c++-common/Wrestrict.c
@@ -223,7 +223,7 @@ void test_memcpy_range (char *d, size_t sz)
 
   /* Because the size is constant and a power of 2 the following is
      folded too early to detect the overlap.  */
-  T (d + ir, d, 4);               /* { dg-warning "accessing 4 bytes at offsets \\\[2, 3] and 0 overlaps 2 byte at offset 2" "" { xfail *-*-* } } */
+  T (d + ir, d, 4);               /* { dg-warning "accessing 4 bytes at offsets \\\[2, 3] and 0 overlaps 2 byte at offset 2" "memcpy" { xfail *-*-* } } */
   T (d + ir, d, 5);               /* { dg-warning "accessing 5 bytes at offsets \\\[2, 3] and 0 overlaps between 2 and 3 bytes at offset \\\[2, 3]" "memcpy" } */
 
   /* Exercise the full range of size_t.  */
@@ -325,11 +325,11 @@ void test_memcpy_anti_range (char *d, const char *s)
   T (d, d + SAR (0, 3), 1);
   T (d, d + SAR (0, 3), 2);
   T (d, d + SAR (0, 3), 3);
-  T (d, d + SAR (0, 3), DIFF_MAX - 2);   /* { dg-warning "overlaps \[0-9\]+ bytes at offset 2" } */
-  T (d, d + SAR (0, 3), DIFF_MAX - 1);   /* { dg-warning "overlaps \[0-9\]+ bytes at offset 1" } */
-  T (d, d + SAR (0, 3), DIFF_MAX);       /* { dg-warning "overlaps \[0-9\]+ bytes at offset 0" } */
+  T (d, d + SAR (0, 3), DIFF_MAX - 2);   /* { dg-warning "overlaps \[0-9\]+ bytes at offset 2" "memcpy" } */
+  T (d, d + SAR (0, 3), DIFF_MAX - 1);   /* { dg-warning "overlaps \[0-9\]+ bytes at offset 1" "memcpy" } */
+  T (d, d + SAR (0, 3), DIFF_MAX);       /* { dg-warning "overlaps \[0-9\]+ bytes at offset 0" "memcpy" } */
 
-  T (d, d + SAR (0, 3), UR (DIFF_MAX - 2, DIFF_MAX));               /* { dg-warning "accessing \[0-9\]+ or more bytes at offsets 0 and \\\[-?\[0-9\]+, -?\[0-9\]+] overlaps \[0-9\]+ bytes at offset 2" } */
+  T (d, d + SAR (0, 3), UR (DIFF_MAX - 2, DIFF_MAX));               /* { dg-warning "accessing \[0-9\]+ or more bytes at offsets 0 and \\\[-?\[0-9\]+, -?\[0-9\]+] overlaps \[0-9\]+ bytes at offset 2" "memcpy" } */
 
   /* Verify that a size in an anti-range ~[0, N] where N >= PTRDIFF_MAX
      doesn't trigger a warning.  */
@@ -398,8 +398,8 @@ void test_memcpy_range_exceed (char *d, const char *s)
   T (d, s + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[9223372036854775805, 9223372036854775807] overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
   T (d + i, s, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[9223372036854775805, 9223372036854775807] and 0 overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
 #elif __SIZEOF_SIZE_T__ == 4
-  T (d, d + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[2147483645, 2147483647] overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32 } } */
-  T (d + i, d, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[2147483645, 2147483647] and 0 overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32} } */
+  T (d, d + i, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[2147483645, 2147483647] and 0 overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32 } } */
+  T (d + i, d, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[2147483645, 2147483647] and 0 overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32 } } */
 
   T (d, s + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[2147483645, 2147483647] overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32 } } */
   T (d + i, s, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[2147483645, 2147483647] and 0 overlaps 3 bytes at offset 2147483642" "ILP32" { target ilp32} } */
@@ -523,7 +523,7 @@ void test_memcpy_memarrray (struct MemArrays *p)
   T (p->a8, p->a8 + 2, 2);
   T (p->a8, p->a8 + 8, 1);
 
-  T (p->a8, p->a8 + 2, 3);        /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" } */
+  T (p->a8, p->a8 + 2, 3);        /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" "memcpy" } */
 }
 
 /* Exercise the absence of warnings with memmove.  */
@@ -768,13 +768,13 @@ void test_strcpy_range (void)
 
   /* The overlap in the cases below isn't inevitable but it is diagnosed
      because it is possible and so the code is considered unsafe.  */
-  T (8, "", a, a + r);               /* { dg-warning "accessing 1 byte may overlap 1 byte" "strcpy" } */
-  T (8, "0", a + r, a);              /* { dg-warning "accessing 2 bytes may overlap up to 2 bytes" "strcpy" } */
-  T (8, "012", a + r, a);            /* { dg-warning "accessing 4 bytes may overlap up to 4 bytes" "strcpy" } */
+  T (8, "", a, a + r);               /* { dg-warning "accessing 1 byte at offsets 0 and \\\[0, 8] may overlap 1 byte" "strcpy" } */
+  T (8, "0", a + r, a);              /* { dg-warning "accessing 2 bytes at offsets \\\[0, 8] and 0 may overlap up to 2 bytes" "strcpy" } */
+  T (8, "012", a + r, a);            /* { dg-warning "accessing 4 bytes at offsets \\\[0, 8] and 0 may overlap up to 4 bytes" "strcpy" } */
 
-  T (8, "", a, a + r);               /* { dg-warning "accessing 1 byte may overlap" "strcpy" } */
-  T (8, "0", a, a + r);              /* { dg-warning "accessing between 0 and 2 bytes may overlap up to 2 bytes" "strcpy" } */
-  T (8, "012", a, a + r);            /* { dg-warning "accessing between 0 and 4 bytes may overlap up to 4 bytes" "strcpy" } */
+  T (8, "", a, a + r);               /* { dg-warning "accessing 1 byte at offsets 0 and \\\[0, 8] may overlap" "strcpy" } */
+  T (8, "0", a, a + r);              /* { dg-warning "accessing between 0 and 2 bytes at offsets 0 and \\\[0, 8] may overlap up to 2 bytes" "strcpy" } */
+  T (8, "012", a, a + r);            /* { dg-warning "accessing between 0 and 4 bytes at offsets 0 and \\\[0, 8] may overlap up to 4 bytes" "strcpy" } */
 }
 
 /* Exercise strcpy with destination and/or source of unknown lengthu.  */
diff --git a/gcc/testsuite/gcc.dg/Wrestrict-6.c b/gcc/testsuite/gcc.dg/Wrestrict-6.c
index c1bb373..cc7185f 100644
--- a/gcc/testsuite/gcc.dg/Wrestrict-6.c
+++ b/gcc/testsuite/gcc.dg/Wrestrict-6.c
@@ -21,7 +21,7 @@ void warn_2_smax_p2 (void)
 
   ptrdiff_t i = UR (2, DIFF_MAX + (size_t)2);
 
-  strcpy (d, d + i);          /* { dg-warning "accessing between 0 and 4 bytes at offsets 0 and \\\[2, -\[0-9\]+] may overlap up to 2 bytes at offset 2" } */
+  strcpy (d, d + i);          /* { dg-warning "accessing between 0 and 4 bytes at offsets 0 and \\\[2, 7] may overlap up to 2 bytes at offset 2" } */
 
   sink (d);
 }
@@ -47,7 +47,7 @@ void warn_2u_smax_p2 (void)
 
   size_t i = UR (2, DIFF_MAX + (size_t)2);
 
-  strcpy (d, d + i);          /* { dg-warning "accessing between 0 and 4 bytes at offsets 0 and \\\[2, -\[0-9\]+] may overlap up to 2 bytes at offset 2" } */
+  strcpy (d, d + i);          /* { dg-warning "accessing between 0 and 4 bytes at offsets 0 and \\\[2, 7] may overlap up to 2 bytes at offset 2" } */
 
   sink (d);
 }
diff --git a/gcc/testsuite/gcc.dg/Wrestrict-8.c b/gcc/testsuite/gcc.dg/Wrestrict-8.c
new file mode 100644
index 0000000..24946b0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wrestrict-8.c
@@ -0,0 +1,116 @@
+/* PR tree-optimization/84095 - false-positive -Wrestrict warnings for
+   memcpy within array
+   { dg-do compile }
+   { dg-options "-O2 -Wrestrict -ftrack-macro-expansion=0" } */
+
+typedef __SIZE_TYPE__ size_t;
+
+extern void* memcpy (void* restrict, const void* restrict, size_t);
+
+#define T(d, s, n)   memcpy (d, s, n)
+
+struct S1 { char c; } a8_1[8];
+
+void test_1_dim_var (int i, int j)
+{
+  /* Variable destination index and constant source index.  */
+  T (&a8_1[i], &a8_1[0], 1);
+  T (&a8_1[i], &a8_1[0], 2);
+  T (&a8_1[i], &a8_1[0], 3);
+  T (&a8_1[i], &a8_1[0], 4);
+
+  T (&a8_1[i], &a8_1[0], 5);    /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and 0 overlaps between 2 and 5 bytes at offset \\\[0, 3\\\]" } */
+  T (&a8_1[i], &a8_1[0], 6);    /* { dg-warning "accessing 6 bytes at offsets \\\[0, 8] and 0 overlaps between 4 and 6 bytes at offset \\\[0, 2\\\]" } */
+  T (&a8_1[i], &a8_1[0], 7);    /* { dg-warning "accessing 7 bytes at offsets \\\[0, 8] and 0 overlaps between 6 and 7 bytes at offset \\\[0, 1\\\]" } */
+  T (&a8_1[i], &a8_1[0], 8);    /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and 0 overlaps 8 bytes at offset 0" } */
+
+  /* The following is diagnosed by -Warray-bounds when it's enabled
+     rather than by -Wrestrict.  */
+  T (&a8_1[i], &a8_1[0], 9);    /* { dg-warning "accessing 9 bytes at offsets \\\[0, 8] and 0 overlaps 9 bytes at offset 0" } */
+
+  /* Same as above but with constant destination index and variable
+     source index.  */
+  T (&a8_1[0], &a8_1[i], 1);
+  T (&a8_1[0], &a8_1[i], 2);
+  T (&a8_1[0], &a8_1[i], 3);
+  T (&a8_1[0], &a8_1[i], 4);
+
+  T (&a8_1[0], &a8_1[i], 5);    /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[0, 8] overlaps between 2 and 5 bytes at offset \\\[0, 3\\\]" } */
+  T (&a8_1[0], &a8_1[i], 6);    /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[0, 8] overlaps between 4 and 6 bytes at offset \\\[0, 2\\\]" } */
+  T (&a8_1[0], &a8_1[i], 7);    /* { dg-warning "accessing 7 bytes at offsets 0 and \\\[0, 8] overlaps between 6 and 7 bytes at offset \\\[0, 1\\\]" } */
+  T (&a8_1[0], &a8_1[i], 8);    /* { dg-warning "accessing 8 bytes at offsets 0 and \\\[0, 8] overlaps 8 bytes at offset 0" } */
+  T (&a8_1[0], &a8_1[i], 9);    /* { dg-warning "accessing 9 bytes at offsets 0 and \\\[0, 8] overlaps 9 bytes at offset 0" } */
+
+
+  /* Variable destination and source indices.  */
+  T (&a8_1[i], &a8_1[j], 1);
+  T (&a8_1[i], &a8_1[j], 2);
+  T (&a8_1[i], &a8_1[j], 3);
+  T (&a8_1[i], &a8_1[j], 4);
+
+  T (&a8_1[i], &a8_1[j], 5);    /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps between 2 and 5 bytes at offset \\\[0, 3\\\]" } */
+  T (&a8_1[i], &a8_1[j], 6);    /* { dg-warning "accessing 6 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps between 4 and 6 bytes at offset \\\[0, 2\\\]" } */
+  T (&a8_1[i], &a8_1[j], 7);    /* { dg-warning "accessing 7 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps between 6 and 7 bytes at offset \\\[0, 1\\\]" } */
+  T (&a8_1[i], &a8_1[j], 8);    /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps 8 bytes at offset 0" } */
+
+  /* The following is diagnosed by -Warray-bounds when it's enabled
+     rather than by -Wrestrict.  */
+  T (&a8_1[i], &a8_1[j], 9);    /* { dg-warning "accessing 9 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps 9 bytes at offset 0" } */
+}
+
+struct S4 { char a4[4]; } a2_4[2];
+
+void test_2_dim (int i, int j)
+{
+  T (&a2_4[i], &a2_4[0], 1);
+  T (&a2_4[i], &a2_4[0], 4);
+
+  T (&a2_4[i], &a2_4[0], 5);    /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and 0 overlaps between 2 and 5 bytes at offset \\\[0, 3]" } */
+  T (&a2_4[i], &a2_4[0], 6);    /* { dg-warning "accessing 6 bytes at offsets \\\[0, 8] and 0 overlaps between 4 and 6 bytes at offset \\\[0, 2]" } */
+  T (&a2_4[i], &a2_4[0], 7);    /* { dg-warning "accessing 7 bytes at offsets \\\[0, 8] and 0 overlaps between 6 and 7 bytes at offset \\\[0, 1]" } */
+  T (&a2_4[i], &a2_4[0], 8);    /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and 0 overlaps 8 bytes at offset 0" } */
+
+  T (a2_4[i].a4, a2_4[0].a4, 1);
+  T (a2_4[i].a4, a2_4[0].a4, 4);
+
+  T (a2_4[i].a4, a2_4[0].a4, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and 0 overlaps between 2 and 5 bytes at offset \\\[0, 3]" } */
+  T (a2_4[i].a4, a2_4[0].a4, 8);   /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and 0 overlaps 8 bytes at offset 0" } */
+
+  T (a2_4[i].a4, a2_4[j].a4, 1);
+  T (a2_4[i].a4, a2_4[j].a4, 4);
+
+  /* The destination and source offsets printed below ignore the size
+     of the copy and only indicate the values that are valid for each
+     of the destination and source arguments on its own, without
+     considering the size of the overlapping access.  */
+  T (a2_4[i].a4, a2_4[j].a4, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps between 2 and 5 bytes at offset \\\[0, 3]" } */
+  T (a2_4[i].a4, a2_4[j].a4, 8);   /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps 8 bytes at offset 0" } */
+
+  /* Same as above but referencing the first elements of each array.  */
+  T (&a2_4[i].a4[0], &a2_4[j].a4[0], 1);
+  T (&a2_4[i].a4[0], &a2_4[j].a4[0], 4);
+
+  T (&a2_4[i].a4[0], &a2_4[j].a4[0], 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps between 2 and 5 bytes at offset \\\[0, 3]" } */
+  T (&a2_4[i].a4[0], &a2_4[j].a4[0], 8);   /* { dg-warning "accessing 8 bytes at offsets \\\[0, 8] and \\\[0, 8] overlaps 8 bytes at offset 0" } */
+
+  T (&a2_4[i].a4[0], &a2_4[j].a4[1], 3);
+  T (&a2_4[i].a4[0], &a2_4[j].a4[2], 2);
+  T (&a2_4[i].a4[0], &a2_4[j].a4[3], 1);
+}
+
+struct { int i; } a2[2][8];
+
+void test_single_2_dim_major (int i)
+{
+  memcpy (&a2[i], &a2[0], sizeof *a2);   /* { dg-bogus "\\\[-Wrestrict]" } */
+}
+
+void test_single_2_dim_minor (int i)
+{
+  memcpy (&a2[i][0], &a2[0][0], sizeof a2[0][0]);   /* { dg-bogus "\\\[-Wrestrict]" } */
+}
+
+void test_single_2_dim_major_minor (int i, int j)
+{
+  memcpy (&a2[i][j], &a2[0][0], sizeof a2[0][0]);   /* { dg-bogus "\\\[-Wrestrict]" } */
+}

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