aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2013-06-21 13:11:44 -0700
committerPaul Eggert2013-06-21 13:11:44 -0700
commitfbe9e0b9fb6a250674e7619e9ba794e74ff5f0bc (patch)
tree7b1836faca02f39413afec531c2ae467898523f5 /src
parentcad5d1cb5af7210154814b60825576d14740158f (diff)
downloademacs-fbe9e0b9fb6a250674e7619e9ba794e74ff5f0bc.tar.gz
emacs-fbe9e0b9fb6a250674e7619e9ba794e74ff5f0bc.zip
Use C99-style flexible array members if available.
This avoids some subtle aliasing issues, which typically aren't a problem with GCC but may be a problem elsewhere. * lib-src/ebrowse.c (struct member, struct alias, struct sym): Use FLEXIBLE_ARRAY_MEMBER. (add_sym, add_member, make_namespace, register_namespace_alias): Use offsetof (struct, flex_array_member), not sizeof (struct), as that ports better to pre-C99 non-GCC. * src/alloc.c (sdata): New typedef, replacing the old struct sdata. It is a struct if GC_CHECK_STRING_BYTES, a union otherwise. In either case, it uses a flexible array member rather than the old struct hack. All uses changed. (SDATA_NBYTES, sweep_strings) [!GC_CHECK_STRING_BYTES]: Adjust to sdata reorganization. * src/alloc.c (VBLOCK_BYTES_MIN, allocate_vectorlike, Fgarbage_collect): Use offsetof (struct, flex_array_member), not sizeof (struct), as that ports better to pre-C99 non-GCC. * src/chartab.c (Fmake_char_table, make_sub_char_table, copy_char_table): Use CHAR_TABLE_STANDARD_SLOTS rather than its definition, as the latter has changed. * src/conf_post.h (FLEXIBLE_ARRAY_MEMBER): Move here from w32.c, and port better to pre-C99 GCC. * src/image.c (struct xpm_cached_color): * src/lisp.h (struct Lisp_Vector, struct Lisp_Bool_Vector) (struct Lisp_Char_Table, struct Lisp_Sub_Char_Table): Use FLEXIBLE_ARRAY_MEMBER. * src/lisp.h (string_bytes) [GC_CHECK_STRING_BYTES]: Move decl to top level so it gets checked against implementation. (CHAR_TABLE_STANDARD_SLOTS): Adjust to struct Lisp_Char_Table change. * src/w32.c (FLEXIBLE_ARRAY_MEMBER): Move to conf_post.h.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog28
-rw-r--r--src/alloc.c80
-rw-r--r--src/chartab.c6
-rw-r--r--src/conf_post.h11
-rw-r--r--src/image.c2
-rw-r--r--src/lisp.h16
-rw-r--r--src/w32.c6
7 files changed, 99 insertions, 50 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 4e52f5b2818..4821f5fb7eb 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,31 @@
12013-06-21 Paul Eggert <eggert@cs.ucla.edu>
2
3 Use C99-style flexible array members if available.
4 This avoids some subtle aliasing issues, which typically
5 aren't a problem with GCC but may be a problem elsewhere.
6 * alloc.c (sdata): New typedef, replacing the old struct sdata.
7 It is a struct if GC_CHECK_STRING_BYTES, a union otherwise.
8 In either case, it uses a flexible array member rather than
9 the old struct hack. All uses changed.
10 (SDATA_NBYTES, sweep_strings) [!GC_CHECK_STRING_BYTES]:
11 Adjust to sdata reorganization.
12 * alloc.c (VBLOCK_BYTES_MIN, allocate_vectorlike, Fgarbage_collect):
13 Use offsetof (struct, flex_array_member), not sizeof (struct), as
14 that ports better to pre-C99 non-GCC.
15 * chartab.c (Fmake_char_table, make_sub_char_table, copy_char_table):
16 Use CHAR_TABLE_STANDARD_SLOTS rather than its definition,
17 as the latter has changed.
18 * conf_post.h (FLEXIBLE_ARRAY_MEMBER): Move here from w32.c,
19 and port better to pre-C99 GCC.
20 * image.c (struct xpm_cached_color):
21 * lisp.h (struct Lisp_Vector, struct Lisp_Bool_Vector)
22 (struct Lisp_Char_Table, struct Lisp_Sub_Char_Table):
23 Use FLEXIBLE_ARRAY_MEMBER.
24 * lisp.h (string_bytes) [GC_CHECK_STRING_BYTES]:
25 Move decl to top level so it gets checked against implementation.
26 (CHAR_TABLE_STANDARD_SLOTS): Adjust to struct Lisp_Char_Table change.
27 * w32.c (FLEXIBLE_ARRAY_MEMBER): Move to conf_post.h.
28
12013-06-20 Paul Eggert <eggert@cs.ucla.edu> 292013-06-20 Paul Eggert <eggert@cs.ucla.edu>
2 30
3 * syntax.c: Integer cleanups. 31 * syntax.c: Integer cleanups.
diff --git a/src/alloc.c b/src/alloc.c
index d277dd2419b..eaef0d4b797 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -1260,7 +1260,7 @@ mark_interval (register INTERVAL i, Lisp_Object dummy)
1260 When a Lisp_String is freed during GC, it is put back on 1260 When a Lisp_String is freed during GC, it is put back on
1261 string_free_list, and its `data' member and its sdata's `string' 1261 string_free_list, and its `data' member and its sdata's `string'
1262 pointer is set to null. The size of the string is recorded in the 1262 pointer is set to null. The size of the string is recorded in the
1263 `u.nbytes' member of the sdata. So, sdata structures that are no 1263 `n.nbytes' member of the sdata. So, sdata structures that are no
1264 longer used, can be easily recognized, and it's easy to compact the 1264 longer used, can be easily recognized, and it's easy to compact the
1265 sblocks of small strings which we do in compact_small_strings. */ 1265 sblocks of small strings which we do in compact_small_strings. */
1266 1266
@@ -1274,10 +1274,12 @@ mark_interval (register INTERVAL i, Lisp_Object dummy)
1274 1274
1275#define LARGE_STRING_BYTES 1024 1275#define LARGE_STRING_BYTES 1024
1276 1276
1277/* Structure describing string memory sub-allocated from an sblock. 1277/* Struct or union describing string memory sub-allocated from an sblock.
1278 This is where the contents of Lisp strings are stored. */ 1278 This is where the contents of Lisp strings are stored. */
1279 1279
1280struct sdata 1280#ifdef GC_CHECK_STRING_BYTES
1281
1282typedef struct
1281{ 1283{
1282 /* Back-pointer to the string this sdata belongs to. If null, this 1284 /* Back-pointer to the string this sdata belongs to. If null, this
1283 structure is free, and the NBYTES member of the union below 1285 structure is free, and the NBYTES member of the union below
@@ -1287,34 +1289,42 @@ struct sdata
1287 contents. */ 1289 contents. */
1288 struct Lisp_String *string; 1290 struct Lisp_String *string;
1289 1291
1290#ifdef GC_CHECK_STRING_BYTES
1291
1292 ptrdiff_t nbytes; 1292 ptrdiff_t nbytes;
1293 unsigned char data[1]; 1293 unsigned char data[FLEXIBLE_ARRAY_MEMBER];
1294} sdata;
1294 1295
1295#define SDATA_NBYTES(S) (S)->nbytes 1296#define SDATA_NBYTES(S) (S)->nbytes
1296#define SDATA_DATA(S) (S)->data 1297#define SDATA_DATA(S) (S)->data
1297#define SDATA_SELECTOR(member) member 1298#define SDATA_SELECTOR(member) member
1298 1299
1299#else /* not GC_CHECK_STRING_BYTES */ 1300#else
1300 1301
1301 union 1302typedef union
1303{
1304 struct Lisp_String *string;
1305
1306 /* When STRING is non-null. */
1307 struct
1302 { 1308 {
1303 /* When STRING is non-null. */ 1309 struct Lisp_String *string;
1304 unsigned char data[1]; 1310 unsigned char data[FLEXIBLE_ARRAY_MEMBER];
1311 } u;
1305 1312
1306 /* When STRING is null. */ 1313 /* When STRING is null. */
1314 struct
1315 {
1316 struct Lisp_String *string;
1307 ptrdiff_t nbytes; 1317 ptrdiff_t nbytes;
1308 } u; 1318 } n;
1319} sdata;
1309 1320
1310#define SDATA_NBYTES(S) (S)->u.nbytes 1321#define SDATA_NBYTES(S) (S)->n.nbytes
1311#define SDATA_DATA(S) (S)->u.data 1322#define SDATA_DATA(S) (S)->u.data
1312#define SDATA_SELECTOR(member) u.member 1323#define SDATA_SELECTOR(member) u.member
1313 1324
1314#endif /* not GC_CHECK_STRING_BYTES */ 1325#endif /* not GC_CHECK_STRING_BYTES */
1315 1326
1316#define SDATA_DATA_OFFSET offsetof (struct sdata, SDATA_SELECTOR (data)) 1327#define SDATA_DATA_OFFSET offsetof (sdata, SDATA_SELECTOR (data))
1317};
1318 1328
1319 1329
1320/* Structure describing a block of memory which is sub-allocated to 1330/* Structure describing a block of memory which is sub-allocated to
@@ -1329,10 +1339,10 @@ struct sblock
1329 1339
1330 /* Pointer to the next free sdata block. This points past the end 1340 /* Pointer to the next free sdata block. This points past the end
1331 of the sblock if there isn't any space left in this block. */ 1341 of the sblock if there isn't any space left in this block. */
1332 struct sdata *next_free; 1342 sdata *next_free;
1333 1343
1334 /* Start of data. */ 1344 /* Start of data. */
1335 struct sdata first_data; 1345 sdata first_data;
1336}; 1346};
1337 1347
1338/* Number of Lisp strings in a string_block structure. The 1020 is 1348/* Number of Lisp strings in a string_block structure. The 1020 is
@@ -1388,7 +1398,7 @@ static EMACS_INT total_string_bytes;
1388 a pointer to the `u.data' member of its sdata structure; the 1398 a pointer to the `u.data' member of its sdata structure; the
1389 structure starts at a constant offset in front of that. */ 1399 structure starts at a constant offset in front of that. */
1390 1400
1391#define SDATA_OF_STRING(S) ((struct sdata *) ((S)->data - SDATA_DATA_OFFSET)) 1401#define SDATA_OF_STRING(S) ((sdata *) ((S)->data - SDATA_DATA_OFFSET))
1392 1402
1393 1403
1394#ifdef GC_CHECK_STRING_OVERRUN 1404#ifdef GC_CHECK_STRING_OVERRUN
@@ -1487,7 +1497,7 @@ string_bytes (struct Lisp_String *s)
1487static void 1497static void
1488check_sblock (struct sblock *b) 1498check_sblock (struct sblock *b)
1489{ 1499{
1490 struct sdata *from, *end, *from_end; 1500 sdata *from, *end, *from_end;
1491 1501
1492 end = b->next_free; 1502 end = b->next_free;
1493 1503
@@ -1501,7 +1511,7 @@ check_sblock (struct sblock *b)
1501 same as the one recorded in the sdata structure. */ 1511 same as the one recorded in the sdata structure. */
1502 nbytes = SDATA_SIZE (from->string ? string_bytes (from->string) 1512 nbytes = SDATA_SIZE (from->string ? string_bytes (from->string)
1503 : SDATA_NBYTES (from)); 1513 : SDATA_NBYTES (from));
1504 from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); 1514 from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA);
1505 } 1515 }
1506} 1516}
1507 1517
@@ -1631,7 +1641,7 @@ void
1631allocate_string_data (struct Lisp_String *s, 1641allocate_string_data (struct Lisp_String *s,
1632 EMACS_INT nchars, EMACS_INT nbytes) 1642 EMACS_INT nchars, EMACS_INT nbytes)
1633{ 1643{
1634 struct sdata *data, *old_data; 1644 sdata *data, *old_data;
1635 struct sblock *b; 1645 struct sblock *b;
1636 ptrdiff_t needed, old_nbytes; 1646 ptrdiff_t needed, old_nbytes;
1637 1647
@@ -1701,7 +1711,7 @@ allocate_string_data (struct Lisp_String *s,
1701 b = current_sblock; 1711 b = current_sblock;
1702 1712
1703 data = b->next_free; 1713 data = b->next_free;
1704 b->next_free = (struct sdata *) ((char *) data + needed + GC_STRING_EXTRA); 1714 b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA);
1705 1715
1706 MALLOC_UNBLOCK_INPUT; 1716 MALLOC_UNBLOCK_INPUT;
1707 1717
@@ -1772,7 +1782,7 @@ sweep_strings (void)
1772 else 1782 else
1773 { 1783 {
1774 /* String is dead. Put it on the free-list. */ 1784 /* String is dead. Put it on the free-list. */
1775 struct sdata *data = SDATA_OF_STRING (s); 1785 sdata *data = SDATA_OF_STRING (s);
1776 1786
1777 /* Save the size of S in its sdata so that we know 1787 /* Save the size of S in its sdata so that we know
1778 how large that is. Reset the sdata's string 1788 how large that is. Reset the sdata's string
@@ -1781,7 +1791,7 @@ sweep_strings (void)
1781 if (string_bytes (s) != SDATA_NBYTES (data)) 1791 if (string_bytes (s) != SDATA_NBYTES (data))
1782 emacs_abort (); 1792 emacs_abort ();
1783#else 1793#else
1784 data->u.nbytes = STRING_BYTES (s); 1794 data->n.nbytes = STRING_BYTES (s);
1785#endif 1795#endif
1786 data->string = NULL; 1796 data->string = NULL;
1787 1797
@@ -1862,13 +1872,13 @@ static void
1862compact_small_strings (void) 1872compact_small_strings (void)
1863{ 1873{
1864 struct sblock *b, *tb, *next; 1874 struct sblock *b, *tb, *next;
1865 struct sdata *from, *to, *end, *tb_end; 1875 sdata *from, *to, *end, *tb_end;
1866 struct sdata *to_end, *from_end; 1876 sdata *to_end, *from_end;
1867 1877
1868 /* TB is the sblock we copy to, TO is the sdata within TB we copy 1878 /* TB is the sblock we copy to, TO is the sdata within TB we copy
1869 to, and TB_END is the end of TB. */ 1879 to, and TB_END is the end of TB. */
1870 tb = oldest_sblock; 1880 tb = oldest_sblock;
1871 tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); 1881 tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE);
1872 to = &tb->first_data; 1882 to = &tb->first_data;
1873 1883
1874 /* Step through the blocks from the oldest to the youngest. We 1884 /* Step through the blocks from the oldest to the youngest. We
@@ -1897,7 +1907,7 @@ compact_small_strings (void)
1897 eassert (nbytes <= LARGE_STRING_BYTES); 1907 eassert (nbytes <= LARGE_STRING_BYTES);
1898 1908
1899 nbytes = SDATA_SIZE (nbytes); 1909 nbytes = SDATA_SIZE (nbytes);
1900 from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); 1910 from_end = (sdata *) ((char *) from + nbytes + GC_STRING_EXTRA);
1901 1911
1902#ifdef GC_CHECK_STRING_OVERRUN 1912#ifdef GC_CHECK_STRING_OVERRUN
1903 if (memcmp (string_overrun_cookie, 1913 if (memcmp (string_overrun_cookie,
@@ -1910,14 +1920,14 @@ compact_small_strings (void)
1910 if (s) 1920 if (s)
1911 { 1921 {
1912 /* If TB is full, proceed with the next sblock. */ 1922 /* If TB is full, proceed with the next sblock. */
1913 to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); 1923 to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA);
1914 if (to_end > tb_end) 1924 if (to_end > tb_end)
1915 { 1925 {
1916 tb->next_free = to; 1926 tb->next_free = to;
1917 tb = tb->next; 1927 tb = tb->next;
1918 tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); 1928 tb_end = (sdata *) ((char *) tb + SBLOCK_SIZE);
1919 to = &tb->first_data; 1929 to = &tb->first_data;
1920 to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); 1930 to_end = (sdata *) ((char *) to + nbytes + GC_STRING_EXTRA);
1921 } 1931 }
1922 1932
1923 /* Copy, and update the string's `data' pointer. */ 1933 /* Copy, and update the string's `data' pointer. */
@@ -2581,7 +2591,7 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
2581 2591
2582/* Size of the minimal vector allocated from block. */ 2592/* Size of the minimal vector allocated from block. */
2583 2593
2584#define VBLOCK_BYTES_MIN vroundup (sizeof (struct Lisp_Vector)) 2594#define VBLOCK_BYTES_MIN vroundup (header_size + sizeof (Lisp_Object))
2585 2595
2586/* Size of the largest vector allocated from block. */ 2596/* Size of the largest vector allocated from block. */
2587 2597
@@ -2938,7 +2948,8 @@ allocate_vectorlike (ptrdiff_t len)
2938 else 2948 else
2939 { 2949 {
2940 struct large_vector *lv 2950 struct large_vector *lv
2941 = lisp_malloc (sizeof (*lv) + (len - 1) * word_size, 2951 = lisp_malloc ((offsetof (struct large_vector, v.contents)
2952 + len * word_size),
2942 MEM_TYPE_VECTORLIKE); 2953 MEM_TYPE_VECTORLIKE);
2943 lv->next.vector = large_vectors; 2954 lv->next.vector = large_vectors;
2944 large_vectors = lv; 2955 large_vectors = lv;
@@ -5416,7 +5427,8 @@ See Info node `(elisp)Garbage Collection'. */)
5416 total[4] = list3 (Qstring_bytes, make_number (1), 5427 total[4] = list3 (Qstring_bytes, make_number (1),
5417 bounded_number (total_string_bytes)); 5428 bounded_number (total_string_bytes));
5418 5429
5419 total[5] = list3 (Qvectors, make_number (sizeof (struct Lisp_Vector)), 5430 total[5] = list3 (Qvectors,
5431 make_number (header_size + sizeof (Lisp_Object)),
5420 bounded_number (total_vectors)); 5432 bounded_number (total_vectors));
5421 5433
5422 total[6] = list4 (Qvector_slots, make_number (word_size), 5434 total[6] = list4 (Qvector_slots, make_number (word_size),
diff --git a/src/chartab.c b/src/chartab.c
index 1c76e5a21e9..b7b9590a538 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -128,7 +128,7 @@ the char-table has no extra slot. */)
128 n_extras = XINT (n); 128 n_extras = XINT (n);
129 } 129 }
130 130
131 size = VECSIZE (struct Lisp_Char_Table) - 1 + n_extras; 131 size = CHAR_TABLE_STANDARD_SLOTS + n_extras;
132 vector = Fmake_vector (make_number (size), init); 132 vector = Fmake_vector (make_number (size), init);
133 XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE); 133 XSETPVECTYPE (XVECTOR (vector), PVEC_CHAR_TABLE);
134 set_char_table_parent (vector, Qnil); 134 set_char_table_parent (vector, Qnil);
@@ -141,7 +141,7 @@ static Lisp_Object
141make_sub_char_table (int depth, int min_char, Lisp_Object defalt) 141make_sub_char_table (int depth, int min_char, Lisp_Object defalt)
142{ 142{
143 Lisp_Object table; 143 Lisp_Object table;
144 int size = VECSIZE (struct Lisp_Sub_Char_Table) - 1 + chartab_size[depth]; 144 int size = CHAR_TABLE_STANDARD_SLOTS + chartab_size[depth];
145 145
146 table = Fmake_vector (make_number (size), defalt); 146 table = Fmake_vector (make_number (size), defalt);
147 XSETPVECTYPE (XVECTOR (table), PVEC_SUB_CHAR_TABLE); 147 XSETPVECTYPE (XVECTOR (table), PVEC_SUB_CHAR_TABLE);
@@ -207,7 +207,7 @@ copy_char_table (Lisp_Object table)
207 ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i]) 207 ? copy_sub_char_table (XCHAR_TABLE (table)->contents[i])
208 : XCHAR_TABLE (table)->contents[i])); 208 : XCHAR_TABLE (table)->contents[i]));
209 set_char_table_ascii (copy, char_table_ascii (copy)); 209 set_char_table_ascii (copy, char_table_ascii (copy));
210 size -= VECSIZE (struct Lisp_Char_Table) - 1; 210 size -= CHAR_TABLE_STANDARD_SLOTS;
211 for (i = 0; i < size; i++) 211 for (i = 0; i < size; i++)
212 set_char_table_extras (copy, i, XCHAR_TABLE (table)->extras[i]); 212 set_char_table_extras (copy, i, XCHAR_TABLE (table)->extras[i]);
213 213
diff --git a/src/conf_post.h b/src/conf_post.h
index 46aea32ef30..32c4341b7a3 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -243,6 +243,17 @@ extern void _DebPrint (const char *fmt, ...);
243#define INLINE_HEADER_BEGIN _GL_INLINE_HEADER_BEGIN 243#define INLINE_HEADER_BEGIN _GL_INLINE_HEADER_BEGIN
244#define INLINE_HEADER_END _GL_INLINE_HEADER_END 244#define INLINE_HEADER_END _GL_INLINE_HEADER_END
245 245
246/* To use the struct hack with N elements, declare the struct like this:
247 struct s { ...; t name[FLEXIBLE_ARRAY_MEMBER]; };
248 and allocate (offsetof (struct s, name) + N * sizeof (t)) bytes. */
249#if 199901 <= __STDC_VERSION__
250# define FLEXIBLE_ARRAY_MEMBER
251#elif __GNUC__ && !defined __STRICT_ANSI__
252# define FLEXIBLE_ARRAY_MEMBER 0
253#else
254# define FLEXIBLE_ARRAY_MEMBER 1
255#endif
256
246/* Use this to suppress gcc's `...may be used before initialized' warnings. */ 257/* Use this to suppress gcc's `...may be used before initialized' warnings. */
247#ifdef lint 258#ifdef lint
248/* Use CODE only if lint checking is in effect. */ 259/* Use CODE only if lint checking is in effect. */
diff --git a/src/image.c b/src/image.c
index f9f6ce70040..ffb3cd15e93 100644
--- a/src/image.c
+++ b/src/image.c
@@ -3057,7 +3057,7 @@ struct xpm_cached_color
3057 XColor color; 3057 XColor color;
3058 3058
3059 /* Color name. */ 3059 /* Color name. */
3060 char name[1]; 3060 char name[FLEXIBLE_ARRAY_MEMBER];
3061}; 3061};
3062 3062
3063/* The hash table used for the color cache, and its bucket vector 3063/* The hash table used for the color cache, and its bucket vector
diff --git a/src/lisp.h b/src/lisp.h
index e2d091e98f1..f4356cd140d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -1073,16 +1073,20 @@ SCHARS (Lisp_Object string)
1073{ 1073{
1074 return XSTRING (string)->size; 1074 return XSTRING (string)->size;
1075} 1075}
1076
1077#ifdef GC_CHECK_STRING_BYTES
1078extern ptrdiff_t string_bytes (struct Lisp_String *);
1079#endif
1076LISP_INLINE ptrdiff_t 1080LISP_INLINE ptrdiff_t
1077STRING_BYTES (struct Lisp_String *s) 1081STRING_BYTES (struct Lisp_String *s)
1078{ 1082{
1079#ifdef GC_CHECK_STRING_BYTES 1083#ifdef GC_CHECK_STRING_BYTES
1080 extern ptrdiff_t string_bytes (struct Lisp_String *);
1081 return string_bytes (s); 1084 return string_bytes (s);
1082#else 1085#else
1083 return s->size_byte < 0 ? s->size : s->size_byte; 1086 return s->size_byte < 0 ? s->size : s->size_byte;
1084#endif 1087#endif
1085} 1088}
1089
1086LISP_INLINE ptrdiff_t 1090LISP_INLINE ptrdiff_t
1087SBYTES (Lisp_Object string) 1091SBYTES (Lisp_Object string)
1088{ 1092{
@@ -1136,7 +1140,7 @@ struct vectorlike_header
1136struct Lisp_Vector 1140struct Lisp_Vector
1137 { 1141 {
1138 struct vectorlike_header header; 1142 struct vectorlike_header header;
1139 Lisp_Object contents[1]; 1143 Lisp_Object contents[FLEXIBLE_ARRAY_MEMBER];
1140 }; 1144 };
1141 1145
1142/* A boolvector is a kind of vectorlike, with contents are like a string. */ 1146/* A boolvector is a kind of vectorlike, with contents are like a string. */
@@ -1149,7 +1153,7 @@ struct Lisp_Bool_Vector
1149 /* This is the size in bits. */ 1153 /* This is the size in bits. */
1150 EMACS_INT size; 1154 EMACS_INT size;
1151 /* This contains the actual bits, packed into bytes. */ 1155 /* This contains the actual bits, packed into bytes. */
1152 unsigned char data[1]; 1156 unsigned char data[FLEXIBLE_ARRAY_MEMBER];
1153 }; 1157 };
1154 1158
1155/* Some handy constants for calculating sizes 1159/* Some handy constants for calculating sizes
@@ -1272,7 +1276,7 @@ struct Lisp_Char_Table
1272 Lisp_Object contents[(1 << CHARTAB_SIZE_BITS_0)]; 1276 Lisp_Object contents[(1 << CHARTAB_SIZE_BITS_0)];
1273 1277
1274 /* These hold additional data. It is a vector. */ 1278 /* These hold additional data. It is a vector. */
1275 Lisp_Object extras[1]; 1279 Lisp_Object extras[FLEXIBLE_ARRAY_MEMBER];
1276 }; 1280 };
1277 1281
1278struct Lisp_Sub_Char_Table 1282struct Lisp_Sub_Char_Table
@@ -1293,7 +1297,7 @@ struct Lisp_Sub_Char_Table
1293 Lisp_Object min_char; 1297 Lisp_Object min_char;
1294 1298
1295 /* Use set_sub_char_table_contents to set this. */ 1299 /* Use set_sub_char_table_contents to set this. */
1296 Lisp_Object contents[1]; 1300 Lisp_Object contents[FLEXIBLE_ARRAY_MEMBER];
1297 }; 1301 };
1298 1302
1299LISP_INLINE Lisp_Object 1303LISP_INLINE Lisp_Object
@@ -1366,7 +1370,7 @@ struct Lisp_Subr
1366 slots. */ 1370 slots. */
1367enum CHAR_TABLE_STANDARD_SLOTS 1371enum CHAR_TABLE_STANDARD_SLOTS
1368 { 1372 {
1369 CHAR_TABLE_STANDARD_SLOTS = VECSIZE (struct Lisp_Char_Table) - 1 1373 CHAR_TABLE_STANDARD_SLOTS = PSEUDOVECSIZE (struct Lisp_Char_Table, extras)
1370 }; 1374 };
1371 1375
1372/* Return the number of "extra" slots in the char table CT. */ 1376/* Return the number of "extra" slots in the char table CT. */
diff --git a/src/w32.c b/src/w32.c
index 7a39a617ee3..230479cd61a 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -3785,12 +3785,6 @@ get_rid (PSID sid)
3785 3785
3786/* Caching SID and account values for faster lokup. */ 3786/* Caching SID and account values for faster lokup. */
3787 3787
3788#ifdef __GNUC__
3789# define FLEXIBLE_ARRAY_MEMBER
3790#else
3791# define FLEXIBLE_ARRAY_MEMBER 1
3792#endif
3793
3794struct w32_id { 3788struct w32_id {
3795 unsigned rid; 3789 unsigned rid;
3796 struct w32_id *next; 3790 struct w32_id *next;