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