(root)/
gcc-13.2.0/
gcc/
testsuite/
c-c++-common/
Wrestrict.c
       1  /* PR 35503 - Warn about restricted pointers
       2     { dg-do compile }
       3     { dg-options "-O2 -Wrestrict -ftrack-macro-expansion=0" } */
       4  
       5  #include "../gcc.dg/range.h"
       6  
       7  #if !defined LINE
       8  # define LINE 0
       9  #endif
      10  
      11  #if __cplusplus
      12  #  define restrict __restrict
      13  extern "C" {
      14  #endif
      15  
      16  extern void* memcpy (void* restrict, const void* restrict, size_t);
      17  extern void* mempcpy (void* restrict, const void* restrict, size_t);
      18  extern void* memmove (void*, const void*, size_t);
      19  
      20  extern char* stpcpy (char* restrict, const char* restrict);
      21  
      22  extern char* strcat (char* restrict, const char* restrict);
      23  extern char* strcpy (char* restrict, const char* restrict);
      24  extern char* strncpy (char* restrict, const char* restrict, size_t);
      25  
      26  #if __cplusplus
      27  }   /* extern "C" */
      28  #endif
      29  
      30  void sink (void*, ...);
      31  
      32  struct MemArrays
      33  {
      34    char a8[8];
      35    char a16[16];
      36    char ax[];
      37  };
      38  
      39  /* Exercise memcpy with constant or known arguments.  */
      40  
      41  void test_memcpy_cst (void *d, const void *s)
      42  {
      43  #undef T
      44  #define T(dst, src, n) do {				\
      45      if (!LINE || LINE == __LINE__) {			\
      46        char a[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };	\
      47        void *pd = (dst);					\
      48        const void *ps = (src);				\
      49        memcpy (pd, ps, (n));				\
      50        sink (a, pd, ps);					\
      51      }							\
      52    } while (0)
      53  
      54    T (a, a, 0);
      55  
      56    /* This isn't detected because memcpy calls with size of 1 are
      57       intentionally folded into safe copies equivalent to memmove,
      58       regardless of the target (larger power-of-2 copies may or
      59       may not be folded depending on the target -- see non_strict_align
      60       below, for example).
      61       It's marked xfail only because there is value in detecting such
      62       invalid calls for portability, and as a reminder of why it isn't
      63       diagnosed.  */
      64    T (a, a + 1, 1);           /* { dg-warning "\\\[-Wrestrict" "memcpy with a small power of 2 size" { xfail *-*-* } } */
      65    T (a, a + 3, 3);
      66    T (a, a + 3, 5);           /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
      67  
      68    {
      69      char a[3][7];
      70      sink (a);
      71  
      72      void *d = a[0];
      73      const void *s = a[1];
      74      memcpy (d, s, sizeof a[0]);
      75      sink (&a);
      76  
      77      d = a[0];
      78      s = a[1];
      79      /* The following is only diagnosed for sizes that aren't small
      80         powers of 2.  */
      81      memcpy (d, s, sizeof a[0] + 2); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
      82      sink (&a);
      83  
      84      d = a[0] + 1;
      85      s = a[1] + 1;
      86      memcpy (d, s, sizeof a[0]);
      87      sink (&a);
      88  
      89      d = a[0] + 1;
      90      s = a[1] + 1;
      91      memcpy (d, s, sizeof a[0] + 2); /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
      92      sink (&a);
      93    }
      94  
      95    {
      96      struct {
      97        char a[7];
      98        char b[7];
      99        char c[7];
     100      } x;
     101      sink (&x);
     102  
     103      void *d = x.a;
     104      const void *s = x.b;
     105      memcpy (d, s, sizeof x.a);
     106      sink (&x);
     107  
     108      d = x.a + 4;
     109      s = x.b;
     110      memcpy (d, s, sizeof x.a);    /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
     111      sink (&x);
     112  
     113      d = x.a + 6;
     114      s = x.b;
     115      memcpy (d, s, 1);
     116      sink (&x);
     117  
     118      d = x.a + 7;
     119      s = x.b;
     120      memcpy (d, s, 3);             /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
     121      sink (&x);
     122  
     123      d = x.a + 7;
     124      s = x.b + 1;
     125      memcpy (d, s, 1);
     126      sink (&x);
     127  
     128      d = x.b;
     129      s = x.a;
     130      memcpy (d, s, 1);
     131      sink (&x);
     132  
     133      d = x.b;
     134      s = x.a;
     135      memcpy (d, s, sizeof x.b);
     136      sink (&x);
     137  
     138      d = x.b + 2;
     139      s = x.a + 1;
     140      memcpy (d, s, sizeof x.b);
     141      sink (&x);
     142  
     143      d = x.b + 2;
     144      s = x.a + 2;
     145      memcpy (d, s, sizeof x.b);
     146      sink (&x);
     147  
     148      d = x.b + 2;
     149      s = x.a + 3;
     150      memcpy (d, s, sizeof x.b);    /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
     151      sink (&x);
     152    }
     153  
     154    {
     155  #undef T
     156  #define T(dst, src, n) do {				\
     157      if (!LINE || LINE == __LINE__) {			\
     158        char a[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };	\
     159        memcpy ((dst), (src), (n));			\
     160        sink (a);						\
     161      }							\
     162      } while (0)
     163  
     164      /* Verify the offset of the overlap is the same regardless of whether
     165         the destination is at lower or higher offset than the source.  */
     166      T (a, a + 1, 5);             /* { dg-warning "accessing 5 bytes at offsets 0 and 1 overlaps 4 bytes at offset 1" "memcpy" } */
     167      T (a, a + 2, 5);             /* { dg-warning "accessing 5 bytes at offsets 0 and 2 overlaps 3 bytes at offset 2" "memcpy" } */
     168      T (a, a + 3, 5);             /* { dg-warning "accessing 5 bytes at offsets 0 and 3 overlaps 2 bytes at offset 3" "memcpy" } */
     169  
     170      T (a + 1, a, 5);             /* { dg-warning "accessing 5 bytes at offsets 1 and 0 overlaps 4 bytes at offset 1" "memcpy" } */
     171      T (a + 2, a, 5);             /* { dg-warning "accessing 5 bytes at offsets 2 and 0 overlaps 3 bytes at offset 2" "memcpy" } */
     172      T (a + 3, a, 5);             /* { dg-warning "accessing 5 bytes at offsets 3 and 0 overlaps 2 bytes at offset 3" "memcpy" } */
     173    }
     174  }
     175  
     176  /* Exercise memcpy with destination or source offset or size in
     177     a determinate range.  */
     178  
     179  void test_memcpy_range (char *d, size_t sz)
     180  {
     181  #undef T
     182  #define T(dst, src, n) do {			\
     183      if (!LINE || LINE == __LINE__) {		\
     184        char a[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };	\
     185        void *pd = (dst);					\
     186        const void *ps = (src);				\
     187        memcpy (pd, ps, (n));				\
     188        sink (a, pd, ps);					\
     189      }							\
     190    } while (0)
     191  
     192    ptrdiff_t ir = SR (2, 3);
     193    T (a + ir, a, 0);
     194    T (a + ir, a, 1);
     195    T (a + ir, a, 2);
     196    T (a + ir, a, 3);
     197    /* The following fails because the size is a small power of 2.  */
     198    T (a + ir, a, 4);               /* { dg-warning "accessing 4 bytes at offsets \\\[2, 3] and 0 overlaps between 1 and 2 bytes at offset \(\\\[3, 2]|\\\[2, 3]\)" "pr79220" { xfail non_strict_align } } */
     199    T (a + ir, a, 5);               /* { dg-warning "accessing 5 bytes at offsets \\\[2, 3] and 0 overlaps between 2 and 3 bytes at offset \\\[2, 3]" "memcpy" } */
     200  
     201    T (d + ir, d, 0);
     202    T (d + ir, d, 1);
     203    T (d + ir, d, 2);
     204    T (d + ir, d, 3);
     205    T (d + ir, d, 4);               /* { dg-warning "accessing 4 bytes at offsets \\\[2, 3] and 0 overlaps between 1 and 2 bytes at offset \\\[2, 3]" "pr79220" { xfail non_strict_align } } */
     206    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" } */
     207  
     208    /* Because the size is constant and a power of 2 the following is
     209       folded too early to detect the overlap.  */
     210    T (d + ir, d, 4);               /* { dg-warning "accessing 4 bytes at offsets \\\[2, 3] and 0 overlaps between 1 and 2 bytes at offset \\\[2, 3]" "pr79220" { xfail non_strict_align } } */
     211    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" } */
     212  
     213    /* Exercise the full range of size_t.  */
     214    T (d + sz, d, 0);
     215    T (d + sz, d, 1);
     216    T (d + sz, d, 9);
     217  
     218    T (a, a + 1, SR (0, 1));
     219    T (a, a + 1, SR (0, 2));
     220    T (a, a + 1, SR (1, 2));
     221    T (a, a + 1, SR (2, 3));         /* { dg-warning "accessing between 2 and 3 bytes at offsets 0 and 1 overlaps between 1 and 2 bytes at offset 1" "memcpy" } */
     222    T (a, a + 1, UR (2, DIFF_MAX + (size_t)1));  /* { dg-warning "accessing 2 or more bytes at offsets 0 and 1 overlaps 1 or more bytes at offset 1" "memcpy" } */
     223    T (a, a + 1, UR (2, SIZE_MAX - 1));        /* { dg-warning "accessing 2 or more bytes at offsets 0 and 1 overlaps 1 or more bytes at offset 1" "memcpy" } */
     224    T (a, a + 2, SR (2, 3));
     225    T (a, a + 2, SR (3, 4));         /* { dg-warning "accessing between 3 and 4 bytes at offsets 0 and 2 overlaps between 1 and 2 bytes at offset 2" "memcpy" } */
     226    T (a, a + 3, SR (3, 4));
     227    T (a, a + 3, SR (4, 5));         /* { dg-warning "accessing between 4 and 5 bytes at offsets 0 and 3 overlaps between 1 and 2 bytes at offset 3" "memcpy" } */
     228    T (a, a + 3, SR (5, 6));         /* { dg-warning "accessing between 5 and 6 bytes at offsets 0 and 3 overlaps between 2 and 3 bytes at offset 3" "memcpy" } */
     229  
     230    T (a + 1, a, SR (0, 1));
     231    T (a + 1, a, SR (0, 2));
     232    T (a + 1, a, SR (1, 2));
     233    T (a + 1, a, SR (2, 3));         /* { dg-warning "accessing between 2 and 3 bytes at offsets 1 and 0 overlaps between 1 and 2 bytes at offset 1" "memcpy" } */
     234    T (a + 1, a, UR (2, DIFF_MAX + (size_t)1)); /* { dg-warning "accessing 2 or more bytes at offsets 1 and 0 overlaps 1 or more bytes at offset 1" "memcpy" } */
     235    T (a + 1, a, UR (2, SIZE_MAX - 1)); /* { dg-warning "accessing 2 or more bytes at offsets 1 and 0 overlaps 1 or more bytes at offset 1" "memcpy" } */
     236    T (a + 2, a, SR (2, 3));
     237    T (a + 2, a, SR (3, 4));         /* { dg-warning "accessing between 3 and 4 bytes at offsets 2 and 0 overlaps between 1 and 2 bytes at offset 2" "memcpy" } */
     238    T (a + 3, a, SR (3, 4));
     239    T (a + 3, a, SR (4, 5));         /* { dg-warning "accessing between 4 and 5 bytes at offsets 3 and 0 overlaps between 1 and 2 bytes at offset 3" "memcpy" } */
     240    T (a + 3, a, SR (5, 6));         /* { dg-warning "accessing between 5 and 6 bytes at offsets 3 and 0 overlaps between 2 and 3 bytes at offset 3" "memcpy" } */
     241  
     242    ir = SR (2, 5);
     243    T (a, a + ir, 4);
     244    T (a, a + ir, 5);                /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[2, 5] overlaps between 1 and 3 bytes at offset \\\[2, 4]" "memcpy" } */
     245    T (a, a + ir, 6);                /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[2, 5] overlaps between 3 and 4 bytes at offset \\\[2, 3]" "memcpy" } */
     246  
     247    /* Below, there are two possible regions for the source of the copy:
     248         1) one just before the high end of the address space that's 3
     249            bytes large close to the lower end of the offset range, and
     250         2) another in the [DIFF_MIN, -8] range from D and so at least
     251            8 bytes in size
     252       A copy from (1) overlaps but one from (2) does not.  Verify that
     253       the copy is not diagnosed.  (This test case was reduced from
     254       the Linux kernel.) */
     255    T (d, d + UR (DIFF_MAX - 3, SIZE_MAX - 7), 5);
     256    T (d, d + UR (DIFF_MAX - 3, SIZE_MAX - 7), 6);
     257    T (d, d + UR (DIFF_MAX - 3, SIZE_MAX - 7), 7);
     258    T (d, d + UR (DIFF_MAX - 3, SIZE_MAX - 7), 9);
     259  
     260    T (d + UR (DIFF_MAX - 3, SIZE_MAX - 7), d, 5);
     261    T (d + UR (DIFF_MAX - 3, SIZE_MAX - 7), d, 6);
     262    T (d + UR (DIFF_MAX - 3, SIZE_MAX - 7), d, 7);
     263    T (d + UR (DIFF_MAX - 3, SIZE_MAX - 7), d, 9);
     264  
     265    {
     266      /* Create an offset in the range [0, -1].  */
     267      size_t o = sz << 1;
     268  #if __SIZEOF_SIZE_T__ < 4
     269      T (d, d + o, 1234);
     270      T (d + o, d, 2345);
     271  #else
     272      T (d, d + o, 12345);
     273      T (d + o, d, 23456);
     274  #endif
     275    }
     276  
     277    /* Exercise memcpy with both destination and source pointer offsets
     278       in some known range.  */
     279    size_t n = UR (3, 4);
     280    T (a + SR (1, 3), a + SR (1, 3), n);  /* { dg-warning "accessing between 3 and 4 bytes at offsets \\\[1, 3] and \\\[1, 3] overlaps between 1 and 4 bytes at offset \\\[1, 3]" "memcpy" } */
     281  
     282    /* This is an interesting case:
     283         memcpy (a + i, a + j, n) with i in [1, 3], j in [2, 3], and n in [3, 4]
     284       we have the following possibilities ('^' denotesthe destination offset,
     285       '*' marks the overlap, and '?' is the possible overlap for large n):
     286         i j | a = 012345678   SIZ  OFF (size and offset of the overlap)
     287         1 2 |      ^**?       2-3   2
     288         1 3 |      ^ *?       1-2   3
     289         2 2 |       ***?      3-4   2
     290         2 3 |       ^**?      2-3   3
     291         3 3 |        ***?     3-4   3
     292       There are two ways to present the results:
     293       1) overlaps between 1 and 4 bytes at offset [2, 3]
     294       2) overlaps between 1 and 4 bytes at offset 2.  */
     295    T (a + SR (1, 3), a + SR (2, 3), n);  /* { dg-warning "accessing between 3 and 4 bytes at offsets \\\[1, 3] and \\\[2, 3] overlaps between 1 and 4 bytes at offset \\\[2, 3]" "memcpy" } */
     296    T (a + SR (1, 3), a + SR (3, 4), n);
     297  
     298    T (a + SR (2, 3), a + SR (3, 4), n);  /* { dg-warning "accessing between 3 and 4 bytes at offsets \\\[2, 3] and \\\[3, 4] overlaps between 1 and 4 bytes at offset \\\[3, 4]" "memcpy" } */
     299  
     300    T (a + SR (1, 3), a + SR (4, 5), n);
     301    T (a + SR (2, 3), a + SR (4, 5), n);
     302    T (a + SR (3, 4), a + SR (4, 5), n);  /* { dg-warning "accessing between 3 and 4 bytes at offsets \\\[3, 4] and \\\[4, 5] overlaps between 1 and 4 bytes at offset \\\[4, 5]" "memcpy" } */
     303  
     304    /* Exercise the full range of size_t.  */
     305    T (d, d + sz, 0);
     306    T (d, d + sz, 1);
     307    T (d, d + sz, 9);
     308  }
     309  
     310  /* Exercise memcpy with offset and/or size in a determinate anti-range.  */
     311  
     312  void test_memcpy_anti_range (char *d, const char *s)
     313  {
     314    T (d, d + SAR (0, 3), 1);
     315    T (d, d + SAR (0, 3), 2);
     316    T (d, d + SAR (0, 3), 3);
     317    T (d, d + SAR (0, 3), DIFF_MAX - 2);   /* { dg-warning "overlaps \[0-9\]+ bytes at offset 2" "memcpy" } */
     318    T (d, d + SAR (0, 3), DIFF_MAX - 1);   /* { dg-warning "overlaps \[0-9\]+ bytes at offset 1" "memcpy" } */
     319    T (d, d + SAR (0, 3), DIFF_MAX);       /* { dg-warning "overlaps \[0-9\]+ bytes at offset 0" "memcpy" } */
     320  
     321    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" } */
     322  
     323    /* Verify that a size in an anti-range ~[1, N] where N >= PTRDIFF_MAX - 2
     324       doesn't trigger a warning.
     325       With ~[1, PTRDIFF_MAX - 1] the difference between the just-past-the-end
     326       pointer to A and A for char A[PTRDIFF_MAX] wouldn't be representable in
     327       ptrdiff_t.  Since such a large object cannot exist, so the size of
     328       the region must be zero.  */
     329    T (d, s, UAR (1, DIFF_MAX / 2 - 1));
     330    T (d, s, UAR (1, DIFF_MAX - 1));
     331    T (d, s, UAR (1, DIFF_MAX));
     332    T (d, s, UAR (1, SIZE_MAX - 1));
     333    T (d, s, UAR (1, SIZE_MAX));
     334  }
     335  
     336  /* Verify calls to memcpy() where the combination of offsets in some
     337     range and size is such that either overlap is unavoidable or one
     338     or both offsets would exceed the maximum size of an object
     339     (DIFF_MAX).  */
     340  
     341  void test_memcpy_range_exceed (char *d, const char *s)
     342  {
     343    /* Verify offset and size both in some range.  The memcpy checking
     344       is less strict than that of string functions like strncpy and
     345       doesn't trigger unless the overlap is certain.  The following
     346       overlaps for (r == 3 && n > 3) but not, for example, for
     347       (r == 4 && n == 4), and so it's not diagnosed.  */
     348    ptrdiff_t i = SR (3, 5);
     349    size_t n = UR (4, 6);
     350  
     351    T (a, a + i, n);
     352    T (a + i, a, n);
     353    /* Ditto for objects of unknown sizes.  */
     354    T (d, d + i, n);
     355    T (d + i, d, n);
     356  
     357    /* Verify that a warning is issued for a copy between two regions
     358       whose aggregate size would exceed DIFF_MAX if it were to not
     359       overlap.  */
     360    T (d, s, DIFF_MAX / 2);
     361    T (d, s, DIFF_MAX / 2 + 1);   /* { dg-warning "overlaps 1 byte" "memcpy" } */
     362    T (d, s, DIFF_MAX / 2 + 2);   /* { dg-warning "overlaps 3 bytes" "memcpy" } */
     363    T (d, s, DIFF_MAX / 2 + 3);   /* { dg-warning "overlaps 5 bytes" "memcpy" } */
     364  
     365    i = SR (DIFF_MAX - 2, DIFF_MAX);
     366  
     367    /* Verify a warning for an out-of-bounds offset range and constant
     368       size addition.  */
     369    T (d, d + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
     370    T (d + i, d, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 0 overlaps 1 byte" "memcpy" } */
     371  
     372    T (d + 1, d + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 1 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
     373    T (d + i, d + 1, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 1 overlaps 1 byte" "memcpy" } */
     374  
     375    /* Verify that the warnings above are independent of whether the source
     376       and destination are known to be based on the same object.  */
     377    T (d, s + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
     378    T (d + i, s, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 0 overlaps 1 byte" "memcpy" } */
     379  
     380    T (d + 1, s + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 1 and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 byte" "memcpy" } */
     381    T (d + i, s + 1, 3);   /* { dg-warning "accessing 3 bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and 1 overlaps 1 byte" "memcpy" } */
     382  
     383  #if __SIZEOF_SIZE_T__ == 8
     384    /* Verfiy the offset and size computation is correct.  The overlap
     385       offset mentioned in the warning plus sthe size of the access must
     386       not exceed DIFF_MAX.  */
     387    T (d, d + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[9223372036854775805, 9223372036854775807] overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
     388    T (d + i, d, 5);   /* { dg-warning "accessing 5 bytes at offsets \\\[9223372036854775805, 9223372036854775807] and 0 overlaps 3 bytes at offset 9223372036854775802" "LP64" { target lp64 } } */
     389  
     390    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 } } */
     391    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 } } */
     392  #elif __SIZEOF_SIZE_T__ == 4
     393    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 } } */
     394    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 } } */
     395  
     396    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 } } */
     397    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} } */
     398  #endif
     399  
     400    ptrdiff_t j = SR (DIFF_MAX - 9, DIFF_MAX - 1);
     401    i = SR (DIFF_MAX - 5, DIFF_MAX - 1);
     402    n = UR (4, 5);
     403    T (d + i, d + j, n);
     404  
     405    n = UR (4, DIFF_MAX - 1);
     406    T (d + i, d + j, n);
     407  
     408    n = UR (4, SIZE_MAX - 1);
     409    T (d + i, d + j, n);
     410  
     411    j = SR (DIFF_MAX - 8, DIFF_MAX - 1);
     412    T (d + i, d + j, n);
     413  
     414    j = SR (DIFF_MAX - 7, DIFF_MAX - 1);
     415    T (d + i, d + j, n);   /* { dg-warning "accessing 4( or more)? bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps" "memcpy" } */
     416  
     417    j = SR (DIFF_MAX - 6, DIFF_MAX - 1);
     418    T (d + i, d + j, n);   /* { dg-warning "accessing 4( or more)? bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps" "memcpy" } */
     419  
     420    n = UR (3, DIFF_MAX);
     421    T (d + i, d + j, n);
     422  
     423    j = SR (DIFF_MAX - 6, DIFF_MAX - 1);
     424    T (d + i, d + j, n);
     425  
     426    j = SR (DIFF_MAX - 5, DIFF_MAX - 1);
     427    T (d + i, d + j, n);   /* { dg-warning "accessing 3 or more bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 or more bytes" "memcpy" } */
     428  
     429    j = SR (DIFF_MAX - 4, DIFF_MAX - 1);
     430    T (d + i, d + j, n);   /* { dg-warning "accessing 3 or more bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 or more bytes" "memcpy" } */
     431  
     432    j = SR (DIFF_MAX - 2, DIFF_MAX - 1);
     433    T (d + i, d + j, n);   /* { dg-warning "accessing 3 or more bytes at offsets \\\[\[0-9\]+, \[0-9\]+] and \\\[\[0-9\]+, \[0-9\]+] overlaps 1 or more bytes" "memcpy" } */
     434  }
     435  
     436  /* Exercise memcpy with destination and source of unknown size.  */
     437  
     438  void test_memcpy_var (char *d, const char *s)
     439  {
     440    size_t n = unsigned_value ();
     441  
     442    /* Since no copying takes place no warning should be issued.  */
     443    memcpy (d, d, 0);
     444    sink (d);
     445  
     446    /* The following overlaps if n is greater than 1.  */
     447    s = d + 1;
     448    memcpy (d, s, n);
     449    sink (d);
     450  
     451    s = d + n;
     452    memcpy (d, s, n);
     453    sink (d);
     454  
     455    s = d + signed_value ();
     456    memcpy (d, s, unsigned_value ());
     457    sink (d);
     458  
     459    s = d + 3;
     460    n = 1;
     461    memcpy (d, s, n);
     462    sink (d);
     463  
     464    s = d + 3;
     465    n = 2;
     466    memcpy (d, s, n);
     467    sink (d);
     468  
     469    s = d + 3;
     470    n = 3;
     471    memcpy (d, s, n);
     472    sink (d);
     473  
     474    s = d + 3;
     475    n = 4;
     476    memcpy (d, s, n);               /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
     477    sink (d);
     478  
     479    s = d + 5;
     480    n = 7;
     481    memcpy (d, s, n);               /* { dg-warning "\\\[-Wrestrict" "memcpy" } */
     482  }
     483  
     484  
     485  void test_memcpy_memarrray (struct MemArrays *p)
     486  {
     487  #undef T
     488  #define T(dst, src, n) do {			\
     489      if (!LINE || LINE == __LINE__) {		\
     490        void *pd = (dst);				\
     491        const void *ps = (src);			\
     492        memcpy (pd, ps, (n));			\
     493        sink (pd, ps);				\
     494      }						\
     495    } while (0)
     496  
     497    T (p->a8, p->a8, 0);
     498    T (p->a8, p->a8 + 1, 1);
     499    T (p->a8, p->a8 + 2, 2);
     500    T (p->a8, p->a8 + 8, 1);
     501  
     502    T (p->a8, p->a8 + 2, 3);        /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" "memcpy" } */
     503  }
     504  
     505  /* Exercise the absence of warnings with memmove.  */
     506  
     507  void test_memmove (void)
     508  {
     509    {
     510      char d[7];
     511      sink (d);
     512  
     513      const void *s = d;
     514      memmove (d, s, 7);
     515      sink (d);
     516  
     517      s = d + 1;
     518      memmove (d, s, 6);
     519      sink (d);
     520  
     521      s = d + 2;
     522      memmove (d + 1, s, 5);
     523      sink (d);
     524    }
     525  }
     526  
     527  /* Exercise strcat with constant or known arguments.  */
     528  
     529  void test_strcat_cst (const char *s)
     530  {
     531  #undef T
     532  #define T(init, dst, src) do {				\
     533      if (!LINE || LINE == __LINE__) {			\
     534        char a[9] = init;					\
     535        char *pd = (dst);					\
     536        const char *ps = (src);				\
     537        strcat (pd, ps);					\
     538        sink (a, pd, ps);					\
     539      }							\
     540    } while (0)
     541  
     542    T ("0",   a, a);                /* { dg-warning "source argument is the same as destination" "strcat" } */
     543    T ("01",  a, a);                /* { dg-warning "source argument is the same as destination" "strcat" } */
     544    T ("012", a, a);                /* { dg-warning "source argument is the same as destination" "strcat" } */
     545    /* The 3 bytes "12\0" being appended to "012" overwrite the final NUL.  */
     546    T ("012", a, a + 1);            /* { dg-warning "accessing 3 bytes at offsets 0 and 1 overlaps 1 byte at offset 3" "strcat" } */
     547    T ("012", a, a + 2);            /* { dg-warning "accessing 2 bytes at offsets 0 and 2 overlaps 1 byte at offset 3" "strcat" } */
     548    /* The nul copied from a[3] to a[3] overwrites itself so this is
     549       diagnosed.  */
     550    T ("012", a, a + 3);            /* { dg-warning "accessing 1 byte at offsets 0 and 3 overlaps 1 byte at offset 3" "strcat" } */
     551  
     552    T ("012", a, a + 4);
     553    T ("012", a, a + 5);
     554    T ("012", a, a + 6);
     555    T ("012", a, a + 7);
     556    T ("012", a, a + 8);
     557  
     558    T ("0",   a + 1, a);            /* { dg-warning "accessing 2 bytes at offsets 1 and 0 overlaps 1 byte at offset 1" "strcat" } */
     559    T ("0",   a + 2, a);
     560  
     561    /* The first of the two offsets in the diagnostic for strcat is that
     562       of the first write into the destination, not that of the initial
     563       read from it to compute its length.  */
     564    T ("01",  a + 1, a);            /* { dg-warning "accessing 3 bytes at offsets 1 and 0 overlaps 1 byte at offset 2" "strcat" } */
     565    T ("01",  a + 2, a);            /* { dg-warning "accessing 3 bytes at offsets 2 and 0 overlaps 1 byte at offset 2" "strcat" } */
     566    T ("01",  a + 3, a);
     567  
     568    T ("012", a + 1, a);            /* { dg-warning "accessing 4 bytes at offsets 1 and 0 overlaps 1 byte at offset 3" "strcat" } */
     569    T ("012", a + 2, a);            /* { dg-warning "accessing 4 bytes at offsets 2 and 0 overlaps 1 byte at offset 3" "strcat" } */
     570    T ("012", a + 3, a);            /* { dg-warning "accessing 4 bytes at offsets 3 and 0 overlaps 1 byte at offset 3 " "strcat" } */
     571    T ("012", a + 4, a);
     572    T ("012", a + 5, a);
     573  
     574    /* Verify that the obviously benign cases below aren't diagnosed.  */
     575    T ("012",      a, "012");
     576    T ("012",      a, s);
     577    T ("01234567", a, s);
     578  }
     579  
     580  /* Exercise strcat with destination and source of unknown length.  */
     581  
     582  void test_strcat_var (char *d, const char *s)
     583  {
     584  #undef T
     585  #define T(dst, src) do {				\
     586      if (!LINE || LINE == __LINE__) {			\
     587        char *pd = (dst);					\
     588        const char *ps = (src);				\
     589        strcat (pd, ps);					\
     590        sink (pd, ps);					\
     591      }							\
     592    } while (0)
     593  
     594    T (d, d);                       /* { dg-warning "source argument is the same as destination" "strcat" } */
     595    T (d, d + 1);                   /* { dg-warning "accessing 2 or more bytes at offsets 0 and 1 may overlap 1 byte" "strcat" } */
     596    T (d, d + 2);                   /* { dg-warning "accessing 3 or more bytes at offsets 0 and 2 may overlap 1 byte at offset 2" "strcat" } */
     597    T (d, d + 999);                 /* { dg-warning "accessing 1000 or more bytes at offsets 0 and 999 may overlap 1 byte at offset 999" "strcat" } */
     598  
     599    /* The source string must be at least 100 bytes in length for the copy
     600       below to overlap.  */
     601    T (d, d + -99);                 /* { dg-warning "accessing 100 or more bytes at offsets 0 and -99 may overlap 1 byte" "strcat" } */
     602  
     603    size_t n = unsigned_value ();
     604  
     605    T (d + n, d + n);                       /* { dg-warning "\\\[-Wrestrict" "strcat" } */
     606  
     607    /* Verify that the obviously benign cases below aren't diagnosed.  */
     608    T (d, "012");
     609    T (d + 1, "0123");
     610    T (d + n, "01234");
     611    T (d, s);
     612    T (d + 1, s);
     613    T (d + n, s);
     614  
     615    /* Since the offset is unknown the overlap in the call below, while
     616       possible, is certainly not inevitable.  Conservatively, it should
     617       not be diagnosed.  For safety, an argument for diagnosing can be
     618       made.  It's a judgment call, partly determined by the effort and
     619       complexity of treating this case differently from other similar
     620       to it.   */
     621    T (d, d + n); /* { dg-warning "may overlap" "strcat" } */
     622  }
     623  
     624  /* Exercise strcpy with constant or known arguments.  */
     625  
     626  void test_strcpy_cst (ptrdiff_t i)
     627  {
     628  #undef T
     629  #define T(init, dst, src) do {				\
     630      if (!LINE || LINE == __LINE__) {			\
     631        char a[8] = init;					\
     632        char *pd = (dst);					\
     633        const char *ps = (src);				\
     634        strcpy (pd, ps);					\
     635        sink (a, pd, ps);					\
     636      }							\
     637    } while (0)
     638  
     639    T ("012", a, a);                /* { dg-warning "source argument is the same as destination" "strcpy" } */
     640    T ("012", a, a + 1);            /* { dg-warning "accessing 3 bytes at offsets 0 and 1 overlaps 2 bytes at offset 1" "strcpy" } */
     641    T ("012", a, a + 2);
     642    T ("012", a, a + 3);
     643    T ("012", a, a + sizeof a);     /* { dg-warning "\\\[-Wstringop-overread" "pr81437" } */
     644  
     645    /* The terminating nul written to d[2] overwrites s[0].  */
     646    T ("0123", a, a + 2);           /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" } */
     647  
     648    /* The '5' copied from s[2] to d[2] overwrites s[0].  */
     649    T ("01234", a, a + 2);          /* { dg-warning "accessing 4 bytes at offsets 0 and 2 overlaps 2 bytes at offset 2" } */
     650  
     651    /* This happens to be safe in GCC but it's still wrong.  */
     652    T ("012", a, a);                /* { dg-warning "source argument is the same as destination" "strcpy" } */
     653  
     654    T ("012", a + 1, a);            /* { dg-warning "accessing 4 bytes at offsets 1 and 0 overlaps 3 bytes at offset 1" "strcpy" } */
     655    T ("012", a + 2, a);            /* { dg-warning "accessing 4 bytes at offsets 2 and 0 overlaps 2 bytes at offset 2" "strcpy" } */
     656    T ("012", a + 3, a);            /* { dg-warning "accessing 4 bytes at offsets 3 and 0 overlaps 1 byte at offset 3" "strcpy" } */
     657    T ("012", a + 4, a);
     658    /* The following doesn't overlap but it triggers -Wstringop-overflow
     659       for writing past the end.  */
     660    T ("012", a + sizeof a, a);     /* { dg-warning "\\\[-Wstringop-overflow" } */
     661  }
     662  
     663  /* Exercise strcpy with constant or known arguments offset by a range.
     664     The tests verify the use of the lower bound of the range which is
     665     more restrictive than using the upper bound for positive values.  */
     666  
     667  void test_strcpy_range (void)
     668  {
     669  #undef T
     670  #define T(N, init, dst, src)			\
     671    do {						\
     672      if (!LINE || LINE == __LINE__) {		\
     673        char a[N] = init;				\
     674        char *pd = (dst);				\
     675        const char *ps = (src);			\
     676        strcpy (pd, ps);				\
     677        sink (a, pd, ps);				\
     678      }						\
     679    } while (0)
     680  
     681    ptrdiff_t r;
     682  
     683    r = SR (0, 1);
     684    T (8, "0", a + r, a);   /* { dg-warning "accessing between 1 and 2 bytes at offsets \\\[0, 1] and 0 overlaps up to 2 bytes at offset \\\[0, 1]" "strcpy" { xfail *-*-*} } */
     685  
     686    r = SR (2, 5);
     687    T (8, "01",  a + r, a);            /* { dg-warning "accessing 3 bytes at offsets \\\[2, 5] and 0 may overlap 1 byte at offset 2" } */
     688    T (8, "012", a + r, a);            /* { dg-warning "accessing 4 bytes at offsets \\\[2, 5] and 0 may overlap up to 2 bytes at offset \\\[2, 3]" "strcpy" } */
     689  
     690    /* The highest offset to which to copy without overflowing the 8-byte
     691       destination is 3 and that overlaps 2 bytes.  */
     692    T (8, "0123", a + r, a);           /* { dg-warning "accessing 5 bytes at offsets \\\[2, 5] and 0 overlaps between 2 and 3 bytes at offset \\\[2, 3]" "strcpy" } */
     693  
     694    /* With a 9-byte destination the highest offset is 4 and that still
     695       overlaps 1 byte (the final NUL).  */
     696    T (9, "0123", a + r, a);           /* { dg-warning "accessing 5 bytes at offsets \\\[2, 5] and 0 overlaps between 1 and 3 bytes at offset \\\[2, 4]" "strcpy" } */
     697  
     698    /* With a 10-byte buffer it's possible to copy all 5 bytes without
     699       overlap at (a + 5).  Copying at offsets 2 through 4 overflows
     700       between 3 and 1 bytes, respectively.  */
     701    T (10, "0123", a + r, a);          /* { dg-warning "accessing 5 bytes at offsets \\\[2, 5] and 0 may overlap up to 3 bytes at offset \\\[2, 4]" "strcpy" } */
     702  
     703  
     704    r  = SR (3, 4);
     705    T (8, "01",  a + r, a);
     706    T (8, "012", a + r, a);            /* { dg-warning "accessing 4 bytes at offsets \\\[3, 4] and 0 may overlap 1 byte at offset 3" "strcpy" } */
     707  
     708    /* The highest offset to which to copy without overflowing the 8-byte
     709       destination is 3 and that overlaps 2 bytes.  */
     710    T (8, "0123", a + r, a);           /* { dg-warning "accessing 5 bytes at offsets \\\[3, 4] and 0 overlaps 2 bytes at offset 3" "strcpy" } */
     711  
     712    /* With a 9-byte destination the highest offset is 4 and that still
     713       overlaps 1 byte (the final NUL).  */
     714    T (9, "0123", a + r, a);           /* { dg-warning "accessing 5 bytes at offsets \\\[3, 4] and 0 overlaps between 1 and 2 bytes at offset \\\[3, 4]" "strcpy" } */
     715  
     716    /* With a 10-byte buffer it's possible to copy all 5 bytes without
     717       overlap at (a + 5).  Copying at offsets 2 through 4 overflows
     718       between 3 and 1 bytes, respectively.  */
     719    T (10, "0123", a + r, a);          /* { dg-warning "accessing 5 bytes at offsets \\\[3, 4] and 0 overlaps between 1 and 2 bytes at offset \\\[3, 4]" "strcpy" } */
     720  
     721    T (8, "01",     a, a + r);
     722    T (8, "012",    a, a + r);
     723    T (8, "0123",   a, a + r);
     724    T (8, "01234",  a, a + r);
     725  
     726    /* With the smaller offset of 3 the final NUL definitely overlaps
     727       the '4' at a[3], but with the larger offset of 4 there is no
     728       overlap, so the warning is a "may overlap" and the size of
     729       the overlap is 1 byte.  */
     730    T (8, "012345", a, a + r);         /* { dg-warning "accessing between 3 and 4 bytes at offsets 0 and \\\[3, 4] may overlap 1 byte at offset 3" "strcpy" } */
     731    T (8, "0123456", a, a + r);        /* { dg-warning "accessing between 4 and 5 bytes at offsets 0 and \\\[3, 4] may overlap up to 2 bytes at offset \\\[3, 4]" "strcpy" } */
     732  
     733    r = SR (3, DIFF_MAX - 3);
     734    T (8, "01",  a + r, a);
     735  
     736    /* The accesses below might trigger either
     737         -Wrestrict: accessing 4 bytes at offsets [3, \[0-9\]+] and 0 may overlap 1 byte at offset 3
     738       or
     739         -Wstringop-overflow: writing 4 bytes into a region of size 0
     740       Either of the two is appropriate.  */
     741    T (8, "012", a + r, a);            /* { dg-warning "\\\[-Wrestrict|-Wstringop-overflow" } */
     742  
     743    r = SR (DIFF_MAX - 2, DIFF_MAX - 1);
     744    T (8, "012", a + r, a);            /* { dg-warning "\\\[-Wrestrict|-Wstringop-overflow" } */
     745  
     746    /* Exercise the full range of ptrdiff_t.  */
     747    r = signed_value ();
     748  
     749    /* The overlap in the cases below isn't inevitable but it is diagnosed
     750       because it is possible and so the code is considered unsafe.  */
     751    T (8, "", a, a + r);               /* { dg-warning "accessing 1 byte at offsets 0 and \\\[0, 8] may overlap 1 byte" "strcpy" } */
     752    T (8, "0", a + r, a);              /* { dg-warning "accessing 2 bytes at offsets \\\[0, 8] and 0 may overlap up to 2 bytes" "strcpy" } */
     753    T (8, "012", a + r, a);            /* { dg-warning "accessing 4 bytes at offsets \\\[0, 8] and 0 may overlap up to 4 bytes" "strcpy" } */
     754  
     755    T (8, "", a, a + r);               /* { dg-warning "accessing 1 byte at offsets 0 and \\\[0, 8] may overlap" "strcpy" } */
     756    T (8, "0", a, a + r);              /* { dg-warning "accessing between 1 and 2 bytes at offsets 0 and \\\[0, 8] may overlap up to 2 bytes" "strcpy" } */
     757    T (8, "012", a, a + r);            /* { dg-warning "accessing between 1 and 4 bytes at offsets 0 and \\\[0, 8] may overlap up to 4 bytes" "strcpy" } */
     758  }
     759  
     760  /* Exercise strcpy with destination and/or source of unknown lengthu.  */
     761  
     762  void test_strcpy_var (char *d, const char *s)
     763  {
     764  #undef T
     765  #define T(dst, src) do {			\
     766      if (!LINE || LINE == __LINE__) {			\
     767        char *pd = (dst);					\
     768        const char *ps = (src);				\
     769        strcpy (pd, ps);					\
     770        sink (pd, ps);					\
     771      }							\
     772    } while (0)
     773  
     774    T (d, s);
     775  
     776    T (d, &d[0]);                   /* { dg-warning "source argument is the same as destination" "strcpy" } */
     777    T (&d[0], d);                   /* { dg-warning "source argument is the same as destination" "strcpy" } */
     778  
     779    s = d;
     780    T (d, s);                       /* { dg-warning "source argument is the same as destination" "strcpy" } */
     781  
     782    /* The following overlaps if *s is not nul.  It arguably should be
     783       diagnosed.  */
     784    T (d, d + 1);
     785  
     786    /* The following overlaps if strlen (d) is greater than 1.  Like
     787       the above, it possibly should be diagnosed too.  */
     788    int r = SR (2, 3);
     789    T (d, d + r);
     790  
     791    /* The following overlaps only if strlen (s + n) >= n so it's not
     792       diagnosed.  */
     793    s = d + signed_value ();
     794    T (d, s);
     795  }
     796  
     797  /* Exercise strncpy with constant or known arguments.  */
     798  
     799  void test_strncpy_cst (void)
     800  {
     801  #undef T
     802  #define T(init, dst, src, size) do {			\
     803      if (!LINE || LINE == __LINE__) {			\
     804        char a[9] = init;					\
     805        char *pd = (dst);					\
     806        const char *ps = (src);				\
     807        strncpy (pd, ps, (size));				\
     808        sink (a, pd, ps);					\
     809      }							\
     810    } while (0)
     811  
     812    T ("012", a, a, 0);
     813    T ("012", a, a, 1);             /* { dg-warning "source argument is the same as destination " "strncpy" } */
     814  
     815    T ("012", a, a + 1, 1);
     816    T ("012", a, a + 1, 2);         /* { dg-warning "accessing 2 bytes at offsets 0 and 1 overlaps 1 byte at offset 1" "strncpy" } */
     817    T ("012", a, a + 1, 3);         /* { dg-warning "accessing 3 bytes at offsets 0 and 1 overlaps 2 bytes at offset 1" "strncpy" } */
     818    T ("012", a, a + 1, 4);         /* { dg-warning "accessing 4 bytes at offsets 0 and 1 overlaps 3 bytes at offset 1" "strncpy" } */
     819    T ("012", a, a + 1, 5);         /* { dg-warning "accessing 5 bytes at offsets 0 and 1 overlaps 3 bytes at offset 1" "strncpy" } */
     820    T ("012", a, a + 1, 6);         /* { dg-warning "accessing 6 bytes at offsets 0 and 1 overlaps 3 bytes at offset 1" "strncpy" } */
     821  
     822    T ("012", a, a + 2, 1);
     823    T ("012", a, a + 2, 2);
     824    /* The third written byte (nul) overwrites a[2].  */
     825    T ("012", a, a + 2, 3);         /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" "strncpy" } */
     826    T ("012", a, a + 2, 4);         /* { dg-warning "accessing 4 bytes at offsets 0 and 2 overlaps 2 bytes at offset 2" "strncpy" } */
     827    T ("012", a, a + 2, 5);         /* { dg-warning "accessing 5 bytes at offsets 0 and 2 overlaps 2 bytes at offset 2" "strncpy" } */
     828  
     829    T ("0123", a, a + 2, 1);
     830    T ("0123", a, a + 2, 2);
     831    /* The terminating nul written to a[2] overwrites s[0].  */
     832    T ("0123", a, a + 2, 3);        /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" "strncpy" } */
     833    T ("0123", a, a + 2, 4);        /* { dg-warning "accessing 4 bytes at offsets 0 and 2 overlaps 2 bytes at offset 2" "strncpy" } */
     834    T ("0123", a, a + 2, 5);        /* { dg-warning "accessing 5 bytes at offsets 0 and 2 overlaps 3 bytes at offset 2" "strncpy" } */
     835    T ("0123", a, a + 2, 6);        /* { dg-warning "accessing 6 bytes at offsets 0 and 2 overlaps 3 bytes at offset 2" "strncpy" } */
     836  
     837    T ("01234", a, a + 2, 1);
     838    T ("01234", a, a + 2, 2);
     839    T ("01234", a, a + 2, 3);       /* { dg-warning "accessing 3 bytes at offsets 0 and 2 overlaps 1 byte at offset 2" "strncpy" } */
     840    /* The '5' copied from s[2] to d[2] overwrites s[0].  */
     841    T ("01234", a, a + 2, 4);       /* { dg-warning "accessing 4 bytes at offsets 0 and 2 overlaps 2 bytes at offset 2" "strncpy" } */
     842    T ("01234", a, a + 2, 5);       /* { dg-warning "accessing 5 bytes at offsets 0 and 2 overlaps 3 bytes at offset 2" "strncpy" } */
     843  }
     844  
     845  
     846  /* Exercise strncpy with one or more arguments in a determinate range.  */
     847  
     848  void test_strncpy_range (char *d, size_t n)
     849  {
     850  #undef T
     851  #define T(init, dst, src, size) do {			\
     852      if (!LINE || LINE == __LINE__) {			\
     853        char a[9] = init;					\
     854        strncpy ((dst), (src), (size));			\
     855        sink (a, (dst), (src));				\
     856      }							\
     857    } while (0)
     858  
     859    ptrdiff_t i;
     860  
     861    i = SR (0, 1);
     862    T ("0123", a, a + i, 0);
     863    T ("0123", a, a + i, 1);
     864    /* Offset in the range [0, i] is represented as a PHI (&a, &a + i)
     865       that the implementation isn't equipped to handle yet.  */
     866    T ("0123", a, a + i, 2);   /* { dg-warning "accessing 2 bytes at offsets 0 and \\\[0, 1] may overlap 1 byte at offset 1" "strncpy" { xfail *-*-* } } */
     867  
     868    i = SR (1, 5);
     869    T ("0123", a, a + i, 0);
     870    T ("0123", a, a + i, 1);
     871    T ("0123", a, a + i, 2);   /* { dg-warning "accessing 2 bytes at offsets 0 and \\\[1, 5] may overlap 1 byte at offset 1" "strncpy" } */
     872    T ("0123", a, a + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[1, 5] may overlap up to 2 bytes at offset \\\[1, 2]" "strncpy" } */
     873    T ("0123", a, a + i, 4);   /* { dg-warning "accessing 4 bytes at offsets 0 and \\\[1, 5] may overlap up to 3 bytes at offset \\\[1, 3]" "strncpy" } */
     874    T ("0123", a, a + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[1, 5] may overlap up to 4 bytes at offset \\\[1, 4]" "strncpy" } */
     875  
     876    i = SR (2, 5);
     877    T ("0123", a, a + i, 0);
     878    T ("0123", a, a + i, 1);
     879    T ("0123", a, a + i, 2);
     880    T ("0123", a, a + i, 3);   /* { dg-warning "accessing 3 bytes at offsets 0 and \\\[2, 5] may overlap 1 byte at offset 2" "strncpy" } */
     881    T ("0123", a, a + i, 4);   /* { dg-warning "accessing 4 bytes at offsets 0 and \\\[2, 5] may overlap up to 2 bytes at offset \\\[2, 3]" "strncpy" } */
     882    T ("0123", a, a + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[2, 5] may overlap up to 3 bytes at offset \\\[2, 4]" "strncpy" } */
     883    /* When i == 5 the following overlaps at least 1 byte: the nul at a[5]
     884       (if a + 5 is the empty string).  If a + 5 is not empty then it overlaps
     885       it plus as many non-nul characters after it, up to the total of 6.  */
     886    T ("0123", a, a + i, 6);   /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[2, 5] overlaps between 1 and 3 bytes at offset \\\[2, 5]" "strncpy" } */
     887  
     888    i = SR (3, 5);
     889    T ("0123", a, a + i, 0);
     890    T ("0123", a, a + i, 1);
     891    T ("0123", a, a + i, 2);
     892    T ("0123", a, a + i, 3);
     893    T ("0123", a, a + i, 4);   /* { dg-warning "accessing 4 bytes at offsets 0 and \\\[3, 5] may overlap 1 byte at offset 3" "strncpy" } */
     894    T ("0123", a, a + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[3, 5] may overlap up to 2 bytes at offset \\\[3, 4]" "strncpy" } */
     895  
     896    /* The following copy overlaps at most 2 bytes.  When i == 3 it overlaps
     897       the 2 bytes at "3", when i == 4 just the final nul.  When i == 5 it
     898       also overlaps 1 byte, the nul at a[5].  Although the overlap offset
     899       range suggests the overlap is up to three bytes, it correctly reflects
     900       the union of the two cases.  */
     901    T ("0123", a, a + i, 6);   /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[3, 5] overlaps between 1 and 2 bytes at offset \\\[3, 5]" "strncpy" } */
     902  
     903    i = SR (4, 5);
     904    T ("0123", a, a + i, 0);
     905    T ("0123", a, a + i, 1);
     906    T ("0123", a, a + i, 2);
     907    T ("0123", a, a + i, 3);
     908    T ("0123", a, a + i, 4);
     909    T ("0123", a, a + i, 5);   /* { dg-warning "accessing 5 bytes at offsets 0 and \\\[4, 5] may overlap 1 byte at offset 4" "strncpy" } */
     910    /* Regardless of the value of i, the following overlaps exactlty
     911       one byte: the nul at a[4].  There is no overlap at a[5] because
     912       the source is not read past the nul so the offset below isn't
     913       entirely correct.  */
     914    T ("0123", a, a + i, 6);   /* { dg-warning "accessing 6 bytes at offsets 0 and \\\[4, 5] overlaps 1 byte at offset \\\[4, 5]" "strncpy" } */
     915  
     916    /* Verify offset and size both in some range.  The strncpy checking
     917       is more strict than that of memcpy and triggers even when the
     918       overlap is possible but not inevitable.  The following overlaps
     919       like so ('*' denotes the terminating NUL, '.' the appended NUL
     920       that's not copied from the source):
     921          a:        01234567*  (also indicates offset)
     922          i = 4:    4567       none
     923                    4567*      overlaps 1 at offset 4
     924                    4567*.     overlaps 2 at offset 4
     925          i = 5:    567*       none
     926                    567*.      none
     927                    567*..     overlaps 1 at offset 5  */
     928    T ("01234567", a, a + i, UR (4, 6));   /* { dg-warning "accessing between 4 and 6 bytes at offsets 0 and \\\[4, 5] may overlap up to 2 bytes at offset \\\[4, 5]" "strncpy" } */
     929  
     930    /* Ditto for objects of unknown sizes.  */
     931    T ("01234567", d, d + i, UR (4, 6));  /* { dg-warning "accessing between 4 and 6 bytes at offsets 0 and \\\[4, 5] may overlap up to 2 bytes at offset \\\[4, 5]" "strncpy" } */
     932  
     933    T ("01234567", a, a + i, UR (6, 7));  /* { dg-warning "accessing between 6 and 7 bytes at offsets 0 and \\\[4, 5] overlaps between 1 and 3 bytes at offset \\\[4, 5]" "strncpy" } */
     934  
     935    /* The following overlaps except in the unlikely case that value ()
     936       is zero, so it's diagnosed.  */
     937    T ("012", a, a, n);             /* { dg-warning "\\\[-Wrestrict]" "strncpy" } */
     938  }
     939  
     940  
     941  /* Exercise strncpy with destination and source of unknown length.  */
     942  
     943  void test_strncpy_var (char *d, const char *s, size_t n)
     944  {
     945  #undef T
     946  #define T(dst, src, size) do {			\
     947      if (!LINE || LINE == __LINE__) {		\
     948        char *pd = (dst);				\
     949        const char *ps = (src);			\
     950        strncpy (pd, ps, (size));			\
     951        sink (pd, ps);				\
     952      }						\
     953    } while (0)
     954  
     955    T (d, s, 1);
     956    T (d, s, n);
     957  
     958    T (d, d, 1);                    /* { dg-warning "\\\[-Wrestrict" "strncpy" } */
     959    T (d, d, n);                    /* { dg-warning "\\\[-Wrestrict" "strncpy" } */
     960  
     961    T (d,     d + 1, 1);
     962    T (d,     d + 1, 2);            /* { dg-warning "\\\[-Wrestrict" "strncpy" } */
     963    T (d + 1, d,     1);
     964    T (d + 1, d,     2);            /* { dg-warning "\\\[-Wrestrict" "strncpy" } */
     965  }
     966  
     967  struct MemberArrays
     968  {
     969    char a[7];
     970    char b[8];
     971    char c[9];
     972  };
     973  
     974  void test_strncpy_strcpy_var (struct MemberArrays *ar, const char *s)
     975  {
     976    /* The following is safe and should not trigger a warning.  */
     977    strncpy (ar->b, s, sizeof ar->b - 1);
     978    ar->b[sizeof ar->b - 1] = '\0';
     979    strcpy (ar->a, ar->b);
     980    sink (ar);
     981  
     982    /* The following is not as safe (it might overflow ar->a) but there
     983       is no overlap so it also shouldn't trigger -Wrestrict.  */
     984    strncpy (ar->c, s, sizeof ar->c - 1);
     985    ar->c[sizeof ar->c - 1] = '\0';
     986    strcpy (ar->a, ar->c);
     987    sink (ar);
     988  }