1  /* PR middle-end/92815 - spurious -Wstringop-overflow writing into
       2     a flexible array of an extern struct
       3     { dg-do compile }
       4     { dg-options "-O -Wall -fdump-tree-optimized" }
       5     { dg-skip-if "test assumes that structs have padding" { default_packed } } */
       6  
       7  #define ASSERT(expr) ((expr) ? (void)0 : fail (__LINE__))
       8  #define bos0(expr) __builtin_object_size (expr, 1)
       9  #define bos1(expr) __builtin_object_size (expr, 1)
      10  #define bos2(expr) __builtin_object_size (expr, 2)
      11  #define bos3(expr) __builtin_object_size (expr, 3)
      12  
      13  typedef __INT16_TYPE__ int16_t;
      14  typedef __INT32_TYPE__ int32_t;
      15  typedef __INT64_TYPE__ int64_t;
      16  typedef __SIZE_TYPE__  size_t;
      17  
      18  
      19  extern void fail (int);
      20  
      21  
      22  
      23  
      24  /* Verify sizes of a struct with a flexible array member and 1 byte
      25     of tail padding.  */
      26  
      27  struct AI16CX { int16_t i; char n, a[]; };
      28  
      29  struct AI16CX ai16c0 = { 0 };
      30  struct AI16CX ai16c1 = { 0, 1, { 1 } };
      31  struct AI16CX ai16c2 = { 0, 2, { 1, 2 } };
      32  struct AI16CX ai16c3 = { 0, 3, { 1, 2, 3 } };
      33  struct AI16CX ai16c4 = { 0, 4, { 1, 2, 3, 4 } };
      34  struct AI16CX ai16c5 = { 0, 5, { 1, 2, 3, 4, 5 } };
      35  struct AI16CX ai16c6 = { 0, 6, { 1, 2, 3, 4, 5, 6 } };
      36  struct AI16CX ai16c7 = { 0, 7, { 1, 2, 3, 4, 5, 6, 7 } };
      37  struct AI16CX ai16c8 = { 0, 8, { 1, 2, 3, 4, 5, 6, 7, 8 } };
      38  
      39  extern struct AI16CX eai16cx;
      40  
      41  void fai16cx (void)
      42  {
      43    ASSERT (bos0 (&ai16c0) == sizeof ai16c0);
      44    ASSERT (bos0 (&ai16c1) == sizeof ai16c1);
      45    ASSERT (bos0 (&ai16c2) == sizeof ai16c2 + 1);
      46    ASSERT (bos0 (&ai16c3) == sizeof ai16c3 + 2);
      47  
      48    ASSERT (bos0 (&ai16c4) == sizeof ai16c4 + 3);
      49    ASSERT (bos0 (&ai16c5) == sizeof ai16c5 + 4);
      50    ASSERT (bos0 (&ai16c6) == sizeof ai16c6 + 5);
      51    ASSERT (bos0 (&ai16c7) == sizeof ai16c6 + 6);
      52    ASSERT (bos0 (&ai16c8) == sizeof ai16c6 + 7);
      53  
      54    ASSERT (bos0 (&eai16cx) == (size_t)-1);
      55  
      56  
      57    ASSERT (bos1 (&ai16c0) == sizeof ai16c0);
      58    ASSERT (bos1 (&ai16c1) == sizeof ai16c1);
      59    ASSERT (bos1 (&ai16c2) == sizeof ai16c2 + 1);
      60    ASSERT (bos1 (&ai16c3) == sizeof ai16c3 + 2);
      61  
      62    ASSERT (bos1 (&ai16c4) == sizeof ai16c4 + 3);
      63    ASSERT (bos1 (&ai16c5) == sizeof ai16c5 + 4);
      64    ASSERT (bos1 (&ai16c6) == sizeof ai16c6 + 5);
      65    ASSERT (bos1 (&ai16c7) == sizeof ai16c6 + 6);
      66    ASSERT (bos1 (&ai16c8) == sizeof ai16c6 + 7);
      67  
      68    ASSERT (bos1 (&eai16cx) == (size_t)-1);
      69  
      70  
      71    ASSERT (bos2 (&ai16c0) == sizeof ai16c0);
      72    ASSERT (bos2 (&ai16c1) == sizeof ai16c1);
      73    ASSERT (bos2 (&ai16c2) == sizeof ai16c2 + 1);
      74    ASSERT (bos2 (&ai16c3) == sizeof ai16c3 + 2);
      75  
      76    ASSERT (bos2 (&ai16c4) == sizeof ai16c4 + 3);
      77    ASSERT (bos2 (&ai16c5) == sizeof ai16c5 + 4);
      78    ASSERT (bos2 (&ai16c6) == sizeof ai16c6 + 5);
      79    ASSERT (bos2 (&ai16c7) == sizeof ai16c6 + 6);
      80    ASSERT (bos2 (&ai16c8) == sizeof ai16c6 + 7);
      81  
      82    ASSERT (bos2 (&eai16cx) == sizeof eai16cx);
      83  
      84  
      85    ASSERT (bos3 (&ai16c0) == sizeof ai16c0);
      86    ASSERT (bos3 (&ai16c1) == sizeof ai16c1);
      87    ASSERT (bos3 (&ai16c2) == sizeof ai16c2 + 1);
      88    ASSERT (bos3 (&ai16c3) == sizeof ai16c3 + 2);
      89  
      90    ASSERT (bos3 (&ai16c4) == sizeof ai16c4 + 3);
      91    ASSERT (bos3 (&ai16c5) == sizeof ai16c5 + 4);
      92    ASSERT (bos3 (&ai16c6) == sizeof ai16c6 + 5);
      93    ASSERT (bos3 (&ai16c7) == sizeof ai16c6 + 6);
      94    ASSERT (bos3 (&ai16c8) == sizeof ai16c6 + 7);
      95  
      96    ASSERT (bos3 (&eai16cx) == sizeof eai16cx);
      97  }
      98  
      99  
     100  /* Verify sizes of a struct with a flexible array member and 3 bytes
     101     of tail padding.  */
     102  
     103  struct AI32CX { int32_t i; char n, a[]; };
     104  
     105  struct AI32CX ai32c0 = { 0 };
     106  struct AI32CX ai32c1 = { 0, 1, { 1 } };
     107  struct AI32CX ai32c2 = { 0, 2, { 1, 2 } };
     108  struct AI32CX ai32c3 = { 0, 3, { 1, 2, 3 } };
     109  struct AI32CX ai32c4 = { 0, 4, { 1, 2, 3, 4 } };
     110  struct AI32CX ai32c5 = { 0, 5, { 1, 2, 3, 4, 5 } };
     111  struct AI32CX ai32c6 = { 0, 6, { 1, 2, 3, 4, 5, 6 } };
     112  struct AI32CX ai32c7 = { 0, 7, { 1, 2, 3, 4, 5, 6, 7 } };
     113  struct AI32CX ai32c8 = { 0, 8, { 1, 2, 3, 4, 5, 6, 7, 8 } };
     114  
     115  extern struct AI32CX eai32cx;
     116  
     117  void fai32cx (void)
     118  {
     119    ASSERT (bos0 (&ai32c0) == sizeof ai32c0);
     120    ASSERT (bos0 (&ai32c1) == sizeof ai32c1);
     121    ASSERT (bos0 (&ai32c2) == sizeof ai32c2);
     122    ASSERT (bos0 (&ai32c3) == sizeof ai32c3);
     123  
     124    ASSERT (bos0 (&ai32c4) == sizeof ai32c4 + 1);
     125    ASSERT (bos0 (&ai32c5) == sizeof ai32c5 + 2);
     126    ASSERT (bos0 (&ai32c6) == sizeof ai32c6 + 3);
     127    ASSERT (bos0 (&ai32c7) == sizeof ai32c6 + 4);
     128    ASSERT (bos0 (&ai32c8) == sizeof ai32c6 + 5);
     129  
     130    ASSERT (bos0 (&eai32cx) == (size_t)-1);
     131  
     132  
     133    ASSERT (bos1 (&ai32c0) == sizeof ai32c0);
     134    ASSERT (bos1 (&ai32c1) == sizeof ai32c1);
     135    ASSERT (bos1 (&ai32c2) == sizeof ai32c2);
     136    ASSERT (bos1 (&ai32c3) == sizeof ai32c3);
     137  
     138    ASSERT (bos1 (&ai32c4) == sizeof ai32c4 + 1);
     139    ASSERT (bos1 (&ai32c5) == sizeof ai32c5 + 2);
     140    ASSERT (bos1 (&ai32c6) == sizeof ai32c6 + 3);
     141    ASSERT (bos1 (&ai32c7) == sizeof ai32c6 + 4);
     142    ASSERT (bos1 (&ai32c8) == sizeof ai32c6 + 5);
     143  
     144    ASSERT (bos1 (&eai32cx) == (size_t)-1);
     145  
     146  
     147    ASSERT (bos2 (&ai32c0) == sizeof ai32c0);
     148    ASSERT (bos2 (&ai32c1) == sizeof ai32c1);
     149    ASSERT (bos2 (&ai32c2) == sizeof ai32c2);
     150    ASSERT (bos2 (&ai32c3) == sizeof ai32c3);
     151  
     152    ASSERT (bos2 (&ai32c4) == sizeof ai32c4 + 1);
     153    ASSERT (bos2 (&ai32c5) == sizeof ai32c5 + 2);
     154    ASSERT (bos2 (&ai32c6) == sizeof ai32c6 + 3);
     155    ASSERT (bos2 (&ai32c7) == sizeof ai32c6 + 4);
     156    ASSERT (bos2 (&ai32c8) == sizeof ai32c6 + 5);
     157  
     158    ASSERT (bos2 (&eai32cx) == sizeof eai32cx);
     159  
     160  
     161    ASSERT (bos3 (&ai32c0) == sizeof ai32c0);
     162    ASSERT (bos3 (&ai32c1) == sizeof ai32c1);
     163    ASSERT (bos3 (&ai32c2) == sizeof ai32c2);
     164    ASSERT (bos3 (&ai32c3) == sizeof ai32c3);
     165  
     166    ASSERT (bos3 (&ai32c4) == sizeof ai32c4 + 1);
     167    ASSERT (bos3 (&ai32c5) == sizeof ai32c5 + 2);
     168    ASSERT (bos3 (&ai32c6) == sizeof ai32c6 + 3);
     169    ASSERT (bos3 (&ai32c7) == sizeof ai32c6 + 4);
     170    ASSERT (bos3 (&ai32c8) == sizeof ai32c6 + 5);
     171  
     172    ASSERT (bos3 (&eai32cx) == sizeof eai32cx);
     173  }
     174  
     175  
     176  /* Verify sizes of a struct with a flexible array member and 7 bytes
     177     of tail padding.  */
     178  
     179  struct AI64CX { int64_t i __attribute__ ((aligned (8))); char n, a[]; };
     180  
     181  struct AI64CX ai64c0 = { 0 };
     182  struct AI64CX ai64c1 = { 0, 1, { 1 } };
     183  struct AI64CX ai64c2 = { 0, 2, { 1, 2 } };
     184  struct AI64CX ai64c3 = { 0, 3, { 1, 2, 3 } };
     185  struct AI64CX ai64c4 = { 0, 4, { 1, 2, 3, 4 } };
     186  struct AI64CX ai64c5 = { 0, 5, { 1, 2, 3, 4, 5 } };
     187  struct AI64CX ai64c6 = { 0, 6, { 1, 2, 3, 4, 5, 6 } };
     188  struct AI64CX ai64c7 = { 0, 7, { 1, 2, 3, 4, 5, 6, 7 } };
     189  struct AI64CX ai64c8 = { 0, 8, { 1, 2, 3, 4, 5, 6, 7, 8 } };
     190  struct AI64CX ai64c9 = { 0, 8, { 1, 2, 3, 4, 5, 6, 7, 8, 9 } };
     191  
     192  extern struct AI64CX eai64cx;
     193  
     194  void fai64cx (void)
     195  {
     196    ASSERT (bos0 (&ai64c0) == sizeof ai64c0);
     197    ASSERT (bos0 (&ai64c1) == sizeof ai64c1);
     198    ASSERT (bos0 (&ai64c2) == sizeof ai64c2);
     199    ASSERT (bos0 (&ai64c3) == sizeof ai64c3);
     200    ASSERT (bos0 (&ai64c4) == sizeof ai64c4);
     201    ASSERT (bos0 (&ai64c5) == sizeof ai64c5);
     202    ASSERT (bos0 (&ai64c6) == sizeof ai64c6);
     203    ASSERT (bos0 (&ai64c7) == sizeof ai64c7);
     204  
     205    ASSERT (bos0 (&ai64c8) == sizeof ai64c8 + 1);
     206    ASSERT (bos0 (&ai64c9) == sizeof ai64c9 + 2);
     207  
     208    ASSERT (bos0 (&eai64cx) == (size_t)-1);
     209  
     210  
     211    ASSERT (bos1 (&ai64c0) == sizeof ai64c0);
     212    ASSERT (bos1 (&ai64c1) == sizeof ai64c1);
     213    ASSERT (bos1 (&ai64c2) == sizeof ai64c2);
     214    ASSERT (bos1 (&ai64c3) == sizeof ai64c3);
     215    ASSERT (bos1 (&ai64c4) == sizeof ai64c4);
     216    ASSERT (bos1 (&ai64c5) == sizeof ai64c5);
     217    ASSERT (bos1 (&ai64c6) == sizeof ai64c6);
     218    ASSERT (bos1 (&ai64c7) == sizeof ai64c7);
     219  
     220    ASSERT (bos1 (&ai64c8) == sizeof ai64c8 + 1);
     221    ASSERT (bos1 (&ai64c9) == sizeof ai64c9 + 2);
     222  
     223    ASSERT (bos1 (&eai64cx) == (size_t)-1);
     224  
     225  
     226    ASSERT (bos2 (&ai64c0) == sizeof ai64c0);
     227    ASSERT (bos2 (&ai64c1) == sizeof ai64c1);
     228    ASSERT (bos2 (&ai64c2) == sizeof ai64c2);
     229    ASSERT (bos2 (&ai64c3) == sizeof ai64c3);
     230    ASSERT (bos2 (&ai64c4) == sizeof ai64c4);
     231    ASSERT (bos2 (&ai64c5) == sizeof ai64c5);
     232    ASSERT (bos2 (&ai64c6) == sizeof ai64c6);
     233    ASSERT (bos2 (&ai64c7) == sizeof ai64c7);
     234  
     235    ASSERT (bos2 (&ai64c8) == sizeof ai64c8 + 1);
     236    ASSERT (bos2 (&ai64c9) == sizeof ai64c9 + 2);
     237  
     238    ASSERT (bos2 (&eai64cx) == sizeof eai64cx);
     239  
     240    ASSERT (bos3 (&ai64c0) == sizeof ai64c0);
     241    ASSERT (bos3 (&ai64c1) == sizeof ai64c1);
     242    ASSERT (bos3 (&ai64c2) == sizeof ai64c2);
     243    ASSERT (bos3 (&ai64c3) == sizeof ai64c3);
     244    ASSERT (bos3 (&ai64c4) == sizeof ai64c4);
     245    ASSERT (bos3 (&ai64c5) == sizeof ai64c5);
     246    ASSERT (bos3 (&ai64c6) == sizeof ai64c6);
     247    ASSERT (bos3 (&ai64c7) == sizeof ai64c7);
     248  
     249    ASSERT (bos3 (&ai64c8) == sizeof ai64c8 + 1);
     250    ASSERT (bos3 (&ai64c9) == sizeof ai64c9 + 2);
     251  
     252    ASSERT (bos3 (&eai64cx) == sizeof eai64cx);
     253  }
     254  
     255  /* { dg-final { scan-tree-dump-not "fail" "optimized" } } */