aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Eggert2019-04-01 11:54:23 -0700
committerPaul Eggert2019-04-01 12:02:37 -0700
commit9287813da1ae9076f29be111674d1795bee66447 (patch)
treed48781deb3ccc24f40de2944efdccc6a84280fd5 /src
parent197fbfc71f49b307baa3831a30732c3a0c4c7420 (diff)
downloademacs-9287813da1ae9076f29be111674d1795bee66447.tar.gz
emacs-9287813da1ae9076f29be111674d1795bee66447.zip
Fix union Lisp_Fwd * alignment bug
It's not portable to cast (e.g.) struct Lisp_Objfwd * to union Lisp_Fwd * and then back again, because the compiler can then assume that the pointer is aligned for union Lisp_Fwd * when accessing the struct Lisp_Objfwd * components, and this assumption might be incorrect becase we don't force that alignment. * src/lisp.h (lispfwd): New type, replacing ... (union Lisp_Fwd): ... this type, which was removed. All uses changed. (SET_SYMBOL_FWD): 2nd arg is now void *, not lispfwd. All uses changed (casts no longer needed; they were not portable anyway).
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c8
-rw-r--r--src/data.c74
-rw-r--r--src/lisp.h41
-rw-r--r--src/lread.c8
-rw-r--r--src/pdumper.c26
5 files changed, 80 insertions, 77 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 7c4691e52c0..c0f7521c9e1 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1207,7 +1207,7 @@ buffer_local_value (Lisp_Object variable, Lisp_Object buffer)
1207 result = Fassoc (variable, BVAR (buf, local_var_alist), Qnil); 1207 result = Fassoc (variable, BVAR (buf, local_var_alist), Qnil);
1208 if (!NILP (result)) 1208 if (!NILP (result))
1209 { 1209 {
1210 if (blv->fwd) 1210 if (blv->fwd.fwdptr)
1211 { /* What binding is loaded right now? */ 1211 { /* What binding is loaded right now? */
1212 Lisp_Object current_alist_element = blv->valcell; 1212 Lisp_Object current_alist_element = blv->valcell;
1213 1213
@@ -1228,7 +1228,7 @@ buffer_local_value (Lisp_Object variable, Lisp_Object buffer)
1228 } 1228 }
1229 case SYMBOL_FORWARDED: 1229 case SYMBOL_FORWARDED:
1230 { 1230 {
1231 union Lisp_Fwd *fwd = SYMBOL_FWD (sym); 1231 lispfwd fwd = SYMBOL_FWD (sym);
1232 if (BUFFER_OBJFWDP (fwd)) 1232 if (BUFFER_OBJFWDP (fwd))
1233 result = per_buffer_value (buf, XBUFFER_OBJFWD (fwd)->offset); 1233 result = per_buffer_value (buf, XBUFFER_OBJFWD (fwd)->offset);
1234 else 1234 else
@@ -2140,7 +2140,7 @@ void set_buffer_internal_2 (register struct buffer *b)
2140 Lisp_Object var = XCAR (XCAR (tail)); 2140 Lisp_Object var = XCAR (XCAR (tail));
2141 struct Lisp_Symbol *sym = XSYMBOL (var); 2141 struct Lisp_Symbol *sym = XSYMBOL (var);
2142 if (sym->u.s.redirect == SYMBOL_LOCALIZED /* Just to be sure. */ 2142 if (sym->u.s.redirect == SYMBOL_LOCALIZED /* Just to be sure. */
2143 && SYMBOL_BLV (sym)->fwd) 2143 && SYMBOL_BLV (sym)->fwd.fwdptr)
2144 /* Just reference the variable 2144 /* Just reference the variable
2145 to cause it to become set for this buffer. */ 2145 to cause it to become set for this buffer. */
2146 Fsymbol_value (var); 2146 Fsymbol_value (var);
@@ -5444,7 +5444,7 @@ defvar_per_buffer (struct Lisp_Buffer_Objfwd *bo_fwd, const char *namestring,
5444 bo_fwd->predicate = predicate; 5444 bo_fwd->predicate = predicate;
5445 sym->u.s.declared_special = true; 5445 sym->u.s.declared_special = true;
5446 sym->u.s.redirect = SYMBOL_FORWARDED; 5446 sym->u.s.redirect = SYMBOL_FORWARDED;
5447 SET_SYMBOL_FWD (sym, (union Lisp_Fwd *) bo_fwd); 5447 SET_SYMBOL_FWD (sym, bo_fwd);
5448 XSETSYMBOL (PER_BUFFER_SYMBOL (offset), sym); 5448 XSETSYMBOL (PER_BUFFER_SYMBOL (offset), sym);
5449 5449
5450 if (PER_BUFFER_IDX (offset) == 0) 5450 if (PER_BUFFER_IDX (offset) == 0)
diff --git a/src/data.c b/src/data.c
index 30c578dee94..936bb74f69a 100644
--- a/src/data.c
+++ b/src/data.c
@@ -42,49 +42,49 @@ static void swap_in_symval_forwarding (struct Lisp_Symbol *,
42 struct Lisp_Buffer_Local_Value *); 42 struct Lisp_Buffer_Local_Value *);
43 43
44static bool 44static bool
45BOOLFWDP (union Lisp_Fwd *a) 45BOOLFWDP (lispfwd a)
46{ 46{
47 return XFWDTYPE (a) == Lisp_Fwd_Bool; 47 return XFWDTYPE (a) == Lisp_Fwd_Bool;
48} 48}
49static bool 49static bool
50INTFWDP (union Lisp_Fwd *a) 50INTFWDP (lispfwd a)
51{ 51{
52 return XFWDTYPE (a) == Lisp_Fwd_Int; 52 return XFWDTYPE (a) == Lisp_Fwd_Int;
53} 53}
54static bool 54static bool
55KBOARD_OBJFWDP (union Lisp_Fwd *a) 55KBOARD_OBJFWDP (lispfwd a)
56{ 56{
57 return XFWDTYPE (a) == Lisp_Fwd_Kboard_Obj; 57 return XFWDTYPE (a) == Lisp_Fwd_Kboard_Obj;
58} 58}
59static bool 59static bool
60OBJFWDP (union Lisp_Fwd *a) 60OBJFWDP (lispfwd a)
61{ 61{
62 return XFWDTYPE (a) == Lisp_Fwd_Obj; 62 return XFWDTYPE (a) == Lisp_Fwd_Obj;
63} 63}
64 64
65static struct Lisp_Boolfwd * 65static struct Lisp_Boolfwd *
66XBOOLFWD (union Lisp_Fwd *a) 66XBOOLFWD (lispfwd a)
67{ 67{
68 eassert (BOOLFWDP (a)); 68 eassert (BOOLFWDP (a));
69 return &a->u_boolfwd; 69 return a.fwdptr;
70} 70}
71static struct Lisp_Kboard_Objfwd * 71static struct Lisp_Kboard_Objfwd *
72XKBOARD_OBJFWD (union Lisp_Fwd *a) 72XKBOARD_OBJFWD (lispfwd a)
73{ 73{
74 eassert (KBOARD_OBJFWDP (a)); 74 eassert (KBOARD_OBJFWDP (a));
75 return &a->u_kboard_objfwd; 75 return a.fwdptr;
76} 76}
77static struct Lisp_Intfwd * 77static struct Lisp_Intfwd *
78XFIXNUMFWD (union Lisp_Fwd *a) 78XFIXNUMFWD (lispfwd a)
79{ 79{
80 eassert (INTFWDP (a)); 80 eassert (INTFWDP (a));
81 return &a->u_intfwd; 81 return a.fwdptr;
82} 82}
83static struct Lisp_Objfwd * 83static struct Lisp_Objfwd *
84XOBJFWD (union Lisp_Fwd *a) 84XOBJFWD (lispfwd a)
85{ 85{
86 eassert (OBJFWDP (a)); 86 eassert (OBJFWDP (a));
87 return &a->u_objfwd; 87 return a.fwdptr;
88} 88}
89 89
90static void 90static void
@@ -669,7 +669,7 @@ global value outside of any lexical scope. */)
669 case SYMBOL_LOCALIZED: 669 case SYMBOL_LOCALIZED:
670 { 670 {
671 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); 671 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
672 if (blv->fwd) 672 if (blv->fwd.fwdptr)
673 /* In set_internal, we un-forward vars when their value is 673 /* In set_internal, we un-forward vars when their value is
674 set to Qunbound. */ 674 set to Qunbound. */
675 return Qt; 675 return Qt;
@@ -980,7 +980,7 @@ chain of aliases, signal a `cyclic-variable-indirection' error. */)
980 swap_in_symval_forwarding for that. */ 980 swap_in_symval_forwarding for that. */
981 981
982Lisp_Object 982Lisp_Object
983do_symval_forwarding (union Lisp_Fwd *valcontents) 983do_symval_forwarding (lispfwd valcontents)
984{ 984{
985 switch (XFWDTYPE (valcontents)) 985 switch (XFWDTYPE (valcontents))
986 { 986 {
@@ -1071,7 +1071,8 @@ wrong_range (Lisp_Object min, Lisp_Object max, Lisp_Object wrong)
1071 current buffer. This only plays a role for per-buffer variables. */ 1071 current buffer. This only plays a role for per-buffer variables. */
1072 1072
1073static void 1073static void
1074store_symval_forwarding (union Lisp_Fwd *valcontents, register Lisp_Object newval, struct buffer *buf) 1074store_symval_forwarding (lispfwd valcontents, Lisp_Object newval,
1075 struct buffer *buf)
1075{ 1076{
1076 switch (XFWDTYPE (valcontents)) 1077 switch (XFWDTYPE (valcontents))
1077 { 1078 {
@@ -1178,12 +1179,12 @@ swap_in_global_binding (struct Lisp_Symbol *symbol)
1178 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (symbol); 1179 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (symbol);
1179 1180
1180 /* Unload the previously loaded binding. */ 1181 /* Unload the previously loaded binding. */
1181 if (blv->fwd) 1182 if (blv->fwd.fwdptr)
1182 set_blv_value (blv, do_symval_forwarding (blv->fwd)); 1183 set_blv_value (blv, do_symval_forwarding (blv->fwd));
1183 1184
1184 /* Select the global binding in the symbol. */ 1185 /* Select the global binding in the symbol. */
1185 set_blv_valcell (blv, blv->defcell); 1186 set_blv_valcell (blv, blv->defcell);
1186 if (blv->fwd) 1187 if (blv->fwd.fwdptr)
1187 store_symval_forwarding (blv->fwd, XCDR (blv->defcell), NULL); 1188 store_symval_forwarding (blv->fwd, XCDR (blv->defcell), NULL);
1188 1189
1189 /* Indicate that the global binding is set up now. */ 1190 /* Indicate that the global binding is set up now. */
@@ -1213,7 +1214,7 @@ swap_in_symval_forwarding (struct Lisp_Symbol *symbol, struct Lisp_Buffer_Local_
1213 1214
1214 /* Unload the previously loaded binding. */ 1215 /* Unload the previously loaded binding. */
1215 tem1 = blv->valcell; 1216 tem1 = blv->valcell;
1216 if (blv->fwd) 1217 if (blv->fwd.fwdptr)
1217 set_blv_value (blv, do_symval_forwarding (blv->fwd)); 1218 set_blv_value (blv, do_symval_forwarding (blv->fwd));
1218 /* Choose the new binding. */ 1219 /* Choose the new binding. */
1219 { 1220 {
@@ -1227,7 +1228,7 @@ swap_in_symval_forwarding (struct Lisp_Symbol *symbol, struct Lisp_Buffer_Local_
1227 1228
1228 /* Load the new binding. */ 1229 /* Load the new binding. */
1229 set_blv_valcell (blv, tem1); 1230 set_blv_valcell (blv, tem1);
1230 if (blv->fwd) 1231 if (blv->fwd.fwdptr)
1231 store_symval_forwarding (blv->fwd, blv_value (blv), NULL); 1232 store_symval_forwarding (blv->fwd, blv_value (blv), NULL);
1232 } 1233 }
1233} 1234}
@@ -1255,7 +1256,9 @@ find_symbol_value (Lisp_Object symbol)
1255 { 1256 {
1256 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); 1257 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
1257 swap_in_symval_forwarding (sym, blv); 1258 swap_in_symval_forwarding (sym, blv);
1258 return blv->fwd ? do_symval_forwarding (blv->fwd) : blv_value (blv); 1259 return (blv->fwd.fwdptr
1260 ? do_symval_forwarding (blv->fwd)
1261 : blv_value (blv));
1259 } 1262 }
1260 case SYMBOL_FORWARDED: 1263 case SYMBOL_FORWARDED:
1261 return do_symval_forwarding (SYMBOL_FWD (sym)); 1264 return do_symval_forwarding (SYMBOL_FWD (sym));
@@ -1357,7 +1360,7 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
1357 We need to unload it, and choose a new binding. */ 1360 We need to unload it, and choose a new binding. */
1358 1361
1359 /* Write out `realvalue' to the old loaded binding. */ 1362 /* Write out `realvalue' to the old loaded binding. */
1360 if (blv->fwd) 1363 if (blv->fwd.fwdptr)
1361 set_blv_value (blv, do_symval_forwarding (blv->fwd)); 1364 set_blv_value (blv, do_symval_forwarding (blv->fwd));
1362 1365
1363 /* Find the new binding. */ 1366 /* Find the new binding. */
@@ -1404,12 +1407,12 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
1404 /* Store the new value in the cons cell. */ 1407 /* Store the new value in the cons cell. */
1405 set_blv_value (blv, newval); 1408 set_blv_value (blv, newval);
1406 1409
1407 if (blv->fwd) 1410 if (blv->fwd.fwdptr)
1408 { 1411 {
1409 if (voide) 1412 if (voide)
1410 /* If storing void (making the symbol void), forward only through 1413 /* If storing void (making the symbol void), forward only through
1411 buffer-local indicator, not through Lisp_Objfwd, etc. */ 1414 buffer-local indicator, not through Lisp_Objfwd, etc. */
1412 blv->fwd = NULL; 1415 blv->fwd.fwdptr = NULL;
1413 else 1416 else
1414 store_symval_forwarding (blv->fwd, newval, 1417 store_symval_forwarding (blv->fwd, newval,
1415 BUFFERP (where) 1418 BUFFERP (where)
@@ -1421,7 +1424,7 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
1421 { 1424 {
1422 struct buffer *buf 1425 struct buffer *buf
1423 = BUFFERP (where) ? XBUFFER (where) : current_buffer; 1426 = BUFFERP (where) ? XBUFFER (where) : current_buffer;
1424 union Lisp_Fwd *innercontents = SYMBOL_FWD (sym); 1427 lispfwd innercontents = SYMBOL_FWD (sym);
1425 if (BUFFER_OBJFWDP (innercontents)) 1428 if (BUFFER_OBJFWDP (innercontents))
1426 { 1429 {
1427 int offset = XBUFFER_OBJFWD (innercontents)->offset; 1430 int offset = XBUFFER_OBJFWD (innercontents)->offset;
@@ -1593,14 +1596,14 @@ default_value (Lisp_Object symbol)
1593 But the `realvalue' slot may be more up to date, since 1596 But the `realvalue' slot may be more up to date, since
1594 ordinary setq stores just that slot. So use that. */ 1597 ordinary setq stores just that slot. So use that. */
1595 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym); 1598 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
1596 if (blv->fwd && EQ (blv->valcell, blv->defcell)) 1599 if (blv->fwd.fwdptr && EQ (blv->valcell, blv->defcell))
1597 return do_symval_forwarding (blv->fwd); 1600 return do_symval_forwarding (blv->fwd);
1598 else 1601 else
1599 return XCDR (blv->defcell); 1602 return XCDR (blv->defcell);
1600 } 1603 }
1601 case SYMBOL_FORWARDED: 1604 case SYMBOL_FORWARDED:
1602 { 1605 {
1603 union Lisp_Fwd *valcontents = SYMBOL_FWD (sym); 1606 lispfwd valcontents = SYMBOL_FWD (sym);
1604 1607
1605 /* For a built-in buffer-local variable, get the default value 1608 /* For a built-in buffer-local variable, get the default value
1606 rather than letting do_symval_forwarding get the current value. */ 1609 rather than letting do_symval_forwarding get the current value. */
@@ -1688,13 +1691,13 @@ set_default_internal (Lisp_Object symbol, Lisp_Object value,
1688 XSETCDR (blv->defcell, value); 1691 XSETCDR (blv->defcell, value);
1689 1692
1690 /* If the default binding is now loaded, set the REALVALUE slot too. */ 1693 /* If the default binding is now loaded, set the REALVALUE slot too. */
1691 if (blv->fwd && EQ (blv->defcell, blv->valcell)) 1694 if (blv->fwd.fwdptr && EQ (blv->defcell, blv->valcell))
1692 store_symval_forwarding (blv->fwd, value, NULL); 1695 store_symval_forwarding (blv->fwd, value, NULL);
1693 return; 1696 return;
1694 } 1697 }
1695 case SYMBOL_FORWARDED: 1698 case SYMBOL_FORWARDED:
1696 { 1699 {
1697 union Lisp_Fwd *valcontents = SYMBOL_FWD (sym); 1700 lispfwd valcontents = SYMBOL_FWD (sym);
1698 1701
1699 /* Handle variables like case-fold-search that have special slots 1702 /* Handle variables like case-fold-search that have special slots
1700 in the buffer. 1703 in the buffer.
@@ -1750,7 +1753,7 @@ for this variable. */)
1750union Lisp_Val_Fwd 1753union Lisp_Val_Fwd
1751 { 1754 {
1752 Lisp_Object value; 1755 Lisp_Object value;
1753 union Lisp_Fwd *fwd; 1756 lispfwd fwd;
1754 }; 1757 };
1755 1758
1756static struct Lisp_Buffer_Local_Value * 1759static struct Lisp_Buffer_Local_Value *
@@ -1770,7 +1773,10 @@ make_blv (struct Lisp_Symbol *sym, bool forwarded,
1770 or keyboard-local forwarding. */ 1773 or keyboard-local forwarding. */
1771 eassert (!(forwarded && BUFFER_OBJFWDP (valcontents.fwd))); 1774 eassert (!(forwarded && BUFFER_OBJFWDP (valcontents.fwd)));
1772 eassert (!(forwarded && KBOARD_OBJFWDP (valcontents.fwd))); 1775 eassert (!(forwarded && KBOARD_OBJFWDP (valcontents.fwd)));
1773 blv->fwd = forwarded ? valcontents.fwd : NULL; 1776 if (forwarded)
1777 blv->fwd = valcontents.fwd;
1778 else
1779 blv->fwd.fwdptr = NULL;
1774 set_blv_where (blv, Qnil); 1780 set_blv_where (blv, Qnil);
1775 blv->local_if_set = 0; 1781 blv->local_if_set = 0;
1776 set_blv_defcell (blv, tem); 1782 set_blv_defcell (blv, tem);
@@ -1941,7 +1947,7 @@ Instead, use `add-hook' and specify t for the LOCAL argument. */)
1941 Otherwise, if C code modifies the variable before we load the 1947 Otherwise, if C code modifies the variable before we load the
1942 binding in, then that new value would clobber the default binding 1948 binding in, then that new value would clobber the default binding
1943 the next time we unload it. See bug#34318. */ 1949 the next time we unload it. See bug#34318. */
1944 if (blv->fwd) 1950 if (blv->fwd.fwdptr)
1945 swap_in_symval_forwarding (sym, blv); 1951 swap_in_symval_forwarding (sym, blv);
1946 } 1952 }
1947 1953
@@ -1968,7 +1974,7 @@ From now on the default value will apply in this buffer. Return VARIABLE. */)
1968 case SYMBOL_PLAINVAL: return variable; 1974 case SYMBOL_PLAINVAL: return variable;
1969 case SYMBOL_FORWARDED: 1975 case SYMBOL_FORWARDED:
1970 { 1976 {
1971 union Lisp_Fwd *valcontents = SYMBOL_FWD (sym); 1977 lispfwd valcontents = SYMBOL_FWD (sym);
1972 if (BUFFER_OBJFWDP (valcontents)) 1978 if (BUFFER_OBJFWDP (valcontents))
1973 { 1979 {
1974 int offset = XBUFFER_OBJFWD (valcontents)->offset; 1980 int offset = XBUFFER_OBJFWD (valcontents)->offset;
@@ -2051,7 +2057,7 @@ BUFFER defaults to the current buffer. */)
2051 } 2057 }
2052 case SYMBOL_FORWARDED: 2058 case SYMBOL_FORWARDED:
2053 { 2059 {
2054 union Lisp_Fwd *valcontents = SYMBOL_FWD (sym); 2060 lispfwd valcontents = SYMBOL_FWD (sym);
2055 if (BUFFER_OBJFWDP (valcontents)) 2061 if (BUFFER_OBJFWDP (valcontents))
2056 { 2062 {
2057 int offset = XBUFFER_OBJFWD (valcontents)->offset; 2063 int offset = XBUFFER_OBJFWD (valcontents)->offset;
@@ -2122,7 +2128,7 @@ If the current binding is global (the default), the value is nil. */)
2122 case SYMBOL_PLAINVAL: return Qnil; 2128 case SYMBOL_PLAINVAL: return Qnil;
2123 case SYMBOL_FORWARDED: 2129 case SYMBOL_FORWARDED:
2124 { 2130 {
2125 union Lisp_Fwd *valcontents = SYMBOL_FWD (sym); 2131 lispfwd valcontents = SYMBOL_FWD (sym);
2126 if (KBOARD_OBJFWDP (valcontents)) 2132 if (KBOARD_OBJFWDP (valcontents))
2127 return Fframe_terminal (selected_frame); 2133 return Fframe_terminal (selected_frame);
2128 else if (!BUFFER_OBJFWDP (valcontents)) 2134 else if (!BUFFER_OBJFWDP (valcontents))
diff --git a/src/lisp.h b/src/lisp.h
index 178eebed2a5..62c3230a148 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -797,6 +797,13 @@ INLINE void
797 797
798#define XUNTAG(a, type, ctype) ((ctype *) \ 798#define XUNTAG(a, type, ctype) ((ctype *) \
799 ((char *) XLP (a) - LISP_WORD_TAG (type))) 799 ((char *) XLP (a) - LISP_WORD_TAG (type)))
800
801/* A forwarding pointer to a value. It uses a generic pointer to
802 avoid alignment bugs that could occur if it used a pointer to a
803 union of the possible values (struct Lisp_Objfwd, struct
804 Lisp_Intfwd, etc.). The pointer is packaged inside a struct to
805 help static checking. */
806typedef struct { void *fwdptr; } lispfwd;
800 807
801/* Interned state of a symbol. */ 808/* Interned state of a symbol. */
802 809
@@ -862,7 +869,7 @@ struct Lisp_Symbol
862 Lisp_Object value; 869 Lisp_Object value;
863 struct Lisp_Symbol *alias; 870 struct Lisp_Symbol *alias;
864 struct Lisp_Buffer_Local_Value *blv; 871 struct Lisp_Buffer_Local_Value *blv;
865 union Lisp_Fwd *fwd; 872 lispfwd fwd;
866 } val; 873 } val;
867 874
868 /* Function value of the symbol or Qnil if not fboundp. */ 875 /* Function value of the symbol or Qnil if not fboundp. */
@@ -2171,10 +2178,10 @@ SYMBOL_BLV (struct Lisp_Symbol *sym)
2171 eassume (sym->u.s.redirect == SYMBOL_LOCALIZED && sym->u.s.val.blv); 2178 eassume (sym->u.s.redirect == SYMBOL_LOCALIZED && sym->u.s.val.blv);
2172 return sym->u.s.val.blv; 2179 return sym->u.s.val.blv;
2173} 2180}
2174INLINE union Lisp_Fwd * 2181INLINE lispfwd
2175SYMBOL_FWD (struct Lisp_Symbol *sym) 2182SYMBOL_FWD (struct Lisp_Symbol *sym)
2176{ 2183{
2177 eassume (sym->u.s.redirect == SYMBOL_FORWARDED && sym->u.s.val.fwd); 2184 eassume (sym->u.s.redirect == SYMBOL_FORWARDED && sym->u.s.val.fwd.fwdptr);
2178 return sym->u.s.val.fwd; 2185 return sym->u.s.val.fwd;
2179} 2186}
2180 2187
@@ -2197,10 +2204,10 @@ SET_SYMBOL_BLV (struct Lisp_Symbol *sym, struct Lisp_Buffer_Local_Value *v)
2197 sym->u.s.val.blv = v; 2204 sym->u.s.val.blv = v;
2198} 2205}
2199INLINE void 2206INLINE void
2200SET_SYMBOL_FWD (struct Lisp_Symbol *sym, union Lisp_Fwd *v) 2207SET_SYMBOL_FWD (struct Lisp_Symbol *sym, void *v)
2201{ 2208{
2202 eassume (sym->u.s.redirect == SYMBOL_FORWARDED && v); 2209 eassume (sym->u.s.redirect == SYMBOL_FORWARDED && v);
2203 sym->u.s.val.fwd = v; 2210 sym->u.s.val.fwd.fwdptr = v;
2204} 2211}
2205 2212
2206INLINE Lisp_Object 2213INLINE Lisp_Object
@@ -2727,7 +2734,7 @@ struct Lisp_Buffer_Local_Value
2727 Presumably equivalent to (defcell!=valcell). */ 2734 Presumably equivalent to (defcell!=valcell). */
2728 bool_bf found : 1; 2735 bool_bf found : 1;
2729 /* If non-NULL, a forwarding to the C var where it should also be set. */ 2736 /* If non-NULL, a forwarding to the C var where it should also be set. */
2730 union Lisp_Fwd *fwd; /* Should never be (Buffer|Kboard)_Objfwd. */ 2737 lispfwd fwd; /* Should never be (Buffer|Kboard)_Objfwd. */
2731 /* The buffer for which the loaded binding was found. */ 2738 /* The buffer for which the loaded binding was found. */
2732 Lisp_Object where; 2739 Lisp_Object where;
2733 /* A cons cell that holds the default value. It has the form 2740 /* A cons cell that holds the default value. It has the form
@@ -2749,32 +2756,24 @@ struct Lisp_Kboard_Objfwd
2749 int offset; 2756 int offset;
2750 }; 2757 };
2751 2758
2752union Lisp_Fwd
2753 {
2754 struct Lisp_Intfwd u_intfwd;
2755 struct Lisp_Boolfwd u_boolfwd;
2756 struct Lisp_Objfwd u_objfwd;
2757 struct Lisp_Buffer_Objfwd u_buffer_objfwd;
2758 struct Lisp_Kboard_Objfwd u_kboard_objfwd;
2759 };
2760
2761INLINE enum Lisp_Fwd_Type 2759INLINE enum Lisp_Fwd_Type
2762XFWDTYPE (union Lisp_Fwd *a) 2760XFWDTYPE (lispfwd a)
2763{ 2761{
2764 return a->u_intfwd.type; 2762 enum Lisp_Fwd_Type *p = a.fwdptr;
2763 return *p;
2765} 2764}
2766 2765
2767INLINE bool 2766INLINE bool
2768BUFFER_OBJFWDP (union Lisp_Fwd *a) 2767BUFFER_OBJFWDP (lispfwd a)
2769{ 2768{
2770 return XFWDTYPE (a) == Lisp_Fwd_Buffer_Obj; 2769 return XFWDTYPE (a) == Lisp_Fwd_Buffer_Obj;
2771} 2770}
2772 2771
2773INLINE struct Lisp_Buffer_Objfwd * 2772INLINE struct Lisp_Buffer_Objfwd *
2774XBUFFER_OBJFWD (union Lisp_Fwd *a) 2773XBUFFER_OBJFWD (lispfwd a)
2775{ 2774{
2776 eassert (BUFFER_OBJFWDP (a)); 2775 eassert (BUFFER_OBJFWDP (a));
2777 return &a->u_buffer_objfwd; 2776 return a.fwdptr;
2778} 2777}
2779 2778
2780/* Lisp floating point type. */ 2779/* Lisp floating point type. */
@@ -3552,7 +3551,7 @@ extern _Noreturn void args_out_of_range (Lisp_Object, Lisp_Object);
3552extern _Noreturn void args_out_of_range_3 (Lisp_Object, Lisp_Object, 3551extern _Noreturn void args_out_of_range_3 (Lisp_Object, Lisp_Object,
3553 Lisp_Object); 3552 Lisp_Object);
3554extern _Noreturn void circular_list (Lisp_Object); 3553extern _Noreturn void circular_list (Lisp_Object);
3555extern Lisp_Object do_symval_forwarding (union Lisp_Fwd *); 3554extern Lisp_Object do_symval_forwarding (lispfwd);
3556enum Set_Internal_Bind { 3555enum Set_Internal_Bind {
3557 SET_INTERNAL_SET, 3556 SET_INTERNAL_SET,
3558 SET_INTERNAL_BIND, 3557 SET_INTERNAL_BIND,
diff --git a/src/lread.c b/src/lread.c
index 2d64b638ff5..dd35cf9063e 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -4434,7 +4434,7 @@ defvar_int (struct Lisp_Intfwd *i_fwd,
4434 i_fwd->intvar = address; 4434 i_fwd->intvar = address;
4435 XSYMBOL (sym)->u.s.declared_special = true; 4435 XSYMBOL (sym)->u.s.declared_special = true;
4436 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; 4436 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED;
4437 SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)i_fwd); 4437 SET_SYMBOL_FWD (XSYMBOL (sym), i_fwd);
4438} 4438}
4439 4439
4440/* Similar but define a variable whose value is t if address contains 1, 4440/* Similar but define a variable whose value is t if address contains 1,
@@ -4449,7 +4449,7 @@ defvar_bool (struct Lisp_Boolfwd *b_fwd,
4449 b_fwd->boolvar = address; 4449 b_fwd->boolvar = address;
4450 XSYMBOL (sym)->u.s.declared_special = true; 4450 XSYMBOL (sym)->u.s.declared_special = true;
4451 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; 4451 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED;
4452 SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)b_fwd); 4452 SET_SYMBOL_FWD (XSYMBOL (sym), b_fwd);
4453 Vbyte_boolean_vars = Fcons (sym, Vbyte_boolean_vars); 4453 Vbyte_boolean_vars = Fcons (sym, Vbyte_boolean_vars);
4454} 4454}
4455 4455
@@ -4468,7 +4468,7 @@ defvar_lisp_nopro (struct Lisp_Objfwd *o_fwd,
4468 o_fwd->objvar = address; 4468 o_fwd->objvar = address;
4469 XSYMBOL (sym)->u.s.declared_special = true; 4469 XSYMBOL (sym)->u.s.declared_special = true;
4470 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; 4470 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED;
4471 SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)o_fwd); 4471 SET_SYMBOL_FWD (XSYMBOL (sym), o_fwd);
4472} 4472}
4473 4473
4474void 4474void
@@ -4492,7 +4492,7 @@ defvar_kboard (struct Lisp_Kboard_Objfwd *ko_fwd,
4492 ko_fwd->offset = offset; 4492 ko_fwd->offset = offset;
4493 XSYMBOL (sym)->u.s.declared_special = true; 4493 XSYMBOL (sym)->u.s.declared_special = true;
4494 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED; 4494 XSYMBOL (sym)->u.s.redirect = SYMBOL_FORWARDED;
4495 SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)ko_fwd); 4495 SET_SYMBOL_FWD (XSYMBOL (sym), ko_fwd);
4496} 4496}
4497 4497
4498/* Check that the elements of lpath exist. */ 4498/* Check that the elements of lpath exist. */
diff --git a/src/pdumper.c b/src/pdumper.c
index a9b3732a2d4..53a10b62b3f 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2334,32 +2334,30 @@ dump_fwd_kboard_obj (struct dump_context *ctx,
2334} 2334}
2335 2335
2336static dump_off 2336static dump_off
2337dump_fwd (struct dump_context *ctx, union Lisp_Fwd *fwd) 2337dump_fwd (struct dump_context *ctx, lispfwd fwd)
2338{ 2338{
2339#if CHECK_STRUCTS && !defined (HASH_Lisp_Fwd_5227B18E87)
2340# error "Lisp_Fwd changed. See CHECK_STRUCTS comment."
2341#endif
2342#if CHECK_STRUCTS && !defined (HASH_Lisp_Fwd_Type_9CBA6EE55E) 2339#if CHECK_STRUCTS && !defined (HASH_Lisp_Fwd_Type_9CBA6EE55E)
2343# error "Lisp_Fwd_Type changed. See CHECK_STRUCTS comment." 2340# error "Lisp_Fwd_Type changed. See CHECK_STRUCTS comment."
2344#endif 2341#endif
2342 void const *p = fwd.fwdptr;
2345 dump_off offset; 2343 dump_off offset;
2346 2344
2347 switch (XFWDTYPE (fwd)) 2345 switch (XFWDTYPE (fwd))
2348 { 2346 {
2349 case Lisp_Fwd_Int: 2347 case Lisp_Fwd_Int:
2350 offset = dump_fwd_int (ctx, &fwd->u_intfwd); 2348 offset = dump_fwd_int (ctx, p);
2351 break; 2349 break;
2352 case Lisp_Fwd_Bool: 2350 case Lisp_Fwd_Bool:
2353 offset = dump_fwd_bool (ctx, &fwd->u_boolfwd); 2351 offset = dump_fwd_bool (ctx, p);
2354 break; 2352 break;
2355 case Lisp_Fwd_Obj: 2353 case Lisp_Fwd_Obj:
2356 offset = dump_fwd_obj (ctx, &fwd->u_objfwd); 2354 offset = dump_fwd_obj (ctx, p);
2357 break; 2355 break;
2358 case Lisp_Fwd_Buffer_Obj: 2356 case Lisp_Fwd_Buffer_Obj:
2359 offset = dump_fwd_buffer_obj (ctx, &fwd->u_buffer_objfwd); 2357 offset = dump_fwd_buffer_obj (ctx, p);
2360 break; 2358 break;
2361 case Lisp_Fwd_Kboard_Obj: 2359 case Lisp_Fwd_Kboard_Obj:
2362 offset = dump_fwd_kboard_obj (ctx, &fwd->u_kboard_objfwd); 2360 offset = dump_fwd_kboard_obj (ctx, p);
2363 break; 2361 break;
2364 default: 2362 default:
2365 emacs_abort (); 2363 emacs_abort ();
@@ -2372,20 +2370,20 @@ static dump_off
2372dump_blv (struct dump_context *ctx, 2370dump_blv (struct dump_context *ctx,
2373 const struct Lisp_Buffer_Local_Value *blv) 2371 const struct Lisp_Buffer_Local_Value *blv)
2374{ 2372{
2375#if CHECK_STRUCTS && !defined (HASH_Lisp_Buffer_Local_Value_066F33A92E) 2373#if CHECK_STRUCTS && !defined HASH_Lisp_Buffer_Local_Value_3C363FAC3C
2376# error "Lisp_Buffer_Local_Value changed. See CHECK_STRUCTS comment." 2374# error "Lisp_Buffer_Local_Value changed. See CHECK_STRUCTS comment."
2377#endif 2375#endif
2378 struct Lisp_Buffer_Local_Value out; 2376 struct Lisp_Buffer_Local_Value out;
2379 dump_object_start (ctx, &out, sizeof (out)); 2377 dump_object_start (ctx, &out, sizeof (out));
2380 DUMP_FIELD_COPY (&out, blv, local_if_set); 2378 DUMP_FIELD_COPY (&out, blv, local_if_set);
2381 DUMP_FIELD_COPY (&out, blv, found); 2379 DUMP_FIELD_COPY (&out, blv, found);
2382 if (blv->fwd) 2380 if (blv->fwd.fwdptr)
2383 dump_field_fixup_later (ctx, &out, blv, &blv->fwd); 2381 dump_field_fixup_later (ctx, &out, blv, &blv->fwd.fwdptr);
2384 dump_field_lv (ctx, &out, blv, &blv->where, WEIGHT_NORMAL); 2382 dump_field_lv (ctx, &out, blv, &blv->where, WEIGHT_NORMAL);
2385 dump_field_lv (ctx, &out, blv, &blv->defcell, WEIGHT_STRONG); 2383 dump_field_lv (ctx, &out, blv, &blv->defcell, WEIGHT_STRONG);
2386 dump_field_lv (ctx, &out, blv, &blv->valcell, WEIGHT_STRONG); 2384 dump_field_lv (ctx, &out, blv, &blv->valcell, WEIGHT_STRONG);
2387 dump_off offset = dump_object_finish (ctx, &out, sizeof (out)); 2385 dump_off offset = dump_object_finish (ctx, &out, sizeof (out));
2388 if (blv->fwd) 2386 if (blv->fwd.fwdptr)
2389 dump_remember_fixup_ptr_raw 2387 dump_remember_fixup_ptr_raw
2390 (ctx, 2388 (ctx,
2391 offset + dump_offsetof (struct Lisp_Buffer_Local_Value, fwd), 2389 offset + dump_offsetof (struct Lisp_Buffer_Local_Value, fwd),
@@ -2437,7 +2435,7 @@ dump_symbol (struct dump_context *ctx,
2437 Lisp_Object object, 2435 Lisp_Object object,
2438 dump_off offset) 2436 dump_off offset)
2439{ 2437{
2440#if CHECK_STRUCTS && !defined (HASH_Lisp_Symbol_60EA1E748E) 2438#if CHECK_STRUCTS && !defined HASH_Lisp_Symbol_999DC26DEC
2441# error "Lisp_Symbol changed. See CHECK_STRUCTS comment." 2439# error "Lisp_Symbol changed. See CHECK_STRUCTS comment."
2442#endif 2440#endif
2443#if CHECK_STRUCTS && !defined (HASH_symbol_redirect_ADB4F5B113) 2441#if CHECK_STRUCTS && !defined (HASH_symbol_redirect_ADB4F5B113)