aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Monnier2018-03-23 11:29:06 -0400
committerNoam Postavsky2018-06-03 12:48:14 -0400
commited962f2b8a2f63c7dbf31ec5df3c915703dd571d (patch)
tree880aa4dab830e5e7699e6eace5c0a1097a091baa /src
parent3ba5fc2bbec3f0f64c7afc1b05c9016710805463 (diff)
downloademacs-ed962f2b8a2f63c7dbf31ec5df3c915703dd571d.tar.gz
emacs-ed962f2b8a2f63c7dbf31ec5df3c915703dd571d.zip
Fix bug#30846, along with misc cleanups found along the way
* test/src/data-tests.el (data-tests-kill-all-local-variables): New test. * src/buffer.c (swap_out_buffer_local_variables): Remove. Fuse the body of its loop into that of reset_buffer_local_variables. (Fkill_buffer, Fkill_all_local_variables): Don't call it any more. (reset_buffer_local_variables): Make sure the buffer's local binding is swapped out before removing it from the alist (bug#30846). Call watchers before actually killing the var. * src/data.c (Fmake_local_variable): Simplify. Use swap_in_global_binding to swap out any local binding, instead of a mix of find_symbol_value followed by messing with where&found. Don't call swap_in_symval_forwarding since the currently swapped binding is never one we've modified. (Fkill_local_variable): Use swap_in_global_binding rather than messing with where&found to try and trick find_symbol_value into doing the same. * src/alloc.c (mark_localized_symbol): 'where' can't be a frame any more. (cherry picked from commit 3ddff080341580eb6fc18d907181e9cc2301f62d)
Diffstat (limited to 'src')
-rw-r--r--src/alloc.c8
-rw-r--r--src/buffer.c55
-rw-r--r--src/data.c36
-rw-r--r--src/lisp.h19
4 files changed, 38 insertions, 80 deletions
diff --git a/src/alloc.c b/src/alloc.c
index 09d61b7e5f3..7baaa512c20 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -6334,12 +6334,8 @@ mark_localized_symbol (struct Lisp_Symbol *ptr)
6334{ 6334{
6335 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); 6335 struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr);
6336 Lisp_Object where = blv->where; 6336 Lisp_Object where = blv->where;
6337 /* If the value is set up for a killed buffer or deleted 6337 /* If the value is set up for a killed buffer restore its global binding. */
6338 frame, restore its global binding. If the value is 6338 if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where))))
6339 forwarded to a C variable, either it's not a Lisp_Object
6340 var, or it's staticpro'd already. */
6341 if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where)))
6342 || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where))))
6343 swap_in_global_binding (ptr); 6339 swap_in_global_binding (ptr);
6344 mark_object (blv->where); 6340 mark_object (blv->where);
6345 mark_object (blv->valcell); 6341 mark_object (blv->valcell);
diff --git a/src/buffer.c b/src/buffer.c
index 9b54e4b7787..b0cee717036 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -108,7 +108,6 @@ int last_per_buffer_idx;
108static void call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay, 108static void call_overlay_mod_hooks (Lisp_Object list, Lisp_Object overlay,
109 bool after, Lisp_Object arg1, 109 bool after, Lisp_Object arg1,
110 Lisp_Object arg2, Lisp_Object arg3); 110 Lisp_Object arg2, Lisp_Object arg3);
111static void swap_out_buffer_local_variables (struct buffer *b);
112static void reset_buffer_local_variables (struct buffer *, bool); 111static void reset_buffer_local_variables (struct buffer *, bool);
113 112
114/* Alist of all buffer names vs the buffers. This used to be 113/* Alist of all buffer names vs the buffers. This used to be
@@ -991,10 +990,29 @@ reset_buffer_local_variables (struct buffer *b, bool permanent_too)
991 else 990 else
992 { 991 {
993 Lisp_Object tmp, last = Qnil; 992 Lisp_Object tmp, last = Qnil;
993 Lisp_Object buffer;
994 XSETBUFFER (buffer, b);
995
994 for (tmp = BVAR (b, local_var_alist); CONSP (tmp); tmp = XCDR (tmp)) 996 for (tmp = BVAR (b, local_var_alist); CONSP (tmp); tmp = XCDR (tmp))
995 { 997 {
996 Lisp_Object local_var = XCAR (XCAR (tmp)); 998 Lisp_Object local_var = XCAR (XCAR (tmp));
997 Lisp_Object prop = Fget (local_var, Qpermanent_local); 999 Lisp_Object prop = Fget (local_var, Qpermanent_local);
1000 Lisp_Object sym = local_var;
1001
1002 /* Watchers are run *before* modifying the var. */
1003 if (XSYMBOL (local_var)->u.s.trapped_write == SYMBOL_TRAPPED_WRITE)
1004 notify_variable_watchers (local_var, Qnil,
1005 Qmakunbound, Fcurrent_buffer ());
1006
1007 eassert (XSYMBOL (sym)->u.s.redirect == SYMBOL_LOCALIZED);
1008 /* Need not do anything if some other buffer's binding is
1009 now cached. */
1010 if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer))
1011 {
1012 /* Symbol is set up for this buffer's old local value:
1013 swap it out! */
1014 swap_in_global_binding (XSYMBOL (sym));
1015 }
998 1016
999 if (!NILP (prop)) 1017 if (!NILP (prop))
1000 { 1018 {
@@ -1034,10 +1052,6 @@ reset_buffer_local_variables (struct buffer *b, bool permanent_too)
1034 bset_local_var_alist (b, XCDR (tmp)); 1052 bset_local_var_alist (b, XCDR (tmp));
1035 else 1053 else
1036 XSETCDR (last, XCDR (tmp)); 1054 XSETCDR (last, XCDR (tmp));
1037
1038 if (XSYMBOL (local_var)->u.s.trapped_write == SYMBOL_TRAPPED_WRITE)
1039 notify_variable_watchers (local_var, Qnil,
1040 Qmakunbound, Fcurrent_buffer ());
1041 } 1055 }
1042 } 1056 }
1043 1057
@@ -1867,7 +1881,6 @@ cleaning up all windows currently displaying the buffer to be killed. */)
1867 won't be protected from GC. They would be protected 1881 won't be protected from GC. They would be protected
1868 if they happened to remain cached in their symbols. 1882 if they happened to remain cached in their symbols.
1869 This gets rid of them for certain. */ 1883 This gets rid of them for certain. */
1870 swap_out_buffer_local_variables (b);
1871 reset_buffer_local_variables (b, 1); 1884 reset_buffer_local_variables (b, 1);
1872 1885
1873 bset_name (b, Qnil); 1886 bset_name (b, Qnil);
@@ -2737,11 +2750,6 @@ the normal hook `change-major-mode-hook'. */)
2737{ 2750{
2738 run_hook (Qchange_major_mode_hook); 2751 run_hook (Qchange_major_mode_hook);
2739 2752
2740 /* Make sure none of the bindings in local_var_alist
2741 remain swapped in, in their symbols. */
2742
2743 swap_out_buffer_local_variables (current_buffer);
2744
2745 /* Actually eliminate all local bindings of this buffer. */ 2753 /* Actually eliminate all local bindings of this buffer. */
2746 2754
2747 reset_buffer_local_variables (current_buffer, 0); 2755 reset_buffer_local_variables (current_buffer, 0);
@@ -2753,31 +2761,6 @@ the normal hook `change-major-mode-hook'. */)
2753 return Qnil; 2761 return Qnil;
2754} 2762}
2755 2763
2756/* Make sure no local variables remain set up with buffer B
2757 for their current values. */
2758
2759static void
2760swap_out_buffer_local_variables (struct buffer *b)
2761{
2762 Lisp_Object oalist, alist, buffer;
2763
2764 XSETBUFFER (buffer, b);
2765 oalist = BVAR (b, local_var_alist);
2766
2767 for (alist = oalist; CONSP (alist); alist = XCDR (alist))
2768 {
2769 Lisp_Object sym = XCAR (XCAR (alist));
2770 eassert (XSYMBOL (sym)->u.s.redirect == SYMBOL_LOCALIZED);
2771 /* Need not do anything if some other buffer's binding is
2772 now cached. */
2773 if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer))
2774 {
2775 /* Symbol is set up for this buffer's old local value:
2776 swap it out! */
2777 swap_in_global_binding (XSYMBOL (sym));
2778 }
2779 }
2780}
2781 2764
2782/* Find all the overlays in the current buffer that contain position POS. 2765/* Find all the overlays in the current buffer that contain position POS.
2783 Return the number found, and store them in a vector in *VEC_PTR. 2766 Return the number found, and store them in a vector in *VEC_PTR.
diff --git a/src/data.c b/src/data.c
index 45b2bf73026..4bee194e296 100644
--- a/src/data.c
+++ b/src/data.c
@@ -1188,7 +1188,7 @@ swap_in_global_binding (struct Lisp_Symbol *symbol)
1188 1188
1189 /* Indicate that the global binding is set up now. */ 1189 /* Indicate that the global binding is set up now. */
1190 set_blv_where (blv, Qnil); 1190 set_blv_where (blv, Qnil);
1191 set_blv_found (blv, 0); 1191 set_blv_found (blv, false);
1192} 1192}
1193 1193
1194/* Set up the buffer-local symbol SYMBOL for validity in the current buffer. 1194/* Set up the buffer-local symbol SYMBOL for validity in the current buffer.
@@ -1257,7 +1257,6 @@ find_symbol_value (Lisp_Object symbol)
1257 swap_in_symval_forwarding (sym, blv); 1257 swap_in_symval_forwarding (sym, blv);
1258 return blv->fwd ? do_symval_forwarding (blv->fwd) : blv_value (blv); 1258 return blv->fwd ? do_symval_forwarding (blv->fwd) : blv_value (blv);
1259 } 1259 }
1260 /* FALLTHROUGH */
1261 case SYMBOL_FORWARDED: 1260 case SYMBOL_FORWARDED:
1262 return do_symval_forwarding (SYMBOL_FWD (sym)); 1261 return do_symval_forwarding (SYMBOL_FWD (sym));
1263 default: emacs_abort (); 1262 default: emacs_abort ();
@@ -1366,7 +1365,7 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
1366 tem1 = assq_no_quit (symbol, 1365 tem1 = assq_no_quit (symbol,
1367 BVAR (XBUFFER (where), local_var_alist)); 1366 BVAR (XBUFFER (where), local_var_alist));
1368 set_blv_where (blv, where); 1367 set_blv_where (blv, where);
1369 blv->found = 1; 1368 blv->found = true;
1370 1369
1371 if (NILP (tem1)) 1370 if (NILP (tem1))
1372 { 1371 {
@@ -1381,7 +1380,7 @@ set_internal (Lisp_Object symbol, Lisp_Object newval, Lisp_Object where,
1381 if (bindflag || !blv->local_if_set 1380 if (bindflag || !blv->local_if_set
1382 || let_shadows_buffer_binding_p (sym)) 1381 || let_shadows_buffer_binding_p (sym))
1383 { 1382 {
1384 blv->found = 0; 1383 blv->found = false;
1385 tem1 = blv->defcell; 1384 tem1 = blv->defcell;
1386 } 1385 }
1387 /* If it's a local_if_set, being set not bound, 1386 /* If it's a local_if_set, being set not bound,
@@ -1796,7 +1795,7 @@ make_blv (struct Lisp_Symbol *sym, bool forwarded,
1796 blv->local_if_set = 0; 1795 blv->local_if_set = 0;
1797 set_blv_defcell (blv, tem); 1796 set_blv_defcell (blv, tem);
1798 set_blv_valcell (blv, tem); 1797 set_blv_valcell (blv, tem);
1799 set_blv_found (blv, 0); 1798 set_blv_found (blv, false);
1800 return blv; 1799 return blv;
1801} 1800}
1802 1801
@@ -1946,30 +1945,17 @@ Instead, use `add-hook' and specify t for the LOCAL argument. */)
1946 CALLN (Fmessage, format, SYMBOL_NAME (variable)); 1945 CALLN (Fmessage, format, SYMBOL_NAME (variable));
1947 } 1946 }
1948 1947
1949 /* Swap out any local binding for some other buffer, and make 1948 if (BUFFERP (blv->where) && current_buffer == XBUFFER (blv->where))
1950 sure the current value is permanently recorded, if it's the 1949 /* Make sure the current value is permanently recorded, if it's the
1951 default value. */ 1950 default value. */
1952 find_symbol_value (variable); 1951 swap_in_global_binding (sym);
1953 1952
1954 bset_local_var_alist 1953 bset_local_var_alist
1955 (current_buffer, 1954 (current_buffer,
1956 Fcons (Fcons (variable, XCDR (blv->defcell)), 1955 Fcons (Fcons (variable, XCDR (blv->defcell)),
1957 BVAR (current_buffer, local_var_alist))); 1956 BVAR (current_buffer, local_var_alist)));
1958
1959 /* Make sure symbol does not think it is set up for this buffer;
1960 force it to look once again for this buffer's value. */
1961 if (current_buffer == XBUFFER (blv->where))
1962 set_blv_where (blv, Qnil);
1963 set_blv_found (blv, 0);
1964 } 1957 }
1965 1958
1966 /* If the symbol forwards into a C variable, then load the binding
1967 for this buffer now. If C code modifies the variable before we
1968 load the binding in, then that new value will clobber the default
1969 binding the next time we unload it. */
1970 if (blv->fwd)
1971 swap_in_symval_forwarding (sym, blv);
1972
1973 return variable; 1959 return variable;
1974} 1960}
1975 1961
@@ -2031,11 +2017,7 @@ From now on the default value will apply in this buffer. Return VARIABLE. */)
2031 { 2017 {
2032 Lisp_Object buf; XSETBUFFER (buf, current_buffer); 2018 Lisp_Object buf; XSETBUFFER (buf, current_buffer);
2033 if (EQ (buf, blv->where)) 2019 if (EQ (buf, blv->where))
2034 { 2020 swap_in_global_binding (sym);
2035 set_blv_where (blv, Qnil);
2036 blv->found = 0;
2037 find_symbol_value (variable);
2038 }
2039 } 2021 }
2040 2022
2041 return variable; 2023 return variable;
diff --git a/src/lisp.h b/src/lisp.h
index cd6d07288e0..56ad8b814b6 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -2587,18 +2587,15 @@ struct Lisp_Buffer_Objfwd
2587 in the buffer structure itself. They are handled differently, 2587 in the buffer structure itself. They are handled differently,
2588 using struct Lisp_Buffer_Objfwd.) 2588 using struct Lisp_Buffer_Objfwd.)
2589 2589
2590 The `realvalue' slot holds the variable's current value, or a 2590 The `valcell' slot holds the variable's current value (unless `fwd'
2591 forwarding pointer to where that value is kept. This value is the 2591 is set). This value is the one that corresponds to the loaded binding.
2592 one that corresponds to the loaded binding. To read or set the 2592 To read or set the variable, you must first make sure the right binding
2593 variable, you must first make sure the right binding is loaded; 2593 is loaded; then you can access the value in (or through) `valcell'.
2594 then you can access the value in (or through) `realvalue'. 2594
2595 2595 `where' is the buffer for which the loaded binding was found.
2596 `where' is the buffer for which the loaded binding was found. If 2596 If it has changed, to make sure the right binding is loaded it is
2597 it has changed, to make sure the right binding is loaded it is
2598 necessary to find which binding goes with the current buffer, then 2597 necessary to find which binding goes with the current buffer, then
2599 load it. To load it, first unload the previous binding, then copy 2598 load it. To load it, first unload the previous binding.
2600 the value of the new binding into `realvalue' (or through it).
2601 Also update LOADED-BINDING to point to the newly loaded binding.
2602 2599
2603 `local_if_set' indicates that merely setting the variable creates a 2600 `local_if_set' indicates that merely setting the variable creates a
2604 local binding for the current buffer. Otherwise the latter, setting 2601 local binding for the current buffer. Otherwise the latter, setting