Subject: 26.1; clone-buffer globally unsets locally void variable

From: Braun Gábor <[email-masked]>
Date: Tue, 12 Nov 2019 16:16:16 +0100

Hi,

* Idea:

Let's create a test, which sets the default value of a variable but
undefines it locally in some buffer.  Then clone the buffer and check
that the default value of the variable is unchanged, and it is locally
undefined in both the original buffer and the clone.

* Recipe to reproduce the bug:

Create test.el with the following content
(there is no empty line in the file):

(ert-deftest clone-buffer-unbound-local-variable ()
  "Test `clone-buffer' on locally unbound variables."
  (let ((var (make-symbol "test")))
    (set-default var 1)
    (with-temp-buffer
      (makunbound (make-local-variable var))
      (let ((buffer (current-buffer))
            (clone (clone-buffer)))
        (unwind-protect
            (progn
              (should (eq (default-value var) 1))
              (should-not (boundp var))
              (with-current-buffer clone
                (should-not (boundp var))))
          (when (buffer-live-p clone)
            (kill-buffer clone)))))))

Run the test:

$ emacs -Q -batch -l ert -l test.el -f ert-run-tests-batch-and-exit

Running 1 tests (2019-11-12 15:55:39+0100)
Test clone-buffer-unbound-local-variable backtrace:
  signal(void-variable (test))
  apply(signal (void-variable (test)))
  (setq value-2 (apply fn-0 args-1))
  (unwind-protect (setq value-2 (apply fn-0 args-1)) (setq form-descri
  (if (unwind-protect (setq value-2 (apply fn-0 args-1)) (setq form-de
  (let (form-description-4) (if (unwind-protect (setq value-2 (apply f
  (let ((value-2 'ert-form-evaluation-aborted-3)) (let (form-descripti
  (let* ((fn-0 (function eq)) (args-1 (condition-case err (let ((signa
  (progn (let* ((fn-0 (function eq)) (args-1 (condition-case err (let
  (unwind-protect (progn (let* ((fn-0 (function eq)) (args-1 (conditio
  (let ((buffer (current-buffer)) (clone (clone-buffer))) (unwind-prot
  (progn (makunbound (make-local-variable var)) (let ((buffer (current
  (unwind-protect (progn (makunbound (make-local-variable var)) (let (
  (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn
  (let ((temp-buffer (generate-new-buffer " *temp*"))) (save-current-b
  (let ((var (make-symbol "test"))) (set-default var 1) (let ((temp-bu
  (lambda nil (let ((var (make-symbol "test"))) (set-default var 1) (l
  ert--run-test-internal(#s(ert--test-execution-info :test #s(ert-test
  ert-run-test(#s(ert-test :name clone-buffer-unbound-local-variable :
  ert-run-or-rerun-test(#s(ert--stats :selector t :tests [#s(ert-test
  ert-run-tests(t #f(compiled-function (event-type &rest event-args) #
  ert-run-tests-batch(nil)
  ert-run-tests-batch-and-exit()
  command-line-1(("-l" "ert" "-l" "test.el" "-f" "ert-run-tests-batch-
  command-line()
  normal-top-level()
Test clone-buffer-unbound-local-variable condition:
    (void-variable test)
   FAILED  1/1  clone-buffer-unbound-local-variable

Ran 1 tests, 0 results as expected, 1 unexpected (2019-11-12 15:55:40+0100)

1 unexpected results:
   FAILED  clone-buffer-unbound-local-variable

The test failed but it should pass.

* Patch to fix the problem

When copying buffer local variables, make even undefined variables
buffer local before undefining them:

--- lisp/simple.el
+++ lisp/simple.el
@@ -8535,7 +8535,7 @@
       (mapc (lambda (v)
 	      (condition-case ()	;in case var is read-only
 		  (if (symbolp v)
-		      (makunbound v)
+		      (makunbound (make-local-variable v))
 		    (set (make-local-variable (car v)) (cdr v)))
 		(error nil)))
 	    lvars)

Best wishes,

     Gábor

In GNU Emacs 26.1 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.24.4)
 of 2019-02-03, modified by Debian built on zam904
Windowing system distributor 'The X.Org Foundation', version 11.0.12004000
System Description:	Debian GNU/Linux 10 (buster)

Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.
Ran 1 tests, 0 results were as expected, 1 unexpected
scroll-up-command: End of buffer

Configured using:
 'configure --build x86_64-linux-gnu --prefix=/usr
 --sharedstatedir=/var/lib --libexecdir=/usr/lib
 --localstatedir=/var/lib --infodir=/usr/share/info
 --mandir=/usr/share/man --enable-libsystemd --with-pop=yes
 --enable-locallisppath=/etc/emacs:/usr/local/share/emacs/26.1/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/26.1/site-lisp:/usr/share/emacs/site-lisp
 --with-sound=alsa --without-gconf --with-mailutils --build
 x86_64-linux-gnu --prefix=/usr --sharedstatedir=/var/lib
 --libexecdir=/usr/lib --localstatedir=/var/lib
 --infodir=/usr/share/info --mandir=/usr/share/man --enable-libsystemd
 --with-pop=yes
 --enable-locallisppath=/etc/emacs:/usr/local/share/emacs/26.1/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/26.1/site-lisp:/usr/share/emacs/site-lisp
 --with-sound=alsa --without-gconf --with-mailutils --with-x=yes
 --with-x-toolkit=gtk3 --with-toolkit-scroll-bars 'CFLAGS=-g -O2
 -fdebug-prefix-map=/build/emacs-26.1+1=. -fstack-protector-strong
 -Wformat -Werror=format-security -Wall' 'CPPFLAGS=-Wdate-time
 -D_FORTIFY_SOURCE=2' LDFLAGS=-Wl,-z,relro'

Configured features:
XPM JPEG TIFF GIF PNG RSVG IMAGEMAGICK SOUND GPM DBUS GSETTINGS NOTIFY
ACL LIBSELINUX GNUTLS LIBXML2 FREETYPE M17N_FLT LIBOTF XFT ZLIB
TOOLKIT_SCROLL_BARS GTK3 X11 THREADS LIBSYSTEMD LCMS2

Important settings:
  value of $LANG: hu_HU.UTF-8
  locale-coding-system: utf-8-unix

Major mode: ERT-Results

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  buffer-read-only: t
  line-number-mode: t
  transient-mark-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message rmc puny seq byte-opt bytecomp
byte-compile cconv dired dired-loaddefs format-spec rfc822 mml mml-sec
password-cache epa derived epg epg-config gnus-util rmail rmail-loaddefs
mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils
mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr
mail-utils cl-seq cl-extra help-mode cl-macs gv ert pp find-func ewoc
easymenu debug cl-loaddefs cl-lib elec-pair time-date mule-util tooltip
eldoc electric uniquify ediff-hook vc-hooks lisp-float-type mwheel
term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image
regexp-opt fringe tabulated-list replace newcomment text-mode elisp-mode
lisp-mode prog-mode register page menu-bar rfn-eshadow isearch timer
select scroll-bar mouse jit-lock font-lock syntax facemenu font-core
term/tty-colors frame cl-generic cham georgian utf-8-lang misc-lang
vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932
hebrew greek romanian slovak czech european ethiopic indian cyrillic
chinese composite charscript charprop case-table epa-hook jka-cmpr-hook
help simple abbrev obarray minibuffer cl-preloaded nadvice loaddefs
button faces cus-face macroexp files text-properties overlay sha1 md5
base64 format env code-pages mule custom widget hashtable-print-readable
backquote dbusbind inotify lcms2 dynamic-setting system-font-setting
font-render-setting move-toolbar gtk x-toolkit x multi-tty
make-network-process emacs)

Memory information:
((conses 16 104606 9545)
 (symbols 48 21227 1)
 (miscs 40 55 129)
 (strings 32 30450 1108)
 (string-bytes 1 805629)
 (vectors 16 15583)
 (vector-slots 8 506210 7590)
 (floats 8 59 58)
 (intervals 56 284 0)
 (buffers 992 12))