(root)/
gcc-13.2.0/
gcc/
testsuite/
c-c++-common/
attr-nonstring-2.c
       1  /* Test to exercise attribute "nonstring".
       2     { dg-do compile }
       3     { dg-options "-O2 -Wattributes -Wstringop-truncation -ftrack-macro-expansion=0" }  */
       4  
       5  #define ATTR(list) __attribute__ (list)
       6  #define NONSTR     ATTR ((nonstring))
       7  #define strncpy(d, s, n) (__builtin_strncpy ((d), (s), (n)), sink (d))
       8  
       9  void sink (void*);
      10  
      11  /* Global string with an unknown bound.  */
      12  extern char gsx[];
      13  
      14  /* Global string with an known bound.  */
      15  extern char gs3[3];
      16  
      17  /* Global non-strings with an unknown bound.  */
      18  extern NONSTR char gax_1[];
      19  extern char NONSTR gax_2[];
      20  extern char gax_3[] NONSTR;
      21  
      22  /* Global non-strings with a known bound.  */
      23  NONSTR char gns3[3];
      24  char NONSTR gns4[4];
      25  char gns5[5] NONSTR;
      26  
      27  /* Global string pointer.  */
      28  extern char *ps_1;
      29  
      30  /* Global non-string pointers.  */
      31  extern NONSTR char *pns_1;
      32  extern char* NONSTR pns_2;
      33  extern char *pns_3 NONSTR;
      34  
      35  struct MemArrays
      36  {
      37    NONSTR char ma3[3];
      38    char NONSTR ma4[4];
      39    char ma5[5] NONSTR;
      40    char max[] NONSTR;
      41  };
      42  
      43  
      44  void test_array (const char *s, unsigned n)
      45  {
      46    const char s7[] = "1234567";
      47  
      48    strncpy (gs3, "", 0);           /* { dg-warning "destination unchanged after copying no bytes" } */
      49    strncpy (gs3, "a", 1);          /* { dg-warning "output truncated before terminating nul copying 1 byte from a string of the same length" } */
      50    strncpy (gs3, "a", 2);
      51    strncpy (gs3, "a", 3);
      52    strncpy (gs3, "ab", 3);
      53    strncpy (gs3, "abc", 3);        /* { dg-warning "output truncated before terminating nul copying 3 bytes from a string of the same length" } */
      54  
      55    /* It might perhaps be helpful to diagnose certain truncation even
      56       for non-strings.  Then again, since the destination has been
      57       explicitly annotated as non-string, it might be viewed as a false
      58       positive.  A valid use case seen in Glibc goes something like this:
      59  
      60       #if FOO
      61       # define S "1234"
      62       #else
      63       # define S "12345678"
      64       #endif
      65  
      66       strncpy (d, S, 8);
      67    */
      68    strncpy (gax_3, s7, 3);
      69  
      70    strncpy (gax_1, "a", 1);
      71    strncpy (gax_2, "ab", 2);
      72    strncpy (gax_3, "abc", 3);
      73    strncpy (gax_3, s7, 3);
      74  
      75    strncpy (gax_1, s, 1);
      76    strncpy (gax_2, s, 1);
      77    strncpy (gax_3, s, 1);
      78  
      79    strncpy (gax_1, s, n);
      80    strncpy (gax_2, s, n);
      81    strncpy (gax_3, s, n);
      82  }
      83  
      84  
      85  void test_pointer (const char *s, unsigned n)
      86  {
      87    const char s7[] = "1234567";
      88  
      89    strncpy (pns_1, "a", 1);
      90    strncpy (pns_2, "ab", 2);
      91    strncpy (pns_3, "abc", 3);
      92    strncpy (pns_3, s7, 3);
      93  
      94    strncpy (pns_1, s, 1);
      95    strncpy (pns_2, s, 1);
      96    strncpy (pns_3, s, 1);
      97  
      98    strncpy (pns_1, s, n);
      99    strncpy (pns_2, s, n);
     100    strncpy (pns_3, s, n);
     101  }
     102  
     103  
     104  void test_member_array (struct MemArrays *p, const char *s, unsigned n)
     105  {
     106    const char s7[] = "1234567";
     107  
     108    strncpy (p->ma3, "", 0);
     109    strncpy (p->ma3, "a", 1);
     110    strncpy (p->ma4, "ab", 2);
     111    strncpy (p->ma5, "abc", 3);
     112    strncpy (p->max, "abcd", 4);
     113    strncpy (p->max, s7, 5);
     114  
     115    strncpy (p->ma3, s, 1);
     116    strncpy (p->ma4, s, 1);
     117    strncpy (p->ma5, s, 1);
     118    strncpy (p->max, s, 1);
     119  
     120    strncpy (p->ma3, s7, n);
     121    strncpy (p->ma4, s7, n);
     122    strncpy (p->ma5, s7, n);
     123    strncpy (p->max, s7, n);
     124  }