diff options
author | Mattias EngdegÄrd <mattiase@acm.org> | 2019-05-17 11:25:06 +0200 |
---|---|---|
committer | Mattias EngdegÄrd <mattiase@acm.org> | 2019-05-27 13:25:27 +0200 |
commit | 68b374a62d8b7b98fd0b144ae83077d698e20bdb (patch) | |
tree | e67783a51e27c314b7ddbc734b865beba0c8913a /test/lisp/emacs-lisp | |
parent | 457b02440510a594e3ff6f17cc6846a3a467a6a1 (diff) | |
download | emacs-68b374a62d8b7b98fd0b144ae83077d698e20bdb.tar.gz emacs-68b374a62d8b7b98fd0b144ae83077d698e20bdb.tar.bz2 emacs-68b374a62d8b7b98fd0b144ae83077d698e20bdb.zip |
Correctly eliminate duplicate cases in switch compilation
Fix code mistakes that prevented the correct elimination of duplicated
cases when compiling a `cond' form to a switch bytecode, as in
(cond ((eq x 'a) 1)
((eq x 'b) 2)
((eq x 'a) 3) ; should be elided
((eq x 'c) 4))
Sometimes, this caused the bytecode to use the wrong branch (bug#35770).
* lisp/emacs-lisp/bytecomp.el (byte-compile-cond-vars): Return obj2 eval'ed.
(byte-compile-cond-jump-table-info):
Discard redundant condition. Use `obj2' as evaluated.
Discard duplicated cases instead of failing the table generation.
* test/lisp/emacs-lisp/bytecomp-tests.el (toplevel): Require subr-x.
(byte-opt-testsuite-arith-data, bytecomp-test--switch-duplicates): Test.
Diffstat (limited to 'test/lisp/emacs-lisp')
-rw-r--r-- | test/lisp/emacs-lisp/bytecomp-tests.el | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index 5fb64ff2881..ed100020def 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -27,6 +27,7 @@ (require 'ert) (require 'cl-lib) +(require 'subr-x) (require 'bytecomp) ;;; Code: @@ -296,7 +297,21 @@ ((eq variable 'default) (message "equal")) (t - (message "not equal"))))) + (message "not equal")))) + ;; Bug#35770 + (let ((x 'a)) (cond ((eq x 'a) 'correct) + ((eq x 'b) 'incorrect) + ((eq x 'a) 'incorrect) + ((eq x 'c) 'incorrect))) + (let ((x #x10000000000000000)) + (cond ((eql x #x10000000000000000) 'correct) + ((eql x #x10000000000000001) 'incorrect) + ((eql x #x10000000000000000) 'incorrect) + ((eql x #x10000000000000002) 'incorrect))) + (let ((x "a")) (cond ((equal x "a") 'correct) + ((equal x "b") 'incorrect) + ((equal x "a") 'incorrect) + ((equal x "c") 'incorrect)))) "List of expression for test. Each element will be executed by interpreter and with bytecompiled code, and their results compared.") @@ -613,6 +628,44 @@ literals (Bug#20852)." (if (buffer-live-p byte-compile-log-buffer) (kill-buffer byte-compile-log-buffer))))) +(ert-deftest bytecomp-test--switch-duplicates () + "Check that duplicates in switches are eliminated correctly (bug#35770)." + (dolist (params + '(((lambda (x) + (cond ((eq x 'a) 111) + ((eq x 'b) 222) + ((eq x 'a) 333) + ((eq x 'c) 444))) + (a b c) + string<) + ((lambda (x) + (cond ((eql x #x10000000000000000) 111) + ((eql x #x10000000000000001) 222) + ((eql x #x10000000000000000) 333) + ((eql x #x10000000000000002) 444))) + (#x10000000000000000 #x10000000000000001 #x10000000000000002) + <) + ((lambda (x) + (cond ((equal x "a") 111) + ((equal x "b") 222) + ((equal x "a") 333) + ((equal x "c") 444))) + ("a" "b" "c") + string<))) + (let* ((lisp (nth 0 params)) + (keys (nth 1 params)) + (lessp (nth 2 params)) + (bc (byte-compile lisp)) + (lap (byte-decompile-bytecode (aref bc 1) (aref bc 2))) + ;; Assume the first constant is the switch table. + (table (cadr (assq 'byte-constant lap)))) + (should (hash-table-p table)) + (should (equal (sort (hash-table-keys table) lessp) keys)) + (should (member '(byte-constant 111) lap)) + (should (member '(byte-constant 222) lap)) + (should-not (member '(byte-constant 333) lap)) + (should (member '(byte-constant 444) lap))))) + ;; Local Variables: ;; no-byte-compile: t ;; End: |