(root)/
gcc-13.2.0/
gcc/
testsuite/
c-c++-common/
builtin-offsetof-2.c
       1  // { dg-options "-Warray-bounds" }
       2  // { dg-do compile }
       3  
       4  // Test case exercising pr c/67882 - surprising offsetof result
       5  //   on an invalid array member without diagnostic.
       6  
       7  typedef struct A1 {
       8    char a1[1];
       9    char c;
      10  } A1;
      11  
      12  typedef struct A1_x_2 {
      13    char a1[1];
      14    char a[][2];
      15  } A1_x_2;
      16  
      17  typedef struct A1_1_x {
      18    char a1_1[1][1];
      19    char a[];
      20  } A1_1_x;
      21  
      22  typedef struct Ax_2_3 {
      23    int i;
      24    char a_x_2_3[][2][3];
      25  } Ax_2_3;
      26  
      27  typedef struct A1_1 {
      28    char a1_1[1][1];
      29    char c;
      30  } A1_1;
      31  
      32  typedef struct B {
      33    A1_1 a2_3[2][3];
      34    char a1_1[3][5];
      35    char a[];
      36  } B;
      37  
      38  // Structures with members that contain flexible array members are
      39  // an extension accepted by GCC.
      40  typedef struct C {
      41    A1_1_x a5_7 [5][7];
      42    int a;
      43  } C;
      44  
      45  // Structs with a "fake" flexible array member (a GCC extension).
      46  typedef struct FA0 {
      47    int i;
      48    char a0 [0];
      49  } FA0;
      50  
      51  typedef struct FA1 {
      52    int i;
      53    char a1 [1];
      54  } FA1;
      55  
      56  typedef struct FA3 {
      57    int i;
      58    char a3 [3];
      59  } FA3;
      60  
      61  // A "fake" multidimensional flexible array member.
      62  typedef struct FA5_7 {
      63    int i;
      64    char a5_7 [5][7];
      65  } FA5_7;
      66  
      67  static void test (void)
      68  {
      69    // Verify that offsetof references to array elements past the end of
      70    // the array member are diagnosed.  As an extension, permit references
      71    // to the element just past-the-end of the array.
      72  
      73    int a[] = {
      74      __builtin_offsetof (A1, a1),                 // valid
      75      __builtin_offsetof (A1, a1 [0]),             // valid
      76  
      77      // The following expression is valid because it forms the equivalent
      78      // of an address pointing just past the last element of the array.
      79      __builtin_offsetof (A1, a1 [1]),             // valid
      80  
      81      __builtin_offsetof (A1, a1 [2]),             // { dg-warning "index" }
      82  
      83      __builtin_offsetof (A1_x_2, a1),             // valid
      84      __builtin_offsetof (A1_x_2, a1 [0]),         // valid
      85      __builtin_offsetof (A1_x_2, a1 [1]),         // valid
      86      __builtin_offsetof (A1_x_2, a1 [2]),         // { dg-warning "index" }
      87  
      88      __builtin_offsetof (A1_x_2, a),              // valid
      89      __builtin_offsetof (A1_x_2, a [0]),          // valid
      90      __builtin_offsetof (A1_x_2, a [1]),          // valid
      91      __builtin_offsetof (A1_x_2, a [99]),         // valid
      92  
      93      __builtin_offsetof (A1_x_2, a),              // valid
      94      __builtin_offsetof (A1_x_2, a [0][0]),       // valid
      95      __builtin_offsetof (A1_x_2, a [0][1]),       // valid
      96  
      97      // The following expression is valid because it forms the equivalent
      98      // of an address pointing just past the last element of the first
      99      // array.
     100      __builtin_offsetof (A1_x_2, a [0][2]),       // valid
     101  
     102      // Unlike the case above, this is invalid since it refers to an element
     103      // past one one just-past-the-end in A[][2].
     104      __builtin_offsetof (A1_x_2, a [0][3]),       // { dg-warning "index" }
     105  
     106      __builtin_offsetof (A1_x_2, a [1][0]),       // valid
     107      __builtin_offsetof (A1_x_2, a [1][1]),       // valid
     108      __builtin_offsetof (A1_x_2, a [1][2]),       // valid
     109      __builtin_offsetof (A1_x_2, a [99][0]),      // valid
     110      __builtin_offsetof (A1_x_2, a [99][1]),      // valid
     111      __builtin_offsetof (A1_x_2, a [99][2]),      // valid
     112  
     113      __builtin_offsetof (A1_1_x, a),              // valid
     114      __builtin_offsetof (A1_1_x, a [0]),          // valid
     115      __builtin_offsetof (A1_1_x, a [1]),          // valid
     116      __builtin_offsetof (A1_1_x, a [99]),         // valid
     117  
     118      __builtin_offsetof (A1_1_x, a1_1 [0][0]),    // valid
     119      __builtin_offsetof (A1_1_x, a1_1 [0][1]),    // valid
     120      __builtin_offsetof (A1_1_x, a1_1 [0][2]),    // { dg-warning "index" }
     121      __builtin_offsetof (A1_1_x, a1_1 [1][0]),    // { dg-warning "index" }
     122      __builtin_offsetof (A1_1_x, a1_1 [1][1]),    // { dg-warning "index" }
     123  
     124      __builtin_offsetof (Ax_2_3, a_x_2_3 [0][1][3]),  // valid
     125      __builtin_offsetof (Ax_2_3, a_x_2_3 [0][1][4]),  // { dg-warning "index" }
     126      __builtin_offsetof (Ax_2_3, a_x_2_3 [0][2]),     // valid
     127      __builtin_offsetof (Ax_2_3, a_x_2_3 [0][2][0]),  // { dg-warning "index" }
     128  
     129      __builtin_offsetof (B, a2_3 [0][0].c),           // valid
     130      __builtin_offsetof (B, a2_3 [0][0].a1_1 [0][0]), // valid
     131      __builtin_offsetof (B, a2_3 [1][3]),             // valid
     132      __builtin_offsetof (B, a2_3 [1][4]),             // { dg-warning "index" }
     133      __builtin_offsetof (B, a2_3 [0][0].a1_1 [0][1]), // valid
     134      __builtin_offsetof (B, a2_3 [0][0].a1_1 [0][2]), // { dg-warning "index" }
     135  
     136      __builtin_offsetof (B, a2_3 [0][0].a1_1 [1][0]), // { dg-warning "index" }
     137      __builtin_offsetof (B, a2_3 [0][0].a1_1 [1][1]), // { dg-warning "index" }
     138  
     139      __builtin_offsetof (B, a2_3 [1][2].a1_1 [0][0]), // valid
     140  
     141      // Forming an offset to the just-past-end element is valid.
     142      __builtin_offsetof (B, a2_3 [1][2].a1_1 [0][1]), // valid
     143      __builtin_offsetof (B, a2_3 [1][2].a1_1 [1][0]), // { dg-warning "index" }
     144      __builtin_offsetof (B, a2_3 [1][2].a1_1 [1][1]), // { dg-warning "index" }
     145  
     146      // Forming an offset to the just-past-end element is valid.
     147      __builtin_offsetof (B, a2_3 [1][3]),             // valid
     148      // ...but these are diagnosed because they dereference a just-past-the-end
     149      // element.
     150      __builtin_offsetof (B, a2_3 [1][3].a1_1 [0][0]), // { dg-warning "index" }
     151      __builtin_offsetof (B, a2_3 [1][3].a1_1 [0][0]), // { dg-warning "index" }
     152      __builtin_offsetof (B, a2_3 [1][3].a1_1 [0][1]), // { dg-warning "index" }
     153      __builtin_offsetof (B, a2_3 [1][3].a1_1 [1][0]), // { dg-warning "index" }
     154      __builtin_offsetof (B, a2_3 [1][3].a1_1 [1][1]), // { dg-warning "index" }
     155  
     156      // Analogous to the case above, these are both diagnosed because they
     157      // dereference just-past-the-end elements of the a2_3 array.
     158      __builtin_offsetof (B, a2_3 [1][3].c),       // { dg-warning "index" }
     159      __builtin_offsetof (B, a2_3 [1][3].c),       // { dg-warning "index" }
     160  
     161      // The following are all invalid because of the reference to a2_3[2].
     162      __builtin_offsetof (B, a2_3 [2][0].a1_1 [0][0]), // { dg-warning "index" }
     163      __builtin_offsetof (B, a2_3 [2][0].a1_1 [0][1]), // { dg-warning "index" }
     164      __builtin_offsetof (B, a2_3 [2][0].a1_1 [1][0]), // { dg-warning "index" }
     165      __builtin_offsetof (B, a2_3 [2][0].a1_1 [1][1]), // { dg-warning "index" }
     166      __builtin_offsetof (B, a2_3 [2][0].c),           // { dg-warning "index" }
     167  
     168      __builtin_offsetof (C, a5_7 [4][6]),
     169      __builtin_offsetof (C, a5_7 [4][6].a),
     170      __builtin_offsetof (C, a5_7 [4][6].a [0]),
     171      __builtin_offsetof (C, a5_7 [4][6].a [99]),
     172  
     173      __builtin_offsetof (C, a5_7 [4][7]),             // valid
     174      // Diagnose the following even though the object whose offset is
     175      // computed is a flexible array member.
     176      __builtin_offsetof (C, a5_7 [4][7].a),           // { dg-warning "index" }
     177      __builtin_offsetof (C, a5_7 [4][7].a [0]),       // { dg-warning "index" }
     178      __builtin_offsetof (C, a5_7 [4][7].a [99]),      // { dg-warning "index" }
     179  
     180      // Verify that no diagnostic is issued for offsetof expressions
     181      // involving structs where the array has a rank of 1 and is the last
     182      // member (e.g., those are treated as flexible array members).
     183      __builtin_offsetof (FA0, a0 [0]),
     184      __builtin_offsetof (FA0, a0 [1]),
     185      __builtin_offsetof (FA0, a0 [99]),
     186  
     187      __builtin_offsetof (FA1, a1 [0]),
     188      __builtin_offsetof (FA1, a1 [1]),
     189      __builtin_offsetof (FA1, a1 [99]),
     190  
     191      __builtin_offsetof (FA3, a3 [0]),
     192      __builtin_offsetof (FA3, a3 [3]),
     193      __builtin_offsetof (FA3, a3 [99]),
     194  
     195      __builtin_offsetof (FA5_7, a5_7 [0][0]),
     196  
     197      // Unlike one-dimensional arrays, verify that out-of-bounds references
     198      // to "fake" flexible arrays with rank of 2 and greater are diagnosed.
     199  
     200      // The following are valid because they compute the offset of just past
     201      // the end of each of the a5_7[0] and a5_7[1] arrays.
     202      __builtin_offsetof (FA5_7, a5_7 [0][7]),         // valid
     203      __builtin_offsetof (FA5_7, a5_7 [1][7]),         // valid
     204  
     205      // The following two are accepted as an extesion (because a5_7 is
     206      // treated as a flexible array member).
     207      __builtin_offsetof (FA5_7, a5_7 [5][0]),         // extension
     208      __builtin_offsetof (FA5_7, a5_7 [5][7]),         // extension
     209  
     210      // The following are invalid since in both cases they denote an element
     211      // that's beyond just-past-the-end of the array.
     212      __builtin_offsetof (FA5_7, a5_7 [0][8]),        // { dg-warning "index" }
     213      __builtin_offsetof (FA5_7, a5_7 [6][8])         // { dg-warning "index" }
     214    };
     215  
     216    (void)&a;
     217  }